VirtualBox

Changeset 79573 in vbox for trunk/src


Ignore:
Timestamp:
Jul 7, 2019 9:23:05 AM (6 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
131863
Message:

VMM/IEM: Nested VMX: bugref:9180 Use a separate HC page for the guest's virtual-APIC page.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/VMM/VMMAll/IEMAllCImplVmxInstr.cpp.h

    r79528 r79573  
    25612561            return iemVmxAbort(pVCpu, VMXABORT_SAVE_GUEST_MSRS);
    25622562
     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
    25632577        /* Clear any saved NMI-blocking state so we don't assert on next VM-entry (if it was in effect on the previous one). */
    25642578        pVCpu->cpum.GstCtx.hwvirt.fLocalForcedActions &= ~VMCPU_FF_BLOCK_NMIS;
     
    39123926    PCVMXVVMCS pVmcs = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
    39133927    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;
    39253932    return uReg;
    39263933}
     
    39383945    PCVMXVVMCS pVmcs = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
    39393946    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;
    39513951    return uReg;
    39523952}
     
    39643964    PCVMXVVMCS pVmcs = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
    39653965    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;
    39743971}
    39753972
     
    39863983    PCVMXVVMCS pVmcs = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
    39873984    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;
    39963990}
    39973991
     
    40104004    PCVMXVVMCS pVmcs = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
    40114005    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     else
    4028     {
    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;
    40324026}
    40334027
     
    40464040    PCVMXVVMCS pVmcs = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
    40474041    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);
    40494046    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;
    40684062}
    40694063
     
    63156309            IEM_VMX_VMENTRY_FAILED_RET(pVCpu, pszInstr, pszFailure, kVmxVDiag_Vmentry_AddrVirtApicPage);
    63166310
    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
    63206324            IEM_VMX_VMENTRY_FAILED_RET(pVCpu, pszInstr, pszFailure, kVmxVDiag_Vmentry_TprThresholdRsvd);
    63216325
    6322         /* TPR threshold and VTPR. */
     6326        /* Verify TPR threshold and VTPR when both virtualize-APIC accesses and virtual-interrupt delivery aren't used. */
    63236327        if (   !(pVmcs->u32ProcCtls2 & VMX_PROC_CTLS2_VIRT_APIC_ACCESS)
    63246328            && !(pVmcs->u32ProcCtls2 & VMX_PROC_CTLS2_VIRT_INT_DELIVERY))
    63256329        {
    63266330            /* 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;
    63336334
    63346335            /* Bits 3:0 of the TPR-threshold must not be greater than bits 7:4 of VTPR. */
     
    73867387                                    return rcStrict;
    73877388                                }
     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;
    73887392
    73897393                                /* We've now entered nested-guest execution. */
Note: See TracChangeset for help on using the changeset viewer.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette