VirtualBox

Changeset 37062 in vbox for trunk


Ignore:
Timestamp:
May 13, 2011 10:18:29 AM (14 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
71699
Message:

VMM: Support for online/offlining of CPUs.

Location:
trunk/src/VBox
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/HostDrivers/Support/SUPDrv.c

    r36730 r37062  
    322322    { "RTMpIsCpuOnline",                        (void *)RTMpIsCpuOnline },
    323323    { "RTMpIsCpuWorkPending",                   (void *)RTMpIsCpuWorkPending },
     324    { "RTMpNotificationRegister",               (void *)RTMpNotificationRegister },
     325    { "RTMpNotificationDeregister",             (void *)RTMpNotificationDeregister },
    324326    { "RTMpOnAll",                              (void *)RTMpOnAll },
    325327    { "RTMpOnOthers",                           (void *)RTMpOnOthers },
     
    49904992
    49914993/**
     4994 * Helper for finding the CPU index from the CPU Id.
     4995 *
     4996 * @param    pGip               The GIP.
     4997 * @param    idCpu              The CPU ID.
     4998 *
     4999 * @returns Index of the CPU in the cache set.
     5000 */
     5001static inline uint32_t supdrvGipCpuIndexFromCpuId(PSUPGLOBALINFOPAGE pGip, RTCPUID idCpu)
     5002{
     5003    uint32_t i = 0;
     5004
     5005    /*
     5006     * Find our entry, or allocate one if not found.
     5007     * ASSUMES that CPU IDs are constant.
     5008     */
     5009    for (i = 0; i < pGip->cCpus; i++)
     5010        if (pGip->aCPUs[i].idCpu == idCpu)
     5011            break;
     5012
     5013    if (i >= pGip->cCpus)
     5014        for (i = 0; i < pGip->cCpus; i++)
     5015        {
     5016            bool fRc;
     5017            ASMAtomicCmpXchgSize(&pGip->aCPUs[i].idCpu, idCpu, NIL_RTCPUID, fRc);
     5018            if (fRc)
     5019                break;
     5020        }
     5021
     5022    AssertRelease(i < pGip->cCpus);
     5023    return i;
     5024}
     5025
     5026
     5027/**
    49925028 * The calling CPU should be accounted as online, update GIP accordingly.
    49935029 *
     
    49995035static void supdrvGipMpEventOnline(PSUPGLOBALINFOPAGE pGip, RTCPUID idCpu)
    50005036{
    5001     int         iCpuSet;
    5002     uint8_t     idApic;
    5003     uint32_t    i;
    5004 
    5005     Assert(idCpu == RTMpCpuId());
     5037    int         iCpuSet = 0;
     5038    uint16_t    idApic = UINT16_MAX;
     5039    uint32_t    i = 0;
     5040
     5041    AssertRelease(idCpu == RTMpCpuId());
    50065042    Assert(pGip->cPossibleCpus == RTMpGetCount());
    50075043
     
    50195055    }
    50205056
    5021     /*
    5022      * Find our entry, or allocate one if not found.
    5023      * ASSUMES that CPU IDs are constant.
    5024      */
    5025     for (i = 0; i < pGip->cCpus; i++)
    5026         if (pGip->aCPUs[i].idCpu == idCpu)
    5027             break;
    5028 
    5029     if (i >= pGip->cCpus)
    5030         for (i = 0; i < pGip->cCpus; i++)
    5031         {
    5032             bool fRc;
    5033             ASMAtomicCmpXchgSize(&pGip->aCPUs[i].idCpu, idCpu, NIL_RTCPUID, fRc);
    5034             if (fRc)
    5035                 break;
    5036         }
    5037 
    5038     AssertReturnVoid(i < pGip->cCpus);
     5057    i = supdrvGipCpuIndexFromCpuId(pGip, idCpu);
    50395058
    50405059    /*
     
    50455064    ASMAtomicUoWriteS16(&pGip->aCPUs[i].iCpuSet, (int16_t)iCpuSet);
    50465065    ASMAtomicUoWriteSize(&pGip->aCPUs[i].idCpu,  idCpu);
    5047     ASMAtomicWriteSize(&pGip->aCPUs[i].enmState, SUPGIPCPUSTATE_ONLINE);
    50485066
    50495067    /*
     
    50525070    ASMAtomicWriteU16(&pGip->aiCpuFromApicId[idApic],     i);
    50535071    ASMAtomicWriteU16(&pGip->aiCpuFromCpuSetIdx[iCpuSet], i);
     5072
     5073    ASMAtomicWriteSize(&pGip->aCPUs[i].enmState, SUPGIPCPUSTATE_ONLINE);
    50545074}
    50555075
     
    50765096
    50775097    Assert(RTCpuSetIsMemberByIndex(&pGip->PossibleCpuSet, iCpuSet));
     5098    RTCpuSetDelByIndex(&pGip->OnlineCpuSet, iCpuSet);
    50785099    ASMAtomicWriteSize(&pGip->aCPUs[i].enmState, SUPGIPCPUSTATE_OFFLINE);
    5079     RTCpuSetDelByIndex(&pGip->OnlineCpuSet, iCpuSet);
    50805100}
    50815101
     
    50955115    PSUPDRVDEVEXT       pDevExt = (PSUPDRVDEVEXT)pvUser;
    50965116    PSUPGLOBALINFOPAGE  pGip    = pDevExt->pGip;
     5117
     5118    AssertRelease(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
    50975119
    50985120    /*
     
    53595381        pGip->aCPUs[i].idCpu             = NIL_RTCPUID;
    53605382        pGip->aCPUs[i].iCpuSet           = -1;
    5361         pGip->aCPUs[i].idApic            = UINT8_MAX;
     5383        pGip->aCPUs[i].idApic            = UINT16_MAX;
    53625384
    53635385        /*
     
    56185640                                  RTCPUID idCpu, uint8_t idApic, uint64_t iTick)
    56195641{
     5642    /*
     5643     * Avoid a potential race when a CPU online notification doesn't fire on the onlined CPU
     5644     * but the tick creeps in before the event notification is run.
     5645     */
     5646    if (iTick == 1)
     5647    {
     5648        uint32_t i = supdrvGipCpuIndexFromCpuId(pGip, idCpu);
     5649        if (pGip->aCPUs[i].enmState == SUPGIPCPUSTATE_OFFLINE)
     5650            supdrvGipMpEventOnline(pGip, idCpu);
     5651    }
     5652
    56205653    unsigned iCpu = pGip->aiCpuFromApicId[idApic];
    56215654
  • trunk/src/VBox/Runtime/r0drv/solaris/vbi/mp-r0drv-solaris.c

    r36232 r37062  
    174174    PRTMPARGS pArgs = (PRTMPARGS)(uArg);
    175175
     176    /*
     177     * Solaris CPU cross calls execute on offline CPUs too. Check our CPU cache
     178     * set and ignore if it's offline.
     179     */
     180    if (!RTMpIsCpuOnline(RTMpCpuId()))
     181        return 0;
     182
    176183    pArgs->pfnWorker(RTMpCpuId(), pArgs->pvUser1, pArgs->pvUser2);
    177184
     
    279286        return VERR_CPU_NOT_FOUND;
    280287
     288    if (RT_UNLIKELY(!RTMpIsCpuOnline(idCpu)))
     289        return RTMpIsCpuPresent(idCpu) ? VERR_CPU_OFFLINE : VERR_CPU_NOT_FOUND;
     290
    281291    Args.pfnWorker = pfnWorker;
    282292    Args.pvUser1 = pvUser1;
  • trunk/src/VBox/Runtime/r0drv/solaris/vbi/mpnotification-r0drv-solaris.c

    r36555 r37062  
    3434#include <iprt/mp.h>
    3535#include <iprt/cpuset.h>
     36#include <iprt/string.h>
    3637#include "r0drv/mp-r0drv.h"
    3738
     
    4950
    5051
    51 static void rtMpNotificationSolarisCallback(void *pvUser, int iCpu, int online)
     52static void rtMpNotificationSolarisOnCurrentCpu(void *pvArgs, void *uIgnored1, void *uIgnored2)
    5253{
    53     NOREF(pvUser);
     54    NOREF(uIgnored1);
     55    NOREF(uIgnored2);
    5456
    55     /* ASSUMES iCpu == RTCPUID */
     57    PRTMPARGS pArgs = (PRTMPARGS)(pvArgs);
     58    AssertRelease(pArgs && pArgs->idCpu == RTMpCpuId());
     59    Assert(pArgs->pvUser2);
     60    Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
     61
     62    int online = *(int *)pArgs->pvUser2;
    5663    if (online)
    5764    {
    58         RTCpuSetAdd(&g_rtMpSolarisCpuSet, iCpu);
    59         rtMpNotificationDoCallbacks(RTMPEVENT_ONLINE, iCpu);
     65        RTCpuSetAdd(&g_rtMpSolarisCpuSet, pArgs->idCpu);
     66        rtMpNotificationDoCallbacks(RTMPEVENT_ONLINE, pArgs->idCpu);
    6067    }
    6168    else
    6269    {
    63         RTCpuSetDel(&g_rtMpSolarisCpuSet, iCpu);
    64         rtMpNotificationDoCallbacks(RTMPEVENT_OFFLINE, iCpu);
     70        RTCpuSetDel(&g_rtMpSolarisCpuSet, pArgs->idCpu);
     71        rtMpNotificationDoCallbacks(RTMPEVENT_OFFLINE, pArgs->idCpu);
    6572    }
     73}
     74
     75
     76static void rtMpNotificationSolarisCallback(void *pvUser, int iCpu, int online)
     77{
     78    vbi_preempt_disable();
     79
     80    RTMPARGS Args;
     81    RT_ZERO(Args);
     82    Args.pvUser1 = pvUser;
     83    Args.pvUser2 = &online;
     84    Args.idCpu   = iCpu;
     85
     86    /*
     87     * If we're not on the target CPU, schedule (synchronous) the event notification callback
     88     * to run on the target CPU i.e. the one pertaining to the MP event.
     89     */
     90    bool fRunningOnTargetCpu = iCpu == RTMpCpuId();      /* ASSUMES iCpu == RTCPUID */
     91    if (fRunningOnTargetCpu)
     92        rtMpNotificationSolarisOnCurrentCpu(&Args, NULL /* pvIgnored1 */, NULL /* pvIgnored2 */);
     93    else
     94        vbi_execute_on_one(rtMpNotificationSolarisOnCurrentCpu, &Args, iCpu);
     95
     96    vbi_preempt_enable();
    6697}
    6798
  • trunk/src/VBox/VMM/VMMR0/HWACCMR0.cpp

    r36913 r37062  
    5151static bool               hwaccmR0IsSubjectToVmxPreemptionTimerErratum(void);
    5252static DECLCALLBACK(void) hwaccmR0PowerCallback(RTPOWEREVENT enmEvent, void *pvUser);
     53static DECLCALLBACK(void) hwaccmR0CpuCallback(RTMPEVENT enmEvent, RTCPUID idCpu, void *pvData);
    5354
    5455/*******************************************************************************
     
    498499    if (!HWACCMR0Globals.vmx.fUsingSUPR0EnableVTx)
    499500    {
     501        rc = RTMpNotificationRegister(hwaccmR0CpuCallback, 0);
     502        AssertRC(rc);
     503
    500504        rc = RTPowerNotificationRegister(hwaccmR0PowerCallback, 0);
    501505        AssertRC(rc);
     
    575579        if (!HWACCMR0Globals.vmx.fUsingSUPR0EnableVTx)
    576580        {
     581            /* Doesn't really matter if this fails. */
     582            rc = RTMpNotificationDeregister(hwaccmR0CpuCallback, 0);
     583            AssertRC(rc);
    577584            rc = RTPowerNotificationDeregister(hwaccmR0PowerCallback, 0);
    578585            AssertRC(rc);
     
    732739                Assert(!HWACCMR0Globals.aCpuInfo[i].pMemObj);
    733740
    734                 /** @todo this is rather dangerous if cpus can be taken offline; we don't care for now */
    735                 if (RTMpIsCpuOnline(i))
     741                if (RTMpIsCpuPossible(RTMpCpuId()))
    736742                {
    737743                    rc = RTR0MemObjAllocCont(&HWACCMR0Globals.aCpuInfo[i].pMemObj, 1 << PAGE_SHIFT, true /* executable R0 mapping */);
     
    748754#endif
    749755                }
     756                HWACCMR0Globals.aCpuInfo[i].fConfigured = false;
    750757            }
    751758            if (HWACCMR0Globals.fGlobalInit)
     
    798805    if (!pCpu->pMemObj)
    799806    {
     807        LogRel(("HWACCMR0: hwaccmR0EnableCpu failed idCpu=%d.\n", idCpu));
    800808        AssertFailed();
    801809        return VERR_INTERNAL_ERROR;
     
    883891    hwaccmR0FirstRcSetStatus(pFirstRc, hwaccmR0DisableCpu(idCpu));
    884892}
     893
     894
     895/**
     896 * Callback function invoked when a cpu goes online or offline.
     897 *
     898 * @param   enmEvent            The Mp event.
     899 * @param   idCpu               The identifier for the CPU the function is called on.
     900 * @param   pvData              Opaque data (PVM pointer).
     901 */
     902static DECLCALLBACK(void) hwaccmR0CpuCallback(RTMPEVENT enmEvent, RTCPUID idCpu, void *pvData)
     903{
     904    /*
     905     * We only care about uninitializing a CPU that is going offline. When a
     906     * CPU comes online, the initialization is done lazily in HWACCMR0Enter().
     907     */
     908    AssertRelease(idCpu == RTMpCpuId());
     909    Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
     910    switch (enmEvent)
     911    {
     912        case RTMPEVENT_OFFLINE:
     913        {
     914            int rc = hwaccmR0DisableCpu(idCpu);
     915            AssertRC(rc);
     916            break;
     917        }
     918
     919        default:
     920            break;
     921    }
     922}
     923
    885924
    886925/**
     
    11291168 *
    11301169 * @returns VBox status code.
    1131  * @param   pVM         The VM to operate on.
    1132  * @param   pVCpu      VMCPUD id.
     1170 * @param   pVM        The VM to operate on.
     1171 * @param   pVCpu      VMCPU handle.
    11331172 */
    11341173VMMR0DECL(int) HWACCMR0Enter(PVM pVM, PVMCPU pVCpu)
     
    11631202        pVM->hwaccm.s.u64RegisterMask = UINT64_C(0xFFFFFFFF);
    11641203
    1165     /* Enable VT-x or AMD-V if local init is required. */
    1166     if (!HWACCMR0Globals.fGlobalInit)
     1204    /* Enable VT-x or AMD-V if local init is required, or enable if it's a freshly onlined CPU. */
     1205    if (   !pCpu->fConfigured
     1206        || !HWACCMR0Globals.fGlobalInit)
    11671207    {
    11681208        rc = hwaccmR0EnableCpu(pVM, idCpu);
     
    11981238 *
    11991239 * @returns VBox status code.
    1200  * @param   pVM         The VM to operate on.
    1201  * @param   pVCpu      VMCPUD id.
     1240 * @param   pVM        The VM to operate on.
     1241 * @param   pVCpu      VMCPU handle.
    12021242 */
    12031243VMMR0DECL(int) HWACCMR0Leave(PVM pVM, PVMCPU pVCpu)
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