VirtualBox

Changeset 39306 in vbox for trunk/src/VBox/Devices/PC


Ignore:
Timestamp:
Nov 15, 2011 1:14:13 PM (13 years ago)
Author:
vboxsync
Message:

DevAPIC: > 32 CPUs, cleanups.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Devices/PC/DevAPIC.cpp

    r39136 r39306  
    66
    77/*
    8  * Copyright (C) 2006-2010 Oracle Corporation
     8 * Copyright (C) 2006-2011 Oracle Corporation
    99 *
    1010 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    4848#include <VBox/log.h>
    4949#include <VBox/vmm/stam.h>
     50#include <VBox/vmm/vmcpuset.h>
     51#include <iprt/asm.h>
    5052#include <iprt/assert.h>
    51 #include <iprt/asm.h>
    5253
    5354#include <VBox/msi.h>
     
    125126    } while (0)
    126127
    127 #define foreach_apic(pDev, mask, code)                    \
    128     do {                                                  \
    129         APICState *apic = (pDev)->CTX_SUFF(paLapics);     \
    130         for (uint32_t i = 0; i < (pDev)->cCpus; i++)      \
    131         {                                                 \
    132             if (mask & (1 << (apic->id)))                 \
    133             {                                             \
    134                 code;                                     \
    135             }                                             \
    136             apic++;                                       \
    137         }                                                 \
     128/**
     129 * Begins an APIC enumeration block.
     130 *
     131 * Code placed between this and the APIC_FOREACH_END macro will be executed for
     132 * each APIC instance present in the system.
     133 *
     134 * @param   a_pDev      The APIC device.
     135 */
     136#define APIC_FOREACH_BEGIN(a_pDev) \
     137    do { \
     138        VMCPUID const cApics   = (a_pDev)->cCpus; \
     139        APICState    *pCurApic = (a_pDev)->CTX_SUFF(paLapics); \
     140        for (VMCPUID  iCurApic = 0; iCurApic < cApics; iCurApic++, pCurApic++) \
     141        { \
     142            do { } while (0)
     143
     144/**
     145 * Begins an APIC enumeration block, given a destination set.
     146 *
     147 * Code placed between this and the APIC_FOREACH_END macro will be executed for
     148 * each APIC instance present in @a a_pDstSet.
     149 *
     150 * @param   a_pDev      The APIC device.
     151 * @param   a_pDstSet   The destination set.
     152 */
     153#define APIC_FOREACH_IN_SET_BEGIN(a_pDev, a_pDstSet) \
     154    APIC_FOREACH_BEGIN(a_pDev); \
     155        if (!VMCPUSET_IS_PRESENT((a_pDstSet), iCurApic)) \
     156            continue; \
     157        do { } while (0)
     158
     159
     160/** Counterpart to APIC_FOREACH_IN_SET_BEGIN and APIC_FOREACH_BEGIN. */
     161#define APIC_FOREACH_END() \
     162        } \
    138163    } while (0)
    139 
    140 # define set_bit(pvBitmap, iBit)    ASMBitSet(pvBitmap, iBit)
    141 # define reset_bit(pvBitmap, iBit)  ASMBitClear(pvBitmap, iBit)
    142 # define fls_bit(value)             (ASMBitLastSetU32(value) - 1)
    143 # define ffs_bit(value)             (ASMBitFirstSetU32(value) - 1)
    144164
    145165#define DEBUG_APIC
     
    190210*   Structures and Typedefs                                                    *
    191211*******************************************************************************/
    192 typedef struct APICState {
     212typedef struct APIC256BITREG
     213{
     214    /** The bitmap data.  */
     215    uint32_t    au32Bitmap[8 /*256/32*/];
     216} APIC256BITREG;
     217typedef APIC256BITREG *PAPIC256BITREG;
     218typedef APIC256BITREG const *PCAPIC256BITREG;
     219
     220/**
     221 * Tests if a bit in the 256-bit APIC register is set.
     222 *
     223 * @returns true if set, false if clear.
     224 *
     225 * @param   pReg        The register.
     226 * @param   iBit        The bit to test for.
     227 */
     228DECLINLINE(bool) Apic256BitReg_IsBitSet(PCAPIC256BITREG pReg, unsigned iBit)
     229{
     230    Assert(iBit < 256);
     231    return ASMBitTest(&pReg->au32Bitmap[0], iBit);
     232}
     233
     234
     235/**
     236 * Sets a bit in the 256-bit APIC register is set.
     237 *
     238 * @param   pReg        The register.
     239 * @param   iBit        The bit to set.
     240 */
     241DECLINLINE(void) Apic256BitReg_SetBit(PAPIC256BITREG pReg, unsigned iBit)
     242{
     243    Assert(iBit < 256);
     244    return ASMBitSet(&pReg->au32Bitmap[0], iBit);
     245}
     246
     247
     248/**
     249 * Clears a bit in the 256-bit APIC register is set.
     250 *
     251 * @param   pReg        The register.
     252 * @param   iBit        The bit to clear.
     253 */
     254DECLINLINE(void) Apic256BitReg_ClearBit(PAPIC256BITREG pReg, unsigned iBit)
     255{
     256    Assert(iBit < 256);
     257    return ASMBitClear(&pReg->au32Bitmap[0], iBit);
     258}
     259
     260/**
     261 * Clears all bits in the 256-bit APIC register set.
     262 *
     263 * @param   pReg        The register.
     264 */
     265DECLINLINE(void) Apic256BitReg_Empty(PAPIC256BITREG pReg)
     266{
     267    memset(&pReg->au32Bitmap[0], 0, sizeof(pReg->au32Bitmap));
     268}
     269
     270/**
     271 * Finds the last bit set in the register, i.e. the highest priority interrupt.
     272 *
     273 * @returns The index of the found bit, @a iRetAllClear if none was found.
     274 *
     275 * @param   pReg            The register.
     276 * @param   iRetAllClear    What to return if all bits are clear.
     277 */
     278static int Apic256BitReg_FindLastSetBit(PCAPIC256BITREG pReg, int iRetAllClear)
     279{
     280    uint32_t i = RT_ELEMENTS(pReg->au32Bitmap);
     281    while (i-- > 0)
     282    {
     283        uint32_t u = pReg->au32Bitmap[i];
     284        if (u)
     285        {
     286            u = ASMBitLastSetU32(u);
     287            u--;
     288            u |= i << 5;
     289            return (int)u;
     290        }
     291    }
     292    return iRetAllClear;
     293}
     294
     295
     296typedef struct APICState
     297{
    193298    uint32_t apicbase;
    194299    /* Task priority register (interrupt level) */
     
    203308    uint8_t log_dest;
    204309    uint8_t dest_mode;
    205     uint32_t isr[8];  /* in service register */
    206     uint32_t tmr[8];  /* trigger mode register */
    207     uint32_t irr[8]; /* interrupt request register */
     310    APIC256BITREG isr;  /**< in service register */
     311    APIC256BITREG tmr;  /**< trigger mode register */
     312    APIC256BITREG irr;  /**< interrupt request register */
    208313    uint32_t lvt[APIC_LVT_NB];
    209314    uint32_t esr; /* error register */
     
    319424
    320425static void apic_eoi(APICDeviceInfo *pDev, APICState* s); /*  */
    321 static uint32_t apic_get_delivery_bitmask(APICDeviceInfo* pDev, uint8_t dest, uint8_t dest_mode);
     426static PVMCPUSET apic_get_delivery_bitmask(APICDeviceInfo* pDev, uint8_t dest, uint8_t dest_mode, PVMCPUSET pDstSet);
    322427static int apic_deliver(APICDeviceInfo* pDev, APICState *s,
    323428                        uint8_t dest, uint8_t dest_mode,
     
    359464    LogFlow(("apic: setting interrupt flag for cpu %d\n", getCpuFromLapic(pDev, s)));
    360465    pDev->CTX_SUFF(pApicHlp)->pfnSetInterruptFF(pDev->CTX_SUFF(pDevIns), enmType,
    361                                                getCpuFromLapic(pDev, s));
     466                                                getCpuFromLapic(pDev, s));
    362467}
    363468
     
    366471    LogFlow(("apic: clear interrupt flag\n"));
    367472    pDev->CTX_SUFF(pApicHlp)->pfnClearInterruptFF(pDev->CTX_SUFF(pDevIns), enmType,
    368                                                  getCpuFromLapic(pDev, s));
     473                                                  getCpuFromLapic(pDev, s));
    369474}
    370475
     
    376481
    377482    pDev->pApicHlpR3->pfnSendSipi(pDev->pDevInsR3,
    378                                  getCpuFromLapic(pDev, s),
    379                                  vector);
     483                                  getCpuFromLapic(pDev, s),
     484                                  vector);
    380485}
    381486
     
    424529
    425530static int apic_bus_deliver(APICDeviceInfo* pDev,
    426                             uint32_t deliver_bitmask, uint8_t delivery_mode,
     531                            PCVMCPUSET pDstSet, uint8_t delivery_mode,
    427532                            uint8_t vector_num, uint8_t polarity,
    428533                            uint8_t trigger_mode)
    429534{
    430     LogFlow(("apic_bus_deliver mask=%x mode=%x vector=%x polarity=%x trigger_mode=%x\n", deliver_bitmask, delivery_mode, vector_num, polarity, trigger_mode));
    431     switch (delivery_mode) {
     535    LogFlow(("apic_bus_deliver mask=%R[vmcpuset] mode=%x vector=%x polarity=%x trigger_mode=%x\n",
     536             pDstSet, delivery_mode, vector_num, polarity, trigger_mode));
     537
     538    switch (delivery_mode)
     539    {
    432540        case APIC_DM_LOWPRI:
    433541        {
    434             int d = -1;
    435             if (deliver_bitmask)
    436                 d = ffs_bit(deliver_bitmask);
    437             if (d >= 0)
     542            VMCPUID idDstCpu = VMCPUSET_FIND_FIRST_PRESENT(pDstSet);
     543            if (idDstCpu != NIL_VMCPUID)
    438544            {
    439                 APICState* apic = getLapicById(pDev, d);
    440                 apic_set_irq(pDev, apic, vector_num, trigger_mode);
     545                APICState *pApic = getLapicById(pDev, idDstCpu);
     546                apic_set_irq(pDev, pApic, vector_num, trigger_mode);
    441547            }
    442548            return VINF_SUCCESS;
    443549        }
     550
    444551        case APIC_DM_FIXED:
    445             /* XXX: arbitration */
     552            /** @todo XXX: arbitration */
    446553            break;
    447554
    448555        case APIC_DM_SMI:
    449             foreach_apic(pDev, deliver_bitmask,
    450                          cpuSetInterrupt(pDev, apic, PDMAPICIRQ_SMI));
     556            APIC_FOREACH_IN_SET_BEGIN(pDev, pDstSet);
     557                cpuSetInterrupt(pDev, pCurApic, PDMAPICIRQ_SMI);
     558            APIC_FOREACH_END();
    451559            return VINF_SUCCESS;
    452560
    453561        case APIC_DM_NMI:
    454             foreach_apic(pDev, deliver_bitmask,
    455                          cpuSetInterrupt(pDev, apic, PDMAPICIRQ_NMI));
     562            APIC_FOREACH_IN_SET_BEGIN(pDev, pDstSet);
     563                cpuSetInterrupt(pDev, pCurApic, PDMAPICIRQ_NMI);
     564            APIC_FOREACH_END();
    456565            return VINF_SUCCESS;
    457566
     
    459568            /* normal INIT IPI sent to processors */
    460569#ifdef IN_RING3
    461             foreach_apic(pDev, deliver_bitmask,
    462                          apicSendInitIpi(pDev, apic));
     570            APIC_FOREACH_IN_SET_BEGIN(pDev, pDstSet);
     571                apicSendInitIpi(pDev, pCurApic);
     572            APIC_FOREACH_END();
    463573            return VINF_SUCCESS;
    464574#else
    465             /* We shall send init IPI only in R3, R0 calls should be
    466                rescheduled to R3 */
     575            /* We shall send init IPI only in R3. */
    467576            return VINF_IOM_HC_MMIO_READ_WRITE;
    468577#endif /* IN_RING3 */
     578
    469579        case APIC_DM_EXTINT:
    470580            /* handled in I/O APIC code */
     
    475585    }
    476586
    477     foreach_apic(pDev, deliver_bitmask,
    478                        apic_set_irq (pDev, apic, vector_num, trigger_mode));
     587    APIC_FOREACH_IN_SET_BEGIN(pDev, pDstSet);
     588        apic_set_irq(pDev, pCurApic, vector_num, trigger_mode);
     589    APIC_FOREACH_END();
    479590    return VINF_SUCCESS;
    480591}
     
    712823                APIC_LOCK(pDev, rcBusy);
    713824                int vector = u64Value & 0xff;
     825                VMCPUSET SelfSet;
     826                VMCPUSET_EMPTY(&SelfSet);
     827                VMCPUSET_ADD(&SelfSet, pApic->id);
    714828                rc = apic_bus_deliver(pDev,
    715                                       1 << pApic->id /* Self */,
     829                                      &SelfSet,
    716830                                      0 /* Delivery mode - fixed */,
    717831                                      vector,
     
    838952        case 0x10: case 0x11: case 0x12: case 0x13: case 0x14: case 0x15: case 0x16: case 0x17:
    839953            APIC_LOCK(pDev, rcBusy);
    840             *pu64Value = pApic->isr[iReg & 7];
     954            *pu64Value = pApic->isr.au32Bitmap[iReg & 7];
    841955            APIC_UNLOCK(pDev);
    842956            break;
     
    844958        case 0x18: case 0x19: case 0x1a: case 0x1b: case 0x1c: case 0x1d: case 0x1e: case 0x1f:
    845959            APIC_LOCK(pDev, rcBusy);
    846             *pu64Value = pApic->tmr[iReg & 7];
     960            *pu64Value = pApic->tmr.au32Bitmap[iReg & 7];
    847961            APIC_UNLOCK(pDev);
    848962            break;
     
    850964        case 0x20: case 0x21: case 0x22: case 0x23: case 0x24: case 0x25: case 0x26: case 0x27:
    851965            APIC_LOCK(pDev, rcBusy);
    852             *pu64Value = pApic->irr[iReg & 7];
     966            *pu64Value = pApic->irr.au32Bitmap[iReg & 7];
    853967            APIC_UNLOCK(pDev);
    854968            break;
     
    9631077 */
    9641078PDMBOTHCBDECL(int) apicBusDeliverCallback(PPDMDEVINS pDevIns, uint8_t u8Dest, uint8_t u8DestMode,
    965                                            uint8_t u8DeliveryMode, uint8_t iVector, uint8_t u8Polarity,
    966                                            uint8_t u8TriggerMode)
     1079                                          uint8_t u8DeliveryMode, uint8_t iVector, uint8_t u8Polarity,
     1080                                          uint8_t u8TriggerMode)
    9671081{
    9681082    APICDeviceInfo *pDev = PDMINS_2_DATA(pDevIns, APICDeviceInfo *);
     
    9701084    LogFlow(("apicBusDeliverCallback: pDevIns=%p u8Dest=%#x u8DestMode=%#x u8DeliveryMode=%#x iVector=%#x u8Polarity=%#x u8TriggerMode=%#x\n",
    9711085             pDevIns, u8Dest, u8DestMode, u8DeliveryMode, iVector, u8Polarity, u8TriggerMode));
    972     return apic_bus_deliver(pDev, apic_get_delivery_bitmask(pDev, u8Dest, u8DestMode),
     1086    VMCPUSET DstSet;
     1087    return apic_bus_deliver(pDev, apic_get_delivery_bitmask(pDev, u8Dest, u8DestMode, &DstSet),
    9731088                            u8DeliveryMode, iVector, u8Polarity, u8TriggerMode);
    9741089}
     
    10641179}
    10651180
    1066 /* return -1 if no bit is set */
    1067 static int get_highest_priority_int(uint32_t const *tab)
    1068 {
    1069     int i;
    1070     for(i = 7; i >= 0; i--) {
    1071         if (tab[i] != 0) {
    1072             return i * 32 + fls_bit(tab[i]);
    1073         }
    1074     }
    1075     return -1;
    1076 }
    1077 
    10781181static int apic_get_ppr(APICState const *s)
    10791182{
    1080     int tpr, isrv, ppr;
    1081 
    1082     tpr = (s->tpr >> 4);
    1083     isrv = get_highest_priority_int(s->isr);
    1084     if (isrv < 0)
    1085         isrv = 0;
     1183    int ppr;
     1184
     1185    int tpr = (s->tpr >> 4);
     1186    int isrv = Apic256BitReg_FindLastSetBit(&s->isr, 0);
    10861187    isrv >>= 4;
    10871188    if (tpr >= isrv)
     
    10941195static int apic_get_ppr_zero_tpr(APICState *s)
    10951196{
    1096     int isrv;
    1097 
    1098     isrv = get_highest_priority_int(s->isr);
    1099     if (isrv < 0)
    1100         isrv = 0;
    1101     return isrv;
     1197    return Apic256BitReg_FindLastSetBit(&s->isr, 0);
    11021198}
    11031199
    11041200static int apic_get_arb_pri(APICState const *s)
    11051201{
    1106     /* XXX: arbitration */
     1202    /** @todo XXX: arbitration */
    11071203    return 0;
    11081204}
     
    11111207static bool apic_update_irq(APICDeviceInfo *pDev, APICState* s)
    11121208{
    1113     int irrv, ppr;
    11141209    if (!(s->spurious_vec & APIC_SV_ENABLE))
    11151210    {
     
    11191214    }
    11201215
    1121     irrv = get_highest_priority_int(s->irr);
     1216    int irrv = Apic256BitReg_FindLastSetBit(&s->irr, -1);
    11221217    if (irrv < 0)
    11231218        return false;
    1124     ppr = apic_get_ppr(s);
     1219    int ppr = apic_get_ppr(s);
    11251220    if (ppr && (irrv & 0xf0) <= (ppr & 0xf0))
    11261221        return false;
     
    11321227PDMBOTHCBDECL(bool) apicHasPendingIrq(PPDMDEVINS pDevIns)
    11331228{
    1134     int irrv, ppr;
    11351229    APICDeviceInfo *pDev = PDMINS_2_DATA(pDevIns, APICDeviceInfo *);
    11361230    if (!pDev)
     
    11431237    /*
    11441238     * All our callbacks now come from single IOAPIC, thus locking
    1145      * seems to be excessive now (@todo: check)
     1239     * seems to be excessive now
    11461240     */
    1147     irrv = get_highest_priority_int(s->irr);
     1241    /** @todo check excessive locking whatever... */
     1242    int irrv = Apic256BitReg_FindLastSetBit(&s->irr, -1);
    11481243    if (irrv < 0)
    11491244        return false;
    11501245
    1151     ppr = apic_get_ppr_zero_tpr(s);
     1246    int ppr = apic_get_ppr_zero_tpr(s);
    11521247
    11531248    if (ppr && (irrv & 0xf0) <= (ppr & 0xf0))
     
    11781273{
    11791274    LogFlow(("CPU%d: apic_set_irq vector=%x, trigger_mode=%x\n", s->phys_id, vector_num, trigger_mode));
    1180     set_bit(s->irr, vector_num);
     1275    Apic256BitReg_SetBit(&s->irr, vector_num);
    11811276    if (trigger_mode)
    1182         set_bit(s->tmr, vector_num);
     1277        Apic256BitReg_SetBit(&s->tmr, vector_num);
    11831278    else
    1184         reset_bit(s->tmr, vector_num);
     1279        Apic256BitReg_ClearBit(&s->tmr, vector_num);
    11851280    apic_update_irq(pDev, s);
    11861281}
     
    11881283static void apic_eoi(APICDeviceInfo *pDev, APICState* s)
    11891284{
    1190     int isrv;
    1191     isrv = get_highest_priority_int(s->isr);
     1285    int isrv = Apic256BitReg_FindLastSetBit(&s->isr, -1);
    11921286    if (isrv < 0)
    11931287        return;
    1194     reset_bit(s->isr, isrv);
     1288    Apic256BitReg_ClearBit(&s->isr, isrv);
    11951289    LogFlow(("CPU%d: apic_eoi isrv=%x\n", s->phys_id, isrv));
    1196     /* XXX: send the EOI packet to the APIC bus to allow the I/O APIC to
    1197             set the remote IRR bit for level triggered interrupts. */
     1290    /** @todo XXX: send the EOI packet to the APIC bus to allow the I/O APIC to
     1291     *             set the remote IRR bit for level triggered interrupts. */
    11981292    apic_update_irq(pDev, s);
    11991293}
    12001294
    1201 static uint32_t apic_get_delivery_bitmask(APICDeviceInfo *pDev, uint8_t dest, uint8_t dest_mode)
    1202 {
    1203     uint32_t mask = 0;
     1295static PVMCPUSET apic_get_delivery_bitmask(APICDeviceInfo *pDev, uint8_t dest, uint8_t dest_mode, PVMCPUSET pDstSet)
     1296{
     1297    VMCPUSET_EMPTY(pDstSet);
    12041298
    12051299    if (dest_mode == 0)
    12061300    {
    12071301        if (dest == 0xff)
    1208             mask = 0xff;
     1302        {
     1303            /* was: mask = 0xff; - weird */ /** @todo check this; could this (1) differ on X2APIC and (2) actully mean a broadcast? */
     1304            for (VMCPUID iCpu = 0; iCpu < 8; iCpu++)
     1305                VMCPUSET_ADD(pDstSet, iCpu);
     1306        }
    12091307        else
    1210             mask = 1 << dest;
     1308            VMCPUSET_ADD(pDstSet, dest);
    12111309    }
    12121310    else
    12131311    {
    1214         APICState *apic = pDev->CTX_SUFF(paLapics);
    1215         uint32_t i;
    1216 
    1217         /* XXX: cluster mode */
    1218         for(i = 0; i < pDev->cCpus; i++)
    1219         {
    1220             if (apic->dest_mode == APIC_DESTMODE_FLAT)
     1312        /** @todo XXX: cluster mode */
     1313        APIC_FOREACH_BEGIN(pDev);
     1314            if (pCurApic->dest_mode == APIC_DESTMODE_FLAT)
    12211315            {
    1222                 if (dest & apic->log_dest)
    1223                     mask |= (1 << i);
     1316                if (dest & pCurApic->log_dest)
     1317                    VMCPUSET_ADD(pDstSet, iCurApic);
    12241318            }
    1225             else if (apic->dest_mode == APIC_DESTMODE_CLUSTER)
     1319            else if (pCurApic->dest_mode == APIC_DESTMODE_CLUSTER)
    12261320            {
    1227                 if ((dest & 0xf0) == (apic->log_dest & 0xf0)
    1228                     &&
    1229                     (dest & apic->log_dest & 0x0f))
    1230                 {
    1231                     mask |= (1 << i);
    1232                 }
     1321                if (   (dest & 0xf0) == (pCurApic->log_dest & 0xf0)
     1322                    && (dest & pCurApic->log_dest & 0x0f))
     1323                    VMCPUSET_ADD(pDstSet, iCurApic);
    12331324            }
    1234             apic++;
    1235         }
    1236     }
    1237 
    1238     return mask;
     1325        APIC_FOREACH_END();
     1326    }
     1327
     1328    return pDstSet;
    12391329}
    12401330
     
    12501340    s->log_dest = 0;
    12511341    s->dest_mode = 0xff; /** @todo 0xff???? */
    1252     memset(s->isr, 0, sizeof(s->isr));
    1253     memset(s->tmr, 0, sizeof(s->tmr));
    1254     memset(s->irr, 0, sizeof(s->irr));
     1342    Apic256BitReg_Empty(&s->isr);
     1343    Apic256BitReg_Empty(&s->tmr);
     1344    Apic256BitReg_Empty(&s->irr);
    12551345    s->esr = 0;
    12561346    memset(s->icr, 0, sizeof(s->icr));
     
    12771367#endif /* IN_RING3 */
    12781368
    1279 static int  apic_deliver(APICDeviceInfo* pDev, APICState *s,
     1369static int  apic_deliver(APICDeviceInfo *pDev, APICState *s,
    12801370                         uint8_t dest, uint8_t dest_mode,
    12811371                         uint8_t delivery_mode, uint8_t vector_num,
    12821372                         uint8_t polarity, uint8_t trigger_mode)
    12831373{
    1284     uint32_t deliver_bitmask = 0;
    12851374    int dest_shorthand = (s->icr[0] >> 18) & 3;
    1286 
    12871375    LogFlow(("apic_deliver dest=%x dest_mode=%x dest_shorthand=%x delivery_mode=%x vector_num=%x polarity=%x trigger_mode=%x\n", dest, dest_mode, dest_shorthand, delivery_mode, vector_num, polarity, trigger_mode));
    12881376
    1289     switch (dest_shorthand) {
     1377    VMCPUSET DstSet;
     1378    switch (dest_shorthand)
     1379    {
    12901380        case 0:
    1291             deliver_bitmask = apic_get_delivery_bitmask(pDev, dest, dest_mode);
     1381            apic_get_delivery_bitmask(pDev, dest, dest_mode, &DstSet);
    12921382            break;
    12931383        case 1:
    1294             deliver_bitmask = (1 << s->id);
     1384            VMCPUSET_EMPTY(&DstSet);
     1385            VMCPUSET_ADD(&DstSet, s->id);
    12951386            break;
    12961387        case 2:
    1297             deliver_bitmask = 0xffffffff;
     1388            VMCPUSET_FILL(&DstSet);
    12981389            break;
    12991390        case 3:
    1300             deliver_bitmask = 0xffffffff & ~(1 << s->id);
    1301             break;
    1302     }
    1303 
    1304     switch (delivery_mode) {
     1391            VMCPUSET_FILL(&DstSet);
     1392            VMCPUSET_DEL(&DstSet, s->id);
     1393            break;
     1394    }
     1395
     1396    switch (delivery_mode)
     1397    {
    13051398        case APIC_DM_INIT:
     1399        {
     1400            uint32_t const trig_mode = (s->icr[0] >> 15) & 1;
     1401            uint32_t const level     = (s->icr[0] >> 14) & 1;
     1402            if (level == 0 && trig_mode == 1)
    13061403            {
    1307                 int trig_mode = (s->icr[0] >> 15) & 1;
    1308                 int level = (s->icr[0] >> 14) & 1;
    1309                 if (level == 0 && trig_mode == 1) {
    1310                     foreach_apic(pDev, deliver_bitmask,
    1311                                        apic->arb_id = apic->id);
    1312                     Log(("CPU%d: APIC_DM_INIT arbitration id(s) set\n", s->phys_id));
    1313                     return VINF_SUCCESS;
    1314                 }
     1404                APIC_FOREACH_IN_SET_BEGIN(pDev, &DstSet);
     1405                    pCurApic->arb_id = pCurApic->id;
     1406                APIC_FOREACH_END();
     1407                Log(("CPU%d: APIC_DM_INIT arbitration id(s) set\n", s->phys_id));
     1408                return VINF_SUCCESS;
    13151409            }
    13161410            break;
     1411        }
    13171412
    13181413        case APIC_DM_SIPI:
    13191414# ifdef IN_RING3
    1320             foreach_apic(pDev, deliver_bitmask,
    1321                          apic_startup(pDev, apic, vector_num));
     1415            APIC_FOREACH_IN_SET_BEGIN(pDev, &DstSet);
     1416                apic_startup(pDev, pCurApic, vector_num);
     1417            APIC_FOREACH_END();
    13221418            return VINF_SUCCESS;
    13231419# else
    13241420            /* We shall send SIPI only in R3, R0 calls should be
    13251421               rescheduled to R3 */
    1326             return  VINF_IOM_HC_MMIO_WRITE;
     1422            return VINF_IOM_HC_MMIO_WRITE;
    13271423# endif
    13281424    }
    13291425
    1330     return apic_bus_deliver(pDev, deliver_bitmask, delivery_mode, vector_num,
     1426    return apic_bus_deliver(pDev, &DstSet, delivery_mode, vector_num,
    13311427                            polarity, trigger_mode);
    13321428}
     
    13471443
    13481444    APICState *s = getLapic(pDev);  /** @todo fix interface */
    1349     int intno;
    1350 
    1351     if (!(s->spurious_vec & APIC_SV_ENABLE)) {
     1445
     1446    if (!(s->spurious_vec & APIC_SV_ENABLE))
     1447    {
    13521448        Log(("CPU%d: apic_get_interrupt: returns -1 (APIC_SV_ENABLE)\n", s->phys_id));
    13531449        return -1;
    13541450    }
    13551451
    1356     /* XXX: spurious IRQ handling */
    1357     intno = get_highest_priority_int(s->irr);
    1358     if (intno < 0) {
     1452    /** @todo XXX: spurious IRQ handling */
     1453    int intno = Apic256BitReg_FindLastSetBit(&s->irr, -1);
     1454    if (intno < 0)
     1455    {
    13591456        Log(("CPU%d: apic_get_interrupt: returns -1 (irr)\n", s->phys_id));
    13601457        return -1;
    13611458    }
    1362     if (s->tpr && (uint32_t)intno <= s->tpr) {
     1459
     1460    if (s->tpr && (uint32_t)intno <= s->tpr)
     1461    {
    13631462        Log(("apic_get_interrupt: returns %d (sp)\n", s->spurious_vec & 0xff));
    13641463        return s->spurious_vec & 0xff;
    13651464    }
    1366     reset_bit(s->irr, intno);
    1367     set_bit(s->isr, intno);
     1465    Apic256BitReg_ClearBit(&s->irr, intno);
     1466    Apic256BitReg_SetBit(&s->isr, intno);
    13681467    apic_update_irq(pDev, s);
    13691468    LogFlow(("CPU%d: apic_get_interrupt: returns %d\n", s->phys_id, intno));
     
    16211720    SSMR3PutU8(f,  s->dest_mode);
    16221721    for (i = 0; i < 8; i++) {
    1623         SSMR3PutU32(f, s->isr[i]);
    1624         SSMR3PutU32(f, s->tmr[i]);
    1625         SSMR3PutU32(f, s->irr[i]);
     1722        SSMR3PutU32(f, s->isr.au32Bitmap[i]);
     1723        SSMR3PutU32(f, s->tmr.au32Bitmap[i]);
     1724        SSMR3PutU32(f, s->irr.au32Bitmap[i]);
    16261725    }
    16271726    for (i = 0; i < APIC_LVT_NB; i++) {
     
    16451744    int i;
    16461745
    1647      /* XXX: what if the base changes? (registered memory regions) */
     1746    /** @todo XXX: what if the base changes? (registered memory regions) */
    16481747    SSMR3GetU32(f, &s->apicbase);
    16491748
     
    16751774    SSMR3GetU8(f, &s->dest_mode);
    16761775    for (i = 0; i < 8; i++) {
    1677         SSMR3GetU32(f, &s->isr[i]);
    1678         SSMR3GetU32(f, &s->tmr[i]);
    1679         SSMR3GetU32(f, &s->irr[i]);
     1776        SSMR3GetU32(f, &s->isr.au32Bitmap[i]);
     1777        SSMR3GetU32(f, &s->tmr.au32Bitmap[i]);
     1778        SSMR3GetU32(f, &s->irr.au32Bitmap[i]);
    16801779    }
    16811780    for (i = 0; i < APIC_LVT_NB; i++) {
     
    18221921static void apicR3DumpVec(APICDeviceInfo *pDev, APICState *pApic, PCDBGFINFOHLP pHlp, uint32_t iStartReg)
    18231922{
    1824     for (uint32_t i = 0; i < 8; ++i)
     1923    for (uint32_t i = 0; i < 8; i++)
    18251924        pHlp->pfnPrintf(pHlp, "%08x", apicR3InfoReadReg(pDev, pApic, iStartReg + i));
    18261925    pHlp->pfnPrintf(pHlp, "\n");
     
    18631962    pHlp->pfnPrintf(pHlp, "  ISR       : ");
    18641963    apicR3DumpVec(pDev, pApic, pHlp, 0x10);
    1865     int iMax = get_highest_priority_int(pApic->isr);
     1964    int iMax = Apic256BitReg_FindLastSetBit(&pApic->isr, -1);
    18661965    pHlp->pfnPrintf(pHlp, "    highest = %02x\n", iMax == -1 ? 0 : iMax);
    18671966    pHlp->pfnPrintf(pHlp, "  IRR       : ");
    18681967    apicR3DumpVec(pDev, pApic, pHlp, 0x20);
    1869     iMax = get_highest_priority_int(pApic->irr);
     1968    iMax = Apic256BitReg_FindLastSetBit(&pApic->irr, -1);
    18701969    pHlp->pfnPrintf(pHlp, "    highest = %02X\n", iMax == -1 ? 0 : iMax);
    18711970}
     
    19792078    apicR3LiveExec(pDevIns, pSSM, SSM_PASS_FINAL);
    19802079
    1981     /* save all APICs data, @todo: is it correct? */
    1982     foreach_apic(pDev, 0xffffffff, apic_save(pSSM, apic));
     2080    /* save all APICs data */ /** @todo: is it correct? */
     2081    APIC_FOREACH_BEGIN(pDev);
     2082        apic_save(pSSM, pCurApic);
     2083    APIC_FOREACH_END();
    19832084
    19842085    return VINF_SUCCESS;
     
    19982099
    19992100    /* config */
    2000     if (uVersion > APIC_SAVED_STATE_VERSION_VBOX_30) {
     2101    if (uVersion > APIC_SAVED_STATE_VERSION_VBOX_30)
     2102    {
    20012103        uint32_t cCpus;
    20022104        int rc = SSMR3GetU32(pSSM, &cCpus); AssertRCReturn(rc, rc);
    20032105        if (cCpus != pDev->cCpus)
    20042106            return SSMR3SetCfgError(pSSM, RT_SRC_POS, N_("Config mismatch - cCpus: saved=%#x config=%#x"), cCpus, pDev->cCpus);
     2107
    20052108        bool fIoApic;
    20062109        rc = SSMR3GetBool(pSSM, &fIoApic); AssertRCReturn(rc, rc);
    20072110        if (fIoApic != pDev->fIoApic)
    20082111            return SSMR3SetCfgError(pSSM, RT_SRC_POS, N_("Config mismatch - fIoApic: saved=%RTbool config=%RTbool"), fIoApic, pDev->fIoApic);
     2112
    20092113        uint32_t uApicVersion;
    20102114        rc = SSMR3GetU32(pSSM, &uApicVersion); AssertRCReturn(rc, rc);
     
    20182122    /* load all APICs data */ /** @todo: is it correct? */
    20192123    APIC_LOCK(pDev, VERR_INTERNAL_ERROR_3);
    2020     foreach_apic(pDev, 0xffffffff,
    2021                  if (apic_load(pSSM, apic, uVersion)) {
    2022                       AssertFailed();
    2023                       APIC_UNLOCK(pDev);
    2024                       return VERR_SSM_UNSUPPORTED_DATA_UNIT_VERSION;
    2025                  }
    2026                  );
     2124
     2125    int rc = VINF_SUCCESS;
     2126    APIC_FOREACH_BEGIN(pDev);
     2127        rc = apic_load(pSSM, pCurApic, uVersion);
     2128        if (RT_FAILURE(rc))
     2129            break;
     2130    APIC_FOREACH_END();
     2131
    20272132    APIC_UNLOCK(pDev);
    2028     return VINF_SUCCESS;
     2133    return rc;
    20292134}
    20302135
     
    20392144
    20402145    /* Reset all APICs. */
    2041     for (VMCPUID i = 0; i < pDev->cCpus; i++) {
     2146    for (VMCPUID i = 0; i < pDev->cCpus; i++)
     2147    {
    20422148        APICState *pApic = &pDev->CTX_SUFF(paLapics)[i];
    20432149        TMTimerStop(pApic->CTX_SUFF(pTimer));
     
    20452151        /* Clear LAPIC state as if an INIT IPI was sent. */
    20462152        apic_init_ipi(pDev, pApic);
     2153
    20472154        /* The IDs are not touched by apic_init_ipi() and must be reset now. */
    20482155        pApic->arb_id = pApic->id = i;
    20492156        Assert(pApic->id == pApic->phys_id);    /* The two should match again. */
     2157
    20502158        /* Reset should re-enable the APIC, see comment in msi.h */
    20512159        pApic->apicbase = VBOX_MSI_ADDR_BASE | MSR_IA32_APICBASE_ENABLE;
     
    21092217static DECLCALLBACK(int) apicR3Construct(PPDMDEVINS pDevIns, int iInstance, PCFGMNODE pCfg)
    21102218{
    2111     PDMAPICREG      ApicReg;
    2112     int             rc;
     2219    APICDeviceInfo *pDev = PDMINS_2_DATA(pDevIns, APICDeviceInfo *);
    21132220    uint32_t        i;
    2114     bool            fIoApic;
    2115     bool            fGCEnabled;
    2116     bool            fR0Enabled;
    2117     APICDeviceInfo *pDev = PDMINS_2_DATA(pDevIns, APICDeviceInfo *);
    2118     uint32_t        cCpus;
    21192221
    21202222    /*
     
    21262228     * Validate configuration.
    21272229     */
    2128     if (!CFGMR3AreValuesValid(pCfg,
    2129                               "IOAPIC\0"
    2130                               "GCEnabled\0"
    2131                               "R0Enabled\0"
    2132                               "NumCPUs\0"))
    2133         return VERR_PDM_DEVINS_UNKNOWN_CFG_VALUES;
    2134 
    2135     rc = CFGMR3QueryBoolDef(pCfg, "IOAPIC", &fIoApic, true);
     2230    PDMDEV_VALIDATE_CONFIG_RETURN(pDevIns, "IOAPIC|RZEnabled|NumCPUs", "");
     2231
     2232    bool fIoApic;
     2233    int rc = CFGMR3QueryBoolDef(pCfg, "IOAPIC", &fIoApic, true);
    21362234    if (RT_FAILURE(rc))
    21372235        return PDMDEV_SET_ERROR(pDevIns, rc,
    21382236                                N_("Configuration error: Failed to read \"IOAPIC\""));
    21392237
    2140     rc = CFGMR3QueryBoolDef(pCfg, "GCEnabled", &fGCEnabled, true);
     2238    bool fRZEnabled;
     2239    rc = CFGMR3QueryBoolDef(pCfg, "RZEnabled", &fRZEnabled, true);
    21412240    if (RT_FAILURE(rc))
    21422241        return PDMDEV_SET_ERROR(pDevIns, rc,
    2143                                 N_("Configuration error: Failed to query boolean value \"GCEnabled\""));
    2144 
    2145     rc = CFGMR3QueryBoolDef(pCfg, "R0Enabled", &fR0Enabled, true);
    2146     if (RT_FAILURE(rc))
    2147         return PDMDEV_SET_ERROR(pDevIns, rc,
    2148                                 N_("Configuration error: Failed to query boolean value \"R0Enabled\""));
    2149 
     2242                                N_("Configuration error: Failed to query boolean value \"RZEnabled\""));
     2243
     2244    uint32_t cCpus;
    21502245    rc = CFGMR3QueryU32Def(pCfg, "NumCPUs", &cCpus, 1);
    21512246    if (RT_FAILURE(rc))
     
    21532248                                N_("Configuration error: Failed to query integer value \"NumCPUs\""));
    21542249
    2155     Log(("APIC: cCpus=%d fR0Enabled=%RTbool fGCEnabled=%RTbool fIoApic=%RTbool\n", cCpus, fR0Enabled, fGCEnabled, fIoApic));
    2156 
    2157     /** @todo Current implementation is limited to 32 CPUs due to the use of 32
    2158      *        bits bitmasks. */
    2159     if (cCpus > 32)
     2250    Log(("APIC: cCpus=%d fRZEnabled=%RTbool fIoApic=%RTbool\n", cCpus, fRZEnabled, fIoApic));
     2251    if (cCpus > 255)
    21602252        return PDMDEV_SET_ERROR(pDevIns, rc,
    21612253                                N_("Configuration error: Invalid value for \"NumCPUs\""));
     
    21932285     * Register the APIC.
    21942286     */
     2287    PDMAPICREG ApicReg;
    21952288    ApicReg.u32Version              = PDM_APICREG_VERSION;
    21962289    ApicReg.pfnGetInterruptR3       = apicGetInterrupt;
     
    22042297    ApicReg.pfnBusDeliverR3         = apicBusDeliverCallback;
    22052298    ApicReg.pfnLocalInterruptR3     = apicLocalInterrupt;
    2206     if (fGCEnabled) {
     2299    if (fRZEnabled)
     2300    {
    22072301        ApicReg.pszGetInterruptRC   = "apicGetInterrupt";
    22082302        ApicReg.pszHasPendingIrqRC  = "apicHasPendingIrq";
     
    22152309        ApicReg.pszBusDeliverRC     = "apicBusDeliverCallback";
    22162310        ApicReg.pszLocalInterruptRC = "apicLocalInterrupt";
    2217     } else {
     2311
     2312        ApicReg.pszGetInterruptR0   = "apicGetInterrupt";
     2313        ApicReg.pszHasPendingIrqR0  = "apicHasPendingIrq";
     2314        ApicReg.pszSetBaseR0        = "apicSetBase";
     2315        ApicReg.pszGetBaseR0        = "apicGetBase";
     2316        ApicReg.pszSetTPRR0         = "apicSetTPR";
     2317        ApicReg.pszGetTPRR0         = "apicGetTPR";
     2318        ApicReg.pszWriteMSRR0       = "apicWriteMSR";
     2319        ApicReg.pszReadMSRR0        = "apicReadMSR";
     2320        ApicReg.pszBusDeliverR0     = "apicBusDeliverCallback";
     2321        ApicReg.pszLocalInterruptR0 = "apicLocalInterrupt";
     2322    }
     2323    else
     2324    {
    22182325        ApicReg.pszGetInterruptRC   = NULL;
    22192326        ApicReg.pszHasPendingIrqRC  = NULL;
     
    22262333        ApicReg.pszBusDeliverRC     = NULL;
    22272334        ApicReg.pszLocalInterruptRC = NULL;
    2228     }
    2229     if (fR0Enabled) {
    2230         ApicReg.pszGetInterruptR0   = "apicGetInterrupt";
    2231         ApicReg.pszHasPendingIrqR0  = "apicHasPendingIrq";
    2232         ApicReg.pszSetBaseR0        = "apicSetBase";
    2233         ApicReg.pszGetBaseR0        = "apicGetBase";
    2234         ApicReg.pszSetTPRR0         = "apicSetTPR";
    2235         ApicReg.pszGetTPRR0         = "apicGetTPR";
    2236         ApicReg.pszWriteMSRR0       = "apicWriteMSR";
    2237         ApicReg.pszReadMSRR0        = "apicReadMSR";
    2238         ApicReg.pszBusDeliverR0     = "apicBusDeliverCallback";
    2239         ApicReg.pszLocalInterruptR0 = "apicLocalInterrupt";
    2240     } else {
     2335
    22412336        ApicReg.pszGetInterruptR0   = NULL;
    22422337        ApicReg.pszHasPendingIrqR0  = NULL;
     
    22612356    uint32_t u32Eax, u32Ebx, u32Ecx, u32Edx;
    22622357    PDMDevHlpGetCpuId(pDevIns, 0, &u32Eax, &u32Ebx, &u32Ecx, &u32Edx);
    2263     if (u32Eax >= 1) {
     2358    if (u32Eax >= 1)
     2359    {
    22642360        if (   fIoApic                       /* If IOAPIC is enabled, enable Local APIC in any case */
    22652361            || (   u32Ebx == X86_CPUID_VENDOR_INTEL_EBX
     
    22682364            || (   u32Ebx == X86_CPUID_VENDOR_AMD_EBX
    22692365                && u32Ecx == X86_CPUID_VENDOR_AMD_ECX
    2270                 && u32Edx == X86_CPUID_VENDOR_AMD_EDX   /* AuthenticAMD */)) {
     2366                && u32Edx == X86_CPUID_VENDOR_AMD_EDX   /* AuthenticAMD */))
     2367        {
    22712368            LogRel(("Activating Local APIC\n"));
    22722369            pDev->pApicHlpR3->pfnChangeFeature(pDevIns, pDev->enmVersion);
     
    22762373    /*
    22772374     * Register the MMIO range.
    2278      * @todo: shall reregister, if base changes.
    22792375     */
     2376    /** @todo: shall reregister, if base changes. */
    22802377    uint32_t ApicBase = pDev->paLapicsR3[0].apicbase & ~0xfff;
    22812378    rc = PDMDevHlpMMIORegister(pDevIns, ApicBase, 0x1000, pDev,
     
    22852382        return rc;
    22862383
    2287     if (fGCEnabled) {
     2384    if (fRZEnabled)
     2385    {
    22882386        pDev->pApicHlpRC  = pDev->pApicHlpR3->pfnGetRCHelpers(pDevIns);
    22892387        pDev->pCritSectRC = pDev->pApicHlpR3->pfnGetRCCritSect(pDevIns);
    2290 
    22912388        rc = PDMDevHlpMMIORegisterRC(pDevIns, ApicBase, 0x1000, NIL_RTRCPTR /*pvUser*/, "apicMMIOWrite", "apicMMIORead");
    22922389        if (RT_FAILURE(rc))
    22932390            return rc;
    2294     }
    2295 
    2296     if (fR0Enabled) {
     2391
    22972392        pDev->pApicHlpR0  = pDev->pApicHlpR3->pfnGetR0Helpers(pDevIns);
    22982393        pDev->pCritSectR0 = pDev->pApicHlpR3->pfnGetR0CritSect(pDevIns);
    2299 
    23002394        rc = PDMDevHlpMMIORegisterR0(pDevIns, ApicBase, 0x1000, NIL_RTR0PTR /*pvUser*/, "apicMMIOWrite", "apicMMIORead");
    23012395        if (RT_FAILURE(rc))
     
    23062400     * Create the APIC timers.
    23072401     */
    2308     for (i = 0; i < cCpus; i++) {
     2402    for (i = 0; i < cCpus; i++)
     2403    {
    23092404        APICState *pApic = &pDev->paLapicsR3[i];
    23102405        pApic->pszDesc = MMR3HeapAPrintf(pVM, MM_TAG_PDM_DEVICE_USER, "APIC Timer #%u", i);
     
    23412436    PDMDevHlpSTAMRegister(pDevIns, &pDev->StatMMIOWriteHC,    STAMTYPE_COUNTER,  "/Devices/APIC/MMIOWriteHC",  STAMUNIT_OCCURENCES, "Number of APIC MMIO writes in HC.");
    23422437    PDMDevHlpSTAMRegister(pDevIns, &pDev->StatClearedActiveIrq,STAMTYPE_COUNTER, "/Devices/APIC/MaskedActiveIRQ", STAMUNIT_OCCURENCES, "Number of cleared irqs.");
    2343     for (i = 0; i < cCpus; i++) {
     2438    for (i = 0; i < cCpus; i++)
     2439    {
    23442440        APICState *pApic = &pDev->paLapicsR3[i];
    23452441        PDMDevHlpSTAMRegisterF(pDevIns, &pApic->StatTimerSetInitialCount,       STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_OCCURENCES, "Calls to apicTimerSetInitialCount.",   "/Devices/APIC/%u/TimerSetInitialCount", i);
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