VirtualBox

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


Ignore:
Timestamp:
Jun 13, 2016 4:04:42 PM (9 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
108043
Message:

VMM: I/O APIC lockless implementation.

File:
1 edited

Legend:

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

    r61375 r61685  
    8181#define IOAPIC_VER_HAS_PRQ(a_Reg)               RT_BOOL((a_Reg) & RT_BIT_32(15))
    8282
     83/** Index register - Valid write mask. */
     84#define IOAPIC_INDEX_VALID_WRITE_MASK           UINT32_C(0xff)
     85
    8386/** Arbitration register - Gets the ID. */
    8487#define IOAPIC_ARB_GET_ID(a_Reg)                ((a_Reg) >> 24 & 0xf)
     
    9093#define IOAPIC_RTE_VECTOR                       UINT64_C(0xff)
    9194/** Redirection table entry - Delivery mode. */
    92 #define IOAPIC_RTE_DELIVERY_MODE                (RT_BIT_64(8) | RT_BIT_64(9) | RT_BIT_64(10))
     95#define IOAPIC_RTE_DELIVERY_MODE                (RT_BIT(8) | RT_BIT(9) | RT_BIT(10))
    9396/** Redirection table entry - Destination mode. */
    94 #define IOAPIC_RTE_DEST_MODE                    RT_BIT_64(11)
     97#define IOAPIC_RTE_DEST_MODE                    RT_BIT(11)
    9598/** Redirection table entry - Delivery status. */
    96 #define IOAPIC_RTE_DELIVERY_STATUS              RT_BIT_64(12)
     99#define IOAPIC_RTE_DELIVERY_STATUS              RT_BIT(12)
    97100/** Redirection table entry - Interrupt input pin polarity. */
    98 #define IOAPIC_RTE_POLARITY                     RT_BIT_64(13)
     101#define IOAPIC_RTE_POLARITY                     RT_BIT(13)
    99102/** Redirection table entry - Remote IRR. */
    100 #define IOAPIC_RTE_REMOTE_IRR                   RT_BIT_64(14)
     103#define IOAPIC_RTE_REMOTE_IRR                   RT_BIT(14)
    101104/** Redirection table entry - Trigger Mode. */
    102 #define IOAPIC_RTE_TRIGGER_MODE                 RT_BIT_64(15)
     105#define IOAPIC_RTE_TRIGGER_MODE                 RT_BIT(15)
    103106/** Redirection table entry - the mask bit number. */
    104107#define IOAPIC_RTE_MASK_BIT                     16
    105108/** Redirection table entry - the mask. */
    106 #define IOAPIC_RTE_MASK                         RT_BIT_64(IOAPIC_RTE_MASK_BIT)
     109#define IOAPIC_RTE_MASK                         RT_BIT(IOAPIC_RTE_MASK_BIT)
    107110/** Redirection table entry - Extended Destination ID. */
    108111#define IOAPIC_RTE_EXT_DEST_ID                  UINT64_C(0x00ff000000000000)
     
    151154/** Redirection table entry - Trigger mode level. */
    152155#define IOAPIC_RTE_TRIGGER_MODE_LEVEL           1
     156/** Redirection table entry - Destination mode physical. */
     157#define IOAPIC_RTE_DEST_MODE_PHYSICAL           0
     158/** Redirection table entry - Destination mode logical. */
     159#define IOAPIC_RTE_DEST_MODE_LOGICAL            1
     160
    153161
    154162/** Index of indirect registers in the I/O APIC register table. */
     
    193201*   Structures and Typedefs                                                                                                      *
    194202*********************************************************************************************************************************/
     203/**
     204 * The I/O Redirection Table Entry (RTE).
     205 */
     206typedef union RTE
     207{
     208    /** Unsigned integer view. */
     209    uint64_t volatile       u;
     210    /** 64 bit unsigned integer view. */
     211    uint64_t volatile       au64[1];
     212    /** 32 bit unsigned integer view. */
     213    uint32_t volatile       au32[2];
     214} RTE;
     215AssertCompileSize(RTE, sizeof(uint64_t));
     216
     217/**
     218 * The per-VM I/O APIC device state.
     219 */
    195220typedef struct IOAPIC
    196221{
     
    211236
    212237    /** The ID register. */
    213     uint8_t                 u8Id;
     238    uint8_t volatile        u8Id;
    214239    /** The index register. */
    215     uint8_t                 u8Index;
     240    uint8_t volatile        u8Index;
    216241    /** Number of CPUs. */
    217242    uint8_t                 cCpus;
    218243    /* Alignment padding. */
    219244    uint8_t                 u8Padding0[5];
    220 #if IOAPIC_HARDWARE_VERSION == IOAPIC_HARDWARE_VERSION_ICH9
    221     /** The EOI register. */
    222     uint32_t                u32Eoi;
    223     uint32_t                u32Padding1;
    224 #else
    225     uint64_t                u64Padding0;
    226 #endif
    227245
    228246    /** The redirection table registers. */
    229     uint64_t                au64RedirTable[IOAPIC_NUM_INTR_PINS];
     247    RTE                     au64RedirTable[IOAPIC_NUM_INTR_PINS];
    230248    /** The IRQ tags and source IDs for each pin (tracing purposes). */
    231249    uint32_t                au32TagSrc[IOAPIC_NUM_INTR_PINS];
     
    233251    /** Alignment padding. */
    234252    uint32_t                u32Padding2;
    235     /** The internal IRR reflecting interrupt lines. */
    236     uint32_t                uIrr;
     253    /** The internal IRR reflecting state of the interrupt lines. */
     254    uint32_t volatile       uIrr;
    237255
    238256#ifdef VBOX_WITH_STATISTICS
     
    264282    /** Number of SetEoi calls in RC. */
    265283    STAMCOUNTER             StatSetEoiRC;
     284
     285    /** Number of redundant edge-triggered interrupts. */
     286    STAMCOUNTER             StatRedundantEdgeIntr;
     287    /** Number of redundant level-triggered interrupts. */
     288    STAMCOUNTER             StatRedundantLevelIntr;
     289    /** Number of suppressed level-triggered interrupts (by remote IRR). */
     290    STAMCOUNTER             StatSuppressedLevelIntr;
    266291#endif
    267292} IOAPIC;
     
    310335{
    311336    Log2(("IOAPIC: ioapicSetId: uValue=%#RX32\n", uValue));
    312     pThis->u8Id = (uValue >> 24) & IOAPIC_ID_MASK;
     337    ASMAtomicWriteU8(&pThis->u8Id, (uValue >> 24) & IOAPIC_ID_MASK);
    313338}
    314339
     
    337362{
    338363    LogFlow(("IOAPIC: ioapicSetIndex: uValue=%#RX32\n", uValue));
    339     pThis->u8Index = uValue & 0xff;
     364    ASMAtomicWriteU8(&pThis->u8Index, uValue & IOAPIC_INDEX_VALID_WRITE_MASK);
    340365}
    341366
     
    360385 * @param   pThis       The IOAPIC instance.
    361386 * @param   idxRte      The index of the RTE.
    362  */
    363 static void ioapicSignalIrqForRte(PIOAPIC pThis, uint8_t idxRte)
    364 {
    365     /* Check if there's an interrupt on the corresponding interrupt input pin. */
    366     uint32_t const uPinMask = UINT32_C(1) << idxRte;
    367     if (pThis->uIrr & uPinMask)
    368     {
    369         /* Ensure the RTE isn't masked. */
    370         uint64_t const u64Rte = pThis->au64RedirTable[idxRte];
    371         if (!IOAPIC_RTE_IS_MASKED(u64Rte))
     387 *
     388 * @remarks It is the responsibility of the caller to verify that an interrupt is
     389 *          pending for the pin corresponding to the RTE before calling this
     390 *          function.
     391 */
     392static void ioapicSignalIntrForRte(PIOAPIC pThis, uint8_t idxRte)
     393{
     394    /* Ensure the RTE isn't masked. */
     395    uint64_t const u64Rte = pThis->au64RedirTable[idxRte].u;
     396    if (!IOAPIC_RTE_IS_MASKED(u64Rte))
     397    {
     398        /* We cannot accept another level-triggered interrupt until remote IRR has been cleared. */
     399        uint8_t const u8TriggerMode = IOAPIC_RTE_GET_TRIGGER_MODE(u64Rte);
     400        if (u8TriggerMode == IOAPIC_RTE_TRIGGER_MODE_LEVEL)
    372401        {
    373             uint32_t const u32TagSrc      = pThis->au32TagSrc[idxRte];
    374             uint8_t const  u8Vector       = IOAPIC_RTE_GET_VECTOR(u64Rte);
    375             uint8_t const  u8DeliveryMode = IOAPIC_RTE_GET_DELIVERY_MODE(u64Rte);
    376             uint8_t const  u8DestMode     = IOAPIC_RTE_GET_DEST_MODE(u64Rte);
    377             uint8_t const  u8Polarity     = IOAPIC_RTE_GET_POLARITY(u64Rte);
    378             uint8_t const  u8TriggerMode  = IOAPIC_RTE_GET_TRIGGER_MODE(u64Rte);
    379             uint8_t const  u8Dest         = IOAPIC_RTE_GET_DEST(u64Rte);
    380 
    381             /* We cannot accept another level-triggered interrupt until remote IRR has been cleared. */
    382             if (u8TriggerMode == IOAPIC_RTE_TRIGGER_MODE_LEVEL)
     402            uint8_t const u8RemoteIrr = IOAPIC_RTE_GET_REMOTE_IRR(u64Rte);
     403            if (u8RemoteIrr)
    383404            {
    384                 uint8_t const u8RemoteIrr = IOAPIC_RTE_GET_REMOTE_IRR(u64Rte);
    385                 if (u8RemoteIrr)
    386                     return;
     405                STAM_COUNTER_INC(&pThis->StatSuppressedLevelIntr);
     406                return;
    387407            }
    388 
    389             /*
    390              * Deliver to the local APIC via the system/3-wire-APIC bus.
    391              */
    392             int rc = pThis->CTX_SUFF(pIoApicHlp)->pfnApicBusDeliver(pThis->CTX_SUFF(pDevIns),
    393                                                                     u8Dest,
    394                                                                     u8DestMode,
    395                                                                     u8DeliveryMode,
    396                                                                     u8Vector,
    397                                                                     u8Polarity,
    398                                                                     u8TriggerMode,
    399                                                                     u32TagSrc);
    400             /* Can't reschedule to R3. */
    401             Assert(rc == VINF_SUCCESS);
    402 
    403             /*
    404              * For edge triggered interrupts, we can clear our IRR bit to receive further
    405              * edge-triggered interrupts, as the local APIC has accepted the interrupt.
    406              */
    407             if (u8TriggerMode == IOAPIC_RTE_TRIGGER_MODE_EDGE)
    408             {
    409                 pThis->uIrr &= ~uPinMask;
    410                 pThis->au32TagSrc[idxRte] = 0;
    411             }
    412             else
    413             {
    414                 /*
    415                  * For level triggered interrupts, we set the remote IRR bit to indicate
    416                  * the local APIC has accepted the interrupt.
    417                  */
    418                 Assert(u8TriggerMode == IOAPIC_RTE_TRIGGER_MODE_LEVEL);
    419                 pThis->au64RedirTable[idxRte] |= IOAPIC_RTE_REMOTE_IRR;
    420             }
     408        }
     409
     410        uint8_t const  u8Vector       = IOAPIC_RTE_GET_VECTOR(u64Rte);
     411        uint8_t const  u8DeliveryMode = IOAPIC_RTE_GET_DELIVERY_MODE(u64Rte);
     412        uint8_t const  u8DestMode     = IOAPIC_RTE_GET_DEST_MODE(u64Rte);
     413        uint8_t const  u8Polarity     = IOAPIC_RTE_GET_POLARITY(u64Rte);
     414        uint8_t const  u8Dest         = IOAPIC_RTE_GET_DEST(u64Rte);
     415        uint32_t const u32TagSrc      = pThis->au32TagSrc[idxRte];
     416
     417        Log2(("IOAPIC: Signaling %s-triggered interrupt. Dest=%#x DestMode=%s Vector=%#x (%u)",
     418              u8TriggerMode == IOAPIC_RTE_TRIGGER_MODE_EDGE ? "edge" : "level", u8Dest,
     419              u8DestMode == IOAPIC_RTE_DEST_MODE_PHYSICAL ? "physical" : "logical", u8Vector, u8Vector));
     420
     421        /*
     422         * Deliver to the local APIC via the system/3-wire-APIC bus.
     423         */
     424        int rc = pThis->CTX_SUFF(pIoApicHlp)->pfnApicBusDeliver(pThis->CTX_SUFF(pDevIns),
     425                                                                u8Dest,
     426                                                                u8DestMode,
     427                                                                u8DeliveryMode,
     428                                                                u8Vector,
     429                                                                u8Polarity,
     430                                                                u8TriggerMode,
     431                                                                u32TagSrc);
     432        /* Can't reschedule to R3. */
     433        Assert(rc == VINF_SUCCESS);
     434
     435        /*
     436         * For level-triggered interrupts, we set the remote IRR bit to indicate
     437         * the local APIC has accepted the interrupt.
     438         *
     439         * For edge-triggered interrupts, we should not clear the IRR bit as it
     440         * should remain intact to reflect the state of the interrupt line.
     441         * The device will explicitly transition to inactive state via the
     442         * ioapicSetIrq() callback.
     443         */
     444        if (u8TriggerMode == IOAPIC_RTE_TRIGGER_MODE_LEVEL)
     445        {
     446            Assert(u8TriggerMode == IOAPIC_RTE_TRIGGER_MODE_LEVEL);
     447            ASMAtomicOrU32(&pThis->au64RedirTable[idxRte].au32[0], IOAPIC_RTE_REMOTE_IRR);
    421448        }
    422449    }
     
    436463    uint32_t uValue;
    437464    if (!(uIndex & 1))
    438         uValue = RT_LO_U32(pThis->au64RedirTable[idxRte]) & RT_LO_U32(IOAPIC_RTE_VALID_READ_MASK);
     465        uValue = pThis->au64RedirTable[idxRte].au32[0] & RT_LO_U32(IOAPIC_RTE_VALID_READ_MASK);
    439466    else
    440         uValue = RT_HI_U32(pThis->au64RedirTable[idxRte]) & RT_HI_U32(IOAPIC_RTE_VALID_READ_MASK);
     467        uValue = pThis->au64RedirTable[idxRte].au32[1] & RT_HI_U32(IOAPIC_RTE_VALID_READ_MASK);
    441468
    442469    LogFlow(("IOAPIC: ioapicGetRedirTableEntry: uIndex=%#RX32 idxRte=%u returns %#RX32\n", uIndex, idxRte, uValue));
     
    462489     * Update only the valid, writable bits.
    463490     */
    464     uint64_t const u64Rte = pThis->au64RedirTable[idxRte];
     491    uint64_t const u64Rte = pThis->au64RedirTable[idxRte].u;
    465492    if (!(uIndex & 1))
    466493    {
    467494        uint32_t const u32RteNewLo = uValue & RT_LO_U32(IOAPIC_RTE_VALID_WRITE_MASK);
    468         uint64_t const u64RteHi    = u64Rte & UINT64_C(0xffffffff00000000);
    469         pThis->au64RedirTable[idxRte] = u64RteHi | u32RteNewLo;
     495        ASMAtomicWriteU32(&pThis->au64RedirTable[idxRte].au32[0], u32RteNewLo);
    470496    }
    471497    else
    472498    {
    473         uint32_t const u32RteLo    = RT_LO_U32(u64Rte);
    474         uint64_t const u64RteNewHi = (uint64_t)(uValue & RT_HI_U32(IOAPIC_RTE_VALID_WRITE_MASK)) << 32;
    475         pThis->au64RedirTable[idxRte] = u64RteNewHi | u32RteLo;
    476     }
    477 
    478     ioapicSignalIrqForRte(pThis, idxRte);
     499        uint32_t const u32RteNewHi = uValue & RT_HI_U32(IOAPIC_RTE_VALID_WRITE_MASK);
     500        ASMAtomicWriteU32(&pThis->au64RedirTable[idxRte].au32[1], u32RteNewHi);
     501    }
     502
     503    /*
     504     * Signal the next pending interrupt for this RTE.
     505     */
     506    uint32_t const uPinMask = UINT32_C(1) << idxRte;
     507    if (pThis->uIrr & uPinMask)
     508        ioapicSignalIntrForRte(pThis, idxRte);
    479509
    480510    LogFlow(("IOAPIC: ioapicSetRedirTableEntry: uIndex=%#RX32 idxRte=%u uValue=%#RX32\n", uIndex, idxRte, uValue));
     
    547577/**
    548578 * @interface_method_impl{PDMIOAPICREG,pfnSetEoiR3}
    549  * @remarks The device critsect is entered by the caller(s).
    550579 */
    551580PDMBOTHCBDECL(void) ioapicSetEoi(PPDMDEVINS pDevIns, uint8_t u8Vector)
     
    557586    for (uint8_t idxRte = 0; idxRte < RT_ELEMENTS(pThis->au64RedirTable); idxRte++)
    558587    {
    559         uint64_t const u64Rte = pThis->au64RedirTable[idxRte];
     588        uint64_t const u64Rte = pThis->au64RedirTable[idxRte].u;
    560589        if (IOAPIC_RTE_GET_VECTOR(u64Rte) == u8Vector)
    561590        {
    562             pThis->au64RedirTable[idxRte] &= ~IOAPIC_RTE_REMOTE_IRR;
     591            ASMAtomicAndU32(&pThis->au64RedirTable[idxRte].au32[0], ~IOAPIC_RTE_REMOTE_IRR);
    563592            Log2(("IOAPIC: ioapicSetEoi: Cleared remote IRR for RTE %u\n", idxRte));
    564             ioapicSignalIrqForRte(pThis, idxRte);
     593
     594            /*
     595             * Signal the next pending interrupt for this RTE.
     596             */
     597            uint32_t const uPinMask = UINT32_C(1) << idxRte;
     598            if (pThis->uIrr & uPinMask)
     599                ioapicSignalIntrForRte(pThis, idxRte);
    565600        }
    566601    }
     
    570605/**
    571606 * @interface_method_impl{PDMIOAPICREG,pfnSetIrqR3}
    572  * @remarks The device critsect is entered by the caller(s).
    573607 */
    574608PDMBOTHCBDECL(void) ioapicSetIrq(PPDMDEVINS pDevIns, int iIrq, int iLevel, uint32_t uTagSrc)
     
    579613    STAM_COUNTER_INC(&pThis->CTX_SUFF(StatSetIrq));
    580614
    581     if (iIrq >= 0 && iIrq < (int)RT_ELEMENTS(pThis->au64RedirTable))
    582     {
    583         uint8_t  const idxRte = iIrq;
    584         uint64_t const u64Rte = pThis->au64RedirTable[idxRte];
    585         uint8_t  const u8TriggerMode = IOAPIC_RTE_GET_TRIGGER_MODE(u64Rte);
    586         uint32_t const uPinMask = UINT32_C(1) << idxRte;
     615    if (RT_LIKELY(iIrq >= 0 && iIrq < (int)RT_ELEMENTS(pThis->au64RedirTable)))
     616    {
     617        uint8_t  const idxRte        = iIrq;
     618        uint32_t const uPinMask      = UINT32_C(1) << idxRte;
     619        uint32_t const u32RteLo      = pThis->au64RedirTable[idxRte].au32[0];
     620        uint8_t  const u8TriggerMode = IOAPIC_RTE_GET_TRIGGER_MODE(u32RteLo);
     621
     622        bool fActive = RT_BOOL(iLevel & 1);
     623        /** @todo Polarity is busted elsewhere, we need to fix that
     624         *        first. See @bugref{8386#c7}. */
     625#if 0
     626        uint8_t const u8Polarity = IOAPIC_RTE_GET_POLARITY(u32RteLo);
     627        fActive ^= u8Polarity; */
     628#endif
     629        if (!fActive)
     630        {
     631            ASMAtomicAndU32(&pThis->uIrr, ~uPinMask);
     632            return;
     633        }
     634
     635        /*
     636         * If the device is flip-flopping the interrupt line, there's no need to
     637         * set and unset the IRR as they're atomic operations and the fewer the
     638         * better.
     639         */
     640        bool const fTouchIrr = !((iLevel & PDM_IRQ_LEVEL_FLIP_FLOP) == PDM_IRQ_LEVEL_FLIP_FLOP);
    587641
    588642        if (u8TriggerMode == IOAPIC_RTE_TRIGGER_MODE_EDGE)
    589643        {
    590             /** @todo Consider polarity for edge-triggered interrupts? There
    591              *        seems to be a conflict between "The Unabridged Pentium"
    592              *        book and the I/O APIC specs. */
    593             if (iLevel)
     644            /*
     645             * For edge-triggered interrupts, we need to act only on an edge transition.
     646             * See ICH9 spec. 13.5.7 "REDIR_TBL: Redirection Table (LPC I/F-D31:F0)"
     647             */
     648            uint32_t const uPrevIrr = pThis->uIrr & uPinMask;
     649            if (!uPrevIrr)
    594650            {
    595                 pThis->uIrr |= uPinMask;
     651                if (fTouchIrr)
     652                    ASMAtomicOrU32(&pThis->uIrr, uPinMask);
     653
    596654                if (!pThis->au32TagSrc[idxRte])
    597655                    pThis->au32TagSrc[idxRte] = uTagSrc;
     
    599657                    pThis->au32TagSrc[idxRte] = RT_BIT_32(31);
    600658
    601                 ioapicSignalIrqForRte(pThis, idxRte);
     659                ioapicSignalIntrForRte(pThis, idxRte);
    602660            }
    603661            else
    604                 pThis->uIrr &= ~uPinMask;
     662            {
     663                STAM_COUNTER_INC(&pThis->StatRedundantEdgeIntr);
     664                Log2(("IOAPIC: Redundant edge-triggered interrupt %#x (%u)\n", idxRte, idxRte));
     665            }
    605666        }
    606667        else
     
    608669            Assert(u8TriggerMode == IOAPIC_RTE_TRIGGER_MODE_LEVEL);
    609670
    610             bool fActive = RT_BOOL(iLevel & 1);
    611             /** @todo Polarity is busted elsewhere, we need to fix that
    612              *        first. See @bugref{8386#c7}. */
    613 #if 0
    614             uint8_t const u8Polarity = IOAPIC_RTE_GET_POLARITY(u64Rte);
    615             fActive ^= u8Polarity; */
    616 #endif
    617 
    618             if (fActive)
     671            /*
     672             * For level-triggered interrupts, redundant interrupts are not a problem
     673             * and will eventually be delivered anyway after an EOI, but our PDM devices
     674             * should not typically call us with no change to the level.
     675             */
     676            uint32_t const uPrevIrr = pThis->uIrr & uPinMask;
     677            if (!uPrevIrr)
     678            { /* likely */ }
     679            else
    619680            {
    620                 pThis->uIrr |= uPinMask;
    621                 if (!pThis->au32TagSrc[idxRte])
    622                     pThis->au32TagSrc[idxRte] = uTagSrc;
    623                 else
    624                     pThis->au32TagSrc[idxRte] = RT_BIT_32(31);
    625 
    626                 ioapicSignalIrqForRte(pThis, idxRte);
    627 
    628                 if ((iLevel & PDM_IRQ_LEVEL_FLIP_FLOP) == PDM_IRQ_LEVEL_FLIP_FLOP)
    629                 {
    630                     pThis->uIrr &= ~uPinMask;
    631                     pThis->au32TagSrc[idxRte] = 0;
    632                 }
     681                STAM_COUNTER_INC(&pThis->StatRedundantLevelIntr);
     682                Log2(("IOAPIC: Redundant level-triggered interrupt %#x (%u)\n", idxRte, idxRte));
    633683            }
     684
     685            if (fTouchIrr)
     686                ASMAtomicOrU32(&pThis->uIrr, uPinMask);
     687
     688            if (!pThis->au32TagSrc[idxRte])
     689                pThis->au32TagSrc[idxRte] = uTagSrc;
    634690            else
    635                 pThis->uIrr &= ~uPinMask;
     691                pThis->au32TagSrc[idxRte] = RT_BIT_32(31);
     692
     693            ioapicSignalIntrForRte(pThis, idxRte);
    636694        }
    637695    }
     
    641699/**
    642700 * @interface_method_impl{PDMIOAPICREG,pfnSendMsiR3}
    643  * @remarks The device critsect is entered by the caller(s).
    644701 */
    645702PDMBOTHCBDECL(void) ioapicSendMsi(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, uint32_t uValue, uint32_t uTagSrc)
     
    689746    STAM_COUNTER_INC(&pThis->CTX_SUFF(StatMmioRead));
    690747
    691     IOAPIC_LOCK(pThis, VINF_IOM_R3_MMIO_READ);
    692 
    693748    int       rc      = VINF_SUCCESS;
    694749    uint32_t *puValue = (uint32_t *)pv;
     
    710765    }
    711766
    712     IOAPIC_UNLOCK(pThis);
    713 
    714767    LogFlow(("IOAPIC: ioapicMmioRead: offReg=%#x, returns %#RX32\n", offReg, *puValue));
    715768    return rc;
     
    725778
    726779    STAM_COUNTER_INC(&pThis->CTX_SUFF(StatMmioWrite));
    727 
    728     IOAPIC_LOCK(pThis, VINF_IOM_R3_MMIO_WRITE);
    729780
    730781    Assert(!(GCPhysAddr & 3));
     
    757808    }
    758809
    759     IOAPIC_UNLOCK(pThis);
    760810    return VINF_SUCCESS;
    761811}
     
    926976        };
    927977
    928         const uint64_t uEntry = pThis->au64RedirTable[idxRte];
    929         const char    *pszDestMode       = IOAPIC_RTE_GET_DEST_MODE(uEntry) == 0 ? "phys" : "log ";
    930         const uint8_t  uDest             = IOAPIC_RTE_GET_DEST(uEntry);
    931         const uint8_t  uMask             = IOAPIC_RTE_GET_MASK(uEntry);
    932         const char    *pszTriggerMode    = IOAPIC_RTE_GET_TRIGGER_MODE(uEntry) == 0 ? "edge " : "level";
    933         const uint8_t  uRemoteIrr        = IOAPIC_RTE_GET_REMOTE_IRR(uEntry);
    934         const char    *pszPolarity       = IOAPIC_RTE_GET_POLARITY(uEntry) == 0 ? "acthi" : "actlo";
    935         const char    *pszDeliveryStatus = IOAPIC_RTE_GET_DELIVERY_STATUS(uEntry) == 0 ? "idle" : "pend";
    936         const uint8_t  uDeliveryMode     = IOAPIC_RTE_GET_DELIVERY_MODE(uEntry);
    937                                            Assert(uDeliveryMode < RT_ELEMENTS(s_apszDeliveryModes));
     978        const uint64_t u64Rte = pThis->au64RedirTable[idxRte].u;
     979        const char    *pszDestMode       = IOAPIC_RTE_GET_DEST_MODE(u64Rte) == 0 ? "phys" : "log ";
     980        const uint8_t  uDest             = IOAPIC_RTE_GET_DEST(u64Rte);
     981        const uint8_t  uMask             = IOAPIC_RTE_GET_MASK(u64Rte);
     982        const char    *pszTriggerMode    = IOAPIC_RTE_GET_TRIGGER_MODE(u64Rte) == 0 ? "edge " : "level";
     983        const uint8_t  uRemoteIrr        = IOAPIC_RTE_GET_REMOTE_IRR(u64Rte);
     984        const char    *pszPolarity       = IOAPIC_RTE_GET_POLARITY(u64Rte) == 0 ? "acthi" : "actlo";
     985        const char    *pszDeliveryStatus = IOAPIC_RTE_GET_DELIVERY_STATUS(u64Rte) == 0 ? "idle" : "pend";
     986        const uint8_t  uDeliveryMode     = IOAPIC_RTE_GET_DELIVERY_MODE(u64Rte);
     987        Assert(uDeliveryMode < RT_ELEMENTS(s_apszDeliveryModes));
    938988        const char    *pszDeliveryMode   = s_apszDeliveryModes[uDeliveryMode];
    939         const uint8_t  uVector           = IOAPIC_RTE_GET_VECTOR(uEntry);
     989        const uint8_t  uVector           = IOAPIC_RTE_GET_VECTOR(u64Rte);
    940990
    941991        pHlp->pfnPrintf(pHlp, "   %02d   %s      %02x     %u    %u   %s   %u   %s  %s     %s   %3u (%016llx)\n",
     
    9511001                        pszDeliveryMode,
    9521002                        uVector,
    953                         pThis->au64RedirTable[idxRte]);
     1003                        u64Rte);
    9541004    }
    9551005}
     
    9681018    SSMR3PutU8(pSSM,  pThis->u8Index);
    9691019    for (uint8_t idxRte = 0; idxRte < RT_ELEMENTS(pThis->au64RedirTable); idxRte++)
    970         SSMR3PutU64(pSSM, pThis->au64RedirTable[idxRte]);
     1020        SSMR3PutU64(pSSM, pThis->au64RedirTable[idxRte].u);
    9711021
    9721022    return VINF_SUCCESS;
     
    9941044
    9951045    if (uVersion == IOAPIC_SAVED_STATE_VERSION)
    996         SSMR3GetU32(pSSM, &pThis->uIrr);
    997 
    998     SSMR3GetU8(pSSM, &pThis->u8Id);
    999     SSMR3GetU8(pSSM, &pThis->u8Index);
     1046        SSMR3GetU32(pSSM, (uint32_t *)&pThis->uIrr);
     1047
     1048    SSMR3GetU8(pSSM, (uint8_t *)&pThis->u8Id);
     1049    SSMR3GetU8(pSSM, (uint8_t *)&pThis->u8Index);
    10001050    for (uint8_t idxRte = 0; idxRte < RT_ELEMENTS(pThis->au64RedirTable); idxRte++)
    1001         SSMR3GetU64(pSSM, &pThis->au64RedirTable[idxRte]);
     1051        SSMR3GetU64(pSSM, (uint64_t *)&pThis->au64RedirTable[idxRte].u);
    10021052
    10031053    return VINF_SUCCESS;
     
    10131063    LogFlow(("IOAPIC: ioapicR3Reset: pThis=%p\n", pThis));
    10141064
    1015     /* We lock here to prevent concurrent writes from ioapicSetIrq() from device threads. */
    1016     IOAPIC_LOCK_VOID(pThis);
    1017 
    1018     pThis->uIrr    = 0;
    1019     pThis->u8Index = 0;
    1020     pThis->u8Id    = 0;
     1065    /* There might be devices threads calling ioapicSetIrq() in parallel, hence the atomics. */
     1066    ASMAtomicWriteU32(&pThis->uIrr, 0);
     1067    ASMAtomicWriteU8(&pThis->u8Index, 0);
     1068    ASMAtomicWriteU8(&pThis->u8Id, 0);
    10211069
    10221070    for (uint8_t idxRte = 0; idxRte < RT_ELEMENTS(pThis->au64RedirTable); idxRte++)
    10231071    {
    1024         pThis->au64RedirTable[idxRte] = IOAPIC_RTE_MASK;
    1025         pThis->au32TagSrc[idxRte]     = 0;
    1026     }
    1027 
    1028     IOAPIC_UNLOCK(pThis);
     1072        ASMAtomicWriteU64(&pThis->au64RedirTable[idxRte].u, IOAPIC_RTE_MASK);
     1073        pThis->au32TagSrc[idxRte] = 0;
     1074    }
    10291075}
    10301076
     
    10641110    PDMDEV_VALIDATE_CONFIG_RETURN(pDevIns, "NumCPUs|RZEnabled", "");
    10651111
     1112    /* The number of CPUs is currently unused, but left in CFGM and saved-state in case an ID of 0 is
     1113       upsets some guest which we haven't yet tested. */
    10661114    uint32_t cCpus;
    10671115    int rc = CFGMR3QueryU32Def(pCfg, "NumCPUs", &cCpus, 1);
    10681116    if (RT_FAILURE(rc))
    10691117        return PDMDEV_SET_ERROR(pDevIns, rc, N_("Configuration error: Failed to query integer value \"NumCPUs\""));
    1070     if (cCpus > UINT8_MAX - 2) /* ID 255 is broadcast and the IO-APIC needs one (ID=cCpus). */
    1071     {
    1072         return PDMDevHlpVMSetError(pDevIns, rc, RT_SRC_POS,
    1073                                    N_("Configuration error: Max %u CPUs, %u specified"), UINT8_MAX - 1, cCpus);
    1074     }
    10751118    pThis->cCpus = (uint8_t)cCpus;
    10761119
     
    10841127
    10851128    /*
    1086      * We shall do locking for this device via IOAPIC helpers.
     1129     * We don't do any locking for the IOAPIC device.
    10871130     */
    10881131    rc = PDMDevHlpSetDeviceCritSect(pDevIns, PDMDevHlpCritSectGetNop(pDevIns));
     
    11831226    PDMDevHlpSTAMRegister(pDevIns, &pThis->StatSetIrqRC,    STAMTYPE_COUNTER, "/Devices/IOAPIC/RC/SetIrqRC",    STAMUNIT_OCCURENCES, "Number of IOAPIC SetIrq calls in RC.");
    11841227    PDMDevHlpSTAMRegister(pDevIns, &pThis->StatSetEoiRC,    STAMTYPE_COUNTER, "/Devices/IOAPIC/RC/SetEoiRC",    STAMUNIT_OCCURENCES, "Number of IOAPIC SetEoi calls in RC.");
     1228
     1229    PDMDevHlpSTAMRegister(pDevIns, &pThis->StatRedundantEdgeIntr,   STAMTYPE_COUNTER, "/Devices/IOAPIC/RedundantEdgeIntr",   STAMUNIT_OCCURENCES, "Number of redundant edge-triggered interrupts (no IRR change).");
     1230    PDMDevHlpSTAMRegister(pDevIns, &pThis->StatRedundantLevelIntr,  STAMTYPE_COUNTER, "/Devices/IOAPIC/RedundantLevelIntr",  STAMUNIT_OCCURENCES, "Number of redundant level-triggered interrupts (no IRR change).");
     1231    PDMDevHlpSTAMRegister(pDevIns, &pThis->StatSuppressedLevelIntr, STAMTYPE_COUNTER, "/Devices/IOAPIC/SuppressedLevelIntr", STAMUNIT_OCCURENCES, "Number of suppressed level-triggered interrupts by remote IRR.");
    11851232#endif
    11861233
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