VirtualBox

Changeset 64036 in vbox for trunk/src


Ignore:
Timestamp:
Sep 27, 2016 10:40:37 AM (8 years ago)
Author:
vboxsync
Message:

AHCI: Free the request before notifying the guest about the completion or it might submit a new request with the same tag while it is still allocated causing errors

File:
1 edited

Legend:

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

    r64030 r64036  
    52085208 * @returns nothing.
    52095209 * @param   pAhciPort          The port of the SATA controller.
    5210  * @param   pAhciReq           The state of the task.
     5210 * @param   cbTransfer         Transfer size of the request.
    52115211 * @param   pCmdFis            Pointer to the command FIS from the guest.
     5212 * @param   fRead              Flag whether this is a read request.
    52125213 * @param   fInterrupt         If an interrupt should be send to the guest.
    52135214 */
    5214 static void ahciSendPioSetupFis(PAHCIPort pAhciPort, PAHCIREQ pAhciReq, uint8_t *pCmdFis,
    5215                                 bool fInterrupt)
     5215static void ahciSendPioSetupFis(PAHCIPort pAhciPort, size_t cbTransfer, uint8_t *pCmdFis,
     5216                                bool fRead, bool fInterrupt)
    52165217{
    52175218    uint8_t abPioSetupFis[20];
     
    52215222    ahciLog(("%s: building PIO setup Fis\n", __FUNCTION__));
    52225223
    5223     AssertMsg(   pAhciReq->cbTransfer > 0
    5224               && pAhciReq->cbTransfer <= 65534,
     5224    AssertMsg(   cbTransfer > 0
     5225              && cbTransfer <= 65534,
    52255226              ("Can't send PIO setup FIS for requests with 0 bytes to transfer or greater than 65534\n"));
    52265227
     
    52305231        abPioSetupFis[AHCI_CMDFIS_TYPE]  = AHCI_CMDFIS_TYPE_PIOSETUP;
    52315232        abPioSetupFis[AHCI_CMDFIS_BITS]  = (fInterrupt ? AHCI_CMDFIS_I : 0);
    5232         if (pAhciReq->enmType == PDMMEDIAEXIOREQTYPE_READ)
     5233        if (fRead)
    52335234            abPioSetupFis[AHCI_CMDFIS_BITS] |= AHCI_CMDFIS_D;
    52345235        abPioSetupFis[AHCI_CMDFIS_STS]   = pCmdFis[AHCI_CMDFIS_STS];
     
    52455246
    52465247        /* Set transfer count. */
    5247         abPioSetupFis[16] = (pAhciReq->cbTransfer >> 8) & 0xff;
    5248         abPioSetupFis[17] = pAhciReq->cbTransfer & 0xff;
     5248        abPioSetupFis[16] = (cbTransfer >> 8) & 0xff;
     5249        abPioSetupFis[17] = cbTransfer & 0xff;
    52495250
    52505251        /* Update registers. */
     
    52745275 * @returns Nothing
    52755276 * @param   pAhciPort          The port of the SATA controller.
    5276  * @param   pAhciReq           The state of the task.
     5277 * @param   uTag               The tag of the request.
    52775278 * @param   pCmdFis            Pointer to the command FIS from the guest.
    52785279 * @param   fInterrupt         If an interrupt should be send to the guest.
    52795280 */
    5280 static void ahciSendD2HFis(PAHCIPort pAhciPort, PAHCIREQ pAhciReq, uint8_t *pCmdFis, bool fInterrupt)
     5281static void ahciSendD2HFis(PAHCIPort pAhciPort, uint32_t uTag, uint8_t *pCmdFis, bool fInterrupt)
    52815282{
    52825283    uint8_t d2hFis[20];
     
    53275328
    53285329            /* Mark command as completed. */
    5329             ASMAtomicOrU32(&pAhciPort->u32TasksFinished, (1 << pAhciReq->uTag));
     5330            ASMAtomicOrU32(&pAhciPort->u32TasksFinished, RT_BIT_32(uTag));
    53305331        }
    53315332
     
    58575858static void ahciR3ReqFree(PAHCIPort pAhciPort, PAHCIREQ pAhciReq)
    58585859{
    5859     int rc = pAhciPort->pDrvMediaEx->pfnIoReqFree(pAhciPort->pDrvMediaEx, pAhciReq->hIoReq);
    5860     AssertRC(rc);
     5860    if (   pAhciReq
     5861        && !(pAhciReq->fFlags & AHCI_REQ_IS_ON_STACK))
     5862    {
     5863        int rc = pAhciPort->pDrvMediaEx->pfnIoReqFree(pAhciPort->pDrvMediaEx, pAhciReq->hIoReq);
     5864        AssertRC(rc);
     5865    }
    58615866}
    58625867
     
    59575962        }
    59585963
     5964        /*
     5965         * Make a copy of the required data now and free the request. Otherwise the guest
     5966         * might issue a new request with the same tag and we run into a conflict when allocating
     5967         * a new request with the same tag later on.
     5968         */
     5969        uint32_t fFlags = pAhciReq->fFlags;
     5970        uint32_t uTag   = pAhciReq->uTag;
     5971        size_t   cbTransfer = pAhciReq->cbTransfer;
     5972        bool     fRead      = pAhciReq->enmType == PDMMEDIAEXIOREQTYPE_READ;
     5973        uint8_t  cmdFis[AHCI_CMDFIS_TYPE_H2D_SIZE];
     5974        memcpy(&cmdFis[0], &pAhciReq->cmdFis[0], sizeof(cmdFis));
     5975
     5976        ahciR3ReqFree(pAhciPort, pAhciReq);
    59595977        if (!fRedo)
    59605978        {
    59615979
    59625980            /* Post a PIO setup FIS first if this is a PIO command which transfers data. */
    5963             if (pAhciReq->fFlags & AHCI_REQ_PIO_DATA)
    5964                 ahciSendPioSetupFis(pAhciPort, pAhciReq, pAhciReq->cmdFis, false /* fInterrupt */);
    5965 
    5966             if (pAhciReq->fFlags & AHCI_REQ_CLEAR_SACT)
     5981            if (fFlags & AHCI_REQ_PIO_DATA)
     5982                ahciSendPioSetupFis(pAhciPort, cbTransfer, &cmdFis[0], fRead, false /* fInterrupt */);
     5983
     5984            if (fFlags & AHCI_REQ_CLEAR_SACT)
    59675985            {
    59685986                if (RT_SUCCESS(rcReq) && !ASMAtomicReadPtrT(&pAhciPort->pTaskErr, PAHCIREQ))
    5969                     ASMAtomicOrU32(&pAhciPort->u32QueuedTasksFinished, RT_BIT_32(pAhciReq->uTag));
     5987                    ASMAtomicOrU32(&pAhciPort->u32QueuedTasksFinished, RT_BIT_32(uTag));
    59705988            }
    59715989
    5972             if (pAhciReq->fFlags & AHCI_REQ_IS_QUEUED)
     5990            if (fFlags & AHCI_REQ_IS_QUEUED)
    59735991            {
    59745992                /*
     
    59805998            }
    59815999            else
    5982                 ahciSendD2HFis(pAhciPort, pAhciReq, pAhciReq->cmdFis, true);
     6000                ahciSendD2HFis(pAhciPort, uTag, &cmdFis[0], true);
    59836001        }
    59846002    }
     
    60096027                        pAhciReq->cbTransfer, rcReq));
    60106028         }
     6029
     6030         ahciR3ReqFree(pAhciPort, pAhciReq);
    60116031    }
    60126032
     
    60246044        PDMDevHlpAsyncNotificationCompleted(pAhciPort->pDevInsR3);
    60256045
    6026     /* Don't free the request if it is on the stack. */
    6027     if (   pAhciReq
    6028         && !(pAhciReq->fFlags & AHCI_REQ_IS_ON_STACK))
    6029         ahciR3ReqFree(pAhciPort, pAhciReq);
    60306046    return fCanceled;
    60316047}
     
    64566472         * but this FIS does not assert an interrupt
    64576473         */
    6458         ahciSendD2HFis(pAhciPort, pAhciReq, pAhciReq->cmdFis, false);
     6474        ahciSendD2HFis(pAhciPort, pAhciReq->uTag, pAhciReq->cmdFis, false);
    64596475        pAhciPort->regTFD &= ~AHCI_PORT_TFD_BSY;
    64606476    }
     
    65866602                ahciLog(("%s: Setting device into reset state\n", __FUNCTION__));
    65876603                pAhciPort->fResetDevice = true;
    6588                 ahciSendD2HFis(pAhciPort, pAhciReq, pAhciReq->cmdFis, true);
     6604                ahciSendD2HFis(pAhciPort, pAhciReq->uTag, pAhciReq->cmdFis, true);
    65896605            }
    65906606            else if (pAhciPort->fResetDevice) /* The bit is not set and we are in a reset state. */
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