VirtualBox

Changeset 75620 in vbox for trunk/src/VBox/VMM/VMMAll


Ignore:
Timestamp:
Nov 20, 2018 2:42:07 PM (6 years ago)
Author:
vboxsync
Message:

VMM: Nested VMX: bugref:9180 APIC-write emulation bits.

Location:
trunk/src/VBox/VMM/VMMAll
Files:
3 edited

Legend:

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

    r75611 r75620  
    1571515715
    1571615716/**
    15717  * Interface for HM and EM to perform a post-instruction virtual-APIC update.
     15717 * Interface for HM and EM to perform a APIC-write emulation.
    1571815718 *
    1571915719 * @returns Strict VBox status code.
    15720  * @retval  VINF_VMX_VMEXIT if the virtual-APIC update causes a VM-exit.
    15721  * @retval  VINF_VMX_INTERCEPT_NOT_ACTIVE if no change was made.
    15722  *
    1572315720 * @param   pVCpu       The cross context virtual CPU structure of the calling EMT.
    1572415721 * @thread  EMT(pVCpu)
    1572515722 */
    15726 VMM_INT_DECL(VBOXSTRICTRC) IEMExecVmxVirtApicUpdate(PVMCPU pVCpu)
     15723VMM_INT_DECL(VBOXSTRICTRC) IEMExecVmxVirtApicWriteEmulation(PVMCPU pVCpu)
    1572715724{
    1572815725    IEM_CTX_ASSERT(pVCpu, IEM_CPUMCTX_EXTRN_VMX_VMEXIT_MASK);
    1572915726
    15730     /*
    15731      * Record the virtual-APIC offset which was just updated and clear
    15732      * the virtual-APIC update force-flag and process it now.
    15733      */
    15734     uint16_t const offApicWrite = iemVmxVirtApicClearPostAction(pVCpu);
    15735     VBOXSTRICTRC rcStrict;
    15736     switch (offApicWrite)
    15737     {
    15738         case XAPIC_OFF_TPR:         rcStrict = iemVmxTprVirtualization(pVCpu);      break;
    15739         case XAPIC_OFF_EOI:         rcStrict = iemVmxEoiVirtualization(pVCpu);      break;
    15740         case X2APIC_OFF_SELF_IPI:   rcStrict = iemVmxSelfIpiVirtualization(pVCpu);  break;
    15741         IEM_NOT_REACHED_DEFAULT_CASE_RET();
    15742     }
     15727    VBOXSTRICTRC rcStrict = iemVmxApicWriteEmulation(pVCpu);
    1574315728    if (pVCpu->iem.s.cActiveMappings)
    1574415729        iemMemRollback(pVCpu);
  • trunk/src/VBox/VMM/VMMAll/IEMAllCImpl.cpp.h

    r75604 r75620  
    53685368                if (IEM_VMX_IS_PROCCTLS_SET(pVCpu, VMX_PROC_CTLS_USE_TPR_SHADOW))
    53695369                {
    5370                     uint32_t const uVTpr = iemVmxVirtApicReadRaw32(pVCpu, XAPIC_OFF_TPR);
    5371                     crX = (uVTpr >> 4) & 0xf;
     5370                    uint32_t const uTpr = iemVmxVirtApicReadRaw32(pVCpu, XAPIC_OFF_TPR);
     5371                    crX = (uTpr >> 4) & 0xf;
    53725372                    break;
    53735373                }
     
    59055905                 * cleared. Following this the processor performs TPR virtualization.
    59065906                 *
    5907                  * See Intel Spec. 29.3 "Virtualizing CR8-based TPR Accesses"
     5907                 * However, we should not perform TPR virtualization immediately here but
     5908                 * after this instruction has completed.
     5909                 *
     5910                 * See Intel spec. 29.3 "Virtualizing CR8-based TPR Accesses"
     5911                 * See Intel spec. 27.1 "Architectural State Before A VM-exit"
    59085912                 */
    5909                 uint32_t const uVTpr = (uNewCrX & 0xf) << 4;
    5910                 iemVmxVirtApicWriteRaw32(pVCpu, XAPIC_OFF_TPR, uVTpr);
    5911                 iemVmxVirtApicSetPostAction(pVCpu, XAPIC_OFF_TPR);
     5913                uint32_t const uTpr = (uNewCrX & 0xf) << 4;
     5914                iemVmxVirtApicWriteRaw32(pVCpu, XAPIC_OFF_TPR, uTpr);
     5915                iemVmxVirtApicSetPendingWrite(pVCpu, XAPIC_OFF_TPR);
    59125916                rcStrict = VINF_SUCCESS;
    59135917                break;
  • trunk/src/VBox/VMM/VMMAll/IEMAllCImplVmxInstr.cpp.h

    r75611 r75620  
    911911
    912912/**
    913  * Signal that a virtual-APIC post instruction-execution action needs to be
    914  * performed at a later time (post instruction execution).
     913 * Sets virtual-APIC write emulation as pending.
    915914 *
    916915 * @param   pVCpu       The cross context virtual CPU structure.
    917  * @param   offApic     The virtual-APIC page offset that was updated pertaining to
    918  *                      the event.
    919  */
    920 DECLINLINE(void) iemVmxVirtApicSetPostAction(PVMCPU pVCpu, uint16_t offApic)
     916 * @param   offApic     The offset in the virtual-APIC page that was written.
     917 */
     918DECLINLINE(void) iemVmxVirtApicSetPendingWrite(PVMCPU pVCpu, uint16_t offApic)
    921919{
    922920    Assert(offApic < XAPIC_OFF_END + 4);
     
    930928
    931929    /*
    932      * Signal that we need to perform a virtual-APIC action (TPR/PPR/EOI/Self-IPI
     930     * Signal that we need to perform virtual-APIC write emulation (TPR/PPR/EOI/Self-IPI
    933931     * virtualization or APIC-write emulation).
    934932     */
    935     if (!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_VMX_UPDATE_VAPIC))
    936         VMCPU_FF_SET(pVCpu, VMCPU_FF_VMX_UPDATE_VAPIC);
    937 }
    938 
    939 
    940 /**
    941  * Clears any virtual-APIC post instruction-execution action.
    942  *
    943  * @returns The virtual-APIC write offset before clearing it.
     933    if (!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_VMX_APIC_WRITE))
     934        VMCPU_FF_SET(pVCpu, VMCPU_FF_VMX_APIC_WRITE);
     935}
     936
     937
     938/**
     939 * Clears any pending virtual-APIC write emulation.
     940 *
     941 * @returns The virtual-APIC offset that was written before clearing it.
    944942 * @param   pVCpu       The cross context virtual CPU structure.
    945  * @param   offApic     The virtual-APIC page offset that was updated pertaining to
    946  *                      the event.
    947  */
    948 DECLINLINE(uint16_t) iemVmxVirtApicClearPostAction(PVMCPU pVCpu)
     943 */
     944DECLINLINE(uint16_t) iemVmxVirtApicClearPendingWrite(PVMCPU pVCpu)
    949945{
    950946    uint8_t const offVirtApicWrite = pVCpu->cpum.GstCtx.hwvirt.vmx.offVirtApicWrite;
    951947    pVCpu->cpum.GstCtx.hwvirt.vmx.offVirtApicWrite = 0;
    952     Assert(VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_VMX_UPDATE_VAPIC));
    953     VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_VMX_UPDATE_VAPIC);
     948    Assert(VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_VMX_APIC_WRITE));
     949    VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_VMX_APIC_WRITE);
    954950    return offVirtApicWrite;
    955951}
     
    41644160     * virtualized a virtual-APIC write, we must cause a VM-exit.
    41654161     */
    4166     if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_VMX_UPDATE_VAPIC))
     4162    if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_VMX_APIC_WRITE))
    41674163        return true;
    41684164
     
    43304326 *
    43314327 * @param   pVCpu       The cross context virtual CPU structure.
    4332  */
    4333 IEM_STATIC VBOXSTRICTRC iemVmxVmexitApicWrite(PVMCPU pVCpu)
    4334 {
    4335     iemVmxVmcsSetExitQual(pVCpu, pVCpu->cpum.GstCtx.hwvirt.vmx.offVirtApicWrite);
     4328 * @param   offApic     The write to the virtual-APIC page offset that caused this
     4329 *                      VM-exit.
     4330 */
     4331IEM_STATIC VBOXSTRICTRC iemVmxVmexitApicWrite(PVMCPU pVCpu, uint16_t offApic)
     4332{
     4333    Assert(offApic < XAPIC_OFF_END + 4);
     4334    iemVmxVmcsSetExitQual(pVCpu, offApic);
    43364335    return iemVmxVmexit(pVCpu, VMX_EXIT_APIC_WRITE);
    43374336}
     
    44444443         * See Intel spec. 29.4.3.2 "APIC-Write Emulation".
    44454444         */
    4446         iemVmxVirtApicSetPostAction(pVCpu, offAccess);
     4445        iemVmxVirtApicSetPendingWrite(pVCpu, offAccess);
    44474446    }
    44484447    else
     
    45754574         * as for supplying the exit qualification when causing an APIC-write VM-exit.
    45764575         */
    4577         iemVmxVirtApicSetPostAction(pVCpu, offReg);
     4576        iemVmxVirtApicSetPendingWrite(pVCpu, offReg);
    45784577
    45794578        return VINF_VMX_MODIFIES_BEHAVIOR;
     
    46634662     * See Intel spec. 29.1.3 "PPR Virtualization".
    46644663     */
    4665     uint32_t const uVTpr = iemVmxVirtApicReadRaw32(pVCpu, XAPIC_OFF_TPR);
     4664    uint32_t const uTpr = iemVmxVirtApicReadRaw32(pVCpu, XAPIC_OFF_TPR);
    46664665    uint32_t const uSvi  = RT_HI_U8(pVmcs->u16GuestIntStatus);
    46674666
    46684667    uint32_t uVPpr;
    4669     if (((uVTpr >> 4) & 0xf) >= ((uSvi >> 4) & 0xf))
    4670         uVPpr = uVTpr & 0xff;
     4668    if (((uTpr >> 4) & 0xf) >= ((uSvi >> 4) & 0xf))
     4669        uVPpr = uTpr & 0xff;
    46714670    else
    46724671        uVPpr = uSvi & 0xf0;
    46734672    iemVmxVirtApicWriteRaw32(pVCpu, XAPIC_OFF_PPR, uVPpr);
    4674     Log2(("ppr_virt: uVTpr=%u uSvi=%u -> VM-exit\n", uVTpr, uSvi));
     4673    Log2(("ppr_virt: uTpr=%u uSvi=%u -> VM-exit\n", uTpr, uSvi));
    46754674}
    46764675
     
    46974696    {
    46984697        uint32_t const uTprThreshold = pVmcs->u32TprThreshold;
    4699         uint32_t const uVTpr         = iemVmxVirtApicReadRaw32(pVCpu, XAPIC_OFF_TPR);
     4698        uint32_t const uTpr          = iemVmxVirtApicReadRaw32(pVCpu, XAPIC_OFF_TPR);
    47004699
    47014700        /*
     
    47034702         * See Intel spec. 29.1.2 "TPR Virtualization".
    47044703         */
    4705         if (((uVTpr >> 4) & 0xf) < uTprThreshold)
    4706         {
    4707             Log2(("tpr_virt: uVTpr=%u uTprThreshold=%u -> VM-exit\n", uVTpr, uTprThreshold));
     4704        if (((uTpr >> 4) & 0xf) < uTprThreshold)
     4705        {
     4706            Log2(("tpr_virt: uTpr=%u uTprThreshold=%u -> VM-exit\n", uTpr, uTprThreshold));
    47084707            iemVmxVmcsSetExitQual(pVCpu, 0);
    47094708            return iemVmxVmexit(pVCpu, VMX_EXIT_TPR_BELOW_THRESHOLD);
     
    48244823    Assert(pVmcs->u32ProcCtls2 & VMX_PROC_CTLS2_APIC_REG_VIRT);
    48254824
    4826     /** @todo NSTVMX: APIC-write emulation. */
    4827     RT_NOREF(pVCpu);
    4828 
    4829     return VERR_IEM_ASPECT_NOT_IMPLEMENTED;
     4825    /*
     4826     * Perform APIC-write emulation based on the virtual-APIC register written.
     4827     * See Intel spec. 29.4.3.2 "APIC-Write Emulation".
     4828     */
     4829    uint16_t const offApicWrite = iemVmxVirtApicClearPendingWrite(pVCpu);
     4830    VBOXSTRICTRC rcStrict;
     4831    switch (offApicWrite)
     4832    {
     4833        case XAPIC_OFF_TPR:
     4834        {
     4835            /* Clear bytes 3:1 of the VTPR and perform TPR virtualization. */
     4836            uint32_t uTpr = iemVmxVirtApicReadRaw32(pVCpu, XAPIC_OFF_TPR);
     4837            uTpr         &= UINT32_C(0x000000ff);
     4838            iemVmxVirtApicWriteRaw32(pVCpu, XAPIC_OFF_TPR, uTpr);
     4839            rcStrict = iemVmxTprVirtualization(pVCpu);
     4840            break;
     4841        }
     4842
     4843        case XAPIC_OFF_EOI:
     4844        {
     4845            if (pVmcs->u32ProcCtls2 & VMX_PROC_CTLS2_VIRT_INT_DELIVERY)
     4846            {
     4847                /* Clear VEOI and perform EOI virtualization. */
     4848                iemVmxVirtApicWriteRaw32(pVCpu, XAPIC_OFF_EOI, 0);
     4849                rcStrict = iemVmxEoiVirtualization(pVCpu);
     4850            }
     4851            else
     4852                rcStrict = iemVmxVmexitApicWrite(pVCpu, offApicWrite);
     4853            break;
     4854        }
     4855
     4856        case XAPIC_OFF_ICR_LO:
     4857        {
     4858            if (pVmcs->u32ProcCtls2 & VMX_PROC_CTLS2_VIRT_INT_DELIVERY)
     4859            {
     4860                /* If the ICR_LO is valid, write it and perform self-IPI virtualization. */
     4861                uint32_t const uIcrLo    = iemVmxVirtApicReadRaw32(pVCpu, XAPIC_OFF_TPR);
     4862                uint32_t const fIcrLoMb0 = UINT32_C(0xfffbb700);
     4863                uint32_t const fIcrLoMb1 = UINT32_C(0x000000f0);
     4864                if (   !(uIcrLo & fIcrLoMb0)
     4865                    &&  (uIcrLo & fIcrLoMb1))
     4866                    rcStrict = iemVmxSelfIpiVirtualization(pVCpu);
     4867                else
     4868                    rcStrict = iemVmxVmexitApicWrite(pVCpu, offApicWrite);
     4869            }
     4870            else
     4871                rcStrict = iemVmxVmexitApicWrite(pVCpu, offApicWrite);
     4872            break;
     4873        }
     4874
     4875        case XAPIC_OFF_ICR_HI:
     4876        {
     4877            /* Clear bytes 2:0 of VICR_HI. No other virtualization or VM-exit must occur. */
     4878            uint32_t uIcrHi = iemVmxVirtApicReadRaw32(pVCpu, XAPIC_OFF_ICR_HI);
     4879            uIcrHi          &= UINT32_C(0xff000000);
     4880            iemVmxVirtApicWriteRaw32(pVCpu, XAPIC_OFF_ICR_HI, uIcrHi);
     4881            rcStrict = VINF_SUCCESS;
     4882            break;
     4883        }
     4884
     4885        default:
     4886        {
     4887            /* Writes to any other virtual-APIC register causes an APIC-write VM-exit. */
     4888            rcStrict = iemVmxVmexitApicWrite(pVCpu, offApicWrite);
     4889            break;
     4890        }
     4891    }
     4892
     4893    return rcStrict;
    48304894}
    48314895
Note: See TracChangeset for help on using the changeset viewer.

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