- Timestamp:
- Oct 21, 2021 4:26:49 PM (3 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/VMM/VMMAll/IEMAllCImplVmxInstr.cpp.h
r91971 r91974 5888 5888 5889 5889 5890 #ifdef VBOX_WITH_NESTED_HWVIRT_VMX_EPT 5891 /** 5892 * Checks the EPT pointer VMCS field as part of VM-entry. 5893 * 5894 * @returns VBox status code. 5895 * @param pVCpu The cross context virtual CPU structure. 5896 * @param penmVmxDiag Where to store the diagnostic reason on failure (not 5897 * updated on success). Optional, can be NULL. 5898 */ 5899 IEM_STATIC int iemVmxVmentryCheckEptPtr(PVMCPUCC pVCpu, VMXVDIAG *penmVmxDiag) 5900 { 5901 VMXVDIAG enmVmxDiag; 5902 PCVMXVVMCS const pVmcs = &pVCpu->cpum.GstCtx.hwvirt.vmx.Vmcs; 5903 5904 /* Reserved bits. */ 5905 uint8_t const cMaxPhysAddrWidth = IEM_GET_GUEST_CPU_FEATURES(pVCpu)->cMaxPhysAddrWidth; 5906 uint64_t const fValidMask = VMX_EPTP_VALID_MASK & ~(UINT64_MAX << cMaxPhysAddrWidth); 5907 if (pVmcs->u64EptPtr.u & fValidMask) 5908 { 5909 /* Memory Type. */ 5910 uint64_t const fCaps = pVCpu->cpum.GstCtx.hwvirt.vmx.Msrs.u64EptVpidCaps; 5911 uint8_t const fMemType = RT_BF_GET(pVmcs->u64EptPtr.u, VMX_BF_EPTP_MEMTYPE); 5912 if ( ( fMemType == VMX_EPTP_MEMTYPE_WB 5913 && RT_BF_GET(fCaps, VMX_BF_EPT_VPID_CAP_MEMTYPE_WB)) 5914 || ( fMemType == VMX_EPTP_MEMTYPE_UC 5915 && RT_BF_GET(fCaps, VMX_BF_EPT_VPID_CAP_MEMTYPE_UC))) 5916 { 5917 /* 5918 * Page walk length (PML4). 5919 * Intel used to specify bit 7 of IA32_VMX_EPT_VPID_CAP as page walk length 5920 * of 5 but that seems to be removed from the latest specs. leaving only PML4 5921 * as the maximum supported page-walk level hence we hardcode it as 3 (1 less than 4) 5922 */ 5923 Assert(RT_BF_GET(fCaps, VMX_BF_EPT_VPID_CAP_PAGE_WALK_LENGTH_4)); 5924 if (RT_BF_GET(pVmcs->u64EptPtr.u, VMX_BF_EPTP_PAGE_WALK_LENGTH) == 3) 5925 { 5926 /* Access and dirty bits support in EPT structures. */ 5927 if ( !RT_BF_GET(pVmcs->u64EptPtr.u, VMX_BF_EPTP_ACCESS_DIRTY) 5928 || RT_BF_GET(fCaps, VMX_BF_EPT_VPID_CAP_ACCESS_DIRTY)) 5929 return VINF_SUCCESS; 5930 5931 enmVmxDiag = kVmxVDiag_Vmentry_EptpAccessDirty; 5932 } 5933 else 5934 enmVmxDiag = kVmxVDiag_Vmentry_EptpPageWalkLength; 5935 } 5936 else 5937 enmVmxDiag = kVmxVDiag_Vmentry_EptpMemType; 5938 } 5939 else 5940 enmVmxDiag = kVmxVDiag_Vmentry_EptpRsvd; 5941 5942 if (penmVmxDiag) 5943 *penmVmxDiag = enmVmxDiag; 5944 return VERR_VMX_VMENTRY_FAILED; 5945 } 5946 #endif 5947 5948 5890 5949 /** 5891 5950 * Checks VMCS controls fields as part of VM-entry. … … 6097 6156 if (pVmcs->u32ProcCtls2 & VMX_PROC_CTLS2_EPT) 6098 6157 { 6099 /* Reserved bits. */ 6100 uint8_t const cMaxPhysAddrWidth = IEM_GET_GUEST_CPU_FEATURES(pVCpu)->cMaxPhysAddrWidth; 6101 uint64_t const fValidMask = VMX_EPTP_VALID_MASK & ~(UINT64_MAX << cMaxPhysAddrWidth); 6102 if (pVmcs->u64EptPtr.u & fValidMask) 6158 VMXVDIAG enmVmxDiag; 6159 rc = iemVmxVmentryCheckEptPtr(pVCpu, &enmVmxDiag); 6160 if (RT_SUCCESS(rc)) 6103 6161 { /* likely */ } 6104 6162 else 6105 IEM_VMX_VMENTRY_FAILED_RET(pVCpu, pszInstr, pszFailure, kVmxVDiag_Vmentry_EptpRsvd); 6106 6107 /* Memory Type. */ 6108 uint64_t const fCaps = pVCpu->cpum.GstCtx.hwvirt.vmx.Msrs.u64EptVpidCaps; 6109 uint8_t const fMemType = RT_BF_GET(pVmcs->u64EptPtr.u, VMX_BF_EPTP_MEMTYPE); 6110 if ( ( fMemType == VMX_EPTP_MEMTYPE_WB 6111 && RT_BF_GET(fCaps, VMX_BF_EPT_VPID_CAP_MEMTYPE_WB)) 6112 || ( fMemType == VMX_EPTP_MEMTYPE_UC 6113 && RT_BF_GET(fCaps, VMX_BF_EPT_VPID_CAP_MEMTYPE_UC))) 6114 { /* likely */ } 6115 else 6116 IEM_VMX_VMENTRY_FAILED_RET(pVCpu, pszInstr, pszFailure, kVmxVDiag_Vmentry_EptpMemType); 6117 6118 /* 6119 * Page walk length (PML4). 6120 * Intel used to specify bit 7 of IA32_VMX_EPT_VPID_CAP as page walk length 6121 * of 5 but that seems to be removed from the latest specs. leaving only PML4 6122 * as the maximum supported page-walk level hence we hardcode it as 3 (1 less than 4) 6123 */ 6124 Assert(RT_BF_GET(fCaps, VMX_BF_EPT_VPID_CAP_PAGE_WALK_LENGTH_4)); 6125 if (RT_BF_GET(pVmcs->u64EptPtr.u, VMX_BF_EPTP_PAGE_WALK_LENGTH) == 3) 6126 { /* likely */ } 6127 else 6128 IEM_VMX_VMENTRY_FAILED_RET(pVCpu, pszInstr, pszFailure, kVmxVDiag_Vmentry_EptpPageWalkLength); 6129 6130 /* Access and dirty bits support in EPT structures. */ 6131 if ( !RT_BF_GET(pVmcs->u64EptPtr.u, VMX_BF_EPTP_ACCESS_DIRTY) 6132 || RT_BF_GET(fCaps, VMX_BF_EPT_VPID_CAP_ACCESS_DIRTY)) 6133 { /* likely */ } 6134 else 6135 IEM_VMX_VMENTRY_FAILED_RET(pVCpu, pszInstr, pszFailure, kVmxVDiag_Vmentry_EptpAccessDirty); 6163 IEM_VMX_VMENTRY_FAILED_RET(pVCpu, pszInstr, pszFailure, enmVmxDiag); 6136 6164 } 6137 6165 #else
Note:
See TracChangeset
for help on using the changeset viewer.