VirtualBox

Changeset 74751 in vbox for trunk


Ignore:
Timestamp:
Oct 11, 2018 5:01:25 AM (6 years ago)
Author:
vboxsync
Message:

VMM/IEM: Nested VMX: bugref:9180 VM-exit bits; Added triple fault intercept. Fixed task switch intercept to include the VM-exit instruciton length.

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

Legend:

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

    r74736 r74751  
    431431 * Invokes the VMX VM-exit handler for a task switch.
    432432 */
    433 # define IEM_VMX_VMEXIT_TASK_SWITCH_RET(a_pVCpu, a_enmTaskSwitch, a_SelNewTss) \
    434     do { return iemVmxVmexitTaskSwitch((a_pVCpu), (a_enmTaskSwitch), (a_SelNewTss)); } while (0)
     433# define IEM_VMX_VMEXIT_TASK_SWITCH_RET(a_pVCpu, a_enmTaskSwitch, a_SelNewTss, a_cbInstr) \
     434    do { return iemVmxVmexitTaskSwitch((a_pVCpu), (a_enmTaskSwitch), (a_SelNewTss), (a_cbInstr)); } while (0)
    435435
    436436/**
     
    440440    do { return iemVmxVmexitInstrMwait((a_pVCpu), (a_fMonitorArmed), (a_cbInstr)); } while (0)
    441441
     442/**
     443 * Invokes the VMX VM-exit handle for triple faults.
     444 */
     445# define IEM_VMX_VMEXIT_TRIPLE_FAULT_RET(a_pVCpu) \
     446    do { return iemVmxVmexitTripleFault(a_pVCpu); } while (0)
     447
    442448#else
    443 # define IEM_VMX_IS_ROOT_MODE(a_pVCpu)                                  (false)
    444 # define IEM_VMX_IS_NON_ROOT_MODE(a_pVCpu)                              (false)
    445 # define IEM_VMX_IS_PINCTLS_SET(a_pVCpu, a_cbInstr)                     (false)
    446 # define IEM_VMX_IS_PROCCTLS_SET(a_pVCpu, a_cbInstr)                    (false)
    447 # define IEM_VMX_IS_PROCCTLS2_SET(a_pVCpu, a_cbInstr)                   (false)
     449# define IEM_VMX_IS_ROOT_MODE(a_pVCpu)                                          (false)
     450# define IEM_VMX_IS_NON_ROOT_MODE(a_pVCpu)                                      (false)
     451# define IEM_VMX_IS_PINCTLS_SET(a_pVCpu, a_cbInstr)                             (false)
     452# define IEM_VMX_IS_PROCCTLS_SET(a_pVCpu, a_cbInstr)                            (false)
     453# define IEM_VMX_IS_PROCCTLS2_SET(a_pVCpu, a_cbInstr)                           (false)
    448454# define IEM_VMX_VMEXIT_INSTR_RET(a_pVCpu, a_uExitReason, a_cbInstr)            do { return VERR_VMX_IPE_1; } while (0)
    449 # define IEM_VMX_VMEXIT_INSTR_NEEDS_INFO_RET(a_pVCpu, a_uExitReason, a_uInstrId, a_cbInstr)     do { return VERR_VMX_IPE_1; } while (0)
    450 # define IEM_VMX_VMEXIT_TASK_SWITCH_RET(a_pVCpu, a_enmTaskSwitch, a_SelNewTss)  do { return VERR_VMX_IPE_1; } while (0)
     455# define IEM_VMX_VMEXIT_INSTR_NEEDS_INFO_RET(a_pVCpu, a_uExitReason, a_uInstrId, a_cbInstr)  do { return VERR_VMX_IPE_1; } while (0)
     456# define IEM_VMX_VMEXIT_TASK_SWITCH_RET(a_pVCpu, a_enmTaskSwitch, a_SelNewTss, a_cbInstr)    do { return VERR_VMX_IPE_1; } while (0)
    451457# define IEM_VMX_VMEXIT_MWAIT_RET(a_pVCpu, a_fMonitorArmed, a_cbInstr)          do { return VERR_VMX_IPE_1; } while (0)
     458# define IEM_VMX_VMEXIT_TRIPLE_FAULT_RET(a_pVCpu)                               do { return VERR_VMX_IPE_1; } while (0)
    452459
    453460#endif
     
    967974
    968975#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
    969 IEM_STATIC VBOXSTRICTRC     iemVmxVmexitTaskSwitch(PVMCPU pVCpu, IEMTASKSWITCH enmTaskSwitch, RTSEL SelNewTss);
    970 IEM_STATIC VBOXSTRICTRC     iemVmxVmexitEvent(PVMCPU pVCpu, uint8_t uVector, uint32_t fFlags, uint32_t uErrCode, uint64_t uCr2);
     976IEM_STATIC VBOXSTRICTRC     iemVmxVmexitTaskSwitch(PVMCPU pVCpu, IEMTASKSWITCH enmTaskSwitch, RTSEL SelNewTss, uint8_t cbInstr);
     977IEM_STATIC VBOXSTRICTRC     iemVmxVmexitEvent(PVMCPU pVCpu, uint8_t uVector, uint32_t fFlags, uint32_t uErrCode, uint64_t uCr2,
     978                                              uint8_t cbInstr);
     979IEM_STATIC VBOXSTRICTRC     iemVmxVmexitTripleFault(PVMCPU pVCpu);
    971980#endif
    972981
    973982#ifdef VBOX_WITH_NESTED_HWVIRT_SVM
    974983IEM_STATIC VBOXSTRICTRC     iemSvmVmexit(PVMCPU pVCpu, uint64_t uExitCode, uint64_t uExitInfo1, uint64_t uExitInfo2);
    975 IEM_STATIC VBOXSTRICTRC     iemHandleSvmEventIntercept(PVMCPU pVCpu, uint8_t u8Vector, uint32_t fFlags, uint32_t uErr, uint64_t uCr2);
     984IEM_STATIC VBOXSTRICTRC     iemHandleSvmEventIntercept(PVMCPU pVCpu, uint8_t u8Vector, uint32_t fFlags, uint32_t uErr,
     985                                                       uint64_t uCr2);
    976986#endif
    977987
     
    34643474IEM_STATIC VBOXSTRICTRC iemInitiateCpuShutdown(PVMCPU pVCpu)
    34653475{
     3476    if (IEM_VMX_IS_NON_ROOT_MODE(pVCpu))
     3477        IEM_VMX_VMEXIT_TRIPLE_FAULT_RET(pVCpu);
     3478
    34663479    if (IEM_SVM_IS_CTRL_INTERCEPT_SET(pVCpu, SVM_CTRL_INTERCEPT_SHUTDOWN))
    34673480    {
     
    40434056    {
    40444057        Log(("iemTaskSwitch: Guest intercept (source=%u, sel=%#x) -> VM-exit.\n", enmTaskSwitch, SelTSS));
    4045         IEM_VMX_VMEXIT_TASK_SWITCH_RET(pVCpu, enmTaskSwitch, SelTSS);
     4058        IEM_VMX_VMEXIT_TASK_SWITCH_RET(pVCpu, enmTaskSwitch, SelTSS, uNextEip - pVCpu->cpum.GstCtx.eip);
    40464059    }
    40474060
     
    55145527    if (IEM_VMX_IS_NON_ROOT_MODE(pVCpu))
    55155528    {
    5516         VBOXSTRICTRC rcStrict0 = iemVmxVmexitEvent(pVCpu, u8Vector, fFlags, uErr, uCr2);
     5529        VBOXSTRICTRC rcStrict0 = iemVmxVmexitEvent(pVCpu, u8Vector, fFlags, uErr, uCr2, cbInstr);
    55175530        if (rcStrict0 != VINF_VMX_INTERCEPT_NOT_ACTIVE)
    55185531            return rcStrict0;
     
    55795592            u8Vector = X86_XCPT_DF;
    55805593            uErr     = 0;
     5594            /** @todo NSTVMX: Do we need to do something here for VMX? */
    55815595            /* SVM nested-guest #DF intercepts need to be checked now. See AMD spec. 15.12 "Exception Intercepts". */
    55825596            if (IEM_SVM_IS_XCPT_INTERCEPT_SET(pVCpu, X86_XCPT_DF))
  • trunk/src/VBox/VMM/VMMAll/IEMAllCImplVmxInstr.cpp.h

    r74737 r74751  
    1919#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
    2020/** @todo NSTVMX: The following VM-exit intercepts are pending:
    21  *  VMX_EXIT_XCPT_OR_NMI
    22  *  VMX_EXIT_EXT_INT
    23  *  VMX_EXIT_TRIPLE_FAULT
     21 *  VMX_EXIT_EXT_INT ("acknowledge interrupt on exit" behavior pending)
    2422 *  VMX_EXIT_INIT_SIGNAL
    2523 *  VMX_EXIT_SIPI
     
    35473545 * @param   enmTaskSwitch   The cause of the task switch.
    35483546 * @param   SelNewTss       The selector of the new TSS.
    3549  */
    3550 IEM_STATIC VBOXSTRICTRC iemVmxVmexitTaskSwitch(PVMCPU pVCpu, IEMTASKSWITCH enmTaskSwitch, RTSEL SelNewTss)
    3551 {
    3552     /*
    3553      * Task-switch VM-exits are unconditional and only provide the
    3554      * VM-exit qualification.
     3547 * @param   cbInstr         The instruction length in bytes.
     3548 */
     3549IEM_STATIC VBOXSTRICTRC iemVmxVmexitTaskSwitch(PVMCPU pVCpu, IEMTASKSWITCH enmTaskSwitch, RTSEL SelNewTss, uint8_t cbInstr)
     3550{
     3551    /*
     3552     * Task-switch VM-exits are unconditional and provide the VM-exit qualification.
     3553     *
     3554     * If the the cause of the task switch is due to execution of CALL, IRET or the JMP
     3555     * instruction or delivery of the exception generated by one of these instructions
     3556     * lead to a task switch through a task gate in the IDT, we need to provide the
     3557     * VM-exit instruction length. Any other means of invoking a task switch VM-exit
     3558     * leaves the VM-exit instruction length field undefined.
    35553559     *
    35563560     * See Intel spec. 25.2 "Other Causes Of VM Exits".
    3557      */
    3558     uint32_t uTaskSwitchSrc;
     3561     * See Intel spec. 27.2.4 "Information for VM Exits Due to Instruction Execution".
     3562     */
     3563    Assert(cbInstr <= 15);
     3564
     3565    uint8_t uType;
    35593566    switch (enmTaskSwitch)
    35603567    {
    3561         case IEMTASKSWITCH_CALL:     uTaskSwitchSrc = 0; break;
    3562         case IEMTASKSWITCH_IRET:     uTaskSwitchSrc = 1; break;
    3563         case IEMTASKSWITCH_JUMP:     uTaskSwitchSrc = 2; break;
    3564         case IEMTASKSWITCH_INT_XCPT: uTaskSwitchSrc = 3; break;
     3568        case IEMTASKSWITCH_CALL:        uType = VMX_EXIT_QUAL_TASK_SWITCH_TYPE_CALL; break;
     3569        case IEMTASKSWITCH_IRET:        uType = VMX_EXIT_QUAL_TASK_SWITCH_TYPE_IRET; break;
     3570        case IEMTASKSWITCH_JUMP:        uType = VMX_EXIT_QUAL_TASK_SWITCH_TYPE_JMP; break;
     3571        case IEMTASKSWITCH_INT_XCPT:    uType = VMX_EXIT_QUAL_TASK_SWITCH_TYPE_IDT; break;
    35653572        IEM_NOT_REACHED_DEFAULT_CASE_RET();
    35663573    }
    35673574
    35683575    uint64_t const uExitQual = RT_BF_MAKE(VMX_BF_EXIT_QUAL_TASK_SWITCH_NEW_TSS, SelNewTss)
    3569                              | RT_BF_MAKE(VMX_BF_EXIT_QUAL_TASK_SWITCH_SOURCE,  uTaskSwitchSrc);
     3576                             | RT_BF_MAKE(VMX_BF_EXIT_QUAL_TASK_SWITCH_SOURCE,  uType);
    35703577    iemVmxVmcsSetExitQual(pVCpu, uExitQual);
     3578    iemVmxVmcsSetExitInstrLen(pVCpu, cbInstr);
    35713579    return iemVmxVmexit(pVCpu, VMX_EXIT_TASK_SWITCH);
    35723580}
     
    35823590 * @param   uErrCode    The error code associated with the event.
    35833591 * @param   uCr2        The CR2 value in case of a \#PF exception.
    3584  */
    3585 IEM_STATIC VBOXSTRICTRC iemVmxVmexitEvent(PVMCPU pVCpu, uint8_t uVector, uint32_t fFlags, uint32_t uErrCode, uint64_t uCr2)
     3592 * @param   cbInstr     The instruction length in bytes.
     3593 */
     3594IEM_STATIC VBOXSTRICTRC iemVmxVmexitEvent(PVMCPU pVCpu, uint8_t uVector, uint32_t fFlags, uint32_t uErrCode, uint64_t uCr2,
     3595                                          uint8_t cbInstr)
    35863596{
    35873597    PCVMXVVMCS pVmcs = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
     
    36893699        iemVmxVmcsSetExitIntErrCode(pVCpu, uErrCode);
    36903700        iemVmxVmcsSetExitQual(pVCpu, uExitQual);
     3701
     3702        /*
     3703         * For VM exits due to software exceptions (those generated by INT3 or INTO) or privileged
     3704         * software exceptions (those generated by INT1/ICEBP) we need to supply the VM-exit instruction
     3705         * length.
     3706         */
     3707        if (   (fFlags & IEM_XCPT_FLAGS_T_SOFT_INT)
     3708            && (fFlags & (IEM_XCPT_FLAGS_BP_INSTR | IEM_XCPT_FLAGS_OF_INSTR | IEM_XCPT_FLAGS_ICEBP_INSTR)))
     3709            iemVmxVmcsSetExitInstrLen(pVCpu, cbInstr);
     3710        else
     3711            iemVmxVmcsSetExitInstrLen(pVCpu, 0);
     3712
    36913713        return iemVmxVmexit(pVCpu, uExitReason);
    36923714    }
     
    37123734    ExitInfo.u64Qual = fMonitorHwArmed;
    37133735    return iemVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
     3736}
     3737
     3738
     3739/**
     3740 * VMX VM-exit handler for VM-exits due to a triple fault.
     3741 *
     3742 * @returns VBox strict status code.
     3743 * @param   pVCpu               The cross context virtual CPU structure.
     3744 */
     3745IEM_STATIC VBOXSTRICTRC iemVmxVmexitTripleFault(PVMCPU pVCpu)
     3746{
     3747    PCVMXVVMCS pVmcs = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
     3748    Assert(pVmcs);
     3749    iemVmxVmcsSetExitQual(pVCpu, 0);
     3750    return iemVmxVmexit(pVCpu, VMX_EXIT_TRIPLE_FAULT);
    37143751}
    37153752
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