VirtualBox

Changeset 75631 in vbox


Ignore:
Timestamp:
Nov 21, 2018 4:55:45 AM (6 years ago)
Author:
vboxsync
Message:

VMM: Nested VMX: bugref:9180 APIC-access page deregistration and other related bits. Include VMCPU_FF_INTERRUPT_NESTED_GUEST in the external halted mask it must also wake the processor from HLT and MWAIT states. Same applies for AMD-V.

Location:
trunk
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/include/VBox/vmm/vm.h

    r75620 r75631  
    569569#define VMCPU_FF_EXTERNAL_HALTED_MASK           (  VMCPU_FF_UPDATE_APIC | VMCPU_FF_INTERRUPT_APIC | VMCPU_FF_INTERRUPT_PIC \
    570570                                                 | VMCPU_FF_REQUEST     | VMCPU_FF_INTERRUPT_NMI  | VMCPU_FF_INTERRUPT_SMI \
    571                                                  | VMCPU_FF_UNHALT      | VMCPU_FF_TIMER          | VMCPU_FF_DBGF )
     571                                                 | VMCPU_FF_UNHALT      | VMCPU_FF_TIMER          | VMCPU_FF_DBGF \
     572                                                 | VMCPU_FF_INTERRUPT_NESTED_GUEST)
    572573
    573574/** High priority VM pre-execution actions. */
  • trunk/src/VBox/VMM/VMMAll/IEMAll.cpp

    r75620 r75631  
    1604416044    RT_NOREF4(pVM, pvPhys, enmOrigin, pvUser);
    1604516045
    16046     Assert(CPUMIsGuestInVmxNonRootMode(IEM_GET_CTX(pVCpu)));
    16047     Assert(CPUMIsGuestVmxProcCtls2Set(pVCpu, IEM_GET_CTX(pVCpu), VMX_PROC_CTLS2_VIRT_APIC_ACCESS));
    16048 
    16049 #ifdef VBOX_STRICT
    16050     RTGCPHYS const GCPhysApicBase   = CPUMGetGuestVmxApicAccessPageAddr(pVCpu, IEM_GET_CTX(pVCpu));
    1605116046    RTGCPHYS const GCPhysAccessBase = GCPhysFault & ~(RTGCPHYS)PAGE_OFFSET_MASK;
    16052     Assert(GCPhysApicBase == GCPhysAccessBase);
    16053 #endif
    16054 
    16055     uint16_t const offAccess = GCPhysFault & PAGE_OFFSET_MASK;
    16056     uint32_t const fAccess   = enmAccessType == PGMACCESSTYPE_WRITE ? IEM_ACCESS_TYPE_WRITE : IEM_ACCESS_TYPE_READ;
    16057 
    16058     VBOXSTRICTRC rcStrict = iemVmxVirtApicAccessMem(pVCpu, offAccess, cbBuf, pvBuf, fAccess);
    16059     if (RT_FAILURE(rcStrict))
    16060         return rcStrict;
    16061 
    16062     /* Any access on this APIC-access page has been handled, caller should not carry out the access. */
    16063     return VINF_SUCCESS;
     16047    if (CPUMIsGuestInVmxNonRootMode(IEM_GET_CTX(pVCpu)))
     16048    {
     16049        Assert(CPUMIsGuestVmxProcCtls2Set(pVCpu, IEM_GET_CTX(pVCpu), VMX_PROC_CTLS2_VIRT_APIC_ACCESS));
     16050        Assert(CPUMGetGuestVmxApicAccessPageAddr(pVCpu, IEM_GET_CTX(pVCpu)) == GCPhysAccessBase);
     16051
     16052        /** @todo NSTVMX: How are we to distinguish instruction fetch accesses here?
     16053         *        Currently they will go through as read accesses. */
     16054        uint32_t const fAccess   = enmAccessType == PGMACCESSTYPE_WRITE ? IEM_ACCESS_TYPE_WRITE : IEM_ACCESS_TYPE_READ;
     16055        uint16_t const offAccess = GCPhysFault & PAGE_OFFSET_MASK;
     16056        VBOXSTRICTRC rcStrict = iemVmxVirtApicAccessMem(pVCpu, offAccess, cbBuf, pvBuf, fAccess);
     16057        if (RT_FAILURE(rcStrict))
     16058            return rcStrict;
     16059
     16060        /* Any access on this APIC-access page has been handled, caller should not carry out the access. */
     16061        return VINF_SUCCESS;
     16062    }
     16063
     16064    Log(("iemVmxApicAccessPageHandler: Access outside VMX non-root mode, deregistering page at %#RGp\n", GCPhysAccessBase));
     16065    int rc = PGMHandlerPhysicalDeregister(pVM, GCPhysAccessBase);
     16066    if (RT_FAILURE(rc))
     16067        return rc;
     16068
     16069    /* Instruct the caller of this handler to perform the read/write as normal memory. */
     16070    return VINF_PGM_HANDLER_DO_DEFAULT;
    1606416071}
    1606516072
  • trunk/src/VBox/VMM/VMMAll/IEMAllCImpl.cpp.h

    r75620 r75631  
    59125912                 */
    59135913                uint32_t const uTpr = (uNewCrX & 0xf) << 4;
     5914                Log(("iemCImpl_load_Cr%#x: Virtualizing TPR (%#x) write\n", iCrReg, uTpr));
    59145915                iemVmxVirtApicWriteRaw32(pVCpu, XAPIC_OFF_TPR, uTpr);
    59155916                iemVmxVirtApicSetPendingWrite(pVCpu, XAPIC_OFF_TPR);
  • trunk/src/VBox/VMM/VMMAll/IEMAllCImplVmxInstr.cpp.h

    r75620 r75631  
    21822182             *
    21832183             * If Delta >= VmcsPreemptTimer * RT_BIT(PreemptTimerShift) cause a VMX-preemption timer VM-exit.
    2184              *
    21852184             * The saved VMX-preemption timer value is calculated as follows:
    21862185             * PreemptTimerVal = VmcsPreemptTimer - (Delta / (VmcsPreemptTimer * RT_BIT(PreemptTimerShift)))
     
    27502749    /* Clear address range monitoring. */
    27512750    EMMonitorWaitClear(pVCpu);
    2752 
    2753     /* De-register the handler for the APIC-access page. */
    2754     if (pVmcs->u32ProcCtls2 & VMX_PROC_CTLS2_VIRT_APIC_ACCESS)
    2755     {
    2756         PVM pVM = pVCpu->CTX_SUFF(pVM);
    2757         RTGCPHYS const GCPhysApicAccess = pVmcs->u64AddrApicAccess.u;
    2758         if (PGMHandlerPhysicalIsRegistered(pVM, GCPhysApicAccess))
    2759         {
    2760             /** @todo NSTVMX: This is broken! We cannot simply deregister the handler for the
    2761              *        physical address as other VCPUs executing other nested-VCPUs might have
    2762              *        it registered! */
    2763             int rc = PGMHandlerPhysicalDeregister(pVM, GCPhysApicAccess);
    2764             if (RT_FAILURE(rc))
    2765                 return rc;
    2766         }
    2767     }
    27682751
    27692752    /* Perform the VMX transition (PGM updates). */
     
    46384621    Assert(pVmcs->u32ProcCtls2 & VMX_PROC_CTLS2_VIRT_INT_DELIVERY);
    46394622
    4640     /** @todo NSTVMX: evaluate pending virtual interrupts. */
    4641     RT_NOREF(pVCpu);
     4623    if (!(pVmcs->u32ProcCtls & VMX_PROC_CTLS_INT_WINDOW_EXIT))
     4624    {
     4625        uint8_t const uRvi = RT_LO_U8(pVmcs->u16GuestIntStatus);
     4626        uint8_t const uPpr = iemVmxVirtApicReadRaw32(pVCpu, XAPIC_OFF_PPR);
     4627
     4628        if ((uRvi >> 4) > (uPpr >> 4))
     4629        {
     4630            Log2(("eval_virt_intrs: uRvi=%#x uPpr=%#x - Signaling pending interrupt\n", uRvi, uPpr));
     4631            VMCPU_FF_SET(pVCpu, VMCPU_FF_INTERRUPT_NESTED_GUEST);
     4632        }
     4633        else
     4634            Log2(("eval_virt_intrs: uRvi=%#x uPpr=%#x - Nothing to do\n", uRvi, uPpr));
     4635    }
    46424636}
    46434637
     
    46634657     */
    46644658    uint32_t const uTpr = iemVmxVirtApicReadRaw32(pVCpu, XAPIC_OFF_TPR);
    4665     uint32_t const uSvi  = RT_HI_U8(pVmcs->u16GuestIntStatus);
    4666 
    4667     uint32_t uVPpr;
     4659    uint32_t const uSvi = RT_HI_U8(pVmcs->u16GuestIntStatus);
     4660
     4661    uint32_t uPpr;
    46684662    if (((uTpr >> 4) & 0xf) >= ((uSvi >> 4) & 0xf))
    4669         uVPpr = uTpr & 0xff;
     4663        uPpr = uTpr & 0xff;
    46704664    else
    4671         uVPpr = uSvi & 0xf0;
    4672     iemVmxVirtApicWriteRaw32(pVCpu, XAPIC_OFF_PPR, uVPpr);
    4673     Log2(("ppr_virt: uTpr=%u uSvi=%u -> VM-exit\n", uTpr, uSvi));
     4665        uPpr = uSvi & 0xf0;
     4666
     4667    Log2(("ppr_virt: uTpr=%#x uSvi=%#x uPpr=%#x\n", uTpr, uSvi, uPpr));
     4668    iemVmxVirtApicWriteRaw32(pVCpu, XAPIC_OFF_PPR, uPpr);
    46744669}
    46754670
     
    47634758    uint8_t const uRvi = RT_LO_U8(pVmcs->u16GuestIntStatus);
    47644759    uint8_t const uSvi = RT_HI_U8(pVmcs->u16GuestIntStatus);
     4760    Log2(("eoi_virt: uRvi=%#x uSvi=%#x\n", uRvi, uSvi));
    47654761
    47664762    uint8_t uVector = uSvi;
     
    47694765    uVector = 0;
    47704766    iemVmxVirtApicGetHighestSetBitInReg(pVCpu, XAPIC_OFF_ISR0, &uVector);
     4767
     4768    if (uVector)
     4769        Log2(("eoi_virt: next interrupt %#x\n", uVector));
     4770    else
     4771        Log2(("eoi_virt: no interrupt pending in ISR\n"));
    47714772
    47724773    /* Update guest-interrupt status SVI (leave RVI portion as it is) in the VMCS. */
     
    47994800     * See Intel spec. 29.1.5 "Self-IPI Virtualization".
    48004801     */
    4801     uint8_t const uVector = iemVmxVirtApicReadRaw32(pVCpu, X2APIC_OFF_SELF_IPI);
    4802 
     4802    uint8_t const uVector = iemVmxVirtApicReadRaw32(pVCpu, XAPIC_OFF_ICR_LO);
     4803    Log2(("self_ipi_virt: uVector=%#x\n", uVector));
    48034804    iemVmxVirtApicSetVector(pVCpu, XAPIC_OFF_IRR0, uVector);
    48044805    uint8_t const uRvi = RT_LO_U8(pVmcs->u16GuestIntStatus);
     
    48374838            uTpr         &= UINT32_C(0x000000ff);
    48384839            iemVmxVirtApicWriteRaw32(pVCpu, XAPIC_OFF_TPR, uTpr);
     4840            Log2(("iemVmxApicWriteEmulation: TPR write %#x\n", uTpr));
    48394841            rcStrict = iemVmxTprVirtualization(pVCpu);
    48404842            break;
     
    48474849                /* Clear VEOI and perform EOI virtualization. */
    48484850                iemVmxVirtApicWriteRaw32(pVCpu, XAPIC_OFF_EOI, 0);
     4851                Log2(("iemVmxApicWriteEmulation: EOI write\n"));
    48494852                rcStrict = iemVmxEoiVirtualization(pVCpu);
    48504853            }
     
    48644867                if (   !(uIcrLo & fIcrLoMb0)
    48654868                    &&  (uIcrLo & fIcrLoMb1))
     4869                {
     4870                    Log2(("iemVmxApicWriteEmulation: Self-IPI virtualization with vector %#x\n", (uIcrLo & 0xff)));
    48664871                    rcStrict = iemVmxSelfIpiVirtualization(pVCpu);
     4872                }
    48674873                else
    48684874                    rcStrict = iemVmxVmexitApicWrite(pVCpu, offApicWrite);
     
    64036409        }
    64046410
    6405         /* Register the handler for the APIC-access page. */
     6411        /*
     6412         * Register the handler for the APIC-access page.
     6413         *
     6414         * We don't deregister the APIC-access page handler during the VM-exit as a different
     6415         * nested-VCPU might be using the same guest-physical address for its APIC-access page.
     6416         *
     6417         * We leave the page registered until the first access that happens outside VMX non-root
     6418         * mode. Guest software is allowed to access structures such as the APIC-access page
     6419         * only when no logical processor with a current VMCS references it in VMX non-root mode,
     6420         * otherwise it can lead to unpredictable behavior including guest triple-faults.
     6421         *
     6422         * See Intel spec. 24.11.4 "Software Access to Related Structures".
     6423         */
    64066424        int rc = PGMHandlerPhysicalRegister(pVCpu->CTX_SUFF(pVM), GCPhysApicAccess, GCPhysApicAccess,
    64076425                                            pVCpu->iem.s.hVmxApicAccessPage, NIL_RTR3PTR /* pvUserR3 */,
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