VirtualBox

Changeset 64018 in vbox for trunk/src/VBox/Devices


Ignore:
Timestamp:
Sep 26, 2016 4:29:33 PM (8 years ago)
Author:
vboxsync
Message:

AHCI: Remove allocating I/O buffers on our own and let the provider of PDMIMEDIAEX manage it for us

File:
1 edited

Legend:

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

    r64016 r64018  
    234234 * @returns VBox status code.
    235235 * @param   pAhciReq    The task state.
     236 * @param   pSgBuf      Buffer holding the data to process.
     237 * @param   cbBuf       Size of the buffer.
     238 * @param   offBuf      Offset into the guest buffer.
    236239 * @param   ppvProc     Where to store the pointer to the buffer holding the processed data on success.
    237240 *                      Must be freed with RTMemFree().
    238241 * @param   pcbProc     Where to store the size of the buffer on success.
    239242 */
    240 typedef DECLCALLBACK(int)   FNAHCIPOSTPROCESS(PAHCIREQ pAhciReq, void **ppvProc, size_t *pcbProc);
     243typedef DECLCALLBACK(int)   FNAHCIPOSTPROCESS(PAHCIREQ pAhciReq, PRTSGBUF pSgBuf, size_t cbBuf,
     244                                              uint32_t offBuf, void **ppvProc, size_t *pcbProc);
    241245/** Pointer to a FNAHCIPOSTPROCESS() function. */
    242246typedef FNAHCIPOSTPROCESS *PFNAHCIPOSTPROCESS;
     
    271275    /** Physical address of the command header. - GC */
    272276    RTGCPHYS                   GCPhysCmdHdrAddr;
    273     /** Physical address if the PRDT */
     277    /** Physical address of the PRDT */
    274278    RTGCPHYS                   GCPhysPrdtl;
    275279    /** Number of entries in the PRDTL. */
     
    283287    /** Flags for this task. */
    284288    uint32_t                   fFlags;
    285     /** Additional memory allocation for this task. */
    286     void                      *pvAlloc;
    287     /** Siize of the allocation. */
    288     size_t                     cbAlloc;
    289     /** Number of times we had too much memory allocated for the request. */
    290     unsigned                   cAllocTooMuch;
    291     /** Data dependent on the transfer direction. */
    292     union
    293     {
    294         /** Data for an I/O request. */
    295         struct
    296         {
    297             /** Data segment. */
    298             RTSGSEG            DataSeg;
    299             /** Post processing callback.
    300              * If this is set we will use a buffer for the data
    301              * and the callback returns a buffer with the final data. */
    302             PFNAHCIPOSTPROCESS pfnPostProcess;
    303         } Io;
    304     } u;
     289    /** Post processing callback.
     290     * If this is set we will use a buffer for the data
     291     * and the callback returns a buffer with the final data. */
     292    PFNAHCIPOSTPROCESS         pfnPostProcess;
    305293} AHCIREQ;
    306294
     
    320308 * @implements PDMIBASE
    321309 * @implements PDMIMEDIAPORT
    322  * @implements PDMIMEDIAASYNCPORT
     310 * @implements PDMIMEDIAEXPORT
    323311 * @implements PDMIMOUNTNOTIFY
    324312 */
     
    681669AssertCompileSize(SGLEntry, 16);
    682670
     671#ifdef IN_RING3
     672/**
     673 * Memory buffer callback.
     674 *
     675 * @returns nothing.
     676 * @param   pThis    The NVME controller instance.
     677 * @param   GCPhys   The guest physical address of the memory buffer.
     678 * @param   pSgBuf   The pointer to the host R3 S/G buffer.
     679 * @param   cbCopy   How many bytes to copy between the two buffers.
     680 * @param   pcbSkip  Initially contains the amount of bytes to skip
     681 *                   starting from the guest physical address before
     682 *                   accessing the S/G buffer and start copying data.
     683 *                   On return this contains the remaining amount if
     684 *                   cbCopy < *pcbSkip or 0 otherwise.
     685 */
     686typedef DECLCALLBACK(void) AHCIR3MEMCOPYCALLBACK(PAHCI pThis, RTGCPHYS GCPhys, PRTSGBUF pSgBuf, size_t cbCopy,
     687                                                 size_t *pcbSkip);
     688/** Pointer to a memory copy buffer callback. */
     689typedef AHCIR3MEMCOPYCALLBACK *PAHCIR3MEMCOPYCALLBACK;
     690#endif
     691
    683692/** Defines for a scatter gather list entry. */
    684693#define SGLENTRY_DBA_READONLY     ~(RT_BIT(0))
     
    887896static int  ahciPostFisIntoMemory(PAHCIPort pAhciPort, unsigned uFisType, uint8_t *cmdFis);
    888897static void ahciPostFirstD2HFisIntoMemory(PAHCIPort pAhciPort);
    889 static uint32_t ahciCopyToPrdtl(PPDMDEVINS pDevIns, PAHCIREQ pAhciReq, const void *pvBuf, size_t cbBuf);
    890 static size_t ahciCopyFromPrdtl(PPDMDEVINS pDevIns, PAHCIREQ pAhciReq, void *pvBuf, size_t cbBuf);
     898static size_t ahciR3CopyBufferToPrdtl(PAHCI pThis, PAHCIREQ pAhciReq, const void *pvSrc,
     899                                      size_t cbSrc, size_t cbSkip);
     900static size_t ahciR3CopyBufferFromPrdtl(PAHCI pThis, PAHCIREQ pAhciReq, void *pvDst, size_t cbDst);
    891901static bool ahciCancelActiveTasks(PAHCIPort pAhciPort);
    892 static void ahciReqMemFree(PAHCIPort pAhciPort, PAHCIREQ pAhciReq, bool fForceFree);
    893902#endif
    894903RT_C_DECLS_END
     
    32383247
    32393248    /* Copy the buffer in to the scatter gather list. */
    3240     *pcbData =  ahciCopyToPrdtl(pAhciPort->pDevInsR3, pAhciReq, (void *)&p[0], RT_MIN(cbData, sizeof(p)));
     3249    *pcbData = ahciR3CopyBufferToPrdtl(pAhciPort->CTX_SUFF(pAhci), pAhciReq, (void *)&p[0],
     3250                                       RT_MIN(cbData, sizeof(p)), 0 /* cbSkip */);
    32413251
    32423252    atapiCmdOK(pAhciPort, pAhciReq);
     
    32523262
    32533263    /* Copy the buffer in to the scatter gather list. */
    3254     *pcbData = ahciCopyToPrdtl(pAhciPort->pDevInsR3, pAhciReq, (void *)&aBuf[0], RT_MIN(cbData, sizeof(aBuf)));
     3264    *pcbData = ahciR3CopyBufferToPrdtl(pAhciPort->CTX_SUFF(pAhci), pAhciReq, (void *)&aBuf[0],
     3265                                       RT_MIN(cbData, sizeof(aBuf)), 0 /* cbSkip */);
    32553266
    32563267    atapiCmdOK(pAhciPort, pAhciReq);
     
    32793290
    32803291    /* Copy the buffer in to the scatter gather list. */
    3281     *pcbData = ahciCopyToPrdtl(pAhciPort->pDevInsR3, pAhciReq, (void *)&aBuf[0], RT_MIN(cbData, sizeof(aBuf)));
     3292    *pcbData = ahciR3CopyBufferToPrdtl(pAhciPort->CTX_SUFF(pAhci), pAhciReq, (void *)&aBuf[0],
     3293                                       RT_MIN(cbData, sizeof(aBuf)), 0 /* cbSkip */);
    32823294
    32833295    atapiCmdOK(pAhciPort, pAhciReq);
     
    33093321
    33103322    /* Copy the buffer in to the scatter gather list. */
    3311     *pcbData = ahciCopyToPrdtl(pAhciPort->pDevInsR3, pAhciReq, (void *)&aBuf[0], RT_MIN(cbData, sizeof(aBuf)));
     3323    *pcbData = ahciR3CopyBufferToPrdtl(pAhciPort->CTX_SUFF(pAhci), pAhciReq, (void *)&aBuf[0],
     3324                                       RT_MIN(cbData, sizeof(aBuf)), 0 /* cbSkip */);
    33123325
    33133326    atapiCmdOK(pAhciPort, pAhciReq);
     
    34903503
    34913504    /* Copy the buffer in to the scatter gather list. */
    3492     *pcbData = ahciCopyToPrdtl(pAhciPort->pDevInsR3, pAhciReq, (void *)&aBuf[0], RT_MIN(cbData, sizeof(aBuf)));
     3505    *pcbData = ahciR3CopyBufferToPrdtl(pAhciPort->CTX_SUFF(pAhci), pAhciReq, (void *)&aBuf[0],
     3506                                       RT_MIN(cbData, sizeof(aBuf)), 0 /* cbSkip */);
    34933507
    34943508    atapiCmdOK(pAhciPort, pAhciReq);
     
    35663580    } while (!ASMAtomicCmpXchgU32(&pAhciPort->MediaEventStatus, NewStatus, OldStatus));
    35673581
    3568     *pcbData = ahciCopyToPrdtl(pAhciPort->pDevInsR3, pAhciReq, (void *)&abBuf[0], RT_MIN(cbData, sizeof(abBuf)));
     3582    *pcbData = ahciR3CopyBufferToPrdtl(pAhciPort->CTX_SUFF(pAhci), pAhciReq, (void *)&abBuf[0],
     3583                                       RT_MIN(cbData, sizeof(abBuf)), 0 /* cbSkip */);
    35693584
    35703585    atapiCmdOK(pAhciPort, pAhciReq);
     
    35903605
    35913606    /* Copy the buffer in to the scatter gather list. */
    3592     *pcbData = ahciCopyToPrdtl(pAhciPort->pDevInsR3, pAhciReq, (void *)&aBuf[0], RT_MIN(cbData, sizeof(aBuf)));
     3607    *pcbData = ahciR3CopyBufferToPrdtl(pAhciPort->CTX_SUFF(pAhci), pAhciReq, (void *)&aBuf[0],
     3608                                       RT_MIN(cbData, sizeof(aBuf)), 0 /* cbSkip */);
    35933609
    35943610    atapiCmdOK(pAhciPort, pAhciReq);
     
    36193635
    36203636    /* Copy the buffer in to the scatter gather list. */
    3621     *pcbData = ahciCopyToPrdtl(pAhciPort->pDevInsR3, pAhciReq, (void *)&aBuf[0], RT_MIN(cbData, sizeof(aBuf)));
     3637    *pcbData = ahciR3CopyBufferToPrdtl(pAhciPort->CTX_SUFF(pAhci), pAhciReq, (void *)&aBuf[0],
     3638                                       RT_MIN(cbData, sizeof(aBuf)), 0 /* cbSkip */);
    36223639
    36233640    atapiCmdOK(pAhciPort, pAhciReq);
     
    36693686
    36703687    /* Copy the buffer in to the scatter gather list. */
    3671     *pcbData = ahciCopyToPrdtl(pAhciPort->pDevInsR3, pAhciReq, (void *)&aBuf[0], RT_MIN(cbData, sizeof(aBuf)));
     3688    *pcbData = ahciR3CopyBufferToPrdtl(pAhciPort->CTX_SUFF(pAhci), pAhciReq, (void *)&aBuf[0],
     3689                                       RT_MIN(cbData, sizeof(aBuf)), 0 /* cbSkip */);
    36723690
    36733691    atapiCmdOK(pAhciPort, pAhciReq);
     
    36793697{
    36803698    /* Copy the buffer in to the scatter gather list. */
    3681     *pcbData = ahciCopyToPrdtl(pAhciPort->pDevInsR3, pAhciReq,
    3682                                pAhciPort->abATAPISense, RT_MIN(cbData, sizeof(pAhciPort->abATAPISense)));
     3699    *pcbData = ahciR3CopyBufferToPrdtl(pAhciPort->CTX_SUFF(pAhci), pAhciReq,
     3700                                       pAhciPort->abATAPISense, RT_MIN(cbData, sizeof(pAhciPort->abATAPISense)),
     3701                                       0 /* cbSkip */);
    36833702
    36843703    atapiCmdOK(pAhciPort, pAhciReq);
     
    37003719
    37013720    /* Copy the buffer in to the scatter gather list. */
    3702     *pcbData = ahciCopyToPrdtl(pAhciPort->pDevInsR3, pAhciReq, (void *)&aBuf[0], RT_MIN(cbData, sizeof(aBuf)));
     3721    *pcbData = ahciR3CopyBufferToPrdtl(pAhciPort->CTX_SUFF(pAhci), pAhciReq, (void *)&aBuf[0],
     3722                                       RT_MIN(cbData, sizeof(aBuf)), 0 /* cbSkip */);
    37033723
    37043724    atapiCmdOK(pAhciPort, pAhciReq);
     
    37623782
    37633783    /* Copy the buffer in to the scatter gather list. */
    3764     *pcbData = ahciCopyToPrdtl(pAhciPort->pDevInsR3, pAhciReq, (void *)&aBuf[0], RT_MIN(cbData, cbSize));
     3784    *pcbData = ahciR3CopyBufferToPrdtl(pAhciPort->CTX_SUFF(pAhci), pAhciReq, (void *)&aBuf[0],
     3785                                       RT_MIN(cbData, cbSize), 0 /* cbSkip */);
    37653786
    37663787    atapiCmdOK(pAhciPort, pAhciReq);
     
    37953816
    37963817    /* Copy the buffer in to the scatter gather list. */
    3797     *pcbData = ahciCopyToPrdtl(pAhciPort->pDevInsR3, pAhciReq, (void *)&aBuf[0], RT_MIN(cbData, sizeof(aBuf)));
     3818    *pcbData = ahciR3CopyBufferToPrdtl(pAhciPort->CTX_SUFF(pAhci), pAhciReq, (void *)&aBuf[0],
     3819                                       RT_MIN(cbData, sizeof(aBuf)), 0 /* cbSkip */);
    37983820
    37993821    atapiCmdOK(pAhciPort, pAhciReq);
     
    38833905
    38843906    /* Copy the buffer in to the scatter gather list. */
    3885     *pcbData = ahciCopyToPrdtl(pAhciPort->pDevInsR3, pAhciReq, (void *)&aBuf[0], RT_MIN(cbData, cbSize));
     3907    *pcbData = ahciR3CopyBufferToPrdtl(pAhciPort->CTX_SUFF(pAhci), pAhciReq, (void *)&aBuf[0],
     3908                                       RT_MIN(cbData, cbSize), 0 /* cbSkip */);
    38863909
    38873910    atapiCmdOK(pAhciPort, pAhciReq);
     
    39153938        if (pAhciReq->enmType == PDMMEDIAEXIOREQTYPE_WRITE)
    39163939        {
    3917             ahciCopyFromPrdtl(pAhciPort->pDevInsR3, pAhciReq, pvBuf, cbTransfer);
     3940            ahciR3CopyBufferFromPrdtl(pAhciPort->CTX_SUFF(pAhci), pAhciReq, pvBuf, cbTransfer);
    39183941            if (pAhciReq->fFlags & AHCI_REQ_OVERFLOW)
    39193942                return VINF_SUCCESS;
     
    41044127
    41054128                /* Reply with the same amount of data as the real drive. */
    4106                 *pcbData = ahciCopyToPrdtl(pAhciPort->pDevInsR3, pAhciReq, pvBuf, cbTransfer);
     4129                *pcbData = ahciR3CopyBufferToPrdtl(pAhciPort->CTX_SUFF(pAhci), pAhciReq, pvBuf,
     4130                                                   cbTransfer, 0 /* cbSkip */);
    41074131            }
    41084132            else
     
    42954319
    42964320    /* Copy the buffer into the scatter gather list. */
    4297     *pcbData = ahciCopyToPrdtl(pAhciPort->pDevInsR3, pAhciReq, (void *)&aBuf[0], RT_MIN(cbData, max_len));
     4321    *pcbData = ahciR3CopyBufferToPrdtl(pAhciPort->CTX_SUFF(pAhci), pAhciReq, (void *)&aBuf[0],
     4322                                       RT_MIN(cbData, max_len), 0 /* cbSkip */);
    42984323
    42994324    atapiCmdOK(pAhciPort, pAhciReq);
     
    43194344}
    43204345
    4321 static DECLCALLBACK(int) atapiReadSectors2352PostProcess(PAHCIREQ pAhciReq, void **ppvProc, size_t *pcbProc)
     4346static DECLCALLBACK(int) atapiReadSectors2352PostProcess(PAHCIREQ pAhciReq, PRTSGBUF pSgBuf, size_t cbBuf,
     4347                                                         uint32_t offBuf, void **ppvProc, size_t *pcbProc)
    43224348{
    43234349    uint8_t *pbBuf = NULL;
    4324     uint32_t cSectors  = pAhciReq->cbTransfer / 2048;
    4325     uint32_t iATAPILBA = pAhciReq->uOffset / 2048;
    4326     uint8_t *pbBufDst;
    4327     uint8_t *pbBufSrc  = (uint8_t *)pAhciReq->u.Io.DataSeg.pvSeg;
    4328     size_t cbAlloc = pAhciReq->cbTransfer + cSectors * (1 + 11 + 3 + 1 + 288); /* Per sector data like ECC. */
     4350    uint32_t cSectorsOff = offBuf / 2048;
     4351    uint32_t cSectors  = cbBuf / 2048;
     4352    uint32_t iATAPILBA = cSectorsOff + pAhciReq->uOffset / 2048;
     4353    size_t cbAlloc = cbBuf + cSectors * (1 + 11 + 3 + 1 + 288); /* Per sector data like ECC. */
     4354
     4355    AssertReturn((offBuf % 2048 == 0) && (cbBuf % 2048 == 0), VERR_INVALID_STATE);
    43294356
    43304357    pbBuf = (uint8_t *)RTMemAlloc(cbAlloc);
     
    43324359        return VERR_NO_MEMORY;
    43334360
    4334     pbBufDst = pbBuf;
     4361    uint8_t *pbBufDst = pbBuf;
    43354362
    43364363    for (uint32_t i = iATAPILBA; i < iATAPILBA + cSectors; i++)
     
    43454372        *pbBufDst++ = 0x01; /* mode 1 data */
    43464373        /* data */
    4347         memcpy(pbBufDst, pbBufSrc, 2048);
     4374        RTSgBufCopyToBuf(pSgBuf, pbBufDst, 2048);
    43484375        pbBufDst += 2048;
    4349         pbBufSrc += 2048;
    43504376        /* ECC */
    43514377        memset(pbBufDst, 0, 288);
     
    43554381    *ppvProc = pbBuf;
    43564382    *pcbProc = cbAlloc;
    4357 
    43584383    return VINF_SUCCESS;
    43594384}
     
    43724397        case 2352:
    43734398        {
    4374             pAhciReq->u.Io.pfnPostProcess = atapiReadSectors2352PostProcess;
     4399            pAhciReq->pfnPostProcess = atapiReadSectors2352PostProcess;
    43754400            pAhciReq->uOffset = (uint64_t)iATAPILBA * 2048;
    43764401            pAhciReq->cbTransfer = cSectors * 2048;
     
    46164641                    PPDMDEVINS pDevIns = pAhci->CTX_SUFF(pDevIns);
    46174642
    4618                     /*
    4619                      * Also make sure that the current request has no memory allocated
    4620                      * from the driver below us. We don't require it here anyway.
    4621                      */
    4622                     ahciReqMemFree(pAhciPort, pAhciReq, true /* fForceFree */);
    4623 
    46244643                    rc = VMR3ReqPriorityCallWait(PDMDevHlpGetVM(pDevIns), VMCPUID_ANY,
    46254644                                                 (PFNRT)pAhciPort->pDrvMount->pfnUnmount, 3,
     
    54615480
    54625481/**
    5463  * Allocates memory for the given request using already allocated memory if possible.
     5482 * Copy from guest to host memory worker.
    54645483 *
    5465  * @returns Pointer to the memory or NULL on failure
    5466  * @param   pAhciPort   The AHCI port.
    5467  * @param   pAhciReq    The request to allocate memory for.
    5468  * @param   cb          The amount of memory to allocate.
    5469  */
    5470 static void *ahciReqMemAlloc(PAHCIPort pAhciPort, PAHCIREQ pAhciReq, size_t cb)
    5471 {
    5472     if (pAhciReq->cbAlloc > cb)
    5473     {
    5474         pAhciReq->cAllocTooMuch++;
    5475     }
    5476     else if (pAhciReq->cbAlloc < cb)
    5477     {
    5478         if (pAhciReq->cbAlloc)
    5479             pAhciPort->pDrvMedia->pfnIoBufFree(pAhciPort->pDrvMedia, pAhciReq->pvAlloc, pAhciReq->cbAlloc);
    5480 
    5481         pAhciReq->pvAlloc = NULL;
    5482         pAhciReq->cbAlloc = RT_ALIGN_Z(cb, _4K);
    5483         int rc = pAhciPort->pDrvMedia->pfnIoBufAlloc(pAhciPort->pDrvMedia, pAhciReq->cbAlloc, &pAhciReq->pvAlloc);
    5484         if (RT_FAILURE(rc))
    5485             pAhciReq->pvAlloc = NULL;
    5486 
    5487         pAhciReq->cAllocTooMuch = 0;
    5488         if (RT_UNLIKELY(!pAhciReq->pvAlloc))
    5489             pAhciReq->cbAlloc = 0;
    5490     }
    5491 
    5492     return pAhciReq->pvAlloc;
    5493 }
    5494 
    5495 /**
    5496  * Frees memory allocated for the given request.
     5484 * @copydoc{AHCIR3MEMCOPYCALLBACK}
     5485 */
     5486static DECLCALLBACK(void) ahciR3CopyBufferFromGuestWorker(PAHCI pThis, RTGCPHYS GCPhys, PRTSGBUF pSgBuf,
     5487                                                          size_t cbCopy, size_t *pcbSkip)
     5488{
     5489    size_t cbSkipped = RT_MIN(cbCopy, *pcbSkip);
     5490    cbCopy   -= cbSkipped;
     5491    GCPhys   += cbSkipped;
     5492    *pcbSkip -= cbSkipped;
     5493
     5494    while (cbCopy)
     5495    {
     5496        size_t cbSeg = cbCopy;
     5497        void *pvSeg = RTSgBufGetNextSegment(pSgBuf, &cbSeg);
     5498
     5499        AssertPtr(pvSeg);
     5500        PDMDevHlpPhysRead(pThis->CTX_SUFF(pDevIns), GCPhys, pvSeg, cbSeg);
     5501        GCPhys += cbSeg;
     5502        cbCopy -= cbSeg;
     5503    }
     5504}
     5505
     5506/**
     5507 * Copy from host to guest memory worker.
    54975508 *
    5498  * @returns nothing.
    5499  * @param   pAhciPort   The AHCI port.
    5500  * @param   pAhciReq    The request.
    5501  * @param   fForceFree  Flag whether to force a free
    5502  */
    5503 static void ahciReqMemFree(PAHCIPort pAhciPort, PAHCIREQ pAhciReq, bool fForceFree)
    5504 {
    5505     if (   pAhciReq->cAllocTooMuch >= AHCI_MAX_ALLOC_TOO_MUCH
    5506         || fForceFree)
    5507     {
    5508         if (pAhciReq->cbAlloc)
    5509         {
    5510             pAhciPort->pDrvMedia->pfnIoBufFree(pAhciPort->pDrvMedia, pAhciReq->pvAlloc, pAhciReq->cbAlloc);
    5511             pAhciReq->cbAlloc = 0;
    5512             pAhciReq->cAllocTooMuch = 0;
    5513         }
    5514     }
     5509 * @copydoc{AHCIR3MEMCOPYCALLBACK}
     5510 */
     5511static DECLCALLBACK(void) ahciR3CopyBufferToGuestWorker(PAHCI pThis, RTGCPHYS GCPhys, PRTSGBUF pSgBuf,
     5512                                                        size_t cbCopy, size_t *pcbSkip)
     5513{
     5514    size_t cbSkipped = RT_MIN(cbCopy, *pcbSkip);
     5515    cbCopy   -= cbSkipped;
     5516    GCPhys   += cbSkipped;
     5517    *pcbSkip -= cbSkipped;
     5518
     5519    while (cbCopy)
     5520    {
     5521        size_t cbSeg = cbCopy;
     5522        void *pvSeg = RTSgBufGetNextSegment(pSgBuf, &cbSeg);
     5523
     5524        AssertPtr(pvSeg);
     5525        PDMDevHlpPCIPhysWrite(pThis->CTX_SUFF(pDevIns), GCPhys, pvSeg, cbSeg);
     5526        GCPhys += cbSeg;
     5527        cbCopy -= cbSeg;
     5528    }
     5529}
     5530
     5531/**
     5532 * Walks the PRDTL list copying data between the guest and host memory buffers.
     5533 *
     5534 * @returns Amount of bytes copied.
     5535 * @param   pThis          The AHCI controller device instance.
     5536 * @param   pAhciReq       AHCI request structure.
     5537 * @param   pfnCopyWorker  The copy method to apply for each guest buffer.
     5538 * @param   pSgBuf         The host S/G buffer.
     5539 * @param   cbSkip         How many bytes to skip in advance before starting to copy.
     5540 * @param   cbCopy         How many bytes to copy.
     5541 */
     5542static size_t ahciR3PrdtlWalk(PAHCI pThis, PAHCIREQ pAhciReq,
     5543                              PAHCIR3MEMCOPYCALLBACK pfnCopyWorker,
     5544                              PRTSGBUF pSgBuf, size_t cbSkip, size_t cbCopy)
     5545{
     5546    RTGCPHYS GCPhysPrdtl = pAhciReq->GCPhysPrdtl;
     5547    unsigned cPrdtlEntries = pAhciReq->cPrdtlEntries;
     5548    size_t cbCopied = 0;
     5549
     5550    /*
     5551     * Add the amount to skip to the host buffer size to avoid a
     5552     * few conditionals later on.
     5553     */
     5554    cbCopy += cbSkip;
     5555
     5556    AssertMsgReturn(cPrdtlEntries > 0, ("Copying 0 bytes is not possible\n"), 0);
     5557
     5558    do
     5559    {
     5560        SGLEntry aPrdtlEntries[32];
     5561        uint32_t cPrdtlEntriesRead = cPrdtlEntries < RT_ELEMENTS(aPrdtlEntries)
     5562                                   ? cPrdtlEntries
     5563                                   : RT_ELEMENTS(aPrdtlEntries);
     5564
     5565        PDMDevHlpPhysRead(pThis->CTX_SUFF(pDevIns), GCPhysPrdtl, &aPrdtlEntries[0],
     5566                          cPrdtlEntriesRead * sizeof(SGLEntry));
     5567
     5568        for (uint32_t i = 0; (i < cPrdtlEntriesRead) && cbCopy; i++)
     5569        {
     5570            RTGCPHYS GCPhysAddrDataBase = AHCI_RTGCPHYS_FROM_U32(aPrdtlEntries[i].u32DBAUp, aPrdtlEntries[i].u32DBA);
     5571            uint32_t cbThisCopy = (aPrdtlEntries[i].u32DescInf & SGLENTRY_DESCINF_DBC) + 1;
     5572
     5573            cbThisCopy = (uint32_t)RT_MIN(cbThisCopy, cbCopy);
     5574
     5575            /* Copy into SG entry. */
     5576            pfnCopyWorker(pThis, GCPhysAddrDataBase, pSgBuf, cbThisCopy, &cbSkip);
     5577
     5578            cbCopy   -= cbThisCopy;
     5579            cbCopied += cbThisCopy;
     5580        }
     5581
     5582        GCPhysPrdtl   += cPrdtlEntriesRead * sizeof(SGLEntry);
     5583        cPrdtlEntries -= cPrdtlEntriesRead;
     5584    } while (cPrdtlEntries && cbCopy);
     5585
     5586    if (cbCopied < cbCopy)
     5587        pAhciReq->fFlags |= AHCI_REQ_OVERFLOW;
     5588
     5589    return cbCopied;
    55155590}
    55165591
     
    55195594 *
    55205595 * @returns Amount of bytes copied to the PRDTL.
    5521  * @param   pDevIns        Pointer to the device instance data.
     5596 * @param   pThis          The AHCI controller device instance.
    55225597 * @param   pAhciReq       AHCI request structure.
    5523  * @param   pvBuf          The buffer to copy from.
    5524  * @param   cbBuf          The size of the buffer.
    5525  */
    5526 static uint32_t ahciCopyToPrdtl(PPDMDEVINS pDevIns, PAHCIREQ pAhciReq, void const *pvBuf, size_t cbBuf)
    5527 {
    5528     uint8_t const *pbBuf = (uint8_t const *)pvBuf;
    5529     SGLEntry aPrdtlEntries[32];
    5530     RTGCPHYS GCPhysPrdtl = pAhciReq->GCPhysPrdtl;
    5531     unsigned cPrdtlEntries = pAhciReq->cPrdtlEntries;
    5532     uint32_t cbCopied = 0;
    5533 
    5534     AssertMsgReturn(cPrdtlEntries > 0, ("Copying 0 bytes is not possible\n"), 0);
    5535 
    5536     do
    5537     {
    5538         uint32_t cPrdtlEntriesRead = cPrdtlEntries < RT_ELEMENTS(aPrdtlEntries)
    5539                                    ? cPrdtlEntries
    5540                                    : RT_ELEMENTS(aPrdtlEntries);
    5541 
    5542         PDMDevHlpPhysRead(pDevIns, GCPhysPrdtl, &aPrdtlEntries[0], cPrdtlEntriesRead * sizeof(SGLEntry));
    5543 
    5544         for (uint32_t i = 0; (i < cPrdtlEntriesRead) && cbBuf; i++)
    5545         {
    5546             RTGCPHYS GCPhysAddrDataBase = AHCI_RTGCPHYS_FROM_U32(aPrdtlEntries[i].u32DBAUp, aPrdtlEntries[i].u32DBA);
    5547             uint32_t cbThisCopy = (aPrdtlEntries[i].u32DescInf & SGLENTRY_DESCINF_DBC) + 1;
    5548 
    5549             cbThisCopy = (uint32_t)RT_MIN(cbThisCopy, cbBuf);
    5550 
    5551             /* Copy into SG entry. */
    5552             PDMDevHlpPCIPhysWrite(pDevIns, GCPhysAddrDataBase, pbBuf, cbThisCopy);
    5553 
    5554             pbBuf    += cbThisCopy;
    5555             cbBuf    -= cbThisCopy;
    5556             cbCopied += cbThisCopy;
    5557         }
    5558 
    5559         GCPhysPrdtl   += cPrdtlEntriesRead * sizeof(SGLEntry);
    5560         cPrdtlEntries -= cPrdtlEntriesRead;
    5561     } while (cPrdtlEntries && cbBuf);
    5562 
    5563     if (cbCopied < cbBuf)
    5564         pAhciReq->fFlags |= AHCI_REQ_OVERFLOW;
    5565 
    5566     return cbCopied;
     5598 * @param   pSgBuf         The S/G buffer to copy from.
     5599 * @param   cbSkip         How many bytes to skip in advance before starting to copy.
     5600 * @param   cbCopy         How many bytes to copy.
     5601 */
     5602static size_t ahciR3CopySgBufToPrdtl(PAHCI pThis, PAHCIREQ pAhciReq, PRTSGBUF pSgBuf,
     5603                                     size_t cbSkip, size_t cbCopy)
     5604{
     5605    return ahciR3PrdtlWalk(pThis, pAhciReq, ahciR3CopyBufferToGuestWorker,
     5606                           pSgBuf, cbSkip, cbCopy);
    55675607}
    55685608
     
    55705610 * Copies the S/G buffer into a data buffer.
    55715611 *
    5572  * @returns Amount of bytes copied to the PRDTL.
    5573  * @param   pDevIns        Pointer to the device instance data.
     5612 * @returns Amount of bytes copied from the PRDTL.
     5613 * @param   pThis          The AHCI controller device instance.
    55745614 * @param   pAhciReq       AHCI request structure.
    5575  * @param   pvBuf          The buffer to copy to.
    5576  * @param   cbBuf          The size of the buffer.
    5577  */
    5578 static size_t ahciCopyFromPrdtl(PPDMDEVINS pDevIns, PAHCIREQ pAhciReq,
    5579                                 void *pvBuf, size_t cbBuf)
    5580 {
    5581     uint8_t *pbBuf = (uint8_t *)pvBuf;
    5582     SGLEntry aPrdtlEntries[32];
    5583     RTGCPHYS GCPhysPrdtl = pAhciReq->GCPhysPrdtl;
    5584     unsigned cPrdtlEntries = pAhciReq->cPrdtlEntries;
    5585     size_t cbCopied = 0;
    5586 
    5587     AssertMsgReturn(cPrdtlEntries > 0, ("Copying 0 bytes is not possible\n"), 0);
    5588 
    5589     do
    5590     {
    5591         uint32_t cPrdtlEntriesRead =   (cPrdtlEntries < RT_ELEMENTS(aPrdtlEntries))
    5592                                      ? cPrdtlEntries
    5593                                      : RT_ELEMENTS(aPrdtlEntries);
    5594 
    5595         PDMDevHlpPhysRead(pDevIns, GCPhysPrdtl, &aPrdtlEntries[0], cPrdtlEntriesRead * sizeof(SGLEntry));
    5596 
    5597         for (uint32_t i = 0; (i < cPrdtlEntriesRead) && cbBuf; i++)
    5598         {
    5599             RTGCPHYS GCPhysAddrDataBase = AHCI_RTGCPHYS_FROM_U32(aPrdtlEntries[i].u32DBAUp, aPrdtlEntries[i].u32DBA);
    5600             uint32_t cbThisCopy = (aPrdtlEntries[i].u32DescInf & SGLENTRY_DESCINF_DBC) + 1;
    5601 
    5602             cbThisCopy = (uint32_t)RT_MIN(cbThisCopy, cbBuf);
    5603 
    5604             /* Copy into buffer. */
    5605             PDMDevHlpPhysRead(pDevIns, GCPhysAddrDataBase, pbBuf, cbThisCopy);
    5606 
    5607             pbBuf    += cbThisCopy;
    5608             cbBuf    -= cbThisCopy;
    5609             cbCopied += cbThisCopy;
    5610         }
    5611 
    5612         GCPhysPrdtl   += cPrdtlEntriesRead * sizeof(SGLEntry);
    5613         cPrdtlEntries -= cPrdtlEntriesRead;
    5614     } while (cPrdtlEntries && cbBuf);
    5615 
    5616     if (cbCopied < cbBuf)
    5617         pAhciReq->fFlags |= AHCI_REQ_OVERFLOW;
    5618 
    5619     return cbCopied;
    5620 }
    5621 
    5622 /**
    5623  * Allocate I/O memory and copies the guest buffer for writes.
     5615 * @param   pSgBuf         The S/G buffer to copy into.
     5616 * @param   cbSkip         How many bytes to skip in advance before starting to copy.
     5617 * @param   cbCopy         How many bytes to copy.
     5618 */
     5619static size_t ahciR3CopySgBufFromPrdtl(PAHCI pThis, PAHCIREQ pAhciReq, PRTSGBUF pSgBuf,
     5620                                       size_t cbSkip, size_t cbCopy)
     5621{
     5622    return ahciR3PrdtlWalk(pThis, pAhciReq, ahciR3CopyBufferFromGuestWorker,
     5623                           pSgBuf, cbSkip, cbCopy);
     5624}
     5625
     5626/**
     5627 * Copy a simple memory buffer to the guest memory buffer.
    56245628 *
    5625  * @returns VBox status code.
    5626  * @param   pAhciPort   The AHCI port.
    5627  * @param   pAhciReq    The request state.
    5628  * @param   cbTransfer  Amount of bytes to allocate.
    5629  */
    5630 static int ahciIoBufAllocate(PAHCIPort pAhciPort, PAHCIREQ pAhciReq, size_t cbTransfer)
    5631 {
    5632     AssertMsg(   pAhciReq->enmType == PDMMEDIAEXIOREQTYPE_READ
    5633               || pAhciReq->enmType == PDMMEDIAEXIOREQTYPE_WRITE,
    5634               ("Allocating I/O memory for a non I/O request is not allowed\n"));
    5635 
    5636     pAhciReq->u.Io.DataSeg.pvSeg = ahciReqMemAlloc(pAhciPort, pAhciReq, cbTransfer);
    5637     if (!pAhciReq->u.Io.DataSeg.pvSeg)
    5638         return VERR_NO_MEMORY;
    5639 
    5640     pAhciReq->u.Io.DataSeg.cbSeg = cbTransfer;
    5641     if (pAhciReq->enmType == PDMMEDIAEXIOREQTYPE_WRITE)
    5642     {
    5643         ahciCopyFromPrdtl(pAhciPort->pDevInsR3, pAhciReq,
    5644                           pAhciReq->u.Io.DataSeg.pvSeg,
    5645                           cbTransfer);
    5646     }
    5647     return VINF_SUCCESS;
    5648 }
    5649 
    5650 /**
    5651  * Frees the I/O memory of the given request and updates the guest buffer if necessary.
     5629 * @returns Amount of bytes copied from the PRDTL.
     5630 * @param   pThis          The AHCI controller device instance.
     5631 * @param   pAhciReq       AHCI request structure.
     5632 * @param   pvSrc          The buffer to copy from.
     5633 * @param   cbSrc          How many bytes to copy.
     5634 * @param   cbSkip         How many bytes to skip initially.
     5635 */
     5636static size_t ahciR3CopyBufferToPrdtl(PAHCI pThis, PAHCIREQ pAhciReq, const void *pvSrc,
     5637                                      size_t cbSrc, size_t cbSkip)
     5638{
     5639    RTSGSEG Seg;
     5640    RTSGBUF SgBuf;
     5641    Seg.pvSeg = (void *)pvSrc;
     5642    Seg.cbSeg = cbSrc;
     5643    RTSgBufInit(&SgBuf, &Seg, 1);
     5644    return ahciR3CopySgBufToPrdtl(pThis, pAhciReq, &SgBuf, cbSkip, cbSrc);
     5645}
     5646
     5647/**
     5648 * Copy a data from the geust memory buffer into a simple memory buffer.
    56525649 *
    5653  * @returns nothing.
    5654  * @param   pAhciPort    The AHCI port.
    5655  * @param   pAhciReq     The request state.
    5656  * @param   fCopyToGuest Flag whether to update the guest buffer if necessary.
    5657  *                       Nothing is copied if false even if the request was a read.
    5658  */
    5659 static void ahciIoBufFree(PAHCIPort pAhciPort, PAHCIREQ pAhciReq,
    5660                           bool fCopyToGuest)
    5661 {
    5662     AssertMsg(   pAhciReq->enmType == PDMMEDIAEXIOREQTYPE_READ
    5663               || pAhciReq->enmType == PDMMEDIAEXIOREQTYPE_WRITE,
    5664               ("Freeing I/O memory for a non I/O request is not allowed\n"));
    5665 
    5666     if (   pAhciReq->enmType == PDMMEDIAEXIOREQTYPE_READ
    5667         && fCopyToGuest)
    5668     {
    5669         if (pAhciReq->u.Io.pfnPostProcess)
    5670         {
    5671             void *pv = NULL;
    5672             size_t cb = 0;
    5673             int rc = pAhciReq->u.Io.pfnPostProcess(pAhciReq, &pv, &cb);
    5674 
    5675             if (RT_SUCCESS(rc))
    5676             {
    5677                 pAhciReq->cbTransfer = ahciCopyToPrdtl(pAhciPort->pDevInsR3, pAhciReq, pv, cb);
    5678                 RTMemFree(pv);
    5679             }
    5680         }
    5681         else
    5682             ahciCopyToPrdtl(pAhciPort->pDevInsR3, pAhciReq, pAhciReq->u.Io.DataSeg.pvSeg, pAhciReq->u.Io.DataSeg.cbSeg);
    5683     }
    5684 
    5685     ahciReqMemFree(pAhciPort, pAhciReq, false /* fForceFree */);
    5686     pAhciReq->u.Io.DataSeg.pvSeg = NULL;
    5687     pAhciReq->u.Io.DataSeg.cbSeg = 0;
    5688 }
    5689 
     5650 * @returns Amount of bytes copied from the PRDTL.
     5651 * @param   pThis          The AHCI controller device instance.
     5652 * @param   pAhciReq       AHCI request structure.
     5653 * @param   pvDst          The buffer to copy into.
     5654 * @param   cbDst          How many bytes to copy.
     5655 */
     5656static size_t ahciR3CopyBufferFromPrdtl(PAHCI pThis, PAHCIREQ pAhciReq, void *pvDst,
     5657                                        size_t cbDst)
     5658{
     5659    RTSGSEG Seg;
     5660    RTSGBUF SgBuf;
     5661    Seg.pvSeg = pvDst;
     5662    Seg.cbSeg = cbDst;
     5663    RTSgBufInit(&SgBuf, &Seg, 1);
     5664    return ahciR3CopySgBufFromPrdtl(pThis, pAhciReq, &SgBuf, 0 /* cbSkip */, cbDst);
     5665}
    56905666
    56915667/**
     
    58645840                                                   uTag, 0 /* fFlags */);
    58655841    if (RT_SUCCESS(rc))
     5842    {
    58665843        pAhciReq->hIoReq = hIoReq;
     5844        pAhciReq->pfnPostProcess = NULL;
     5845    }
    58675846    else
    58685847        pAhciReq = NULL;
     
    59145893        if (pAhciReq->enmType == PDMMEDIAEXIOREQTYPE_READ)
    59155894        {
    5916             ahciIoBufFree(pAhciPort, pAhciReq, true /* fCopyToGuest */);
    59175895            STAM_REL_COUNTER_ADD(&pAhciPort->StatBytesRead, pAhciReq->cbTransfer);
    59185896            pAhciPort->Led.Actual.s.fReading = 0;
     
    59205898        else if (pAhciReq->enmType == PDMMEDIAEXIOREQTYPE_WRITE)
    59215899        {
    5922             ahciIoBufFree(pAhciPort, pAhciReq, false /* fCopyToGuest */);
    59235900            STAM_REL_COUNTER_ADD(&pAhciPort->StatBytesWritten, pAhciReq->cbTransfer);
    59245901            pAhciPort->Led.Actual.s.fWriting = 0;
     
    60155992        fCanceled = true;
    60165993
    6017         if (pAhciReq->enmType != PDMMEDIAEXIOREQTYPE_FLUSH)
    6018             ahciIoBufFree(pAhciPort, pAhciReq, false /* fCopyToGuest */);
    6019 
    60205994        /* Leave a log message about the canceled request. */
    60215995        if (pAhciPort->cErrors++ < MAX_LOG_REL_ERRORS)
     
    60666040                                                size_t cbCopy)
    60676041{
    6068     RT_NOREF2(pInterface, hIoReq);
     6042    RT_NOREF1(hIoReq);
     6043    PAHCIPort pAhciPort = RT_FROM_MEMBER(pInterface, AHCIPort, IMediaExPort);
    60696044    int rc = VINF_SUCCESS;
    60706045    PAHCIREQ pIoReq = (PAHCIREQ)pvIoReqAlloc;
    60716046
    6072     if (offDst + cbCopy <= pIoReq->u.Io.DataSeg.cbSeg)
    6073     {
    6074         void *pvBuf = (uint8_t *)pIoReq->u.Io.DataSeg.pvSeg + offDst;
    6075         RTSgBufCopyToBuf(pSgBuf, pvBuf, cbCopy);
    6076     }
     6047    if (!pIoReq->pfnPostProcess)
     6048        ahciR3CopySgBufToPrdtl(pAhciPort->CTX_SUFF(pAhci), pIoReq, pSgBuf, offDst, cbCopy);
    60776049    else
     6050    {
     6051        /* Post process data and copy afterwards. */
     6052        void *pv = NULL;
     6053        size_t cb = 0;
     6054        rc = pIoReq->pfnPostProcess(pIoReq, pSgBuf, cbCopy, offDst, &pv, &cb);
     6055        if (RT_SUCCESS(rc))
     6056        {
     6057            ahciR3CopyBufferToPrdtl(pAhciPort->CTX_SUFF(pAhci), pIoReq, pv, cb, offDst);
     6058            RTMemFree(pv);
     6059        }
     6060    }
     6061
     6062    if (pIoReq->fFlags & AHCI_REQ_OVERFLOW)
    60786063        rc = VERR_PDM_MEDIAEX_IOBUF_OVERFLOW;
    60796064
     
    60886073                                              size_t cbCopy)
    60896074{
    6090     RT_NOREF2(pInterface, hIoReq);
     6075    RT_NOREF1(hIoReq);
     6076    PAHCIPort pAhciPort = RT_FROM_MEMBER(pInterface, AHCIPort, IMediaExPort);
    60916077    int rc = VINF_SUCCESS;
    60926078    PAHCIREQ pIoReq = (PAHCIREQ)pvIoReqAlloc;
    60936079
    6094     if (offSrc + cbCopy <= pIoReq->u.Io.DataSeg.cbSeg)
    6095     {
    6096         void *pvBuf = (uint8_t *)pIoReq->u.Io.DataSeg.pvSeg + offSrc;
    6097         RTSgBufCopyFromBuf(pSgBuf, pvBuf, cbCopy);
    6098     }
    6099     else
     6080    ahciR3CopySgBufFromPrdtl(pAhciPort->CTX_SUFF(pAhci), pIoReq, pSgBuf, offSrc, cbCopy);
     6081    if (pIoReq->fFlags & AHCI_REQ_OVERFLOW)
    61006082        rc = VERR_PDM_MEDIAEX_IOBUF_UNDERRUN;
    61016083
     
    61726154
    61736155                /* Copy the buffer. */
    6174                 uint32_t cbCopied = ahciCopyToPrdtl(pAhciPort->pDevInsR3, pAhciReq, &u16Temp[0], sizeof(u16Temp));
     6156                uint32_t cbCopied = ahciR3CopyBufferToPrdtl(pAhciPort->CTX_SUFF(pAhci), pAhciReq,
     6157                                                            &u16Temp[0], sizeof(u16Temp), 0 /* cbSkip */);
    61756158
    61766159                pAhciReq->fFlags |= AHCI_REQ_PIO_DATA;
     
    63776360
    63786361                /* Copy the buffer. */
    6379                 uint32_t cbCopied = ahciCopyToPrdtl(pAhciPort->pDevInsR3, pAhciReq, &aBuf[offLogRead], cbLogRead);
     6362                uint32_t cbCopied = ahciR3CopyBufferToPrdtl(pAhciPort->CTX_SUFF(pAhci), pAhciReq,
     6363                                                            &aBuf[offLogRead], cbLogRead, 0 /* cbSkip */);
    63806364
    63816365                pAhciReq->fFlags |= AHCI_REQ_PIO_DATA;
     
    67346718
    67356719                    if (enmType != PDMMEDIAEXIOREQTYPE_INVALID)
    6736                     {
    6737                         if (   enmType != PDMMEDIAEXIOREQTYPE_FLUSH
    6738                             && enmType != PDMMEDIAEXIOREQTYPE_DISCARD)
    6739                         {
    6740                             STAM_REL_COUNTER_INC(&pAhciPort->StatDMA);
    6741 
    6742                             rc = ahciIoBufAllocate(pAhciPort, pAhciReq, pAhciReq->cbTransfer);
    6743                             if (RT_FAILURE(rc))
    6744                             {
    6745                                 /* In case we can't allocate enough memory fail the request with an overflow error. */
    6746                                 AssertMsgFailed(("%s: Failed to process command %Rrc\n", __FUNCTION__, rc));
    6747                                 pAhciReq->fFlags |= AHCI_REQ_OVERFLOW;
    6748                             }
    6749                         }
    6750 
    6751                         if (!(pAhciReq->fFlags & AHCI_REQ_OVERFLOW))
    6752                             fReqCanceled = ahciR3ReqSubmit(pAhciPort, pAhciReq, enmType);
    6753                         else /* Overflow is handled in completion routine. */
    6754                             fReqCanceled = ahciTransferComplete(pAhciPort, pAhciReq, VINF_SUCCESS);
    6755                     }
     6720                        fReqCanceled = ahciR3ReqSubmit(pAhciPort, pAhciReq, enmType);
    67566721                    else
    67576722                        fReqCanceled = ahciTransferComplete(pAhciPort, pAhciReq, VINF_SUCCESS);
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