VirtualBox

Changeset 61735 in vbox for trunk/src


Ignore:
Timestamp:
Jun 17, 2016 7:39:35 AM (9 years ago)
Author:
vboxsync
Message:

PDM,VMM: I/O APIC critsect fixes and interface changes to broadcast EOI.

Location:
trunk/src/VBox
Files:
6 edited

Legend:

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

    r61685 r61735  
    9393#define IOAPIC_RTE_VECTOR                       UINT64_C(0xff)
    9494/** Redirection table entry - Delivery mode. */
    95 #define IOAPIC_RTE_DELIVERY_MODE                (RT_BIT(8) | RT_BIT(9) | RT_BIT(10))
     95#define IOAPIC_RTE_DELIVERY_MODE                (RT_BIT_64(8) | RT_BIT_64(9) | RT_BIT_64(10))
    9696/** Redirection table entry - Destination mode. */
    97 #define IOAPIC_RTE_DEST_MODE                    RT_BIT(11)
     97#define IOAPIC_RTE_DEST_MODE                    RT_BIT_64(11)
    9898/** Redirection table entry - Delivery status. */
    99 #define IOAPIC_RTE_DELIVERY_STATUS              RT_BIT(12)
     99#define IOAPIC_RTE_DELIVERY_STATUS              RT_BIT_64(12)
    100100/** Redirection table entry - Interrupt input pin polarity. */
    101 #define IOAPIC_RTE_POLARITY                     RT_BIT(13)
     101#define IOAPIC_RTE_POLARITY                     RT_BIT_64(13)
    102102/** Redirection table entry - Remote IRR. */
    103 #define IOAPIC_RTE_REMOTE_IRR                   RT_BIT(14)
     103#define IOAPIC_RTE_REMOTE_IRR                   RT_BIT_64(14)
    104104/** Redirection table entry - Trigger Mode. */
    105 #define IOAPIC_RTE_TRIGGER_MODE                 RT_BIT(15)
     105#define IOAPIC_RTE_TRIGGER_MODE                 RT_BIT_64(15)
    106106/** Redirection table entry - the mask bit number. */
    107107#define IOAPIC_RTE_MASK_BIT                     16
    108108/** Redirection table entry - the mask. */
    109 #define IOAPIC_RTE_MASK                         RT_BIT(IOAPIC_RTE_MASK_BIT)
     109#define IOAPIC_RTE_MASK                         RT_BIT_64(IOAPIC_RTE_MASK_BIT)
    110110/** Redirection table entry - Extended Destination ID. */
    111111#define IOAPIC_RTE_EXT_DEST_ID                  UINT64_C(0x00ff000000000000)
     
    176176#endif
    177177
    178 /** @def IOAPIC_LOCK
    179  * Acquires the PDM lock. */
    180 #define IOAPIC_LOCK(pThis, rcBusy) \
    181     do { \
    182         int rcLock = (pThis)->CTX_SUFF(pIoApicHlp)->pfnLock((pThis)->CTX_SUFF(pDevIns), rcBusy); \
    183         if (rcLock != VINF_SUCCESS) \
    184             return rcLock; \
    185     } while (0)
    186 
    187 /** @def IOAPIC_LOCK_VOID
    188  * Acquires the PDM lock assumes success. */
    189 #define IOAPIC_LOCK_VOID(pThis) \
    190     do { \
    191         int rcLock = (pThis)->CTX_SUFF(pIoApicHlp)->pfnLock((pThis)->CTX_SUFF(pDevIns), VERR_INTERNAL_ERROR_2); \
    192         Assert(rcLock == VINF_SUCCESS); \
    193     } while (0)
    194 
    195 /** @def IOAPIC_UNLOCK
    196  * Releases the PDM lock. */
    197 #define IOAPIC_UNLOCK(pThis)    (pThis)->CTX_SUFF(pIoApicHlp)->pfnUnlock((pThis)->CTX_SUFF(pDevIns))
    198 
    199178
    200179/*********************************************************************************************************************************
    201180*   Structures and Typedefs                                                                                                      *
    202181*********************************************************************************************************************************/
    203 /**
    204  * The I/O Redirection Table Entry (RTE).
    205  */
    206 typedef 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;
    215 AssertCompileSize(RTE, sizeof(uint64_t));
    216 
    217182/**
    218183 * The per-VM I/O APIC device state.
     
    245210
    246211    /** The redirection table registers. */
    247     RTE                     au64RedirTable[IOAPIC_NUM_INTR_PINS];
     212    uint64_t                au64RedirTable[IOAPIC_NUM_INTR_PINS];
    248213    /** The IRQ tags and source IDs for each pin (tracing purposes). */
    249214    uint32_t                au32TagSrc[IOAPIC_NUM_INTR_PINS];
     
    252217    uint32_t                u32Padding2;
    253218    /** The internal IRR reflecting state of the interrupt lines. */
    254     uint32_t volatile       uIrr;
     219    uint32_t                uIrr;
     220
     221    /** The critsect for updating to the RTEs. */
     222    PDMCRITSECT             CritSect;
    255223
    256224#ifdef VBOX_WITH_STATISTICS
     
    289257    /** Number of suppressed level-triggered interrupts (by remote IRR). */
    290258    STAMCOUNTER             StatSuppressedLevelIntr;
     259    /** Number of returns to ring-3 due to EOI broadcast lock contention. */
     260    STAMCOUNTER             StatEoiContention;
     261    /** Number of returns to ring-3 due to Set RTE lock contention. */
     262    STAMCOUNTER             StatSetRteContention;
    291263#endif
    292264} IOAPIC;
     
    392364static void ioapicSignalIntrForRte(PIOAPIC pThis, uint8_t idxRte)
    393365{
     366    Assert(PDMCritSectIsOwner(&pThis->CritSect));
     367
    394368    /* Ensure the RTE isn't masked. */
    395     uint64_t const u64Rte = pThis->au64RedirTable[idxRte].u;
     369    uint64_t const u64Rte = pThis->au64RedirTable[idxRte];
    396370    if (!IOAPIC_RTE_IS_MASKED(u64Rte))
    397371    {
     
    445419        {
    446420            Assert(u8TriggerMode == IOAPIC_RTE_TRIGGER_MODE_LEVEL);
    447             ASMAtomicOrU32(&pThis->au64RedirTable[idxRte].au32[0], IOAPIC_RTE_REMOTE_IRR);
     421            pThis->au64RedirTable[idxRte] |= IOAPIC_RTE_REMOTE_IRR;
    448422        }
    449423    }
     
    463437    uint32_t uValue;
    464438    if (!(uIndex & 1))
    465         uValue = pThis->au64RedirTable[idxRte].au32[0] & RT_LO_U32(IOAPIC_RTE_VALID_READ_MASK);
     439        uValue = RT_LO_U32(pThis->au64RedirTable[idxRte]) & RT_LO_U32(IOAPIC_RTE_VALID_READ_MASK);
    466440    else
    467         uValue = pThis->au64RedirTable[idxRte].au32[1] & RT_HI_U32(IOAPIC_RTE_VALID_READ_MASK);
     441        uValue = RT_HI_U32(pThis->au64RedirTable[idxRte]) & RT_HI_U32(IOAPIC_RTE_VALID_READ_MASK);
    468442
    469443    LogFlow(("IOAPIC: ioapicGetRedirTableEntry: uIndex=%#RX32 idxRte=%u returns %#RX32\n", uIndex, idxRte, uValue));
     
    479453 * @param   uValue      The value to set.
    480454 */
    481 static void ioapicSetRedirTableEntry(PIOAPIC pThis, uint32_t uIndex, uint32_t uValue)
     455static int ioapicSetRedirTableEntry(PIOAPIC pThis, uint32_t uIndex, uint32_t uValue)
    482456{
    483457    uint8_t const idxRte = (uIndex - IOAPIC_INDIRECT_INDEX_REDIR_TBL_START) >> 1;
     
    485459                                                            RT_ELEMENTS(pThis->au64RedirTable)));
    486460
    487     /*
    488      * Write the low or high 32-bit value into the specified 64-bit RTE register.
    489      * Update only the valid, writable bits.
    490      */
    491     uint64_t const u64Rte = pThis->au64RedirTable[idxRte].u;
    492     if (!(uIndex & 1))
    493     {
    494         uint32_t const u32RteNewLo = uValue & RT_LO_U32(IOAPIC_RTE_VALID_WRITE_MASK);
    495         ASMAtomicWriteU32(&pThis->au64RedirTable[idxRte].au32[0], u32RteNewLo);
     461    int rc = PDMCritSectEnter(&pThis->CritSect, VINF_IOM_R3_MMIO_WRITE);
     462    if (rc == VINF_SUCCESS)
     463    {
     464        /*
     465         * Write the low or high 32-bit value into the specified 64-bit RTE register.
     466         * Update only the valid, writable bits.
     467         */
     468        uint64_t const u64Rte = pThis->au64RedirTable[idxRte];
     469        if (!(uIndex & 1))
     470        {
     471            uint32_t const u32RteNewLo    = uValue & RT_LO_U32(IOAPIC_RTE_VALID_WRITE_MASK);
     472            uint64_t const u64RteHi       = u64Rte & UINT64_C(0xffffffff00000000);
     473            pThis->au64RedirTable[idxRte] = u64RteHi | u32RteNewLo;
     474        }
     475        else
     476        {
     477            uint32_t const u32RteLo       = RT_LO_U32(u64Rte);
     478            uint64_t const u64RteNewHi    = (uint64_t)(uValue & RT_HI_U32(IOAPIC_RTE_VALID_WRITE_MASK)) << 32;
     479            pThis->au64RedirTable[idxRte] = u64RteNewHi | u32RteLo;
     480        }
     481
     482        /*
     483         * Signal the next pending interrupt for this RTE.
     484         */
     485        uint32_t const uPinMask = UINT32_C(1) << idxRte;
     486        if (pThis->uIrr & uPinMask)
     487            ioapicSignalIntrForRte(pThis, idxRte);
     488
     489        PDMCritSectLeave(&pThis->CritSect);
     490        LogFlow(("IOAPIC: ioapicSetRedirTableEntry: uIndex=%#RX32 idxRte=%u uValue=%#RX32\n", uIndex, idxRte, uValue));
    496491    }
    497492    else
    498     {
    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);
    509 
    510     LogFlow(("IOAPIC: ioapicSetRedirTableEntry: uIndex=%#RX32 idxRte=%u uValue=%#RX32\n", uIndex, idxRte, uValue));
     493        STAM_COUNTER_INC(&pThis->StatSetRteContention);
     494
     495    return rc;
    511496}
    512497
     
    521506{
    522507    uint8_t const uIndex = pThis->u8Index;
    523     uint32_t uValue;
    524508    if (   uIndex >= IOAPIC_INDIRECT_INDEX_REDIR_TBL_START
    525509        && uIndex <= IOAPIC_INDIRECT_INDEX_REDIR_TBL_END)
    526         uValue = ioapicGetRedirTableEntry(pThis, uIndex);
    527     else
    528     {
    529         switch (uIndex)
    530         {
    531             case IOAPIC_INDIRECT_INDEX_ID:
    532                 uValue = ioapicGetId(pThis);
    533                 break;
    534 
    535             case IOAPIC_INDIRECT_INDEX_VERSION:
    536                 uValue = ioapicGetVersion();
    537                 break;
     510        return ioapicGetRedirTableEntry(pThis, uIndex);
     511
     512    uint32_t uValue;
     513    switch (uIndex)
     514    {
     515        case IOAPIC_INDIRECT_INDEX_ID:
     516            uValue = ioapicGetId(pThis);
     517            break;
     518
     519        case IOAPIC_INDIRECT_INDEX_VERSION:
     520            uValue = ioapicGetVersion();
     521            break;
    538522
    539523#if IOAPIC_HARDWARE_VERSION == IOAPIC_HARDWARE_VERSION_82093AA
    540             case IOAPIC_INDIRECT_INDEX_ARB:
    541                 uValue = ioapicGetArb();
    542                 break;
     524        case IOAPIC_INDIRECT_INDEX_ARB:
     525            uValue = ioapicGetArb();
     526            break;
    543527#endif
    544528
    545             default:
    546                 Log2(("IOAPIC: Attempt to read register at invalid index %#x\n", uIndex));
    547                 uValue = UINT32_C(0xffffffff);
    548                 break;
    549         }
    550     }
    551 
     529        default:
     530            uValue = UINT32_C(0xffffffff);
     531            Log2(("IOAPIC: Attempt to read register at invalid index %#x\n", uIndex));
     532            break;
     533    }
    552534    return uValue;
    553535}
     
    560542 * @param uValue    The value to set.
    561543 */
    562 static void ioapicSetData(PIOAPIC pThis, uint32_t uValue)
     544static int ioapicSetData(PIOAPIC pThis, uint32_t uValue)
    563545{
    564546    uint8_t const uIndex = pThis->u8Index;
    565547    LogFlow(("IOAPIC: ioapicSetData: uIndex=%#x uValue=%#RX32\n", uIndex, uValue));
    566548
     549    if (   uIndex >= IOAPIC_INDIRECT_INDEX_REDIR_TBL_START
     550        && uIndex <= IOAPIC_INDIRECT_INDEX_REDIR_TBL_END)
     551        return ioapicSetRedirTableEntry(pThis, uIndex, uValue);
     552
    567553    if (uIndex == IOAPIC_INDIRECT_INDEX_ID)
    568554        ioapicSetId(pThis, uValue);
    569     else if (   uIndex >= IOAPIC_INDIRECT_INDEX_REDIR_TBL_START
    570              && uIndex <= IOAPIC_INDIRECT_INDEX_REDIR_TBL_END)
    571         ioapicSetRedirTableEntry(pThis, uIndex, uValue);
    572555    else
    573556        Log2(("IOAPIC: ioapicSetData: Invalid index %#RX32, ignoring write request with uValue=%#RX32\n", uIndex, uValue));
     557
     558    return VINF_SUCCESS;
    574559}
    575560
     
    578563 * @interface_method_impl{PDMIOAPICREG,pfnSetEoiR3}
    579564 */
    580 PDMBOTHCBDECL(void) ioapicSetEoi(PPDMDEVINS pDevIns, uint8_t u8Vector)
     565PDMBOTHCBDECL(int) ioapicSetEoi(PPDMDEVINS pDevIns, uint8_t u8Vector)
    581566{
    582567    PIOAPIC pThis = PDMINS_2_DATA(pDevIns, PIOAPIC);
     
    584569    LogFlow(("IOAPIC: ioapicSetEoi: u8Vector=%#x (%u)\n", u8Vector, u8Vector));
    585570
    586     for (uint8_t idxRte = 0; idxRte < RT_ELEMENTS(pThis->au64RedirTable); idxRte++)
    587     {
    588         uint64_t const u64Rte = pThis->au64RedirTable[idxRte].u;
    589         if (IOAPIC_RTE_GET_VECTOR(u64Rte) == u8Vector)
     571    int rc = PDMCritSectEnter(&pThis->CritSect, VINF_IOM_R3_MMIO_WRITE);
     572    if (rc == VINF_SUCCESS)
     573    {
     574        for (uint8_t idxRte = 0; idxRte < RT_ELEMENTS(pThis->au64RedirTable); idxRte++)
    590575        {
    591             ASMAtomicAndU32(&pThis->au64RedirTable[idxRte].au32[0], ~IOAPIC_RTE_REMOTE_IRR);
    592             Log2(("IOAPIC: ioapicSetEoi: Cleared remote IRR for RTE %u\n", 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);
     576            uint64_t const u64Rte = pThis->au64RedirTable[idxRte];
     577            if (IOAPIC_RTE_GET_VECTOR(u64Rte) == u8Vector)
     578            {
     579                pThis->au64RedirTable[idxRte] &= ~IOAPIC_RTE_REMOTE_IRR;
     580                Log2(("IOAPIC: ioapicSetEoi: Cleared remote IRR, idxRte=%u vector=%#x (%u)\n", idxRte, u8Vector, u8Vector));
     581
     582                /*
     583                 * Signal the next pending interrupt for this RTE.
     584                 */
     585                uint32_t const uPinMask = UINT32_C(1) << idxRte;
     586                if (pThis->uIrr & uPinMask)
     587                    ioapicSignalIntrForRte(pThis, idxRte);
     588            }
    600589        }
    601     }
     590
     591        PDMCritSectLeave(&pThis->CritSect);
     592    }
     593    else
     594        STAM_COUNTER_INC(&pThis->StatEoiContention);
     595
     596    return rc;
    602597}
    603598
     
    615610    if (RT_LIKELY(iIrq >= 0 && iIrq < (int)RT_ELEMENTS(pThis->au64RedirTable)))
    616611    {
     612        int rc = PDMCritSectEnter(&pThis->CritSect, VINF_SUCCESS);
     613        AssertRC(rc);
     614
    617615        uint8_t  const idxRte        = iIrq;
    618616        uint32_t const uPinMask      = UINT32_C(1) << idxRte;
    619         uint32_t const u32RteLo      = pThis->au64RedirTable[idxRte].au32[0];
     617        uint32_t const u32RteLo      = RT_LO_U32(pThis->au64RedirTable[idxRte]);
    620618        uint8_t  const u8TriggerMode = IOAPIC_RTE_GET_TRIGGER_MODE(u32RteLo);
    621619
     
    629627        if (!fActive)
    630628        {
    631             ASMAtomicAndU32(&pThis->uIrr, ~uPinMask);
     629            pThis->uIrr &= ~uPinMask;
     630            PDMCritSectLeave(&pThis->CritSect);
    632631            return;
    633632        }
     
    635634        /*
    636635         * 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.
     636         * set and unset the IRR.
    639637         */
    640         bool const fTouchIrr = !((iLevel & PDM_IRQ_LEVEL_FLIP_FLOP) == PDM_IRQ_LEVEL_FLIP_FLOP);
    641 
     638        bool const     fFlipFlop = ((iLevel & PDM_IRQ_LEVEL_FLIP_FLOP) == PDM_IRQ_LEVEL_FLIP_FLOP);
     639        uint32_t const uPrevIrr  = pThis->uIrr & uPinMask;
    642640        if (u8TriggerMode == IOAPIC_RTE_TRIGGER_MODE_EDGE)
    643641        {
     
    646644             * See ICH9 spec. 13.5.7 "REDIR_TBL: Redirection Table (LPC I/F-D31:F0)"
    647645             */
    648             uint32_t const uPrevIrr = pThis->uIrr & uPinMask;
    649646            if (!uPrevIrr)
    650647            {
    651                 if (fTouchIrr)
    652                     ASMAtomicOrU32(&pThis->uIrr, uPinMask);
     648                if (!fFlipFlop)
     649                    pThis->uIrr |= uPinMask;
    653650
    654651                if (!pThis->au32TagSrc[idxRte])
     
    674671             * should not typically call us with no change to the level.
    675672             */
    676             uint32_t const uPrevIrr = pThis->uIrr & uPinMask;
    677673            if (!uPrevIrr)
    678674            { /* likely */ }
     
    683679            }
    684680
    685             if (fTouchIrr)
    686                 ASMAtomicOrU32(&pThis->uIrr, uPinMask);
     681            if (!fFlipFlop)
     682                pThis->uIrr |= uPinMask;
    687683
    688684            if (!pThis->au32TagSrc[idxRte])
     
    693689            ioapicSignalIntrForRte(pThis, idxRte);
    694690        }
     691
     692        PDMCritSectLeave(&pThis->CritSect);
    695693    }
    696694}
     
    786784
    787785    LogFlow(("IOAPIC: ioapicMmioWrite: pThis=%p GCPhysAddr=%#RGp cb=%u uValue=%#RX32\n", pThis, GCPhysAddr, cb, uValue));
    788 
     786    int rc = VINF_SUCCESS;
    789787    switch (offReg)
    790788    {
     
    794792
    795793        case IOAPIC_DIRECT_OFF_DATA:
    796             ioapicSetData(pThis, uValue);
     794            rc = ioapicSetData(pThis, uValue);
    797795            break;
    798796
    799797#if IOAPIC_HARDWARE_VERSION == IOAPIC_HARDWARE_VERSION_ICH9
    800798        case IOAPIC_DIRECT_OFF_EOI:
    801             ioapicSetEoi(pDevIns, uValue);
     799            rc = ioapicSetEoi(pDevIns, uValue);
    802800            break;
    803801#endif
     
    808806    }
    809807
    810     return VINF_SUCCESS;
     808    return rc;
    811809}
    812810
     
    837835static DECLCALLBACK(int) ioapicDbgReg_SetData(void *pvUser, PCDBGFREGDESC pDesc, PCDBGFREGVAL pValue, PCDBGFREGVAL pfMask)
    838836{
    839      ioapicSetData(PDMINS_2_DATA((PPDMDEVINS)pvUser, PIOAPIC), pValue->u32);
    840      return VINF_SUCCESS;
     837     return ioapicSetData(PDMINS_2_DATA((PPDMDEVINS)pvUser, PIOAPIC), pValue->u32);
    841838}
    842839
     
    872869{
    873870    PIOAPIC pThis = PDMINS_2_DATA((PPDMDEVINS)pvUser, PIOAPIC);
    874     ioapicSetRedirTableEntry(pThis, pDesc->offRegister, pValue->u64);
    875     return VINF_SUCCESS;
     871    return ioapicSetRedirTableEntry(pThis, pDesc->offRegister, pValue->u64);
    876872}
    877873
     
    976972        };
    977973
    978         const uint64_t u64Rte = pThis->au64RedirTable[idxRte].u;
     974        const uint64_t u64Rte = pThis->au64RedirTable[idxRte];
    979975        const char    *pszDestMode       = IOAPIC_RTE_GET_DEST_MODE(u64Rte) == 0 ? "phys" : "log ";
    980976        const uint8_t  uDest             = IOAPIC_RTE_GET_DEST(u64Rte);
     
    10181014    SSMR3PutU8(pSSM,  pThis->u8Index);
    10191015    for (uint8_t idxRte = 0; idxRte < RT_ELEMENTS(pThis->au64RedirTable); idxRte++)
    1020         SSMR3PutU64(pSSM, pThis->au64RedirTable[idxRte].u);
     1016        SSMR3PutU64(pSSM, pThis->au64RedirTable[idxRte]);
    10211017
    10221018    return VINF_SUCCESS;
     
    10491045    SSMR3GetU8(pSSM, (uint8_t *)&pThis->u8Index);
    10501046    for (uint8_t idxRte = 0; idxRte < RT_ELEMENTS(pThis->au64RedirTable); idxRte++)
    1051         SSMR3GetU64(pSSM, (uint64_t *)&pThis->au64RedirTable[idxRte].u);
     1047        SSMR3GetU64(pSSM, &pThis->au64RedirTable[idxRte]);
    10521048
    10531049    return VINF_SUCCESS;
     
    10631059    LogFlow(("IOAPIC: ioapicR3Reset: pThis=%p\n", pThis));
    10641060
    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);
     1061    /* There might be devices threads calling ioapicSetIrq() in parallel, hence the lock. */
     1062    PDMCritSectEnter(&pThis->CritSect, VERR_IGNORED);
     1063
     1064    pThis->uIrr    = 0;
     1065    pThis->u8Index = 0;
     1066    pThis->u8Id    = 0;
    10691067
    10701068    for (uint8_t idxRte = 0; idxRte < RT_ELEMENTS(pThis->au64RedirTable); idxRte++)
    10711069    {
    1072         ASMAtomicWriteU64(&pThis->au64RedirTable[idxRte].u, IOAPIC_RTE_MASK);
     1070        pThis->au64RedirTable[idxRte] = IOAPIC_RTE_MASK;
    10731071        pThis->au32TagSrc[idxRte] = 0;
    10741072    }
     1073
     1074    PDMCritSectLeave(&pThis->CritSect);
    10751075}
    10761076
     
    10861086    pThis->pDevInsRC    = PDMDEVINS_2_RCPTR(pDevIns);
    10871087    pThis->pIoApicHlpRC = pThis->pIoApicHlpR3->pfnGetRCHelpers(pDevIns);
     1088}
     1089
     1090
     1091/**
     1092 * @interface_method_impl{PDMDEVREG,pfnDestruct}
     1093 */
     1094static DECLCALLBACK(int) ioapicR3Destruct(PPDMDEVINS pDevIns)
     1095{
     1096    PIOAPIC pThis = PDMINS_2_DATA(pDevIns, PIOAPIC);
     1097    LogFlow(("IOAPIC: ioapicR3Destruct: pThis=%p\n", pThis));
     1098    PDMDEV_CHECK_VERSIONS_RETURN_QUIET(pDevIns);
     1099
     1100    /*
     1101     * Destroy the RTE critical section.
     1102     */
     1103    if (PDMCritSectIsInitialized(&pThis->CritSect))
     1104        PDMR3CritSectDelete(&pThis->CritSect);
     1105
     1106    return VINF_SUCCESS;
    10881107}
    10891108
     
    11271146
    11281147    /*
    1129      * We don't do any locking for the IOAPIC device.
     1148     * We will use our own critical section for the IOAPIC device.
    11301149     */
    11311150    rc = PDMDevHlpSetDeviceCritSect(pDevIns, PDMDevHlpCritSectGetNop(pDevIns));
    11321151    AssertRCReturn(rc, rc);
     1152
     1153    /*
     1154     * Setup the critical section to protect concurrent writes to the RTEs.
     1155     */
     1156    rc = PDMDevHlpCritSectInit(pDevIns, &pThis->CritSect, RT_SRC_POS, "IOAPIC");
     1157    if (RT_FAILURE(rc))
     1158        return PDMDevHlpVMSetError(pDevIns, rc, RT_SRC_POS, N_("IOAPIC: Failed to create critical section. rc=%Rrc"), rc);
    11331159
    11341160    /*
     
    12301256    PDMDevHlpSTAMRegister(pDevIns, &pThis->StatRedundantLevelIntr,  STAMTYPE_COUNTER, "/Devices/IOAPIC/RedundantLevelIntr",  STAMUNIT_OCCURENCES, "Number of redundant level-triggered interrupts (no IRR change).");
    12311257    PDMDevHlpSTAMRegister(pDevIns, &pThis->StatSuppressedLevelIntr, STAMTYPE_COUNTER, "/Devices/IOAPIC/SuppressedLevelIntr", STAMUNIT_OCCURENCES, "Number of suppressed level-triggered interrupts by remote IRR.");
     1258
     1259    PDMDevHlpSTAMRegister(pDevIns, &pThis->StatEoiContention,    STAMTYPE_COUNTER, "/Devices/IOAPIC/Contention/SetEoi", STAMUNIT_OCCURENCES, "Number of times the critsect is busy during EOI writes causing trips to R3.");
     1260    PDMDevHlpSTAMRegister(pDevIns, &pThis->StatSetRteContention, STAMTYPE_COUNTER, "/Devices/IOAPIC/Contention/SetRte", STAMUNIT_OCCURENCES, "Number of times the critsect is busy during RTE writes causing trips to R3.");
    12321261#endif
    12331262
     
    12691298    ioapicR3Construct,
    12701299    /* pfnDestruct */
    1271     NULL,
     1300    ioapicR3Destruct,
    12721301    /* pfnRelocate */
    12731302    ioapicR3Relocate,
  • trunk/src/VBox/VMM/VMMAll/APICAll.cpp

    r61608 r61735  
    471471 * @param   uVector         The interrupt vector corresponding to the EOI.
    472472 */
    473 DECLINLINE(void) apicBusBroadcastEoi(PVMCPU pVCpu, uint8_t uVector)
     473DECLINLINE(int) apicBusBroadcastEoi(PVMCPU pVCpu, uint8_t uVector)
    474474{
    475475    PVM      pVM      = pVCpu->CTX_SUFF(pVM);
    476476    PAPICDEV pApicDev = VM_TO_APICDEV(pVM);
    477     pApicDev->CTX_SUFF(pApicHlp)->pfnBusBroadcastEoi(pApicDev->CTX_SUFF(pDevIns), uVector);
     477    return pApicDev->CTX_SUFF(pApicHlp)->pfnBusBroadcastEoi(pApicDev->CTX_SUFF(pDevIns), uVector);
    478478}
    479479
     
    12021202    if (isrv >= 0)
    12031203    {
     1204        /*
     1205         * Broadcast the EOI to the I/O APIC(s).
     1206         *
     1207         * We'll handle the EOI broadcast first as there is tiny chance we get rescheduled to
     1208         * ring-3 due to contention on the I/O APIC lock. This way we don't mess with the rest
     1209         * of the APIC state and simply restart the EOI write operation from ring-3.
     1210         */
    12041211        Assert(isrv <= (int)UINT8_MAX);
    1205         uint8_t const uVector = isrv;
    1206         apicClearVectorInReg(&pXApicPage->isr, uVector);
    1207         apicUpdatePpr(pVCpu);
    1208         Log2(("APIC%u: apicSetEoi: Cleared interrupt from ISR. uVector=%#x\n", pVCpu->idCpu, uVector));
    1209 
    1210         bool fLevelTriggered = apicTestVectorInReg(&pXApicPage->tmr, uVector);
     1212        uint8_t const uVector      = isrv;
     1213        bool const fLevelTriggered = apicTestVectorInReg(&pXApicPage->tmr, uVector);
    12111214        if (fLevelTriggered)
    12121215        {
     1216            int rc = apicBusBroadcastEoi(pVCpu, uVector);
     1217            if (rc == VINF_SUCCESS)
     1218            { /* likely */ }
     1219            else
     1220                return XAPIC_IN_X2APIC_MODE(pVCpu) ? VINF_CPUM_R3_MSR_WRITE : VINF_IOM_R3_MMIO_WRITE;
     1221
     1222            /*
     1223             * Clear the vector from the TMR.
     1224             *
     1225             * The broadcast to I/O APIC can re-trigger new interrupts to arrive via the bus. However,
     1226             * APICUpdatePendingInterrupts() which updates TMR can only be done from EMT which we
     1227             * currently are on, so no possibility of concurrent updates.
     1228             */
    12131229            apicClearVectorInReg(&pXApicPage->tmr, uVector);
    1214             apicBusBroadcastEoi(pVCpu, uVector);
    12151230
    12161231            /*
     
    12311246        }
    12321247
     1248        /*
     1249         * Mark interrupt as serviced, update the PPR and signal pending interrupts.
     1250         */
     1251        Log2(("APIC%u: apicSetEoi: Clearing interrupt from ISR. uVector=%#x\n", pVCpu->idCpu, uVector));
     1252        apicClearVectorInReg(&pXApicPage->isr, uVector);
     1253        apicUpdatePpr(pVCpu);
    12331254        apicSignalNextPendingIntr(pVCpu);
    12341255    }
  • trunk/src/VBox/VMM/VMMR0/PDMR0Device.cpp

    r61685 r61735  
    606606
    607607/** @interface_method_impl{PDMAPICHLPR0,pfnBusBroadcastEoi} */
    608 static DECLCALLBACK(void) pdmR0ApicHlp_BusBroadcastEoi(PPDMDEVINS pDevIns, uint8_t u8Vector)
     608static DECLCALLBACK(int) pdmR0ApicHlp_BusBroadcastEoi(PPDMDEVINS pDevIns, uint8_t u8Vector)
    609609{
    610610    /* pfnSetEoi will be NULL in the old IOAPIC code as it's not implemented. */
     
    618618    {
    619619        Assert(pVM->pdm.s.IoApic.CTX_SUFF(pfnSetEoi));
    620         pVM->pdm.s.IoApic.CTX_SUFF(pfnSetEoi)(pVM->pdm.s.IoApic.CTX_SUFF(pDevIns), u8Vector);
     620        return pVM->pdm.s.IoApic.CTX_SUFF(pfnSetEoi)(pVM->pdm.s.IoApic.CTX_SUFF(pDevIns), u8Vector);
    621621    }
    622622#endif
     623    return VINF_SUCCESS;
    623624}
    624625
  • trunk/src/VBox/VMM/VMMR3/PDMDevMiscHlp.cpp

    r61685 r61735  
    269269
    270270/** @interface_method_impl{PDMAPICHLPR3,pfnBusBroadcastEoi} */
    271 static DECLCALLBACK(void) pdmR3ApicHlp_BusBroadcastEoi(PPDMDEVINS pDevIns, uint8_t u8Vector)
     271static DECLCALLBACK(int) pdmR3ApicHlp_BusBroadcastEoi(PPDMDEVINS pDevIns, uint8_t u8Vector)
    272272{
    273273    /* pfnSetEoi will be NULL in the old IOAPIC code as it's not implemented. */
     
    281281    {
    282282        Assert(pVM->pdm.s.IoApic.CTX_SUFF(pfnSetEoi));
    283         pVM->pdm.s.IoApic.CTX_SUFF(pfnSetEoi)(pVM->pdm.s.IoApic.CTX_SUFF(pDevIns), u8Vector);
    284     }
    285 #endif
     283        return pVM->pdm.s.IoApic.CTX_SUFF(pfnSetEoi)(pVM->pdm.s.IoApic.CTX_SUFF(pDevIns), u8Vector);
     284    }
     285#endif
     286    return VINF_SUCCESS;
    286287}
    287288
  • trunk/src/VBox/VMM/VMMRC/PDMRCDevice.cpp

    r61685 r61735  
    561561
    562562/** @interface_method_impl{PDMAPICHLPRC,pfnBusBroadcastEoi} */
    563 static DECLCALLBACK(void) pdmRCApicHlp_BusBroadcastEoi(PPDMDEVINS pDevIns, uint8_t u8Vector)
     563static DECLCALLBACK(int) pdmRCApicHlp_BusBroadcastEoi(PPDMDEVINS pDevIns, uint8_t u8Vector)
    564564{
    565565    /* pfnSetEoi will be NULL in the old IOAPIC code as it's not implemented. */
     
    573573    {
    574574        Assert(pVM->pdm.s.IoApic.CTX_SUFF(pfnSetEoi));
    575         pVM->pdm.s.IoApic.CTX_SUFF(pfnSetEoi)(pVM->pdm.s.IoApic.CTX_SUFF(pDevIns), u8Vector);
     575        return pVM->pdm.s.IoApic.CTX_SUFF(pfnSetEoi)(pVM->pdm.s.IoApic.CTX_SUFF(pDevIns), u8Vector);
    576576    }
    577577#endif
     578    return VINF_SUCCESS;
    578579}
    579580
  • trunk/src/VBox/VMM/include/PDMInternal.h

    r61339 r61735  
    659659    DECLR3CALLBACKMEMBER(void,      pfnSendMsiR3,(PPDMDEVINS pDevIns, RTGCPHYS GCAddr, uint32_t uValue, uint32_t uTagSrc));
    660660    /** @copydoc PDMIOAPICREG::pfnSetEoiR3 */
    661     DECLR3CALLBACKMEMBER(void,      pfnSetEoiR3,(PPDMDEVINS pDevIns, uint8_t u8Vector));
     661    DECLR3CALLBACKMEMBER(int,       pfnSetEoiR3,(PPDMDEVINS pDevIns, uint8_t u8Vector));
    662662
    663663    /** Pointer to the PIC device instance - R0. */
     
    668668    DECLR0CALLBACKMEMBER(void,      pfnSendMsiR0,(PPDMDEVINS pDevIns, RTGCPHYS GCAddr, uint32_t uValue, uint32_t uTagSrc));
    669669    /** @copydoc PDMIOAPICREG::pfnSetEoiR3 */
    670     DECLR0CALLBACKMEMBER(void,      pfnSetEoiR0,(PPDMDEVINS pDevIns, uint8_t u8Vector));
     670    DECLR0CALLBACKMEMBER(int,       pfnSetEoiR0,(PPDMDEVINS pDevIns, uint8_t u8Vector));
    671671
    672672    /** Pointer to the APIC device instance - RC Ptr. */
     
    677677    DECLRCCALLBACKMEMBER(void,      pfnSendMsiRC,(PPDMDEVINS pDevIns, RTGCPHYS GCAddr, uint32_t uValue, uint32_t uTagSrc));
    678678     /** @copydoc PDMIOAPICREG::pfnSendMsiR3 */
    679     DECLRCCALLBACKMEMBER(void,      pfnSetEoiRC,(PPDMDEVINS pDevIns, uint8_t u8Vector));
     679    DECLRCCALLBACKMEMBER(int,       pfnSetEoiRC,(PPDMDEVINS pDevIns, uint8_t u8Vector));
    680680} PDMIOAPIC;
    681681
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