VirtualBox

Changeset 79756 in vbox for trunk/src/VBox


Ignore:
Timestamp:
Jul 13, 2019 4:06:20 PM (6 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
132121
Message:

VMM/IEM: Nested VMX: bugref:9180 Double fault and triple fault VM-exit fixes.

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

Legend:

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

    r79598 r79756  
    445445
    446446/**
    447  * Invokes the VMX VM-exit handle for triple faults.
    448  */
    449 # define IEM_VMX_VMEXIT_TRIPLE_FAULT_RET(a_pVCpu) \
    450     do { return iemVmxVmexitTripleFault(a_pVCpu); } while (0)
     447 * Invokes the VMX VM-exit handler.
     448 */
     449# define IEM_VMX_VMEXIT_TRIPLE_FAULT_RET(a_pVCpu, a_uExitReason, a_uExitQual) \
     450    do { return iemVmxVmexit((a_pVCpu), (a_uExitReason), (a_uExitQual)); } while (0)
    451451
    452452#else
     
    460460# define IEM_VMX_VMEXIT_TASK_SWITCH_RET(a_pVCpu, a_enmTaskSwitch, a_SelNewTss, a_cbInstr)    do { return VERR_VMX_IPE_1; } while (0)
    461461# define IEM_VMX_VMEXIT_MWAIT_RET(a_pVCpu, a_fMonitorArmed, a_cbInstr)          do { return VERR_VMX_IPE_1; } while (0)
    462 # define IEM_VMX_VMEXIT_TRIPLE_FAULT_RET(a_pVCpu)                               do { return VERR_VMX_IPE_1; } while (0)
     462# define IEM_VMX_VMEXIT_TRIPLE_FAULT_RET(a_pVCpu, a_uExitReason, a_uExitQual)   do { return VERR_VMX_IPE_1; } while (0)
    463463
    464464#endif
     
    978978
    979979#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
     980IEM_STATIC VBOXSTRICTRC     iemVmxVmexit(PVMCPU pVCpu, uint32_t uExitReason, uint64_t u64ExitQual);
    980981IEM_STATIC VBOXSTRICTRC     iemVmxVmexitTaskSwitch(PVMCPU pVCpu, IEMTASKSWITCH enmTaskSwitch, RTSEL SelNewTss, uint8_t cbInstr);
    981982IEM_STATIC VBOXSTRICTRC     iemVmxVmexitEvent(PVMCPU pVCpu, uint8_t uVector, uint32_t fFlags, uint32_t uErrCode, uint64_t uCr2, uint8_t cbInstr);
    982983IEM_STATIC VBOXSTRICTRC     iemVmxVmexitEventDoubleFault(PVMCPU pVCpu);
    983 IEM_STATIC VBOXSTRICTRC     iemVmxVmexitTripleFault(PVMCPU pVCpu);
    984984IEM_STATIC VBOXSTRICTRC     iemVmxVirtApicAccessMem(PVMCPU pVCpu, uint16_t offAccess, size_t cbAccess, void *pvData, uint32_t fAccess);
    985 IEM_STATIC VBOXSTRICTRC     iemVmxVmexitApicAccess(PVMCPU pVCpu, uint16_t offAccess, uint32_t fAccess);
    986985IEM_STATIC VBOXSTRICTRC     iemVmxVirtApicAccessMsrRead(PVMCPU pVCpu, uint32_t idMsr, uint64_t *pu64Value);
    987986IEM_STATIC VBOXSTRICTRC     iemVmxVirtApicAccessMsrWrite(PVMCPU pVCpu, uint32_t idMsr, uint64_t u64Value);
     
    34823481{
    34833482    if (IEM_VMX_IS_NON_ROOT_MODE(pVCpu))
    3484         IEM_VMX_VMEXIT_TRIPLE_FAULT_RET(pVCpu);
     3483        IEM_VMX_VMEXIT_TRIPLE_FAULT_RET(pVCpu, VMX_EXIT_TRIPLE_FAULT, 0 /* u64ExitQual */);
    34853484
    34863485    if (IEM_SVM_IS_CTRL_INTERCEPT_SET(pVCpu, SVM_CTRL_INTERCEPT_SHUTDOWN))
     
    1598615985VMM_INT_DECL(VBOXSTRICTRC) IEMExecVmxVmexitTripleFault(PVMCPU pVCpu)
    1598715986{
    15988     VBOXSTRICTRC rcStrict = iemVmxVmexitTripleFault(pVCpu);
     15987    VBOXSTRICTRC rcStrict = iemVmxVmexit(pVCpu, VMX_EXIT_TRIPLE_FAULT, 0 /* u64ExitQual */);
    1598915988    Assert(!pVCpu->iem.s.cActiveMappings);
    1599015989    return iemExecStatusCodeFiddling(pVCpu, rcStrict);
  • trunk/src/VBox/VMM/VMMAll/IEMAllCImplVmxInstr.cpp.h

    r79730 r79756  
    24952495        if (fInEventDelivery)
    24962496        {
    2497             uint8_t  const uIdtVectoringType = iemVmxGetEventType(uVector, fFlags);
    2498             uint8_t  const fErrCodeValid     = RT_BOOL(fFlags & IEM_XCPT_FLAGS_ERR);
    2499             uint32_t const uIdtVectoringInfo = RT_BF_MAKE(VMX_BF_IDT_VECTORING_INFO_VECTOR,         uVector)
    2500                                              | RT_BF_MAKE(VMX_BF_IDT_VECTORING_INFO_TYPE,           uIdtVectoringType)
    2501                                              | RT_BF_MAKE(VMX_BF_IDT_VECTORING_INFO_ERR_CODE_VALID, fErrCodeValid)
    2502                                              | RT_BF_MAKE(VMX_BF_IDT_VECTORING_INFO_VALID,          1);
    2503             iemVmxVmcsSetIdtVectoringInfo(pVCpu, uIdtVectoringInfo);
    2504             iemVmxVmcsSetIdtVectoringErrCode(pVCpu, uErrCode);
     2497            /*
     2498             * A VM-exit is not considered to occur during event delivery when the VM-exit is
     2499             * caused by a triple-fault or the original event results in a double-fault that
     2500             * causes the VM exit directly (exception bitmap). Therefore, we must not set the
     2501             * original event information into the IDT-vectoring information fields.
     2502             *
     2503             * See Intel spec. 27.2.4 Information for VM Exits During Event Delivery
     2504             */
     2505            if (   uExitReason != VMX_EXIT_TRIPLE_FAULT
     2506                && (   uExitReason != VMX_EXIT_XCPT_OR_NMI
     2507                    || !VMX_EXIT_INT_INFO_IS_XCPT_DF(pVmcs->u32RoExitIntInfo)))
     2508            {
     2509                uint8_t  const uIdtVectoringType = iemVmxGetEventType(uVector, fFlags);
     2510                uint8_t  const fErrCodeValid     = RT_BOOL(fFlags & IEM_XCPT_FLAGS_ERR);
     2511                uint32_t const uIdtVectoringInfo = RT_BF_MAKE(VMX_BF_IDT_VECTORING_INFO_VECTOR,         uVector)
     2512                                                 | RT_BF_MAKE(VMX_BF_IDT_VECTORING_INFO_TYPE,           uIdtVectoringType)
     2513                                                 | RT_BF_MAKE(VMX_BF_IDT_VECTORING_INFO_ERR_CODE_VALID, fErrCodeValid)
     2514                                                 | RT_BF_MAKE(VMX_BF_IDT_VECTORING_INFO_VALID,          1);
     2515                iemVmxVmcsSetIdtVectoringInfo(pVCpu, uIdtVectoringInfo);
     2516                iemVmxVmcsSetIdtVectoringErrCode(pVCpu, uErrCode);
     2517            }
    25052518        }
    25062519    }
     
    35613574    if (fXcptBitmap & RT_BIT(X86_XCPT_DF))
    35623575    {
    3563         uint8_t  const fNmiUnblocking = pVCpu->cpum.GstCtx.hwvirt.vmx.fNmiUnblockingIret;
     3576        /*
     3577         * The NMI-unblocking due to IRET field need not be set for double faults.
     3578         * See Intel spec. 31.7.1.2 "Resuming Guest Software After Handling An Exception".
     3579         */
    35643580        uint32_t const uExitIntInfo   = RT_BF_MAKE(VMX_BF_EXIT_INT_INFO_VECTOR,           X86_XCPT_DF)
    35653581                                      | RT_BF_MAKE(VMX_BF_EXIT_INT_INFO_TYPE,             VMX_EXIT_INT_INFO_TYPE_HW_XCPT)
    35663582                                      | RT_BF_MAKE(VMX_BF_EXIT_INT_INFO_ERR_CODE_VALID,   1)
    3567                                       | RT_BF_MAKE(VMX_BF_EXIT_INT_INFO_NMI_UNBLOCK_IRET, fNmiUnblocking)
     3583                                      | RT_BF_MAKE(VMX_BF_EXIT_INT_INFO_NMI_UNBLOCK_IRET, 0)
    35683584                                      | RT_BF_MAKE(VMX_BF_EXIT_INT_INFO_VALID,            1);
    35693585        iemVmxVmcsSetExitIntInfo(pVCpu, uExitIntInfo);
    3570         iemVmxVmcsSetExitIntErrCode(pVCpu, 0);
    3571         iemVmxVmcsSetExitInstrLen(pVCpu, 0);
    3572 
    3573         /*
    3574          * A VM-exit is not considered to occur during event delivery when the original
    3575          * event results in a double-fault that causes a VM-exit directly (i.e. intercepted
    3576          * using the exception bitmap).
    3577          *
    3578          * Therefore, we must clear the original event from the IDT-vectoring fields which
    3579          * would've been recorded before causing the VM-exit.
    3580          *
    3581          * 27.2.3 "Information for VM Exits During Event Delivery"
    3582          */
    3583         iemVmxVmcsSetIdtVectoringInfo(pVCpu, 0);
    3584         iemVmxVmcsSetIdtVectoringErrCode(pVCpu, 0);
    35853586        return iemVmxVmexit(pVCpu, VMX_EXIT_XCPT_OR_NMI, 0 /* u64ExitQual */);
    35863587    }
     
    37383739
    37393740    return VINF_VMX_INTERCEPT_NOT_ACTIVE;
    3740 }
    3741 
    3742 
    3743 /**
    3744  * VMX VM-exit handler for VM-exits due to a triple fault.
    3745  *
    3746  * @returns VBox strict status code.
    3747  * @param   pVCpu   The cross context virtual CPU structure.
    3748  */
    3749 IEM_STATIC VBOXSTRICTRC iemVmxVmexitTripleFault(PVMCPU pVCpu)
    3750 {
    3751     /*
    3752      * A VM-exit is not considered to occur during event delivery when the original
    3753      * event results in a triple-fault.
    3754      *
    3755      * Therefore, we must clear the original event from the IDT-vectoring fields which
    3756      * would've been recorded before causing the VM-exit.
    3757      *
    3758      * 27.2.3 "Information for VM Exits During Event Delivery"
    3759      */
    3760     iemVmxVmcsSetIdtVectoringInfo(pVCpu, 0);
    3761     iemVmxVmcsSetIdtVectoringErrCode(pVCpu, 0);
    3762 
    3763     return iemVmxVmexit(pVCpu, VMX_EXIT_TRIPLE_FAULT, 0 /* u64ExitQual */);
    37643741}
    37653742
Note: See TracChangeset for help on using the changeset viewer.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette