VirtualBox

Changeset 72440 in vbox


Ignore:
Timestamp:
Jun 5, 2018 5:45:11 AM (6 years ago)
Author:
vboxsync
Message:

VMM: Nested hw.virt: Fixes when nested-paging isn't enabled in the outer guest.

Location:
trunk/src/VBox/VMM
Files:
2 edited

Legend:

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

    r72212 r72440  
    9191        else if (     rc == VINF_HM_DOUBLE_FAULT) { return VINF_SUCCESS;            } \
    9292        else if (     rc == VINF_EM_RESET \
    93                  &&   HMIsGuestSvmCtrlInterceptSet(pVCpu, pCtx, SVM_CTRL_INTERCEPT_SHUTDOWN)) \
     93                 &&   CPUMIsGuestSvmCtrlInterceptSet(pVCpu, pCtx, SVM_CTRL_INTERCEPT_SHUTDOWN)) \
    9494            return VBOXSTRICTRC_TODO(IEMExecSvmVmexit(pVCpu, SVM_EXIT_SHUTDOWN, 0, 0)); \
    9595        else \
     
    374374#endif
    375375#ifdef VBOX_WITH_NESTED_HWVIRT_SVM
    376 static FNSVMEXITHANDLER hmR0SvmExitXcptPFNested;
    377376static FNSVMEXITHANDLER hmR0SvmExitClgi;
    378377static FNSVMEXITHANDLER hmR0SvmExitStgi;
     
    50995098                    return HM_SVM_VMEXIT_NESTED(pVCpu, uExitCode, u32ErrCode, uFaultAddress);
    51005099
    5101                 /* If the nested-guest is not intercepting #PFs, forward the #PF to the nested-guest. */
     5100                /* If the nested-guest is not intercepting #PFs, forward the #PF to the guest. */
    51025101                hmR0SvmSetPendingXcptPF(pVCpu, pCtx, u32ErrCode, uFaultAddress);
    51035102                return VINF_SUCCESS;
    51045103            }
    5105             return hmR0SvmExitXcptPFNested(pVCpu, pCtx,pSvmTransient);
     5104            return hmR0SvmExitXcptPF(pVCpu, pCtx,pSvmTransient);
    51065105        }
    51075106
     
    58835882                    /* Determine a vectoring #PF condition, see comment in hmR0SvmExitXcptPF(). */
    58845883                    if (fRaiseInfo & (IEMXCPTRAISEINFO_EXT_INT_PF | IEMXCPTRAISEINFO_NMI_PF))
     5884                    {
    58855885                        pSvmTransient->fVectoringPF = true;
     5886                        Log4(("IDT: Pending vectoring #PF due to delivery of Ext-Int/NMI. uCR2=%#RX64\n", pCtx->cr2));
     5887                    }
    58865888                    else if (   pVmcb->ctrl.ExitIntInfo.n.u3Type == SVM_EVENT_EXCEPTION
    58875889                             && uIdtVector == X86_XCPT_PF)
     
    59235925                if (fRaiseInfo & IEMXCPTRAISEINFO_PF_PF)
    59245926                {
     5927                    Log4(("IDT: Pending vectoring double #PF uCR2=%#RX64\n", pCtx->cr2));
    59255928                    pSvmTransient->fVectoringDoublePF = true;
    59265929                    Assert(rc == VINF_SUCCESS);
     
    72527255{
    72537256    HMSVM_VALIDATE_EXIT_HANDLER_PARAMS();
    7254     HMSVM_ASSERT_NOT_IN_NESTED_GUEST(pCtx);
    72557257
    72567258    HMSVM_CHECK_EXIT_DUE_TO_EVENT_DELIVERY();
    72577259
    72587260    /* See AMD spec. 15.12.15 "#PF (Page Fault)". */
    7259     PSVMVMCB    pVmcb         = pVCpu->hm.s.svm.pVmcb;
    7260     uint32_t    u32ErrCode    = pVmcb->ctrl.u64ExitInfo1;
    7261     RTGCUINTPTR uFaultAddress = pVmcb->ctrl.u64ExitInfo2;
    7262     PVM         pVM           = pVCpu->CTX_SUFF(pVM);
     7261    PVM             pVM           = pVCpu->CTX_SUFF(pVM);
     7262    PSVMVMCB        pVmcb         = hmR0SvmGetCurrentVmcb(pVCpu, pCtx);
     7263    uint32_t        uErrCode      = pVmcb->ctrl.u64ExitInfo1;
     7264    uint64_t const  uFaultAddress = pVmcb->ctrl.u64ExitInfo2;
    72637265
    72647266#if defined(HMSVM_ALWAYS_TRAP_ALL_XCPTS) || defined(HMSVM_ALWAYS_TRAP_PF)
     
    72667268    {
    72677269        pVCpu->hm.s.Event.fPending = false;     /* In case it's a contributory or vectoring #PF. */
    7268         if (!pSvmTransient->fVectoringDoublePF)
     7270        if (   !pSvmTransient->fVectoringDoublePF
     7271            || CPUMIsGuestInSvmNestedHwVirtMode(pCtx))
    72697272        {
    72707273            /* A genuine guest #PF, reflect it to the guest. */
    7271             hmR0SvmSetPendingXcptPF(pVCpu, pCtx, u32ErrCode, uFaultAddress);
    7272             Log4(("#PF: Guest page fault at %04X:%RGv FaultAddr=%RGv ErrCode=%#x\n", pCtx->cs.Sel, (RTGCPTR)pCtx->rip,
    7273                   uFaultAddress, u32ErrCode));
     7274            hmR0SvmSetPendingXcptPF(pVCpu, pCtx, uErrCode, uFaultAddress);
     7275            Log4(("#PF: Guest page fault at %04X:%RGv FaultAddr=%RX64 ErrCode=%#x\n", pCtx->cs.Sel, (RTGCPTR)pCtx->rip,
     7276                  uFaultAddress, uErrCode));
    72747277        }
    72757278        else
     
    72917294    if (   pVM->hm.s.fTprPatchingAllowed
    72927295        && (uFaultAddress & 0xfff) == XAPIC_OFF_TPR
    7293         && !(u32ErrCode & X86_TRAP_PF_P)              /* Not present. */
     7296        && !(uErrCode & X86_TRAP_PF_P)                /* Not present. */
     7297        && !CPUMIsGuestInSvmNestedHwVirtMode(pCtx)
    72947298        && !CPUMIsGuestInLongModeEx(pCtx)
    72957299        && !CPUMGetGuestCPL(pVCpu)
     
    73137317    }
    73147318
    7315     Log4(("#PF: uFaultAddress=%#RX64 CS:RIP=%#04x:%#RX64 u32ErrCode %#RX32 cr3=%#RX64\n", uFaultAddress, pCtx->cs.Sel,
    7316           pCtx->rip, u32ErrCode, pCtx->cr3));
     7319    Log4(("#PF: uFaultAddress=%#RX64 CS:RIP=%#04x:%#RX64 uErrCode %#RX32 cr3=%#RX64\n", uFaultAddress, pCtx->cs.Sel,
     7320          pCtx->rip, uErrCode, pCtx->cr3));
    73177321
    73187322    /* If it's a vectoring #PF, emulate injecting the original event injection as PGMTrap0eHandler() is incapable
     
    73247328    }
    73257329
    7326     TRPMAssertXcptPF(pVCpu, uFaultAddress, u32ErrCode);
    7327     int rc = PGMTrap0eHandler(pVCpu, u32ErrCode, CPUMCTX2CORE(pCtx), (RTGCPTR)uFaultAddress);
    7328 
    7329     Log4(("#PF rc=%Rrc\n", rc));
     7330    TRPMAssertXcptPF(pVCpu, uFaultAddress, uErrCode);
     7331    int rc = PGMTrap0eHandler(pVCpu, uErrCode, CPUMCTX2CORE(pCtx), (RTGCPTR)uFaultAddress);
     7332
     7333    Log4(("#PF: rc=%Rrc\n", rc));
    73307334
    73317335    if (rc == VINF_SUCCESS)
     
    73377341        return rc;
    73387342    }
    7339     else if (rc == VINF_EM_RAW_GUEST_TRAP)
     7343
     7344    if (rc == VINF_EM_RAW_GUEST_TRAP)
    73407345    {
    73417346        pVCpu->hm.s.Event.fPending = false;     /* In case it's a contributory or vectoring #PF. */
    73427347
    7343         if (!pSvmTransient->fVectoringDoublePF)
    7344         {
    7345             /* It's a guest page fault and needs to be reflected to the guest. */
    7346             u32ErrCode = TRPMGetErrorCode(pVCpu);        /* The error code might have been changed. */
     7348        /*
     7349         * If a nested-guest delivers a #PF and that causes a #PF which is -not- a shadow #PF,
     7350         * we should simply forward the #PF to the guest and is up to the nested-hypervisor to
     7351         * determine whether it is a nested-shadow #PF or a #DF, see @bugref{7243#c121}.
     7352         */
     7353        if (  !pSvmTransient->fVectoringDoublePF
     7354            || CPUMIsGuestInSvmNestedHwVirtMode(pCtx))
     7355        {
     7356            /* It's a guest (or nested-guest) page fault and needs to be reflected. */
     7357            uErrCode = TRPMGetErrorCode(pVCpu);        /* The error code might have been changed. */
    73477358            TRPMResetTrap(pVCpu);
    7348             hmR0SvmSetPendingXcptPF(pVCpu, pCtx, u32ErrCode, uFaultAddress);
     7359
     7360#ifdef VBOX_WITH_NESTED_HWVIRT_SVM
     7361            /* If the nested-guest is intercepting #PFs, cause a #PF #VMEXIT. */
     7362            if (   CPUMIsGuestInSvmNestedHwVirtMode(pCtx)
     7363                && HMIsGuestSvmXcptInterceptSet(pVCpu, pCtx, X86_XCPT_PF))
     7364                return VBOXSTRICTRC_TODO(IEMExecSvmVmexit(pVCpu, SVM_EXIT_XCPT_PF, uErrCode, uFaultAddress));
     7365#endif
     7366
     7367            hmR0SvmSetPendingXcptPF(pVCpu, pCtx, uErrCode, uFaultAddress);
    73497368        }
    73507369        else
     
    75947613#ifdef VBOX_WITH_NESTED_HWVIRT_SVM
    75957614/**
    7596  * \#VMEXIT handler for #PF occuring while in nested-guest execution
    7597  * (SVM_EXIT_XCPT_14). Conditional \#VMEXIT.
    7598  */
    7599 HMSVM_EXIT_DECL hmR0SvmExitXcptPFNested(PVMCPU pVCpu, PCPUMCTX pCtx, PSVMTRANSIENT pSvmTransient)
    7600 {
    7601     HMSVM_VALIDATE_EXIT_HANDLER_PARAMS();
    7602 
    7603     HMSVM_CHECK_EXIT_DUE_TO_EVENT_DELIVERY();
    7604 
    7605     /* See AMD spec. 15.12.15 "#PF (Page Fault)". */
    7606     PSVMVMCB       pVmcb         = hmR0SvmGetCurrentVmcb(pVCpu, pCtx);
    7607     uint32_t       u32ErrCode    = pVmcb->ctrl.u64ExitInfo1;
    7608     uint64_t const uFaultAddress = pVmcb->ctrl.u64ExitInfo2;
    7609 
    7610     Log4(("#PFNested: uFaultAddress=%#RX64 CS:RIP=%#04x:%#RX64 u32ErrCode=%#RX32 CR3=%#RX64\n", uFaultAddress, pCtx->cs.Sel,
    7611           pCtx->rip, u32ErrCode, pCtx->cr3));
    7612 
    7613     /* If it's a vectoring #PF, emulate injecting the original event injection as PGMTrap0eHandler() is incapable
    7614        of differentiating between instruction emulation and event injection that caused a #PF. See @bugref{6607}. */
    7615     if (pSvmTransient->fVectoringPF)
    7616     {
    7617         Assert(pVCpu->hm.s.Event.fPending);
    7618         return VINF_EM_RAW_INJECT_TRPM_EVENT;
    7619     }
    7620 
    7621     Assert(!pVCpu->CTX_SUFF(pVM)->hm.s.fNestedPaging);
    7622 
    7623     TRPMAssertXcptPF(pVCpu, uFaultAddress, u32ErrCode);
    7624     int rc = PGMTrap0eHandler(pVCpu, u32ErrCode, CPUMCTX2CORE(pCtx), (RTGCPTR)uFaultAddress);
    7625 
    7626     Log4(("#PFNested: rc=%Rrc\n", rc));
    7627 
    7628     if (rc == VINF_SUCCESS)
    7629     {
    7630         /* Successfully synced shadow pages tables or emulated an MMIO instruction. */
    7631         TRPMResetTrap(pVCpu);
    7632         STAM_COUNTER_INC(&pVCpu->hm.s.StatExitShadowPF);
    7633         HMCPU_CF_SET(pVCpu, HM_CHANGED_ALL_GUEST);
    7634         return rc;
    7635     }
    7636 
    7637     if (rc == VINF_EM_RAW_GUEST_TRAP)
    7638     {
    7639         pVCpu->hm.s.Event.fPending = false;     /* In case it's a contributory or vectoring #PF. */
    7640 
    7641         if (!pSvmTransient->fVectoringDoublePF)
    7642         {
    7643             /* It's a nested-guest page fault and needs to be reflected to the nested-guest. */
    7644             u32ErrCode = TRPMGetErrorCode(pVCpu);        /* The error code might have been changed. */
    7645             TRPMResetTrap(pVCpu);
    7646             hmR0SvmSetPendingXcptPF(pVCpu, pCtx, u32ErrCode, uFaultAddress);
    7647         }
    7648         else
    7649         {
    7650             /* A nested-guest page-fault occurred during delivery of a page-fault. Inject #DF. */
    7651             TRPMResetTrap(pVCpu);
    7652             hmR0SvmSetPendingXcptDF(pVCpu);
    7653             Log4(("#PF: Pending #DF due to vectoring #PF\n"));
    7654         }
    7655 
    7656         STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestPF);
    7657         return VINF_SUCCESS;
    7658     }
    7659 
    7660     TRPMResetTrap(pVCpu);
    7661     STAM_COUNTER_INC(&pVCpu->hm.s.StatExitShadowPFEM);
    7662     return rc;
    7663 }
    7664 
    7665 
    7666 /**
    76677615 * \#VMEXIT handler for CLGI (SVM_EXIT_CLGI). Conditional \#VMEXIT.
    76687616 */
  • trunk/src/VBox/VMM/VMMR3/EM.cpp

    r72327 r72440  
    17161716                             *        doesn't intercept HLT but intercepts INTR? */
    17171717                            *pfResched = true;
    1718                             return VINF_EM_RESCHEDULE;
     1718                            if (rcStrict == VINF_SVM_VMEXIT)
     1719                                return VINF_SUCCESS;
     1720                            if (rcStrict == VINF_PGM_CHANGE_MODE)
     1721                                return PGMChangeMode(pVCpu, pCtx->cr0, pCtx->cr4, pCtx->msrEFER);
     1722                            return VBOXSTRICTRC_VAL(rcStrict);
    17191723                        }
    17201724
     
    17261730                    /** @todo this really isn't nice, should properly handle this */
    17271731                    int rc = TRPMR3InjectEvent(pVM, pVCpu, TRPM_HARDWARE_INT);
     1732                    if (rc == VINF_SVM_VMEXIT)
     1733                        rc = VINF_SUCCESS;
     1734                    else if (rc == VINF_PGM_CHANGE_MODE)
     1735                        rc = PGMChangeMode(pVCpu, pCtx->cr0, pCtx->cr4, pCtx->msrEFER);
    17281736                    if (pVM->em.s.fIemExecutesAll && (   rc == VINF_EM_RESCHEDULE_REM
    17291737                                                      || rc == VINF_EM_RESCHEDULE_HM
     
    17501758                         *        doesn't intercept HLT but intercepts VINTR? */
    17511759                        *pfResched = true;
    1752                         return VINF_EM_RESCHEDULE;
     1760                        if (rcStrict == VINF_SVM_VMEXIT)
     1761                            return VINF_SUCCESS;
     1762                        if (rcStrict == VINF_PGM_CHANGE_MODE)
     1763                            return PGMChangeMode(pVCpu, pCtx->cr0, pCtx->cr4, pCtx->msrEFER);
     1764                        return VBOXSTRICTRC_VAL(rcStrict);
    17531765                    }
    17541766
     
    21292141                        /** @todo this really isn't nice, should properly handle this */
    21302142                        rc2 = TRPMR3InjectEvent(pVM, pVCpu, TRPM_HARDWARE_INT);
    2131 Log(("EM: TRPMR3InjectEvent -> %d\n", rc2));
     2143                        Log(("EM: TRPMR3InjectEvent -> %d\n", rc2));
    21322144                        if (pVM->em.s.fIemExecutesAll && (   rc2 == VINF_EM_RESCHEDULE_REM
    21332145                                                          || rc2 == VINF_EM_RESCHEDULE_HM
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