Changeset 70781 in vbox for trunk/src/VBox/VMM/VMMR3
- Timestamp:
- Jan 29, 2018 5:24:06 AM (7 years ago)
- svn:sync-xref-src-repo-rev:
- 120554
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/VMM/VMMR3/EM.cpp
r70732 r70781 1641 1641 } 1642 1642 1643 #ifdef VBOX_WITH_NESTED_HWVIRT 1644 /** 1645 * Helper for emR3ForcedActions() for injecting interrupts into the 1646 * nested-guest. 1647 * 1648 * @returns VBox status code. 1649 * @param pVCpu The cross context virtual CPU structure. 1650 * @param pCtx Pointer to the nested-guest CPU context. 1651 * @param pfResched Where to store whether a reschedule is required. 1652 * @param pfInject Where to store whether an interrupt was injected (and if 1653 * a wake up is pending). 1654 */ 1655 static int emR3NstGstInjectIntr(PVMCPU pVCpu, PCPUMCTX pCtx, bool *pfResched, bool *pfInject) 1656 { 1657 *pfResched = false; 1658 *pfInject = false; 1659 if (CPUMIsGuestInSvmNestedHwVirtMode(pCtx)) 1660 { 1661 PVM pVM = pVCpu->CTX_SUFF(pVM); 1662 bool fGif = pCtx->hwvirt.fGif; 1663 #ifdef VBOX_WITH_RAW_MODE 1664 fGif &= !PATMIsPatchGCAddr(pVM, pCtx->eip); 1665 #endif 1666 if (fGif) 1667 { 1668 if (CPUMCanSvmNstGstTakePhysIntr(pVCpu, pCtx)) 1669 { 1670 Assert(pVCpu->em.s.enmState != EMSTATE_WAIT_SIPI); 1671 if (VMCPU_FF_IS_PENDING(pVCpu, VMCPU_FF_INTERRUPT_APIC | VMCPU_FF_INTERRUPT_PIC)) 1672 { 1673 if (CPUMIsGuestSvmCtrlInterceptSet(pVCpu, pCtx, SVM_CTRL_INTERCEPT_INTR)) 1674 { 1675 VBOXSTRICTRC rcStrict = IEMExecSvmVmexit(pVCpu, SVM_EXIT_INTR, 0, 0); 1676 if (RT_SUCCESS(rcStrict)) 1677 { 1678 /** @todo r=ramshankar: Do we need to signal a wakeup here? If a nested-guest 1679 * doesn't intercept HLT but intercepts INTR? */ 1680 *pfResched = true; 1681 return VINF_EM_RESCHEDULE; 1682 } 1683 1684 AssertMsgFailed(("INTR #VMEXIT failed! rc=%Rrc\n", VBOXSTRICTRC_VAL(rcStrict))); 1685 return VINF_EM_TRIPLE_FAULT; 1686 } 1687 1688 /* Note: it's important to make sure the return code from TRPMR3InjectEvent isn't ignored! */ 1689 /** @todo this really isn't nice, should properly handle this */ 1690 int rc = TRPMR3InjectEvent(pVM, pVCpu, TRPM_HARDWARE_INT); 1691 if (pVM->em.s.fIemExecutesAll && ( rc == VINF_EM_RESCHEDULE_REM 1692 || rc == VINF_EM_RESCHEDULE_HM 1693 || rc == VINF_EM_RESCHEDULE_RAW)) 1694 { 1695 rc = VINF_EM_RESCHEDULE; 1696 } 1697 1698 *pfResched = true; 1699 *pfInject = true; 1700 return rc; 1701 } 1702 } 1703 1704 if ( VMCPU_FF_IS_PENDING(pVCpu, VMCPU_FF_INTERRUPT_NESTED_GUEST) 1705 && CPUMCanSvmNstGstTakeVirtIntr(pVCpu, pCtx)) 1706 { 1707 if (CPUMIsGuestSvmCtrlInterceptSet(pVCpu, pCtx, SVM_CTRL_INTERCEPT_VINTR)) 1708 { 1709 VBOXSTRICTRC rcStrict = IEMExecSvmVmexit(pVCpu, SVM_EXIT_VINTR, 0, 0); 1710 if (RT_SUCCESS(rcStrict)) 1711 { 1712 /** @todo r=ramshankar: Do we need to signal a wakeup here? If a nested-guest 1713 * doesn't intercept HLT but intercepts VINTR? */ 1714 *pfResched = true; 1715 return VINF_EM_RESCHEDULE; 1716 } 1717 1718 AssertMsgFailed(("VINTR #VMEXIT failed! rc=%Rrc\n", VBOXSTRICTRC_VAL(rcStrict))); 1719 return VINF_EM_TRIPLE_FAULT; 1720 } 1721 1722 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INTERRUPT_NESTED_GUEST); 1723 uint8_t const uNstGstVector = CPUMGetSvmNstGstInterrupt(pCtx); 1724 AssertMsg(uNstGstVector > 0 && uNstGstVector <= X86_XCPT_LAST, ("Invalid VINTR vector %#x\n", uNstGstVector)); 1725 TRPMAssertTrap(pVCpu, uNstGstVector, TRPM_HARDWARE_INT); 1726 Log(("EM: Asserting nested-guest virt. hardware intr: %#x\n", uNstGstVector)); 1727 1728 *pfResched = true; 1729 *pfInject = true; 1730 return VINF_EM_RESCHEDULE; 1731 } 1732 } 1733 return VINF_SUCCESS; 1734 } 1735 1736 if (CPUMIsGuestInVmxNestedHwVirtMode(pCtx)) 1737 { /** @todo Nested VMX. */ } 1738 1739 /* Shouldn't really get here. */ 1740 AssertMsgFailed(("Unrecognized nested hwvirt. arch!\n")); 1741 return VERR_EM_INTERNAL_ERROR; 1742 } 1743 #endif 1643 1744 1644 1745 /** … … 1951 2052 * Interrupts. 1952 2053 */ 1953 /** @todo this can be optimized a bit. later. */1954 2054 bool fWakeupPending = false; 1955 2055 if ( !VM_FF_IS_PENDING(pVM, VM_FF_PGM_NO_MEMORY) … … 1959 2059 && !TRPMHasTrap(pVCpu)) /* an interrupt could already be scheduled for dispatching in the recompiler. */ 1960 2060 { 2061 Assert(!HMR3IsEventPending(pVCpu)); 1961 2062 PCPUMCTX pCtx = pVCpu->em.s.pCtx; 1962 bool fGif = pCtx->hwvirt.fGif; 2063 #ifdef VBOX_WITH_NESTED_HWVIRT 2064 if (CPUMIsGuestInNestedHwVirtMode(pCtx)) 2065 { 2066 bool fResched, fInject; 2067 rc2 = emR3NstGstInjectIntr(pVCpu, pCtx, &fResched, &fInject); 2068 if (fInject) 2069 { 2070 fWakeupPending = true; 2071 #ifdef VBOX_STRICT 2072 rcIrq = rc2; 2073 #endif 2074 } 2075 if (fResched) 2076 UPDATE_RC(); 2077 } 2078 else 2079 #endif 2080 { 2081 if ( VMCPU_FF_IS_PENDING(pVCpu, VMCPU_FF_INTERRUPT_APIC | VMCPU_FF_INTERRUPT_PIC) 2082 #ifdef VBOX_WITH_NESTED_HWVIRT 2083 && pCtx->hwvirt.fGif 2084 #endif 1963 2085 #ifdef VBOX_WITH_RAW_MODE 1964 /* We cannot just inspect EFLAGS when nested hw.virt is enabled (see e.g. CPUMCanSvmNstGstTakePhysIntr). */ 1965 fGif &= !PATMIsPatchGCAddr(pVM, pCtx->eip); 1966 #endif 1967 if (fGif) 1968 { 1969 bool fIntrEnabled; 1970 #ifdef VBOX_WITH_NESTED_HWVIRT 1971 if (CPUMIsGuestInSvmNestedHwVirtMode(pCtx)) 1972 fIntrEnabled = CPUMCanSvmNstGstTakePhysIntr(pVCpu, pCtx); 1973 else 1974 fIntrEnabled = pCtx->eflags.Bits.u1IF; 1975 #else 1976 fIntrEnabled = pCtx->eflags.Bits.u1IF; 1977 #endif 1978 if (fIntrEnabled) 2086 && !PATMIsPatchGCAddr(pVM, pCtx->eip) 2087 #endif 2088 && pCtx->eflags.Bits.u1IF) 1979 2089 { 1980 Assert(!HMR3IsEventPending(pVCpu));1981 2090 Assert(pVCpu->em.s.enmState != EMSTATE_WAIT_SIPI); 1982 if (VMCPU_FF_IS_PENDING(pVCpu, VMCPU_FF_INTERRUPT_APIC | VMCPU_FF_INTERRUPT_PIC)) 2091 /* Note: it's important to make sure the return code from TRPMR3InjectEvent isn't ignored! */ 2092 /** @todo this really isn't nice, should properly handle this */ 2093 rc2 = TRPMR3InjectEvent(pVM, pVCpu, TRPM_HARDWARE_INT); 2094 if (pVM->em.s.fIemExecutesAll && ( rc2 == VINF_EM_RESCHEDULE_REM 2095 || rc2 == VINF_EM_RESCHEDULE_HM 2096 || rc2 == VINF_EM_RESCHEDULE_RAW)) 1983 2097 { 1984 #ifdef VBOX_WITH_NESTED_HWVIRT1985 if (CPUMIsGuestSvmCtrlInterceptSet(pVCpu, pCtx, SVM_CTRL_INTERCEPT_INTR))1986 {1987 VBOXSTRICTRC rcStrict = IEMExecSvmVmexit(pVCpu, SVM_EXIT_INTR, 0, 0);1988 if (RT_SUCCESS(rcStrict))1989 rc2 = VINF_EM_RESCHEDULE;1990 else1991 {1992 AssertMsgFailed(("INTR #VMEXIT failed! rc=%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));1993 Log(("EM: SVM Nested-guest INTR #VMEXIT failed! rc=%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));1994 /** @todo should we call iemInitiateCpuShutdown? Should this1995 * result in trapping triple-fault intercepts? */1996 rc2 = VINF_EM_TRIPLE_FAULT;1997 }1998 }1999 else2000 #endif2001 {2002 /* Note: it's important to make sure the return code from TRPMR3InjectEvent isn't ignored! */2003 /** @todo this really isn't nice, should properly handle this */2004 rc2 = TRPMR3InjectEvent(pVM, pVCpu, TRPM_HARDWARE_INT);2005 if (pVM->em.s.fIemExecutesAll && ( rc2 == VINF_EM_RESCHEDULE_REM2006 || rc2 == VINF_EM_RESCHEDULE_HM2007 || rc2 == VINF_EM_RESCHEDULE_RAW))2008 rc2 = VINF_EM_RESCHEDULE;2009 #ifdef VBOX_STRICT2010 rcIrq = rc2;2011 #endif2012 }2013 UPDATE_RC();2014 /* Reschedule required: We must not miss the wakeup below! */2015 fWakeupPending = true;2016 }2017 }2018 #ifdef VBOX_WITH_NESTED_HWVIRT2019 /*2020 * Check nested-guest virtual interrupts.2021 */2022 else if ( VMCPU_FF_IS_PENDING(pVCpu, VMCPU_FF_INTERRUPT_NESTED_GUEST)2023 && CPUMCanSvmNstGstTakeVirtIntr(pCtx))2024 {2025 if (CPUMIsGuestSvmCtrlInterceptSet(pVCpu, pCtx, SVM_CTRL_INTERCEPT_VINTR))2026 {2027 VBOXSTRICTRC rcStrict = IEMExecSvmVmexit(pVCpu, SVM_EXIT_VINTR, 0, 0);2028 if (RT_SUCCESS(rcStrict))2029 rc2 = VINF_EM_RESCHEDULE;2030 else2031 {2032 AssertMsgFailed(("VINTR #VMEXIT failed! rc=%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));2033 Log(("EM: SVM Nested-guest VINTR #VMEXIT failed! rc=%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));2034 /** @todo should we call iemInitiateCpuShutdown? Should this2035 * result in trapping triple-fault intercepts? */2036 rc2 = VINF_EM_TRIPLE_FAULT;2037 }2038 }2039 else2040 {2041 /*2042 * Prepare the nested-guest interrupt for injection.2043 */2044 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INTERRUPT_NESTED_GUEST);2045 uint8_t uNstGstVector = CPUMGetSvmNstGstInterrupt(pCtx);2046 TRPMAssertTrap(pVCpu, uNstGstVector, TRPM_HARDWARE_INT);2047 Log(("EM: Asserting nested-guest virt. hardware intr: %#x\n", uNstGstVector));2048 /** @todo reschedule to HM/REM later, when the HMR0 nested-guest execution is2049 * done. For now just reschedule to IEM. */2050 2098 rc2 = VINF_EM_RESCHEDULE; 2051 2099 } 2100 #ifdef VBOX_STRICT 2101 rcIrq = rc2; 2102 #endif 2052 2103 UPDATE_RC(); 2053 2104 /* Reschedule required: We must not miss the wakeup below! */ 2054 2105 fWakeupPending = true; 2055 2106 } 2056 #endif /* VBOX_WITH_NESTED_HWVIRT */2057 2107 } 2058 2108 }
Note:
See TracChangeset
for help on using the changeset viewer.