VirtualBox

Changeset 20734 in vbox


Ignore:
Timestamp:
Jun 20, 2009 6:28:44 PM (16 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
48850
Message:

DevAPIC: rewrote timer updates to streamline the handling wrt the virtual sync timer (avoid TM.cpp assertions). Unfortunately I ended cleaning up some annoying mess so the change is larger than what I would've liked it to be.

Location:
trunk/src/VBox/Devices
Files:
2 edited

Legend:

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

    r20676 r20734  
    9292#define IOAPIC_UNLOCK(pThis) (pThis)->CTX_SUFF(pIoApicHlp)->pfnUnlock((pThis)->CTX_SUFF(pDevIns))
    9393
    94 /**  @def LAPIC_BASE
    95  * Return address of first LAPIC state. */
    96 #define LAPIC_BASE(pThis) ((APICState*)(pThis)->CTX_SUFF(pLapics))
    9794
    9895#define foreach_apic(dev, mask, code)                     \
    9996    do {                                                  \
    10097        uint32_t i;                                       \
    101         APICState* apic = LAPIC_BASE(dev);                \
     98        APICState *apic = (dev)->CTX_SUFF(paLapics);      \
    10299        for (i = 0; i < dev->cCpus; i++)                  \
    103100        {                                                 \
     
    222219    uint32_t Alignment0;
    223220#endif
     221#ifndef VBOX
    224222    int64_t initial_count_load_time, next_time;
    225 #ifndef VBOX
    226223    QEMUTimer *timer;
    227224    struct APICState *next_apic;
    228225#else
     226    /** The time stamp of the initial_count load, i.e. when it was started. */
     227    uint64_t                initial_count_load_time;
     228    /** The time stamp of the next timer callback. */
     229    uint64_t                next_time;
    229230     /** The APIC timer - R3 Ptr. */
    230     PTMTIMERR3      pTimerR3;
    231 
     231    PTMTIMERR3              pTimerR3;
    232232    /** The APIC timer - R0 Ptr. */
    233     PTMTIMERR0      pTimerR0;
    234 
     233    PTMTIMERR0              pTimerR0;
    235234    /** The APIC timer - RC Ptr. */
    236     PTMTIMERRC      pTimerRC;
    237 
     235    PTMTIMERRC              pTimerRC;
     236    /** Whether the timer is armed or not */
     237    bool                    fTimerArmed;
    238238    /** Alignment */
    239     uint32_t Alignment1;
     239    bool                    afAlignment[3];
     240    /** Timer description timer. */
     241    R3PTRTYPE(char *)       pszDesc;
     242# ifdef VBOX_WITH_STATISTICS
     243    STAMCOUNTER             StatTimerSetInitialCount;
     244    STAMCOUNTER             StatTimerSetInitialCountArm;
     245    STAMCOUNTER             StatTimerSetInitialCountDisarm;
     246    STAMCOUNTER             StatTimerSetLvt;
     247    STAMCOUNTER             StatTimerSetLvtClearPeriodic;
     248    STAMCOUNTER             StatTimerSetLvtPostponed;
     249    STAMCOUNTER             StatTimerSetLvtArmed;
     250    STAMCOUNTER             StatTimerSetLvtArm;
     251    STAMCOUNTER             StatTimerSetLvtArmRetries;
     252    STAMCOUNTER             StatTimerSetLvtNoRelevantChange;
     253# endif
    240254#endif /* VBOX */
    241255} APICState;
     
    265279
    266280# ifdef VBOX_WITH_STATISTICS
    267     STAMCOUNTER StatMMIOReadGC;
    268     STAMCOUNTER StatMMIOReadHC;
    269     STAMCOUNTER StatMMIOWriteGC;
    270     STAMCOUNTER StatMMIOWriteHC;
    271     STAMCOUNTER StatSetIrqGC;
    272     STAMCOUNTER StatSetIrqHC;
     281    STAMCOUNTER             StatMMIOReadGC;
     282    STAMCOUNTER             StatMMIOReadHC;
     283    STAMCOUNTER             StatMMIOWriteGC;
     284    STAMCOUNTER             StatMMIOWriteHC;
     285    STAMCOUNTER             StatSetIrqGC;
     286    STAMCOUNTER             StatSetIrqHC;
    273287# endif
    274288#endif /* VBOX */
     
    285299    PCPDMAPICHLPR3          pApicHlpR3;
    286300    /** LAPICs states - R3 Ptr */
    287     RTR3PTR                 pLapicsR3;
     301    R3PTRTYPE(APICState *)  paLapicsR3;
    288302    /** The critical section - R3 Ptr. */
    289303    R3PTRTYPE(PPDMCRITSECT) pCritSectR3;
     
    294308    PCPDMAPICHLPR0          pApicHlpR0;
    295309    /** LAPICs states - R0 Ptr */
    296     RTR0PTR                 pLapicsR0;
     310    R0PTRTYPE(APICState *)  paLapicsR0;
    297311    /** The critical section - R3 Ptr. */
    298312    R0PTRTYPE(PPDMCRITSECT) pCritSectR0;
     
    303317    PCPDMAPICHLPRC          pApicHlpRC;
    304318    /** LAPICs states - RC Ptr */
    305     RTRCPTR                 pLapicsRC;
     319    RCPTRTYPE(APICState *)  paLapicsRC;
    306320    /** The critical section - R3 Ptr. */
    307321    RCPTRTYPE(PPDMCRITSECT) pCritSectRC;
     
    318332
    319333# ifdef VBOX_WITH_STATISTICS
    320     STAMCOUNTER     StatMMIOReadGC;
    321     STAMCOUNTER     StatMMIOReadHC;
    322     STAMCOUNTER     StatMMIOWriteGC;
    323     STAMCOUNTER     StatMMIOWriteHC;
    324     STAMCOUNTER     StatClearedActiveIrq;
     334    STAMCOUNTER             StatMMIOReadGC;
     335    STAMCOUNTER             StatMMIOReadHC;
     336    STAMCOUNTER             StatMMIOWriteGC;
     337    STAMCOUNTER             StatMMIOWriteHC;
     338    STAMCOUNTER             StatClearedActiveIrq;
    325339# endif
    326340} APICDeviceInfo;
    327 
    328 static void apic_eoi(APICDeviceInfo *dev, APICState* s);
    329 static int apic_deliver(APICDeviceInfo* dev, APICState *s,
    330                         uint8_t dest, uint8_t dest_mode,
    331                         uint8_t delivery_mode, uint8_t vector_num,
    332                         uint8_t polarity, uint8_t trigger_mode);
    333 static void apic_timer_update(APICDeviceInfo* dev, APICState *s,
    334                               int64_t current_time);
    335 static int apic_get_arb_pri(APICState *s);
    336 static int apic_get_ppr(APICState *s);
    337 static uint32_t apic_get_current_count(APICDeviceInfo* dev, APICState *s);
    338 
    339 
    340 DECLINLINE(APICState*) getLapicById(APICDeviceInfo* dev, VMCPUID id)
    341 {
    342     AssertFatalMsg(id < dev->cCpus, ("CPU id %d out of range\n", id));
    343     return LAPIC_BASE(dev) + id;
    344 }
    345 
    346 DECLINLINE(APICState*) getLapic(APICDeviceInfo* dev)
    347 {
    348     /* LAPIC's array is indexed by CPU id */
    349     VMCPUID id = dev->CTX_SUFF(pApicHlp)->pfnGetCpuId(dev->CTX_SUFF(pDevIns));
    350     return getLapicById(dev, id);
    351 }
    352 
    353 DECLINLINE(VMCPUID) getCpuFromLapic(APICDeviceInfo* dev, APICState *s)
    354 {
    355     /* for now we assume LAPIC physical id == CPU id */
    356     return VMCPUID(s->phys_id);
    357 }
    358 
    359 DECLINLINE(void) cpuSetInterrupt(APICDeviceInfo* dev, APICState *s)
    360 {
    361     Log2(("apic: setting interrupt flag for cpu %d\n", getCpuFromLapic(dev, s)));
    362     dev->CTX_SUFF(pApicHlp)->pfnSetInterruptFF(dev->CTX_SUFF(pDevIns),
    363                                                getCpuFromLapic(dev, s));
    364 }
    365 
    366 DECLINLINE(void) cpuClearInterrupt(APICDeviceInfo* dev, APICState *s)
    367 {
    368     Log2(("apic: clear interrupt flag\n"));
    369     dev->CTX_SUFF(pApicHlp)->pfnClearInterruptFF(dev->CTX_SUFF(pDevIns),
    370                                                  getCpuFromLapic(dev, s));
    371 }
    372 
    373 #ifdef IN_RING3
    374 DECLINLINE(void) cpuSendSipi(APICDeviceInfo* dev, APICState *s, int vector)
    375 {
    376     Log2(("apic: send SIPI vector=%d\n", vector));
    377 
    378     dev->pApicHlpR3->pfnSendSipi(dev->pDevInsR3,
    379                                  getCpuFromLapic(dev, s),
    380                                  vector);
    381 }
    382 
    383 DECLINLINE(void) cpuSendInitIpi(APICDeviceInfo* dev, APICState *s)
    384 {
    385     Log2(("apic: send init IPI\n"));
    386 
    387     dev->pApicHlpR3->pfnSendInitIpi(dev->pDevInsR3,
    388                                     getCpuFromLapic(dev, s));
    389 }
    390 #endif
    391 
    392 DECLINLINE(uint32_t) getApicEnableBits(APICDeviceInfo* dev)
    393 {
    394     switch (dev->enmVersion)
    395     {
    396         case PDMAPICVERSION_NONE:
    397             return 0;
    398         case PDMAPICVERSION_APIC:
    399             return MSR_IA32_APICBASE_ENABLE;
    400         case PDMAPICVERSION_X2APIC:
    401             return MSR_IA32_APICBASE_ENABLE | MSR_IA32_APICBASE_X2ENABLE ;
    402         default:
    403             AssertMsgFailed(("Unsuported APIC version %d\n", dev->enmVersion));
    404             return 0;
    405     }
    406 }
    407 
    408 DECLINLINE(PDMAPICVERSION) getApicMode(APICState *apic)
    409 {
    410     switch (((apic->apicbase) >> 10) & 0x3)
    411     {
    412         case 0:
    413             return PDMAPICVERSION_NONE;
    414         case 1:
    415         default:
    416             /* Invalid */
    417             return PDMAPICVERSION_NONE;
    418         case 2:
    419             return PDMAPICVERSION_APIC;
    420         case 3:
    421             return PDMAPICVERSION_X2APIC;
    422     }
    423 }
    424 
    425341#endif /* VBOX */
    426342
    427343#ifndef VBOX_DEVICE_STRUCT_TESTCASE
     344
    428345#ifndef VBOX
    429346static int apic_io_memory;
     
    432349#endif /* !VBOX */
    433350
    434 static void apic_init_ipi(APICDeviceInfo* dev, APICState *s);
    435 static void apic_set_irq(APICDeviceInfo* dev, APICState *s, int vector_num, int trigger_mode);
    436 static bool apic_update_irq(APICDeviceInfo* dev, APICState *s);
    437351
    438352#ifdef VBOX
    439 static uint32_t apic_get_delivery_bitmask(APICDeviceInfo* dev, uint8_t dest, uint8_t dest_mode);
     353/*******************************************************************************
     354*   Internal Functions                                                         *
     355*******************************************************************************/
    440356RT_C_DECLS_BEGIN
    441357PDMBOTHCBDECL(int)  apicMMIORead(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS GCPhysAddr, void *pv, unsigned cb);
     
    458374static void apic_update_tpr(APICDeviceInfo *dev, APICState* s, uint32_t val);
    459375RT_C_DECLS_END
     376
     377static void apic_eoi(APICDeviceInfo *dev, APICState* s); /*  */
     378static uint32_t apic_get_delivery_bitmask(APICDeviceInfo* dev, uint8_t dest, uint8_t dest_mode);
     379static int apic_deliver(APICDeviceInfo* dev, APICState *s,
     380                        uint8_t dest, uint8_t dest_mode,
     381                        uint8_t delivery_mode, uint8_t vector_num,
     382                        uint8_t polarity, uint8_t trigger_mode);
     383static int apic_get_arb_pri(APICState *s);
     384static int apic_get_ppr(APICState *s);
     385static uint32_t apic_get_current_count(APICDeviceInfo* dev, APICState *s);
     386static void apicTimerSetInitialCount(APICDeviceInfo *dev, APICState *s, uint32_t initial_count);
     387static void apicTimerSetLvt(APICDeviceInfo *dev, APICState *pThis, uint32_t fNew);
     388
     389#endif /* VBOX */
     390
     391static void apic_init_ipi(APICDeviceInfo* dev, APICState *s);
     392static void apic_set_irq(APICDeviceInfo* dev, APICState *s, int vector_num, int trigger_mode);
     393static bool apic_update_irq(APICDeviceInfo* dev, APICState *s);
     394
     395
     396#ifdef VBOX
     397
     398DECLINLINE(APICState*) getLapicById(APICDeviceInfo* dev, VMCPUID id)
     399{
     400    AssertFatalMsg(id < dev->cCpus, ("CPU id %d out of range\n", id));
     401    return &dev->CTX_SUFF(paLapics)[id];
     402}
     403
     404DECLINLINE(APICState*) getLapic(APICDeviceInfo* dev)
     405{
     406    /* LAPIC's array is indexed by CPU id */
     407    VMCPUID id = dev->CTX_SUFF(pApicHlp)->pfnGetCpuId(dev->CTX_SUFF(pDevIns));
     408    return getLapicById(dev, id);
     409}
     410
     411DECLINLINE(VMCPUID) getCpuFromLapic(APICDeviceInfo* dev, APICState *s)
     412{
     413    /* for now we assume LAPIC physical id == CPU id */
     414    return VMCPUID(s->phys_id);
     415}
     416
     417DECLINLINE(void) cpuSetInterrupt(APICDeviceInfo* dev, APICState *s)
     418{
     419    Log2(("apic: setting interrupt flag for cpu %d\n", getCpuFromLapic(dev, s)));
     420    dev->CTX_SUFF(pApicHlp)->pfnSetInterruptFF(dev->CTX_SUFF(pDevIns),
     421                                               getCpuFromLapic(dev, s));
     422}
     423
     424DECLINLINE(void) cpuClearInterrupt(APICDeviceInfo* dev, APICState *s)
     425{
     426    Log2(("apic: clear interrupt flag\n"));
     427    dev->CTX_SUFF(pApicHlp)->pfnClearInterruptFF(dev->CTX_SUFF(pDevIns),
     428                                                 getCpuFromLapic(dev, s));
     429}
     430
     431# ifdef IN_RING3
     432
     433DECLINLINE(void) cpuSendSipi(APICDeviceInfo* dev, APICState *s, int vector)
     434{
     435    Log2(("apic: send SIPI vector=%d\n", vector));
     436
     437    dev->pApicHlpR3->pfnSendSipi(dev->pDevInsR3,
     438                                 getCpuFromLapic(dev, s),
     439                                 vector);
     440}
     441
     442DECLINLINE(void) cpuSendInitIpi(APICDeviceInfo* dev, APICState *s)
     443{
     444    Log2(("apic: send init IPI\n"));
     445
     446    dev->pApicHlpR3->pfnSendInitIpi(dev->pDevInsR3,
     447                                    getCpuFromLapic(dev, s));
     448}
     449
     450# endif /* IN_RING3 */
     451
     452DECLINLINE(uint32_t) getApicEnableBits(APICDeviceInfo* dev)
     453{
     454    switch (dev->enmVersion)
     455    {
     456        case PDMAPICVERSION_NONE:
     457            return 0;
     458        case PDMAPICVERSION_APIC:
     459            return MSR_IA32_APICBASE_ENABLE;
     460        case PDMAPICVERSION_X2APIC:
     461            return MSR_IA32_APICBASE_ENABLE | MSR_IA32_APICBASE_X2ENABLE ;
     462        default:
     463            AssertMsgFailed(("Unsuported APIC version %d\n", dev->enmVersion));
     464            return 0;
     465    }
     466}
     467
     468DECLINLINE(PDMAPICVERSION) getApicMode(APICState *apic)
     469{
     470    switch (((apic->apicbase) >> 10) & 0x3)
     471    {
     472        case 0:
     473            return PDMAPICVERSION_NONE;
     474        case 1:
     475        default:
     476            /* Invalid */
     477            return PDMAPICVERSION_NONE;
     478        case 2:
     479            return PDMAPICVERSION_APIC;
     480        case 3:
     481            return PDMAPICVERSION_X2APIC;
     482    }
     483}
     484
    460485#endif /* VBOX */
    461486
     
    566591{
    567592    APICDeviceInfo *dev = PDMINS_2_DATA(pDevIns, APICDeviceInfo *);
    568     APICState *s = getLapic(dev);
     593    APICState *s = getLapic(dev); /** @todo fix interface */
    569594    Log(("cpu_set_apic_base: %016RX64\n", val));
    570595
     
    606631}
    607632#endif  /* VBOX */
     633
    608634#ifndef VBOX
    609635
     
    672698{
    673699    APICDeviceInfo *dev = PDMINS_2_DATA(pDevIns, APICDeviceInfo *);
    674     APICState *s = getLapic(dev);
     700    APICState *s = getLapic(dev); /** @todo fix interface */
    675701    LogFlow(("apicGetBase: %016llx\n", (uint64_t)s->apicbase));
    676702    return s->apicbase;
     
    693719}
    694720
     721/**
     722 * x2APIC MSR write interface.
     723 *
     724 * @returns VBox status code.
     725 *
     726 * @param   pDevIns         The device instance.
     727 * @param   idCpu           The ID of the virtual CPU and thereby APIC index.
     728 * @param   u32Reg          Register to write (ecx).
     729 * @param   u64Value        The value to write (eax:edx / rax).
     730 *
     731 */
    695732PDMBOTHCBDECL(int) apicWriteMSR(PPDMDEVINS pDevIns, VMCPUID idCpu, uint32_t u32Reg, uint64_t u64Value)
    696733{
     
    701738        return VERR_EM_INTERPRETER;
    702739
     740    APICState *pThis = getLapicById(dev, idCpu);
     741
    703742    uint32_t index = (u32Reg - MSR_IA32_APIC_START) & 0xff;
    704 
    705     APICState* apic = getLapicById(dev, idCpu);
    706 
    707743    switch (index)
    708744    {
    709745        case 0x02:
    710             apic->id = (u64Value >> 24);
     746            pThis->id = (u64Value >> 24);
    711747            break;
    712748        case 0x03:
    713749            break;
    714750        case 0x08:
    715             apic_update_tpr(dev, apic, u64Value);
     751            apic_update_tpr(dev, pThis, u64Value);
    716752            break;
    717753        case 0x09: case 0x0a:
     
    719755            break;
    720756        case 0x0b: /* EOI */
    721             apic_eoi(dev, apic);
     757            apic_eoi(dev, pThis);
    722758            break;
    723759        case 0x0d:
    724             apic->log_dest = u64Value >> 24;
     760            pThis->log_dest = u64Value >> 24;
    725761            break;
    726762        case 0x0e:
    727             apic->dest_mode = u64Value >> 28;
     763            pThis->dest_mode = u64Value >> 28;
    728764            break;
    729765        case 0x0f:
    730             apic->spurious_vec = u64Value & 0x1ff;
    731             apic_update_irq(dev, apic);
     766            pThis->spurious_vec = u64Value & 0x1ff;
     767            apic_update_irq(dev, pThis);
    732768            break;
    733769        case 0x10: case 0x11: case 0x12: case 0x13: case 0x14: case 0x15: case 0x16: case 0x17:
     
    740776        case 0x30:
    741777            /* Here one of the differences with regular APIC: ICR is single 64-bit register */
    742             apic->icr[0] = (uint32_t)u64Value;
    743             apic->icr[1] = (uint32_t)(u64Value >> 32);
    744             rc = apic_deliver(dev, apic, (apic->icr[1] >> 24) & 0xff, (apic->icr[0] >> 11) & 1,
    745                              (apic->icr[0] >>  8) & 7, (apic->icr[0] & 0xff),
    746                              (apic->icr[0] >> 14) & 1, (apic->icr[0] >> 15) & 1);
    747             break;
    748         case 0x32: case 0x33: case 0x34: case 0x35: case 0x36: case 0x37:
    749         {
    750             int n = index - 0x32;
    751             apic->lvt[n] = u64Value;
    752             if (n == APIC_LVT_TIMER)
    753                 apic_timer_update(dev, apic, TMTimerGet(apic->CTX_SUFF(pTimer)));
    754         }
    755         break;
     778            pThis->icr[0] = (uint32_t)u64Value;
     779            pThis->icr[1] = (uint32_t)(u64Value >> 32);
     780            rc = apic_deliver(dev, pThis, (pThis->icr[1] >> 24) & 0xff, (pThis->icr[0] >> 11) & 1,
     781                             (pThis->icr[0] >>  8) & 7, (pThis->icr[0] & 0xff),
     782                             (pThis->icr[0] >> 14) & 1, (pThis->icr[0] >> 15) & 1);
     783            break;
     784        case 0x32 + APIC_LVT_TIMER:
     785            AssertCompile(APIC_LVT_TIMER == 0);
     786            apicTimerSetLvt(dev, pThis, u64Value);
     787            break;
     788
     789        case 0x33: case 0x34: case 0x35: case 0x36: case 0x37:
     790            pThis->lvt[index - 0x32] = u64Value;
     791            break;
    756792        case 0x38:
    757             apic->initial_count = u64Value;
    758             apic->initial_count_load_time = TMTimerGet(apic->CTX_SUFF(pTimer));
    759             apic_timer_update(dev, apic, apic->initial_count_load_time);
     793            apicTimerSetInitialCount(dev, pThis, u64Value);
    760794            break;
    761795        case 0x39:
     
    765799        {
    766800            int v;
    767             apic->divide_conf = u64Value & 0xb;
    768             v = (apic->divide_conf & 3) | ((apic->divide_conf >> 1) & 4);
    769             apic->count_shift = (v + 1) & 7;
     801            pThis->divide_conf = u64Value & 0xb;
     802            v = (pThis->divide_conf & 3) | ((pThis->divide_conf >> 1) & 4);
     803            pThis->count_shift = (v + 1) & 7;
    770804            break;
    771805        }
     
    784818        default:
    785819            AssertMsgFailed(("apicWriteMSR: unknown index %x\n", index));
    786             apic->esr |= ESR_ILLEGAL_ADDRESS;
     820            pThis->esr |= ESR_ILLEGAL_ADDRESS;
    787821            break;
    788822    }
     
    790824    return rc;
    791825}
     826
     827/**
     828 * x2APIC MSR read interface.
     829 *
     830 * @returns VBox status code.
     831 *
     832 * @param   pDevIns         The device instance.
     833 * @param   idCpu           The ID of the virtual CPU and thereby APIC index.
     834 * @param   u32Reg          Register to write (ecx).
     835 * @param   pu64Value       Where to return the value (eax:edx / rax).
     836 */
    792837PDMBOTHCBDECL(int) apicReadMSR(PPDMDEVINS pDevIns, VMCPUID idCpu, uint32_t u32Reg, uint64_t *pu64Value)
    793838{
     
    9721017    if (!dev)
    9731018        return false;
    974     APICState *s = getLapic(dev);
     1019    APICState *s = getLapic(dev); /** @todo fix interface */
    9751020
    9761021    /*
     
    10501095    else
    10511096    {
    1052         APICState *apic = LAPIC_BASE(dev);
     1097        APICState *apic = dev->CTX_SUFF(paLapics);
    10531098        uint32_t i;
    10541099
     
    12181263    APIC_LOCK(dev, VERR_INTERNAL_ERROR);
    12191264
    1220     APICState *s = getLapic(dev);
     1265    APICState *s = getLapic(dev);  /** @todo fix interface */
    12211266    int intno;
    12221267
     
    12481293}
    12491294
    1250 static uint32_t apic_get_current_count(APICDeviceInfo* dev, APICState *s)
     1295static uint32_t apic_get_current_count(APICDeviceInfo *dev, APICState *s)
    12511296{
    12521297    int64_t d;
     
    12711316}
    12721317
     1318#ifndef VBOX /* we've replaced all the code working the APIC timer. */
     1319
    12731320static void apic_timer_update(APICDeviceInfo* dev, APICState *s, int64_t current_time)
    12741321{
     
    12861333        }
    12871334        next_time = s->initial_count_load_time + (d << s->count_shift);
    1288 #ifndef VBOX
     1335# ifndef VBOX
    12891336        qemu_mod_timer(s->timer, next_time);
    1290 #else
     1337# else
    12911338        TMTimerSet(s->CTX_SUFF(pTimer), next_time);
    1292 #endif
     1339        s->fTimerArmed = true;
     1340# endif
    12931341        s->next_time = next_time;
    12941342    } else {
    12951343    no_timer:
    1296 #ifndef VBOX
     1344# ifndef VBOX
    12971345        qemu_del_timer(s->timer);
    1298 #else
     1346# else
    12991347        TMTimerStop(s->CTX_SUFF(pTimer));
    1300 #endif
    1301     }
    1302 }
    1303 
    1304 #ifdef IN_RING3
    1305 # ifndef VBOX
     1348        s->fTimerArmed = false;
     1349# endif
     1350    }
     1351}
     1352
    13061353static void apic_timer(void *opaque)
    13071354{
    13081355    APICState *s = opaque;
    1309 # else /* VBOX */
    1310 static DECLCALLBACK(void) apicTimer(PPDMDEVINS pDevIns, PTMTIMER pTimer, void *pvUser)
    1311 {
    1312     APICDeviceInfo *dev = PDMINS_2_DATA(pDevIns, APICDeviceInfo *);
    1313     APICState *s = (APICState *)pvUser;
    1314     Assert(s->pTimerR3 == pTimer);
    1315 # endif /* VBOX */
    13161356
    13171357    if (!(s->lvt[APIC_LVT_TIMER] & APIC_LVT_MASKED)) {
     
    13211361    apic_timer_update(dev, s, s->next_time);
    13221362}
    1323 #endif /* IN_RING3 */
     1363
     1364#else  /* VBOX */
     1365
     1366/**
     1367 * Implementation of the 0380h access: Timer reset + new initial count.
     1368 *
     1369 * @param   dev                 The device state.
     1370 * @param   pThis               The APIC sub-device state.
     1371 * @param   u32NewInitialCount  The new initial count for the timer.
     1372 */
     1373static void apicTimerSetInitialCount(APICDeviceInfo *dev, APICState *pThis, uint32_t u32NewInitialCount)
     1374{
     1375    STAM_COUNTER_INC(&pThis->StatTimerSetInitialCount);
     1376    pThis->initial_count = u32NewInitialCount;
     1377
     1378    /*
     1379     * Don't (re-)arm the timer if the it's masked or if it's
     1380     * a zero length one-shot timer.
     1381     */
     1382    /** @todo check the correct behavior of setting a 0 initial_count for a one-shot
     1383     *        timer. This is just copying the behavior of the original code. */
     1384    if (    !(pThis->lvt[APIC_LVT_TIMER] & APIC_LVT_MASKED)
     1385        &&  (   (pThis->lvt[APIC_LVT_TIMER] & APIC_LVT_TIMER_PERIODIC)
     1386             || u32NewInitialCount != 0))
     1387    {
     1388        /*
     1389         * Calculate the relative next time and perform a combined timer get/set
     1390         * operation. This avoids racing the clock between get and set.
     1391         */
     1392        uint64_t cTicksNext = u32NewInitialCount;
     1393        cTicksNext         += 1;
     1394        cTicksNext        <<= pThis->count_shift;
     1395        TMTimerSetRelative(pThis->CTX_SUFF(pTimer), cTicksNext, &pThis->initial_count_load_time);
     1396        pThis->next_time = pThis->initial_count_load_time + cTicksNext;
     1397        pThis->fTimerArmed = true;
     1398        STAM_COUNTER_INC(&pThis->StatTimerSetInitialCountArm);
     1399    }
     1400    else
     1401    {
     1402        /* Stop it if necessary and record the load time for unmasking. */
     1403        if (pThis->fTimerArmed)
     1404        {
     1405            STAM_COUNTER_INC(&pThis->StatTimerSetInitialCountDisarm);
     1406            TMTimerStop(pThis->CTX_SUFF(pTimer));
     1407            pThis->fTimerArmed = false;
     1408        }
     1409        pThis->initial_count_load_time = TMTimerGet(pThis->CTX_SUFF(pTimer));
     1410    }
     1411}
     1412
     1413/**
     1414 * Implementation of the 0320h access: change the LVT flags.
     1415 *
     1416 * @param   dev             The device state.
     1417 * @param   pThis           The APIC sub-device state to operate on.
     1418 * @param   fNew            The new flags.
     1419 */
     1420static void apicTimerSetLvt(APICDeviceInfo *dev, APICState *pThis, uint32_t fNew)
     1421{
     1422    STAM_COUNTER_INC(&pThis->StatTimerSetLvt);
     1423
     1424    /*
     1425     * Make the flag change, saving the old ones so we can avoid
     1426     * unnecessary work.
     1427     */
     1428    uint32_t const fOld = pThis->lvt[APIC_LVT_TIMER];
     1429    pThis->lvt[APIC_LVT_TIMER] = fNew;
     1430
     1431    /* Only the masked and peridic bits are relevant (see apic_timer_update). */
     1432    if (    (fOld & (APIC_LVT_MASKED | APIC_LVT_TIMER_PERIODIC))
     1433        !=  (fNew & (APIC_LVT_MASKED | APIC_LVT_TIMER_PERIODIC)))
     1434    {
     1435        /*
     1436         * If changed to one-shot from periodic, stop the timer if we're not
     1437         * in the first period.
     1438         */
     1439        /** @todo check how clearing the periodic flag really should behave when not
     1440         *        in period 1. The current code just mirrors the behavior of the
     1441         *        original implementation. */
     1442        if (    (fOld & APIC_LVT_TIMER_PERIODIC)
     1443            && !(fNew & APIC_LVT_TIMER_PERIODIC))
     1444        {
     1445            STAM_COUNTER_INC(&pThis->StatTimerSetLvtClearPeriodic);
     1446            uint64_t cTicks = (pThis->next_time - pThis->initial_count_load_time) >> pThis->count_shift;
     1447            if (cTicks >= pThis->initial_count)
     1448            {
     1449                /* not first period, stop it. */
     1450                TMTimerStop(pThis->CTX_SUFF(pTimer));
     1451                pThis->fTimerArmed = false;
     1452            }
     1453            /* else: first period, let it fire normally. */
     1454        }
     1455
     1456        /*
     1457         * We postpone stopping the timer when it's masked, this way we can
     1458         * avoid some timer work when the guest temporarily masks the timer.
     1459         * (apicTimerCallback will stop it if still masked.)
     1460         */
     1461        if (fNew & APIC_LVT_MASKED)
     1462            STAM_COUNTER_INC(&pThis->StatTimerSetLvtPostponed);
     1463        else if (pThis->fTimerArmed)
     1464            STAM_COUNTER_INC(&pThis->StatTimerSetLvtArmed);
     1465        /*
     1466         * If unmasked and not armed, we have to rearm the timer so it will
     1467         * fire at the end of the current period.
     1468         * This is code is currently RACING the virtual sync clock!
     1469         */
     1470        else if (fOld & APIC_LVT_MASKED)
     1471        {
     1472            STAM_COUNTER_INC(&pThis->StatTimerSetLvtArm);
     1473            for (unsigned cTries = 0; ; cTries++)
     1474            {
     1475                uint64_t NextTS;
     1476                uint64_t cTicks = (TMTimerGet(pThis->CTX_SUFF(pTimer)) - pThis->initial_count_load_time) >> pThis->count_shift;
     1477                if (fNew & APIC_LVT_TIMER_PERIODIC)
     1478                    NextTS = ((cTicks / ((uint64_t)pThis->initial_count + 1)) + 1) * ((uint64_t)pThis->initial_count + 1);
     1479                else
     1480                {
     1481                    if (cTicks >= pThis->initial_count)
     1482                        break;
     1483                    NextTS = (uint64_t)pThis->initial_count + 1;
     1484                }
     1485                NextTS <<= pThis->count_shift;
     1486                NextTS += pThis->initial_count_load_time;
     1487
     1488                /* Try avoid the assertion in TM.cpp... this isn't perfect! */
     1489                if (    NextTS > TMTimerGet(pThis->CTX_SUFF(pTimer))
     1490                    ||  cTries > 10)
     1491                {
     1492                    TMTimerSet(pThis->CTX_SUFF(pTimer), NextTS);
     1493                    pThis->next_time = NextTS;
     1494                    pThis->fTimerArmed = true;
     1495                    break;
     1496                }
     1497                STAM_COUNTER_INC(&pThis->StatTimerSetLvtArmRetries);
     1498            }
     1499        }
     1500    }
     1501    else
     1502        STAM_COUNTER_INC(&pThis->StatTimerSetLvtNoRelevantChange);
     1503}
     1504
     1505# ifdef IN_RING3
     1506/**
     1507 * Timer callback function.
     1508 *
     1509 * @param  pDevIns      The device state.
     1510 * @param  pTimer       The timer handle.
     1511 * @param  pvUser       User argument pointing to the APIC instance.
     1512 */
     1513static DECLCALLBACK(void) apicTimerCallback(PPDMDEVINS pDevIns, PTMTIMER pTimer, void *pvUser)
     1514{
     1515    APICDeviceInfo *dev   = PDMINS_2_DATA(pDevIns, APICDeviceInfo *);
     1516    APICState      *pThis = (APICState *)pvUser;
     1517    Assert(pThis->pTimerR3 == pTimer);
     1518    Assert(pThis->fTimerArmed);
     1519
     1520    if (!(pThis->lvt[APIC_LVT_TIMER] & APIC_LVT_MASKED)) {
     1521        LogFlow(("apic_timer: trigger irq\n"));
     1522        apic_set_irq(dev, pThis, pThis->lvt[APIC_LVT_TIMER] & 0xff, APIC_TRIGGER_EDGE);
     1523
     1524        if (pThis->lvt[APIC_LVT_TIMER] & APIC_LVT_TIMER_PERIODIC) {
     1525            /* new interval. */
     1526            pThis->next_time += (uint64_t)pThis->initial_count + 1;
     1527            TMTimerSet(pThis->CTX_SUFF(pTimer), pThis->next_time);
     1528            pThis->fTimerArmed = true;
     1529        } else {
     1530            /* single shot. */
     1531            pThis->fTimerArmed = false;
     1532        }
     1533    } else {
     1534        /* masked, do not rearm. */
     1535        pThis->fTimerArmed = false;
     1536    }
     1537}
     1538# endif /* IN_RING3 */
     1539
     1540#endif /* VBOX */
    13241541
    13251542#ifndef VBOX
     
    15371754    case 0x32 ... 0x37:
    15381755#else /* VBOX */
    1539     case 0x32: case 0x33: case 0x34: case 0x35: case 0x36: case 0x37:
     1756    case 0x32 + APIC_LVT_TIMER:
     1757        AssertCompile(APIC_LVT_TIMER == 0);
     1758        apicTimerSetLvt(dev, s, val);
     1759        break;
     1760    case 0x33: case 0x34: case 0x35: case 0x36: case 0x37:
    15401761#endif /* VBOX */
    15411762        {
    15421763            int n = index - 0x32;
    15431764            s->lvt[n] = val;
     1765#ifndef VBOX
    15441766            if (n == APIC_LVT_TIMER)
    1545 #ifndef VBOX
    15461767                apic_timer_update(s, qemu_get_clock(vm_clock));
     1768#endif /* !VBOX*/
     1769        }
     1770        break;
     1771    case 0x38:
     1772#ifndef VBOX
     1773        s->initial_count = val;
     1774        s->initial_count_load_time = qemu_get_clock(vm_clock);
     1775        apic_timer_update(dev, s, s->initial_count_load_time);
    15471776#else /* VBOX */
    1548                 apic_timer_update(dev, s, TMTimerGet(s->CTX_SUFF(pTimer)));
     1777        apicTimerSetInitialCount(dev, s, val);
    15491778#endif /* VBOX*/
    1550         }
    1551         break;
    1552     case 0x38:
    1553         s->initial_count = val;
    1554 #ifndef VBOX
    1555         s->initial_count_load_time = qemu_get_clock(vm_clock);
    1556 #else /* VBOX */
    1557         s->initial_count_load_time = TMTimerGet(s->CTX_SUFF(pTimer));
    1558 #endif /* VBOX*/
    1559         apic_timer_update(dev, s, s->initial_count_load_time);
    15601779        break;
    15611780    case 0x39:
     
    16861905
    16871906#ifdef VBOX
    1688     TMR3TimerLoad(s->CTX_SUFF(pTimer), f);
    1689 #endif
    1690 
    1691     return VINF_SUCCESS;
     1907    int rc = TMR3TimerLoad(s->CTX_SUFF(pTimer), f);
     1908    s->fTimerArmed = TMTimerIsActive(s->CTX_SUFF(pTimer));
     1909#endif
     1910
     1911    return VINF_SUCCESS; /** @todo darn mess! */
    16921912}
    16931913#ifndef VBOX
     
    21532373static DECLCALLBACK(void) apicReset(PPDMDEVINS pDevIns)
    21542374{
     2375    APICDeviceInfo *dev = PDMINS_2_DATA(pDevIns, APICDeviceInfo *);
    21552376    unsigned i;
    2156     APICDeviceInfo* dev = PDMINS_2_DATA(pDevIns, APICDeviceInfo *);
    2157     APICState *apic;
    21582377
    21592378    APIC_LOCK_VOID(dev, VERR_INTERNAL_ERROR);
    21602379
    21612380    /* Reset all APICs. */
    2162     for (i = 0, apic = LAPIC_BASE(dev); i < dev->cCpus; i++)
    2163     {
    2164         TMTimerStop(apic->CTX_SUFF(pTimer));
     2381    for (i = 0; i < dev->cCpus; i++) {
     2382        APICState *pApic = &dev->CTX_SUFF(paLapics)[i];
     2383        TMTimerStop(pApic->CTX_SUFF(pTimer));
    21652384
    21662385        /* Do not send an init ipi to the VCPU; we take
    21672386        * care of the proper init ourselves.
    2168         apic_init_ipi(dev, apic);
     2387        apic_init_ipi(dev, pApic);
    21692388        */
    21702389
    21712390        /* malc, I've removed the initing duplicated in apic_init_ipi(). This
    21722391        * arb_id was left over.. */
    2173         apic->arb_id = 0;
     2392        pApic->arb_id = 0;
    21742393        /* Reset should re-enable the APIC. */
    2175         apic->apicbase = 0xfee00000 | MSR_IA32_APICBASE_ENABLE;
    2176         if (apic->phys_id == 0)
    2177             apic->apicbase |= MSR_IA32_APICBASE_BSP;
     2394        pApic->apicbase = 0xfee00000 | MSR_IA32_APICBASE_ENABLE;
     2395        if (pApic->phys_id == 0)
     2396            pApic->apicbase |= MSR_IA32_APICBASE_BSP;
    21782397
    21792398        /* Clear any pending APIC interrupt action flag. */
    2180         cpuClearInterrupt(dev, apic);
    2181 
    2182         apic++;
     2399        cpuClearInterrupt(dev, pApic);
    21832400    }
    21842401    dev->pApicHlpR3->pfnChangeFeature(dev->pDevInsR3, dev->enmVersion);
     
    21952412    pThis->pDevInsRC   = PDMDEVINS_2_RCPTR(pDevIns);
    21962413    pThis->pApicHlpRC  = pThis->pApicHlpR3->pfnGetRCHelpers(pDevIns);
    2197     pThis->pLapicsRC   = MMHyperR3ToRC(PDMDevHlpGetVM(pDevIns), pThis->pLapicsR3);
     2414    pThis->paLapicsRC  = MMHyperR3ToRC(PDMDevHlpGetVM(pDevIns), pThis->paLapicsR3);
    21982415    pThis->pCritSectRC = pThis->pApicHlpR3->pfnGetRCCritSect(pDevIns);
    2199     foreach_apic(pThis, 0xffffffff,
    2200                  apic->pTimerRC = TMTimerRCPtr(apic->CTX_SUFF(pTimer)));
     2416    for (uint32_t i = 0; i < pThis->cCpus; i++)
     2417        pThis->paLapicsR3[i].pTimerRC = TMTimerRCPtr(pThis->paLapicsR3[i].pTimerR3);
    22012418}
    22022419
     
    22282445    APICDeviceInfo  *pThis = PDMINS_2_DATA(pDevIns, APICDeviceInfo *);
    22292446    uint32_t        cCpus;
    2230     APICState       *apic;
    22312447
    22322448    /*
     
    22862502     * We are not freeing this memory, as it's automatically released when guest exits.
    22872503     */
    2288     rc = MMHyperAlloc(pVM, cCpus*sizeof(APICState), 1, MM_TAG_PDM_DEVICE_USER, (void **)&pThis->pLapicsR3);
     2504    rc = MMHyperAlloc(pVM, cCpus * sizeof(APICState), 1, MM_TAG_PDM_DEVICE_USER, (void **)&pThis->paLapicsR3);
    22892505    if (RT_FAILURE(rc))
    22902506        return VERR_NO_MEMORY;
    2291     pThis->pLapicsR0 = MMHyperR3ToR0(pVM, pThis->pLapicsR3);
    2292     pThis->pLapicsRC = MMHyperR3ToRC(pVM, pThis->pLapicsR3);
    2293 
    2294     for (i = 0, apic = LAPIC_BASE(pThis); i < cCpus; i++)
    2295     {
    2296         initApicData(apic, i);
    2297         apic++;
    2298     }
     2507    pThis->paLapicsR0 = MMHyperR3ToR0(pVM, pThis->paLapicsR3);
     2508    pThis->paLapicsRC = MMHyperR3ToRC(pVM, pThis->paLapicsR3);
     2509
     2510    for (i = 0; i < cCpus; i++)
     2511        initApicData(&pThis->paLapicsR3[i], i);
    22992512
    23002513    /*
     
    23562569    Assert(pDevIns->pDevHlpR3->pfnAPICRegister);
    23572570    rc = pDevIns->pDevHlpR3->pfnAPICRegister(pDevIns, &ApicReg, &pThis->pApicHlpR3);
    2358     if (RT_FAILURE(rc))
    2359     {
    2360         AssertLogRelMsgFailed(("APICRegister -> %Rrc\n", rc));
    2361         return rc;
    2362     }
     2571    AssertLogRelRCReturn(rc, rc);
    23632572    pThis->pCritSectR3 = pThis->pApicHlpR3->pfnGetR3CritSect(pDevIns);
    23642573
     
    23682577    uint32_t u32Eax, u32Ebx, u32Ecx, u32Edx;
    23692578    PDMDevHlpGetCpuId(pDevIns, 0, &u32Eax, &u32Ebx, &u32Ecx, &u32Edx);
    2370     if (u32Eax >= 1)
    2371     {
     2579    if (u32Eax >= 1) {
    23722580        if (   fIOAPIC                       /* If IOAPIC is enabled, enable Local APIC in any case */
    23732581               || (   u32Ebx == X86_CPUID_VENDOR_INTEL_EBX
     
    23762584               || (   u32Ebx == X86_CPUID_VENDOR_AMD_EBX
    23772585                      && u32Ecx == X86_CPUID_VENDOR_AMD_ECX
    2378                       && u32Edx == X86_CPUID_VENDOR_AMD_EDX   /* AuthenticAMD */))
    2379         {
     2586                      && u32Edx == X86_CPUID_VENDOR_AMD_EDX   /* AuthenticAMD */)) {
    23802587            LogRel(("Activating Local APIC\n"));
    23812588            pThis->pApicHlpR3->pfnChangeFeature(pDevIns, pThis->enmVersion);
     
    23862593     * Register the MMIO range.
    23872594     */
    2388     rc = PDMDevHlpMMIORegister(pDevIns, LAPIC_BASE(pThis)->apicbase & ~0xfff, 0x1000, pThis,
     2595    uint32_t ApicBase = pThis->paLapicsR3[0].apicbase & ~0xfff;
     2596    rc = PDMDevHlpMMIORegister(pDevIns, ApicBase, 0x1000, pThis,
    23892597                               apicMMIOWrite, apicMMIORead, NULL, "APIC Memory");
    23902598    if (RT_FAILURE(rc))
     
    23952603        pThis->pCritSectRC = pThis->pApicHlpR3->pfnGetRCCritSect(pDevIns);
    23962604
    2397         rc = PDMDevHlpMMIORegisterGC(pDevIns, LAPIC_BASE(pThis)->apicbase & ~0xfff, 0x1000, 0,
     2605        rc = PDMDevHlpMMIORegisterGC(pDevIns, ApicBase, 0x1000, 0,
    23982606                                     "apicMMIOWrite", "apicMMIORead", NULL);
    23992607        if (RT_FAILURE(rc))
     
    24052613        pThis->pCritSectR0 = pThis->pApicHlpR3->pfnGetR0CritSect(pDevIns);
    24062614
    2407         rc = PDMDevHlpMMIORegisterR0(pDevIns, LAPIC_BASE(pThis)->apicbase & ~0xfff, 0x1000, 0,
     2615        rc = PDMDevHlpMMIORegisterR0(pDevIns, ApicBase, 0x1000, 0,
    24082616                                     "apicMMIOWrite", "apicMMIORead", NULL);
    24092617        if (RT_FAILURE(rc))
     
    24142622     * Create the APIC timers.
    24152623     */
    2416     for (i = 0, apic = LAPIC_BASE(pThis); i < cCpus; i++)
    2417     {
    2418         rc = PDMDevHlpTMTimerCreate(pDevIns, TMCLOCK_VIRTUAL_SYNC, apicTimer, apic,
    2419                                     TMTIMER_FLAGS_NO_CRIT_SECT, "APIC Timer", &apic->pTimerR3);
     2624    for (i = 0; i < cCpus; i++) {
     2625        APICState *pApic = &pThis->paLapicsR3[i];
     2626        pApic->pszDesc = MMR3HeapAPrintf(pVM, MM_TAG_PDM_DEVICE_USER, "APIC Timer #%u", i);
     2627        rc = PDMDevHlpTMTimerCreate(pDevIns, TMCLOCK_VIRTUAL_SYNC, apicTimerCallback, pApic,
     2628                                    TMTIMER_FLAGS_NO_CRIT_SECT, pApic->pszDesc, &pApic->pTimerR3);
    24202629        if (RT_FAILURE(rc))
    24212630            return rc;
    2422         apic->pTimerR0 = TMTimerR0Ptr(apic->pTimerR3);
    2423         apic->pTimerRC = TMTimerRCPtr(apic->pTimerR3);
    2424         TMR3TimerSetCritSect(apic->pTimerR3, pThis->pCritSectR3);
    2425         apic++;
     2631        pApic->pTimerR0 = TMTimerR0Ptr(pApic->pTimerR3);
     2632        pApic->pTimerRC = TMTimerRCPtr(pApic->pTimerR3);
     2633        TMR3TimerSetCritSect(pApic->pTimerR3, pThis->pCritSectR3);
    24262634    }
    24272635
     
    24432651    PDMDevHlpSTAMRegister(pDevIns, &pThis->StatMMIOWriteHC,    STAMTYPE_COUNTER,  "/Devices/APIC/MMIOWriteHC",  STAMUNIT_OCCURENCES, "Number of APIC MMIO writes in HC.");
    24442652    PDMDevHlpSTAMRegister(pDevIns, &pThis->StatClearedActiveIrq,STAMTYPE_COUNTER, "/Devices/APIC/MaskedActiveIRQ", STAMUNIT_OCCURENCES, "Number of cleared irqs.");
     2653    for (i = 0; i < cCpus; i++) {
     2654        APICState *pApic = &pThis->paLapicsR3[i];
     2655        PDMDevHlpSTAMRegisterF(pDevIns, &pApic->StatTimerSetInitialCount,       STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_OCCURENCES, "Calls to apicTimerSetInitialCount.",   "/Devices/APIC/%u/TimerSetInitialCount", i);
     2656        PDMDevHlpSTAMRegisterF(pDevIns, &pApic->StatTimerSetInitialCountArm,    STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_OCCURENCES, "TMTimerSetRelative calls.",            "/Devices/APIC/%u/TimerSetInitialCount/Arm", i);
     2657        PDMDevHlpSTAMRegisterF(pDevIns, &pApic->StatTimerSetInitialCountDisarm, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_OCCURENCES, "TMTimerStop calls.",                   "/Devices/APIC/%u/TimerSetInitialCount/Disasm", i);
     2658        PDMDevHlpSTAMRegisterF(pDevIns, &pApic->StatTimerSetLvt,                STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_OCCURENCES, "Calls to apicTimerSetLvt.",            "/Devices/APIC/%u/TimerSetLvt", i);
     2659        PDMDevHlpSTAMRegisterF(pDevIns, &pApic->StatTimerSetLvtClearPeriodic,   STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_OCCURENCES, "Clearing APIC_LVT_TIMER_PERIODIC.",    "/Devices/APIC/%u/TimerSetLvt/ClearPeriodic", i);
     2660        PDMDevHlpSTAMRegisterF(pDevIns, &pApic->StatTimerSetLvtPostponed,       STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_OCCURENCES, "TMTimerStop postponed.",               "/Devices/APIC/%u/TimerSetLvt/Postponed", i);
     2661        PDMDevHlpSTAMRegisterF(pDevIns, &pApic->StatTimerSetLvtArmed,           STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_OCCURENCES, "TMTimerSet avoided.",                  "/Devices/APIC/%u/TimerSetLvt/Armed", i);
     2662        PDMDevHlpSTAMRegisterF(pDevIns, &pApic->StatTimerSetLvtArm,             STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_OCCURENCES, "TMTimerSet necessary.",                "/Devices/APIC/%u/TimerSetLvt/Arm", i);
     2663        PDMDevHlpSTAMRegisterF(pDevIns, &pApic->StatTimerSetLvtArmRetries,      STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_OCCURENCES, "TMTimerSet retries.",                  "/Devices/APIC/%u/TimerSetLvt/ArmRetries", i);
     2664        PDMDevHlpSTAMRegisterF(pDevIns, &pApic->StatTimerSetLvtNoRelevantChange,STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_OCCURENCES, "No relevant flags changed.",           "/Devices/APIC/%u/TimerSetLvt/NoRelevantChange", i);
     2665    }
    24452666#endif
    24462667
     
    25152736
    25162737    STAM_COUNTER_INC(&CTXSUFF(s->StatMMIORead));
    2517     switch (cb)
    2518     {
    2519         case 1:
    2520             *(uint8_t *)pv = ioapic_mem_readl(s, GCPhysAddr);
    2521             break;
    2522 
    2523         case 2:
    2524             *(uint16_t *)pv = ioapic_mem_readl(s, GCPhysAddr);
    2525             break;
    2526 
    2527         case 4:
    2528             *(uint32_t *)pv = ioapic_mem_readl(s, GCPhysAddr);
    2529             break;
    2530 
    2531         default:
    2532             AssertReleaseMsgFailed(("cb=%d\n", cb)); /* for now we assume simple accesses. */
    2533             IOAPIC_UNLOCK(s);
    2534             return VERR_INTERNAL_ERROR;
     2738    switch (cb) {
     2739    case 1:
     2740        *(uint8_t *)pv = ioapic_mem_readl(s, GCPhysAddr);
     2741        break;
     2742
     2743    case 2:
     2744        *(uint16_t *)pv = ioapic_mem_readl(s, GCPhysAddr);
     2745        break;
     2746
     2747    case 4:
     2748        *(uint32_t *)pv = ioapic_mem_readl(s, GCPhysAddr);
     2749        break;
     2750
     2751    default:
     2752        AssertReleaseMsgFailed(("cb=%d\n", cb)); /* for now we assume simple accesses. */
     2753        IOAPIC_UNLOCK(s);
     2754        return VERR_INTERNAL_ERROR;
    25352755    }
    25362756    IOAPIC_UNLOCK(s);
     
    25432763
    25442764    STAM_COUNTER_INC(&CTXSUFF(s->StatMMIOWrite));
    2545     switch (cb)
    2546     {
    2547         case 1:
    2548         case 2:
    2549         case 4:
    2550             IOAPIC_LOCK(s, VINF_IOM_HC_MMIO_WRITE);
    2551             ioapic_mem_writel(s, GCPhysAddr, *(uint32_t *)pv);
    2552             IOAPIC_UNLOCK(s);
    2553             break;
    2554 
    2555         default:
    2556             AssertReleaseMsgFailed(("cb=%d\n", cb)); /* for now we assume simple accesses. */
    2557             return VERR_INTERNAL_ERROR;
     2765    switch (cb) {
     2766    case 1:
     2767    case 2:
     2768    case 4:
     2769        IOAPIC_LOCK(s, VINF_IOM_HC_MMIO_WRITE);
     2770        ioapic_mem_writel(s, GCPhysAddr, *(uint32_t *)pv);
     2771        IOAPIC_UNLOCK(s);
     2772        break;
     2773
     2774    default:
     2775        AssertReleaseMsgFailed(("cb=%d\n", cb)); /* for now we assume simple accesses. */
     2776        return VERR_INTERNAL_ERROR;
    25582777    }
    25592778    return VINF_SUCCESS;
  • trunk/src/VBox/Devices/testcase/tstDeviceStructSizeGC.cpp

    r20092 r20734  
    590590    GEN_CHECK_OFF(APICState, pTimerR0);
    591591    GEN_CHECK_OFF(APICState, pTimerRC);
     592    GEN_CHECK_OFF(APICState, fTimerArmed);
     593    GEN_CHECK_OFF(APICState, pszDesc);
     594    GEN_CHECK_OFF(APICState, StatTimerSetInitialCount);
     595    GEN_CHECK_OFF(APICState, StatTimerSetLvtNoRelevantChange);
    592596
    593597    GEN_CHECK_SIZE(APICDeviceInfo);
    594598    GEN_CHECK_OFF(APICDeviceInfo, pDevInsR3);
    595599    GEN_CHECK_OFF(APICDeviceInfo, pApicHlpR3);
    596     GEN_CHECK_OFF(APICDeviceInfo, pLapicsR3);
     600    GEN_CHECK_OFF(APICDeviceInfo, paLapicsR3);
    597601    GEN_CHECK_OFF(APICDeviceInfo, pCritSectR3);
    598602    GEN_CHECK_OFF(APICDeviceInfo, pDevInsR0);
    599603    GEN_CHECK_OFF(APICDeviceInfo, pApicHlpR0);
    600     GEN_CHECK_OFF(APICDeviceInfo, pLapicsR0);
     604    GEN_CHECK_OFF(APICDeviceInfo, paLapicsR0);
    601605    GEN_CHECK_OFF(APICDeviceInfo, pCritSectR0);
    602606    GEN_CHECK_OFF(APICDeviceInfo, pDevInsRC);
    603607    GEN_CHECK_OFF(APICDeviceInfo, pApicHlpRC);
    604     GEN_CHECK_OFF(APICDeviceInfo, pLapicsRC);
     608    GEN_CHECK_OFF(APICDeviceInfo, paLapicsRC);
    605609    GEN_CHECK_OFF(APICDeviceInfo, pCritSectRC);
    606610    GEN_CHECK_OFF(APICDeviceInfo, enmVersion);
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