VirtualBox

Changeset 73745 in vbox for trunk/src


Ignore:
Timestamp:
Aug 17, 2018 6:12:20 PM (6 years ago)
Author:
vboxsync
Message:

VMM: Nested VMX: bugref:9180 Implement VMPTRLD.

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

Legend:

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

    r73628 r73745  
    15661566                                 | (pGuestFeatures->fVmxUnrestrictedGuest << VMX_BF_PROC_CTLS2_UNRESTRICTED_GUEST_SHIFT)
    15671567                                 | (pGuestFeatures->fVmxPauseLoopExit     << VMX_BF_PROC_CTLS2_PAUSE_LOOP_EXIT_SHIFT   )
    1568                                  | (pGuestFeatures->fVmxInvpcid           << VMX_BF_PROC_CTLS2_INVPCID_SHIFT           );
     1568                                 | (pGuestFeatures->fVmxInvpcid           << VMX_BF_PROC_CTLS2_INVPCID_SHIFT           )
     1569                                 | (pGuestFeatures->fVmxVmcsShadowing     << VMX_BF_PROC_CTLS2_VMCS_SHADOWING_SHIFT    );
    15691570        uint32_t const fVal      = 0;
    15701571        uint32_t const fZap      = fFeatures;
  • trunk/src/VBox/VMM/VMMAll/HMVMXAll.cpp

    r73617 r73745  
    5151    VMX_INSTR_DIAG_DESC(kVmxVInstrDiag_Vmxon_LongModeCS    , "LongModeCS"   ),
    5252    VMX_INSTR_DIAG_DESC(kVmxVInstrDiag_Vmxon_MsrFeatCtl    , "MsrFeatCtl"   ),
     53    VMX_INSTR_DIAG_DESC(kVmxVInstrDiag_Vmxon_PtrAbnormal   , "PtrAbnormal"  ),
    5354    VMX_INSTR_DIAG_DESC(kVmxVInstrDiag_Vmxon_PtrAlign      , "PtrAlign"     ),
    54     VMX_INSTR_DIAG_DESC(kVmxVInstrDiag_Vmxon_PtrAbnormal   , "PtrAbnormal"  ),
    5555    VMX_INSTR_DIAG_DESC(kVmxVInstrDiag_Vmxon_PtrMap        , "PtrMap"       ),
    5656    VMX_INSTR_DIAG_DESC(kVmxVInstrDiag_Vmxon_PtrPhysRead   , "PtrPhysRead"  ),
     
    7070    VMX_INSTR_DIAG_DESC(kVmxVInstrDiag_Vmxoff_Success      , "Success"      ),
    7171    VMX_INSTR_DIAG_DESC(kVmxVInstrDiag_Vmxoff_Vmxe         , "Vmxe"         ),
    72     VMX_INSTR_DIAG_DESC(kVmxVInstrDiag_Vmxoff_VmxRoot      , "VmxRoot"      )
     72    VMX_INSTR_DIAG_DESC(kVmxVInstrDiag_Vmxoff_VmxRoot      , "VmxRoot"      ),
     73    /* VMPTRLD. */
     74    VMX_INSTR_DIAG_DESC(kVmxVInstrDiag_Vmptrld_Cpl         , "Cpl"          ),
     75    VMX_INSTR_DIAG_DESC(kVmxVInstrDiag_Vmptrld_PtrAbnormal , "PtrAbnormal"  ),
     76    VMX_INSTR_DIAG_DESC(kVmxVInstrDiag_Vmptrld_PtrAlign    , "PtrAlign"     ),
     77    VMX_INSTR_DIAG_DESC(kVmxVInstrDiag_Vmptrld_PtrMap      , "PtrMap"       ),
     78    VMX_INSTR_DIAG_DESC(kVmxVInstrDiag_Vmptrld_PtrReadPhys , "PtrReadPhys"  ),
     79    VMX_INSTR_DIAG_DESC(kVmxVInstrDiag_Vmptrld_PtrVmxon    , "PtrVmxon"     ),
     80    VMX_INSTR_DIAG_DESC(kVmxVInstrDiag_Vmptrld_PtrWidth    , "PtrWidth"     ),
     81    VMX_INSTR_DIAG_DESC(kVmxVInstrDiag_Vmptrld_ShadowVmcs  , "ShadowVmcs"   ),
     82    VMX_INSTR_DIAG_DESC(kVmxVInstrDiag_Vmptrld_Success     , "Success"      ),
     83    VMX_INSTR_DIAG_DESC(kVmxVInstrDiag_Vmptrld_VmcsRevId   , "VmcsRevId"    )
    7384    /* kVmxVInstrDiag_Last */
    7485};
  • trunk/src/VBox/VMM/VMMAll/IEMAll.cpp

    r73608 r73745  
    1258612586            return IEMOP_RAISE_INVALID_OPCODE(); \
    1258712587    } while (0)
    12588 #endif
     12588
     12589/** The instruction can only be executed in VMX operation (VMX root mode and
     12590 * non-root mode).
     12591 */
     12592# define IEMOP_HLP_IN_VMX_OPERATION() \
     12593    do \
     12594    { \
     12595        if (IEM_IS_VMX_ROOT_MODE(pVCpu)) { /* likely */ } \
     12596        else return IEMOP_RAISE_INVALID_OPCODE(); \
     12597    } while (0)
     12598#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
    1258912599
    1259012600/** The instruction is not available in 64-bit mode, throw \#UD if we're in
  • trunk/src/VBox/VMM/VMMAll/IEMAllCImplVmxInstr.cpp.h

    r73739 r73745  
    481481
    482482/**
     483 * VMPTRLD instruction execution worker.
     484 *
     485 * @param   pVCpu           The cross context virtual CPU structure.
     486 * @param   cbInstr         The instruction length.
     487 * @param   GCPtrVmcs       The linear address of the current VMCS pointer.
     488 * @param   pExitInstrInfo  Pointer to the VM-exit instruction information field.
     489 * @param   GCPtrDisp       The displacement field for @a GCPtrVmcs if any.
     490 *
     491 * @remarks Common VMX instruction checks are already expected to by the caller,
     492 *          i.e. VMX operation, CR4.VMXE, Real/V86 mode, EFER/CS.L checks.
     493 */
     494IEM_STATIC VBOXSTRICTRC iemVmxVmptrld(PVMCPU pVCpu, uint8_t cbInstr, RTGCPHYS GCPtrVmcs, PCVMXEXITINSTRINFO pExitInstrInfo,
     495                                      RTGCPTR GCPtrDisp)
     496{
     497    if (IEM_IS_VMX_NON_ROOT_MODE(pVCpu))
     498    {
     499        RT_NOREF(GCPtrDisp);
     500        /** @todo NSTVMX: intercept. */
     501    }
     502    Assert(IEM_IS_VMX_ROOT_MODE(pVCpu));
     503
     504    /* CPL. */
     505    if (CPUMGetGuestCPL(pVCpu) > 0)
     506    {
     507        Log(("vmptrld: CPL %u -> #GP(0)\n", pVCpu->iem.s.uCpl));
     508        pVCpu->cpum.GstCtx.hwvirt.vmx.enmInstrDiag = kVmxVInstrDiag_Vmptrld_Cpl;
     509        return iemRaiseGeneralProtectionFault0(pVCpu);
     510    }
     511
     512    /* Get the VMCS pointer from the location specified by the source memory operand. */
     513    RTGCPHYS GCPhysVmcs;
     514    VBOXSTRICTRC rcStrict = iemMemFetchDataU64(pVCpu, &GCPhysVmcs, pExitInstrInfo->VmxXsave.iSegReg, GCPtrVmcs);
     515    if (RT_UNLIKELY(rcStrict != VINF_SUCCESS))
     516    {
     517        Log(("vmptrld: Failed to read VMCS physaddr from %#RGv, rc=%Rrc\n", GCPtrVmcs, VBOXSTRICTRC_VAL(rcStrict)));
     518        pVCpu->cpum.GstCtx.hwvirt.vmx.enmInstrDiag = kVmxVInstrDiag_Vmptrld_PtrMap;
     519        return rcStrict;
     520    }
     521
     522    /* VMCS pointer alignment. */
     523    if (GCPhysVmcs & X86_PAGE_4K_OFFSET_MASK)
     524    {
     525        Log(("vmptrld: VMCS pointer not page-aligned -> VMFail()\n"));
     526        pVCpu->cpum.GstCtx.hwvirt.vmx.enmInstrDiag = kVmxVInstrDiag_Vmptrld_PtrAlign;
     527        iemVmxVmFail(pVCpu, VMXINSTRERR_VMPTRLD_INVALID_PHYSADDR);
     528        iemRegAddToRipAndClearRF(pVCpu, cbInstr);
     529        return VINF_SUCCESS;
     530    }
     531
     532    /* VMCS physical-address width limits. */
     533    Assert(!VMX_V_VMCS_PHYSADDR_4G_LIMIT);
     534    if (GCPhysVmcs >> IEM_GET_GUEST_CPU_FEATURES(pVCpu)->cMaxPhysAddrWidth)
     535    {
     536        Log(("vmptrld: VMCS pointer extends beyond physical-address width -> VMFail()\n"));
     537        pVCpu->cpum.GstCtx.hwvirt.vmx.enmInstrDiag = kVmxVInstrDiag_Vmptrld_PtrWidth;
     538        iemVmxVmFail(pVCpu, VMXINSTRERR_VMPTRLD_INVALID_PHYSADDR);
     539        iemRegAddToRipAndClearRF(pVCpu, cbInstr);
     540        return VINF_SUCCESS;
     541    }
     542
     543    /* VMCS is not the VMXON region. */
     544    if (GCPhysVmcs == pVCpu->cpum.GstCtx.hwvirt.vmx.GCPhysVmxon)
     545    {
     546        Log(("vmptrld: VMCS pointer cannot be identical to VMXON region pointer -> VMFail()\n"));
     547        pVCpu->cpum.GstCtx.hwvirt.vmx.enmInstrDiag = kVmxVInstrDiag_Vmptrld_PtrVmxon;
     548        iemVmxVmFail(pVCpu, VMXINSTRERR_VMPTRLD_VMXON_PTR);
     549        iemRegAddToRipAndClearRF(pVCpu, cbInstr);
     550        return VINF_SUCCESS;
     551    }
     552
     553    /* Ensure VMCS is not MMIO, ROM etc. This is not an Intel requirement but a
     554       restriction imposed by our implementation. */
     555    if (!PGMPhysIsGCPhysNormal(pVCpu->CTX_SUFF(pVM), GCPhysVmcs))
     556    {
     557        Log(("vmptrld: VMCS not normal memory -> VMFail()\n"));
     558        pVCpu->cpum.GstCtx.hwvirt.vmx.enmInstrDiag = kVmxVInstrDiag_Vmptrld_PtrAbnormal;
     559        iemVmxVmFail(pVCpu, VMXINSTRERR_VMPTRLD_INVALID_PHYSADDR);
     560        iemRegAddToRipAndClearRF(pVCpu, cbInstr);
     561        return VINF_SUCCESS;
     562    }
     563
     564    /* Read the VMCS revision ID from the VMCS. */
     565    VMXVMCSREVID VmcsRevId;
     566    int rc = PGMPhysSimpleReadGCPhys(pVCpu->CTX_SUFF(pVM), &VmcsRevId, GCPhysVmcs, sizeof(VmcsRevId));
     567    if (RT_FAILURE(rc))
     568    {
     569        Log(("vmptrld: Failed to read VMCS at %#RGp, rc=%Rrc\n", GCPhysVmcs, rc));
     570        pVCpu->cpum.GstCtx.hwvirt.vmx.enmInstrDiag = kVmxVInstrDiag_Vmptrld_PtrReadPhys;
     571        return rc;
     572    }
     573
     574    /* Verify the VMCS revision specified by the guest matches what we reported to the guest,
     575       also check VMCS shadowing feature. */
     576    if (   VmcsRevId.n.u31RevisionId != VMX_V_VMCS_REVISION_ID
     577        || (   VmcsRevId.n.fIsShadowVmcs
     578            && !IEM_GET_GUEST_CPU_FEATURES(pVCpu)->fVmxVmcsShadowing))
     579    {
     580        if (VmcsRevId.n.u31RevisionId != VMX_V_VMCS_REVISION_ID)
     581        {
     582            Log(("vmptrld: VMCS revision mismatch, expected %#RX32 got %#RX32 -> VMFail()\n", VMX_V_VMCS_REVISION_ID,
     583                 VmcsRevId.n.u31RevisionId));
     584            pVCpu->cpum.GstCtx.hwvirt.vmx.enmInstrDiag = kVmxVInstrDiag_Vmptrld_VmcsRevId;
     585            iemVmxVmFail(pVCpu, VMXINSTRERR_VMPTRLD_INCORRECT_VMCS_REV);
     586            iemRegAddToRipAndClearRF(pVCpu, cbInstr);
     587            return VINF_SUCCESS;
     588        }
     589
     590        Log(("vmptrld: Shadow VMCS -> VMFail()\n"));
     591        pVCpu->cpum.GstCtx.hwvirt.vmx.enmInstrDiag = kVmxVInstrDiag_Vmptrld_ShadowVmcs;
     592        iemVmxVmFail(pVCpu, VMXINSTRERR_VMPTRLD_INCORRECT_VMCS_REV);
     593        iemRegAddToRipAndClearRF(pVCpu, cbInstr);
     594        return VINF_SUCCESS;
     595    }
     596
     597    pVCpu->cpum.GstCtx.hwvirt.vmx.GCPhysVmcs = GCPhysVmcs;
     598    pVCpu->cpum.GstCtx.hwvirt.vmx.enmInstrDiag = kVmxVInstrDiag_Vmptrld_Success;
     599    iemVmxVmSucceed(pVCpu);
     600    iemRegAddToRipAndClearRF(pVCpu, cbInstr);
     601    return VINF_SUCCESS;
     602}
     603
     604
     605/**
    483606 * VMXON instruction execution worker.
    484607 *
     
    733856}
    734857
     858
     859/**
     860 * Implements 'VMPTRLD'.
     861 */
     862IEM_CIMPL_DEF_1(iemCImpl_vmptrld, RTGCPTR, GCPtrVmcs)
     863{
     864    RTGCPTR GCPtrDisp;
     865    VMXEXITINSTRINFO ExitInstrInfo;
     866    ExitInstrInfo.u = iemVmxGetExitInstrInfo(pVCpu, VMX_EXIT_VMPTRLD, VMX_INSTR_ID_NONE, &GCPtrDisp);
     867    return iemVmxVmptrld(pVCpu, cbInstr, GCPtrVmcs, &ExitInstrInfo, GCPtrDisp);
     868}
     869
     870
    735871#endif
    736872
  • trunk/src/VBox/VMM/VMMAll/IEMAllInstructionsTwoByte0f.cpp.h

    r73606 r73745  
    84218421
    84228422/** Opcode 0x0f 0xc7 !11/6. */
     8423#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
     8424FNIEMOP_DEF_1(iemOp_Grp9_vmptrld_Mq, uint8_t, bRm)
     8425{
     8426    IEMOP_MNEMONIC(vmptrld, "vmptrld");
     8427    IEMOP_HLP_IN_VMX_OPERATION();
     8428    IEMOP_HLP_VMX_INSTR();
     8429    IEM_MC_BEGIN(1, 0);
     8430    IEM_MC_ARG(RTGCPTR, GCPtrEffSrc, 0);
     8431    IEM_MC_CALC_RM_EFF_ADDR(GCPtrEffSrc, bRm, 0);
     8432    IEMOP_HLP_DONE_DECODING_NO_LOCK_REPZ_OR_REPNZ_PREFIXES();
     8433    IEM_MC_CALL_CIMPL_1(iemCImpl_vmptrld, GCPtrEffSrc);
     8434    IEM_MC_END();
     8435    return VINF_SUCCESS;
     8436}
     8437#else
    84238438FNIEMOP_UD_STUB_1(iemOp_Grp9_vmptrld_Mq, uint8_t, bRm);
     8439#endif
    84248440
    84258441/** Opcode 0x66 0x0f 0xc7 !11/6. */
  • trunk/src/VBox/VMM/VMMR3/CPUM.cpp

    r73742 r73745  
    10211021        VMXFEATDUMP("PauseLoopExit - PAUSE-loop exiting                     ", fVmxPauseLoopExit);
    10221022        VMXFEATDUMP("Invpcid - Enable INVPCID                               ", fVmxInvpcid);
     1023        VMXFEATDUMP("VmcsShadowing - VMCS shadowing                         ", fVmxVmcsShadowing);
    10231024        /* VM-entry controls. */
    10241025        VMXFEATDUMP("EntryLoadDebugCtls - Load debug controls on VM-entry   ", fVmxEntryLoadDebugCtls);
     
    11081109            pHostFeat->fVmxPauseLoopExit     = RT_BOOL(fProcCtls2 & VMX_PROC_CTLS2_PAUSE_LOOP_EXIT);
    11091110            pHostFeat->fVmxInvpcid           = RT_BOOL(fProcCtls2 & VMX_PROC_CTLS2_INVPCID);
     1111            pHostFeat->fVmxVmcsShadowing     = RT_BOOL(fProcCtls2 & VMX_PROC_CTLS2_VMCS_SHADOWING);
    11101112        }
    11111113
     
    11761178    EmuFeat.fVmxPauseLoopExit         = 0;
    11771179    EmuFeat.fVmxInvpcid               = 1;
     1180    EmuFeat.fVmxVmcsShadowing         = 0;
    11781181    EmuFeat.fVmxEntryLoadDebugCtls    = 1;
    11791182    EmuFeat.fVmxIa32eModeGuest        = 1;
     
    12361239    pGuestFeat->fVmxPauseLoopExit         = (pBaseFeat->fVmxPauseLoopExit         & EmuFeat.fVmxPauseLoopExit        );
    12371240    pGuestFeat->fVmxInvpcid               = (pBaseFeat->fVmxInvpcid               & EmuFeat.fVmxInvpcid              );
     1241    pGuestFeat->fVmxVmcsShadowing         = (pBaseFeat->fVmxVmcsShadowing         & EmuFeat.fVmxVmcsShadowing        );
    12381242    pGuestFeat->fVmxEntryLoadDebugCtls    = (pBaseFeat->fVmxEntryLoadDebugCtls    & EmuFeat.fVmxEntryLoadDebugCtls   );
    12391243    pGuestFeat->fVmxIa32eModeGuest        = (pBaseFeat->fVmxIa32eModeGuest        & EmuFeat.fVmxIa32eModeGuest       );
  • trunk/src/VBox/VMM/testcase/tstIEMCheckMc.cpp

    r73606 r73745  
    129129#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
    130130# define IEMOP_HLP_VMX_INSTR()                              do { } while (0)
     131# define IEMOP_HLP_IN_VMX_OPERATION()                       do { } while (0)
    131132#endif
    132133
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