VirtualBox

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


Ignore:
Timestamp:
Oct 12, 2018 9:58:57 AM (6 years ago)
Author:
vboxsync
Message:

VMM/IEM: Nested VMX: bugref:9180 VM-exit bits; Prep work for "Acknowledge interrupt on VM-exit".

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/VMM/VMMAll/IEMAllCImplVmxInstr.cpp.h

    r74756 r74784  
    13361336 *
    13371337 * @returns The VMX event type.
    1338  * @param   uVector     The interrupt / exception vector number.
     1338 * @param   uVector     The interrupt / exception vector.
    13391339 * @param   fFlags      The IEM event flag (see IEM_XCPT_FLAGS_XXX).
    13401340 */
     
    36683668
    36693669/**
    3670  * VMX VM-exit handler for VM-exits due to delivery of an event (indirectly).
     3670 * VMX VM-exit handler for VM-exits due to external interrupts.
     3671 *
     3672 * @returns VBox strict status code.
     3673 * @param   pVCpu           The cross context virtual CPU structure.
     3674 * @param   uVector         The external interrupt vector.
     3675 * @param   fIntPending     Whether the external interrupt is pending or
     3676 *                          acknowdledged in the interrupt controller.
     3677 */
     3678IEM_STATIC VBOXSTRICTRC iemVmxVmexitExtInt(PVMCPU pVCpu, uint8_t uVector, bool fIntPending)
     3679{
     3680    PCVMXVVMCS pVmcs = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
     3681    Assert(pVmcs);
     3682
     3683    /* The VM-exit is subject to "External interrupt exiting" is being set. */
     3684    if (pVmcs->u32PinCtls & VMX_PIN_CTLS_EXT_INT_EXIT)
     3685    {
     3686        if (fIntPending)
     3687        {
     3688            /*
     3689             * If the interrupt is pending and we don't need to acknowledge the
     3690             * interrupt on VM-exit, cause the VM-exit immediately.
     3691             *
     3692             * See Intel spec 25.2 "Other Causes Of VM Exits".
     3693             */
     3694            if (!(pVmcs->u32ExitCtls & VMX_EXIT_CTLS_ACK_EXT_INT))
     3695            {
     3696                iemVmxVmcsSetExitIntInfo(pVCpu, 0);
     3697                iemVmxVmcsSetExitIntErrCode(pVCpu, 0);
     3698                iemVmxVmcsSetExitQual(pVCpu, 0);
     3699                return iemVmxVmexit(pVCpu, VMX_EXIT_EXT_INT);
     3700            }
     3701
     3702            /*
     3703             * If the interrupt is pending and we -do- need to acknowledge the interrupt
     3704             * on VM-exit, postpone VM-exit til after the interrupt controller has been
     3705             * acknowledged that the interrupt has been consumed.
     3706             */
     3707            return VINF_VMX_INTERCEPT_NOT_ACTIVE;
     3708        }
     3709
     3710        /*
     3711         * If the interrupt is no longer pending (i.e. it has been acknowledged) and the
     3712         * "External interrupt exiting" and "Acknowledge interrupt on VM-exit" controls are
     3713         * all set, we cause the VM-exit now. We need to record the external interrupt that
     3714         * just occurred in the VM-exit interruption information field.
     3715         *
     3716         * See Intel spec. 27.2.2 "Information for VM Exits Due to Vectored Events".
     3717         */
     3718        if (pVmcs->u32ExitCtls & VMX_EXIT_CTLS_ACK_EXT_INT)
     3719        {
     3720            uint8_t  const fNmiUnblocking = 0;  /** @todo NSTVMX: Implement NMI-unblocking due to IRET. */
     3721            uint32_t const uExitIntInfo   = RT_BF_MAKE(VMX_BF_EXIT_INT_INFO_VECTOR,           uVector)
     3722                                          | RT_BF_MAKE(VMX_BF_EXIT_INT_INFO_TYPE,             VMX_EXIT_INT_INFO_TYPE_EXT_INT)
     3723                                          | RT_BF_MAKE(VMX_BF_EXIT_INT_INFO_NMI_UNBLOCK_IRET, fNmiUnblocking)
     3724                                          | RT_BF_MAKE(VMX_BF_EXIT_INT_INFO_VALID,            1);
     3725            iemVmxVmcsSetExitIntInfo(pVCpu, uExitIntInfo);
     3726            iemVmxVmcsSetExitIntErrCode(pVCpu, 0);
     3727            iemVmxVmcsSetExitQual(pVCpu, 0);
     3728            return iemVmxVmexit(pVCpu, VMX_EXIT_EXT_INT);
     3729        }
     3730    }
     3731
     3732    return VINF_VMX_INTERCEPT_NOT_ACTIVE;
     3733}
     3734
     3735
     3736/**
     3737 * VMX VM-exit handler for VM-exits due to delivery of an event.
    36713738 *
    36723739 * @returns VBox strict status code.
    36733740 * @param   pVCpu       The cross context virtual CPU structure.
    3674  * @param   uVector     The interrupt / exception vector number.
     3741 * @param   uVector     The interrupt / exception vector.
    36753742 * @param   fFlags      The flags (see IEM_XCPT_FLAGS_XXX).
    36763743 * @param   uErrCode    The error code associated with the event.
     
    37083775
    37093776    /*
     3777     * We are injecting an external interrupt, check if we need to cause a VM-exit now.
     3778     * If not, the caller will continue delivery of the external interrupt as it would
     3779     * normally.
     3780     */
     3781    if (fFlags & IEM_XCPT_FLAGS_T_EXT_INT)
     3782    {
     3783        Assert(!VMX_IDT_VECTORING_INFO_IS_VALID(pVmcs->u32RoIdtVectoringInfo));
     3784        return iemVmxVmexitExtInt(pVCpu, uVector, false /* fIntPending */);
     3785    }
     3786
     3787    /*
    37103788     * Evaluate intercepts for hardware exceptions including #BP, #DB, #OF
    37113789     * generated by INT3, INT1 (ICEBP) and INTO respectively.
    37123790     */
    3713     bool     fIntercept = false;
    3714     bool     fIsHwXcpt  = false;
    3715     if (fFlags & (IEM_XCPT_FLAGS_T_CPU_XCPT | IEM_XCPT_FLAGS_T_SOFT_INT))
    3716     {
    3717         if (   !(fFlags & IEM_XCPT_FLAGS_T_SOFT_INT)
    3718             ||  (fFlags & (IEM_XCPT_FLAGS_BP_INSTR | IEM_XCPT_FLAGS_OF_INSTR | IEM_XCPT_FLAGS_ICEBP_INSTR)))
    3719         {
    3720             fIsHwXcpt = true;
    3721             do
     3791    Assert(fFlags & (IEM_XCPT_FLAGS_T_CPU_XCPT | IEM_XCPT_FLAGS_T_SOFT_INT));
     3792    bool fIntercept = false;
     3793    bool fIsHwXcpt  = false;
     3794    if (   !(fFlags & IEM_XCPT_FLAGS_T_SOFT_INT)
     3795        ||  (fFlags & (IEM_XCPT_FLAGS_BP_INSTR | IEM_XCPT_FLAGS_OF_INSTR | IEM_XCPT_FLAGS_ICEBP_INSTR)))
     3796    {
     3797        fIsHwXcpt = true;
     3798        /* NMIs have a dedicated VM-execution control for causing VM-exits. */
     3799        if (uVector == X86_XCPT_NMI)
     3800            fIntercept = RT_BOOL(pVmcs->u32PinCtls & VMX_PIN_CTLS_NMI_EXIT);
     3801        else
     3802        {
     3803            /* Page-faults are subject to masking using its error code. */
     3804            uint32_t fXcptBitmap = pVmcs->u32XcptBitmap;
     3805            if (uVector == X86_XCPT_PF)
    37223806            {
    3723                 /* NMIs have a dedicated VM-execution control for causing VM-exits. */
    3724                 if (uVector == X86_XCPT_NMI)
    3725                 {
    3726                     fIntercept = RT_BOOL(pVmcs->u32PinCtls & VMX_PIN_CTLS_NMI_EXIT);
    3727                     break;
    3728                 }
    3729 
    3730                 /* Page-faults are subject to masking using its error code. */
    3731                 uint32_t fXcptBitmap = pVmcs->u32XcptBitmap;
    3732                 if (uVector == X86_XCPT_PF)
    3733                 {
    3734                     uint32_t const fXcptPFMask  = pVmcs->u32XcptPFMask;
    3735                     uint32_t const fXcptPFMatch = pVmcs->u32XcptPFMatch;
    3736                     if ((uErrCode & fXcptPFMask) != fXcptPFMatch)
    3737                         fXcptBitmap ^= RT_BIT(X86_XCPT_PF);
    3738                 }
    3739 
    3740                 /* Consult the exception bitmap. */
    3741                 if (fXcptBitmap & RT_BIT(uVector))
    3742                     fIntercept = true;
    3743             } while (0);
    3744         }
    3745         /* else: Software interrupts cannot be intercepted and therefore do not cause a VM-exit. */
    3746     }
    3747     else if (fFlags & IEM_XCPT_FLAGS_T_EXT_INT)
    3748     {
    3749         /* External interrupts have a dedicated VM-execution control for causing VM-exits. */
    3750         fIntercept  = RT_BOOL(pVmcs->u32PinCtls & VMX_PIN_CTLS_EXT_INT_EXIT);
    3751 
    3752         /** @todo NSTVMX: What about "acknowledge interrupt on exit" control? */
    3753     }
    3754 
    3755     /*
    3756      * Now that we've determined whether the external interrupt or hardware exception
     3807                uint32_t const fXcptPFMask  = pVmcs->u32XcptPFMask;
     3808                uint32_t const fXcptPFMatch = pVmcs->u32XcptPFMatch;
     3809                if ((uErrCode & fXcptPFMask) != fXcptPFMatch)
     3810                    fXcptBitmap ^= RT_BIT(X86_XCPT_PF);
     3811            }
     3812
     3813            /* Consult the exception bitmap for all hardware exceptions (except NMI). */
     3814            if (fXcptBitmap & RT_BIT(uVector))
     3815                fIntercept = true;
     3816        }
     3817    }
     3818    /* else: Software interrupts cannot be intercepted and therefore do not cause a VM-exit. */
     3819
     3820    /*
     3821     * Now that we've determined whether the software interrupt or hardware exception
    37573822     * causes a VM-exit, we need to construct the relevant VM-exit information and
    37583823     * cause the VM-exit.
     
    37603825    if (fIntercept)
    37613826    {
     3827        Assert(!(fFlags & IEM_XCPT_FLAGS_T_EXT_INT));
     3828
     3829        /* Construct the rest of the event related information fields and cause the VM-exit. */
    37623830        uint64_t uExitQual = 0;
    37633831        if (fIsHwXcpt)
     
    37723840        }
    37733841
    3774         /* Construct the rest of the event related information fields and cause the VM-exit. */
    3775         uint32_t const uExitReason    = (fFlags & IEM_XCPT_FLAGS_T_EXT_INT) ? VMX_EXIT_EXT_INT : VMX_EXIT_XCPT_OR_NMI;
    37763842        uint8_t  const fNmiUnblocking = 0;  /** @todo NSTVMX: Implement NMI-unblocking due to IRET. */
    37773843        uint8_t  const fErrCodeValid  = (fFlags & IEM_XCPT_FLAGS_ERR);
     
    37973863            iemVmxVmcsSetExitInstrLen(pVCpu, 0);
    37983864
    3799         return iemVmxVmexit(pVCpu, uExitReason);
     3865        return iemVmxVmexit(pVCpu, VMX_EXIT_XCPT_OR_NMI);
    38003866    }
    38013867
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