Changeset 92685 in vbox for trunk/src/VBox
- Timestamp:
- Dec 2, 2021 5:59:39 AM (3 years ago)
- Location:
- trunk/src/VBox/VMM
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/VMM/VMMAll/IEMAll.cpp
r92626 r92685 439 439 440 440 /** 441 * Invokes the VMX VM-exit handler for EPT faults. 442 */ 443 # define IEM_VMX_VMEXIT_EPT_RET(a_pVCpu, a_pPtWalk, a_fAccess, a_fSlatFail, a_cbInstr) \ 444 do { return iemVmxVmexitEpt(a_pVCpu, a_pPtWalk, a_fAccess, a_fSlatFail, a_cbInstr); } while (0) 445 446 /** 441 447 * Invokes the VMX VM-exit handler. 442 448 */ … … 454 460 # define IEM_VMX_VMEXIT_TASK_SWITCH_RET(a_pVCpu, a_enmTaskSwitch, a_SelNewTss, a_cbInstr) do { return VERR_VMX_IPE_1; } while (0) 455 461 # define IEM_VMX_VMEXIT_MWAIT_RET(a_pVCpu, a_fMonitorArmed, a_cbInstr) do { return VERR_VMX_IPE_1; } while (0) 462 # define IEM_VMX_VMEXIT_EPT_RET(a_pVCpu, a_pPtWalk, a_fAccess, a_fSlatFail, a_cbInstr) do { return VERR_VMX_IPE_1; } while (0) 456 463 # define IEM_VMX_VMEXIT_TRIPLE_FAULT_RET(a_pVCpu, a_uExitReason, a_uExitQual) do { return VERR_VMX_IPE_1; } while (0) 457 464 … … 980 987 IEM_STATIC VBOXSTRICTRC iemVmxVirtApicAccessMsrRead(PVMCPUCC pVCpu, uint32_t idMsr, uint64_t *pu64Value); 981 988 IEM_STATIC VBOXSTRICTRC iemVmxVirtApicAccessMsrWrite(PVMCPUCC pVCpu, uint32_t idMsr, uint64_t u64Value); 989 IEM_STATIC VBOXSTRICTRC iemVmxVmexitEpt(PVMCPUCC pVCpu, PPGMPTWALK pWalk, uint32_t fAccess, uint32_t fSlatFail, uint8_t cbInstr); 982 990 #endif 983 991 … … 1433 1441 { 1434 1442 Log(("iemInitDecoderAndPrefetchOpcodes: %RGv - rc=%Rrc\n", GCPtrPC, rc)); 1443 #ifdef VBOX_WITH_NESTED_HWVIRT_VMX_EPT 1444 if (Walk.fFailed & PGM_WALKFAIL_EPT) 1445 { 1446 Assert(IEM_VMX_IS_NON_ROOT_MODE(pVCpu)); 1447 IEM_VMX_VMEXIT_EPT_RET(pVCpu, &Walk, IEM_ACCESS_INSTRUCTION, IEM_SLAT_FAIL_LINEAR_TO_PHYS_ADDR, 0 /* cbInstr */); 1448 } 1449 #endif 1435 1450 return iemRaisePageFault(pVCpu, GCPtrPC, IEM_ACCESS_INSTRUCTION, rc); 1436 1451 } -
trunk/src/VBox/VMM/VMMAll/IEMAllCImplVmxInstr.cpp.h
r92626 r92685 3685 3685 3686 3686 3687 #ifdef VBOX_WITH_NESTED_HWVIRT_VMX_EPT3688 3687 /** 3689 3688 * VMX VM-exit handler for EPT violation. 3690 3689 * 3691 * @param pVCpu The cross context virtual CPU structure. 3692 * @param fAccess The access causing the EPT violation, IEM_ACCESS_XXX. 3693 * @param fEptAccess The EPT paging structure bits. 3694 * @param GCPhysAddr The physical address causing the EPT violation. 3695 * @param GCPtrAddr The linear address causing the EPT violation. 3696 * @param cbInstr The VM-exit instruction length. 3697 */ 3698 IEM_STATIC VBOXSTRICTRC iemVmxVmexitEptViolation(PVMCPUCC pVCpu, uint32_t fAccess, uint64_t fEptAccess, RTGCPHYS GCPhysAddr, 3699 uint64_t GCPtrAddr, bool fLinearAddrValid, uint8_t cbInstr) 3690 * @param pVCpu The cross context virtual CPU structure. 3691 * @param fAccess The access causing the EPT violation, IEM_ACCESS_XXX. 3692 * @param fSlatFail The SLAT failure info, IEM_SLAT_FAIL_XXX. 3693 * @param fEptAccess The EPT paging structure bits. 3694 * @param GCPhysAddr The physical address causing the EPT violation. 3695 * @param fIsLinearAddrValid Whether translation of a linear address caused this 3696 * EPT violation. If @c false, GCPtrAddr must be 0. 3697 * @param GCPtrAddr The linear address causing the EPT violation. 3698 * @param cbInstr The VM-exit instruction length. 3699 */ 3700 IEM_STATIC VBOXSTRICTRC iemVmxVmexitEptViolation(PVMCPUCC pVCpu, uint32_t fAccess, uint32_t fSlatFail, uint64_t fEptAccess, 3701 RTGCPHYS GCPhysAddr, bool fLinearAddrValid, uint64_t GCPtrAddr, uint8_t cbInstr) 3700 3702 { 3701 3703 /* … … 3709 3711 uint8_t const fSupportsAccessDirty = fCaps & MSR_IA32_VMX_EPT_VPID_CAP_ACCESS_DIRTY; 3710 3712 3711 uint8_t const fDataRead = ((fAccess & IEM_ACCESS_DATA_R) == IEM_ACCESS_DATA_R) | fSupportsAccessDirty; 3712 uint8_t const fDataWrite = ((fAccess & IEM_ACCESS_DATA_RW) == IEM_ACCESS_DATA_RW) | fSupportsAccessDirty; 3713 uint8_t const fInstrFetch = (fAccess & IEM_ACCESS_INSTRUCTION) == IEM_ACCESS_INSTRUCTION; 3714 bool const fEptRead = RT_BOOL(fEptAccess & EPT_E_READ); 3715 bool const fEptWrite = RT_BOOL(fEptAccess & EPT_E_WRITE); 3716 bool const fEptExec = RT_BOOL(fEptAccess & EPT_E_EXECUTE); 3717 bool const fNmiUnblocking = pVCpu->cpum.GstCtx.hwvirt.vmx.fNmiUnblockingIret; 3718 3719 uint64_t const u64ExitQual = RT_BF_MAKE(VMX_BF_EXIT_QUAL_EPT_ACCESS_READ, fDataRead) 3720 | RT_BF_MAKE(VMX_BF_EXIT_QUAL_EPT_ACCESS_WRITE, fDataWrite) 3721 | RT_BF_MAKE(VMX_BF_EXIT_QUAL_EPT_ACCESS_INSTR_FETCH, fInstrFetch) 3722 | RT_BF_MAKE(VMX_BF_EXIT_QUAL_EPT_ENTRY_READ, fEptRead) 3723 | RT_BF_MAKE(VMX_BF_EXIT_QUAL_EPT_ENTRY_WRITE, fEptWrite) 3724 | RT_BF_MAKE(VMX_BF_EXIT_QUAL_EPT_ENTRY_EXECUTE, fEptExec) 3725 | RT_BF_MAKE(VMX_BF_EXIT_QUAL_EPT_LINEAR_ADDR_VALID, fLinearAddrValid) 3726 | RT_BF_MAKE(VMX_BF_EXIT_QUAL_EPT_NMI_UNBLOCK_IRET, fNmiUnblocking); 3727 3728 /** @todo bit 8 of Exit Qualification! 3729 * If the access causing the EPT violation is to a guest-physical address that is 3730 * the translation of a linear address. 3731 * - OR - 3732 * if the access causing the EPT violation is to a paging-structure entry as part 3733 * of a page walk or the update of an accessed or dirty bit. 3734 * 3735 * Caller needs to be able to distinguish this... */ 3713 uint8_t const fDataRead = ((fAccess & IEM_ACCESS_DATA_R) == IEM_ACCESS_DATA_R) | fSupportsAccessDirty; 3714 uint8_t const fDataWrite = ((fAccess & IEM_ACCESS_DATA_RW) == IEM_ACCESS_DATA_RW) | fSupportsAccessDirty; 3715 uint8_t const fInstrFetch = (fAccess & IEM_ACCESS_INSTRUCTION) == IEM_ACCESS_INSTRUCTION; 3716 bool const fEptRead = RT_BOOL(fEptAccess & EPT_E_READ); 3717 bool const fEptWrite = RT_BOOL(fEptAccess & EPT_E_WRITE); 3718 bool const fEptExec = RT_BOOL(fEptAccess & EPT_E_EXECUTE); 3719 bool const fNmiUnblocking = pVCpu->cpum.GstCtx.hwvirt.vmx.fNmiUnblockingIret; 3720 bool const fLinearToPhysAddr = fLinearAddrValid & RT_BOOL(fSlatFail & IEM_SLAT_FAIL_LINEAR_TO_PHYS_ADDR); 3721 3722 uint64_t const u64ExitQual = RT_BF_MAKE(VMX_BF_EXIT_QUAL_EPT_ACCESS_READ, fDataRead) 3723 | RT_BF_MAKE(VMX_BF_EXIT_QUAL_EPT_ACCESS_WRITE, fDataWrite) 3724 | RT_BF_MAKE(VMX_BF_EXIT_QUAL_EPT_ACCESS_INSTR_FETCH, fInstrFetch) 3725 | RT_BF_MAKE(VMX_BF_EXIT_QUAL_EPT_ENTRY_READ, fEptRead) 3726 | RT_BF_MAKE(VMX_BF_EXIT_QUAL_EPT_ENTRY_WRITE, fEptWrite) 3727 | RT_BF_MAKE(VMX_BF_EXIT_QUAL_EPT_ENTRY_EXECUTE, fEptExec) 3728 | RT_BF_MAKE(VMX_BF_EXIT_QUAL_EPT_LINEAR_ADDR_VALID, fLinearAddrValid) 3729 | RT_BF_MAKE(VMX_BF_EXIT_QUAL_EPT_LINEAR_TO_PHYS_ADDR, fLinearToPhysAddr) 3730 | RT_BF_MAKE(VMX_BF_EXIT_QUAL_EPT_NMI_UNBLOCK_IRET, fNmiUnblocking); 3736 3731 3737 3732 #ifdef VBOX_STRICT … … 3741 3736 Assert(!(fCaps & MSR_IA32_VMX_EPT_VPID_CAP_SUPER_SHW_STACK)); /* Supervisor shadow stack control not supported. */ 3742 3737 Assert(!(RT_BF_GET(fMiscCaps, VMX_BF_MISC_INTEL_PT))); /* Intel PT not supported. */ 3743 Assert(!(RT_BF_GET(fMiscCaps, VMX_BF_MISC_INTEL_PT))); /* Intel PT not supported. */3744 3738 Assert(!(fProcCtls2 & VMX_PROC_CTLS2_MODE_BASED_EPT_PERM)); /* Mode-based execute control not supported. */ 3745 3739 #endif … … 3751 3745 return iemVmxVmexit(pVCpu, VMX_EXIT_EPT_VIOLATION, u64ExitQual); 3752 3746 } 3753 #endif 3747 3748 3749 /** 3750 * VMX VM-exit handler for EPT-induced VM-exits. 3751 * 3752 * @param pVCpu The cross context virtual CPU structure. 3753 * @param pWalk The page walk info. 3754 * @param fAccess The access causing the EPT event, IEM_ACCESS_XXX. 3755 * @param fSlatFail Additional SLAT info, IEM_SLAT_FAIL_XXX. 3756 * @param cbInstr The VM-exit instruction length if applicable. Pass 0 if not 3757 * applicable. 3758 */ 3759 IEM_STATIC VBOXSTRICTRC iemVmxVmexitEpt(PVMCPUCC pVCpu, PPGMPTWALK pWalk, uint32_t fAccess, uint32_t fSlatFail, 3760 uint8_t cbInstr) 3761 { 3762 Assert(pWalk->fIsSlat); 3763 Assert(pWalk->fFailed & PGM_WALKFAIL_EPT); 3764 Assert(!IEM_GET_GUEST_CPU_FEATURES(pVCpu)->fVmxEptXcptVe); /* #VE exceptions not supported. */ 3765 Assert(!(pWalk->fFailed & PGM_WALKFAIL_EPT_VIOLATION_CONVERTIBLE)); /* Without #VE, convertible violations not possible. */ 3766 3767 if (pWalk->fFailed & PGM_WALKFAIL_EPT_VIOLATION) 3768 { 3769 uint64_t const fEptAccess = (pWalk->fEffective & PGM_PTATTRS_EPT_MASK) >> PGM_PTATTRS_EPT_SHIFT; 3770 return iemVmxVmexitEptViolation(pVCpu, fAccess, fSlatFail, fEptAccess, pWalk->GCPhysNested, pWalk->fIsLinearAddrValid, 3771 pWalk->GCPtr, cbInstr); 3772 } 3773 else 3774 { 3775 Assert(pWalk->fFailed & PGM_WALKFAIL_EPT_MISCONFIG); 3776 /** @todo Do EPT misconfig. */ 3777 return VERR_NOT_IMPLEMENTED; 3778 } 3779 } 3754 3780 3755 3781 -
trunk/src/VBox/VMM/VMMAll/PGMAllGstSlatEpt.cpp.h
r92541 r92685 47 47 DECLINLINE(int) PGM_GST_SLAT_NAME_EPT(WalkReturnNotPresent)(PCVMCPUCC pVCpu, PPGMPTWALK pWalk, uint64_t uEntry, uint8_t uLevel) 48 48 { 49 static PGM SLATFAIL const s_aEptViolation[] = { PGMSLATFAIL_EPT_VIOLATION, PGMSLATFAIL_EPT_VIOLATION_CONVERTIBLE };49 static PGMWALKFAIL const s_afEptViolations[] = { PGM_WALKFAIL_EPT_VIOLATION, PGM_WALKFAIL_EPT_VIOLATION_CONVERTIBLE }; 50 50 uint8_t const fEptVeSupported = pVCpu->CTX_SUFF(pVM)->cpum.ro.GuestFeatures.fVmxEptXcptVe; 51 51 uint8_t const idxViolationType = fEptVeSupported & !RT_BF_GET(uEntry, VMX_BF_EPT_PT_SUPPRESS_VE); … … 53 53 pWalk->fNotPresent = true; 54 54 pWalk->uLevel = uLevel; 55 pWalk-> enmSlatFail = s_aEptViolation[idxViolationType];55 pWalk->fFailed |= s_afEptViolations[idxViolationType]; 56 56 return VERR_PAGE_TABLE_NOT_PRESENT; 57 57 } … … 63 63 pWalk->fBadPhysAddr = true; 64 64 pWalk->uLevel = uLevel; 65 pWalk-> enmSlatFail = PGMSLATFAIL_EPT_VIOLATION;65 pWalk->fFailed |= PGM_WALKFAIL_EPT_VIOLATION; 66 66 return VERR_PAGE_TABLE_NOT_PRESENT; 67 67 } 68 68 69 69 70 DECLINLINE(int) PGM_GST_SLAT_NAME_EPT(WalkReturnRsvdError)(PVMCPUCC pVCpu, PPGMPTWALK pWalk, uint8_t uLevel) 71 { 72 NOREF(pVCpu); 70 DECLINLINE(int) PGM_GST_SLAT_NAME_EPT(WalkReturnRsvdError)(PVMCPUCC pVCpu, PPGMPTWALK pWalk, uint64_t uEntry, uint8_t uLevel) 71 { 72 static PGMWALKFAIL const s_afEptViolations[] = { PGM_WALKFAIL_EPT_VIOLATION, PGM_WALKFAIL_EPT_VIOLATION_CONVERTIBLE }; 73 uint8_t const fEptVeSupported = pVCpu->CTX_SUFF(pVM)->cpum.ro.GuestFeatures.fVmxEptXcptVe; 74 uint8_t const fConvertible = RT_BOOL(uLevel == 1 || (uEntry & EPT_E_BIT_LEAF)); 75 uint8_t const idxViolationType = fEptVeSupported & fConvertible & !RT_BF_GET(uEntry, VMX_BF_EPT_PT_SUPPRESS_VE); 76 73 77 pWalk->fRsvdError = true; 74 78 pWalk->uLevel = uLevel; 75 pWalk-> enmSlatFail = PGMSLATFAIL_EPT_MISCONFIG;79 pWalk->fFailed |= s_afEptViolations[idxViolationType]; 76 80 return VERR_PAGE_TABLE_NOT_PRESENT; 77 81 } 78 82 79 83 84 /** 85 * Performs an EPT walk (second-level address translation). 86 * 87 * @returns VBox status code. 88 * @retval VINF_SUCCESS on success. 89 * @retval VERR_PAGE_TABLE_NOT_PRESENT on failure. Check pWalk for details. 90 * 91 * @param pVCpu The cross context virtual CPU structure of the calling EMT. 92 * @param GCPhysNested The nested-guest physical address to walk. 93 * @param fIsLinearAddrValid Whether the linear-address in @c GCPtrNested caused 94 * this page walk. If this is false, @c GCPtrNested 95 * must be 0. 96 * @param GCPtrNested The nested-guest linear address that caused this 97 * page walk. 98 * @param pWalk The page walk info. 99 * @param pGstWalk The guest mode specific page walk info. 100 */ 80 101 DECLINLINE(int) PGM_GST_SLAT_NAME_EPT(Walk)(PVMCPUCC pVCpu, RTGCPHYS GCPhysNested, bool fIsLinearAddrValid, RTGCPTR GCPtrNested, 81 102 PPGMPTWALK pWalk, PGSTPTWALK pGstWalk) 82 103 { 104 Assert(fIsLinearAddrValid || GCPtrNested == 0); 105 83 106 /* 84 107 * Init walk structures. … … 143 166 144 167 if (RT_LIKELY(GST_IS_PML4E_VALID(pVCpu, Pml4e))) { /* likely */ } 145 else return PGM_GST_SLAT_NAME_EPT(WalkReturnRsvdError)(pVCpu, pWalk, 4);168 else return PGM_GST_SLAT_NAME_EPT(WalkReturnRsvdError)(pVCpu, pWalk, Pml4e.u, 4); 146 169 147 170 Assert(!pVCpu->CTX_SUFF(pVM)->cpum.ro.GuestFeatures.fVmxModeBasedExecuteEpt); … … 212 235 return VINF_SUCCESS; 213 236 } 214 else return PGM_GST_SLAT_NAME_EPT(WalkReturnRsvdError)(pVCpu, pWalk, 3);237 else return PGM_GST_SLAT_NAME_EPT(WalkReturnRsvdError)(pVCpu, pWalk, Pdpte.u, 3); 215 238 216 239 int const rc = PGM_GCPHYS_2_PTR_BY_VMCPU(pVCpu, Pdpte.u & EPT_PDPTE_PG_MASK, &pGstWalk->pPd); … … 270 293 return VINF_SUCCESS; 271 294 } 272 else return PGM_GST_SLAT_NAME_EPT(WalkReturnRsvdError)(pVCpu, pWalk, 2);295 else return PGM_GST_SLAT_NAME_EPT(WalkReturnRsvdError)(pVCpu, pWalk, Pde.u, 2); 273 296 274 297 int const rc = PGM_GCPHYS_2_PTR_BY_VMCPU(pVCpu, GST_GET_PDE_GCPHYS(Pde), &pGstWalk->pPt); … … 292 315 { /* likely*/ } 293 316 else 294 return PGM_GST_SLAT_NAME_EPT(WalkReturnRsvdError)(pVCpu, pWalk, 1);317 return PGM_GST_SLAT_NAME_EPT(WalkReturnRsvdError)(pVCpu, pWalk, Pte.u, 1); 295 318 296 319 uint64_t const fEptAttrs = Pte.u & EPT_PTE_ATTR_MASK; -
trunk/src/VBox/VMM/include/IEMInternal.h
r91263 r92685 921 921 } IEMACCESSCRX; 922 922 923 # ifdef VBOX_WITH_NESTED_HWVIRT_VMX 923 #ifdef VBOX_WITH_NESTED_HWVIRT_VMX 924 /** @name IEM_SLAT_FAIL_XXX - Second-level address translation failure information. 925 * 926 * These flags provide further context to SLAT page-walk failures that could not be 927 * determined by PGM (e.g, PGM is not privy to memory access permissions). 928 * 929 * @{ 930 */ 931 /** Translating a nested-guest linear address failed accessing a nested-guest 932 * physical address. */ 933 # define IEM_SLAT_FAIL_LINEAR_TO_PHYS_ADDR RT_BIT_32(0) 934 /** Translating a nested-guest linear address failed accessing a 935 * paging-structure entry. */ 936 # define IEM_SLAT_FAIL_LINEAR_TO_PAGE_TABLE RT_BIT_32(1) 937 /** @} */ 938 924 939 PGM_ALL_CB2_PROTO(FNPGMPHYSHANDLER) iemVmxApicAccessPageHandler; 925 # 940 #endif 926 941 927 942 /**
Note:
See TracChangeset
for help on using the changeset viewer.