- Timestamp:
- Jul 7, 2019 9:23:05 AM (6 years ago)
- svn:sync-xref-src-repo-rev:
- 131863
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/VMM/VMMAll/IEMAllCImplVmxInstr.cpp.h
r79528 r79573 2561 2561 return iemVmxAbort(pVCpu, VMXABORT_SAVE_GUEST_MSRS); 2562 2562 2563 /* 2564 * Write the contents of the virtual-APIC page back into guest memory (shouldn't really fail). 2565 */ 2566 if (pVCpu->cpum.GstCtx.hwvirt.vmx.fVirtApicPageDirty) 2567 { 2568 Assert(pVmcs->u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW); 2569 int rc2 = PGMPhysSimpleWriteGCPhys(pVCpu->CTX_SUFF(pVM), pVmcs->u64AddrVirtApic.u, 2570 pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pvVirtApicPage), VMX_V_VIRT_APIC_SIZE); 2571 AssertRCReturn(rc2, rc2); 2572 2573 /* Clear the virtual-APIC page dirty bit now that it's written back to guest memory. */ 2574 pVCpu->cpum.GstCtx.hwvirt.vmx.fVirtApicPageDirty = false; 2575 } 2576 2563 2577 /* Clear any saved NMI-blocking state so we don't assert on next VM-entry (if it was in effect on the previous one). */ 2564 2578 pVCpu->cpum.GstCtx.hwvirt.fLocalForcedActions &= ~VMCPU_FF_BLOCK_NMIS; … … 3912 3926 PCVMXVVMCS pVmcs = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs); 3913 3927 Assert(pVmcs); 3914 3915 uint32_t uReg; 3916 Assert(offReg <= VMX_V_VIRT_APIC_SIZE - sizeof(uReg)); 3917 RTGCPHYS const GCPhysVirtApic = pVmcs->u64AddrVirtApic.u; 3918 int rc = PGMPhysSimpleReadGCPhys(pVCpu->CTX_SUFF(pVM), &uReg, GCPhysVirtApic + offReg, sizeof(uReg)); 3919 if (RT_FAILURE(rc)) 3920 { 3921 AssertMsgFailed(("Failed to read %u bytes at offset %#x of the virtual-APIC page at %#RGp\n", sizeof(uReg), offReg, 3922 GCPhysVirtApic)); 3923 uReg = 0; 3924 } 3928 Assert(offReg <= VMX_V_VIRT_APIC_SIZE - sizeof(uint32_t)); 3929 uint32_t const *pbVirtApicPage = (uint32_t const *)pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pvVirtApicPage); 3930 pbVirtApicPage += offReg; 3931 uint32_t const uReg = *pbVirtApicPage; 3925 3932 return uReg; 3926 3933 } … … 3938 3945 PCVMXVVMCS pVmcs = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs); 3939 3946 Assert(pVmcs); 3940 3941 uint64_t uReg; 3942 Assert(offReg <= VMX_V_VIRT_APIC_SIZE - sizeof(uReg)); 3943 RTGCPHYS const GCPhysVirtApic = pVmcs->u64AddrVirtApic.u; 3944 int rc = PGMPhysSimpleReadGCPhys(pVCpu->CTX_SUFF(pVM), &uReg, GCPhysVirtApic + offReg, sizeof(uReg)); 3945 if (RT_FAILURE(rc)) 3946 { 3947 AssertMsgFailed(("Failed to read %u bytes at offset %#x of the virtual-APIC page at %#RGp\n", sizeof(uReg), offReg, 3948 GCPhysVirtApic)); 3949 uReg = 0; 3950 } 3947 Assert(offReg <= VMX_V_VIRT_APIC_SIZE - sizeof(uint64_t)); 3948 uint64_t const *pbVirtApicPage = (uint64_t const *)pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pvVirtApicPage); 3949 pbVirtApicPage += offReg; 3950 uint64_t const uReg = *pbVirtApicPage; 3951 3951 return uReg; 3952 3952 } … … 3964 3964 PCVMXVVMCS pVmcs = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs); 3965 3965 Assert(pVmcs); 3966 Assert(offReg <= VMX_V_VIRT_APIC_SIZE - sizeof(uReg)); 3967 RTGCPHYS const GCPhysVirtApic = pVmcs->u64AddrVirtApic.u; 3968 int rc = PGMPhysSimpleWriteGCPhys(pVCpu->CTX_SUFF(pVM), GCPhysVirtApic + offReg, &uReg, sizeof(uReg)); 3969 if (RT_FAILURE(rc)) 3970 { 3971 AssertMsgFailed(("Failed to write %u bytes at offset %#x of the virtual-APIC page at %#RGp\n", sizeof(uReg), offReg, 3972 GCPhysVirtApic)); 3973 } 3966 Assert(offReg <= VMX_V_VIRT_APIC_SIZE - sizeof(uint32_t)); 3967 uint32_t *pbVirtApicPage = (uint32_t *)pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pvVirtApicPage); 3968 pbVirtApicPage += offReg; 3969 *pbVirtApicPage = uReg; 3970 pVCpu->cpum.GstCtx.hwvirt.vmx.fVirtApicPageDirty = true; 3974 3971 } 3975 3972 … … 3986 3983 PCVMXVVMCS pVmcs = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs); 3987 3984 Assert(pVmcs); 3988 Assert(offReg <= VMX_V_VIRT_APIC_SIZE - sizeof(uReg)); 3989 RTGCPHYS const GCPhysVirtApic = pVmcs->u64AddrVirtApic.u; 3990 int rc = PGMPhysSimpleWriteGCPhys(pVCpu->CTX_SUFF(pVM), GCPhysVirtApic + offReg, &uReg, sizeof(uReg)); 3991 if (RT_FAILURE(rc)) 3992 { 3993 AssertMsgFailed(("Failed to write %u bytes at offset %#x of the virtual-APIC page at %#RGp\n", sizeof(uReg), offReg, 3994 GCPhysVirtApic)); 3995 } 3985 Assert(offReg <= VMX_V_VIRT_APIC_SIZE - sizeof(uint64_t)); 3986 uint64_t *pbVirtApicPage = (uint64_t *)pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pvVirtApicPage); 3987 pbVirtApicPage += offReg; 3988 *pbVirtApicPage = uReg; 3989 pVCpu->cpum.GstCtx.hwvirt.vmx.fVirtApicPageDirty = true; 3996 3990 } 3997 3991 … … 4010 4004 PCVMXVVMCS pVmcs = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs); 4011 4005 Assert(pVmcs); 4012 uint32_t uReg; 4013 uint16_t const offVector = (uVector & UINT32_C(0xe0)) >> 1;4014 RTGCPHYS const GCPhysVirtApic = pVmcs->u64AddrVirtApic.u;4015 int rc = PGMPhysSimpleReadGCPhys(pVCpu->CTX_SUFF(pVM), &uReg, GCPhysVirtApic + offReg + offVector, sizeof(uReg));4016 if (RT_SUCCESS(rc))4017 { 4018 uint16_t const idxVectorBit = uVector & UINT32_C(0x1f);4019 uReg |= RT_BIT(idxVectorBit);4020 rc = PGMPhysSimpleWriteGCPhys(pVCpu->CTX_SUFF(pVM), GCPhysVirtApic + offReg + offVector, &uReg, sizeof(uReg));4021 if (RT_FAILURE(rc)) 4022 {4023 AssertMsgFailed(("Failed to set vector %#x in 256-bit register at %#x of the virtual-APIC page at %#RGp\n",4024 uVector, offReg, GCPhysVirtApic));4025 } 4026 }4027 else4028 {4029 AssertMsgFailed(("Failed to get vector %#x in 256-bit register at %#x of the virtual-APIC page at %#RGp\n", 4030 uVector, offReg, GCPhysVirtApic));4031 }4006 4007 /* Determine the vector offset within the chunk. */ 4008 uint32_t uReg; 4009 uint32_t *pbVirtApicPage = (uint32_t *)pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pvVirtApicPage); 4010 uint16_t const offVector = (uVector & UINT32_C(0xe0)) >> 1; 4011 4012 /* Read the chunk at the offset. */ 4013 pbVirtApicPage += offReg + offVector; 4014 uReg = *pbVirtApicPage; 4015 4016 /* Set the vector bit in the chunk. */ 4017 uint16_t const idxVectorBit = uVector & UINT32_C(0x1f); 4018 uReg |= RT_BIT(idxVectorBit); 4019 4020 /* Write back the chunk at the offset. */ 4021 pbVirtApicPage += offReg + offVector; 4022 *pbVirtApicPage = uReg; 4023 4024 /* Mark the page dirty. */ 4025 pVCpu->cpum.GstCtx.hwvirt.vmx.fVirtApicPageDirty = true; 4032 4026 } 4033 4027 … … 4046 4040 PCVMXVVMCS pVmcs = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs); 4047 4041 Assert(pVmcs); 4048 uint32_t uReg; 4042 4043 /* Determine the vector offset within the chunk. */ 4044 uint32_t uReg; 4045 uint32_t *pbVirtApicPage = (uint32_t *)pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pvVirtApicPage); 4049 4046 uint16_t const offVector = (uVector & UINT32_C(0xe0)) >> 1; 4050 RTGCPHYS const GCPhysVirtApic = pVmcs->u64AddrVirtApic.u; 4051 int rc = PGMPhysSimpleReadGCPhys(pVCpu->CTX_SUFF(pVM), &uReg, GCPhysVirtApic + offReg + offVector, sizeof(uReg)); 4052 if (RT_SUCCESS(rc)) 4053 { 4054 uint16_t const idxVectorBit = uVector & UINT32_C(0x1f); 4055 uReg &= ~RT_BIT(idxVectorBit); 4056 rc = PGMPhysSimpleWriteGCPhys(pVCpu->CTX_SUFF(pVM), GCPhysVirtApic + offReg + offVector, &uReg, sizeof(uReg)); 4057 if (RT_FAILURE(rc)) 4058 { 4059 AssertMsgFailed(("Failed to clear vector %#x in 256-bit register at %#x of the virtual-APIC page at %#RGp\n", 4060 uVector, offReg, GCPhysVirtApic)); 4061 } 4062 } 4063 else 4064 { 4065 AssertMsgFailed(("Failed to get vector %#x in 256-bit register at %#x of the virtual-APIC page at %#RGp\n", 4066 uVector, offReg, GCPhysVirtApic)); 4067 } 4047 4048 /* Read the chunk at the offset. */ 4049 pbVirtApicPage += offReg + offVector; 4050 uReg = *pbVirtApicPage; 4051 4052 /* Clear the vector bit in the chunk. */ 4053 uint16_t const idxVectorBit = uVector & UINT32_C(0x1f); 4054 uReg &= ~RT_BIT(idxVectorBit); 4055 4056 /* Write back the chunk at the offset. */ 4057 pbVirtApicPage += offReg + offVector; 4058 *pbVirtApicPage = uReg; 4059 4060 /* Mark the page dirty. */ 4061 pVCpu->cpum.GstCtx.hwvirt.vmx.fVirtApicPageDirty = true; 4068 4062 } 4069 4063 … … 6315 6309 IEM_VMX_VMENTRY_FAILED_RET(pVCpu, pszInstr, pszFailure, kVmxVDiag_Vmentry_AddrVirtApicPage); 6316 6310 6317 /* TPR threshold without virtual-interrupt delivery. */ 6318 if ( !(pVmcs->u32ProcCtls2 & VMX_PROC_CTLS2_VIRT_INT_DELIVERY) 6319 && (pVmcs->u32TprThreshold & ~VMX_TPR_THRESHOLD_MASK)) 6311 /* Read the virtual-APIC page. */ 6312 int rc = PGMPhysSimpleReadGCPhys(pVCpu->CTX_SUFF(pVM), pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pvVirtApicPage), 6313 GCPhysVirtApic, VMX_V_VIRT_APIC_SIZE); 6314 if (RT_SUCCESS(rc)) 6315 { /* likely */ } 6316 else 6317 IEM_VMX_VMENTRY_FAILED_RET(pVCpu, pszInstr, pszFailure, kVmxVDiag_Vmentry_VirtApicPagePtrReadPhys); 6318 6319 /* TPR threshold bits 31:4 MBZ without virtual-interrupt delivery. */ 6320 if ( !(pVmcs->u32TprThreshold & ~VMX_TPR_THRESHOLD_MASK) 6321 || (pVmcs->u32ProcCtls2 & VMX_PROC_CTLS2_VIRT_INT_DELIVERY)) 6322 { /* likely */ } 6323 else 6320 6324 IEM_VMX_VMENTRY_FAILED_RET(pVCpu, pszInstr, pszFailure, kVmxVDiag_Vmentry_TprThresholdRsvd); 6321 6325 6322 /* TPR threshold and VTPR. */6326 /* Verify TPR threshold and VTPR when both virtualize-APIC accesses and virtual-interrupt delivery aren't used. */ 6323 6327 if ( !(pVmcs->u32ProcCtls2 & VMX_PROC_CTLS2_VIRT_APIC_ACCESS) 6324 6328 && !(pVmcs->u32ProcCtls2 & VMX_PROC_CTLS2_VIRT_INT_DELIVERY)) 6325 6329 { 6326 6330 /* Read the VTPR from the virtual-APIC page. */ 6327 uint8_t u8VTpr; 6328 int rc = PGMPhysSimpleReadGCPhys(pVCpu->CTX_SUFF(pVM), &u8VTpr, GCPhysVirtApic + XAPIC_OFF_TPR, sizeof(u8VTpr)); 6329 if (RT_SUCCESS(rc)) 6330 { /* likely */ } 6331 else 6332 IEM_VMX_VMENTRY_FAILED_RET(pVCpu, pszInstr, pszFailure, kVmxVDiag_Vmentry_VirtApicPagePtrReadPhys); 6331 uint8_t const *pbVirtApicPage = (uint8_t const *)pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pvVirtApicPage); 6332 pbVirtApicPage += XAPIC_OFF_TPR; 6333 uint8_t const u8VTpr = *pbVirtApicPage; 6333 6334 6334 6335 /* Bits 3:0 of the TPR-threshold must not be greater than bits 7:4 of VTPR. */ … … 7386 7387 return rcStrict; 7387 7388 } 7389 7390 /* Clear virtual-APIC page dirty bit to ensure it's not stale due to prior, failed VM-exits. */ 7391 pVCpu->cpum.GstCtx.hwvirt.vmx.fVirtApicPageDirty = false; 7388 7392 7389 7393 /* We've now entered nested-guest execution. */
Note:
See TracChangeset
for help on using the changeset viewer.