Changeset 99652 in vbox for trunk/src/VBox/VMM
- Timestamp:
- May 8, 2023 7:08:35 AM (21 months ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/VMM/VMMR3/EM.cpp
r99576 r99652 1412 1412 #ifdef VBOX_WITH_NESTED_HWVIRT_VMX 1413 1413 /* Handle the "external interrupt" VM-exit intercept. */ 1414 if (CPUMIsGuestVmxPinCtlsSet(&pVCpu->cpum.GstCtx, VMX_PIN_CTLS_EXT_INT_EXIT)) 1414 if ( CPUMIsGuestVmxPinCtlsSet(&pVCpu->cpum.GstCtx, VMX_PIN_CTLS_EXT_INT_EXIT) 1415 && !CPUMIsGuestVmxExitCtlsSet(&pVCpu->cpum.GstCtx, VMX_EXIT_CTLS_ACK_EXT_INT)) 1415 1416 { 1416 1417 VBOXSTRICTRC rcStrict = IEMExecVmxVmexitExtInt(pVCpu, 0 /* uVector */, true /* fIntPending */); 1417 AssertMsg( rcStrict != VINF_VMX_VMEXIT 1418 && rcStrict != VINF_NO_CHANGE , ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));1419 if (rcStrict != VINF_VMX_INTERCEPT_NOT_ACTIVE)1420 return VBOXSTRICTRC_TODO(rcStrict);1418 AssertMsg( rcStrict != VINF_VMX_VMEXIT /* VM-exit should have been converted to VINF_SUCCESS. */ 1419 && rcStrict != VINF_NO_CHANGE 1420 && rcStrict != VINF_VMX_INTERCEPT_NOT_ACTIVE, ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict))); 1421 return VBOXSTRICTRC_VAL(rcStrict); 1421 1422 } 1422 1423 #else … … 1781 1782 1782 1783 # ifdef VBOX_WITH_NESTED_HWVIRT_VMX 1783 if (VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_VMX_APIC_WRITE | VMCPU_FF_VMX_MTF | VMCPU_FF_VMX_PREEMPT_TIMER)) 1784 if (VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_VMX_APIC_WRITE | VMCPU_FF_VMX_MTF | VMCPU_FF_VMX_PREEMPT_TIMER 1785 | VMCPU_FF_VMX_NMI_WINDOW | VMCPU_FF_VMX_INT_WINDOW)) 1784 1786 { 1785 1787 /* … … 1796 1798 1797 1799 /* 1798 * VMX Nested-guest monitor-trap flag (MTF) VM-exit. 1799 * Takes priority over "Traps on the previous instruction". 1800 * See Intel spec. 6.9 "Priority Among Simultaneous Exceptions And Interrupts". 1800 * APIC write emulation MAY have a caused a VM-exit. 1801 * If it did cause a VM-exit, there's no point checking the other VMX non-root mode FFs here. 1801 1802 */ 1802 if ( VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_VMX_MTF))1803 if (CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx)) 1803 1804 { 1804 rc2 = VBOXSTRICTRC_VAL(IEMExecVmxVmexit(pVCpu, VMX_EXIT_MTF, 0 /* uExitQual */)); 1805 Assert(rc2 != VINF_VMX_INTERCEPT_NOT_ACTIVE); 1806 UPDATE_RC(); 1805 /* 1806 * VMX Nested-guest monitor-trap flag (MTF) VM-exit. 1807 * Takes priority over "Traps on the previous instruction". 1808 * See Intel spec. 6.9 "Priority Among Simultaneous Exceptions And Interrupts". 1809 */ 1810 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_VMX_MTF)) 1811 { 1812 rc2 = VBOXSTRICTRC_VAL(IEMExecVmxVmexit(pVCpu, VMX_EXIT_MTF, 0 /* uExitQual */)); 1813 Assert(rc2 != VINF_VMX_INTERCEPT_NOT_ACTIVE); 1814 UPDATE_RC(); 1815 } 1816 /* 1817 * VMX Nested-guest preemption timer VM-exit. 1818 * Takes priority over NMI-window VM-exits. 1819 */ 1820 else if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_VMX_PREEMPT_TIMER)) 1821 { 1822 rc2 = VBOXSTRICTRC_VAL(IEMExecVmxVmexitPreemptTimer(pVCpu)); 1823 Assert(rc2 != VINF_VMX_INTERCEPT_NOT_ACTIVE); 1824 UPDATE_RC(); 1825 } 1826 /* 1827 * VMX interrupt-window and NMI-window VM-exits. 1828 * Takes priority over non-maskable interrupts (NMIs) and external interrupts respectively. 1829 * If we are in an interrupt shadow or if we already in the process of delivering 1830 * an event then these VM-exits cannot occur. 1831 * 1832 * Interrupt shadows block NMI-window VM-exits. 1833 * Any event that is already in TRPM (e.g. injected during VM-entry) takes priority. 1834 * NMIs block delivery of other interrupts including NMIs. 1835 * 1836 * See Intel spec. 25.2 "Other Causes Of VM Exits". 1837 * See Intel spec. 26.7.6 "NMI-Window Exiting". 1838 * See Intel spec. 6.7 "Nonmaskable Interrupt (NMI)". 1839 */ 1840 else if ( !CPUMIsInInterruptShadow(&pVCpu->cpum.GstCtx) 1841 && !CPUMAreInterruptsInhibitedByNmi(&pVCpu->cpum.GstCtx) 1842 && !TRPMHasTrap(pVCpu)) 1843 { 1844 /* 1845 * VMX NMI-window VM-exit. 1846 */ 1847 if ( VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_VMX_NMI_WINDOW) 1848 && !CPUMIsGuestVmxVirtNmiBlocking(&pVCpu->cpum.GstCtx)) 1849 { 1850 Assert(CPUMIsGuestVmxProcCtlsSet(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS_NMI_WINDOW_EXIT)); 1851 Assert(CPUMIsGuestVmxInterceptEvents(&pVCpu->cpum.GstCtx)); 1852 rc2 = VBOXSTRICTRC_VAL(IEMExecVmxVmexit(pVCpu, VMX_EXIT_NMI_WINDOW, 0 /* uExitQual */)); 1853 AssertMsg( rc2 != VINF_VMX_INTERCEPT_NOT_ACTIVE 1854 && rc2 != VINF_VMX_VMEXIT 1855 && rc2 != VINF_NO_CHANGE, ("%Rrc\n", rc2)); 1856 UPDATE_RC(); 1857 } 1858 /* 1859 * VMX interrupt-window VM-exit. 1860 * This is a bit messy with the way the code below is currently structured, 1861 * but checking VMCPU_FF_INTERRUPT_NMI here should allow pending NMI to be delivered 1862 * prior to causing an interrupt-window VM-exit. 1863 */ 1864 /** @todo Restructure this later to happen after injecting NMI/causing NMI-exit, see 1865 * code in VMX R0 event delivery. */ 1866 else if ( VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_VMX_INT_WINDOW) 1867 && !VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INTERRUPT_NMI) 1868 && CPUMIsGuestVmxVirtIntrEnabled(&pVCpu->cpum.GstCtx)) 1869 { 1870 Assert(CPUMIsGuestVmxProcCtlsSet(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS_INT_WINDOW_EXIT)); 1871 Assert(CPUMIsGuestVmxInterceptEvents(&pVCpu->cpum.GstCtx)); 1872 rc2 = VBOXSTRICTRC_VAL(IEMExecVmxVmexit(pVCpu, VMX_EXIT_INT_WINDOW, 0 /* uExitQual */)); 1873 AssertMsg( rc2 != VINF_VMX_INTERCEPT_NOT_ACTIVE 1874 && rc2 != VINF_VMX_VMEXIT 1875 && rc2 != VINF_NO_CHANGE, ("%Rrc\n", rc2)); 1876 UPDATE_RC(); 1877 } 1878 } 1807 1879 } 1808 1880 1809 1881 /* 1810 * VMX Nested-guest preemption timer VM-exit. 1811 * Takes priority over NMI-window VM-exits. 1882 * Interrupt-window and NMI-window force flags might still be pending if we didn't actually cause 1883 * a VM-exit above. They will get cleared eventually when ANY nested-guest VM-exit occurs. 1884 * However, the force flags asserted below MUST have been cleared at this point. 1812 1885 */ 1813 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_VMX_PREEMPT_TIMER))1814 {1815 rc2 = VBOXSTRICTRC_VAL(IEMExecVmxVmexitPreemptTimer(pVCpu));1816 Assert(rc2 != VINF_VMX_INTERCEPT_NOT_ACTIVE);1817 UPDATE_RC();1818 }1819 1886 Assert(!VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_VMX_APIC_WRITE | VMCPU_FF_VMX_MTF | VMCPU_FF_VMX_PREEMPT_TIMER)); 1820 1887 } … … 1832 1899 && (!rc || rc >= VINF_EM_RESCHEDULE_HM) 1833 1900 && !CPUMIsInInterruptShadow(&pVCpu->cpum.GstCtx) /* Interrupt shadows block both NMIs and interrupts. */ 1834 /** @todo r=bird: But interrupt shadows probably do not block vmexits due to host interrupts... */1835 1901 && !TRPMHasTrap(pVCpu)) /* An event could already be scheduled for dispatching. */ 1836 1902 { … … 1850 1916 } 1851 1917 1852 if (0)1853 { }1854 # ifdef VBOX_WITH_NESTED_HWVIRT_VMX1855 /*1856 * VMX NMI-window VM-exit.1857 * Takes priority over non-maskable interrupts (NMIs).1858 * Interrupt shadows block NMI-window VM-exits.1859 * Any event that is already in TRPM (e.g. injected during VM-entry) takes priority.1860 *1861 * See Intel spec. 25.2 "Other Causes Of VM Exits".1862 * See Intel spec. 26.7.6 "NMI-Window Exiting".1863 */1864 else if ( VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_VMX_NMI_WINDOW)1865 && !CPUMIsGuestVmxVirtNmiBlocking(&pVCpu->cpum.GstCtx))1866 {1867 Assert(CPUMIsGuestVmxProcCtlsSet(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS_NMI_WINDOW_EXIT));1868 Assert(CPUMIsGuestVmxInterceptEvents(&pVCpu->cpum.GstCtx));1869 rc2 = VBOXSTRICTRC_VAL(IEMExecVmxVmexit(pVCpu, VMX_EXIT_NMI_WINDOW, 0 /* uExitQual */));1870 AssertMsg( rc2 != VINF_VMX_INTERCEPT_NOT_ACTIVE1871 && rc2 != VINF_VMX_VMEXIT1872 && rc2 != VINF_NO_CHANGE, ("%Rrc\n", rc2));1873 UPDATE_RC();1874 }1875 # endif1876 1918 /* 1877 1919 * NMIs (take priority over external interrupts). 1878 1920 */ 1879 elseif ( VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INTERRUPT_NMI)1880 1921 if ( VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INTERRUPT_NMI) 1922 && !CPUMAreInterruptsInhibitedByNmi(&pVCpu->cpum.GstCtx)) 1881 1923 { 1882 1924 # ifdef VBOX_WITH_NESTED_HWVIRT_VMX … … 1884 1926 && CPUMIsGuestVmxPinCtlsSet(&pVCpu->cpum.GstCtx, VMX_PIN_CTLS_NMI_EXIT)) 1885 1927 { 1928 /* We MUST clear the NMI force-flag here, see @bugref{10318#c19}. */ 1929 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INTERRUPT_NMI); 1886 1930 rc2 = VBOXSTRICTRC_VAL(IEMExecVmxVmexitXcptNmi(pVCpu)); 1887 1931 Assert(rc2 != VINF_VMX_INTERCEPT_NOT_ACTIVE); … … 1919 1963 } 1920 1964 } 1921 # ifdef VBOX_WITH_NESTED_HWVIRT_VMX1922 /*1923 * VMX Interrupt-window VM-exits.1924 * Takes priority over external interrupts.1925 */1926 else if ( VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_VMX_INT_WINDOW)1927 && CPUMIsGuestVmxVirtIntrEnabled(&pVCpu->cpum.GstCtx))1928 {1929 Assert(CPUMIsGuestVmxProcCtlsSet(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS_INT_WINDOW_EXIT));1930 Assert(CPUMIsGuestVmxInterceptEvents(&pVCpu->cpum.GstCtx));1931 rc2 = VBOXSTRICTRC_VAL(IEMExecVmxVmexit(pVCpu, VMX_EXIT_INT_WINDOW, 0 /* uExitQual */));1932 AssertMsg( rc2 != VINF_VMX_INTERCEPT_NOT_ACTIVE1933 && rc2 != VINF_VMX_VMEXIT1934 && rc2 != VINF_NO_CHANGE, ("%Rrc\n", rc2));1935 UPDATE_RC();1936 }1937 # endif1938 1965 # ifdef VBOX_WITH_NESTED_HWVIRT_SVM 1939 1966 /** @todo NSTSVM: Handle this for SVM here too later not when an interrupt is
Note:
See TracChangeset
for help on using the changeset viewer.