VirtualBox

Changeset 69934 in vbox


Ignore:
Timestamp:
Dec 5, 2017 12:16:04 PM (7 years ago)
Author:
vboxsync
Message:

VMM/HMSVMR0: Nested Hw.virt: Bits

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/VMM/VMMR0/HMSVMR0.cpp

    r69932 r69934  
    12301230 * updates the corresponding VMCB Clean bit.
    12311231 *
     1232 * @param   pVCpu       The cross context virtual CPU structure.
     1233 * @param   pCtx        Pointer to the guest-CPU context.
    12321234 * @param   pVmcb       Pointer to the VM control block.
    12331235 * @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 */
     1241DECLINLINE(void) hmR0SvmRemoveXcptIntercept(PVMCPU pVCpu, PCPUMCTX pCtx, PSVMVMCB pVmcb, uint32_t u32Xcpt)
    12361242{
    12371243    Assert(u32Xcpt != X86_XCPT_DB);
     
    12401246    if (pVmcb->ctrl.u32InterceptXcpt & RT_BIT(u32Xcpt))
    12411247    {
    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);
    12451259#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 *
    12511276 * Although the guest CR0 is a separate field in the VMCB we have to consider
    12521277 * the FPU state itself which is shared between the host and the guest.
     
    13031328        hmR0SvmAddXcptIntercept(pVmcb, X86_XCPT_NM);
    13041329    else
    1305         hmR0SvmRemoveXcptIntercept(pVmcb, X86_XCPT_NM);
     1330        hmR0SvmRemoveXcptIntercept(pVCpu, pCtx, pVmcb, X86_XCPT_NM);
    13061331
    13071332    if (fInterceptMF)
    13081333        hmR0SvmAddXcptIntercept(pVmcb, X86_XCPT_MF);
    13091334    else
    1310         hmR0SvmRemoveXcptIntercept(pVmcb, X86_XCPT_MF);
     1335        hmR0SvmRemoveXcptIntercept(pVCpu, pCtx, pVmcb, X86_XCPT_MF);
    13111336
    13121337    pVmcb->guest.u64CR0 = u64GuestCR0;
     
    18161841 * @param   pVCpu       The cross context virtual CPU structure.
    18171842 * @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 */
     1845static void hmR0SvmLoadGuestXcptIntercepts(PVMCPU pVCpu, PSVMVMCB pVmcb, PCPUMCTX pCtx)
    18201846{
    18211847    if (HMCPU_CF_IS_PENDING(pVCpu, HM_CHANGED_GUEST_XCPT_INTERCEPTS))
     
    18251851            hmR0SvmAddXcptIntercept(pVmcb, X86_XCPT_UD);
    18261852        else
    1827             hmR0SvmRemoveXcptIntercept(pVmcb, X86_XCPT_UD);
     1853            hmR0SvmRemoveXcptIntercept(pVCpu, pCtx, pVmcb, X86_XCPT_UD);
    18281854
    18291855        /* Trap #BP for INT3 debug breakpoints set by the VM debugger. */
     
    18311857            hmR0SvmAddXcptIntercept(pVmcb, X86_XCPT_BP);
    18321858        else
    1833             hmR0SvmRemoveXcptIntercept(pVmcb, X86_XCPT_BP);
     1859            hmR0SvmRemoveXcptIntercept(pVCpu, pCtx, pVmcb, X86_XCPT_BP);
    18341860
    18351861        /* The remaining intercepts are handled elsewhere, e.g. in hmR0SvmLoadSharedCR0(). */
     
    18491875 * @param   pVCpu           The cross context virtual CPU structure.
    18501876 * @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 */
     1879static void hmR0SvmLoadGuestXcptInterceptsNested(PVMCPU pVCpu, PSVMVMCB pVmcbNstGst, PCPUMCTX pCtx)
    18531880{
    18541881    if (HMCPU_CF_IS_PENDING(pVCpu, HM_CHANGED_GUEST_XCPT_INTERCEPTS))
     
    18561883        /* First, load the guest intercepts into the guest VMCB. */
    18571884        PSVMVMCB pVmcb = pVCpu->hm.s.svm.pVmcb;
    1858         hmR0SvmLoadGuestXcptIntercepts(pVCpu, pVmcb);
     1885        hmR0SvmLoadGuestXcptIntercepts(pVCpu, pVmcb, pCtx);
    18591886
    18601887        /* Next, merge the intercepts into the nested-guest VMCB. */
     
    18941921        pVmcbNstGst->ctrl.u64InterceptCtrl  &= ~SVM_CTRL_INTERCEPT_VMMCALL;
    18951922
    1896         /* Remove exception intercepts that we don't need while executing the nested-guest. */
    1897         pVmcbNstGst->ctrl.u32InterceptXcpt  &= ~RT_BIT(X86_XCPT_UD);
    1898 
    18991923        Assert(!HMCPU_CF_IS_PENDING(pVCpu, HM_CHANGED_GUEST_XCPT_INTERCEPTS));
    19001924    }
     
    20852109    AssertLogRelMsgRCReturn(rc, ("hmR0SvmLoadGuestApicState! rc=%Rrc (pVM=%p pVCpu=%p)\n", rc, pVM, pVCpu), rc);
    20862110
    2087     hmR0SvmLoadGuestXcptIntercepts(pVCpu, pVmcb);
     2111    hmR0SvmLoadGuestXcptIntercepts(pVCpu, pVmcb, pCtx);
    20882112
    20892113    rc = hmR0SvmSetupVMRunHandler(pVCpu);
     
    22412265
    22422266    hmR0SvmLoadGuestApicStateNested(pVCpu, pVmcbNstGst);
    2243     hmR0SvmLoadGuestXcptInterceptsNested(pVCpu, pVmcbNstGst);
     2267    hmR0SvmLoadGuestXcptInterceptsNested(pVCpu, pVmcbNstGst, pCtx);
    22442268
    22452269    rc = hmR0SvmSetupVMRunHandler(pVCpu);
     
    22892313    if (HMCPU_CF_IS_PENDING(pVCpu, HM_CHANGED_GUEST_CR0))
    22902314    {
    2291 #ifdef VBOX_WITH_NESTED_HWVIRT
    2292         /* We use nested-guest CR0 unmodified, hence nothing to do here. */
    2293         if (!CPUMIsGuestInSvmNestedHwVirtMode(pCtx))
    2294             hmR0SvmLoadSharedCR0(pVCpu, pVmcb, pCtx);
    2295         else
    2296             Assert(pVmcb->guest.u64CR0 == pCtx->cr0);
    2297 #else
    22982315        hmR0SvmLoadSharedCR0(pVCpu, pVmcb, pCtx);
    2299 #endif
    23002316        HMCPU_CF_CLEAR(pVCpu, HM_CHANGED_GUEST_CR0);
    23012317    }
     
    23032319    if (HMCPU_CF_IS_PENDING(pVCpu, HM_CHANGED_GUEST_DEBUG))
    23042320    {
    2305         /* We use nested-guest CR0 unmodified, hence nothing to do here. */
     2321        /** @todo Figure out stepping with nested-guest. */
    23062322        if (!CPUMIsGuestInSvmNestedHwVirtMode(pCtx))
    23072323            hmR0SvmLoadSharedDebugState(pVCpu, pVmcb, pCtx);
     
    64816497    STAM_COUNTER_INC(&pVCpu->hm.s.StatExitDRxRead);
    64826498
    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->fWasHyperDebugStateActive
    6495 #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        }
    65226538    }
    65236539
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette