VirtualBox

Ignore:
Timestamp:
Feb 24, 2022 3:14:31 PM (3 years ago)
Author:
vboxsync
Message:

VMM: Nested VMX: bugref:10092 EPT VM-exit handling with HM ring-0 code.

File:
1 edited

Legend:

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

    r93650 r93922  
    37113711 *                          This need not be page aligned (e.g. nested-guest in real
    37123712 *                          mode).
    3713  * @param   pExitEventInfo  Pointer to the VM-exit event information. Optional, can
    3714  *                          be NULL.
    3715  */
    3716 IEM_STATIC VBOXSTRICTRC iemVmxVmexitEptMisconfig(PVMCPUCC pVCpu, RTGCPHYS GCPhysAddr, PCVMXVEXITEVENTINFO pExitEventInfo)
    3717 {
    3718     if (pExitEventInfo)
    3719     {
    3720         iemVmxVmcsSetExitIntInfo(pVCpu, pExitEventInfo->uExitIntInfo);
    3721         iemVmxVmcsSetExitIntErrCode(pVCpu, pExitEventInfo->uExitIntErrCode);
    3722         iemVmxVmcsSetIdtVectoringInfo(pVCpu, pExitEventInfo->uIdtVectoringInfo);
    3723         iemVmxVmcsSetIdtVectoringErrCode(pVCpu, pExitEventInfo->uIdtVectoringErrCode);
    3724     }
    3725 
     3713 */
     3714IEM_STATIC VBOXSTRICTRC iemVmxVmexitEptMisconfig(PVMCPUCC pVCpu, RTGCPHYS GCPhysAddr)
     3715{
     3716    iemVmxVmcsSetExitGuestPhysAddr(pVCpu, GCPhysAddr);
     3717    return iemVmxVmexit(pVCpu, VMX_EXIT_EPT_MISCONFIG, 0 /* u64ExitQual */);
     3718}
     3719
     3720
     3721/**
     3722 * VMX VM-exit handler for EPT misconfiguration.
     3723 *
     3724 * This is intended for EPT misconfigurations where the caller provides all the
     3725 * relevant VM-exit information.
     3726 *
     3727 * @param   pVCpu           The cross context virtual CPU structure.
     3728 * @param   GCPhysAddr      The physical address causing the EPT misconfiguration.
     3729 *                          This need not be page aligned (e.g. nested-guest in real
     3730 *                          mode).
     3731 * @param   pExitEventInfo  Pointer to the VM-exit event information.
     3732 */
     3733IEM_STATIC VBOXSTRICTRC iemVmxVmexitEptMisconfigWithInfo(PVMCPUCC pVCpu, RTGCPHYS GCPhysAddr, PCVMXVEXITEVENTINFO pExitEventInfo)
     3734{
     3735    Assert(pExitEventInfo);
     3736    Assert(!VMX_EXIT_INT_INFO_IS_VALID(pExitEventInfo->uExitIntInfo));
     3737    iemVmxVmcsSetIdtVectoringInfo(pVCpu, pExitEventInfo->uIdtVectoringInfo);
     3738    iemVmxVmcsSetIdtVectoringErrCode(pVCpu, pExitEventInfo->uIdtVectoringErrCode);
    37263739    iemVmxVmcsSetExitGuestPhysAddr(pVCpu, GCPhysAddr);
    37273740    return iemVmxVmexit(pVCpu, VMX_EXIT_EPT_MISCONFIG, 0 /* u64ExitQual */);
     
    37453758 */
    37463759IEM_STATIC VBOXSTRICTRC iemVmxVmexitEptViolation(PVMCPUCC pVCpu, uint32_t fAccess, uint32_t fSlatFail, uint64_t fEptAccess,
    3747                                                  RTGCPHYS GCPhysAddr, bool fLinearAddrValid, uint64_t GCPtrAddr, uint8_t cbInstr)
     3760                                                 RTGCPHYS GCPhysAddr, bool fIsLinearAddrValid, uint64_t GCPtrAddr,
     3761                                                 uint8_t cbInstr)
    37483762{
    37493763    /*
     
    37523766     * While we can leave it this way, it's preferrable to zero it for consistency.
    37533767     */
    3754     Assert(fLinearAddrValid || GCPtrAddr == 0);
     3768    Assert(fIsLinearAddrValid || GCPtrAddr == 0);
    37553769
    37563770    uint64_t const fCaps = pVCpu->cpum.GstCtx.hwvirt.vmx.Msrs.u64EptVpidCaps;
    3757     uint8_t const fSupportsAccessDirty = fCaps & MSR_IA32_VMX_EPT_VPID_CAP_ACCESS_DIRTY;
    3758 
    3759     uint8_t const fDataRead      = ((fAccess & IEM_ACCESS_DATA_R)  == IEM_ACCESS_DATA_R)  | fSupportsAccessDirty;
    3760     uint8_t const fDataWrite     = ((fAccess & IEM_ACCESS_DATA_RW) == IEM_ACCESS_DATA_RW) | fSupportsAccessDirty;
    3761     uint8_t const fInstrFetch    = (fAccess & IEM_ACCESS_INSTRUCTION) == IEM_ACCESS_INSTRUCTION;
    3762     bool const fEptRead          = RT_BOOL(fEptAccess & EPT_E_READ);
    3763     bool const fEptWrite         = RT_BOOL(fEptAccess & EPT_E_WRITE);
    3764     bool const fEptExec          = RT_BOOL(fEptAccess & EPT_E_EXECUTE);
    3765     bool const fNmiUnblocking    = pVCpu->cpum.GstCtx.hwvirt.vmx.fNmiUnblockingIret;
    3766     bool const fLinearToPhysAddr = fLinearAddrValid & RT_BOOL(fSlatFail & IEM_SLAT_FAIL_LINEAR_TO_PHYS_ADDR);
     3771    bool const fSupportsAccessDirty = RT_BOOL(fCaps & MSR_IA32_VMX_EPT_VPID_CAP_ACCESS_DIRTY);
     3772
     3773    uint32_t const fDataRdMask     = IEM_ACCESS_WHAT_MASK | IEM_ACCESS_TYPE_READ;
     3774    uint32_t const fDataWrMask     = IEM_ACCESS_WHAT_MASK | IEM_ACCESS_TYPE_WRITE;
     3775    uint32_t const fInstrMask      = IEM_ACCESS_WHAT_MASK | IEM_ACCESS_TYPE_EXEC;
     3776    bool const fDataRead           = ((fAccess & fDataRdMask) == IEM_ACCESS_DATA_R) | fSupportsAccessDirty;
     3777    bool const fDataWrite          = ((fAccess & fDataWrMask) == IEM_ACCESS_DATA_W) | fSupportsAccessDirty;
     3778    bool const fInstrFetch         = ((fAccess & fInstrMask)  == IEM_ACCESS_INSTRUCTION);
     3779    bool const fEptRead            = RT_BOOL(fEptAccess & EPT_E_READ);
     3780    bool const fEptWrite           = RT_BOOL(fEptAccess & EPT_E_WRITE);
     3781    bool const fEptExec            = RT_BOOL(fEptAccess & EPT_E_EXECUTE);
     3782    bool const fNmiUnblocking      = pVCpu->cpum.GstCtx.hwvirt.vmx.fNmiUnblockingIret;
     3783    bool const fIsLinearToPhysAddr = fIsLinearAddrValid & RT_BOOL(fSlatFail & IEM_SLAT_FAIL_LINEAR_TO_PHYS_ADDR);
    37673784
    37683785    uint64_t const u64ExitQual = RT_BF_MAKE(VMX_BF_EXIT_QUAL_EPT_ACCESS_READ,         fDataRead)
     
    37723789                               | RT_BF_MAKE(VMX_BF_EXIT_QUAL_EPT_ENTRY_WRITE,         fEptWrite)
    37733790                               | RT_BF_MAKE(VMX_BF_EXIT_QUAL_EPT_ENTRY_EXECUTE,       fEptExec)
    3774                                | RT_BF_MAKE(VMX_BF_EXIT_QUAL_EPT_LINEAR_ADDR_VALID,   fLinearAddrValid)
    3775                                | RT_BF_MAKE(VMX_BF_EXIT_QUAL_EPT_LINEAR_TO_PHYS_ADDR, fLinearToPhysAddr)
     3791                               | RT_BF_MAKE(VMX_BF_EXIT_QUAL_EPT_LINEAR_ADDR_VALID,   fIsLinearAddrValid)
     3792                               | RT_BF_MAKE(VMX_BF_EXIT_QUAL_EPT_LINEAR_TO_PHYS_ADDR, fIsLinearToPhysAddr)
    37763793                               | RT_BF_MAKE(VMX_BF_EXIT_QUAL_EPT_NMI_UNBLOCK_IRET,    fNmiUnblocking);
    37773794
     
    38073824                                                         PCVMXVEXITEVENTINFO pExitEventInfo)
    38083825{
     3826    Assert(pExitInfo);
     3827    Assert(pExitEventInfo);
    38093828    Assert(pExitInfo->uReason == VMX_EXIT_EPT_VIOLATION);
    3810 
    3811     iemVmxVmcsSetExitIntInfo(pVCpu, pExitEventInfo->uExitIntInfo);
    3812     iemVmxVmcsSetExitIntErrCode(pVCpu, pExitEventInfo->uExitIntErrCode);
     3829    Assert(!VMX_EXIT_INT_INFO_IS_VALID(pExitEventInfo->uExitIntInfo));
     3830
    38133831    iemVmxVmcsSetIdtVectoringInfo(pVCpu, pExitEventInfo->uIdtVectoringInfo);
    38143832    iemVmxVmcsSetIdtVectoringErrCode(pVCpu, pExitEventInfo->uIdtVectoringErrCode);
     
    38183836        iemVmxVmcsSetExitGuestLinearAddr(pVCpu, pExitInfo->u64GuestLinearAddr);
    38193837    else
    3820         iemVmxVmcsSetExitGuestLinearAddr(pVCpu,  0);
     3838        iemVmxVmcsSetExitGuestLinearAddr(pVCpu, 0);
    38213839    iemVmxVmcsSetExitInstrLen(pVCpu, pExitInfo->cbInstr);
    38223840    return iemVmxVmexit(pVCpu, VMX_EXIT_EPT_VIOLATION, pExitInfo->u64Qual);
     
    38343852 *                      applicable.
    38353853 */
    3836 IEM_STATIC VBOXSTRICTRC iemVmxVmexitEpt(PVMCPUCC pVCpu, PPGMPTWALK pWalk, uint32_t fAccess, uint32_t fSlatFail,
    3837                                         uint8_t cbInstr)
     3854IEM_STATIC VBOXSTRICTRC iemVmxVmexitEpt(PVMCPUCC pVCpu, PPGMPTWALK pWalk, uint32_t fAccess, uint32_t fSlatFail, uint8_t cbInstr)
    38383855{
    38393856    Assert(pWalk->fIsSlat);
     
    38523869    Log(("EptMisconfig: cs:rip=%x:%#RX64 fAccess=%#RX32\n", pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip, fAccess));
    38533870    Assert(pWalk->fFailed & PGM_WALKFAIL_EPT_MISCONFIG);
    3854     return iemVmxVmexitEptMisconfig(pVCpu, pWalk->GCPhysNested, NULL /* pExitEventInfo */);
     3871    return iemVmxVmexitEptMisconfig(pVCpu, pWalk->GCPhysNested);
    38553872}
    38563873
     
    38613878 * @param   pVCpu       The cross context virtual CPU structure.
    38623879 * @param   offAccess   The offset of the register being accessed.
    3863  * @param   fAccess     The type of access (must contain IEM_ACCESS_TYPE_READ or
    3864  *                      IEM_ACCESS_TYPE_WRITE or IEM_ACCESS_INSTRUCTION).
     3880 * @param   fAccess     The type of access, see IEM_ACCESS_XXX.
    38653881 */
    38663882IEM_STATIC VBOXSTRICTRC iemVmxVmexitApicAccess(PVMCPUCC pVCpu, uint16_t offAccess, uint32_t fAccess)
    38673883{
    3868     Assert((fAccess & IEM_ACCESS_TYPE_READ) || (fAccess & IEM_ACCESS_TYPE_WRITE) || (fAccess & IEM_ACCESS_INSTRUCTION));
    3869 
    38703884    VMXAPICACCESS enmAccess;
    38713885    bool const fInEventDelivery = IEMGetCurrentXcpt(pVCpu, NULL, NULL, NULL, NULL);
    38723886    if (fInEventDelivery)
    38733887        enmAccess = VMXAPICACCESS_LINEAR_EVENT_DELIVERY;
    3874     else if (fAccess & IEM_ACCESS_INSTRUCTION)
     3888    else if ((fAccess & (IEM_ACCESS_WHAT_MASK | IEM_ACCESS_TYPE_MASK)) == IEM_ACCESS_INSTRUCTION)
    38753889        enmAccess = VMXAPICACCESS_LINEAR_INSTR_FETCH;
    38763890    else if (fAccess & IEM_ACCESS_TYPE_WRITE)
     
    41274141 * @param   offAccess   The offset of the register being accessed.
    41284142 * @param   cbAccess    The size of the access in bytes.
    4129  * @param   fAccess     The type of access (must be IEM_ACCESS_TYPE_READ or
    4130  *                      IEM_ACCESS_TYPE_WRITE).
     4143 * @param   fAccess     The type of access, see IEM_ACCESS_XXX.
    41314144 *
    41324145 * @remarks This must not be used for MSR-based APIC-access page accesses!
     
    41364149{
    41374150    PCVMXVVMCS const pVmcs = &pVCpu->cpum.GstCtx.hwvirt.vmx.Vmcs;
    4138     Assert(fAccess == IEM_ACCESS_TYPE_READ || fAccess == IEM_ACCESS_TYPE_WRITE);
    41394151
    41404152    /*
     
    42974309 *
    42984310 * @param   pVCpu           The cross context virtual CPU structure.
    4299  * @param   pGCPhysAccess   Pointer to the guest-physical address used.
    4300  */
    4301 IEM_STATIC VBOXSTRICTRC iemVmxVirtApicAccessUnused(PVMCPUCC pVCpu, PRTGCPHYS pGCPhysAccess)
     4311 * @param   pGCPhysAccess   Pointer to the guest-physical address accessed.
     4312 * @param   fAccess         The type of access, see IEM_ACCESS_XXX.
     4313 */
     4314IEM_STATIC VBOXSTRICTRC iemVmxVirtApicAccessUnused(PVMCPUCC pVCpu, PRTGCPHYS pGCPhysAccess, uint32_t fAccess)
    43024315{
    43034316    Assert(pVCpu->cpum.GstCtx.hwvirt.vmx.Vmcs.u32ProcCtls2 & VMX_PROC_CTLS2_VIRT_APIC_ACCESS);
     
    43114324    {
    43124325        uint16_t const offAccess = *pGCPhysAccess & GUEST_PAGE_OFFSET_MASK;
    4313         uint32_t const fAccess   = IEM_ACCESS_TYPE_READ;
    43144326        uint16_t const cbAccess  = 1;
    43154327        bool const fIntercept = iemVmxVirtApicIsMemAccessIntercepted(pVCpu, offAccess, cbAccess, fAccess);
     
    43384350 * @param   pvData      Pointer to the data being written or where to store the data
    43394351 *                      being read.
    4340  * @param   fAccess     The type of access (must contain IEM_ACCESS_TYPE_READ or
    4341  *                      IEM_ACCESS_TYPE_WRITE or IEM_ACCESS_INSTRUCTION).
     4352 * @param   fAccess     The type of access, see IEM_ACCESS_XXX.
    43424353 */
    43434354IEM_STATIC VBOXSTRICTRC iemVmxVirtApicAccessMem(PVMCPUCC pVCpu, uint16_t offAccess, size_t cbAccess, void *pvData,
     
    43464357    Assert(pVCpu->cpum.GstCtx.hwvirt.vmx.Vmcs.u32ProcCtls2 & VMX_PROC_CTLS2_VIRT_APIC_ACCESS);
    43474358    Assert(pvData);
    4348     Assert(   (fAccess & IEM_ACCESS_TYPE_READ)
    4349            || (fAccess & IEM_ACCESS_TYPE_WRITE)
    4350            || (fAccess & IEM_ACCESS_INSTRUCTION));
    43514359
    43524360    bool const fIntercept = iemVmxVirtApicIsMemAccessIntercepted(pVCpu, offAccess, cbAccess, fAccess);
     
    43894397         * See Intel spec. 29.4.2 "Virtualizing Reads from the APIC-Access Page".
    43904398         */
     4399        Assert(fAccess & IEM_ACCESS_TYPE_READ);
     4400
    43914401        Assert(cbAccess <= 4);
    43924402        Assert(offAccess < XAPIC_OFF_END + 4);
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