VirtualBox

Changeset 74005 in vbox


Ignore:
Timestamp:
Aug 31, 2018 5:23:00 PM (6 years ago)
Author:
vboxsync
Message:

VMM/HMVMXR0: Nested VMX: bugref:9180 Use a macro for hmR0VmxDecodeMemOperand. Cleanups.

Location:
trunk
Files:
2 edited

Legend:

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

    r73984 r74005  
    839839    /** Plain unsigned int representation. */
    840840    uint32_t    u;
     841
    841842    /** INS and OUTS information. */
    842843    struct
     
    850851        uint32_t    uReserved2  : 14;
    851852    } StrIo;
     853
    852854    struct
    853855    {
     
    873875        uint32_t    iReg2           : 4;
    874876    } Inv;
     877
    875878    /** VMCLEAR, VMPTRLD, VMPTRST, VMXON, XRSTORS, XSAVES information. */
    876879    struct
     
    897900        uint32_t    iReg2           : 4;
    898901    } VmxXsave;
     902
    899903    /** LIDT, LGDT, SIDT, SGDT information. */
    900904    struct
     
    924928        uint32_t    u2Undef0        : 2;
    925929    } GdtIdt;
     930
    926931    /** LLDT, LTR, SLDT, STR information. */
    927932    struct
     
    951956        uint32_t    u2Undef0        : 2;
    952957    } LdtTr;
     958
    953959    /** RDRAND, RDSEED information. */
    954960    struct
     
    963969        uint32_t    u19Def0         : 20;
    964970    } RdrandRdseed;
     971
    965972    struct
    966973    {
     
    989996        uint32_t    iReg2           : 4;
    990997    } VmreadVmwrite;
     998
    991999    /** This is a combination field of all instruction information. Note! Not all field
    992      *  combinations are valid (e.g., iReg1 is undefined for memory operands). */
     1000     *  combinations are valid (e.g., iReg1 is undefined for memory operands) and
     1001     *  specialized fields are overwritten by their generic counterparts (e.g. no
     1002     *  instruction identity field). */
    9931003    struct
    9941004    {
  • trunk/src/VBox/VMM/VMMR0/HMVMXR0.cpp

    r73998 r74005  
    205205        } \
    206206    } while (0)
     207
     208/** Macro that decodes a memory operand for an instruction VM-exit. */
     209# define HMVMX_DECODE_MEM_OPERAND(a_pVCpu, a_uExitInstrInfo, a_uExitQual, a_enmMemAccess, a_pGCPtrEffAddr) \
     210    do \
     211    { \
     212        VBOXSTRICTRC rcStrictTmp = hmR0VmxDecodeMemOperand((a_pVCpu), (a_uExitInstrInfo), (a_uExitQual), (a_enmMemAccess), \
     213                                                           (a_pGCPtrEffAddr)); \
     214        if (rcStrictTmp == VINF_SUCCESS) \
     215        { /* likely */ } \
     216        else if (rcStrictTmp == VINF_HM_PENDING_XCPT) \
     217        { \
     218            uint8_t const uXcptTmp = VMX_ENTRY_INT_INFO_VECTOR((a_pVCpu)->hm.s.Event.u64IntInfo); \
     219            Log4Func(("Memory operand decoding failed, raising xcpt %#x\n", uXcptTmp)); \
     220            return VINF_SUCCESS; \
     221        } \
     222        else \
     223        { \
     224            Log4Func(("hmR0VmxCheckExitDueToVmxInstr failed. rc=%Rrc\n", VBOXSTRICTRC_VAL(rcStrictTmp))); \
     225            return rcStrictTmp; \
     226        } \
     227    } while (0)
     228
    207229#endif  /* VBOX_WITH_NESTED_HWVIRT_VMX */
    208230
     
    285307typedef VMXTRANSIENT *PVMXTRANSIENT;
    286308
    287 
    288309/**
    289310 * MSR-bitmap read permissions.
     
    312333typedef VMXMSREXITWRITE* PVMXMSREXITWRITE;
    313334
     335/**
     336 * Memory operand read or write access.
     337 */
     338typedef enum VMXMEMACCESS
     339{
     340    VMXMEMACCESS_READ  = 0,
     341    VMXMEMACCESS_WRITE = 1
     342} VMXMEMACCESS;
    314343
    315344/**
     
    368397# define HMVMX_EXIT_NSRC_DECL HMVMX_EXIT_DECL
    369398#endif
    370 
    371399
    372400/** @name VM-exit handlers.
     
    58785906 *          operand.
    58795907 * @param   pVCpu           The cross context virtual CPU structure.
    5880  * @param   pExitInstrInfo  Pointer to the VM-exit instruction information.
    5881  * @param   fIsDstOperand   Whether the operand is a destination memory
    5882  *                          operand (i.e. writeable memory location) or not.
     5908 * @param   uExitInstrInfo  The VM-exit instruction information field.
     5909 * @param   enmMemAccess    The memory operand's access type (read or write).
    58835910 * @param   GCPtrDisp       The instruction displacement field, if any. For
    58845911 *                          RIP-relative addressing pass RIP + displacement here.
    58855912 * @param   pGCPtrMem       Where to store the effective destination memory address.
    58865913 */
    5887 static VBOXSTRICTRC hmR0VmxDecodeMemOperand(PVMCPU pVCpu, PCVMXEXITINSTRINFO pExitInstrInfo, RTGCPTR GCPtrDisp,
    5888                                             bool fIsDstOperand, PRTGCPTR pGCPtrMem)
    5889 {
    5890     Assert(pExitInstrInfo);
     5914static VBOXSTRICTRC hmR0VmxDecodeMemOperand(PVMCPU pVCpu, uint32_t uExitInstrInfo, RTGCPTR GCPtrDisp, VMXMEMACCESS enmMemAccess,
     5915                                            PRTGCPTR pGCPtrMem)
     5916{
    58915917    Assert(pGCPtrMem);
    58925918    Assert(!CPUMIsGuestInRealOrV86Mode(pVCpu));
     
    58975923    AssertCompile(RT_ELEMENTS(s_auAccessSizeMasks) == RT_ELEMENTS(s_auAddrSizeMasks));
    58985924
    5899     uint8_t const   uAddrSize     =  pExitInstrInfo->All.u3AddrSize;
    5900     uint8_t const   iSegReg       =  pExitInstrInfo->All.iSegReg;
    5901     bool const      fIdxRegValid  = !pExitInstrInfo->All.fIdxRegInvalid;
    5902     uint8_t const   iIdxReg       =  pExitInstrInfo->All.iIdxReg;
    5903     uint8_t const   uScale        =  pExitInstrInfo->All.u2Scaling;
    5904     bool const      fBaseRegValid = !pExitInstrInfo->All.fBaseRegInvalid;
    5905     uint8_t const   iBaseReg      =  pExitInstrInfo->All.iBaseReg;
    5906     bool const      fIsMemOperand = !pExitInstrInfo->All.fIsRegOperand;
     5925    VMXEXITINSTRINFO ExitInstrInfo;
     5926    ExitInstrInfo.u = uExitInstrInfo;
     5927    uint8_t const   uAddrSize     =  ExitInstrInfo.All.u3AddrSize;
     5928    uint8_t const   iSegReg       =  ExitInstrInfo.All.iSegReg;
     5929    bool const      fIdxRegValid  = !ExitInstrInfo.All.fIdxRegInvalid;
     5930    uint8_t const   iIdxReg       =  ExitInstrInfo.All.iIdxReg;
     5931    uint8_t const   uScale        =  ExitInstrInfo.All.u2Scaling;
     5932    bool const      fBaseRegValid = !ExitInstrInfo.All.fBaseRegInvalid;
     5933    uint8_t const   iBaseReg      =  ExitInstrInfo.All.iBaseReg;
     5934    bool const      fIsMemOperand = !ExitInstrInfo.All.fIsRegOperand;
    59075935    bool const      fIsLongMode   =  CPUMIsGuestInLongModeEx(&pVCpu->cpum.GstCtx);
    59085936
     
    59125940     */
    59135941    AssertLogRelMsgReturn(uAddrSize < RT_ELEMENTS(s_auAddrSizeMasks),
    5914                           ("Invalid address size. ExitInstrInfo=%#RX32\n", pExitInstrInfo->u), VERR_VMX_IPE_1);
     5942                          ("Invalid address size. ExitInstrInfo=%#RX32\n", ExitInstrInfo.u), VERR_VMX_IPE_1);
    59155943    AssertLogRelMsgReturn(iSegReg  < X86_SREG_COUNT,
    5916                           ("Invalid segment register. ExitInstrInfo=%#RX32\n", pExitInstrInfo->u), VERR_VMX_IPE_2);
     5944                          ("Invalid segment register. ExitInstrInfo=%#RX32\n", ExitInstrInfo.u), VERR_VMX_IPE_2);
    59175945    AssertLogRelMsgReturn(fIsMemOperand,
    5918                           ("Expected memory operand. ExitInstrInfo=%#RX32\n", pExitInstrInfo->u), VERR_VMX_IPE_3);
     5946                          ("Expected memory operand. ExitInstrInfo=%#RX32\n", ExitInstrInfo.u), VERR_VMX_IPE_3);
    59195947
    59205948    /*
     
    59746002        {
    59756003            /* Check permissions for the data segment. */
    5976             if (   fIsDstOperand
     6004            if (   enmMemAccess == VMXMEMACCESS_WRITE
    59776005                && !(pSel->Attr.n.u4Type & X86_SEL_TYPE_WRITE))
    59786006            {
     
    60196047        {
    60206048            /* Check permissions for the code segment. */
    6021             if (   fIsDstOperand
    6022                 || !(pSel->Attr.n.u4Type & X86_SEL_TYPE_READ))
     6049            if (   enmMemAccess == VMXMEMACCESS_WRITE
     6050                || (   enmMemAccess == VMXMEMACCESS_READ
     6051                    && !(pSel->Attr.n.u4Type & X86_SEL_TYPE_READ)))
    60236052            {
    60246053                Log4Func(("Code segment access invalid. Attr=%#RX32\n", pSel->Attr.u));
     
    1343213461    ExitInfo.cbInstr     = pVmxTransient->cbInstr;
    1343313462    if (!ExitInfo.InstrInfo.VmreadVmwrite.fIsRegOperand)
    13434     {
    13435         RTGCPTR GCPtrVal;
    13436         VBOXSTRICTRC rcStrict = hmR0VmxDecodeMemOperand(pVCpu, &ExitInfo.InstrInfo, ExitInfo.u64Qual, false /* fIsDstOperand */,
    13437                                                          &GCPtrVal);
    13438         if (rcStrict == VINF_SUCCESS)
    13439         { /* likely */ }
    13440         else if (rcStrict == VINF_HM_PENDING_XCPT)
    13441         {
    13442             Assert(pVCpu->hm.s.Event.fPending);
    13443             Log4Func(("Memory operand decoding failed, raising xcpt %#x\n",
    13444                       VMX_ENTRY_INT_INFO_VECTOR(pVCpu->hm.s.Event.u64IntInfo)));
    13445             return VINF_SUCCESS;
    13446         }
    13447         else
    13448         {
    13449             Log4Func(("hmR0VmxCheckExitDueToVmxInstr failed. rc=%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
    13450             return rcStrict;
    13451         }
    13452         ExitInfo.GCPtrEffAddr = GCPtrVal;
    13453     }
     13463        HMVMX_DECODE_MEM_OPERAND(pVCpu, ExitInfo.InstrInfo.u, ExitInfo.u64Qual, VMXMEMACCESS_WRITE, &ExitInfo.GCPtrEffAddr);
    1345413464
    1345513465    VBOXSTRICTRC rcStrict = IEMExecDecodedVmread(pVCpu, &ExitInfo);
     
    1350113511    ExitInfo.cbInstr     = pVmxTransient->cbInstr;
    1350213512    if (!ExitInfo.InstrInfo.VmreadVmwrite.fIsRegOperand)
    13503     {
    13504         RTGCPTR GCPtrVal;
    13505         VBOXSTRICTRC rcStrict = hmR0VmxDecodeMemOperand(pVCpu, &ExitInfo.InstrInfo, ExitInfo.u64Qual, false /* fIsDstOperand */,
    13506                                                          &GCPtrVal);
    13507         if (rcStrict == VINF_SUCCESS)
    13508         { /* likely */ }
    13509         else if (rcStrict == VINF_HM_PENDING_XCPT)
    13510         {
    13511             Assert(pVCpu->hm.s.Event.fPending);
    13512             Log4Func(("Memory operand decoding failed, raising xcpt %#x\n",
    13513                       VMX_ENTRY_INT_INFO_VECTOR(pVCpu->hm.s.Event.u64IntInfo)));
    13514             return VINF_SUCCESS;
    13515         }
    13516         else
    13517         {
    13518             Log4Func(("hmR0VmxCheckExitDueToVmxInstr failed. rc=%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
    13519             return rcStrict;
    13520         }
    13521         ExitInfo.GCPtrEffAddr = GCPtrVal;
    13522     }
     13513        HMVMX_DECODE_MEM_OPERAND(pVCpu, ExitInfo.InstrInfo.u, ExitInfo.u64Qual, VMXMEMACCESS_READ, &ExitInfo.GCPtrEffAddr);
    1352313514
    1352413515    VBOXSTRICTRC rcStrict = IEMExecDecodedVmwrite(pVCpu, &ExitInfo);
     
    1358413575    ExitInfo.InstrInfo.u = pVmxTransient->ExitInstrInfo.u;
    1358513576    ExitInfo.cbInstr     = pVmxTransient->cbInstr;
    13586 
    13587     RTGCPTR GCPtrVmxon;
    13588     VBOXSTRICTRC rcStrict = hmR0VmxDecodeMemOperand(pVCpu, &ExitInfo.InstrInfo, ExitInfo.u64Qual, false /* fIsDstOperand */,
    13589                                                     &GCPtrVmxon);
    13590     if (rcStrict == VINF_SUCCESS)
    13591     { /* likely */ }
    13592     else if (rcStrict == VINF_HM_PENDING_XCPT)
    13593     {
    13594         Log4Func(("Memory operand decoding failed, raising xcpt %#x\n", VMX_ENTRY_INT_INFO_VECTOR(pVCpu->hm.s.Event.u64IntInfo)));
    13595         return VINF_SUCCESS;
    13596     }
    13597     else
    13598     {
    13599         Log4Func(("hmR0VmxCheckExitDueToVmxInstr failed. rc=%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
    13600         return rcStrict;
    13601     }
    13602     ExitInfo.GCPtrEffAddr = GCPtrVmxon;
    13603 
    13604     rcStrict = IEMExecDecodedVmxon(pVCpu, &ExitInfo);
     13577    HMVMX_DECODE_MEM_OPERAND(pVCpu, ExitInfo.InstrInfo.u, ExitInfo.u64Qual, VMXMEMACCESS_READ, &ExitInfo.GCPtrEffAddr);
     13578
     13579    VBOXSTRICTRC rcStrict = IEMExecDecodedVmxon(pVCpu, &ExitInfo);
    1360513580    if (RT_LIKELY(rcStrict == VINF_SUCCESS))
    1360613581        ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_HWVIRT);
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