VirtualBox

Changeset 91378 in vbox for trunk


Ignore:
Timestamp:
Sep 27, 2021 9:04:31 AM (3 years ago)
Author:
vboxsync
Message:

VMM/IEM: Nested VMX: bugref:10092 VM-exit handler for EPT violation.

File:
1 edited

Legend:

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

    r91360 r91378  
    37123712    return VINF_VMX_INTERCEPT_NOT_ACTIVE;
    37133713}
     3714
     3715
     3716#ifdef VBOX_WITH_NESTED_HWVIRT_VMX_EPT
     3717/**
     3718 * VMX VM-exit handler for EPT violation.
     3719 *
     3720 * @param   pVCpu       The cross context virtual CPU structure.
     3721 * @param   fAccess     The access causing the EPT violation, IEM_ACCESS_XXX.
     3722 * @param   fEptAccess  The EPT paging structure bits.
     3723 * @param   GCPhysAddr  The physical address causing the EPT violation.
     3724 * @param   GCPtrAddr   The linear address causing the EPT violation.
     3725 * @param   cbInstr     The VM-exit instruction length.
     3726 */
     3727IEM_STATIC VBOXSTRICTRC iemVmxVmexitEptViolation(PVMCPUCC pVCpu, uint32_t fAccess, uint64_t fEptAccess, RTGCPHYS GCPhysAddr,
     3728                                                 uint64_t GCPtrAddr, bool fLinearAddrValid, uint8_t cbInstr)
     3729{
     3730    /*
     3731     * If the linear address isn't valid (can happen when loading PDPTEs
     3732     * as part of MOV CR execution) the linear address field is undefined.
     3733     * While we can leave it this way, it's preferrable to zero it for consistency.
     3734     */
     3735    Assert(fLinearAddrValid || GCPtrAddr == 0);
     3736
     3737    uint64_t const fCaps = pVCpu->cpum.GstCtx.hwvirt.vmx.Msrs.u64EptVpidCaps;
     3738    uint8_t const fSupportsAccessDirty = fCaps & MSR_IA32_VMX_EPT_VPID_CAP_ACCESS_DIRTY;
     3739
     3740    uint8_t const fDataRead   = ((fAccess & IEM_ACCESS_DATA_R)  == IEM_ACCESS_DATA_R)  | fSupportsAccessDirty;
     3741    uint8_t const fDataWrite  = ((fAccess & IEM_ACCESS_DATA_RW) == IEM_ACCESS_DATA_RW) | fSupportsAccessDirty;
     3742    uint8_t const fInstrFetch = (fAccess & IEM_ACCESS_INSTRUCTION) == IEM_ACCESS_INSTRUCTION;
     3743    uint8_t const fEptRead    = fEptAccess & EPT_E_READ;
     3744    uint8_t const fEptWrite   = fEptAccess & EPT_E_WRITE;
     3745    uint8_t const fEptExec    = fEptAccess & EPT_E_EXECUTE;
     3746    bool const fNmiUnblocking = pVCpu->cpum.GstCtx.hwvirt.vmx.fNmiUnblockingIret;
     3747
     3748    uint64_t const u64ExitQual = RT_BF_MAKE(VMX_BF_EXIT_QUAL_EPT_ACCESS_READ,        fDataRead)
     3749                               | RT_BF_MAKE(VMX_BF_EXIT_QUAL_EPT_ACCESS_WRITE,       fDataWrite)
     3750                               | RT_BF_MAKE(VMX_BF_EXIT_QUAL_EPT_ACCESS_INSTR_FETCH, fInstrFetch)
     3751                               | RT_BF_MAKE(VMX_BF_EXIT_QUAL_EPT_ENTRY_READ,         fEptRead)
     3752                               | RT_BF_MAKE(VMX_BF_EXIT_QUAL_EPT_ENTRY_WRITE,        fEptWrite)
     3753                               | RT_BF_MAKE(VMX_BF_EXIT_QUAL_EPT_ENTRY_EXECUTE,      fEptExec)
     3754                               | RT_BF_MAKE(VMX_BF_EXIT_QUAL_EPT_LINEAR_ADDR_VALID,  fLinearAddrValid)
     3755                               | RT_BF_MAKE(VMX_BF_EXIT_QUAL_EPT_NMI_UNBLOCK_IRET,   fNmiUnblocking);
     3756
     3757    /** @todo bit 8 of Exit Qualification!
     3758     *  If the access causing the EPT violation is to a guest-physical address that is
     3759     *  the translation of a linear address.
     3760     *   - OR -
     3761     *  if the access causing the EPT violation is to a paging-structure entry as part
     3762     *  of a page walk or the update of an accessed or dirty bit.
     3763     *
     3764     *  Caller needs to be able to distinguish this... */
     3765
     3766    uint64_t const fMiscCaps  = pVCpu->cpum.GstCtx.hwvirt.vmx.Msrs.u64Misc;
     3767    uint32_t const fProcCtls2 = pVCpu->cpum.GstCtx.hwvirt.vmx.Vmcs.u32ProcCtls2;
     3768    Assert(!(fCaps & MSR_IA32_VMX_EPT_VPID_CAP_ADVEXITINFO_EPT_VIOLATION));   /* Advanced VM-exit info. not supported */
     3769    Assert(!(fCaps & MSR_IA32_VMX_EPT_VPID_CAP_SUPER_SHW_STACK));             /* Supervisor shadow stack control not supported. */
     3770    Assert(!(RT_BF_GET(fMiscCaps, VMX_BF_MISC_INTEL_PT)));                    /* Intel PT not supported. */
     3771    Assert(!(RT_BF_GET(fMiscCaps, VMX_BF_MISC_INTEL_PT)));                    /* Intel PT not supported. */
     3772    Assert(!(fProcCtls2 & VMX_PROC_CTLS2_MODE_BASED_EPT_PERM));               /* Mode-based execute control not supported. */
     3773
     3774    iemVmxVmcsSetExitGuestPhysAddr(pVCpu, GCPhysAddr);
     3775    iemVmxVmcsSetExitGuestLinearAddr(pVCpu, GCPtrAddr);
     3776    iemVmxVmcsSetExitInstrLen(pVCpu, cbInstr);
     3777
     3778    return iemVmxVmexit(pVCpu, VMX_EXIT_EPT_VIOLATION, u64ExitQual);
     3779}
     3780#endif
    37143781
    37153782
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