VirtualBox

Changeset 39579 in vbox


Ignore:
Timestamp:
Dec 11, 2011 9:43:40 PM (13 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
75339
Message:

AHCI: Set overflow bit if the guest tries to transfer more data than is available in the buffer

File:
1 edited

Legend:

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

    r39136 r39579  
    68436843                    }
    68446844
    6845                     if (enmTxDir == AHCITXDIR_FLUSH)
     6845                    if (pAhciPortTaskState->cbSGBuffers < pAhciPortTaskState->cbTransfer)
    68466846                    {
    6847                         rc = pAhciPort->pDrvBlockAsync->pfnStartFlush(pAhciPort->pDrvBlockAsync,
    6848                                                                       pAhciPortTaskState);
    6849                     }
    6850                     else if (enmTxDir == AHCITXDIR_TRIM)
    6851                     {
    6852                         rc = ahciTrimRangesCreate(pAhciPort, pAhciPortTaskState);
    6853                         if (RT_SUCCESS(rc))
    6854                         {
    6855                             pAhciPort->Led.Asserted.s.fWriting = pAhciPort->Led.Actual.s.fWriting = 1;
    6856                             rc = pAhciPort->pDrvBlockAsync->pfnStartDiscard(pAhciPort->pDrvBlockAsync, pAhciPortTaskState->paRanges,
    6857                                                                             pAhciPortTaskState->cRanges, pAhciPortTaskState);
    6858                         }
    6859                     }
    6860                     else if (enmTxDir == AHCITXDIR_READ)
    6861                     {
    6862                         pAhciPort->Led.Asserted.s.fReading = pAhciPort->Led.Actual.s.fReading = 1;
    6863                         rc = pAhciPort->pDrvBlockAsync->pfnStartRead(pAhciPort->pDrvBlockAsync, pAhciPortTaskState->uOffset,
    6864                                                                      pAhciPortTaskState->pSGListHead, pAhciPortTaskState->cSGListUsed,
    6865                                                                      pAhciPortTaskState->cbTransfer,
    6866                                                                      pAhciPortTaskState);
     6847                        /*
     6848                         * The guest tried to transfer more data than there is space in the buffer.
     6849                         * Terminate task and set the overflow bit.
     6850                         */
     6851                        ASMAtomicCmpXchgSize(&pAhciPortTaskState->enmTxState, AHCITXSTATE_FREE, AHCITXSTATE_ACTIVE, fXchg);
     6852                        AssertMsg(fXchg, ("Task is not active\n"));
     6853
     6854                        /* Add the task to the cache. */
     6855                        pAhciPort->aCachedTasks[pAhciPortTaskState->uTag] = pAhciPortTaskState;
     6856
     6857                        /* Notify the guest. */
     6858                        ASMAtomicOrU32(&pAhciPort->regIS, AHCI_PORT_IS_OFS);
     6859                        if (pAhciPort->regIE & AHCI_PORT_IE_OFE)
     6860                            ahciHbaSetInterrupt(pAhciPort->CTX_SUFF(pAhci), pAhciPort->iLUN, VERR_IGNORED);
    68676861                    }
    68686862                    else
    68696863                    {
    6870                         pAhciPort->Led.Asserted.s.fWriting = pAhciPort->Led.Actual.s.fWriting = 1;
    6871                         rc = pAhciPort->pDrvBlockAsync->pfnStartWrite(pAhciPort->pDrvBlockAsync, pAhciPortTaskState->uOffset,
    6872                                                                       pAhciPortTaskState->pSGListHead, pAhciPortTaskState->cSGListUsed,
    6873                                                                       pAhciPortTaskState->cbTransfer,
    6874                                                                       pAhciPortTaskState);
     6864                        if (enmTxDir == AHCITXDIR_FLUSH)
     6865                        {
     6866                            rc = pAhciPort->pDrvBlockAsync->pfnStartFlush(pAhciPort->pDrvBlockAsync,
     6867                                                                          pAhciPortTaskState);
     6868                        }
     6869                        else if (enmTxDir == AHCITXDIR_TRIM)
     6870                        {
     6871                            rc = ahciTrimRangesCreate(pAhciPort, pAhciPortTaskState);
     6872                            if (RT_SUCCESS(rc))
     6873                            {
     6874                                pAhciPort->Led.Asserted.s.fWriting = pAhciPort->Led.Actual.s.fWriting = 1;
     6875                                rc = pAhciPort->pDrvBlockAsync->pfnStartDiscard(pAhciPort->pDrvBlockAsync, pAhciPortTaskState->paRanges,
     6876                                                                                pAhciPortTaskState->cRanges, pAhciPortTaskState);
     6877                            }
     6878                        }
     6879                        else if (enmTxDir == AHCITXDIR_READ)
     6880                        {
     6881                            pAhciPort->Led.Asserted.s.fReading = pAhciPort->Led.Actual.s.fReading = 1;
     6882                            rc = pAhciPort->pDrvBlockAsync->pfnStartRead(pAhciPort->pDrvBlockAsync, pAhciPortTaskState->uOffset,
     6883                                                                         pAhciPortTaskState->pSGListHead, pAhciPortTaskState->cSGListUsed,
     6884                                                                         pAhciPortTaskState->cbTransfer,
     6885                                                                         pAhciPortTaskState);
     6886                        }
     6887                        else
     6888                        {
     6889                            pAhciPort->Led.Asserted.s.fWriting = pAhciPort->Led.Actual.s.fWriting = 1;
     6890                            rc = pAhciPort->pDrvBlockAsync->pfnStartWrite(pAhciPort->pDrvBlockAsync, pAhciPortTaskState->uOffset,
     6891                                                                          pAhciPortTaskState->pSGListHead, pAhciPortTaskState->cSGListUsed,
     6892                                                                          pAhciPortTaskState->cbTransfer,
     6893                                                                          pAhciPortTaskState);
     6894                        }
     6895                        if (rc == VINF_VD_ASYNC_IO_FINISHED)
     6896                            rc = ahciTransferComplete(pAhciPort, pAhciPortTaskState, VINF_SUCCESS);
     6897                        else if (RT_FAILURE(rc) && rc != VERR_VD_ASYNC_IO_IN_PROGRESS)
     6898                            rc = ahciTransferComplete(pAhciPort, pAhciPortTaskState, rc);
    68756899                    }
    6876                     if (rc == VINF_VD_ASYNC_IO_FINISHED)
    6877                         rc = ahciTransferComplete(pAhciPort, pAhciPortTaskState, VINF_SUCCESS);
    6878                     else if (RT_FAILURE(rc) && rc != VERR_VD_ASYNC_IO_IN_PROGRESS)
    6879                         rc = ahciTransferComplete(pAhciPort, pAhciPortTaskState, rc);
    68806900                }
    68816901                else
     
    71107130                else if (enmTxDir != AHCITXDIR_NONE)
    71117131                {
    7112                     uint64_t uOffset;
    7113                     size_t cbTransfer;
     7132                    uint64_t uOffset = 0;
     7133                    size_t cbTransfer = 0;
    71147134                    PRTSGSEG pSegCurr;
    71157135                    PAHCIPORTTASKSTATESGENTRY pSGInfoCurr;
     
    71197139                        AssertMsgFailed(("%s: Failed to get number of list elments %Rrc\n", __FUNCTION__, rc));
    71207140
    7121                     STAM_REL_COUNTER_INC(&pAhciPort->StatDMA);
    7122 
    7123                     /* Initialize all values. */
    7124                     uOffset     = pAhciPortTaskState->uOffset;
    7125                     cbTransfer  = pAhciPortTaskState->cbTransfer;
    7126                     pSegCurr    = &pAhciPortTaskState->pSGListHead[0];
    7127                     pSGInfoCurr = pAhciPortTaskState->paSGEntries;
    7128 
    7129                     STAM_PROFILE_START(&pAhciPort->StatProfileReadWrite, b);
    7130 
    7131                     while (cbTransfer)
     7141                    if (pAhciPortTaskState->cbSGBuffers < pAhciPortTaskState->cbTransfer)
    71327142                    {
    7133                         size_t cbProcess = (cbTransfer < pSegCurr->cbSeg) ? cbTransfer : pSegCurr->cbSeg;
    7134 
    7135                         AssertMsg(!(pSegCurr->cbSeg % 512), ("Buffer is not sector aligned cbSeg=%d\n", pSegCurr->cbSeg));
    7136                         AssertMsg(!(uOffset % 512), ("Offset is not sector aligned %llu\n", uOffset));
    7137                         AssertMsg(!(cbProcess % 512), ("Number of bytes to process is not sector aligned %lu\n", cbProcess));
    7138 
    7139                         if (enmTxDir == AHCITXDIR_READ)
     7143                        /*
     7144                         * The guest tried to transfer more data than there is space in the buffer.
     7145                         * Terminate task and set the overflow bit.
     7146                         */
     7147                        int rc2 = ahciScatterGatherListDestroy(pAhciPort, pAhciPortTaskState);
     7148                        AssertMsgRC(rc2, ("Destroying task list failed rc=%Rrc\n", rc2));
     7149
     7150                       /* Notify the guest. */
     7151                        ASMAtomicOrU32(&pAhciPort->regIS, AHCI_PORT_IS_OFS);
     7152                        if (pAhciPort->regIE & AHCI_PORT_IE_OFE)
     7153                            ahciHbaSetInterrupt(pAhciPort->CTX_SUFF(pAhci), pAhciPort->iLUN, VERR_IGNORED);
     7154                    }
     7155                    else
     7156                    {
     7157                        STAM_REL_COUNTER_INC(&pAhciPort->StatDMA);
     7158
     7159                        /* Initialize all values. */
     7160                        uOffset     = pAhciPortTaskState->uOffset;
     7161                        cbTransfer  = pAhciPortTaskState->cbTransfer;
     7162                        pSegCurr    = &pAhciPortTaskState->pSGListHead[0];
     7163                        pSGInfoCurr = pAhciPortTaskState->paSGEntries;
     7164
     7165                        STAM_PROFILE_START(&pAhciPort->StatProfileReadWrite, b);
     7166
     7167                        while (cbTransfer)
    71407168                        {
    7141                             pAhciPort->Led.Asserted.s.fReading = pAhciPort->Led.Actual.s.fReading = 1;
    7142                             rc = pAhciPort->pDrvBlock->pfnRead(pAhciPort->pDrvBlock, uOffset,
    7143                                                                pSegCurr->pvSeg, cbProcess);
    7144                             pAhciPort->Led.Actual.s.fReading = 0;
    7145                             if (RT_FAILURE(rc))
    7146                                 break;
    7147 
    7148                             STAM_REL_COUNTER_ADD(&pAhciPort->StatBytesRead, cbProcess);
    7149                         }
    7150                         else
    7151                         {
    7152                             pAhciPort->Led.Asserted.s.fWriting = pAhciPort->Led.Actual.s.fWriting = 1;
    7153                             rc = pAhciPort->pDrvBlock->pfnWrite(pAhciPort->pDrvBlock, uOffset,
    7154                                                                 pSegCurr->pvSeg, cbProcess);
    7155                             pAhciPort->Led.Actual.s.fWriting = 0;
    7156                             if (RT_FAILURE(rc))
    7157                                 break;
    7158 
    7159                             STAM_REL_COUNTER_ADD(&pAhciPort->StatBytesWritten, cbProcess);
    7160                         }
    7161 
    7162                         /* Go to the next entry. */
    7163                         uOffset    += cbProcess;
    7164                         cbTransfer -= cbProcess;
    7165                         pSegCurr++;
    7166                         pSGInfoCurr++;
    7167                     }
    7168 
    7169                     STAM_PROFILE_STOP(&pAhciPort->StatProfileReadWrite, b);
    7170 
    7171                     /* Log the error. */
    7172                     if (   RT_FAILURE(rc)
    7173                         && pAhciPort->cErrors++ < MAX_LOG_REL_ERRORS)
    7174                     {
    7175                         LogRel(("AHCI#%u: %s at offset %llu (%u bytes left) returned rc=%Rrc\n",
    7176                                 pAhciPort->iLUN,
    7177                                 enmTxDir == AHCITXDIR_READ
    7178                                 ? "Read"
    7179                                 : "Write",
    7180                                 uOffset, cbTransfer, rc));
    7181                     }
    7182 
    7183                     /* Cleanup. */
    7184                     int rc2 = ahciScatterGatherListDestroy(pAhciPort, pAhciPortTaskState);
    7185                     if (RT_FAILURE(rc2))
    7186                         AssertMsgFailed(("Destroying task list failed rc=%Rrc\n", rc));
    7187 
    7188                     if (RT_LIKELY(!pAhciPort->fPortReset))
    7189                     {
    7190                         pAhciPortTaskState->cmdHdr.u32PRDBC = pAhciPortTaskState->cbTransfer - cbTransfer;
    7191                         if (RT_FAILURE(rc))
    7192                         {
    7193                             if (!ahciIsRedoSetWarning(pAhciPort, rc))
     7169                            size_t cbProcess = (cbTransfer < pSegCurr->cbSeg) ? cbTransfer : pSegCurr->cbSeg;
     7170
     7171                            AssertMsg(!(pSegCurr->cbSeg % 512), ("Buffer is not sector aligned cbSeg=%d\n", pSegCurr->cbSeg));
     7172                            AssertMsg(!(uOffset % 512), ("Offset is not sector aligned %llu\n", uOffset));
     7173                            AssertMsg(!(cbProcess % 512), ("Number of bytes to process is not sector aligned %lu\n", cbProcess));
     7174
     7175                            if (enmTxDir == AHCITXDIR_READ)
    71947176                            {
    7195                                 pAhciPortTaskState->uATARegError = ID_ERR;
    7196                                 pAhciPortTaskState->uATARegStatus = ATA_STAT_READY | ATA_STAT_ERR;
     7177                                pAhciPort->Led.Asserted.s.fReading = pAhciPort->Led.Actual.s.fReading = 1;
     7178                                rc = pAhciPort->pDrvBlock->pfnRead(pAhciPort->pDrvBlock, uOffset,
     7179                                                                   pSegCurr->pvSeg, cbProcess);
     7180                                pAhciPort->Led.Actual.s.fReading = 0;
     7181                                if (RT_FAILURE(rc))
     7182                                    break;
     7183
     7184                                STAM_REL_COUNTER_ADD(&pAhciPort->StatBytesRead, cbProcess);
    71977185                            }
    71987186                            else
    71997187                            {
    7200                                 /* Add the task to the mask again. */
    7201                                 ASMAtomicOrU32(&pAhciPort->u32TasksNew, (1 << pAhciPortTaskState->uTag));
     7188                                pAhciPort->Led.Asserted.s.fWriting = pAhciPort->Led.Actual.s.fWriting = 1;
     7189                                rc = pAhciPort->pDrvBlock->pfnWrite(pAhciPort->pDrvBlock, uOffset,
     7190                                                                    pSegCurr->pvSeg, cbProcess);
     7191                                pAhciPort->Led.Actual.s.fWriting = 0;
     7192                                if (RT_FAILURE(rc))
     7193                                    break;
     7194
     7195                                STAM_REL_COUNTER_ADD(&pAhciPort->StatBytesWritten, cbProcess);
    72027196                            }
     7197
     7198                            /* Go to the next entry. */
     7199                            uOffset    += cbProcess;
     7200                            cbTransfer -= cbProcess;
     7201                            pSegCurr++;
     7202                            pSGInfoCurr++;
    72037203                        }
    7204                         else
     7204
     7205                        STAM_PROFILE_STOP(&pAhciPort->StatProfileReadWrite, b);
     7206
     7207                        /* Log the error. */
     7208                        if (   RT_FAILURE(rc)
     7209                            && pAhciPort->cErrors++ < MAX_LOG_REL_ERRORS)
    72057210                        {
    7206                             pAhciPortTaskState->uATARegError = 0;
    7207                             pAhciPortTaskState->uATARegStatus = ATA_STAT_READY | ATA_STAT_SEEK;
     7211                            LogRel(("AHCI#%u: %s at offset %llu (%u bytes left) returned rc=%Rrc\n",
     7212                                    pAhciPort->iLUN,
     7213                                    enmTxDir == AHCITXDIR_READ
     7214                                    ? "Read"
     7215                                    : "Write",
     7216                                    uOffset, cbTransfer, rc));
    72087217                        }
    72097218
    7210                         if (!pAhciPort->fRedo)
     7219                        /* Cleanup. */
     7220                        int rc2 = ahciScatterGatherListDestroy(pAhciPort, pAhciPortTaskState);
     7221                        if (RT_FAILURE(rc2))
     7222                            AssertMsgFailed(("Destroying task list failed rc=%Rrc\n", rc));
     7223
     7224                        if (RT_LIKELY(!pAhciPort->fPortReset))
    72117225                        {
    7212                             /* Write updated command header into memory of the guest. */
    7213                             PDMDevHlpPhysWrite(pAhciPort->CTX_SUFF(pDevIns), pAhciPortTaskState->GCPhysCmdHdrAddr,
    7214                                                &pAhciPortTaskState->cmdHdr, sizeof(CmdHdr));
    7215 
    7216                             if (pAhciPortTaskState->fQueued)
    7217                                 ASMAtomicOrU32(&pAhciPort->u32QueuedTasksFinished, (1 << pAhciPortTaskState->uTag));
     7226                            pAhciPortTaskState->cmdHdr.u32PRDBC = pAhciPortTaskState->cbTransfer - cbTransfer;
     7227                            if (RT_FAILURE(rc))
     7228                            {
     7229                                if (!ahciIsRedoSetWarning(pAhciPort, rc))
     7230                                {
     7231                                    pAhciPortTaskState->uATARegError = ID_ERR;
     7232                                    pAhciPortTaskState->uATARegStatus = ATA_STAT_READY | ATA_STAT_ERR;
     7233                                }
     7234                                else
     7235                                {
     7236                                    /* Add the task to the mask again. */
     7237                                    ASMAtomicOrU32(&pAhciPort->u32TasksNew, (1 << pAhciPortTaskState->uTag));
     7238                                }
     7239                            }
    72187240                            else
    72197241                            {
    7220                                 /* Task is not queued send D2H FIS */
    7221                                 ahciSendD2HFis(pAhciPort, pAhciPortTaskState, &pAhciPortTaskState->cmdFis[0], true);
     7242                                pAhciPortTaskState->uATARegError = 0;
     7243                                pAhciPortTaskState->uATARegStatus = ATA_STAT_READY | ATA_STAT_SEEK;
    72227244                            }
    72237245
    7224                             uIORequestsProcessed++;
     7246                            if (!pAhciPort->fRedo)
     7247                            {
     7248                                /* Write updated command header into memory of the guest. */
     7249                                PDMDevHlpPhysWrite(pAhciPort->CTX_SUFF(pDevIns), pAhciPortTaskState->GCPhysCmdHdrAddr,
     7250                                                   &pAhciPortTaskState->cmdHdr, sizeof(CmdHdr));
     7251
     7252                                if (pAhciPortTaskState->fQueued)
     7253                                    ASMAtomicOrU32(&pAhciPort->u32QueuedTasksFinished, (1 << pAhciPortTaskState->uTag));
     7254                                else
     7255                                {
     7256                                    /* Task is not queued send D2H FIS */
     7257                                    ahciSendD2HFis(pAhciPort, pAhciPortTaskState, &pAhciPortTaskState->cmdFis[0], true);
     7258                                }
     7259
     7260                                uIORequestsProcessed++;
     7261                            }
    72257262                        }
    72267263                    }
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