VirtualBox

Changeset 74683 in vbox for trunk


Ignore:
Timestamp:
Oct 8, 2018 3:13:52 PM (6 years ago)
Author:
vboxsync
Message:

VMM/IEM: Nested VMX: bugref:9180 VM-exit bits; Add task switch intercept.

Location:
trunk
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/include/VBox/vmm/hm_vmx.h

    r74667 r74683  
    26872687/** Task switch caused by an interrupt gate. */
    26882688#define VMX_EXIT_QUAL_TASK_SWITCH_TYPE_IDT                      3
     2689
     2690/** Bit fields for Exit qualification for task switches. */
     2691#define VMX_BF_EXIT_QUAL_TASK_SWITCH_NEW_TSS_SHIFT              0
     2692#define VMX_BF_EXIT_QUAL_TASK_SWITCH_NEW_TSS_MASK               UINT64_C(0x000000000000ffff)
     2693#define VMX_BF_EXIT_QUAL_TASK_SWITCH_RSVD_16_29_SHIFT           16
     2694#define VMX_BF_EXIT_QUAL_TASK_SWITCH_RSVD_16_29_MASK            UINT64_C(0x000000003fff0000)
     2695#define VMX_BF_EXIT_QUAL_TASK_SWITCH_SOURCE_SHIFT               30
     2696#define VMX_BF_EXIT_QUAL_TASK_SWITCH_SOURCE_MASK                UINT64_C(0x00000000c0000000)
     2697#define VMX_BF_EXIT_QUAL_TASK_SWITCH_RSVD_32_63_SHIFT           32
     2698#define VMX_BF_EXIT_QUAL_TASK_SWITCH_RSVD_32_63_MASK            UINT64_C(0xffffffff00000000)
     2699RT_BF_ASSERT_COMPILE_CHECKS(VMX_BF_EXIT_QUAL_TASK_SWITCH_, UINT64_C(0), UINT64_MAX,
     2700                            (NEW_TSS, RSVD_16_29, SOURCE, RSVD_32_63));
    26892701/** @} */
    26902702
  • trunk/src/VBox/VMM/VMMAll/IEMAll.cpp

    r74661 r74683  
    397397
    398398/**
     399 * Check if the nested-guest has the given Pin-based VM-execution control set.
     400 */
     401# define IEM_VMX_IS_PINCTLS_SET(a_pVCpu, a_PinCtl) \
     402    (CPUMIsGuestVmxPinCtlsSet((a_pVCpu), IEM_GET_CTX(a_pVCpu), (a_PinCtl)))
     403
     404/**
     405 * Check if the nested-guest has the given Processor-based VM-execution control set.
     406 */
     407#define IEM_VMX_IS_PROCCTLS_SET(a_pVCpu, a_ProcCtl) \
     408    (CPUMIsGuestVmxProcCtlsSet((a_pVCpu), IEM_GET_CTX(a_pVCpu), (a_ProcCtl)))
     409
     410/**
     411 * Check if the nested-guest has the given Secondary Processor-based VM-execution
     412 * control set.
     413 */
     414#define IEM_VMX_IS_PROCCTLS2_SET(a_pVCpu, a_ProcCtl2) \
     415    (CPUMIsGuestVmxProcCtls2Set((a_pVCpu), IEM_GET_CTX(a_pVCpu), (a_ProcCtl2)))
     416
     417/**
    399418 * Invokes the VMX VM-exit handler for an instruction intercept.
    400419 */
     
    410429
    411430/**
    412  * Check if the nested-guest has the given Pin-based VM-execution control set.
    413  */
    414 # define IEM_VMX_IS_PINCTLS_SET(a_pVCpu, a_PinCtl) \
    415     (CPUMIsGuestVmxPinCtlsSet((a_pVCpu), IEM_GET_CTX(a_pVCpu), (a_PinCtl)))
    416 
    417 /**
    418  * Check if the nested-guest has the given Processor-based VM-execution control set.
    419  */
    420 #define IEM_VMX_IS_PROCCTLS_SET(a_pVCpu, a_ProcCtl) \
    421     (CPUMIsGuestVmxProcCtlsSet((a_pVCpu), IEM_GET_CTX(a_pVCpu), (a_ProcCtl)))
    422 
    423 /**
    424  * Check if the nested-guest has the given Secondary Processor-based VM-execution
    425  * control set.
    426  */
    427 #define IEM_VMX_IS_PROCCTLS2_SET(a_pVCpu, a_ProcCtl2) \
    428     (CPUMIsGuestVmxProcCtls2Set((a_pVCpu), IEM_GET_CTX(a_pVCpu), (a_ProcCtl2)))
     431 * Invokes the VMX VM-exit handler for a task switch.
     432 */
     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)
    429435
    430436#else
     
    434440# define IEM_VMX_IS_PROCCTLS_SET(a_pVCpu, a_cbInstr)                    (false)
    435441# define IEM_VMX_IS_PROCCTLS2_SET(a_pVCpu, a_cbInstr)                   (false)
    436 # define IEM_VMX_VMEXIT_INSTR_RET(a_pVCpu, a_uExitReason, a_cbInstr)    do { return VERR_VMX_IPE_1; } while (0)
     442# define IEM_VMX_VMEXIT_TASK_SWITCH_RET(a_pVCpu, a_enmTaskSwitch, a_SelNewTss)  do { return VERR_VMX_IPE_1; } while (0)
     443# define IEM_VMX_VMEXIT_INSTR_RET(a_pVCpu, a_uExitReason, a_cbInstr)            do { return VERR_VMX_IPE_1; } while (0)
    437444# define IEM_VMX_VMEXIT_INSTR_NEEDS_INFO_RET(a_pVCpu, a_uExitReason, a_uInstrId, a_cbInstr)     do { return VERR_VMX_IPE_1; } while (0)
    438445
     
    951958IEM_STATIC uint16_t         iemSRegFetchU16(PVMCPU pVCpu, uint8_t iSegReg);
    952959IEM_STATIC uint64_t         iemSRegBaseFetchU64(PVMCPU pVCpu, uint8_t iSegReg);
     960
     961#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
     962IEM_STATIC VBOXSTRICTRC     iemVmxVmexitTaskSwitch(PVMCPU pVCpu, IEMTASKSWITCH enmTaskSwitch, RTSEL SelNewTss);
     963#endif
    953964
    954965#ifdef VBOX_WITH_NESTED_HWVIRT_SVM
     
    39613972 * @returns VBox strict status code.
    39623973 * @param   pVCpu           The cross context virtual CPU structure of the calling thread.
    3963  * @param   enmTaskSwitch   What caused this task switch.
     3974 * @param   enmTaskSwitch   The cause of the task switch.
    39643975 * @param   uNextEip        The EIP effective after the task switch.
    39653976 * @param   fFlags          The flags, see IEM_XCPT_FLAGS_XXX.
     
    40124023             enmTaskSwitch, uNewTSSLimit, uNewTSSLimitMin));
    40134024        return iemRaiseTaskSwitchFaultWithErr(pVCpu, SelTSS & X86_SEL_MASK_OFF_RPL);
     4025    }
     4026
     4027    /*
     4028     * Task switches in VMX non-root mode always cause task switches.
     4029     * The new TSS must have been read and validated (DPL, limits etc.) before a
     4030     * task-switch VM-exit commences.
     4031     *
     4032     * See Intel spec. 25.4.2 ".Treatment of Task Switches"
     4033     */
     4034    if (IEM_VMX_IS_NON_ROOT_MODE(pVCpu))
     4035    {
     4036        Log(("iemTaskSwitch: Guest intercept (source=%u, sel=%#x) -> VM-exit.\n", enmTaskSwitch, SelTSS));
     4037        IEM_VMX_VMEXIT_TASK_SWITCH_RET(pVCpu, enmTaskSwitch, SelTSS);
    40144038    }
    40154039
     
    40374061        RT_NOREF2(uExitInfo1, uExitInfo2);
    40384062    }
    4039     /** @todo Nested-VMX task-switch intercept. */
    40404063
    40414064    /*
     
    41184141        Log(("iemTaskSwitch: Switching to the same TSS! enmTaskSwitch=%u GCPtr[Cur|New]TSS=%#RGv\n", enmTaskSwitch, GCPtrCurTSS));
    41194142        Log(("uCurCr3=%#x uCurEip=%#x uCurEflags=%#x uCurEax=%#x uCurEsp=%#x uCurEbp=%#x uCurCS=%#04x uCurSS=%#04x uCurLdt=%#x\n",
    4120              pVCpu->cpum.GstCtx.cr3, pVCpu->cpum.GstCtx.eip, pVCpu->cpum.GstCtx.eflags.u32, pVCpu->cpum.GstCtx.eax, pVCpu->cpum.GstCtx.esp, pVCpu->cpum.GstCtx.ebp, pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.ss.Sel, pVCpu->cpum.GstCtx.ldtr.Sel));
     4143             pVCpu->cpum.GstCtx.cr3, pVCpu->cpum.GstCtx.eip, pVCpu->cpum.GstCtx.eflags.u32, pVCpu->cpum.GstCtx.eax,
     4144             pVCpu->cpum.GstCtx.esp, pVCpu->cpum.GstCtx.ebp, pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.ss.Sel,
     4145             pVCpu->cpum.GstCtx.ldtr.Sel));
    41214146    }
    41224147    if (fIsNewTSS386)
     
    44204445    else
    44214446    {
    4422         Assert(!pVCpu->cpum.GstCtx.ldtr.Attr.n.u1Present);       /* Ensures that LDT.TI check passes in iemMemFetchSelDesc() below. */
     4447        Assert(!pVCpu->cpum.GstCtx.ldtr.Attr.n.u1Present);   /* Ensures that LDT.TI check passes in iemMemFetchSelDesc() below. */
    44234448
    44244449        IEMSELDESC DescNewLdt;
     
    47054730    }
    47064731
    4707     Log(("iemTaskSwitch: Success! New CS:EIP=%#04x:%#x SS=%#04x\n", pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.eip, pVCpu->cpum.GstCtx.ss.Sel));
     4732    Log(("iemTaskSwitch: Success! New CS:EIP=%#04x:%#x SS=%#04x\n", pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.eip,
     4733         pVCpu->cpum.GstCtx.ss.Sel));
    47084734    return fFlags & IEM_XCPT_FLAGS_T_CPU_XCPT ? VINF_IEM_RAISED_XCPT : VINF_SUCCESS;
    47094735}
     
    48644890
    48654891        /* Do the actual task switch. */
    4866         return iemTaskSwitch(pVCpu, IEMTASKSWITCH_INT_XCPT, (fFlags & IEM_XCPT_FLAGS_T_SOFT_INT) ? pVCpu->cpum.GstCtx.eip + cbInstr : pVCpu->cpum.GstCtx.eip, fFlags, uErr, uCr2, SelTSS, &DescTSS);
     4892        return iemTaskSwitch(pVCpu, IEMTASKSWITCH_INT_XCPT,
     4893                             (fFlags & IEM_XCPT_FLAGS_T_SOFT_INT) ? pVCpu->cpum.GstCtx.eip + cbInstr : pVCpu->cpum.GstCtx.eip,
     4894                             fFlags, uErr, uCr2, SelTSS, &DescTSS);
    48674895    }
    48684896
  • trunk/src/VBox/VMM/VMMAll/IEMAllCImplVmxInstr.cpp.h

    r74678 r74683  
    2828 *  VMX_EXIT_INT_WINDOW
    2929 *  VMX_EXIT_NMI_WINDOW
    30  *  VMX_EXIT_TASK_SWITCH
    3130 *  VMX_EXIT_GETSEC
    3231 *  VMX_EXIT_INVD
    3332 *  VMX_EXIT_RSM
    3433 *  VMX_EXIT_MOV_DRX
    35  *  VMX_EXIT_IO_INSTR
    3634 *  VMX_EXIT_MWAIT
    3735 *  VMX_EXIT_MTF
     
    27272725     *
    27282726     * The VM-exit instruction length is mandatory for all VM-exits that are caused by
    2729      * instruction execution.
     2727     * instruction execution. For VM-exits that are not due to instruction execution this
     2728     * field is undefined.
    27302729     *
    27312730     * In our implementation in IEM, all undefined fields are generally cleared. However,
     
    33733372
    33743373    return VINF_VMX_INTERCEPT_NOT_ACTIVE;
     3374}
     3375
     3376
     3377/**
     3378 * VMX VM-exit handler for VM-exits due to task switches.
     3379 *
     3380 * @returns VBox strict status code.
     3381 * @param   pVCpu           The cross context virtual CPU structure.
     3382 * @param   enmTaskSwitch   The cause of the task switch.
     3383 * @param   SelNewTss       The selector of the new TSS.
     3384 */
     3385IEM_STATIC VBOXSTRICTRC iemVmxVmexitTaskSwitch(PVMCPU pVCpu, IEMTASKSWITCH enmTaskSwitch, RTSEL SelNewTss)
     3386{
     3387    /*
     3388     * Task-switch VM-exits are unconditional and only provide the
     3389     * VM-exit qualification.
     3390     *
     3391     * See Intel spec. 25.2 "Other Causes Of VM Exits".
     3392     */
     3393    uint8_t uTaskSwitchSrc;
     3394    switch (enmTaskSwitch)
     3395    {
     3396        case IEMTASKSWITCH_CALL:     uTaskSwitchSrc = 0; break;
     3397        case IEMTASKSWITCH_IRET:     uTaskSwitchSrc = 1; break;
     3398        case IEMTASKSWITCH_JUMP:     uTaskSwitchSrc = 2; break;
     3399        case IEMTASKSWITCH_INT_XCPT: uTaskSwitchSrc = 3; break;
     3400        IEM_NOT_REACHED_DEFAULT_CASE_RET();
     3401    }
     3402
     3403    uint64_t const uExitQual = RT_BF_MAKE(VMX_BF_EXIT_QUAL_TASK_SWITCH_NEW_TSS, SelNewTss)
     3404                             | RT_BF_MAKE(VMX_BF_EXIT_QUAL_TASK_SWITCH_SOURCE,  uTaskSwitchSrc);
     3405    iemVmxVmcsSetExitQual(pVCpu, uExitQual);
     3406    return iemVmxVmexit(pVCpu, VMX_EXIT_TASK_SWITCH);
    33753407}
    33763408
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