- Timestamp:
- Sep 27, 2021 9:04:31 AM (3 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/VMM/VMMAll/IEMAllCImplVmxInstr.cpp.h
r91360 r91378 3712 3712 return VINF_VMX_INTERCEPT_NOT_ACTIVE; 3713 3713 } 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 */ 3727 IEM_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 3714 3781 3715 3782
Note:
See TracChangeset
for help on using the changeset viewer.