VirtualBox

Changeset 79751 in vbox for trunk/src/VBox/VMM


Ignore:
Timestamp:
Jul 13, 2019 9:00:45 AM (6 years ago)
Author:
vboxsync
Message:

VMM/HMVMXR0: Nested VMX: bugref:9180 Clean up exception/NMI handling.

File:
1 edited

Legend:

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

    r79750 r79751  
    8484#define HMVMX_READ_GUEST_LINEAR_ADDR                RT_BIT_32(7)
    8585/** @} */
     86
     87/** All the VMCS fields required for our processing of exception/NMI VM-exits. */
     88#define HMVMX_READ_XCPT_INFO                        (  HMVMX_READ_EXIT_INTERRUPTION_INFO        \
     89                                                     | HMVMX_READ_EXIT_INTERRUPTION_ERROR_CODE  \
     90                                                     | HMVMX_READ_EXIT_INSTR_LEN                \
     91                                                     | HMVMX_READ_IDT_VECTORING_INFO            \
     92                                                     | HMVMX_READ_IDT_VECTORING_ERROR_CODE)
    8693
    8794/**
     
    1362513632    Assert(!pVCpu->hm.s.Event.fPending);
    1362613633
     13634#ifdef VBOX_STRICT
     13635    /*
     13636     * Validate we have read the required fields from the VMCS.
     13637     */
     13638    uint32_t const fVmcsFieldRead = ASMAtomicUoReadU32(&pVmxTransient->fVmcsFieldsRead);
     13639    RT_UNTRUSTED_NONVOLATILE_COPY_FENCE();
     13640    Assert((fVmcsFieldRead & HMVMX_READ_XCPT_INFO) == HMVMX_READ_XCPT_INFO);
     13641#endif
     13642
    1362713643    /*
    1362813644     * Construct a pending event from IDT vectoring information.
     
    1375613772    VBOXSTRICTRC rcStrict = VINF_SUCCESS;
    1375713773
    13758     /* Read the IDT vectoring info. and VM-exit interruption info. */
    13759     {
    13760         int rc = hmR0VmxReadIdtVectoringInfoVmcs(pVmxTransient);
    13761         rc    |= hmR0VmxReadExitIntInfoVmcs(pVmxTransient);
    13762         AssertRCReturn(rc, rc);
    13763     }
     13774#ifdef VBOX_STRICT
     13775    /*
     13776     * Validate we have read the required fields from the VMCS.
     13777     */
     13778    uint32_t const fVmcsFieldRead = ASMAtomicUoReadU32(&pVmxTransient->fVmcsFieldsRead);
     13779    RT_UNTRUSTED_NONVOLATILE_COPY_FENCE();
     13780    Assert((fVmcsFieldRead & HMVMX_READ_XCPT_INFO) == HMVMX_READ_XCPT_INFO);
     13781#endif
    1376413782
    1376513783    uint32_t const uExitIntInfo   = pVmxTransient->uExitIntInfo;
     
    1385113869                uint32_t u32ErrCode;
    1385213870                if (VMX_IDT_VECTORING_INFO_IS_ERROR_CODE_VALID(uIdtVectorInfo))
    13853                 {
    13854                     int rc = hmR0VmxReadIdtVectoringErrorCodeVmcs(pVmxTransient);
    13855                     AssertRCReturn(rc, rc);
    1385613871                    u32ErrCode = pVmxTransient->uIdtVectoringErrorCode;
    13857                 }
    1385813872                else
    1385913873                    u32ErrCode = 0;
     
    1434214356/**
    1434314357 * VM-exit exception handler for \#PF (Page-fault exception).
     14358 *
     14359 * @remarks Requires all fields in HMVMX_READ_XCPT_INFO to be read from the VMCS.
    1434414360 */
    1434514361static VBOXSTRICTRC hmR0VmxExitXcptPF(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
     
    1434814364    PVM pVM = pVCpu->CTX_SUFF(pVM);
    1434914365    int rc = hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
    14350     rc    |= hmR0VmxReadExitIntInfoVmcs(pVmxTransient);
    14351     rc    |= hmR0VmxReadExitIntErrorCodeVmcs(pVmxTransient);
    1435214366    AssertRCReturn(rc, rc);
    1435314367
     
    1444114455/**
    1444214456 * VM-exit exception handler for \#MF (Math Fault: floating point exception).
     14457 *
     14458 * @remarks Requires all fields in HMVMX_READ_XCPT_INFO to be read from the VMCS.
    1444314459 */
    1444414460static VBOXSTRICTRC hmR0VmxExitXcptMF(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
     
    1446314479    }
    1446414480
    14465     rc  = hmR0VmxReadExitIntInfoVmcs(pVmxTransient);
    14466     rc |= hmR0VmxReadExitIntErrorCodeVmcs(pVmxTransient);
    14467     rc |= hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
    14468     AssertRCReturn(rc, rc);
    14469 
    1447014481    hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntInfo), pVmxTransient->cbInstr,
    1447114482                           pVmxTransient->uExitIntErrorCode, 0 /* GCPtrFaultAddress */);
    14472     return rc;
     14483    return VINF_SUCCESS;
    1447314484}
    1447414485
     
    1447614487/**
    1447714488 * VM-exit exception handler for \#BP (Breakpoint exception).
     14489 *
     14490 * @remarks Requires all fields in HMVMX_READ_XCPT_INFO to be read from the VMCS.
    1447814491 */
    1447914492static VBOXSTRICTRC hmR0VmxExitXcptBP(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
     
    1448514498    AssertRCReturn(rc, rc);
    1448614499
    14487     PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
    1448814500    if (!pVmxTransient->fIsNestedGuest)
    14489         rc = DBGFRZTrap03Handler(pVCpu->CTX_SUFF(pVM), pVCpu, CPUMCTX2CORE(pCtx));
     14501        rc = DBGFRZTrap03Handler(pVCpu->CTX_SUFF(pVM), pVCpu, CPUMCTX2CORE(&pVCpu->cpum.GstCtx));
    1449014502    else
    1449114503        rc = VINF_EM_RAW_GUEST_TRAP;
    1449214504    if (rc == VINF_EM_RAW_GUEST_TRAP)
    1449314505    {
    14494         rc  = hmR0VmxReadExitIntInfoVmcs(pVmxTransient);
    14495         rc |= hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
    14496         rc |= hmR0VmxReadExitIntErrorCodeVmcs(pVmxTransient);
    14497         AssertRCReturn(rc, rc);
    14498 
    1449914506        hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntInfo), pVmxTransient->cbInstr,
    1450014507                               pVmxTransient->uExitIntErrorCode, 0 /* GCPtrFaultAddress */);
     
    1450814515/**
    1450914516 * VM-exit exception handler for \#AC (Alignment-check exception).
     14517 *
     14518 * @remarks Requires all fields in HMVMX_READ_XCPT_INFO to be read from the VMCS.
    1451014519 */
    1451114520static VBOXSTRICTRC hmR0VmxExitXcptAC(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
     
    1451414523    STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestAC);
    1451514524
    14516     /*
    14517      * Re-inject it. We'll detect any nesting before getting here.
    14518      */
    14519     int rc = hmR0VmxReadExitIntErrorCodeVmcs(pVmxTransient);
    14520     rc    |= hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
    14521     AssertRCReturn(rc, rc);
    14522     Assert(ASMAtomicUoReadU32(&pVmxTransient->fVmcsFieldsRead) & HMVMX_READ_EXIT_INTERRUPTION_INFO);
    14523 
     14525    /* Re-inject it. We'll detect any nesting before getting here. */
    1452414526    hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntInfo), pVmxTransient->cbInstr,
    1452514527                           pVmxTransient->uExitIntErrorCode, 0 /* GCPtrFaultAddress */);
     
    1453014532/**
    1453114533 * VM-exit exception handler for \#DB (Debug exception).
     14534 *
     14535 * @remarks Requires all fields in HMVMX_READ_XCPT_INFO to be read from the VMCS.
    1453214536 */
    1453314537static VBOXSTRICTRC hmR0VmxExitXcptDB(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
     
    1454014544     */
    1454114545    int rc = hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
     14546    AssertRCReturn(rc, rc);
    1454214547
    1454314548    /* Refer Intel spec. Table 27-1. "Exit Qualifications for debug exceptions" for the format. */
     
    1459414599         * Intel 386, see Intel spec. 24.8.3 "VM-Entry Controls for Event Injection".
    1459514600         */
    14596         rc  = hmR0VmxReadExitIntInfoVmcs(pVmxTransient);
    14597         rc |= hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
    14598         rc |= hmR0VmxReadExitIntErrorCodeVmcs(pVmxTransient);
    14599         AssertRCReturn(rc, rc);
    1460014601        hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntInfo), pVmxTransient->cbInstr,
    1460114602                               pVmxTransient->uExitIntErrorCode, 0 /* GCPtrFaultAddress */);
     
    1468414685/**
    1468514686 * VM-exit exception handler for \#GP (General-protection exception).
     14687 *
     14688 * @remarks Requires all fields in HMVMX_READ_XCPT_INFO to be read from the VMCS.
    1468614689 */
    1468714690static VBOXSTRICTRC hmR0VmxExitXcptGP(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
     
    1469014693    STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestGP);
    1469114694
    14692     PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
     14695    PCPUMCTX     pCtx      = &pVCpu->cpum.GstCtx;
    1469314696    PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
    1469414697    if (pVmcsInfo->RealMode.fRealOnV86Active)
     
    1470314706         * executing a nested-guest, reflect #GP to the guest or nested-guest.
    1470414707         */
    14705         int rc  = hmR0VmxReadExitIntInfoVmcs(pVmxTransient);
    14706         rc     |= hmR0VmxReadExitIntErrorCodeVmcs(pVmxTransient);
    14707         rc     |= hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
    14708         rc     |= hmR0VmxImportGuestState(pVCpu, pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
     14708        int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
    1470914709        AssertRCReturn(rc, rc);
    1471014710        Log4Func(("Gst: cs:rip=%#04x:%#RX64 ErrorCode=%#x cr0=%#RX64 cpl=%u tr=%#04x\n", pCtx->cs.Sel, pCtx->rip,
     
    1476714767 * This simply re-injects the exception back into the VM without any special
    1476814768 * processing.
     14769 *
     14770 * @remarks Requires all fields in HMVMX_READ_XCPT_INFO to be read from the VMCS.
    1476914771 */
    1477014772static VBOXSTRICTRC hmR0VmxExitXcptOthers(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
     
    1478414786     * would have been handled while checking exits due to event delivery.
    1478514787     */
    14786     int rc = hmR0VmxReadExitIntInfoVmcs(pVmxTransient);
    14787     rc    |= hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
    14788     rc    |= hmR0VmxReadExitIntErrorCodeVmcs(pVmxTransient);
    14789     AssertRCReturn(rc, rc);
    14790 
    1479114788    uint8_t const uVector = VMX_EXIT_INT_INFO_VECTOR(pVmxTransient->uExitIntInfo);
    1479214789
    1479314790#ifdef HMVMX_ALWAYS_TRAP_ALL_XCPTS
    14794     rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_CS | CPUMCTX_EXTRN_RIP);
     14791    int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_CS | CPUMCTX_EXTRN_RIP);
    1479514792    AssertRCReturn(rc, rc);
    1479614793    Log4Func(("Reinjecting Xcpt. uVector=%#x cs:rip=%#04x:%#RX64\n", uVector, pCtx->cs.Sel, pCtx->rip));
     
    1484214839DECL_FORCE_INLINE(VBOXSTRICTRC) hmR0VmxExitXcptAll(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient, uint8_t uVector)
    1484314840{
     14841    /*
     14842     * Validate we have read the required fields from the VMCS.
     14843     */
     14844#ifdef VBOX_STRICT
     14845    uint32_t const fVmcsFieldRead = ASMAtomicUoReadU32(&pVmxTransient->fVmcsFieldsRead);
     14846    RT_UNTRUSTED_NONVOLATILE_COPY_FENCE();
     14847    Assert((fVmcsFieldRead & HMVMX_READ_XCPT_INFO) == HMVMX_READ_XCPT_INFO);
     14848#endif
     14849
    1484414850    switch (uVector)
    1484514851    {
     
    1489014896    AssertRCReturn(rc, rc);
    1489114897
    14892     uint32_t const uIntType = VMX_EXIT_INT_INFO_TYPE(pVmxTransient->uExitIntInfo);
     14898    uint32_t const uExitIntType = VMX_EXIT_INT_INFO_TYPE(pVmxTransient->uExitIntInfo);
     14899    uint32_t const uVector      =  VMX_EXIT_INT_INFO_VECTOR(pVmxTransient->uExitIntInfo);
    1489314900    Assert(VMX_EXIT_INT_INFO_IS_VALID(pVmxTransient->uExitIntInfo));
    1489414901
    1489514902    PCVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
    1489614903    Assert(   !(pVmcsInfo->u32ExitCtls & VMX_EXIT_CTLS_ACK_EXT_INT)
    14897            && uIntType != VMX_EXIT_INT_INFO_TYPE_EXT_INT);
     14904           && uExitIntType != VMX_EXIT_INT_INFO_TYPE_EXT_INT);
    1489814905    NOREF(pVmcsInfo);
    1489914906
    14900     if (uIntType == VMX_EXIT_INT_INFO_TYPE_NMI)
     14907    VBOXSTRICTRC rcStrict;
     14908    switch (uExitIntType)
    1490114909    {
    1490214910        /*
    14903          * This cannot be a guest NMI as the only way for the guest to receive an NMI is if we
    14904          * injected it ourselves and anything we inject is not going to cause a VM-exit directly
    14905          * for the event being injected[1]. Go ahead and dispatch the NMI to the host[2].
     14911         * Host physical NMIs:
     14912         *     This cannot be a guest NMI as the only way for the guest to receive an NMI is if we
     14913         *     injected it ourselves and anything we inject is not going to cause a VM-exit directly
     14914         *     for the event being injected[1]. Go ahead and dispatch the NMI to the host[2].
    1490614915         *
    14907          * [1] -- See Intel spec. 27.2.3 "Information for VM Exits During Event Delivery".
    14908          * [2] -- See Intel spec. 27.5.5 "Updating Non-Register State".
     14916         *     See Intel spec. 27.2.3 "Information for VM Exits During Event Delivery".
     14917         *     See Intel spec. 27.5.5 "Updating Non-Register State".
    1490914918         */
    14910         STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitXcptNmi, y3);
    14911         return hmR0VmxExitHostNmi(pVCpu, pVmcsInfo);
    14912     }
    14913 
    14914     /* If this VM-exit occurred while delivering an event through the guest IDT, handle it accordingly. */
    14915     VBOXSTRICTRC rcStrict = hmR0VmxCheckExitDueToEventDelivery(pVCpu, pVmxTransient);
    14916     if (RT_UNLIKELY(rcStrict == VINF_SUCCESS))
    14917     { /* likely */ }
    14918     else
    14919     {
    14920         if (rcStrict == VINF_HM_DOUBLE_FAULT)
    14921         {
    14922             Assert(pVCpu->hm.s.Event.fPending);
    14923             rcStrict = VINF_SUCCESS;
    14924         }
    14925         STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitXcptNmi, y3);
    14926         return rcStrict;
    14927     }
    14928 
    14929     uint32_t const uExitIntInfo = pVmxTransient->uExitIntInfo;
    14930     uint32_t const uVector      = VMX_EXIT_INT_INFO_VECTOR(uExitIntInfo);
    14931     switch (uIntType)
    14932     {
    14933         case VMX_EXIT_INT_INFO_TYPE_PRIV_SW_XCPT:  /* Privileged software exception. (#DB from ICEBP) */
     14919        case VMX_EXIT_INT_INFO_TYPE_NMI:
     14920        {
     14921            rcStrict = hmR0VmxExitHostNmi(pVCpu, pVmcsInfo);
     14922            break;
     14923        }
     14924
     14925        /*
     14926         * Privileged software exceptions (#DB from ICEBP),
     14927         * Software exceptions (#BP and #OF),
     14928         * Hardware exceptions:
     14929         *     Process the required exceptions and resume guest execution if possible.
     14930         */
     14931        case VMX_EXIT_INT_INFO_TYPE_PRIV_SW_XCPT:
    1493414932            Assert(uVector == X86_XCPT_DB);
    1493514933            RT_FALL_THRU();
    14936         case VMX_EXIT_INT_INFO_TYPE_SW_XCPT:       /* Software exception. (#BP or #OF) */
    14937             Assert(uVector == X86_XCPT_BP || uVector == X86_XCPT_OF || uIntType == VMX_EXIT_INT_INFO_TYPE_PRIV_SW_XCPT);
     14934        case VMX_EXIT_INT_INFO_TYPE_SW_XCPT:
     14935            Assert(uVector == X86_XCPT_BP || uVector == X86_XCPT_OF || uExitIntType == VMX_EXIT_INT_INFO_TYPE_PRIV_SW_XCPT);
    1493814936            RT_FALL_THRU();
    1493914937        case VMX_EXIT_INT_INFO_TYPE_HW_XCPT:
    1494014938        {
     14939            rc  = hmR0VmxReadExitIntErrorCodeVmcs(pVmxTransient);
     14940            rc |= hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
     14941            rc |= hmR0VmxReadIdtVectoringInfoVmcs(pVmxTransient);
     14942            rc |= hmR0VmxReadIdtVectoringErrorCodeVmcs(pVmxTransient);
     14943            AssertRCReturn(rc, rc);
     14944
    1494114945            /*
    14942              * If there's any exception caused as a result of event injection, the resulting
    14943              * secondary/final execption will be pending, we shall continue guest execution
    14944              * after injecting the event. The page-fault case is complicated and we manually
    14945              * handle any currently pending event in hmR0VmxExitXcptPF.
     14946             * If this VM-exit occurred while delivering an event through the guest IDT, take
     14947             * action based on the return code and additional hints (e.g. for page-faults)
     14948             * that will be updated in the VMX transient structure.
    1494614949             */
    14947             if (!pVCpu->hm.s.Event.fPending)
    14948             { /* likely */ }
    14949             else if (uVector != X86_XCPT_PF)
     14950            rcStrict = hmR0VmxCheckExitDueToEventDelivery(pVCpu, pVmxTransient);
     14951            if (rcStrict == VINF_SUCCESS)
    1495014952            {
     14953                /*
     14954                 * If an exception caused a VM-exit due to delivery of an event, the secondary
     14955                 * exception may be made pending for re-injection. We shall reinject it and
     14956                 * continue guest execution. However, the page-fault case is a complicated case
     14957                 * and needs additional processing done in hmR0VmxExitXcptPF.
     14958                 */
     14959                if (   !pVCpu->hm.s.Event.fPending
     14960                    || uVector == X86_XCPT_PF)
     14961                    rcStrict = hmR0VmxExitXcptAll(pVCpu, pVmxTransient, uVector);
     14962            }
     14963            else if (rcStrict == VINF_HM_DOUBLE_FAULT)
     14964            {
     14965                Assert(pVCpu->hm.s.Event.fPending);
    1495114966                rcStrict = VINF_SUCCESS;
    14952                 break;
    1495314967            }
    14954             rcStrict = hmR0VmxExitXcptAll(pVCpu, pVmxTransient, uVector);
    1495514968            break;
    1495614969        }
     
    1495814971        default:
    1495914972        {
    14960             pVCpu->hm.s.u32HMError = uExitIntInfo;
     14973            pVCpu->hm.s.u32HMError = pVmxTransient->uExitIntInfo;
    1496114974            rcStrict = VERR_VMX_UNEXPECTED_INTERRUPTION_EXIT_TYPE;
    14962             AssertMsgFailed(("Unexpected interruption info %#x\n", VMX_EXIT_INT_INFO_TYPE(uExitIntInfo)));
     14975            AssertMsgFailed(("Invalid/unexpected VM-exit interruption info %#x\n", pVmxTransient->uExitIntInfo));
    1496314976            break;
    1496414977        }
    1496514978    }
     14979
    1496614980    STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitXcptNmi, y3);
    1496714981    return rcStrict;
     
    1629016304    STAM_COUNTER_INC(&pVCpu->hm.s.StatExitApicAccess);
    1629116305
    16292     /* If this VM-exit occurred while delivering an event through the guest IDT, handle it accordingly. */
    16293     VBOXSTRICTRC rcStrict1 = hmR0VmxCheckExitDueToEventDelivery(pVCpu, pVmxTransient);
    16294     if (RT_LIKELY(rcStrict1 == VINF_SUCCESS))
     16306    int rc  = hmR0VmxReadExitIntInfoVmcs(pVmxTransient);
     16307    rc     |= hmR0VmxReadExitIntErrorCodeVmcs(pVmxTransient);
     16308    rc     |= hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
     16309    rc     |= hmR0VmxReadIdtVectoringInfoVmcs(pVmxTransient);
     16310    rc     |= hmR0VmxReadIdtVectoringErrorCodeVmcs(pVmxTransient);
     16311    AssertRCReturn(rc, rc);
     16312
     16313    /*
     16314     * If this VM-exit occurred while delivering an event through the guest IDT, handle it accordingly.
     16315     */
     16316    VBOXSTRICTRC rcStrict = hmR0VmxCheckExitDueToEventDelivery(pVCpu, pVmxTransient);
     16317    if (RT_LIKELY(rcStrict == VINF_SUCCESS))
    1629516318    {
    1629616319        /* For some crazy guest, if an event delivery causes an APIC-access VM-exit, go to instruction emulation. */
     
    1630316326    else
    1630416327    {
    16305         if (rcStrict1 == VINF_HM_DOUBLE_FAULT)
    16306         {
    16307             Assert(pVCpu->hm.s.Event.fPending);
    16308             rcStrict1 = VINF_SUCCESS;
    16309         }
    16310         return rcStrict1;
     16328        Assert(rcStrict != VINF_HM_DOUBLE_FAULT);
     16329        return rcStrict;
    1631116330    }
    1631216331
    1631316332    /* IOMMIOPhysHandler() below may call into IEM, save the necessary state. */
    1631416333    PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
    16315     int rc  = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
    16316     rc     |= hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
     16334    rc  = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
     16335    rc |= hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
    1631716336    AssertRCReturn(rc, rc);
    1631816337
    1631916338    /* See Intel spec. 27-6 "Exit Qualifications for APIC-access VM-exits from Linear Accesses & Guest-Phyiscal Addresses" */
    1632016339    uint32_t const uAccessType = VMX_EXIT_QUAL_APIC_ACCESS_TYPE(pVmxTransient->uExitQual);
    16321     VBOXSTRICTRC rcStrict2;
    1632216340    switch (uAccessType)
    1632316341    {
     
    1633716355            PVM      pVM  = pVCpu->CTX_SUFF(pVM);
    1633816356            PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
    16339             rcStrict2 = IOMMMIOPhysHandler(pVM, pVCpu,
    16340                                            uAccessType == VMX_APIC_ACCESS_TYPE_LINEAR_READ ? 0 : X86_TRAP_PF_RW,
    16341                                            CPUMCTX2CORE(pCtx), GCPhys);
    16342             Log4Func(("IOMMMIOPhysHandler returned %Rrc\n", VBOXSTRICTRC_VAL(rcStrict2)));
    16343             if (   rcStrict2 == VINF_SUCCESS
    16344                 || rcStrict2 == VERR_PAGE_TABLE_NOT_PRESENT
    16345                 || rcStrict2 == VERR_PAGE_NOT_PRESENT)
     16357            rcStrict = IOMMMIOPhysHandler(pVM, pVCpu,
     16358                                          uAccessType == VMX_APIC_ACCESS_TYPE_LINEAR_READ ? 0 : X86_TRAP_PF_RW,
     16359                                          CPUMCTX2CORE(pCtx), GCPhys);
     16360            Log4Func(("IOMMMIOPhysHandler returned %Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
     16361            if (   rcStrict == VINF_SUCCESS
     16362                || rcStrict == VERR_PAGE_TABLE_NOT_PRESENT
     16363                || rcStrict == VERR_PAGE_NOT_PRESENT)
    1634616364            {
    1634716365                ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RSP | HM_CHANGED_GUEST_RFLAGS
    1634816366                                                         | HM_CHANGED_GUEST_APIC_TPR);
    16349                 rcStrict2 = VINF_SUCCESS;
     16367                rcStrict = VINF_SUCCESS;
    1635016368            }
    1635116369            break;
     
    1635516373        {
    1635616374            Log4Func(("uAccessType=%#x\n", uAccessType));
    16357             rcStrict2 = VINF_EM_RAW_EMULATE_INSTR;
     16375            rcStrict = VINF_EM_RAW_EMULATE_INSTR;
    1635816376            break;
    1635916377        }
    1636016378    }
    1636116379
    16362     if (rcStrict2 != VINF_SUCCESS)
     16380    if (rcStrict != VINF_SUCCESS)
    1636316381        STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchApicAccessToR3);
    16364     return rcStrict2;
     16382    return rcStrict;
    1636516383}
    1636616384
     
    1646516483    Assert(pVCpu->CTX_SUFF(pVM)->hm.s.fNestedPaging);
    1646616484
    16467     /* If this VM-exit occurred while delivering an event through the guest IDT, handle it accordingly. */
     16485    int rc  = hmR0VmxReadExitIntInfoVmcs(pVmxTransient);
     16486    rc     |= hmR0VmxReadExitIntErrorCodeVmcs(pVmxTransient);
     16487    rc     |= hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
     16488    rc     |= hmR0VmxReadIdtVectoringInfoVmcs(pVmxTransient);
     16489    rc     |= hmR0VmxReadIdtVectoringErrorCodeVmcs(pVmxTransient);
     16490    AssertRCReturn(rc, rc);
     16491
     16492    /*
     16493     * If this VM-exit occurred while delivering an event through the guest IDT, handle it accordingly.
     16494     */
    1646816495    VBOXSTRICTRC rcStrict = hmR0VmxCheckExitDueToEventDelivery(pVCpu, pVmxTransient);
    1646916496    if (RT_LIKELY(rcStrict == VINF_SUCCESS))
     
    1648916516    else
    1649016517    {
    16491         if (rcStrict == VINF_HM_DOUBLE_FAULT)
    16492             rcStrict = VINF_SUCCESS;
     16518        Assert(rcStrict != VINF_HM_DOUBLE_FAULT);
    1649316519        return rcStrict;
    1649416520    }
     
    1649916525    RTGCPHYS GCPhys;
    1650016526    PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
    16501     int rc = VMXReadVmcs64(VMX_VMCS64_RO_GUEST_PHYS_ADDR_FULL, &GCPhys);
    16502     rc    |= hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
     16527    rc = VMXReadVmcs64(VMX_VMCS64_RO_GUEST_PHYS_ADDR_FULL, &GCPhys);
     16528    rc |= hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
    1650316529    AssertRCReturn(rc, rc);
    1650416530
     
    1655716583    Assert(pVCpu->CTX_SUFF(pVM)->hm.s.fNestedPaging);
    1655816584
    16559     /* If this VM-exit occurred while delivering an event through the guest IDT, handle it accordingly. */
     16585    int rc  = hmR0VmxReadExitIntInfoVmcs(pVmxTransient);
     16586    rc     |= hmR0VmxReadExitIntErrorCodeVmcs(pVmxTransient);
     16587    rc     |= hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
     16588    rc     |= hmR0VmxReadIdtVectoringInfoVmcs(pVmxTransient);
     16589    rc     |= hmR0VmxReadIdtVectoringErrorCodeVmcs(pVmxTransient);
     16590    AssertRCReturn(rc, rc);
     16591
     16592    /*
     16593     * If this VM-exit occurred while delivering an event through the guest IDT, handle it accordingly.
     16594     */
    1656016595    VBOXSTRICTRC rcStrict = hmR0VmxCheckExitDueToEventDelivery(pVCpu, pVmxTransient);
    1656116596    if (RT_LIKELY(rcStrict == VINF_SUCCESS))
     
    1657016605    else
    1657116606    {
    16572         if (rcStrict == VINF_HM_DOUBLE_FAULT)
    16573         {
    16574             Assert(pVCpu->hm.s.Event.fPending);
    16575             rcStrict = VINF_SUCCESS;
    16576         }
     16607        Assert(rcStrict != VINF_HM_DOUBLE_FAULT);
    1657716608        return rcStrict;
    1657816609    }
     
    1658016611    RTGCPHYS GCPhys;
    1658116612    PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
    16582     int rc  = VMXReadVmcs64(VMX_VMCS64_RO_GUEST_PHYS_ADDR_FULL, &GCPhys);
    16583     rc     |= hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
    16584     rc     |= hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
     16613    rc  = VMXReadVmcs64(VMX_VMCS64_RO_GUEST_PHYS_ADDR_FULL, &GCPhys);
     16614    rc |= hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
     16615    rc |= hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
    1658516616    AssertRCReturn(rc, rc);
    1658616617
     
    1699817029    HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
    1699917030
    17000     int rc = hmR0VmxCheckExitDueToEventDeliveryNested(pVCpu, pVmxTransient);
    17001     AssertRCReturn(rc, rc);
    17002 
    17003     rc = hmR0VmxReadExitIntInfoVmcs(pVmxTransient);
     17031    int rc = hmR0VmxReadExitIntInfoVmcs(pVmxTransient);
    1700417032    AssertRCReturn(rc, rc);
    1700517033
     
    1701217040        /*
    1701317041         * Physical NMIs:
    17014          *   We shouldn't direct host physical NMIs to the nested-guest. Dispatch it to the host.
     17042         *     We shouldn't direct host physical NMIs to the nested-guest. Dispatch it to the host.
    1701517043         */
    1701617044        case VMX_EXIT_INT_INFO_TYPE_NMI:
    17017         {
    17018             Assert(!pVCpu->hm.s.Event.fPending);  /* An NMI cannot be caused by the delivery on another event. */
    1701917045            return hmR0VmxExitHostNmi(pVCpu, pVmxTransient->pVmcsInfo);
    17020         }
    1702117046
    1702217047        /*
     
    1702417049         * Software exceptions,
    1702517050         * Privileged software exceptions:
    17026          *   Figure out if the exception must be delivered to the guest or the nested-guest.
    17027          *
    17028          *   For VM-exits due to software exceptions (those generated by INT3 or INTO) and privileged
    17029          *   software exceptions (those generated by INT1/ICEBP) we need to supply the VM-exit instruction
    17030          *   length. However, if delivery of a software interrupt, software exception or privileged
    17031          *   software exception causes a VM-exit, that too provides the VM-exit instruction length.
    17032          *   Hence, we read it for all exception types below to keep it simple.
     17051         *     Figure out if the exception must be delivered to the guest or the nested-guest.
    1703317052         */
    1703417053        case VMX_EXIT_INT_INFO_TYPE_SW_XCPT:
     
    1703617055        case VMX_EXIT_INT_INFO_TYPE_HW_XCPT:
    1703717056        {
    17038             rc  = hmR0VmxReadExitIntErrorCodeVmcs(pVmxTransient);
    17039             rc |= hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
     17057            rc    |= hmR0VmxReadExitIntErrorCodeVmcs(pVmxTransient);
     17058            rc    |= hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
     17059            rc    |= hmR0VmxReadIdtVectoringInfoVmcs(pVmxTransient);
     17060            rc    |= hmR0VmxReadIdtVectoringErrorCodeVmcs(pVmxTransient);
     17061            AssertRCReturn(rc, rc);
     17062
     17063            /*
     17064             * If this VM-exit occurred while delivering an event through the nested-guest IDT, handle it accordingly.
     17065             */
     17066            rc = hmR0VmxCheckExitDueToEventDeliveryNested(pVCpu, pVmxTransient);
    1704017067            AssertRCReturn(rc, rc);
    1704117068
     
    1704817075            if (fIntercept)
    1704917076            {
    17050                 rc  = hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
    17051                 rc |= hmR0VmxReadIdtVectoringInfoVmcs(pVmxTransient);
    17052                 rc |= hmR0VmxReadIdtVectoringErrorCodeVmcs(pVmxTransient);
     17077                rc = hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
    1705317078                AssertRCReturn(rc, rc);
    1705417079
     17080                /*
     17081                 * For VM-exits due to software exceptions (those generated by INT3 or INTO) and privileged
     17082                 * software exceptions (those generated by INT1/ICEBP) we need to supply the VM-exit instruction
     17083                 * length. However, if delivery of a software interrupt, software exception or privileged
     17084                 * software exception causes a VM-exit, that too provides the VM-exit instruction length.
     17085                 */
    1705517086                VMXVEXITINFO ExitInfo;
    1705617087                RT_ZERO(ExitInfo);
     
    1768817719    HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
    1768917720
    17690     int rc = hmR0VmxCheckExitDueToEventDeliveryNested(pVCpu, pVmxTransient);
     17721    int rc  = hmR0VmxReadExitIntInfoVmcs(pVmxTransient);
     17722    rc     |= hmR0VmxReadExitIntErrorCodeVmcs(pVmxTransient);
     17723    rc     |= hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
     17724    rc     |= hmR0VmxReadIdtVectoringInfoVmcs(pVmxTransient);
     17725    rc     |= hmR0VmxReadIdtVectoringErrorCodeVmcs(pVmxTransient);
    1769117726    AssertRCReturn(rc, rc);
    1769217727
     17728    rc = hmR0VmxCheckExitDueToEventDeliveryNested(pVCpu, pVmxTransient);
     17729    AssertRCReturn(rc, rc);
     17730
    1769317731    Assert(CPUMIsGuestVmxProcCtls2Set(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS2_VIRT_APIC_ACCESS));
    17694     rc  = hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
    17695     rc |= hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
    17696     rc |= hmR0VmxReadIdtVectoringInfoVmcs(pVmxTransient);
    17697     rc |= hmR0VmxReadIdtVectoringErrorCodeVmcs(pVmxTransient);
     17732    rc = hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
    1769817733    AssertRCReturn(rc, rc);
    1769917734
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