VirtualBox

Ignore:
Timestamp:
Jul 15, 2009 3:26:05 PM (15 years ago)
Author:
vboxsync
Message:

AHCI: fix race condition resulting in hanging I/O

File:
1 edited

Legend:

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

    r21363 r21615  
    294294    uint32_t                        regFBU;
    295295    /** Interrupt Status. */
    296     uint32_t                        regIS;
     296    volatile uint32_t               regIS;
    297297    /** Interrupt Enable. */
    298298    uint32_t                        regIE;
     
    10291029{
    10301030    ahciLog(("%s: write u32Value=%#010x\n", __FUNCTION__, u32Value));
    1031     pAhciPort->regSERR &= ~u32Value;
    1032     if (u32Value & AHCI_PORT_SERR_X)
    1033     {
     1031
     1032    if (   (u32Value & AHCI_PORT_SERR_X)
     1033        && (pAhciPort->regSERR & AHCI_PORT_SERR_X))
     1034    {
     1035        ASMAtomicAndU32(&pAhciPort->regIS, ~AHCI_PORT_IS_PCS);
    10341036        pAhciPort->regTFD |= ATA_STAT_ERR;
    10351037        pAhciPort->regTFD &= ~(ATA_STAT_DRQ | ATA_STAT_BUSY);
    10361038    }
     1039
     1040    pAhciPort->regSERR &= ~u32Value;
     1041
    10371042    return VINF_SUCCESS;
    10381043}
     
    10981103
    10991104            /* We received a COMINIT from the device. Tell the guest. */
    1100             pAhciPort->regIS   |= AHCI_PORT_IS_PCS;
     1105            ASMAtomicOrU32(&pAhciPort->regIS, AHCI_PORT_IS_PCS);
    11011106            pAhciPort->regSERR |= AHCI_PORT_SERR_X;
    11021107            pAhciPort->regTFD  |= ATA_STAT_BUSY;
     
    11051110            {
    11061111                ahciPostFirstD2HFisIntoMemory(pAhciPort);
    1107                 pAhciPort->regIS |= AHCI_PORT_IS_DHRS;
     1112                ASMAtomicOrU32(&pAhciPort->regIS, AHCI_PORT_IS_DHRS);
    11081113
    11091114                if (pAhciPort->regIE & AHCI_PORT_IE_DHRE)
     
    12471252#else
    12481253                ahciPostFirstD2HFisIntoMemory(pAhciPort);
    1249                 pAhciPort->regIS |= AHCI_PORT_IS_DHRS;
     1254                ASMAtomicOrU32(&pAhciPort->regIS, AHCI_PORT_IS_DHRS);
    12501255
    12511256                if (pAhciPort->regIE & AHCI_PORT_IE_DHRE)
     
    13641369{
    13651370    ahciLog(("%s: write u32Value=%#010x\n", __FUNCTION__, u32Value));
    1366     pAhciPort->regIS &= ~u32Value;
    1367 
    1368     if (u32Value & AHCI_PORT_IS_PCS)
    1369         pAhciPort->regSERR &= ~AHCI_PORT_SERR_X;
     1371    ASMAtomicAndU32(&pAhciPort->regIS, ~(u32Value & AHCI_PORT_IS_READONLY));
     1372
    13701373    return VINF_SUCCESS;
    13711374}
     
    15021505         * notification bits.
    15031506         */
     1507        bool fClear = true;
    15041508
    15051509        ahci->regHbaIs &= ~(u32Value);
    15061510
    1507         if ((!ahci->u32PortsInterrupted) && (!ahci->regHbaIs))
     1511        fClear = (!ahci->u32PortsInterrupted) && (!ahci->regHbaIs);
     1512        if (fClear)
     1513        {
     1514            unsigned i = 0;
     1515
     1516            /* Check if the cleared ports have a interrupt status bit set. */
     1517            while (u32Value > 0)
     1518            {
     1519                if (u32Value & 0x01)
     1520                {
     1521                    PAHCIPort pAhciPort = &ahci->ahciPort[i];
     1522
     1523                    if (pAhciPort->regIE & pAhciPort->regIS)
     1524                    {
     1525                        Log(("%s: Interrupt status of port %u set -> Set interrupt again\n", __FUNCTION__, i));
     1526                        ASMAtomicOrU32(&ahci->u32PortsInterrupted, 1 << i);
     1527                        fClear = false;
     1528                        break;
     1529                    }
     1530                }
     1531                u32Value = u32Value >> 1;
     1532                i++;
     1533            }
     1534        }
     1535
     1536        if (fClear)
    15081537            ahciHbaClearInterrupt(ahci);
    15091538        else
     
    17911820        pAhciPort->regCMD |= AHCI_PORT_CMD_CPS; /* Indicate that there is a device on that port */
    17921821        /* We received a COMINIT signal */
    1793         pAhciPort->regSERR |= AHCI_PORT_SERR_X;
    1794         pAhciPort->regIS   |= AHCI_PORT_IS_PCS;
    17951822        pAhciPort->regTFD  |= ATA_STAT_BUSY;
    17961823
     
    38223849        {
    38233850            /* Error bit is set. */
    3824             pAhciPort->regIS |= AHCI_PORT_IS_TFES;
     3851            ASMAtomicOrU32(&pAhciPort->regIS, AHCI_PORT_IS_TFES);
    38253852            if (pAhciPort->regIE & AHCI_PORT_IE_TFEE)
    38263853                fAssertIntr = true;
     
    38293856        if (fInterrupt)
    38303857        {
    3831             pAhciPort->regIS |= AHCI_PORT_IS_DHRS;
     3858            ASMAtomicOrU32(&pAhciPort->regIS, AHCI_PORT_IS_DHRS);
    38323859            /* Check if we should assert an interrupt */
    38333860            if (pAhciPort->regIE & AHCI_PORT_IE_DHRE)
     
    38733900        {
    38743901            /* Error bit is set. */
    3875             pAhciPort->regIS |= AHCI_PORT_IS_TFES;
     3902            ASMAtomicOrU32(&pAhciPort->regIS, AHCI_PORT_IS_TFES);
    38763903            if (pAhciPort->regIE & AHCI_PORT_IE_TFEE)
    38773904                fAssertIntr = true;
     
    38803907        if (fInterrupt)
    38813908        {
    3882             pAhciPort->regIS |= AHCI_PORT_IS_SDBS;
     3909            ASMAtomicOrU32(&pAhciPort->regIS, AHCI_PORT_IS_SDBS);
    38833910            /* Check if we should assert an interrupt */
    38843911            if (pAhciPort->regIE & AHCI_PORT_IE_SDBE)
     
    49434970    /* Print some infos about the FIS. */
    49444971    ahciDumpFisInfo(pAhciPort, &pAhciPortTaskState->cmdFis[0]);
     4972
     4973    /* Print the PRDT */
     4974    RTGCPHYS GCPhysAddrPRDTLEntryStart = AHCI_RTGCPHYS_FROM_U32(pAhciPortTaskState->cmdHdr.u32CmdTblAddrUp, pAhciPortTaskState->cmdHdr.u32CmdTblAddr) + AHCI_CMDHDR_PRDT_OFFSET;
     4975
     4976    ahciLog(("PRDT address %RGp number of entries %u\n", GCPhysAddrPRDTLEntryStart, AHCI_CMDHDR_PRDTL_ENTRIES(pAhciPortTaskState->cmdHdr.u32DescInf)));
     4977
     4978    for (unsigned i = 0; i < AHCI_CMDHDR_PRDTL_ENTRIES(pAhciPortTaskState->cmdHdr.u32DescInf); i++)
     4979    {
     4980        SGLEntry SGEntry;
     4981
     4982        ahciLog(("Entry %u at address %RGp\n", i, GCPhysAddrPRDTLEntryStart));
     4983        PDMDevHlpPhysRead(pAhciPort->CTX_SUFF(pDevIns), GCPhysAddrPRDTLEntryStart, &SGEntry, sizeof(SGLEntry));
     4984
     4985        RTGCPHYS GCPhysDataAddr = AHCI_RTGCPHYS_FROM_U32(SGEntry.u32DBAUp, SGEntry.u32DBA);
     4986        ahciLog(("GCPhysAddr=%RGp Size=%u\n", GCPhysDataAddr, SGEntry.u32DescInf & SGLENTRY_DESCINF_DBC));
     4987
     4988        GCPhysAddrPRDTLEntryStart += sizeof(SGLEntry);
     4989    }
    49454990#endif
    49464991}
     
    51805225        }
    51815226
    5182         ahciLog(("%s: Processing requests\n", __FUNCTION__));
    51835227        ASMAtomicXchgBool(&pAhciPort->fNotificationSend, false);
    51845228
    51855229        uint32_t cTasksToProcess = ASMAtomicXchgU32(&pAhciPort->uActTasksActive, 0);
     5230
     5231        ahciLog(("%s: Processing %u requests\n", __FUNCTION__, cTasksToProcess));
    51865232
    51875233        /* Process commands. */
     
    53515397            ahciLog(("%s: After uActReadPos=%u\n", __FUNCTION__, pAhciPort->uActReadPos));
    53525398            cTasksToProcess--;
     5399            if (!cTasksToProcess)
     5400                cTasksToProcess = ASMAtomicXchgU32(&pAhciPort->uActTasksActive, 0);
    53535401        }
    53545402
     
    54185466     */
    54195467    pAhciPort->regCMD  |= AHCI_PORT_CMD_CPS;
    5420     pAhciPort->regIS   |= AHCI_PORT_IS_CPDS | AHCI_PORT_IS_PRCS;
     5468    ASMAtomicOrU32(&pAhciPort->regIS, AHCI_PORT_IS_CPDS | AHCI_PORT_IS_PRCS);
    54215469    pAhciPort->regSERR |= AHCI_PORT_SERR_N;
    54225470    if (pAhciPort->regIE & AHCI_PORT_IE_CPDE)
     
    54405488    pAhciPort->regSSTS = 0;
    54415489    pAhciPort->regCMD &= ~AHCI_PORT_CMD_CPS;
    5442     pAhciPort->regIS |= AHCI_PORT_IS_CPDS | AHCI_PORT_IS_PRCS;
     5490    ASMAtomicOrU32(&pAhciPort->regIS, AHCI_PORT_IS_CPDS | AHCI_PORT_IS_PRCS);
    54435491    pAhciPort->regSERR |= AHCI_PORT_SERR_N;
    54445492    if (pAhciPort->regIE & AHCI_PORT_IE_CPDE)
     
    58535901        SSMR3GetGCPhys(pSSMHandle, (RTGCPHYS *)&pAhci->ahciPort[i].GCPhysAddrClb);
    58545902        SSMR3GetGCPhys(pSSMHandle, (RTGCPHYS *)&pAhci->ahciPort[i].GCPhysAddrFb);
    5855         SSMR3GetU32(pSSMHandle, &pAhci->ahciPort[i].regIS);
     5903        SSMR3GetU32(pSSMHandle, (uint32_t *)&pAhci->ahciPort[i].regIS);
    58565904        SSMR3GetU32(pSSMHandle, &pAhci->ahciPort[i].regIE);
    58575905        SSMR3GetU32(pSSMHandle, &pAhci->ahciPort[i].regCMD);
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