Changeset 69934 in vbox
- Timestamp:
- Dec 5, 2017 12:16:04 PM (7 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/VMM/VMMR0/HMSVMR0.cpp
r69932 r69934 1230 1230 * updates the corresponding VMCB Clean bit. 1231 1231 * 1232 * @param pVCpu The cross context virtual CPU structure. 1233 * @param pCtx Pointer to the guest-CPU context. 1232 1234 * @param pVmcb Pointer to the VM control block. 1233 1235 * @param u32Xcpt The value of the exception (X86_XCPT_*). 1234 */ 1235 DECLINLINE(void) hmR0SvmRemoveXcptIntercept(PSVMVMCB pVmcb, uint32_t u32Xcpt) 1236 * 1237 * @remarks This takes into account if we're executing a nested-guest and only 1238 * removes the exception intercept if both the guest -and- nested-guest 1239 * are not intercepting it. 1240 */ 1241 DECLINLINE(void) hmR0SvmRemoveXcptIntercept(PVMCPU pVCpu, PCPUMCTX pCtx, PSVMVMCB pVmcb, uint32_t u32Xcpt) 1236 1242 { 1237 1243 Assert(u32Xcpt != X86_XCPT_DB); … … 1240 1246 if (pVmcb->ctrl.u32InterceptXcpt & RT_BIT(u32Xcpt)) 1241 1247 { 1242 pVmcb->ctrl.u32InterceptXcpt &= ~RT_BIT(u32Xcpt); 1243 pVmcb->ctrl.u64VmcbCleanBits &= ~HMSVM_VMCB_CLEAN_INTERCEPTS; 1244 } 1248 bool fRemoveXcpt = true; 1249 #ifdef VBOX_WITH_NESTED_HWVIRT 1250 /* Only remove the intercept if the nested-guest is also not intercepting it! */ 1251 if (CPUMIsGuestInSvmNestedHwVirtMode(pCtx)) 1252 { 1253 Assert(pCtx->hwvirt.svm.fHMCachedVmcb); NOREF(pCtx); 1254 PCSVMNESTEDVMCBCACHE pVmcbNstGstCache = &pVCpu->hm.s.svm.NstGstVmcbCache; 1255 fRemoveXcpt = !(pVmcbNstGstCache->u32InterceptXcpt & RT_BIT(u32Xcpt)); 1256 } 1257 #else 1258 RT_NOREF2(pVCpu, pCtx); 1245 1259 #endif 1246 } 1247 1248 1249 /** 1250 * Loads the guest CR0 control register into the guest-state area in the VMCB. 1260 if (fRemoveXcpt) 1261 { 1262 pVmcb->ctrl.u32InterceptXcpt &= ~RT_BIT(u32Xcpt); 1263 pVmcb->ctrl.u64VmcbCleanBits &= ~HMSVM_VMCB_CLEAN_INTERCEPTS; 1264 } 1265 } 1266 #else 1267 RT_NOREF3(pVCpu, pCtx, pVmcb); 1268 #endif 1269 } 1270 1271 1272 /** 1273 * Loads the guest (or nested-guest) CR0 control register into the guest-state 1274 * area in the VMCB. 1275 * 1251 1276 * Although the guest CR0 is a separate field in the VMCB we have to consider 1252 1277 * the FPU state itself which is shared between the host and the guest. … … 1303 1328 hmR0SvmAddXcptIntercept(pVmcb, X86_XCPT_NM); 1304 1329 else 1305 hmR0SvmRemoveXcptIntercept(pV mcb, X86_XCPT_NM);1330 hmR0SvmRemoveXcptIntercept(pVCpu, pCtx, pVmcb, X86_XCPT_NM); 1306 1331 1307 1332 if (fInterceptMF) 1308 1333 hmR0SvmAddXcptIntercept(pVmcb, X86_XCPT_MF); 1309 1334 else 1310 hmR0SvmRemoveXcptIntercept(pV mcb, X86_XCPT_MF);1335 hmR0SvmRemoveXcptIntercept(pVCpu, pCtx, pVmcb, X86_XCPT_MF); 1311 1336 1312 1337 pVmcb->guest.u64CR0 = u64GuestCR0; … … 1816 1841 * @param pVCpu The cross context virtual CPU structure. 1817 1842 * @param pVmcb Pointer to the VM control block. 1818 */ 1819 static void hmR0SvmLoadGuestXcptIntercepts(PVMCPU pVCpu, PSVMVMCB pVmcb) 1843 * @param pCtx Pointer to the guest-CPU context. 1844 */ 1845 static void hmR0SvmLoadGuestXcptIntercepts(PVMCPU pVCpu, PSVMVMCB pVmcb, PCPUMCTX pCtx) 1820 1846 { 1821 1847 if (HMCPU_CF_IS_PENDING(pVCpu, HM_CHANGED_GUEST_XCPT_INTERCEPTS)) … … 1825 1851 hmR0SvmAddXcptIntercept(pVmcb, X86_XCPT_UD); 1826 1852 else 1827 hmR0SvmRemoveXcptIntercept(pV mcb, X86_XCPT_UD);1853 hmR0SvmRemoveXcptIntercept(pVCpu, pCtx, pVmcb, X86_XCPT_UD); 1828 1854 1829 1855 /* Trap #BP for INT3 debug breakpoints set by the VM debugger. */ … … 1831 1857 hmR0SvmAddXcptIntercept(pVmcb, X86_XCPT_BP); 1832 1858 else 1833 hmR0SvmRemoveXcptIntercept(pV mcb, X86_XCPT_BP);1859 hmR0SvmRemoveXcptIntercept(pVCpu, pCtx, pVmcb, X86_XCPT_BP); 1834 1860 1835 1861 /* The remaining intercepts are handled elsewhere, e.g. in hmR0SvmLoadSharedCR0(). */ … … 1849 1875 * @param pVCpu The cross context virtual CPU structure. 1850 1876 * @param pVmcbNstGst Pointer to the nested-guest VM control block. 1851 */ 1852 static void hmR0SvmLoadGuestXcptInterceptsNested(PVMCPU pVCpu, PSVMVMCB pVmcbNstGst) 1877 * @param pCtx Pointer to the guest-CPU context. 1878 */ 1879 static void hmR0SvmLoadGuestXcptInterceptsNested(PVMCPU pVCpu, PSVMVMCB pVmcbNstGst, PCPUMCTX pCtx) 1853 1880 { 1854 1881 if (HMCPU_CF_IS_PENDING(pVCpu, HM_CHANGED_GUEST_XCPT_INTERCEPTS)) … … 1856 1883 /* First, load the guest intercepts into the guest VMCB. */ 1857 1884 PSVMVMCB pVmcb = pVCpu->hm.s.svm.pVmcb; 1858 hmR0SvmLoadGuestXcptIntercepts(pVCpu, pVmcb );1885 hmR0SvmLoadGuestXcptIntercepts(pVCpu, pVmcb, pCtx); 1859 1886 1860 1887 /* Next, merge the intercepts into the nested-guest VMCB. */ … … 1894 1921 pVmcbNstGst->ctrl.u64InterceptCtrl &= ~SVM_CTRL_INTERCEPT_VMMCALL; 1895 1922 1896 /* Remove exception intercepts that we don't need while executing the nested-guest. */1897 pVmcbNstGst->ctrl.u32InterceptXcpt &= ~RT_BIT(X86_XCPT_UD);1898 1899 1923 Assert(!HMCPU_CF_IS_PENDING(pVCpu, HM_CHANGED_GUEST_XCPT_INTERCEPTS)); 1900 1924 } … … 2085 2109 AssertLogRelMsgRCReturn(rc, ("hmR0SvmLoadGuestApicState! rc=%Rrc (pVM=%p pVCpu=%p)\n", rc, pVM, pVCpu), rc); 2086 2110 2087 hmR0SvmLoadGuestXcptIntercepts(pVCpu, pVmcb );2111 hmR0SvmLoadGuestXcptIntercepts(pVCpu, pVmcb, pCtx); 2088 2112 2089 2113 rc = hmR0SvmSetupVMRunHandler(pVCpu); … … 2241 2265 2242 2266 hmR0SvmLoadGuestApicStateNested(pVCpu, pVmcbNstGst); 2243 hmR0SvmLoadGuestXcptInterceptsNested(pVCpu, pVmcbNstGst );2267 hmR0SvmLoadGuestXcptInterceptsNested(pVCpu, pVmcbNstGst, pCtx); 2244 2268 2245 2269 rc = hmR0SvmSetupVMRunHandler(pVCpu); … … 2289 2313 if (HMCPU_CF_IS_PENDING(pVCpu, HM_CHANGED_GUEST_CR0)) 2290 2314 { 2291 #ifdef VBOX_WITH_NESTED_HWVIRT2292 /* We use nested-guest CR0 unmodified, hence nothing to do here. */2293 if (!CPUMIsGuestInSvmNestedHwVirtMode(pCtx))2294 hmR0SvmLoadSharedCR0(pVCpu, pVmcb, pCtx);2295 else2296 Assert(pVmcb->guest.u64CR0 == pCtx->cr0);2297 #else2298 2315 hmR0SvmLoadSharedCR0(pVCpu, pVmcb, pCtx); 2299 #endif2300 2316 HMCPU_CF_CLEAR(pVCpu, HM_CHANGED_GUEST_CR0); 2301 2317 } … … 2303 2319 if (HMCPU_CF_IS_PENDING(pVCpu, HM_CHANGED_GUEST_DEBUG)) 2304 2320 { 2305 /* We use nested-guest CR0 unmodified, hence nothing to do here. */2321 /** @todo Figure out stepping with nested-guest. */ 2306 2322 if (!CPUMIsGuestInSvmNestedHwVirtMode(pCtx)) 2307 2323 hmR0SvmLoadSharedDebugState(pVCpu, pVmcb, pCtx); … … 6481 6497 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitDRxRead); 6482 6498 6483 /* We should -not- get this #VMEXIT if the guest's debug registers were active. */6484 if ( pSvmTransient->fWasGuestDebugStateActive)6485 { 6486 AssertMsgFailed(("hmR0SvmExitReadDRx: Unexpected exit %#RX32\n", (uint32_t)pSvmTransient->u64ExitCode));6487 pVCpu->hm.s.u32HMError = (uint32_t)pSvmTransient->u64ExitCode;6488 return VERR_SVM_UNEXPECTED_EXIT;6489 }6490 6491 /*6492 * Lazy DR0-3 loading.6493 */ 6494 if ( !pSvmTransient->fWasHyperDebugStateActive6495 #ifdef VBOX_WITH_NESTED_HWVIRT 6496 && !CPUMIsGuestInSvmNestedHwVirtMode(pCtx) /** @todo implement single-stepping when executing a nested-guest.*/6497 #endif 6498 )6499 {6500 Assert(!DBGFIsStepping(pVCpu)); Assert(!pVCpu->hm.s.fSingleInstruction);6501 Log5(("hmR0SvmExitReadDRx: Lazy loading guest debug registers\n")); 6502 6503 /* Don't intercept DRx read and writes. */6504 PSVMVMCB pVmcb = pVCpu->hm.s.svm.pVmcb;6505 pVmcb->ctrl.u16InterceptRdDRx = 0;6506 pVmcb->ctrl.u16InterceptWrDRx = 0;6507 pVmcb->ctrl.u64VmcbCleanBits &= ~HMSVM_VMCB_CLEAN_INTERCEPTS; 6508 6509 /* We're playing with the host CPU state here, make sure we don't preempt or longjmp. */6510 VMMRZCallRing3Disable(pVCpu);6511 HM_DISABLE_PREEMPT(); 6512 6513 /* Save the host & load the guest debug state, restart execution of the MOV DRx instruction. */6514 CPUMR0LoadGuestDebugState(pVCpu, false /* include DR6 */);6515 Assert(CPUMIsGuestDebugStateActive(pVCpu) || HC_ARCH_BITS == 32); 6516 6517 HM_RESTORE_PREEMPT();6518 VMMRZCallRing3Enable(pVCpu); 6519 6520 STAM_COUNTER_INC(&pVCpu->hm.s.StatDRxContextSwitch);6521 return VINF_SUCCESS;6499 /** @todo Stepping with nested-guest. */ 6500 if (!CPUMIsGuestInSvmNestedHwVirtMode(pCtx)) 6501 { 6502 /* We should -not- get this #VMEXIT if the guest's debug registers were active. */ 6503 if (pSvmTransient->fWasGuestDebugStateActive) 6504 { 6505 AssertMsgFailed(("hmR0SvmExitReadDRx: Unexpected exit %#RX32\n", (uint32_t)pSvmTransient->u64ExitCode)); 6506 pVCpu->hm.s.u32HMError = (uint32_t)pSvmTransient->u64ExitCode; 6507 return VERR_SVM_UNEXPECTED_EXIT; 6508 } 6509 6510 /* 6511 * Lazy DR0-3 loading. 6512 */ 6513 if (!pSvmTransient->fWasHyperDebugStateActive) 6514 { 6515 Assert(!DBGFIsStepping(pVCpu)); Assert(!pVCpu->hm.s.fSingleInstruction); 6516 Log5(("hmR0SvmExitReadDRx: Lazy loading guest debug registers\n")); 6517 6518 /* Don't intercept DRx read and writes. */ 6519 PSVMVMCB pVmcb = pVCpu->hm.s.svm.pVmcb; 6520 pVmcb->ctrl.u16InterceptRdDRx = 0; 6521 pVmcb->ctrl.u16InterceptWrDRx = 0; 6522 pVmcb->ctrl.u64VmcbCleanBits &= ~HMSVM_VMCB_CLEAN_INTERCEPTS; 6523 6524 /* We're playing with the host CPU state here, make sure we don't preempt or longjmp. */ 6525 VMMRZCallRing3Disable(pVCpu); 6526 HM_DISABLE_PREEMPT(); 6527 6528 /* Save the host & load the guest debug state, restart execution of the MOV DRx instruction. */ 6529 CPUMR0LoadGuestDebugState(pVCpu, false /* include DR6 */); 6530 Assert(CPUMIsGuestDebugStateActive(pVCpu) || HC_ARCH_BITS == 32); 6531 6532 HM_RESTORE_PREEMPT(); 6533 VMMRZCallRing3Enable(pVCpu); 6534 6535 STAM_COUNTER_INC(&pVCpu->hm.s.StatDRxContextSwitch); 6536 return VINF_SUCCESS; 6537 } 6522 6538 } 6523 6539
Note:
See TracChangeset
for help on using the changeset viewer.