VirtualBox

Changeset 52653 in vbox


Ignore:
Timestamp:
Sep 9, 2014 1:40:20 PM (10 years ago)
Author:
vboxsync
Message:

VMM/HMVMXR0,VMM/HMSVMR0: Fix incorrect disassembly of instruction caused by a #PF caused due to an ext. int/NMI while dealing with shadow #PFs. Fixes the warcraft 2 testcase.

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

Legend:

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

    r52396 r52653  
    218218    /** Whether the #VMEXIT was caused by a page-fault during delivery of a
    219219     *  contributary exception or a page-fault. */
     220    bool            fVectoringDoublePF;
     221    /** Whether the VM-exit was caused by a page-fault during delivery of an
     222     *  external interrupt or NMI. */
    220223    bool            fVectoringPF;
    221224} SVMTRANSIENT, *PSVMTRANSIENT;
     
    22092212    }
    22102213
     2214    /* If we're emulating an instruction, we shouldn't have any TRPM traps pending
     2215       and if we're injecting an event we should have a TRPM trap pending. */
     2216    Assert(rcExit != VINF_EM_RAW_INJECT_TRPM_EVENT || TRPMHasTrap(pVCpu));
     2217    Assert(rcExit != VINF_EM_RAW_EMULATE_INSTR || !TRPMHasTrap(pVCpu));
     2218
    22112219    /* Sync. the necessary state for going back to ring-3. */
    22122220    hmR0SvmLeaveSession(pVM, pVCpu, pCtx);
     
    32203228    pSvmTransient->u64ExitCode  = pVmcb->ctrl.u64ExitCode;      /* Save the #VMEXIT reason. */
    32213229    HMCPU_EXIT_HISTORY_ADD(pVCpu, pVmcb->ctrl.u64ExitCode);     /* Update the #VMEXIT history array. */
     3230    pSvmTransient->fVectoringDoublePF = false;                  /* Vectoring double page-fault needs to be determined later. */
    32223231    pSvmTransient->fVectoringPF = false;                        /* Vectoring page-fault needs to be determined later. */
    32233232
     
    40554064                    && uIdtVector  == X86_XCPT_PF)
    40564065                {
    4057                     pSvmTransient->fVectoringPF = true;
    4058                     Log4(("IDT: Vectoring #PF uCR2=%#RX64\n", pCtx->cr2));
     4066                    pSvmTransient->fVectoringDoublePF = true;
     4067                    Log4(("IDT: Vectoring double #PF uCR2=%#RX64\n", pCtx->cr2));
    40594068                }
    40604069                else if (   (pVmcb->ctrl.u32InterceptException & HMSVM_CONTRIBUTORY_XCPT_MASK)
     
    40854094            }
    40864095        }
    4087         else if (pVmcb->ctrl.ExitIntInfo.n.u3Type != SVM_EVENT_SOFTWARE_INT)
    4088         {
    4089             /* Ignore software interrupts (INT n) as they reoccur when restarting the instruction. */
     4096        else if (   pVmcb->ctrl.ExitIntInfo.n.u3Type == SVM_EVENT_EXTERNAL_IRQ
     4097                 || pVmcb->ctrl.ExitIntInfo.n.u3Type == SVM_EVENT_NMI)
     4098        {
    40904099            enmReflect = SVMREFLECTXCPT_XCPT;
    40914100            fReflectingNmi = RT_BOOL(pVmcb->ctrl.ExitIntInfo.n.u3Type == SVM_EVENT_NMI);
    4092         }
     4101
     4102            if (pSvmTransient->u64ExitCode - SVM_EXIT_EXCEPTION_0 <= SVM_EXIT_EXCEPTION_1F)
     4103            {
     4104                uint8_t uExitVector = (uint8_t)(pSvmTransient->u64ExitCode - SVM_EXIT_EXCEPTION_0);
     4105                if (uExitVector == X86_XCPT_PF)
     4106                {
     4107                    pSvmTransient->fVectoringPF = true;
     4108                    Log4(("IDT: Vectoring #PF due to Ext-Int/NMI. uCR2=%#RX64\n", pCtx->cr2));
     4109                }
     4110            }
     4111        }
     4112        /* else: Ignore software interrupts (INT n) as they reoccur when restarting the instruction. */
    40934113
    40944114        switch (enmReflect)
     
    50445064    {
    50455065        pVCpu->hm.s.Event.fPending = false;     /* In case it's a contributory or vectoring #PF. */
    5046         if (!pSvmTransient->fVectoringPF)
     5066        if (!pSvmTransient->fVectoringDoublePF)
    50475067        {
    50485068            /* A genuine guest #PF, reflect it to the guest. */
     
    50945114          pCtx->rip, u32ErrCode, pCtx->cr3));
    50955115
     5116    /* If it's a vectoring #PF, emulate injecting the original event injection as PGMTrap0eHandler() is incapable
     5117       of differentiating between instruction emulation and event injection that caused a #PF. See @bugref{}. */
     5118    if (pSvmTransient->fVectoringPF)
     5119    {
     5120        Assert(pVCpu->hm.s.Event.fPending);
     5121        return VINF_EM_RAW_INJECT_TRPM_EVENT;
     5122    }
     5123
    50965124    TRPMAssertXcptPF(pVCpu, uFaultAddress, u32ErrCode);
    50975125    int rc = PGMTrap0eHandler(pVCpu, u32ErrCode, CPUMCTX2CORE(pCtx), (RTGCPTR)uFaultAddress);
     
    51115139        pVCpu->hm.s.Event.fPending = false;     /* In case it's a contributory or vectoring #PF. */
    51125140
    5113         if (!pSvmTransient->fVectoringPF)
     5141        if (!pSvmTransient->fVectoringDoublePF)
    51145142        {
    51155143            /* It's a guest page fault and needs to be reflected to the guest. */
  • trunk/src/VBox/VMM/VMMR0/HMVMXR0.cpp

    r52611 r52653  
    279279    /** Whether the VM-exit was caused by a page-fault during delivery of a
    280280     *  contributory exception or a page-fault. */
     281    bool            fVectoringDoublePF;
     282    /** Whether the VM-exit was caused by a page-fault during delivery of an
     283     *  external interrupt or NMI. */
    281284    bool            fVectoringPF;
    282285} VMXTRANSIENT;
     
    58015804                    && uIdtVector == X86_XCPT_PF)
    58025805                {
    5803                     pVmxTransient->fVectoringPF = true;
    5804                     Log4(("IDT: vcpu[%RU32] Vectoring #PF uCR2=%#RX64\n", pVCpu->idCpu, pMixedCtx->cr2));
     5806                    pVmxTransient->fVectoringDoublePF = true;
     5807                    Log4(("IDT: vcpu[%RU32] Vectoring Double #PF uCR2=%#RX64\n", pVCpu->idCpu, pMixedCtx->cr2));
    58055808                }
    58065809                else if (   (pVCpu->hm.s.vmx.u32XcptBitmap & HMVMX_CONTRIBUTORY_XCPT_MASK)
     
    58145817                    enmReflect = VMXREFLECTXCPT_TF;
    58155818            }
    5816             else if (   uIdtVectorType == VMX_IDT_VECTORING_INFO_TYPE_HW_XCPT
    5817                      || uIdtVectorType == VMX_IDT_VECTORING_INFO_TYPE_EXT_INT
     5819            else if (   uIdtVectorType == VMX_IDT_VECTORING_INFO_TYPE_EXT_INT
    58185820                     || uIdtVectorType == VMX_IDT_VECTORING_INFO_TYPE_NMI)
    58195821            {
     
    58235825                 */
    58245826                enmReflect = VMXREFLECTXCPT_XCPT;
     5827
     5828                if (uExitVector == X86_XCPT_PF)
     5829                {
     5830                    pVmxTransient->fVectoringPF = true;
     5831                    Log4(("IDT: vcpu[%RU32] Vectoring #PF due to Ext-Int/NMI. uCR2=%#RX64\n", pVCpu->idCpu, pMixedCtx->cr2));
     5832                }
    58255833            }
    58265834        }
     
    71877195    }
    71887196
     7197    /* If we're emulating an instruction, we shouldn't have any TRPM traps pending
     7198       and if we're injecting an event we should have a TRPM trap pending. */
     7199    Assert(rcExit != VINF_EM_RAW_INJECT_TRPM_EVENT || TRPMHasTrap(pVCpu));
     7200    Assert(rcExit != VINF_EM_RAW_EMULATE_INSTR || !TRPMHasTrap(pVCpu));
     7201
    71897202    /* Save guest state and restore host state bits. */
    71907203    int rc = hmR0VmxLeaveSession(pVM, pVCpu, pMixedCtx);
    71917204    AssertRCReturn(rc, rc);
    71927205    STAM_COUNTER_DEC(&pVCpu->hm.s.StatSwitchLongJmpToR3);
     7206    /* Thread-context hooks are unregistered at this point!!! */
    71937207
    71947208    /* Sync recompiler state. */
     
    86788692    pVmxTransient->fVmcsFieldsRead     = 0;                     /* Transient fields need to be read from the VMCS. */
    86798693    pVmxTransient->fVectoringPF        = false;                 /* Vectoring page-fault needs to be determined later. */
     8694    pVmxTransient->fVectoringDoublePF  = false;                 /* Vectoring double page-fault needs to be determined later. */
    86808695
    86818696    if (!(pVCpu->hm.s.vmx.u32ProcCtls & VMX_VMCS_CTRL_PROC_EXEC_RDTSC_EXIT))
     
    1196311978    {
    1196411979        pVCpu->hm.s.Event.fPending = false;                  /* In case it's a contributory or vectoring #PF. */
    11965         if (RT_LIKELY(!pVmxTransient->fVectoringPF))
     11980        if (RT_LIKELY(!pVmxTransient->fVectoringDoublePF))
    1196611981        {
    1196711982            pMixedCtx->cr2 = pVmxTransient->uExitQualification;  /* Update here in case we go back to ring-3 before injection. */
     
    1198211997    NOREF(pVM);
    1198311998#endif
     11999
     12000    /* If it's a vectoring #PF, emulate injecting the original event injection as PGMTrap0eHandler() is incapable
     12001       of differentiating between instruction emulation and event injection that caused a #PF. See @bugref{}. */
     12002    if (pVmxTransient->fVectoringPF)
     12003    {
     12004        Assert(pVCpu->hm.s.Event.fPending);
     12005        return VINF_EM_RAW_INJECT_TRPM_EVENT;
     12006    }
    1198412007
    1198512008    rc = hmR0VmxSaveGuestState(pVCpu, pMixedCtx);
     
    1200912032    else if (rc == VINF_EM_RAW_GUEST_TRAP)
    1201012033    {
    12011         if (!pVmxTransient->fVectoringPF)
     12034        if (!pVmxTransient->fVectoringDoublePF)
    1201212035        {
    1201312036            /* It's a guest page fault and needs to be reflected to the guest. */
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