VirtualBox

Changeset 66790 in vbox for trunk


Ignore:
Timestamp:
May 4, 2017 12:27:56 PM (7 years ago)
Author:
vboxsync
Message:

VMM/HMVMXR0: Fixes while using the IEM event reflection logic.

File:
1 edited

Legend:

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

    r66756 r66790  
    59005900        uint32_t const uIdtVector     = VMX_IDT_VECTORING_INFO_VECTOR(pVmxTransient->uIdtVectoringInfo);
    59015901#ifdef HMVMX_USE_IEM_EVENT_REFLECTION
    5902         /* See Intel spec. 30.7.1.1 "Reflecting Exceptions to Guest Software". */
     5902        /*
     5903         * If the event was a software interrupt (generated with INT n) or a software exception (generated
     5904         * by INT3/INTO) or a privileged software exception (generated by INT1), we can handle the VM-exit
     5905         * and continue guest execution which will re-execute the instruction rather than re-injecting the
     5906         * exception, as that can cause premature trips to ring-3 before injection and involve TRPM which
     5907         * currently has no way of storing that these exceptions were caused by these instructions
     5908         * (ICEBP's #DB poses the problem).
     5909         */
    59035910        IEMXCPTRAISE     enmRaise;
    59045911        IEMXCPTRAISEINFO fRaiseInfo;
    5905         if (VMX_EXIT_INTERRUPTION_INFO_IS_VALID(pVmxTransient->uExitIntInfo))
     5912        if (   uIdtVectorType == VMX_IDT_VECTORING_INFO_TYPE_SW_INT
     5913            || uIdtVectorType == VMX_IDT_VECTORING_INFO_TYPE_SW_XCPT
     5914            || uIdtVectorType == VMX_IDT_VECTORING_INFO_TYPE_PRIV_SW_XCPT)
     5915        {
     5916            enmRaise   = IEMXCPTRAISE_REEXEC_INSTR;
     5917            fRaiseInfo = IEMXCPTRAISEINFO_NONE;
     5918        }
     5919        else if (VMX_EXIT_INTERRUPTION_INFO_IS_VALID(pVmxTransient->uExitIntInfo))
    59065920        {
    59075921            uint32_t const uExitVectorType  = VMX_IDT_VECTORING_INFO_TYPE(pVmxTransient->uExitIntInfo);
    59085922            uint32_t const fIdtVectorFlags  = hmR0VmxGetIemXcptFlags(uIdtVector, uIdtVectorType);
    59095923            uint32_t const fExitVectorFlags = hmR0VmxGetIemXcptFlags(uExitVector, uExitVectorType);
    5910             AssertMsg(   uExitVectorType == VMX_EXIT_INTERRUPTION_INFO_TYPE_HW_XCPT
    5911                       || uExitVectorType == VMX_EXIT_INTERRUPTION_INFO_TYPE_NMI,
    5912                       ("hmR0VmxCheckExitDueToEventDelivery: Unexpected VM-exit interruption info. type %#x!\n", uExitVectorType));
    5913             enmRaise = IEMEvaluateRecursiveXcpt(pVCpu, fIdtVectorFlags, uIdtVector, fExitVectorFlags, uExitVector,
    5914                                                 &fRaiseInfo);
    5915 
    5916             if (fRaiseInfo & (IEMXCPTRAISEINFO_EXT_INT_XCPT | IEMXCPTRAISEINFO_NMI_XCPT))
    5917             {
    5918                 /*
    5919                  * For some reason we go back to the interpreter if delivery of an external interrupt or
    5920                  * NMI causes an exception, see hmR0VmxExitXcptOrNmi. As long as we go back to the interpret
    5921                  * we need to keep the previous (first) event pending, hence this hack.
    5922                  */
    5923                 enmRaise = IEMXCPTRAISE_PREV_EVENT;
    5924 
    5925                 /* Determine a vectoring #PF condition, see comment in hmR0VmxExitXcptPF(). */
    5926                 if (fRaiseInfo & (IEMXCPTRAISEINFO_EXT_INT_PF | IEMXCPTRAISEINFO_NMI_PF))
    5927                     pVmxTransient->fVectoringPF = true;
    5928             }
     5924            /** @todo Make AssertMsgReturn as just AssertMsg later. */
     5925            AssertMsgReturn(uExitVectorType == VMX_EXIT_INTERRUPTION_INFO_TYPE_HW_XCPT,
     5926                            ("hmR0VmxCheckExitDueToEventDelivery: Unexpected VM-exit interruption info. %#x!\n",
     5927                             uExitVectorType), VERR_VMX_IPE_5);
     5928            enmRaise = IEMEvaluateRecursiveXcpt(pVCpu, fIdtVectorFlags, uIdtVector, fExitVectorFlags, uExitVector, &fRaiseInfo);
    59295929        }
    59305930        else
    59315931        {
    59325932            /*
    5933              * If event delivery caused an EPT violation/misconfig or APIC access VM-exit, then the VM-exit
    5934              * interruption-information will not be valid as it's not an exception and we end up here.
    5935              *
    5936              * If the event was an external interrupt or hardare exception (incl. NMI) it is sufficient to
    5937              * reflect this event to the guest after handling the VM-exit.
    5938              *
    5939              * If the event was a software interrupt (generated with INT n) or a software exception (generated
    5940              * by INT3/INTO) or a privileged software exception (generated by INT1), we can handle the VM-exit
    5941              * and continue guest execution which will re-execute the instruction rather than re-injecting the
    5942              * event, as that can cause premature trips to ring-3 before injection and involve TRPM which
    5943              * currently has no way of storing that the exceptions were caused by these special instructions.
     5933             * If an exception or hardware interrupt delivery caused an EPT violation/misconfig or APIC access
     5934             * VM-exit, then the VM-exit interruption-information will not be valid and we end up here.
     5935             * It is sufficient to reflect the original event to the guest after handling the VM-exit.
    59445936             */
    5945             if (   uIdtVectorType == VMX_IDT_VECTORING_INFO_TYPE_HW_XCPT
    5946                 || uIdtVectorType == VMX_IDT_VECTORING_INFO_TYPE_NMI
    5947                 || uIdtVectorType == VMX_IDT_VECTORING_INFO_TYPE_EXT_INT)
    5948                 enmRaise = IEMXCPTRAISE_PREV_EVENT;
    5949             else
    5950                 enmRaise = IEMXCPTRAISE_REEXEC_INSTR;
     5937            Assert(   uIdtVectorType == VMX_IDT_VECTORING_INFO_TYPE_HW_XCPT
     5938                   || uIdtVectorType == VMX_IDT_VECTORING_INFO_TYPE_NMI
     5939                   || uIdtVectorType == VMX_IDT_VECTORING_INFO_TYPE_EXT_INT);
     5940            enmRaise   = IEMXCPTRAISE_PREV_EVENT;
    59515941            fRaiseInfo = IEMXCPTRAISEINFO_NONE;
    59525942        }
     
    59725962        {
    59735963            case IEMXCPTRAISE_CURRENT_XCPT:
    5974             case IEMXCPTRAISE_REEXEC_INSTR:
    5975                 Assert(rcStrict == VINF_SUCCESS);
    5976                 break;
    5977 
    59785964            case IEMXCPTRAISE_PREV_EVENT:
    59795965            {
    5980                 /*
    5981                  * Re-raise the previous (first) exception/interrupt as delivery caused a premature VM-exit.
    5982                  */
    5983                 Assert(   uIdtVectorType != VMX_IDT_VECTORING_INFO_TYPE_SW_INT
    5984                        && uIdtVectorType != VMX_IDT_VECTORING_INFO_TYPE_SW_XCPT
    5985                        && uIdtVectorType != VMX_IDT_VECTORING_INFO_TYPE_PRIV_SW_XCPT);
     5966                /* Determine a vectoring #PF condition, see comment in hmR0VmxExitXcptPF(). */
     5967                if (fRaiseInfo & (IEMXCPTRAISEINFO_EXT_INT_PF | IEMXCPTRAISEINFO_NMI_PF))
     5968                    pVmxTransient->fVectoringPF = true;
    59865969
    59875970                uint32_t u32ErrCode;
     
    60055988                break;
    60065989            }
     5990
     5991            case IEMXCPTRAISE_REEXEC_INSTR:
     5992                Assert(rcStrict == VINF_SUCCESS);
     5993                break;
    60075994
    60085995            case IEMXCPTRAISE_DOUBLE_FAULT:
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