VirtualBox

Changeset 104432 in vbox


Ignore:
Timestamp:
Apr 25, 2024 2:04:47 PM (9 months ago)
Author:
vboxsync
Message:

Virtio/Core: Fixes and descriptor table printing for our debugger's 'info virtionet' bugref:10572 jiraref:VBP-575

Location:
trunk/src/VBox/Devices
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Devices/Network/DevVirtioNet.cpp

    r103416 r104432  
    905905        pHlp->pfnPrintf(pHlp, "    cVirtqs .,................. %d\n",   pThis->cVirtqs);
    906906        pHlp->pfnPrintf(pHlp, "    cWorkers .................. %d\n",   pThis->cWorkers);
    907         pHlp->pfnPrintf(pHlp, "    MMIO mapping name ......... %d\n",   pThisCC->Virtio.szMmioName);
     907        pHlp->pfnPrintf(pHlp, "    MMIO mapping name ......... %s\n",   pThisCC->Virtio.szMmioName);
    908908        pHlp->pfnPrintf(pHlp, "\n");
    909909    }
     
    924924        pHlp->pfnPrintf(pHlp, "    Promiscuous: .............. %s\n",      pThis->fPromiscuous   ? "true" : "false");
    925925        pHlp->pfnPrintf(pHlp, "\n");
    926         pHlp->pfnPrintf(pHlp, "    Default Rx MAC filter: .... %RTmac\n", pThis->rxFilterMacDefault);
     926        pHlp->pfnPrintf(pHlp, "    Default Rx MAC filter: .... %RTmac\n", &pThis->rxFilterMacDefault);
    927927        pHlp->pfnPrintf(pHlp, "\n");
    928928
     
    36363636     */
    36373637    char szTmp[128];
    3638     rc = PDMDevHlpDBGFInfoRegister(pDevIns, "virtio-net", "Display virtio-net info (help, net, features, state, pointers, queues, all)", virtioNetR3Info);
     3638    rc = PDMDevHlpDBGFInfoRegister(pDevIns, "virtionet", "Display virtionet info (help, net, features, state, pointers, queues, all)", virtioNetR3Info);
    36393639    if (RT_FAILURE(rc))
    36403640        LogRel(("Failed to register DBGF info for device %s\n", szTmp));
  • trunk/src/VBox/Devices/VirtIO/VirtioCore.cpp

    r104280 r104432  
    619619}
    620620
     621DECLINLINE(void) virtioCoreR3DescInfo(PCDBGFINFOHLP pHlp, PVIRTQ_DESC_T pDesc, uint16_t iDesc, const char *cszTail)
     622{
     623    if (pDesc->fFlags & VIRTQ_DESC_F_NEXT)
     624        pHlp->pfnPrintf(pHlp, "          [%4d]%c%c %5d bytes @ %p  [%4d] %s\n",
     625                        iDesc, pDesc->fFlags & VIRTQ_DESC_F_INDIRECT ? 'I' : ' ',
     626                        pDesc->fFlags & VIRTQ_DESC_F_WRITE ? 'W' : 'R',
     627                        pDesc->cb, pDesc->GCPhysBuf, pDesc->uDescIdxNext, cszTail);
     628    else
     629        pHlp->pfnPrintf(pHlp, "          [%4d]%c%c %5d bytes @ %p         %s\n",
     630                        iDesc, pDesc->fFlags & VIRTQ_DESC_F_INDIRECT ? 'I' : ' ',
     631                        pDesc->fFlags & VIRTQ_DESC_F_WRITE ? 'W' : 'R',
     632                        pDesc->cb, pDesc->GCPhysBuf, cszTail);
     633}
     634
    621635/** API Fuunction: See header file */
    622636DECLHIDDEN(void) virtioCoreR3VirtqInfo(PPDMDEVINS pDevIns, PCDBGFINFOHLP pHlp, const char *pszArgs, int uVirtq)
     
    635649    uint16_t uUsedIdxShadow  = pVirtq->uUsedIdxShadow;
    636650
     651    uint16_t uAvailEventIdx = 0;
     652    uint16_t uUsedEventIdx = 0;
     653    bool     fNotify = !!(pVirtio->uDriverFeatures & VIRTIO_F_EVENT_IDX);
     654    if (fNotify)
     655    {
     656        uUsedEventIdx = virtioReadAvailUsedEvent(pDevIns, pVirtio, pVirtq);
     657        /* There is no helper for reading AvailEvent since the device is not supposed to read it. */
     658        virtioCoreGCPhysRead(pVirtio, pDevIns,
     659                            pVirtq->GCPhysVirtqUsed
     660                            + RT_UOFFSETOF_DYN(VIRTQ_USED_T, aRing[pVirtq->uQueueSize]),
     661                            &uAvailEventIdx, sizeof(uAvailEventIdx));
     662    }
     663
    637664    VIRTQBUF_T VirtqBuf;
    638665    PVIRTQBUF pVirtqBuf = &VirtqBuf;
     666    RT_ZERO(VirtqBuf);  /* Make sure pSgPhysSend and pSgPhysReturn are initialized. */
    639667    bool fEmpty = IS_VIRTQ_EMPTY(pDevIns, pVirtio, pVirtq);
    640668
     
    659687    pHlp->pfnPrintf(pHlp, "\n");
    660688    pHlp->pfnPrintf(pHlp, "       avail ring (%d entries):\n", uAvailIdx - uAvailIdxShadow);
    661     pHlp->pfnPrintf(pHlp, "          index: ................ %d\n", uAvailIdx);
    662     pHlp->pfnPrintf(pHlp, "          shadow: ............... %d\n", uAvailIdxShadow);
     689    pHlp->pfnPrintf(pHlp, "          index: ................ %d (%d)\n", pVirtq->uQueueSize ? uAvailIdx % pVirtq->uQueueSize : uAvailIdx, uAvailIdx);
     690    pHlp->pfnPrintf(pHlp, "          shadow: ............... %d (%d)\n", pVirtq->uQueueSize ? uAvailIdxShadow % pVirtq->uQueueSize : uAvailIdxShadow, uAvailIdxShadow);
    663691    pHlp->pfnPrintf(pHlp, "          flags: ................ %s\n", fAvailNoInterrupt ? "NO_INTERRUPT" : "");
    664692    pHlp->pfnPrintf(pHlp, "\n");
    665     pHlp->pfnPrintf(pHlp, "       used ring (%d entries):\n",  uUsedIdx - uUsedIdxShadow);
    666     pHlp->pfnPrintf(pHlp, "          index: ................ %d\n", uUsedIdx);
    667     pHlp->pfnPrintf(pHlp, "          shadow: ............... %d\n", uUsedIdxShadow);
     693    pHlp->pfnPrintf(pHlp, "       used ring (%d entries):\n",  uUsedIdxShadow - uUsedIdx);
     694    pHlp->pfnPrintf(pHlp, "          index: ................ %d (%d)\n", pVirtq->uQueueSize ? uUsedIdx % pVirtq->uQueueSize : uUsedIdx, uUsedIdx);
     695    pHlp->pfnPrintf(pHlp, "          shadow: ............... %d (%d)\n", pVirtq->uQueueSize ? uUsedIdxShadow % pVirtq->uQueueSize : uUsedIdxShadow, uUsedIdxShadow);
    668696    pHlp->pfnPrintf(pHlp, "          flags: ................ %s\n", fUsedNoNotify ? "NO_NOTIFY" : "");
    669697    pHlp->pfnPrintf(pHlp, "\n");
     
    671699    {
    672700        pHlp->pfnPrintf(pHlp, "       desc chain:\n");
    673         pHlp->pfnPrintf(pHlp, "          head idx: ............. %d\n", uUsedIdx);
     701        pHlp->pfnPrintf(pHlp, "          head idx: ............. %d (%d)\n", pVirtq->uQueueSize ? uUsedIdx % pVirtq->uQueueSize : uUsedIdx, uUsedIdx);
    674702        pHlp->pfnPrintf(pHlp, "          segs: ................. %d\n", cSendSegs + cReturnSegs);
    675703        pHlp->pfnPrintf(pHlp, "          refCnt ................ %d\n", pVirtqBuf->cRefs);
     
    683711        }
    684712        pHlp->pfnPrintf(pHlp, "\n");
    685         pHlp->pfnPrintf(pHlp,     "      guest-to-host (%d bytes)\n",       pVirtqBuf->cbPhysReturn);
     713        pHlp->pfnPrintf(pHlp,     "          guest-to-host (%d bytes):\n",  pVirtqBuf->cbPhysReturn);
    686714        pHlp->pfnPrintf(pHlp,     "             segs: .............. %d\n", cReturnSegs);
    687715        if (cReturnSegs)
     
    691719        }
    692720    } else
    693         pHlp->pfnPrintf(pHlp,     "      No desc chains available\n");
     721        pHlp->pfnPrintf(pHlp,     "       no desc chains available\n");
    694722    pHlp->pfnPrintf(pHlp, "\n");
     723
     724    /* Avoid handling zero-sized queues, there is nothing to show anyway. */
     725    if (pVirtq->uQueueSize == 0)
     726        return;
     727
     728    pHlp->pfnPrintf(pHlp, "       desc table:\n");
     729    /*
     730     * Each line in the descriptor table output consists of two parts: a fixed part and a variable "tail".
     731     * The fixed part shows the descriptor index, its writability, size, physical address, and optionally
     732     * which descriptor is next the chain. The tail shows which elements of avail/used rings point to
     733     * this descriptor.
     734     */
     735    VIRTQ_DESC_T descTable[VIRTQ_SIZE];
     736    char aszTails[VIRTQ_SIZE][32];
     737    virtioCoreGCPhysRead(pVirtio, pDevIns, pVirtq->GCPhysVirtqDesc,
     738                        &descTable, sizeof(VIRTQ_DESC_T) * pVirtq->uQueueSize);
     739    RT_BZERO(aszTails, sizeof(aszTails));   /* No tails by default */
     740
     741    /* Fill avail tail fields. */
     742
     743    /* The first available descriptor gets outer reverse angle brackets. */
     744    char chOuterLeft = '>', chOuterRight = '<';
     745    char chLeft = '[', chRight = ']';
     746    /* Use 'not-equal' instead of 'less' because of uint16_t wrapping! */
     747    for (uint16_t i = uAvailIdxShadow; i != uAvailIdx; i++)
     748    {
     749        /* The last descriptor gets inner curly braces, inner square brackets for the rest. */
     750        if (i + 1 == uAvailIdx) { chLeft = '{'; chRight = '}'; }
     751        uint16_t uDescIdx = virtioReadAvailDescIdx(pDevIns, pVirtio, pVirtq, i);
     752        /* Print an exclamation sign instead of outer right bracket if this descriptor triggers notification. */
     753        RTStrPrintf(aszTails[uDescIdx], sizeof(aszTails[0]), "%c%c%4d%c%c ",
     754                    chOuterLeft, chLeft, i % pVirtq->uQueueSize, chRight,
     755                    fNotify ? ((i % pVirtq->uQueueSize) == (uAvailEventIdx % pVirtq->uQueueSize) ? '!' : chOuterRight) : chOuterRight);
     756        chOuterLeft = chOuterRight = ' ';
     757    }
     758
     759    /* Fill used tail fields, see comments in the similar loop above. */
     760
     761    chOuterLeft = '>'; chOuterRight = '<';
     762    chLeft = '['; chRight = ']';
     763    for (uint16_t i = uUsedIdx; i != uUsedIdxShadow; i++)
     764    {
     765        VIRTQ_USED_ELEM_T elem;
     766        virtioCoreGCPhysRead(pVirtio, pDevIns,
     767                             pVirtq->GCPhysVirtqUsed
     768                             + RT_UOFFSETOF_DYN(VIRTQ_USED_T, aRing[i % pVirtq->uQueueSize]),
     769                             &elem, sizeof(elem));
     770        if (i + 1 == uUsedIdxShadow) { chLeft = '{'; chRight = '}'; }
     771        char *szTail = aszTails[elem.uDescIdx % pVirtq->uQueueSize];
     772        /* Add empty avail field if none is present, 9 spaces + terminating zero. */
     773        if (*szTail == '\0')
     774            RTStrCopy(szTail, 10, "          ");
     775        RTStrPrintf(szTail + 9, sizeof(aszTails[0]) - 9, " %c%c%4d%c%c %d bytes",
     776                    chOuterLeft, chLeft, i % pVirtq->uQueueSize, chRight,
     777                    fNotify ? ((i % pVirtq->uQueueSize) == (uUsedEventIdx % pVirtq->uQueueSize) ? '!' : chOuterRight) : chOuterRight,
     778                    elem.cbElem);
     779        chOuterLeft = chOuterRight = ' ';
     780    }
     781
     782    pHlp->pfnPrintf(pHlp, "          index w/r size         phys addr        next    @avail   @used\n");
     783    pHlp->pfnPrintf(pHlp, "          ------ - -----------   ---------------- ------- -------- ------------------\n");
     784    for (uint16_t i = 0; i < pVirtq->uQueueSize; i++)
     785        virtioCoreR3DescInfo(pHlp, &descTable[i], i, aszTails[i]);
    695786}
    696787
     
    857948            if (ASMAtomicIncU32(&s_cMessages) == ASMAtomicReadU32(&s_cThreshold))
    858949            {
    859                 LogRelMax(64, ("Too many linked descriptors; check if the guest arranges descriptors in a loop (cSegsIn=%u cSegsOut=%u uQueueSize=%u).\n",
    860                                cSegsIn, cSegsOut, pVirtq->uQueueSize));
     950                LogRelMax(64, ("Too many linked descriptors; check if the guest arranges descriptors in a loop (cSegsIn=%u cSegsOut=%u uQueueSize=%u uDescIdx=%u queue=%s).\n",
     951                               cSegsIn, cSegsOut, pVirtq->uQueueSize, uDescIdx, pVirtq->szName));
    861952                if (ASMAtomicReadU32(&s_cMessages) != 1)
    862953                    LogRelMax(64, ("(the above error has occured %u times so far)\n", ASMAtomicReadU32(&s_cMessages)));
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