VirtualBox

Changeset 80383 in vbox for trunk/src/VBox/Devices/VirtIO


Ignore:
Timestamp:
Aug 22, 2019 7:25:38 AM (5 years ago)
Author:
vboxsync
Message:

Storage/DevVirtioSCSI.cpp: Got notification and initial worker thread scheme implemented. Structured queue transition into device code, and reading and parsing controlq header and request queue header. See bugref:9440 Comment 56 for more information.

Location:
trunk/src/VBox/Devices/VirtIO
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Devices/VirtIO/Virtio_1_0.cpp

    r80340 r80383  
    2828#include <iprt/mem.h>
    2929#include <iprt/assert.h>
     30#include <iprt/sg.h>
    3031#include <VBox/vmm/pdmdev.h>
    3132#include "Virtio_1_0_impl.h"
     
    3536
    3637#ifdef LOG_ENABLED
    37 # define QUEUENAME(s, q) (q->szName)
     38# define QUEUENAME(s, q) (q->szVirtqName)
    3839#endif
    3940
     
    9394}
    9495
     96/**
     97 * See API comments in header file for description
     98 */
    9599int virtioQueueAttach(VIRTIOHANDLE hVirtio, uint16_t qIdx, const char *pcszName)
    96100{
     
    98102    PVIRTIOSTATE pVirtio = (PVIRTIOSTATE)hVirtio;
    99103    PVIRTQ_PROXY_T pVirtqProxy = &(pVirtio->virtqProxy[qIdx]);
    100     if (pVirtio->uQueueEnable[qIdx])
    101     {
    102         pVirtqProxy->pBufVec = (PVIRTQ_BUF_VECTOR_T)RTMemAllocZ(sizeof(PVIRTQ_BUF_VECTOR_T));
    103         if (!pVirtqProxy->pBufVec)
    104         {
    105             Log(("Out of memory!"));
    106             return VERR_NO_MEMORY;
    107         }
    108         pVirtqProxy->uAvailIdx = 0;
    109         pVirtqProxy->uUsedIdx  = 0;
    110         pVirtqProxy->fEventThresholdReached = false;
    111         RTStrCopy((char *)pVirtqProxy->szName, sizeof(pVirtqProxy->szName), pcszName);
    112         return VINF_SUCCESS;
    113     }
    114     LogFunc(("Couldn't attach to %s: Not enabled\n", pcszName));
    115     return VERR_INVALID_STATE;
    116 }
    117 
    118 PVIRTQ_BUF_VECTOR_T virtioQueueGetBuffer(VIRTIOHANDLE hVirtio, uint16_t qIdx)
    119 {
    120     PVIRTIOSTATE pVirtio = (PVIRTIOSTATE)hVirtio;
    121     if (pVirtio->uDeviceStatus & VIRTIO_STATUS_DRIVER_OK)
    122     {
    123         PVIRTQ_PROXY_T pVirtqProxy = &pVirtio->virtqProxy[qIdx];
    124         return pVirtqProxy->pBufVec;
    125     }
    126     LogFunc(("Can't get buffer, driver not ready\n"));
    127     return NULL;
    128 }
    129 
     104    pVirtqProxy->pDescChain = (PVIRTQ_DESC_CHAIN_T)RTMemAllocZ(sizeof(VIRTQ_DESC_CHAIN_T));
     105    if (!pVirtqProxy->pDescChain)
     106    {
     107        Log(("Out of memory!"));
     108        return VERR_NO_MEMORY;
     109    }
     110    pVirtqProxy->uAvailIdx = 0;
     111    pVirtqProxy->uUsedIdx  = 0;
     112    pVirtqProxy->fEventThresholdReached = false;
     113    RTStrCopy((char *)pVirtqProxy->szVirtqName, sizeof(pVirtqProxy->szVirtqName), pcszName);
     114    return VINF_SUCCESS;
     115
     116}
     117
     118/**
     119 * See API comments in header file for description
     120 */
    130121const char *virtioQueueGetName(VIRTIOHANDLE hVirtio, uint16_t qIdx)
    131122{
     
    134125                    ("Guest driver not in ready state.\n"), "<null>");
    135126
    136     return (const char *)((PVIRTIOSTATE)hVirtio)->virtqProxy[qIdx].szName;
    137 }
    138 
     127    return (const char *)((PVIRTIOSTATE)hVirtio)->virtqProxy[qIdx].szVirtqName;
     128}
     129
     130/**
     131 * See API comments in header file for description
     132 */
    139133int virtioQueueSkip(VIRTIOHANDLE hVirtio, uint16_t qIdx)
    140134{
     
    150144        return VERR_NOT_AVAILABLE;
    151145
    152     Log2Func(("%s: %s avail_idx=%u\n", INSTANCE(pVirtio),
    153           pVirtqProxy->szName, pVirtqProxy->uAvailIdx));
     146    Log2Func(("%s avail_idx=%u\n", pVirtqProxy->szVirtqName, pVirtqProxy->uAvailIdx));
    154147    pVirtqProxy->uAvailIdx++;
    155148
     
    157150}
    158151
     152
     153/**
     154 * See API comments in header file for description
     155 */
     156uint64_t virtioGetNegotiatedFeatures(VIRTIOHANDLE hVirtio)
     157{
     158    PVIRTIOSTATE pVirtio = (PVIRTIOSTATE)hVirtio;
     159    return pVirtio->uDriverFeatures;
     160}
     161
     162
     163/**
     164 * See API comments in header file for description
     165 */
    159166bool virtioQueueIsEmpty(VIRTIOHANDLE hVirtio, uint16_t qIdx)
    160167{
     
    163170}
    164171
    165 int virtioQueuePeek(VIRTIOHANDLE hVirtio, uint16_t qIdx)
    166 {
    167     return virtioQueueGet(hVirtio, qIdx, false /* fRemove */);
    168 }
    169 
    170  /** See API comments in header file prototype for description */
    171 int virtioQueueGet(VIRTIOHANDLE hVirtio, uint16_t qIdx, bool fRemove)
     172/**
     173 * See API comments in header file for description
     174 */
     175int virtioQueuePeek(VIRTIOHANDLE hVirtio, uint16_t qIdx, PPRTSGBUF ppInSegs, PPRTSGBUF ppOutSegs)
     176{
     177    return virtioQueueGet(hVirtio, qIdx, false /* fRemove */, ppInSegs, ppOutSegs);
     178}
     179
     180 /*/**
     181 * See API comments in header file for description
     182 */
     183int virtioQueueGet(VIRTIOHANDLE hVirtio, uint16_t qIdx, bool fRemove,
     184                PPRTSGBUF ppInSegs, PPRTSGBUF ppOutSegs)
    172185{
    173186    PVIRTIOSTATE pVirtio = (PVIRTIOSTATE)hVirtio;
    174187    PVIRTQ_PROXY_T pVirtqProxy = &pVirtio->virtqProxy[qIdx];
    175     PVIRTQ_BUF_VECTOR_T pBufVec = pVirtqProxy->pBufVec;
     188    PVIRTQ_DESC_CHAIN_T pDescChain = pVirtqProxy->pDescChain;
    176189
    177190    AssertMsgReturn(DRIVER_OK(pVirtio) && pVirtio->uQueueEnable[qIdx],
     
    181194        return VERR_NOT_AVAILABLE;
    182195
    183     pBufVec->cSegsIn = pBufVec->cSegsOut = 0;
    184 
    185     Log2Func(("%s avail_idx=%u\n", INSTANCE(pVirtio), pVirtqProxy->szName, pVirtqProxy->uAvailIdx));
    186 
    187     uint16_t uDescIdx;
    188 //    pBufVec->uDescIdx = uDescIdx = vqReadAvailRingDescIdx(pVirtio, qIdx, pVirtqProxy->uAvailIdx);
     196    pDescChain->cSegsIn = pDescChain->cSegsOut = 0;
     197
     198
     199    pDescChain->uHeadIdx = vqReadAvailRingDescIdx(pVirtio, qIdx, pVirtqProxy->uAvailIdx);
     200    uint16_t uDescIdx = pDescChain->uHeadIdx;
     201
     202    Log2Func(("%s DESC CHAIN: (head) desc_idx=%u [avail_idx=%u]\n",
     203            pVirtqProxy->szVirtqName, pDescChain->uHeadIdx, pVirtqProxy->uAvailIdx));
    189204
    190205    if (fRemove)
     
    194209    do
    195210    {
    196         VIRTQ_SEG_T *pSeg;
     211        RTSGSEG *pSeg;
    197212
    198213        /**
     
    202217        * the following aborts I/O if breach and employs a simple log throttling algorithm to notify.
    203218        */
    204         if (pBufVec->cSegsIn + pBufVec->cSegsOut >= VIRTQ_MAX_SIZE)
     219        if (pDescChain->cSegsIn + pDescChain->cSegsOut >= VIRTQ_MAX_SIZE)
    205220        {
    206221            static volatile uint32_t s_cMessages  = 0;
     
    208223            if (ASMAtomicIncU32(&s_cMessages) == ASMAtomicReadU32(&s_cThreshold))
    209224            {
    210                 LogRel(("%s: too many linked descriptors; "
    211                         "check if the guest arranges descriptors in a loop.\n",
    212                            INSTANCE(pVirtio)));
     225                LogRel(("too many linked descriptors; "
     226                        "check if the guest arranges descriptors in a loop.\n"));
    213227                if (ASMAtomicReadU32(&s_cMessages) != 1)
    214                     LogRel(("%s: (the above error has occured %u times so far)\n",
    215                             INSTANCE(pVirtio), ASMAtomicReadU32(&s_cMessages)));
     228                    LogRel(("(the above error has occured %u times so far)\n",
     229                            ASMAtomicReadU32(&s_cMessages)));
    216230                ASMAtomicWriteU32(&s_cThreshold, ASMAtomicReadU32(&s_cThreshold) * 10);
    217231            }
     
    220234        RT_UNTRUSTED_VALIDATED_FENCE();
    221235
    222 //        vqReadDesc(pVirtio, qIdx, uDescIdx, &desc);
     236        vqReadDesc(pVirtio, qIdx, uDescIdx, &desc);
     237
    223238        if (desc.fFlags & VIRTQ_DESC_F_WRITE)
    224239        {
    225             Log2Func(("%s: %s IN  seg=%u desc_idx=%u addr=%RTp cb=%u\n", INSTANCE(pVirtio),
    226                   pVirtqProxy->szName, pBufVec->cSegsIn, uDescIdx, desc.pGcPhysBuf, desc.cb));
    227             pSeg = &(pBufVec->aSegsIn[pBufVec->cSegsIn++]);
     240            Log2Func(("%*s IN  desc_idx=%u seg=%u addr=%RGp cb=%u\n",
     241                RTStrNLen(pVirtqProxy->szVirtqName, sizeof(pVirtqProxy->szVirtqName)), "",
     242                uDescIdx, pDescChain->cSegsIn, desc.pGcPhysBuf, desc.cb));
     243
     244            pSeg = &(pDescChain->aSegsIn[pDescChain->cSegsIn++]);
    228245        }
    229246        else
    230247        {
    231             Log2Func(("%s: %s IN  seg=%u desc_idx=%u addr=%RTp cb=%u\n", INSTANCE(pVirtio),
    232                   pVirtqProxy->szName, pBufVec->cSegsOut, uDescIdx, desc.pGcPhysBuf, desc.cb));
    233             pSeg = &(pBufVec->aSegsOut[pBufVec->cSegsOut++]);
    234         }
    235 
    236         pSeg->addr = (RTGCPHYS)desc.pGcPhysBuf;
    237         pSeg->cb   = desc.cb;
    238         pSeg->pv   = NULL;
     248            Log2Func(("%*s OUT desc_idx=%u seg=%u addr=%RGp cb=%u\n",
     249                RTStrNLen(pVirtqProxy->szVirtqName, sizeof(pVirtqProxy->szVirtqName)), "",
     250                uDescIdx, pDescChain->cSegsOut, desc.pGcPhysBuf, desc.cb));
     251            pSeg = &(pDescChain->aSegsOut[pDescChain->cSegsOut++]);
     252        }
     253
     254        pSeg->pvSeg = (void *)desc.pGcPhysBuf;
     255        pSeg->cbSeg = desc.cb;
    239256
    240257        uDescIdx = desc.uDescIdxNext;
    241258    } while (desc.fFlags & VIRTQ_DESC_F_NEXT);
    242259
    243     Log2Func(("%s: %s head_desc_idx=%u nIn=%u nOut=%u\n", INSTANCE(pVirtio),
    244           pVirtqProxy->szName, pBufVec->uDescIdx, pBufVec->cSegsIn, pBufVec->cSegsOut));
     260    RTSgBufInit(&pVirtqProxy->inSgBuf, (PCRTSGSEG)&pDescChain->aSegsIn,  pDescChain->cSegsIn);
     261    RTSgBufInit(&pVirtqProxy->outSgBuf,(PCRTSGSEG)&pDescChain->aSegsOut, pDescChain->cSegsOut);
     262
     263    *ppInSegs  = &pVirtqProxy->inSgBuf;
     264    *ppOutSegs = &pVirtqProxy->outSgBuf;
     265
     266    Log2Func(("%*s -- segs out: %u,  segs in: %u --\n",
     267              RTStrNLen(pVirtqProxy->szVirtqName, sizeof(pVirtqProxy->szVirtqName)), "",
     268              pDescChain->cSegsOut, pDescChain->cSegsIn));
    245269
    246270    return VINF_SUCCESS;
     
    254278    PVIRTIOSTATE pVirtio = (PVIRTIOSTATE)hVirtio;
    255279    PVIRTQ_PROXY_T pVirtqProxy = &pVirtio->virtqProxy[qIdx];
    256     PVIRTQ_BUF_VECTOR_T pBufVec = pVirtqProxy->pBufVec;
     280    PVIRTQ_DESC_CHAIN_T pDescChain = pVirtqProxy->pDescChain;
    257281
    258282    AssertMsgReturn(DRIVER_OK(pVirtio) && pVirtio->uQueueEnable[qIdx],
    259283                    ("Guest driver not in ready state.\n"), VERR_INVALID_STATE);
    260284
    261     Log2Func(("%s: %s desc_idx=%u acb=%u\n",
    262              INSTANCE(pVirtio), pVirtqProxy->szName, pBufVec->uDescIdx, pBufVec->cSegsIn));
    263 
    264     uint32_t cbRemaining = pBufVec->cSegsIn;
    265 
    266     for (uint32_t iSeg = 0; iSeg < pBufVec->cSegsIn && cbRemaining > 0; ++iSeg)
    267     {
    268         uint32_t cbSegLen = pBufVec->aSegsIn[iSeg].cb;
     285    Log2Func(("%s desc_idx=%u acb=%u\n",
     286             pVirtqProxy->szVirtqName, pDescChain->uHeadIdx, pDescChain->cSegsIn));
     287
     288    uint32_t cbRemaining = pDescChain->cSegsIn;
     289
     290    for (uint32_t iSeg = 0; iSeg < pDescChain->cSegsIn && cbRemaining > 0; ++iSeg)
     291    {
     292        uint32_t cbSegLen = pDescChain->aSegsIn[iSeg].cbSeg;
    269293        if (cbSegLen > cbRemaining)   // last segment only partially used?
    270294            cbSegLen = cbRemaining;
    271295
    272 
    273         if (pBufVec->aSegsIn[iSeg].pv != NULL)
    274         {
    275             Log2Func(("%s: %s used_idx=%u seg=%u addr=%p pv=%p cb=%u acb=%u\n",
    276                      INSTANCE(pVirtio), pVirtqProxy->szName,
    277                      pVirtqProxy->uUsedIdx, iSeg,
    278                      (void *)pBufVec->aSegsIn[iSeg].addr, pBufVec->aSegsIn[iSeg].pv,
    279                      pBufVec->aSegsIn[iSeg].cb, cbSegLen));
    280 
    281             PDMDevHlpPCIPhysWrite(pVirtio->CTX_SUFF(pDevIns),
    282                  pBufVec->aSegsIn[iSeg].addr, pBufVec->aSegsIn[iSeg].pv, cbSegLen);
    283         }
     296//        if (pDescChain->aSegsIn[iSeg].pv != NULL)
     297//        {
     298//            Log2Func(("%s used_idx=%u seg=%u addr=%p cb=%u acb=%u\n",
     299//                     pVirtqProxy->szVirtqName,
     300//                     pVirtqProxy->uUsedIdx, iSeg,
     301//                     (void *)pDescChain->aSegsIn[iSeg].addr,
     302//                     pDescChain->aSegsIn[iSeg].cbSeg, cbSegLen));
     303//
     304//            PDMDevHlpPCIPhysWrite(pVirtio->CTX_SUFF(pDevIns),
     305//                 pDescChain->aSegsIn[iSeg].pvSeg, pDescChain->aSegsIn[iSeg].pv, cbSegLen);
     306//        }
    284307        cbRemaining -= cbSegLen;
    285308    }
    286309
    287310    uint16_t uDescIdx = vqReadUsedDescIdx(pVirtio, qIdx);
    288     Log2Func(("%s: %s used_idx=%u guest_used_idx=%u id=%u len=%u\n",
    289           INSTANCE(pVirtio), pVirtqProxy->szName,
    290           pVirtqProxy->uUsedIdx, uDescIdx, pBufVec->uDescIdx, pBufVec->cSegsIn));
     311    Log2Func(("%s used_idx=%u guest_used_idx=%u id=%u len=%u\n",
     312          pVirtqProxy->szVirtqName,
     313          pVirtqProxy->uUsedIdx, uDescIdx, pDescChain->uHeadIdx, pDescChain->cSegsIn));
    291314
    292315    if (pVirtqProxy->uUsedIdx == vqReadAvailUsedEvent(pVirtio, qIdx))
    293316        pVirtqProxy->fEventThresholdReached = true;
    294     vqWriteUsedElem(pVirtio, qIdx, pVirtqProxy->uUsedIdx++, pBufVec->uDescIdx,  pBufVec->cSegsIn);
     317    vqWriteUsedElem(pVirtio, qIdx, pVirtqProxy->uUsedIdx++, pDescChain->uHeadIdx,  pDescChain->cSegsIn);
    295318
    296319    return VINF_SUCCESS;
    297320}
    298321
    299  /** See API comments in header file prototype for description */
     322/**
     323 * See API comments in header file for description
     324 */
    300325int virtioQueueSync(VIRTIOHANDLE hVirtio, uint16_t qIdx)
    301326{
     
    309334
    310335    uint16_t uDescIdx = vqReadUsedDescIdx(pVirtio, qIdx);
    311     Log2Func(("%s: %s old_used_idx=%u new_used_idx=%u\n",
    312               INSTANCE(pVirtio), uDescIdx, pVirtqProxy->uUsedIdx));
     336    Log2Func(("%s old_used_idx=%u new_used_idx=%u\n",
     337              uDescIdx, pVirtqProxy->uUsedIdx));
    313338
    314339    vqWriteUsedRingDescIdx(pVirtio, qIdx, pVirtqProxy->uUsedIdx);
     
    318343}
    319344
    320  /** See API comments in header file prototype for description */
     345/**
     346 * See API comments in header file for description
     347 */
    321348static void virtioQueueNotified(PVIRTIOSTATE pVirtio, uint16_t qIdx, uint16_t uNotifyIdx)
    322349{
     
    324351
    325352    PVIRTQ_PROXY_T pVirtqProxy = &pVirtio->virtqProxy[qIdx];
    326     Log2Func(("%s: %s notified\n", INSTANCE(pVirtio), pVirtqProxy->szName));
     353    Log2Func(("%s\n", pVirtqProxy->szVirtqName));
    327354
    328355    /** Inform client */
     
    343370                    ("Guest driver not in ready state.\n"));
    344371
    345     LogFlowFunc(("%s: %s availFlags=%x guestFeatures=%x virtioQueue is %sempty\n",
    346         INSTANCE(pVirtio), pVirtqProxy->szName, vqReadAvailFlags(pVirtio, qIdx),
     372    LogFlowFunc(("%s availFlags=%x guestFeatures=%x virtioQueue is %sempty\n",
     373        pVirtqProxy->szVirtqName, vqReadAvailFlags(pVirtio, qIdx),
    347374            pVirtio->uDriverFeatures, vqIsEmpty(pVirtio, qIdx) ? "" : "not "));
    348375
     
    390417    RT_NOREF(offDelta);
    391418    PVIRTIOSTATE pVirtio = *PDMINS_2_DATA(pDevIns, PVIRTIOSTATE *);
    392     LogFunc(("%s\n", INSTANCE(pVirtio)));
     419    LogFunc(("\n"));
    393420
    394421    pVirtio->pDevInsR3 = pDevIns;
     
    406433{
    407434   if (uCause == VIRTIO_ISR_VIRTQ_INTERRUPT)
    408        LogFlowFunc(("%s: Cause: queue interrupt\n", INSTANCE(pVirtio)));
     435       LogFlowFunc(("Cause: queue interrupt\n"));
    409436   else
    410437   if (uCause == VIRTIO_ISR_DEVICE_CONFIG)
    411        LogFlowFunc(("%s: Cause: device config\n", INSTANCE(pVirtio)));
     438       LogFlowFunc(("Cause: device config\n"));
    412439
    413440    pVirtio->uISR |= uCause;
     
    423450static void virtioLowerInterrupt(PVIRTIOSTATE pVirtio)
    424451{
    425     LogFlowFunc(("%s\n", INSTANCE(pVirtio)));
     452    LogFlowFunc(("\n"));
    426453    PDMDevHlpPCISetIrq(pVirtio->CTX_SUFF(pDevIns), 0, 0);
    427454}
     
    713740        {
    714741            ++pVirtio->uConfigGeneration;
    715             Log2Func(("Bumped cfg. generation to %d because %s %s\n",
     742            Log2Func(("Bumped cfg. generation to %d because %s%s\n",
    716743                pVirtio->uConfigGeneration,
    717744                fDevSpecificFieldChanged ? "<dev cfg changed> " : "",
     
    10241051    pVirtio->pDevSpecificCfg  = pDevSpecificCfg;
    10251052
    1026     pVirtio->pPrevDevSpecificCfg = RTMemAlloc(cbDevSpecificCfg);
     1053    pVirtio->pPrevDevSpecificCfg = RTMemAllocZ(cbDevSpecificCfg);
    10271054    if (!pVirtio->pPrevDevSpecificCfg)
    10281055    {
     
    11311158     * VirtIO 1.0 spec says 8-bit, unaligned in MMIO space. Example/diagram
    11321159     * of spec shows it as a 32-bit field with upper bits 'reserved'
    1133      * Will take spec words very literally for now and check linux driver.
     1160     * Will take spec words more literally than the diagram for now.
    11341161     */
    11351162    pCfg = (PVIRTIO_PCI_CAP_T)&pVirtio->dev.abConfig[pCfg->uCapNext];
     
    12011228     *  out size, so pad with an extra page */
    12021229
    1203     rc = PDMDevHlpPCIIORegionRegister(pDevIns, VIRTIOSCSI_REGION_PCI_CAP,  RT_ALIGN_32(cbRegion + 4096, 4096),
     1230    rc = PDMDevHlpPCIIORegionRegister(pDevIns, VIRTIOSCSI_REGION_PCI_CAP,  RT_ALIGN_32(cbRegion + 0x1000, 0x1000),
    12041231                                      PCI_ADDRESS_SPACE_MEM, virtioR3Map);
    12051232    if (RT_FAILURE(rc))
     
    12531280    {
    12541281        Log2Func(("%s queue:\n",
    1255                   "  virtqProxy[%u].uAvailIdx   = %u\n  virtqProxy[%u].uUsedIdx    = %u\n"
     1282                  "  virtqProxy[%u].uAvailIdx    = %u\n  virtqProxy[%u].uUsedIdx    = %u\n"
    12561283                  "  uQueueSize[%u]              = %u\n  uQueueNotifyOff[%u]         = %04x\n"
    12571284                  "  uQueueMsixVector[%u]        = %04x\n  uQueueEnable[%u]            = %04x\n"
    12581285                  "  pGcPhysQueueDesc[%u]        = %RGp\n  pGcPhysQueueAvail[%u]       = %RGp\n"
    12591286                  "  pGcPhysQueueUsed[%u]        = %RGp\n",
    1260                         i, pVirtio->virtqProxy[i].szName, i, pVirtio->virtqProxy[i].uAvailIdx,
     1287                        i, pVirtio->virtqProxy[i].szVirtqName, i, pVirtio->virtqProxy[i].uAvailIdx,
    12611288                        i, pVirtio->virtqProxy[i].uUsedIdx, i, pVirtio->uQueueSize[i],
    12621289                        i, pVirtio->uQueueNotifyOff[i],i, pVirtio->uQueueMsixVector[i],
     
    13191346        rc = SSMR3PutU16(pSSM,      pVirtio->virtqProxy[i].uAvailIdx);
    13201347        rc = SSMR3PutU16(pSSM,      pVirtio->virtqProxy[i].uUsedIdx);
    1321         rc = SSMR3PutMem(pSSM,      pVirtio->virtqProxy[i].szName, 32);
     1348        rc = SSMR3PutMem(pSSM,      pVirtio->virtqProxy[i].szVirtqName, 32);
    13221349    }
    13231350
     
    13781405            rc = SSMR3GetU16(pSSM,      &pVirtio->virtqProxy[i].uAvailIdx);
    13791406            rc = SSMR3GetU16(pSSM,      &pVirtio->virtqProxy[i].uUsedIdx);
    1380             rc = SSMR3GetMem(pSSM,      (void *)&pVirtio->virtqProxy[i].szName, 32);
     1407            rc = SSMR3GetMem(pSSM,      (void *)&pVirtio->virtqProxy[i].szVirtqName, 32);
    13811408        }
    13821409    }
  • trunk/src/VBox/Devices/VirtIO/Virtio_1_0.h

    r80340 r80383  
    2323
    2424#include <iprt/ctype.h>
     25#include <iprt/sg.h>
    2526
    2627typedef void * VIRTIOHANDLE;                                     /**< Opaque handle to the VirtIO framework */
    2728
    28 #define DISABLE_GUEST_DRIVER 0
    2929
    3030/**
     
    3737#define VIRTQ_MAX_SIZE                      1024                 /**< Max size (# desc elements) of a virtq    */
    3838#define VIRTQ_MAX_CNT                       24                   /**< Max queues we allow guest to create      */
    39 #define VIRTQ_DESC_MAX_SIZE                 (2 * 1024 * 1024)
     39
    4040#define VIRTIO_NOTIFY_OFFSET_MULTIPLIER     2                    /**< VirtIO Notify Cap. MMIO config param     */
    4141#define VIRTIOSCSI_REGION_MEM_IO            0                    /**< BAR for MMIO (implementation specific)   */
    4242#define VIRTIOSCSI_REGION_PORT_IO           1                    /**< BAR for PORT I/O (impl specific)         */
    4343#define VIRTIOSCSI_REGION_PCI_CAP           2                    /**< BAR for VirtIO Cap. MMIO (impl specific) */
    44 typedef struct VIRTQ_SEG                                         /**< Describes one segment of a buffer vector */
    45 {
    46     RTGCPHYS addr;                                               /**< Physical addr. of this segment's buffer  */
    47     void    *pv;                                                 /**< Buf to hold value to write or read       */
    48     uint32_t cb;                                                 /**< Number of bytes to write or read         */
    49 } VIRTQ_SEG_T;
    50 
    51     typedef struct VIRTQ_BUF_VECTOR                                  /**< Scatter/gather buffer vector             */
    52 {
    53     uint32_t    uDescIdx;                                        /**< Desc at head of this vector list         */
    54     uint32_t    cSegsIn;                                         /**< Count of segments in aSegsIn[]           */
    55     uint32_t    cSegsOut;                                        /**< Count of segments in aSegsOut[]          */
    56     VIRTQ_SEG_T aSegsIn[VIRTQ_MAX_SIZE];                         /**< List of segments to write to guest       */
    57     VIRTQ_SEG_T aSegsOut[VIRTQ_MAX_SIZE];                        /**< List of segments read from guest         */
    58 } VIRTQ_BUF_VECTOR_T, *PVIRTQ_BUF_VECTOR_T;
    5944
    6045/**
     
    7257    uint16_t  uRevisionId;                                       /**< PCI Cfg Revision ID                      */
    7358    uint16_t  uInterruptLine;                                    /**< PCI Cfg Interrupt line                   */
    74     uint16_t  uInterruptPin;                                     /**< PCI Cfg InterruptPin                     */
     59    uint16_t  uInterruptPin;                                     /**< PCI Cfg Interrupt pin                    */
    7560} VIRTIOPCIPARAMS, *PVIRTIOPCIPARAMS;
    7661
     
    151136 * Allocate client context for client to work with VirtIO-provided with queue
    152137 * As a side effect creates a buffer vector a client can get a pointer to
    153  * with a call to virtioQueueBufVec()
     138 * with a call to virtioQueueDescChain()
    154139 *
    155140 * @param  hVirtio   - Handle to VirtIO framework
     
    164149 */
    165150int virtioQueueAttach(VIRTIOHANDLE hVirtio, uint16_t qIdx, const char *pcszName);
     151
     152
     153/**
     154 * Get the features VirtIO is running withnow.
     155 *
     156 * @returns Features the guest driver has accepted, finalizing the operational features
     157 *
     158 */
     159uint64_t virtioGetNegotiatedFeatures(VIRTIOHANDLE hVirtio);
     160
    166161/**
    167162 * Detaches from queue and release resources
     
    172167 */
    173168int virtioQueueDetach(VIRTIOHANDLE hVirtio, uint16_t qIdx);
    174 
    175 /**
    176  * Return pointer to buffer vector object associated with queue
    177  *
    178  * @param hVirtio   - Handle for VirtIO framework
    179  * @param qIdx      - Queue number
    180  *
    181  * @returns           Pointer pBufVec if success, else NULL
    182  */
    183 PVIRTQ_BUF_VECTOR_T virtioQueueGetBuffer(VIRTIOHANDLE hVirtio, uint16_t qIdx);
    184169
    185170/**
     
    200185 * @param hVirtio   - Handle for VirtIO framework
    201186 * @param qIdx      - Queue number
     187 * @param ppInSegs  - Address to store pointer to host-to-guest data retrieved from virtq as RTSGBUF
     188 * @param ppOutSegs - Address to store pointer to host-to-guest data retrieved from virtq as RTSGBUF
    202189 *
    203190 * @returns status    VINF_SUCCESS         - Success
    204191 *                    VERR_INVALID_STATE   - VirtIO not in ready state
    205192 */
    206 int virtioQueueGet(VIRTIOHANDLE hVirtio, uint16_t qIdx, bool fRemove);
     193int virtioQueueGet(VIRTIOHANDLE hVirtio, uint16_t qIdx, bool fRemove, PPRTSGBUF ppInSegs, PPRTSGBUF ppOutSegs);
    207194
    208195/**
     
    211198 * @param hVirtio   - Handle for VirtIO framework
    212199 * @param qIdx      - Queue number
     200 * @param ppInSegs  - Address to store pointer to host-to-guest data retrieved from virtq as RTSGBUF
     201 * @param ppOutSegs - Address to store pointer to host-to-guest data retrieved from virtq as RTSGBUF
    213202 *
    214203 * @returns           VINF_SUCCESS         - Success
     
    216205 *                    VERR_NOT_AVAILABLE   - Queue is empty
    217206 */
    218 int virtioQueuePeek(VIRTIOHANDLE hVirtio, uint16_t qIdx);
     207int virtioQueuePeek(VIRTIOHANDLE hVirtio, uint16_t qIdx, PPRTSGBUF ppInSegs, PPRTSGBUF ppOutSegs);
    219208
    220209/**
  • trunk/src/VBox/Devices/VirtIO/Virtio_1_0_impl.h

    r80340 r80383  
    5959#define VIRTIO_STATUS_DEVICE_NEEDS_RESET             0x40        /**< Device experienced unrecoverable error    */
    6060
    61 /* @def Virtio Device PCI Capabilities type codes */
     61/** @def Virtio Device PCI Capabilities type codes */
    6262#define VIRTIO_PCI_CAP_COMMON_CFG                       1        /**< Common configuration PCI capability ID    */
    6363#define VIRTIO_PCI_CAP_NOTIFY_CFG                       2        /**< Notification area PCI capability ID       */
     
    8585
    8686/**
     87 * Translation of the descriptor chain associated with one element of virtq avail ring into its
     88 * IN and OUT components and represented as respective arrays of SG segments.
     89 */
     90typedef struct VIRTQ_DESC_CHAIN                                  /**< Describes a single queue element          */
     91{
     92    RTSGSEG     aSegsIn[VIRTQ_MAX_SIZE];                         /**< List of segments to write to guest        */
     93    RTSGSEG     aSegsOut[VIRTQ_MAX_SIZE];                        /**< List of segments read from guest          */
     94    uint32_t    uHeadIdx;                                        /**< Index at head desc (source of seg arrays) */
     95    uint32_t    cSegsIn;                                         /**< Count of segments in aSegsIn[]            */
     96    uint32_t    cSegsOut;                                        /**< Count of segments in aSegsOut[]           */
     97} VIRTQ_DESC_CHAIN_T, *PVIRTQ_DESC_CHAIN_T;
     98
     99/**
    87100 * Local implementation's usage context of a queue (e.g. not part of VirtIO specification)
    88101 */
    89102typedef struct VIRTQ_PROXY
    90103{
    91     const char          szName[32];                              /**< Dev-specific name of queue                */
    92     PVIRTQ_BUF_VECTOR_T pBufVec;                                 /**< Per-queue s/g data. Serialize access!     */
    93     uint16_t            uAvailIdx;                               /**< Consumer's position in avail ring         */
    94     uint16_t            uUsedIdx;                                /**< Consumer's position in used ring          */
    95     bool                fEventThresholdReached;                  /**< Don't lose track while queueing ahead     */
     104    RTSGBUF     inSgBuf;                                         /**< host-to-guest buffers                     */
     105    RTSGBUF     outSgBuf;                                        /**< guest-to-host buffers                     */
     106    const char  szVirtqName[32];                                 /**< Dev-specific name of queue                */
     107    uint16_t    uAvailIdx;                                       /**< Consumer's position in avail ring         */
     108    uint16_t    uUsedIdx;                                        /**< Consumer's position in used ring          */
     109    bool        fEventThresholdReached;                          /**< Don't lose track while queueing ahead     */
     110    PVIRTQ_DESC_CHAIN_T pDescChain;                              /**< Per-queue s/g data.                       */
    96111} VIRTQ_PROXY_T, *PVIRTQ_PROXY_T;
    97112
     
    107122    uint32_t  uDeviceFeatures;                                   /**< RO (device reports features to driver)    */
    108123    uint32_t  uDriverFeaturesSelect;                             /**< RW (driver selects driver features)       */
    109     uint32_t  uDriverFeatures;                                   /**< RW (driver accepts device features)       */
     124    uint32_t  uDriverFeatures;                                   /**< RW (driver-accepted device features)      */
    110125    uint16_t  uMsixConfig;                                       /**< RW (driver sets MSI-X config vector)      */
    111126    uint16_t  uNumQueues;                                        /**< RO (device specifies max queues)          */
    112     uint8_t   uDeviceStatus;                                     /**< RW (driver writes device status, 0 resets)*/
     127    uint8_t   uDeviceStatus;                                     /**< RW (driver writes device status, 0=reset) */
    113128    uint8_t   uConfigGeneration;                                 /**< RO (device changes when changing configs) */
    114129
     
    136151} VIRTIO_PCI_CFG_CAP_T,   *PVIRTIO_PCI_CFG_CAP_T;
    137152
    138 
    139153/**
    140154 * The core (/common) state of the VirtIO PCI device
     
    146160    PDMPCIDEV                 dev;                               /**< PCI device                                */
    147161    char                      szInstance[16];                    /**< Instance name, e.g. "VIRTIOSCSI0"         */
    148     void *                    pClientContext;                     /**< Client callback returned on callbacks     */
     162    void *                    pClientContext;                    /**< Client callback returned on callbacks     */
    149163
    150164    PPDMDEVINSR3              pDevInsR3;                         /**< Device instance - R3                      */
     
    177191    uint8_t                   uConfigGeneration;                 /**< (MMIO) Device config sequencer       HOST */
    178192
    179     VIRTQ_PROXY_T             virtqProxy[VIRTQ_MAX_CNT];        /**< Local impl-specific queue context         */
     193    VIRTQ_PROXY_T             virtqProxy[VIRTQ_MAX_CNT];         /**< Local impl-specific queue context         */
    180194    VIRTIOCALLBACKS           virtioCallbacks;                   /**< Callback vectors to client                */
    181195
     
    223237    uint16_t  uDescIdx;                                          /**< idx        Index of next free ring slot   */
    224238    uint16_t  auRing[1];                                         /**< ring       Ring: avail drv to dev bufs    */
    225     uint16_t  uUsedEventIdx;                                     /**< used_event (if VIRTQ_USED_F_NO_NOTIFY)    */
     239    uint16_t  uUsedEventIdx;                                     /**< used_event (if VIRTQ_USED_F_EVENT_IDX)    */
    226240} VIRTQ_AVAIL_T, *PVIRTQ_AVAIL_T;
    227241
     
    237251    uint16_t  uDescIdx;                                          /**< idx         Index of next ring slot       */
    238252    VIRTQ_USED_ELEM_T auRing[1];                                 /**< ring        Ring: used dev to drv bufs    */
    239     uint16_t  uAvailEventIdx;                                    /**< avail_event if (VIRTQ_USED_F_NO_NOTIFY)   */
     253    uint16_t  uAvailEventIdx;                                    /**< avail_event if (VIRTQ_USED_F_EVENT_IDX)   */
    240254} VIRTQ_USED_T, *PVIRTQ_USED_T;
    241255
     
    335349 */
    336350
    337 static int         vqIsEventNeeded(uint16_t uEventIdx, uint16_t uDescIdxNew, uint16_t uDescIdxOld);
     351static int         vqIsEventNeeded        (uint16_t uEventIdx, uint16_t uDescIdxNew, uint16_t uDescIdxOld);
    338352static bool        vqIsEmpty              (PVIRTIOSTATE pVirtio, uint16_t qIdx);
    339353static void        vqReadDesc             (PVIRTIOSTATE pVirtio, uint16_t qIdx, uint32_t uDescIdx, PVIRTQ_DESC_T pDesc);
     
    361375
    362376/**
    363  * Accessor for virtq descspVirtio
     377 * Accessor for virtq descriptor
    364378 */
    365379DECLINLINE(void) vqReadDesc(PVIRTIOSTATE pVirtio, uint16_t qIdx, uint32_t uDescIdx, PVIRTQ_DESC_T pDesc)
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