VirtualBox

Changeset 29827 in vbox for trunk/src


Ignore:
Timestamp:
May 26, 2010 6:27:38 PM (15 years ago)
Author:
vboxsync
Message:

LsiLogic: Fix a possible race condition in the interrupt handling code which can lead to I/O timeouts

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Devices/Storage/DevLsiLogicSCSI.cpp

    r29744 r29827  
    404404    uIntSts = (ASMAtomicReadU32(&pThis->uInterruptStatus) & ~LSILOGIC_REG_HOST_INTR_STATUS_DOORBELL_STS);
    405405    /* Check maskable interrupts. */
    406     uIntSts &= ~(pThis->uInterruptMask & ~LSILOGIC_REG_HOST_INTR_MASK_IRQ_ROUTING);
     406    uIntSts &= ~(ASMAtomicReadU32(&pThis->uInterruptMask) & ~LSILOGIC_REG_HOST_INTR_MASK_IRQ_ROUTING);
    407407
    408408    if (uIntSts)
     
    584584    pLsiLogic->uReplyPostQueueNextEntryFreeWrite %= pLsiLogic->cReplyQueueEntries;
    585585
    586     PDMCritSectLeave(&pLsiLogic->ReplyPostQueueCritSect);
    587 
    588586    /* Set interrupt. */
    589587    lsilogicSetInterrupt(pLsiLogic, LSILOGIC_REG_HOST_INTR_STATUS_REPLY_INTR);
     588
     589    PDMCritSectLeave(&pLsiLogic->ReplyPostQueueCritSect);
    590590}
    591591
     
    702702        pLsiLogic->uReplyPostQueueNextEntryFreeWrite %= pLsiLogic->cReplyQueueEntries;
    703703
    704         PDMCritSectLeave(&pLsiLogic->ReplyPostQueueCritSect);
    705 
    706704        if (fForceReplyFifo)
    707705        {
     
    712710        /* Set interrupt. */
    713711        lsilogicSetInterrupt(pLsiLogic, LSILOGIC_REG_HOST_INTR_STATUS_REPLY_INTR);
     712
     713        PDMCritSectLeave(&pLsiLogic->ReplyPostQueueCritSect);
    714714#else
    715715        AssertMsgFailed(("This is not allowed to happen.\n"));
     
    10601060             * the latter one is read only.
    10611061             */
    1062             pThis->uInterruptStatus = pThis->uInterruptStatus & ~LSILOGIC_REG_HOST_INTR_STATUS_SYSTEM_DOORBELL;
     1062            ASMAtomicAndU32(&pThis->uInterruptStatus, ~LSILOGIC_REG_HOST_INTR_STATUS_SYSTEM_DOORBELL);
    10631063
    10641064            /*
     
    10851085        case LSILOGIC_REG_HOST_INTR_MASK:
    10861086        {
    1087             pThis->uInterruptMask = (u32 & LSILOGIC_REG_HOST_INTR_MASK_W_MASK);
     1087            ASMAtomicWriteU32(&pThis->uInterruptMask, u32 & LSILOGIC_REG_HOST_INTR_MASK_W_MASK);
    10881088            lsilogicUpdateInterrupt(pThis);
    10891089            break;
     
    11471147static int lsilogicRegisterRead(PLSILOGICSCSI pThis, uint32_t uOffset, void *pv, unsigned cb)
    11481148{
     1149    int rc = VINF_SUCCESS;
    11491150    uint32_t u32 = 0;
    11501151
     
    11611162                LogFlowFunc((": cb is not 4 (%u)\n", cb));
    11621163
    1163             if (pThis->uReplyPostQueueNextEntryFreeWrite != pThis->uReplyPostQueueNextAddressRead)
     1164            rc = PDMCritSectEnter(&pThis->ReplyPostQueueCritSect, VINF_IOM_HC_MMIO_READ);
     1165            if (rc != VINF_SUCCESS)
     1166                break;
     1167
     1168            uint32_t idxReplyPostQueueWrite = ASMAtomicUoReadU32(&pThis->uReplyPostQueueNextEntryFreeWrite);
     1169            uint32_t idxReplyPostQueueRead  = ASMAtomicUoReadU32(&pThis->uReplyPostQueueNextAddressRead);
     1170
     1171            if (idxReplyPostQueueWrite != idxReplyPostQueueRead)
    11641172            {
    1165                 u32 = pThis->CTX_SUFF(pReplyPostQueueBase)[pThis->uReplyPostQueueNextAddressRead];
    1166                 pThis->uReplyPostQueueNextAddressRead++;
    1167                 pThis->uReplyPostQueueNextAddressRead %= pThis->cReplyQueueEntries;
     1173                u32 = pThis->CTX_SUFF(pReplyPostQueueBase)[idxReplyPostQueueRead];
     1174                idxReplyPostQueueRead++;
     1175                idxReplyPostQueueRead %= pThis->cReplyQueueEntries;
     1176                ASMAtomicWriteU32(&pThis->uReplyPostQueueNextAddressRead, idxReplyPostQueueRead);
    11681177            }
    11691178            else
     
    11731182                lsilogicClearInterrupt(pThis, LSILOGIC_REG_HOST_INTR_STATUS_REPLY_INTR);
    11741183            }
     1184            PDMCritSectLeave(&pThis->ReplyPostQueueCritSect);
     1185
    11751186            Log(("%s: Returning address %#x\n", __FUNCTION__, u32));
    11761187            break;
     
    12001211        case LSILOGIC_REG_HOST_INTR_STATUS:
    12011212        {
    1202             u32 = pThis->uInterruptStatus;
     1213            u32 = ASMAtomicReadU32(&pThis->uInterruptStatus);
    12031214            break;
    12041215        }
    12051216        case LSILOGIC_REG_HOST_INTR_MASK:
    12061217        {
    1207             u32 = pThis->uInterruptMask;
     1218            u32 = ASMAtomicReadU32(&pThis->uInterruptMask);
    12081219            break;
    12091220        }
     
    12551266    LogFlowFunc(("pThis=%#p uOffset=%#x pv=%#p{%.*Rhxs} cb=%u\n", pThis, uOffset, pv, cb, pv, cb));
    12561267
    1257     return VINF_SUCCESS;
     1268    return rc;
    12581269}
    12591270
     
    12811292    Assert(cb <= 4);
    12821293
    1283     return lsilogicRegisterRead(pThis, uOffset, pu32, cb);
     1294    int rc = lsilogicRegisterRead(pThis, uOffset, pu32, cb);
     1295    if (rc == VINF_IOM_HC_MMIO_READ)
     1296        rc = VINF_IOM_HC_IOPORT_READ;
     1297
     1298    return rc;
    12841299}
    12851300
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