VirtualBox

Changeset 60377 in vbox for trunk


Ignore:
Timestamp:
Apr 7, 2016 3:53:36 PM (9 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
106461
Message:

VMM: Fix APIC, CPUM init ordering for the new APIC code while still retaining the old code. Namely, consistent MSR APIC base caching and APIC page dependency on PDM construction, see bugref:8245:46 for more details.

Location:
trunk
Files:
11 edited

Legend:

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

    r60307 r60377  
    3838#define XAPIC_HARDWARE_VERSION               XAPIC_HARDWARE_VERSION_P4
    3939
    40 /** The APIC base physical address. */
    41 #define MSR_APICBASE_PHYSADDR(a)             ((a) >> 12)
    42 /** The APIC base physical address shift. */
    43 #define MSR_APICBASE_PHYSADDR_SHIFT          12
    44 /** The APIC base MSR mode shift. */
    45 #define MSR_APICBASE_MODE_SHIFT              10
     40/** Gets the APIC base physical address. */
     41#define MSR_APICBASE_GET_PHYSADDR(a)         ((a) & PAGE_BASE_GC_MASK)
     42/** Gets the APIC mode. */
     43#define MSR_APICBASE_GET_MODE(a)             (((a) >> 10) & UINT64_C(3))
    4644/** The APIC global enable bit. */
    4745#define MSR_APICBASE_XAPIC_ENABLE_BIT        RT_BIT_64(11)
     
    5149#define MSR_APICBASE_BOOTSTRAP_CPU_BIT       RT_BIT_64(8)
    5250/** The default APIC base address. */
    53 #define XAPIC_APICBASE_PHYSADDR              UINT64_C(0xfee00000)
     51#define XAPIC_APICBASE_PHYSADDR              (UINT64_C(0xfee00000) << PAGE_SHIFT)
    5452/** The APIC base MSR - Is the APIC enabled?  */
    55 #define MSR_APICBASE_IS_ENABLED(a_Msr)      RT_BOOL((a_Msr) & MSR_APICBASE_XAPIC_ENABLE_BIT)
     53#define MSR_APICBASE_IS_ENABLED(a_Msr)       RT_BOOL((a_Msr) & MSR_APICBASE_XAPIC_ENABLE_BIT)
    5654
    5755/** Offset of APIC ID Register. */
  • trunk/include/VBox/vmm/cpum.h

    r58996 r60377  
    3131#include <VBox/vmm/cpumctx.h>
    3232#include <VBox/vmm/stam.h>
     33#include <VBox/vmm/vmapi.h>
    3334
    3435RT_C_DECLS_BEGIN
     
    13831384
    13841385VMMR3DECL(int)          CPUMR3Init(PVM pVM);
    1385 VMMR3DECL(int)          CPUMR3InitCompleted(PVM pVM);
     1386VMMR3DECL(int)          CPUMR3InitCompleted(PVM pVM, VMINITCOMPLETED enmWhat);
    13861387VMMR3DECL(void)         CPUMR3LogCpuIds(PVM pVM);
    13871388VMMR3DECL(void)         CPUMR3Relocate(PVM pVM);
  • trunk/include/VBox/vmm/pdmapi.h

    r60307 r60377  
    5050VMM_INT_DECL(int)       PDMApicHasPendingIrq(PVM pVM, bool *pfPending);
    5151VMMDECL(VBOXSTRICTRC)   PDMApicSetBaseMsr(PVMCPU pVCpu, uint64_t u64Base);
    52 VMMDECL(VBOXSTRICTRC)   PDMApicGetBaseMsr(PVMCPU pVCpu, uint64_t *pu64Base);
     52VMMDECL(VBOXSTRICTRC)   PDMApicGetBaseMsr(PVMCPU pVCpu, uint64_t *pu64Base, bool fIgnoreErrors);
    5353VMMDECL(int)            PDMApicSetTPR(PVMCPU pVCpu, uint8_t u8TPR);
    5454VMMDECL(int)            PDMApicGetTPR(PVMCPU pVCpu, uint8_t *pu8TPR, bool *pfPending, uint8_t *pu8PendingIrq);
  • trunk/src/VBox/VMM/VMMAll/APICAll.cpp

    r60345 r60377  
    223223static APICMODE apicGetMode(uint64_t uApicBaseMsr)
    224224{
    225     uint32_t const uMode   = ((uint32_t)uApicBaseMsr >> MSR_APICBASE_MODE_SHIFT) & UINT32_C(0x3);
     225    uint32_t const uMode   = MSR_APICBASE_GET_MODE(uApicBaseMsr);
    226226    APICMODE const enmMode = (APICMODE)uMode;
    227227#ifdef VBOX_STRICT
     
    10121012            }
    10131013
    1014             /** @todo Signal next interrupt? Most likely not as
    1015              *        APICUpdatePendingInterrupts() will be called before next VM-entry. */
    10161014            apicSignalNextPendingIntr(pVCpu);
    10171015        }
     
    17931791     */
    17941792    /** @todo Handle per-VCPU APIC base relocation. */
    1795     if (MSR_APICBASE_PHYSADDR(uBaseMsr) != XAPIC_APICBASE_PHYSADDR)
     1793    if (MSR_APICBASE_GET_PHYSADDR(uBaseMsr) != XAPIC_APICBASE_PHYSADDR)
    17961794    {
    17971795#ifdef IN_RING3
    17981796        LogRelMax(5, ("APIC%u: Attempt to relocate base to %#RGp, unsupported -> #GP(0)\n", pVCpu->idCpu,
    1799                       MSR_APICBASE_PHYSADDR(uBaseMsr)));
     1797                      MSR_APICBASE_GET_PHYSADDR(uBaseMsr)));
    18001798        return VERR_CPUM_RAISE_GP_0;
    18011799#else
     
    19641962    AssertReturn(u8Level <= 1, VERR_INVALID_PARAMETER);
    19651963
    1966     PCXAPICPAGE   pXApicPage = VMCPU_TO_CXAPICPAGE(pVCpu);
    1967     VBOXSTRICTRC  rcStrict   = VINF_SUCCESS;
     1964    PCXAPICPAGE  pXApicPage = VMCPU_TO_CXAPICPAGE(pVCpu);
     1965    VBOXSTRICTRC rcStrict   = VINF_SUCCESS;
    19681966
    19691967    /* If the APIC is enabled, the interrupt is subject to LVT programming. */
     
    20582056        && pXApicPage->svr.u.fApicSoftwareEnable)
    20592057    {
     2058        APICUpdatePendingInterrupts(pVCpu);
    20602059        int const irrv = apicGetLastSetBit(&pXApicPage->irr, -1);
    20612060        if (irrv >= 0)
     
    20662065            /** @todo this cannot possibly happen for anything other than ExtINT
    20672066             *        interrupts right? */
    2068             uint8_t uTpr = pXApicPage->tpr.u8Tpr;
     2067            uint8_t const uTpr = pXApicPage->tpr.u8Tpr;
    20692068            if (uTpr > 0 && uVector <= uTpr)
    2070             {
    2071                 *puTagSrc = 0;
    20722069                return pXApicPage->svr.u.u8SpuriousVector;
    2073             }
    20742070
    20752071            apicClearVectorInReg(&pXApicPage->irr, uVector);
    20762072            apicSetVectorInReg(&pXApicPage->isr, uVector);
    20772073            apicUpdatePpr(pVCpu);
    2078 
    2079             /** @todo Signal next interrupt? Most likely not as
    2080              *        APICUpdatePendingInterrupts() will be called before next VM-entry. */
     2074            apicSignalNextPendingIntr(pVCpu);
    20812075            return uVector;
    20822076        }
    20832077    }
    2084     /** @todo */
    20852078
    20862079    return -1;
     
    20932086VMMDECL(int) APICReadMmio(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS GCPhysAddr, void *pv, unsigned cb)
    20942087{
     2088    NOREF(pvUser);
    20952089    Assert(!(GCPhysAddr & 0xf));
    20962090    Assert(cb == 4);
     
    21152109VMMDECL(int) APICWriteMmio(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS GCPhysAddr, void const *pv, unsigned cb)
    21162110{
     2111    NOREF(pvUser);
    21172112    Assert(!(GCPhysAddr & 0xf));
    21182113    Assert(cb == 4);
     
    23032298 * @param   u8PendingIntr       The pending interrupt to queue as
    23042299 *                              in-service.
     2300 *
     2301 * @remarks This assumes the caller has done the necessary checks and
     2302 *          is ready to take actually service the interrupt (TPR,
     2303 *          interrupt shadow etc.)
    23052304 */
    23062305VMMDECL(bool) APICQueueInterruptToService(PVMCPU pVCpu, uint8_t u8PendingIntr)
  • trunk/src/VBox/VMM/VMMAll/CPUMAllMsrs.cpp

    r60307 r60377  
    205205static DECLCALLBACK(VBOXSTRICTRC) cpumMsrRd_Ia32ApicBase(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue)
    206206{
    207     return PDMApicGetBaseMsr(pVCpu, puValue);
     207    return PDMApicGetBaseMsr(pVCpu, puValue, false /* fIgnoreErrors */);
    208208}
    209209
  • trunk/src/VBox/VMM/VMMAll/CPUMAllRegs.cpp

    r58170 r60377  
    13911391
    13921392            pVM->cpum.s.GuestFeatures.fApic = 1;
    1393             LogRel(("CPUM: SetGuestCpuIdFeature: Enabled APIC\n"));
     1393            LogRel(("CPUM: SetGuestCpuIdFeature: Enabled xAPIC\n"));
    13941394            break;
    13951395
     
    16881688
    16891689            pVM->cpum.s.GuestFeatures.fApic = 0;
    1690             Log(("CPUM: ClearGuestCpuIdFeature: Disabled APIC\n"));
     1690            Log(("CPUM: ClearGuestCpuIdFeature: Disabled xAPIC\n"));
    16911691            break;
    16921692
  • trunk/src/VBox/VMM/VMMAll/PDMAll.cpp

    r60309 r60377  
    4747    PVM pVM = pVCpu->CTX_SUFF(pVM);
    4848
     49#ifndef VBOX_WITH_NEW_APIC
    4950    pdmLock(pVM);
     51#endif
    5052
    5153    /*
     
    6264        if (i >= 0)
    6365        {
     66#ifndef VBOX_WITH_NEW_APIC
    6467            pdmUnlock(pVM);
     68#endif
    6569            *pu8Interrupt = (uint8_t)i;
    6670            VBOXVMM_PDM_IRQ_GET(pVCpu, RT_LOWORD(uTagSrc), RT_HIWORD(uTagSrc), i);
     
    6872        }
    6973    }
     74
     75#ifdef VBOX_WITH_NEW_APIC
     76    pdmLock(pVM);
     77#endif
    7078
    7179    /*
     
    236244    {
    237245        Assert(pVM->pdm.s.Apic.CTX_SUFF(pfnSetBaseMsr));
     246#ifndef VBOX_WITH_NEW_APIC
    238247        pdmLock(pVM);
     248#endif
    239249        VBOXSTRICTRC rcStrict = pVM->pdm.s.Apic.CTX_SUFF(pfnSetBaseMsr)(pVM->pdm.s.Apic.CTX_SUFF(pDevIns), pVCpu, u64Base);
    240250
     
    244254        pCtx->msrApicBase = pVM->pdm.s.Apic.CTX_SUFF(pfnGetBaseMsr)(pVM->pdm.s.Apic.CTX_SUFF(pDevIns), pVCpu);
    245255
     256#ifndef VBOX_WITH_NEW_APIC
    246257        pdmUnlock(pVM);
     258#endif
    247259        return rcStrict;
    248260    }
     
    262274 *
    263275 * @returns Strict VBox status code.
    264  * @param   pVCpu       The cross context virtual CPU structure.
    265  * @param   pu64Base    Where to store the APIC base.
    266  */
    267 VMMDECL(VBOXSTRICTRC) PDMApicGetBaseMsr(PVMCPU pVCpu, uint64_t *pu64Base)
     276 * @param   pVCpu           The cross context virtual CPU structure.
     277 * @param   pu64Base        Where to store the APIC base.
     278 * @param   fIgnoreErrors   Whether to ignore errors (i.e. not a real guest MSR
     279 *                          access).
     280 */
     281VMMDECL(VBOXSTRICTRC) PDMApicGetBaseMsr(PVMCPU pVCpu, uint64_t *pu64Base, bool fIgnoreErrors)
    268282{
    269283    PVM pVM = pVCpu->CTX_SUFF(pVM);
     
    272286        Assert(pVM->pdm.s.Apic.CTX_SUFF(pfnGetBaseMsr));
    273287#ifdef VBOX_WITH_NEW_APIC
     288        VMCPU_ASSERT_EMT_OR_NOT_RUNNING(pVCpu);
    274289        *pu64Base = pVM->pdm.s.Apic.CTX_SUFF(pfnGetBaseMsr)(pVM->pdm.s.Apic.CTX_SUFF(pDevIns), pVCpu);
    275290#else
     
    282297
    283298    *pu64Base = 0;
     299    if (fIgnoreErrors)
     300        return VINF_SUCCESS;
     301
    284302#ifdef IN_RING3
    285303    LogRelMax(5, ("PDM: APIC%u: Reading APIC base MSR (%#x) invalid without an APIC instance -> #GP(0)\n", pVCpu->idCpu,
  • trunk/src/VBox/VMM/VMMR0/APICR0.cpp

    r60364 r60377  
    7676
    7777    /*
    78      * Allocate and map the virtual-APIC page.
     78     * Allocate and map the virtual-APIC pages.
    7979     */
    8080    for (VMCPUID idCpu = 0; idCpu < pVM->cCpus; idCpu++)
     
    110110                const size_t offApicPib = idCpu * sizeof(APICPIB);
    111111                pApicCpu->HCPhysApicPib = pApic->HCPhysApicPib + offApicPib;
    112                 pApicCpu->pvApicPibR0   = (RTR0PTR)((uint8_t *)pApic->pvApicPibR0 + offApicPib);
    113                 pApicCpu->pvApicPibR3   = (RTR3PTR)((uint8_t *)pApic->pvApicPibR3 + offApicPib);
     112                pApicCpu->pvApicPibR0   = (RTR0PTR)((const uint8_t *)pApic->pvApicPibR0 + offApicPib);
     113                pApicCpu->pvApicPibR3   = (RTR3PTR)((const uint8_t *)pApic->pvApicPibR3 + offApicPib);
    114114            }
    115115            else
  • trunk/src/VBox/VMM/VMMR3/CPUM.cpp

    r60307 r60377  
    10821082     * continues to reside in the APIC device and we cache it here in the VCPU for all further accesses.
    10831083     */
    1084     PDMApicGetBaseMsr(pVCpu, &pCtx->msrApicBase);
     1084    PDMApicGetBaseMsr(pVCpu, &pCtx->msrApicBase, true /* fIgnoreErrors */);
     1085#ifdef VBOX_WITH_NEW_APIC
     1086    LogRel(("CPUM: VCPU%3d: Cached APIC base MSR = %#RX64\n", pVCpu->idCpu, pVCpu->cpum.s.Guest.msrApicBase));
     1087#endif
    10851088}
    10861089
     
    15311534
    15321535        /* Cache the local APIC base from the APIC device. During init. this is done in CPUMR3ResetCpu(). */
    1533         PDMApicGetBaseMsr(pVCpu, &pVCpu->cpum.s.Guest.msrApicBase);
     1536        PDMApicGetBaseMsr(pVCpu, &pVCpu->cpum.s.Guest.msrApicBase, true /* fIgnoreErrors */);
     1537#ifdef VBOX_WITH_NEW_APIC
     1538        LogRel(("CPUM: VCPU%3d: Cached APIC base MSR = %#RX64\n", idCpu, pVCpu->cpum.s.Guest.msrApicBase));
     1539#endif
    15341540
    15351541        /* During init. this is done in CPUMR3InitCompleted(). */
     
    24102416 * @returns VBox status code.
    24112417 * @param   pVM                 The cross context VM structure.
    2412  */
    2413 VMMR3DECL(int) CPUMR3InitCompleted(PVM pVM)
    2414 {
    2415     /*
    2416      * Figure out if the guest uses 32-bit or 64-bit FPU state at runtime for 64-bit capable VMs.
    2417      * Only applicable/used on 64-bit hosts, refer CPUMR0A.asm. See @bugref{7138}.
    2418      */
    2419     bool const fSupportsLongMode = VMR3IsLongModeAllowed(pVM);
    2420     for (VMCPUID i = 0; i < pVM->cCpus; i++)
    2421     {
    2422         PVMCPU pVCpu = &pVM->aCpus[i];
    2423 
    2424         /* Cache the APIC base (from the APIC device) once it has been initialized. */
    2425         PDMApicGetBaseMsr(pVCpu, &pVCpu->cpum.s.Guest.msrApicBase);
    2426         Log(("CPUMR3InitCompleted pVM=%p APIC base[%u]=%RX64\n", pVM, (unsigned)i, pVCpu->cpum.s.Guest.msrApicBase));
    2427 
    2428         /* While loading a saved-state we fix it up in, cpumR3LoadDone(). */
    2429         if (fSupportsLongMode)
    2430             pVCpu->cpum.s.fUseFlags |= CPUM_USE_SUPPORTS_LONGMODE;
    2431     }
    2432 
    2433     cpumR3MsrRegStats(pVM);
     2418 * @param   enmWhat             Which init phase.
     2419 */
     2420VMMR3DECL(int) CPUMR3InitCompleted(PVM pVM, VMINITCOMPLETED enmWhat)
     2421{
     2422    switch (enmWhat)
     2423    {
     2424        case VMINITCOMPLETED_RING3:
     2425        {
     2426            /*
     2427             * Figure out if the guest uses 32-bit or 64-bit FPU state at runtime for 64-bit capable VMs.
     2428             * Only applicable/used on 64-bit hosts, refer CPUMR0A.asm. See @bugref{7138}.
     2429             */
     2430            bool const fSupportsLongMode = VMR3IsLongModeAllowed(pVM);
     2431            for (VMCPUID i = 0; i < pVM->cCpus; i++)
     2432            {
     2433                PVMCPU pVCpu = &pVM->aCpus[i];
     2434                /* While loading a saved-state we fix it up in, cpumR3LoadDone(). */
     2435                if (fSupportsLongMode)
     2436                    pVCpu->cpum.s.fUseFlags |= CPUM_USE_SUPPORTS_LONGMODE;
     2437            }
     2438
     2439            cpumR3MsrRegStats(pVM);
     2440            break;
     2441        }
     2442
     2443        case VMINITCOMPLETED_RING0:
     2444        {
     2445            /* Cache the APIC base (from the APIC device) once it has been initialized. */
     2446            for (VMCPUID i = 0; i < pVM->cCpus; i++)
     2447            {
     2448                PVMCPU pVCpu = &pVM->aCpus[i];
     2449                PDMApicGetBaseMsr(pVCpu, &pVCpu->cpum.s.Guest.msrApicBase, true /* fIgnoreErrors */);
     2450#ifdef VBOX_WITH_NEW_APIC
     2451                LogRel(("CPUM: VCPU%3d: Cached APIC base MSR = %#RX64\n", i, pVCpu->cpum.s.Guest.msrApicBase));
     2452#endif
     2453            }
     2454            break;
     2455        }
     2456
     2457        default:
     2458            break;
     2459    }
    24342460    return VINF_SUCCESS;
    24352461}
  • trunk/src/VBox/VMM/VMMR3/VM.cpp

    r60364 r60377  
    11831183        rc = APICR3InitCompleted(pVM, enmWhat);
    11841184#endif
     1185    if (RT_SUCCESS(rc))
     1186        rc = CPUMR3InitCompleted(pVM, enmWhat);
    11851187#ifndef VBOX_WITH_RAW_MODE
    11861188    if (enmWhat == VMINITCOMPLETED_RING3)
     
    28132815#endif
    28142816        IOMR3Reset(pVM);
    2815         CPUMR3Reset(pVM);
     2817        CPUMR3Reset(pVM);               /* This must come *after* PDM (due to APIC base MSR caching). */
    28162818        TMR3Reset(pVM);
    28172819        EMR3Reset(pVM);
  • trunk/src/VBox/VMM/VMMR3/VMM.cpp

    r60307 r60377  
    687687        {
    688688            /*
    689              * CPUM's post-initialization (APIC base MSR caching).
    690              */
    691             rc = CPUMR3InitCompleted(pVM);
    692             AssertRCReturn(rc, rc);
    693 
    694             /*
    695689             * Set page attributes to r/w for stack pages.
    696690             */
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