Changeset 91419 in vbox for trunk/src/VBox/VMM/VMMAll/IEMAllCImplVmxInstr.cpp.h
- Timestamp:
- Sep 28, 2021 7:14:56 AM (3 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/VMM/VMMAll/IEMAllCImplVmxInstr.cpp.h
r91386 r91419 5626 5626 5627 5627 /** 5628 * Checks if the PDPTEs referenced by the nested-guest CR3 are valid as part of 5629 * VM-entry. 5630 * 5631 * @returns @c true if all PDPTEs are valid, @c false otherwise. 5628 * Checks guest PDPTEs as part of VM-entry. 5629 * 5632 5630 * @param pVCpu The cross context virtual CPU structure. 5633 5631 * @param pszInstr The VMX instruction name (for logging purposes). 5634 * @param pVmcs Pointer to the virtual VMCS. 5635 */ 5636 IEM_STATIC int iemVmxVmentryCheckGuestPdptesForCr3(PVMCPUCC pVCpu, const char *pszInstr, PVMXVVMCS pVmcs) 5637 { 5638 /* 5639 * Check PDPTEs. 5640 * See Intel spec. 4.4.1 "PDPTE Registers". 5641 */ 5642 uint64_t const uGuestCr3 = pVmcs->u64GuestCr3.u & X86_CR3_PAE_PAGE_MASK; 5643 const char *const pszFailure = "VM-exit"; 5644 5645 X86PDPE aPdptes[X86_PG_PAE_PDPE_ENTRIES]; 5646 int rc = PGMPhysSimpleReadGCPhys(pVCpu->CTX_SUFF(pVM), (void *)&aPdptes[0], uGuestCr3, sizeof(aPdptes)); 5647 if (RT_SUCCESS(rc)) 5648 { 5649 for (unsigned iPdpte = 0; iPdpte < RT_ELEMENTS(aPdptes); iPdpte++) 5650 { 5651 if ( !(aPdptes[iPdpte].u & X86_PDPE_P) 5652 || !(aPdptes[iPdpte].u & X86_PDPE_PAE_MBZ_MASK)) 5632 */ 5633 IEM_STATIC int iemVmxVmentryCheckGuestPdptes(PVMCPUCC pVCpu, const char *pszInstr) 5634 { 5635 /* 5636 * Guest PDPTEs. 5637 * See Intel spec. 26.3.1.5 "Checks on Guest Page-Directory-Pointer-Table Entries". 5638 */ 5639 PVMXVVMCS const pVmcs = &pVCpu->cpum.GstCtx.hwvirt.vmx.Vmcs; 5640 const char * const pszFailure = "VM-exit"; 5641 5642 bool const fGstInLongMode = RT_BOOL(pVmcs->u32EntryCtls & VMX_ENTRY_CTLS_IA32E_MODE_GUEST); 5643 if ( !fGstInLongMode 5644 && (pVmcs->u64GuestCr4.u & X86_CR4_PAE) 5645 && (pVmcs->u64GuestCr0.u & X86_CR0_PG)) 5646 { 5647 /* Get the PDPTEs. */ 5648 X86PDPE aPdpes[X86_PG_PAE_PDPE_ENTRIES]; 5649 #ifdef VBOX_WITH_NESTED_HWVIRT_VMX_EPT 5650 if (pVmcs->u32ProcCtls2 & VMX_PROC_CTLS2_EPT) 5651 { 5652 aPdpes[0].u = pVmcs->u64GuestPdpte0.u; 5653 aPdpes[1].u = pVmcs->u64GuestPdpte1.u; 5654 aPdpes[2].u = pVmcs->u64GuestPdpte2.u; 5655 aPdpes[3].u = pVmcs->u64GuestPdpte3.u; 5656 } 5657 else 5658 #endif 5659 { 5660 uint64_t const uGuestCr3 = pVmcs->u64GuestCr3.u & X86_CR3_PAE_PAGE_MASK; 5661 int const rc = PGMPhysSimpleReadGCPhys(pVCpu->CTX_SUFF(pVM), (void *)&aPdpes[0], uGuestCr3, sizeof(aPdpes)); 5662 if (RT_FAILURE(rc)) 5663 { 5664 iemVmxVmcsSetExitQual(pVCpu, VMX_ENTRY_FAIL_QUAL_PDPTE); 5665 IEM_VMX_VMENTRY_FAILED_RET(pVCpu, pszInstr, pszFailure, kVmxVDiag_Vmentry_GuestPdpteCr3ReadPhys); 5666 } 5667 } 5668 5669 /* Check validity of the PDPTEs. */ 5670 for (unsigned idx = 0; idx < RT_ELEMENTS(aPdpes); idx++) 5671 { 5672 if ( !(aPdpes[idx].u & X86_PDPE_P) 5673 || !(aPdpes[idx].u & X86_PDPE_PAE_MBZ_MASK)) 5653 5674 { /* likely */ } 5654 5675 else 5655 5676 { 5677 VMXVDIAG const enmDiag = iemVmxGetDiagVmentryPdpteRsvd(idx); 5656 5678 iemVmxVmcsSetExitQual(pVCpu, VMX_ENTRY_FAIL_QUAL_PDPTE); 5657 VMXVDIAG const enmDiag = iemVmxGetDiagVmentryPdpteRsvd(iPdpte);5658 5679 IEM_VMX_VMENTRY_FAILED_RET(pVCpu, pszInstr, pszFailure, enmDiag); 5659 5680 } 5660 5681 } 5661 5682 } 5662 else 5663 { 5664 iemVmxVmcsSetExitQual(pVCpu, VMX_ENTRY_FAIL_QUAL_PDPTE); 5665 IEM_VMX_VMENTRY_FAILED_RET(pVCpu, pszInstr, pszFailure, kVmxVDiag_Vmentry_GuestPdpteCr3ReadPhys); 5666 } 5667 5683 5684 NOREF(pszInstr); 5668 5685 NOREF(pszFailure); 5669 NOREF(pszInstr); 5670 return rc; 5671 } 5672 5673 5674 /** 5675 * Checks guest PDPTEs as part of VM-entry. 5676 * 5677 * @param pVCpu The cross context virtual CPU structure. 5678 * @param pszInstr The VMX instruction name (for logging purposes). 5679 */ 5680 DECLINLINE(int) iemVmxVmentryCheckGuestPdptes(PVMCPUCC pVCpu, const char *pszInstr) 5681 { 5682 /* 5683 * Guest PDPTEs. 5684 * See Intel spec. 26.3.1.5 "Checks on Guest Page-Directory-Pointer-Table Entries". 5685 */ 5686 PVMXVVMCS const pVmcs = &pVCpu->cpum.GstCtx.hwvirt.vmx.Vmcs; 5687 bool const fGstInLongMode = RT_BOOL(pVmcs->u32EntryCtls & VMX_ENTRY_CTLS_IA32E_MODE_GUEST); 5688 5689 /* Check PDPTes if the VM-entry is to a guest using PAE paging. */ 5690 int rc; 5691 if ( !fGstInLongMode 5692 && (pVmcs->u64GuestCr4.u & X86_CR4_PAE) 5693 && (pVmcs->u64GuestCr0.u & X86_CR0_PG)) 5694 { 5695 /* 5696 * We don't support nested-paging for nested-guests yet. 5697 * 5698 * Without nested-paging for nested-guests, PDPTEs in the VMCS are not used, 5699 * rather we need to check the PDPTEs referenced by the guest CR3. 5700 */ 5701 rc = iemVmxVmentryCheckGuestPdptesForCr3(pVCpu, pszInstr, pVmcs); 5702 } 5703 else 5704 rc = VINF_SUCCESS; 5705 return rc; 5686 return VINF_SUCCESS; 5706 5687 } 5707 5688
Note:
See TracChangeset
for help on using the changeset viewer.