VirtualBox

Changeset 74661 in vbox for trunk/src


Ignore:
Timestamp:
Oct 8, 2018 9:46:26 AM (6 years ago)
Author:
vboxsync
Message:

VMM/IEM: Nested VMX: bugref:9180 VM-exit bits; Added IN/OUT intercepts.

Location:
trunk/src/VBox/VMM
Files:
5 edited

Legend:

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

    r74603 r74661  
    1496814968 * @param   cbInstr     The instruction length in bytes.
    1496914969 * @param   u16Port     The port to read.
     14970 * @param   fImm        Whether the port is specified using an immediate operand or
     14971 *                      using the implicit DX register.
    1497014972 * @param   cbReg       The register size.
    1497114973 *
    1497214974 * @remarks In ring-0 not all of the state needs to be synced in.
    1497314975 */
    14974 VMM_INT_DECL(VBOXSTRICTRC) IEMExecDecodedOut(PVMCPU pVCpu, uint8_t cbInstr, uint16_t u16Port, uint8_t cbReg)
     14976VMM_INT_DECL(VBOXSTRICTRC) IEMExecDecodedOut(PVMCPU pVCpu, uint8_t cbInstr, uint16_t u16Port, bool fImm, uint8_t cbReg)
    1497514977{
    1497614978    IEMEXEC_ASSERT_INSTR_LEN_RETURN(cbInstr, 1);
     
    1497814980
    1497914981    iemInitExec(pVCpu, false /*fBypassHandlers*/);
    14980     VBOXSTRICTRC rcStrict = IEM_CIMPL_CALL_2(iemCImpl_out, u16Port, cbReg);
     14982    VBOXSTRICTRC rcStrict = IEM_CIMPL_CALL_3(iemCImpl_out, u16Port, fImm, cbReg);
    1498114983    Assert(!pVCpu->iem.s.cActiveMappings);
    1498214984    return iemUninitExecAndFiddleStatusAndMaybeReenter(pVCpu, rcStrict);
     
    1499114993 * @param   cbInstr     The instruction length in bytes.
    1499214994 * @param   u16Port     The port to read.
     14995 * @param   fImm        Whether the port is specified using an immediate operand or
     14996 *                      using the implicit DX.
    1499314997 * @param   cbReg       The register size.
    1499414998 */
    14995 VMM_INT_DECL(VBOXSTRICTRC) IEMExecDecodedIn(PVMCPU pVCpu, uint8_t cbInstr, uint16_t u16Port, uint8_t cbReg)
     14999VMM_INT_DECL(VBOXSTRICTRC) IEMExecDecodedIn(PVMCPU pVCpu, uint8_t cbInstr, uint16_t u16Port, bool fImm, uint8_t cbReg)
    1499615000{
    1499715001    IEMEXEC_ASSERT_INSTR_LEN_RETURN(cbInstr, 1);
     
    1499915003
    1500015004    iemInitExec(pVCpu, false /*fBypassHandlers*/);
    15001     VBOXSTRICTRC rcStrict = IEM_CIMPL_CALL_2(iemCImpl_in, u16Port, cbReg);
     15005    VBOXSTRICTRC rcStrict = IEM_CIMPL_CALL_3(iemCImpl_in, u16Port, fImm, cbReg);
    1500215006    Assert(!pVCpu->iem.s.cActiveMappings);
    1500315007    return iemUninitExecAndFiddleStatusAndMaybeReenter(pVCpu, rcStrict);
  • trunk/src/VBox/VMM/VMMAll/IEMAllCImpl.cpp.h

    r74659 r74661  
    66776677 *
    66786678 * @param   u16Port     The source port.
     6679 * @param   fImm        Whether the port was specified through an immediate operand
     6680 *                      or the implicit DX register.
    66796681 * @param   cbReg       The register size.
    66806682 */
    6681 IEM_CIMPL_DEF_2(iemCImpl_in, uint16_t, u16Port, uint8_t, cbReg)
     6683IEM_CIMPL_DEF_3(iemCImpl_in, uint16_t, u16Port, bool, fImm, uint8_t, cbReg)
    66826684{
    66836685    /*
     
    66876689    if (rcStrict != VINF_SUCCESS)
    66886690        return rcStrict;
     6691
     6692    /*
     6693     * Check VMX nested-guest IO intercept.
     6694     */
     6695#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
     6696    if (IEM_VMX_IS_NON_ROOT_MODE(pVCpu))
     6697    {
     6698        rcStrict = iemVmxVmexitInstrIo(pVCpu, VMXINSTRID_IO_IN, u16Port, fImm, cbReg, cbInstr);
     6699        if (rcStrict != VINF_VMX_INTERCEPT_NOT_ACTIVE)
     6700            return rcStrict;
     6701    }
     6702#else
     6703    RT_NOREF(fImm);
     6704#endif
    66896705
    66906706    /*
     
    67626778IEM_CIMPL_DEF_1(iemCImpl_in_eAX_DX, uint8_t, cbReg)
    67636779{
    6764     return IEM_CIMPL_CALL_2(iemCImpl_in, pVCpu->cpum.GstCtx.dx, cbReg);
     6780    return IEM_CIMPL_CALL_3(iemCImpl_in, pVCpu->cpum.GstCtx.dx, false /* fImm */, cbReg);
    67656781}
    67666782
     
    67706786 *
    67716787 * @param   u16Port     The destination port.
     6788 * @param   fImm        Whether the port was specified through an immediate operand
     6789 *                      or the implicit DX register.
    67726790 * @param   cbReg       The register size.
    67736791 */
    6774 IEM_CIMPL_DEF_2(iemCImpl_out, uint16_t, u16Port, uint8_t, cbReg)
     6792IEM_CIMPL_DEF_3(iemCImpl_out, uint16_t, u16Port, bool, fImm, uint8_t, cbReg)
    67756793{
    67766794    /*
     
    67826800
    67836801    /*
    6784      * Check SVM nested-guest IO intercept.
     6802     * Check VMX nested-guest I/O intercept.
     6803     */
     6804#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
     6805    if (IEM_VMX_IS_NON_ROOT_MODE(pVCpu))
     6806    {
     6807        rcStrict = iemVmxVmexitInstrIo(pVCpu, VMXINSTRID_IO_OUT, u16Port, fImm, cbReg, cbInstr);
     6808        if (rcStrict != VINF_VMX_INTERCEPT_NOT_ACTIVE)
     6809            return rcStrict;
     6810    }
     6811#else
     6812    RT_NOREF(fImm);
     6813#endif
     6814
     6815    /*
     6816     * Check SVM nested-guest I/O intercept.
    67856817     */
    67866818#ifdef VBOX_WITH_NESTED_HWVIRT_SVM
     
    68546886IEM_CIMPL_DEF_1(iemCImpl_out_DX_eAX, uint8_t, cbReg)
    68556887{
    6856     return IEM_CIMPL_CALL_2(iemCImpl_out, pVCpu->cpum.GstCtx.dx, cbReg);
     6888    return IEM_CIMPL_CALL_3(iemCImpl_out, pVCpu->cpum.GstCtx.dx, false /* fImm */, cbReg);
    68576889}
    68586890
  • trunk/src/VBox/VMM/VMMAll/IEMAllCImplVmxInstr.cpp.h

    r74660 r74661  
    28662866 * @returns @c true if the instruction is intercepted, @c false otherwise.
    28672867 * @param   pVCpu           The cross context virtual CPU structure.
    2868  * @param   uPort           The I/O port being accessed by the instruction.
    2869  */
    2870 IEM_STATIC bool iemVmxIsIoInterceptSet(PVMCPU pVCpu, uint16_t uPort)
     2868 * @param   u16Port         The I/O port being accessed by the instruction.
     2869 */
     2870IEM_STATIC bool iemVmxIsIoInterceptSet(PVMCPU pVCpu, uint16_t u16Port)
    28712871{
    28722872    PCVMXVVMCS pVmcs = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
     
    28742874
    28752875    /*
    2876      * Check whether the IO instruction must cause a VM-exit or not.
     2876     * Check whether the I/O instruction must cause a VM-exit or not.
    28772877     * See Intel spec. 25.1.3 "Instructions That Cause VM Exits Conditionally".
    28782878     */
     
    28862886        Assert(pbIoBitmapA);
    28872887        Assert(pbIoBitmapB);
    2888         return HMVmxGetIoBitmapPermission(pbIoBitmapA, pbIoBitmapB, uPort);
     2888        return HMVmxGetIoBitmapPermission(pbIoBitmapA, pbIoBitmapB, u16Port);
    28892889    }
    28902890
     
    32853285                         | RT_BF_MAKE(VMX_BF_EXIT_QUAL_CRX_ACCESS,   VMX_EXIT_QUAL_CRX_ACCESS_WRITE)
    32863286                         | RT_BF_MAKE(VMX_BF_EXIT_QUAL_CRX_GENREG,   iGReg);
     3287        return iemVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
     3288    }
     3289
     3290    return VINF_VMX_INTERCEPT_NOT_ACTIVE;
     3291}
     3292
     3293
     3294/**
     3295 * VMX VM-exit handler for VM-exits due to I/O instructions (IN and OUT).
     3296 *
     3297 * @returns VBox strict status code.
     3298 * @param   pVCpu       The cross context virtual CPU structure.
     3299 * @param   uInstrId    The VM-exit instruction identity (VMXINSTRID_IO_IN or
     3300 *                      VMXINSTRID_IO_OUT).
     3301 * @param   u16Port     The I/O port being accessed.
     3302 * @param   fImm        Whether the I/O port was encoded using an immediate operand
     3303 *                      or the implicit DX register.
     3304 * @param   cbAccess    The size of the I/O access in bytes (1, 2 or 4 bytes).
     3305 * @param   cbInstr     The instruction length in bytes.
     3306 */
     3307IEM_STATIC VBOXSTRICTRC iemVmxVmexitInstrIo(PVMCPU pVCpu, VMXINSTRID uInstrId, uint16_t u16Port, bool fImm, uint8_t cbAccess,
     3308                                            uint8_t cbInstr)
     3309{
     3310    Assert(uInstrId == VMXINSTRID_IO_IN || uInstrId == VMXINSTRID_IO_OUT);
     3311    Assert(cbAccess == 1 || cbAccess == 2 || cbAccess == 4);
     3312
     3313    PCVMXVVMCS pVmcs = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
     3314    Assert(pVmcs);
     3315
     3316    bool const fIntercept = iemVmxIsIoInterceptSet(pVCpu, u16Port);
     3317    if (fIntercept)
     3318    {
     3319        uint32_t const uDirection = uInstrId == VMXINSTRID_IO_IN ? VMX_EXIT_QUAL_IO_DIRECTION_IN
     3320                                                                 : VMX_EXIT_QUAL_IO_DIRECTION_OUT;
     3321        VMXVEXITINFO ExitInfo;
     3322        RT_ZERO(ExitInfo);
     3323        ExitInfo.uReason = VMX_EXIT_MOV_CRX;
     3324        ExitInfo.cbInstr = cbInstr;
     3325        ExitInfo.u64Qual = RT_BF_MAKE(VMX_BF_EXIT_QUAL_IO_WIDTH,     cbAccess - 1)
     3326                         | RT_BF_MAKE(VMX_BF_EXIT_QUAL_IO_DIRECTION, uDirection)
     3327                         | RT_BF_MAKE(VMX_BF_EXIT_QUAL_IO_ENCODING,  fImm)
     3328                         | RT_BF_MAKE(VMX_BF_EXIT_QUAL_IO_PORT,      u16Port);
    32873329        return iemVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
    32883330    }
     
    47274769        IEM_VMX_VMENTRY_FAILED_RET(pVCpu, pszInstr, pszFailure, kVmxVDiag_Vmentry_Cr3TargetCount);
    47284770
    4729     /* IO bitmaps physical addresses. */
     4771    /* I/O bitmaps physical addresses. */
    47304772    if (pVmcs->u32ProcCtls & VMX_PROC_CTLS_USE_IO_BITMAPS)
    47314773    {
  • trunk/src/VBox/VMM/VMMAll/IEMAllInstructionsOneByte.cpp.h

    r74490 r74661  
    1039910399    uint8_t u8Imm; IEM_OPCODE_GET_NEXT_U8(&u8Imm);
    1040010400    IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
    10401     return IEM_MC_DEFER_TO_CIMPL_2(iemCImpl_in, u8Imm, 1);
     10401    return IEM_MC_DEFER_TO_CIMPL_3(iemCImpl_in, u8Imm, true /* fImm */, 1);
    1040210402}
    1040310403
     
    1040910409    uint8_t u8Imm; IEM_OPCODE_GET_NEXT_U8(&u8Imm);
    1041010410    IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
    10411     return IEM_MC_DEFER_TO_CIMPL_2(iemCImpl_in, u8Imm, pVCpu->iem.s.enmEffOpSize == IEMMODE_16BIT ? 2 : 4);
     10411    return IEM_MC_DEFER_TO_CIMPL_3(iemCImpl_in, u8Imm, true /* fImm */, pVCpu->iem.s.enmEffOpSize == IEMMODE_16BIT ? 2 : 4);
    1041210412}
    1041310413
     
    1041910419    uint8_t u8Imm; IEM_OPCODE_GET_NEXT_U8(&u8Imm);
    1042010420    IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
    10421     return IEM_MC_DEFER_TO_CIMPL_2(iemCImpl_out, u8Imm, 1);
     10421    return IEM_MC_DEFER_TO_CIMPL_3(iemCImpl_out, u8Imm, true /* fImm */, 1);
    1042210422}
    1042310423
     
    1042910429    uint8_t u8Imm; IEM_OPCODE_GET_NEXT_U8(&u8Imm);
    1043010430    IEMOP_HLP_DONE_DECODING_NO_LOCK_PREFIX();
    10431     return IEM_MC_DEFER_TO_CIMPL_2(iemCImpl_out, u8Imm, pVCpu->iem.s.enmEffOpSize == IEMMODE_16BIT ? 2 : 4);
     10431    return IEM_MC_DEFER_TO_CIMPL_3(iemCImpl_out, u8Imm, true /* fImm */, pVCpu->iem.s.enmEffOpSize == IEMMODE_16BIT ? 2 : 4);
    1043210432}
    1043310433
  • trunk/src/VBox/VMM/VMMRC/IOMRC.cpp

    r72655 r74661  
    8484    STAM_COUNTER_INC(&pVM->iom.s.StatInstIn); RT_NOREF_PV(pVM);
    8585    Assert(pCpu->Param2.fUse & (DISUSE_IMMEDIATE8 | DISUSE_REG_GEN16));
    86     uint16_t u16Port = pCpu->Param2.fUse & DISUSE_REG_GEN16 ? pRegFrame->dx : (uint16_t)pCpu->Param2.uValue;
     86    bool const     fUseReg = RT_BOOL(pCpu->Param2.fUse & DISUSE_REG_GEN16);
     87    uint16_t const u16Port = fUseReg ? pRegFrame->dx : (uint16_t)pCpu->Param2.uValue;
    8788
    8889    Assert(pCpu->Param1.fUse & (DISUSE_REG_GEN32 | DISUSE_REG_GEN16 | DISUSE_REG_GEN8));
    8990    uint8_t cbValue = pCpu->Param1.fUse & DISUSE_REG_GEN32 ? 4 : pCpu->Param1.fUse & DISUSE_REG_GEN16 ? 2 : 1;
    9091
    91     return IEMExecDecodedIn(pVCpu, pCpu->cbInstr, u16Port, cbValue);
     92    return IEMExecDecodedIn(pVCpu, pCpu->cbInstr, u16Port, !fUseReg, cbValue);
    9293}
    9394
     
    116117    STAM_COUNTER_INC(&pVM->iom.s.StatInstOut); RT_NOREF_PV(pVM);
    117118    Assert(pCpu->Param1.fUse & (DISUSE_IMMEDIATE8 | DISUSE_REG_GEN16));
    118     uint16_t const u16Port = pCpu->Param1.fUse & DISUSE_REG_GEN16 ? pRegFrame->dx : (uint16_t)pCpu->Param1.uValue;
     119    bool const     fUseReg = RT_BOOL(pCpu->Param1.fUse & DISUSE_REG_GEN16);
     120    uint16_t const u16Port = fUseReg ? pRegFrame->dx : (uint16_t)pCpu->Param1.uValue;
    119121
    120122    Assert(pCpu->Param2.fUse & (DISUSE_REG_GEN32 | DISUSE_REG_GEN16 | DISUSE_REG_GEN8));
    121123    uint8_t const cbValue = pCpu->Param2.fUse & DISUSE_REG_GEN32 ? 4 : pCpu->Param2.fUse & DISUSE_REG_GEN16 ? 2 : 1;
    122124
    123     return IEMExecDecodedOut(pVCpu, pCpu->cbInstr, u16Port, cbValue);
     125    return IEMExecDecodedOut(pVCpu, pCpu->cbInstr, u16Port, !fUseReg, cbValue);
    124126}
    125127
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