Changeset 74876 in vbox
- Timestamp:
- Oct 17, 2018 8:30:25 AM (6 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/VMM/VMMR3/EM.cpp
r74791 r74876 1710 1710 } 1711 1711 1712 1713 /** 1714 * Helper for emR3ForcedActions() for injecting interrupts into the 1715 * guest. 1716 * 1717 * @returns VBox status code. 1718 * @param pVCpu The cross context virtual CPU structure. 1719 * @param pfWakeupPending Where to store whether a wake up from HLT state is 1720 * pending. 1721 * @param pfInjected Where to store whether an interrupt was injected. 1722 */ 1723 DECLINLINE(int) emR3GstInjectIntr(PVMCPU pVCpu, bool *pfWakeupPending, bool *pfInjected) 1724 { 1725 CPUM_ASSERT_NOT_EXTRN(pVCpu, CPUMCTX_EXTRN_RFLAGS); 1726 *pfWakeupPending = false; 1727 *pfInjected = false; 1728 1729 if ( VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_INTERRUPT_APIC | VMCPU_FF_INTERRUPT_PIC) 1712 1730 #ifdef VBOX_WITH_NESTED_HWVIRT_SVM 1731 && pVCpu->cpum.GstCtx.hwvirt.fGif 1732 #endif 1733 #ifdef VBOX_WITH_RAW_MODE 1734 && !PATMIsPatchGCAddr(pVCpu->CTX_SUFF(pVM), pVCpu->cpum.GstCtx.eip) 1735 #endif 1736 && pVCpu->cpum.GstCtx.eflags.Bits.u1IF) 1737 { 1738 Assert(pVCpu->em.s.enmState != EMSTATE_WAIT_SIPI); 1739 /* Note: it's important to make sure the return code from TRPMR3InjectEvent isn't ignored! */ 1740 /** @todo this really isn't nice, should properly handle this */ 1741 CPUM_IMPORT_EXTRN_RET(pVCpu, IEM_CPUMCTX_EXTRN_XCPT_MASK); 1742 int rc2 = TRPMR3InjectEvent(pVCpu->CTX_SUFF(pVM), pVCpu, TRPM_HARDWARE_INT); 1743 Assert(rc2 != VINF_VMX_VMEXIT && rc2 != VINF_SVM_VMEXIT); 1744 Log(("EM: TRPMR3InjectEvent -> %d\n", rc2)); 1745 *pfWakeupPending = true; 1746 *pfInjected = true; 1747 return rc2; 1748 } 1749 1750 return VINF_NO_CHANGE; 1751 } 1752 1753 1754 #ifdef VBOX_WITH_NESTED_HWVIRT_VMX 1713 1755 /** 1714 1756 * Helper for emR3ForcedActions() for injecting interrupts into the 1715 * nested-guest.1757 * VMX nested-guest. 1716 1758 * 1717 1759 * @returns VBox status code. 1718 * @param pVCpu The cross context virtual CPU structure. 1719 * @param pfResched Where to store whether a reschedule is required. 1720 * @param pfInject Where to store whether an interrupt was injected (and if 1721 * a wake up is pending). 1722 */ 1723 static int emR3NstGstInjectIntr(PVMCPU pVCpu, bool *pfResched, bool *pfInject) 1724 { 1725 *pfResched = false; 1726 *pfInject = false; 1727 if (CPUMIsGuestInSvmNestedHwVirtMode(&pVCpu->cpum.GstCtx)) 1728 { 1729 PVM pVM = pVCpu->CTX_SUFF(pVM); 1730 Assert(pVCpu->cpum.GstCtx.hwvirt.fGif); 1731 bool fVirtualGif = CPUMGetSvmNstGstVGif(&pVCpu->cpum.GstCtx); 1760 * @param pVCpu The cross context virtual CPU structure. 1761 * @param pfWakeupPending Where to store whether a wake up from HLT state is 1762 * pending. 1763 * @param pfInjected Where to store whether an interrrupt was injected. 1764 */ 1765 static int emR3VmxNstGstInjectIntr(PVMCPU pVCpu, bool *pfWakeupPending, bool *pfInjected) 1766 { 1767 Assert(CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx)); 1768 *pfWakeupPending = false; 1769 *pfInjected = false; 1770 1771 /** @todo NSTVMX: Virtual interrupt injection. */ 1772 if ( pVCpu->cpum.GstCtx.eflags.Bits.u1IF 1773 && VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_INTERRUPT_APIC | VMCPU_FF_INTERRUPT_PIC)) 1774 { 1775 if (CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS_INT_WINDOW_EXIT)) 1776 { 1777 /* CPUM_IMPORT_EXTRN_RET(pVCpu, IEM_CPUMCTX_EXTRN_SVM_VMEXIT_MASK); */ /** @todo NSTVMX: Mask. */ 1778 VBOXSTRICTRC rcStrict = IEMExecVmxVmexitIntWindow(pVCpu); 1779 if (rcStrict != VINF_VMX_INTERCEPT_NOT_ACTIVE) 1780 { 1781 *pfWakeupPending = true; 1782 if (RT_SUCCESS(rcStrict)) 1783 { 1784 Assert(rcStrict != VINF_PGM_CHANGE_MODE); 1785 if (rcStrict == VINF_VMX_VMEXIT) 1786 return VINF_SUCCESS; 1787 return VBOXSTRICTRC_VAL(rcStrict); 1788 } 1789 AssertMsgFailed(("Interrupt-window Vm-exit failed! rc=%Rrc\n", VBOXSTRICTRC_VAL(rcStrict))); 1790 return VINF_EM_TRIPLE_FAULT; 1791 } 1792 } 1793 1794 int rc = emR3GstInjectIntr(pVCpu, pfWakeupPending, pfInjected); 1795 if (rc == VINF_VMX_VMEXIT) 1796 rc = VINF_SUCCESS; 1797 return rc; 1798 } 1799 1800 return VINF_NO_CHANGE; 1801 } 1802 #endif /* VBOX_WITH_NESTED_HWVIRT_VMX */ 1803 1804 #ifdef VBOX_WITH_NESTED_HWVIRT_SVM 1805 /** 1806 * Helper for emR3ForcedActions() for injecting interrupts into the 1807 * SVM nested-guest. 1808 * 1809 * @returns VBox status code. 1810 * @param pVCpu The cross context virtual CPU structure. 1811 * @param pfWakeupPending Where to store whether a wake up from HLT state is 1812 * pending. 1813 * @param pfInjected Where to store whether an interrupt was injected. 1814 */ 1815 static int emR3SvmNstGstInjectIntr(PVMCPU pVCpu, bool *pfWakeupPending, bool *pfInjected) 1816 { 1817 Assert(CPUMIsGuestInSvmNestedHwVirtMode(&pVCpu->cpum.GstCtx)); 1818 *pfWakeupPending = false; 1819 *pfInjected = false; 1820 1821 PVM pVM = pVCpu->CTX_SUFF(pVM); 1822 Assert(pVCpu->cpum.GstCtx.hwvirt.fGif); 1823 bool fVirtualGif = CPUMGetSvmNstGstVGif(&pVCpu->cpum.GstCtx); 1732 1824 #ifdef VBOX_WITH_RAW_MODE 1733 fVirtualGif &= !PATMIsPatchGCAddr(pVM, pVCpu->cpum.GstCtx.eip); 1734 #endif 1735 if (fVirtualGif) 1736 { 1737 if (CPUMCanSvmNstGstTakePhysIntr(pVCpu, &pVCpu->cpum.GstCtx)) 1825 fVirtualGif &= !PATMIsPatchGCAddr(pVM, pVCpu->cpum.GstCtx.eip); 1826 #endif 1827 if (fVirtualGif) 1828 { 1829 if (CPUMCanSvmNstGstTakePhysIntr(pVCpu, &pVCpu->cpum.GstCtx)) 1830 { 1831 Assert(pVCpu->em.s.enmState != EMSTATE_WAIT_SIPI); 1832 if (VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_INTERRUPT_APIC | VMCPU_FF_INTERRUPT_PIC)) 1738 1833 { 1739 Assert(pVCpu->em.s.enmState != EMSTATE_WAIT_SIPI); 1740 if (VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_INTERRUPT_APIC | VMCPU_FF_INTERRUPT_PIC)) 1741 { 1742 if (CPUMIsGuestSvmCtrlInterceptSet(pVCpu, &pVCpu->cpum.GstCtx, SVM_CTRL_INTERCEPT_INTR)) 1743 { 1744 CPUM_IMPORT_EXTRN_RET(pVCpu, IEM_CPUMCTX_EXTRN_SVM_VMEXIT_MASK); 1745 VBOXSTRICTRC rcStrict = IEMExecSvmVmexit(pVCpu, SVM_EXIT_INTR, 0, 0); 1746 if (RT_SUCCESS(rcStrict)) 1747 { 1748 /** @todo r=ramshankar: Do we need to signal a wakeup here? If a nested-guest 1749 * doesn't intercept HLT but intercepts INTR? */ 1750 *pfResched = true; 1751 Assert(rcStrict != VINF_PGM_CHANGE_MODE); 1752 if (rcStrict == VINF_SVM_VMEXIT) 1753 return VINF_SUCCESS; 1754 return VBOXSTRICTRC_VAL(rcStrict); 1755 } 1756 1757 AssertMsgFailed(("INTR #VMEXIT failed! rc=%Rrc\n", VBOXSTRICTRC_VAL(rcStrict))); 1758 return VINF_EM_TRIPLE_FAULT; 1759 } 1760 1761 /* Note: it's important to make sure the return code from TRPMR3InjectEvent isn't ignored! */ 1762 /** @todo this really isn't nice, should properly handle this */ 1763 CPUM_IMPORT_EXTRN_RET(pVCpu, IEM_CPUMCTX_EXTRN_XCPT_MASK); 1764 int rc = TRPMR3InjectEvent(pVM, pVCpu, TRPM_HARDWARE_INT); 1765 Assert(rc != VINF_PGM_CHANGE_MODE); 1766 if (rc == VINF_SVM_VMEXIT) 1767 rc = VINF_SUCCESS; 1768 if (pVM->em.s.fIemExecutesAll && ( rc == VINF_EM_RESCHEDULE_REM 1769 || rc == VINF_EM_RESCHEDULE_HM 1770 || rc == VINF_EM_RESCHEDULE_RAW)) 1771 { 1772 rc = VINF_EM_RESCHEDULE; 1773 } 1774 1775 *pfResched = true; 1776 *pfInject = true; 1777 return rc; 1778 } 1779 } 1780 1781 if ( VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INTERRUPT_NESTED_GUEST) 1782 && CPUMCanSvmNstGstTakeVirtIntr(pVCpu, &pVCpu->cpum.GstCtx)) 1783 { 1784 if (CPUMIsGuestSvmCtrlInterceptSet(pVCpu, &pVCpu->cpum.GstCtx, SVM_CTRL_INTERCEPT_VINTR)) 1834 if (CPUMIsGuestSvmCtrlInterceptSet(pVCpu, &pVCpu->cpum.GstCtx, SVM_CTRL_INTERCEPT_INTR)) 1785 1835 { 1786 1836 CPUM_IMPORT_EXTRN_RET(pVCpu, IEM_CPUMCTX_EXTRN_SVM_VMEXIT_MASK); 1787 VBOXSTRICTRC rcStrict = IEMExecSvmVmexit(pVCpu, SVM_EXIT_ VINTR, 0, 0);1837 VBOXSTRICTRC rcStrict = IEMExecSvmVmexit(pVCpu, SVM_EXIT_INTR, 0, 0); 1788 1838 if (RT_SUCCESS(rcStrict)) 1789 1839 { 1790 1840 /** @todo r=ramshankar: Do we need to signal a wakeup here? If a nested-guest 1791 * doesn't intercept HLT but intercepts VINTR? */ 1792 *pfResched = true; 1841 * doesn't intercept HLT but intercepts INTR? */ 1793 1842 Assert(rcStrict != VINF_PGM_CHANGE_MODE); 1794 1843 if (rcStrict == VINF_SVM_VMEXIT) 1795 return VINF_SUCCESS; 1844 rcStrict = VINF_SUCCESS; 1845 *pfWakeupPending = true; 1796 1846 return VBOXSTRICTRC_VAL(rcStrict); 1797 1847 } 1798 1848 1799 AssertMsgFailed((" VINTR #VMEXIT failed! rc=%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));1849 AssertMsgFailed(("INTR #VMEXIT failed! rc=%Rrc\n", VBOXSTRICTRC_VAL(rcStrict))); 1800 1850 return VINF_EM_TRIPLE_FAULT; 1801 1851 } 1802 1852 1803 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INTERRUPT_NESTED_GUEST);1804 uint8_t const uNstGstVector = CPUMGetSvmNstGstInterrupt(&pVCpu->cpum.GstCtx);1805 AssertMsg(uNstGstVector > 0 && uNstGstVector <= X86_XCPT_LAST, ("Invalid VINTR vector %#x\n", uNstGstVector));1806 TRPMAssertTrap(pVCpu, uNstGstVector, TRPM_HARDWARE_INT);1807 Log(("EM: Asserting nested-guest virt. hardware intr: %#x\n", uNstGstVector));1808 1809 *pf Resched= true;1810 *pfInject = true;1811 return VINF_EM_RESCHEDULE;1853 CPUM_IMPORT_EXTRN_RET(pVCpu, IEM_CPUMCTX_EXTRN_XCPT_MASK); 1854 /** @todo this really isn't nice, should properly handle this */ 1855 int rc = TRPMR3InjectEvent(pVM, pVCpu, TRPM_HARDWARE_INT); 1856 Assert(rc != VINF_PGM_CHANGE_MODE); 1857 if (rc == VINF_SVM_VMEXIT) 1858 rc = VINF_SUCCESS; 1859 *pfWakeupPending = true; 1860 *pfInjected = true; 1861 return rc; 1812 1862 } 1813 1863 } 1814 return VINF_SUCCESS; 1815 } 1816 1817 if (CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx)) 1818 { /** @todo Nested VMX. */ } 1819 1820 /* Shouldn't really get here. */ 1821 AssertMsgFailed(("Unrecognized nested hwvirt. arch!\n")); 1822 return VERR_EM_INTERNAL_ERROR; 1823 } 1824 #endif 1864 1865 if ( VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INTERRUPT_NESTED_GUEST) 1866 && CPUMCanSvmNstGstTakeVirtIntr(pVCpu, &pVCpu->cpum.GstCtx)) 1867 { 1868 if (CPUMIsGuestSvmCtrlInterceptSet(pVCpu, &pVCpu->cpum.GstCtx, SVM_CTRL_INTERCEPT_VINTR)) 1869 { 1870 CPUM_IMPORT_EXTRN_RET(pVCpu, IEM_CPUMCTX_EXTRN_SVM_VMEXIT_MASK); 1871 VBOXSTRICTRC rcStrict = IEMExecSvmVmexit(pVCpu, SVM_EXIT_VINTR, 0, 0); 1872 if (RT_SUCCESS(rcStrict)) 1873 { 1874 /** @todo r=ramshankar: Do we need to signal a wakeup here? If a nested-guest 1875 * doesn't intercept HLT but intercepts VINTR? */ 1876 Assert(rcStrict != VINF_PGM_CHANGE_MODE); 1877 if (rcStrict == VINF_SVM_VMEXIT) 1878 rcStrict = VINF_SUCCESS; 1879 *pfWakeupPending = true; 1880 return VBOXSTRICTRC_VAL(rcStrict); 1881 } 1882 1883 AssertMsgFailed(("VINTR #VMEXIT failed! rc=%Rrc\n", VBOXSTRICTRC_VAL(rcStrict))); 1884 return VINF_EM_TRIPLE_FAULT; 1885 } 1886 1887 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INTERRUPT_NESTED_GUEST); 1888 uint8_t const uNstGstVector = CPUMGetSvmNstGstInterrupt(&pVCpu->cpum.GstCtx); 1889 AssertMsg(uNstGstVector > 0 && uNstGstVector <= X86_XCPT_LAST, ("Invalid VINTR vector %#x\n", uNstGstVector)); 1890 TRPMAssertTrap(pVCpu, uNstGstVector, TRPM_HARDWARE_INT); 1891 Log(("EM: Asserting nested-guest virt. hardware intr: %#x\n", uNstGstVector)); 1892 1893 *pfWakeupPending = true; 1894 *pfInjected = true; 1895 return VINF_EM_RESCHEDULE; 1896 } 1897 } 1898 1899 return VINF_SUCCESS; 1900 } 1901 #endif /* VBOX_WITH_NESTED_HWVIRT_SVM */ 1825 1902 1826 1903 /** … … 2140 2217 bool fWakeupPending = false; 2141 2218 if ( !VM_FF_IS_SET(pVM, VM_FF_PGM_NO_MEMORY) 2142 && (!rc || rc >= VINF_EM_RESCHEDULE_HM)) 2143 { 2144 if ( !VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS) 2145 && !TRPMHasTrap(pVCpu)) /* an interrupt could already be scheduled for dispatching in the recompiler. */ 2219 && (!rc || rc >= VINF_EM_RESCHEDULE_HM) 2220 && !VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS) 2221 && !TRPMHasTrap(pVCpu)) /* an interrupt could already be scheduled for dispatching in the recompiler. */ 2222 { 2223 Assert(!HMR3IsEventPending(pVCpu)); 2224 2225 bool fInjected; 2226 #ifdef VBOX_WITH_NESTED_HWVIRT_VMX 2227 if (CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx)) 2228 rc2 = emR3VmxNstGstInjectIntr(pVCpu, &fWakeupPending, &fInjected); 2229 else 2230 #endif 2231 #ifdef VBOX_WITH_NESTED_HWVIRT_SVM 2232 if (CPUMIsGuestInSvmNestedHwVirtMode(&pVCpu->cpum.GstCtx)) 2233 rc2 = emR3SvmNstGstInjectIntr(pVCpu, &fWakeupPending, &fInjected); 2234 else 2235 #endif 2146 2236 { 2147 Assert(!HMR3IsEventPending(pVCpu)); 2148 #ifdef VBOX_WITH_NESTED_HWVIRT_SVM 2149 if (CPUMIsGuestInSvmNestedHwVirtMode(&pVCpu->cpum.GstCtx)) 2237 rc2 = emR3GstInjectIntr(pVCpu, &fWakeupPending, &fInjected); 2238 } 2239 if (rc2 != VINF_NO_CHANGE) 2240 { 2241 if ( pVM->em.s.fIemExecutesAll 2242 && ( rc2 == VINF_EM_RESCHEDULE_REM 2243 || rc2 == VINF_EM_RESCHEDULE_HM 2244 || rc2 == VINF_EM_RESCHEDULE_RAW)) 2150 2245 { 2151 bool fResched, fInject; 2152 rc2 = emR3NstGstInjectIntr(pVCpu, &fResched, &fInject); 2153 if (fInject) 2154 { 2155 fWakeupPending = true; 2156 # ifdef VBOX_STRICT 2157 rcIrq = rc2; 2158 # endif 2159 } 2160 if (fResched) 2161 UPDATE_RC(); 2246 rc2 = VINF_EM_RESCHEDULE; 2162 2247 } 2163 else2164 #endif2165 {2166 CPUM_ASSERT_NOT_EXTRN(pVCpu, CPUMCTX_EXTRN_RFLAGS);2167 if ( VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_INTERRUPT_APIC | VMCPU_FF_INTERRUPT_PIC)2168 #ifdef VBOX_WITH_NESTED_HWVIRT_SVM2169 && pVCpu->cpum.GstCtx.hwvirt.fGif2170 #endif2171 #ifdef VBOX_WITH_RAW_MODE2172 && !PATMIsPatchGCAddr(pVM, pVCpu->cpum.GstCtx.eip)2173 #endif2174 && pVCpu->cpum.GstCtx.eflags.Bits.u1IF)2175 {2176 Assert(pVCpu->em.s.enmState != EMSTATE_WAIT_SIPI);2177 /* Note: it's important to make sure the return code from TRPMR3InjectEvent isn't ignored! */2178 /** @todo this really isn't nice, should properly handle this */2179 CPUM_IMPORT_EXTRN_RET(pVCpu, IEM_CPUMCTX_EXTRN_XCPT_MASK);2180 rc2 = TRPMR3InjectEvent(pVM, pVCpu, TRPM_HARDWARE_INT);2181 Log(("EM: TRPMR3InjectEvent -> %d\n", rc2));2182 if (pVM->em.s.fIemExecutesAll && ( rc2 == VINF_EM_RESCHEDULE_REM2183 || rc2 == VINF_EM_RESCHEDULE_HM2184 || rc2 == VINF_EM_RESCHEDULE_RAW))2185 {2186 rc2 = VINF_EM_RESCHEDULE;2187 }2188 2248 #ifdef VBOX_STRICT 2189 rcIrq = rc2; 2190 #endif 2191 UPDATE_RC(); 2192 /* Reschedule required: We must not miss the wakeup below! */ 2193 fWakeupPending = true; 2194 } 2195 } 2249 if (fInjected) 2250 rcIrq = rc2; 2251 #endif 2252 UPDATE_RC(); 2196 2253 } 2197 2254 }
Note:
See TracChangeset
for help on using the changeset viewer.