VirtualBox

Ignore:
Timestamp:
May 7, 2025 7:42:49 AM (12 days ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
168752
Message:

VirtioNet: Temporary code from 7.0 branch for debugging descriptor loop issue ​bugref:10572

File:
1 edited

Legend:

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

    r107747 r109188  
    673673    PVIRTIONETWORKER pWorker = &pThis->aWorkers[uVirtqNbr];
    674674
     675#ifdef VIRTIO_REL_INFO_DUMP
     676    if (ASMAtomicReadBool(&pVirtio->fRecovering))
     677        LogRel(("[%s] Received notification from the guest on queue %u\n", pThis->szInst, uVirtqNbr));
     678#endif /* VIRTIO_REL_INFO_DUMP */
    675679#if defined (IN_RING3) && defined (LOG_ENABLED)
    676680    RTLogFlush(NULL);
     
    792796 * @callback_method_impl{FNDBGFHANDLERDEV, virtio-net debugger info callback.}
    793797 */
     798#ifdef VIRTIO_REL_INFO_DUMP
     799DECLCALLBACK(void) virtioNetR3Info(PPDMDEVINS pDevIns, PCDBGFINFOHLP pHlp, const char *pszArgs)
     800#else  /* !VIRTIO_REL_INFO_DUMP */
    794801static DECLCALLBACK(void) virtioNetR3Info(PPDMDEVINS pDevIns, PCDBGFINFOHLP pHlp, const char *pszArgs)
     802#endif /* !VIRTIO_REL_INFO_DUMP */
    795803{
    796804    PVIRTIONET     pThis   = PDMDEVINS_2_DATA(pDevIns,  PVIRTIONET);
     
    804812    bool fPointers = pszArgs && (*pszArgs == 'p' || *pszArgs == 'P'); /* "pointers" */
    805813    bool fVirtqs   = pszArgs && (*pszArgs == 'q' || *pszArgs == 'Q'); /* "queues    */
     814#ifdef VIRTIO_REL_INFO_DUMP
     815    if (pszArgs && (*pszArgs == 't' || *pszArgs == 'T'))
     816    {
     817        ASMAtomicWriteBool(&pThis->Virtio.fTestRecovery, true);
     818        pHlp->pfnPrintf(pHlp, "Triggering recovery for %s\n", pThis->szInst);
     819        return;
     820    }
     821#endif /* VIRTIO_REL_INFO_DUMP */
    806822
    807823    /* Show basic information. */
     
    10381054        return fWrite ? VINF_SUCCESS : VINF_IOM_MMIO_UNUSED_00;
    10391055    }
     1056#ifdef VIRTIO_REL_INFO_DUMP
     1057    if (ASMAtomicReadBool(&pThis->Virtio.fRecovering))
     1058        LogRel(("[%s] %s %u bytes @ dev cfg + %u: %.*Rhxs\n", pThis->szInst, fWrite ? "wrote" : "read", cb, uOffsetOfAccess, cb, pv));
     1059#endif /* VIRTIO_REL_INFO_DUMP */
    10401060    return VINF_SUCCESS;
    10411061}
     
    15371557#ifdef IN_RING3
    15381558
     1559#ifdef VIRTIO_REL_INFO_DUMP
     1560/**
     1561 * Attempt to recover from the state when a descriptor loop is discovered in adapter queue.
     1562 * The idea is to force device reset via setting the DEVICE_NEEDS_RESET bit in the device status field.
     1563 * To prevent further accesses to the queue in invalid state we need to bring down the link temporarily.
     1564 * Unfortunately it does not seem to be handled by Linux virtio at all, so the faulty queue will remain
     1565 * disabled, preventing recovery.
     1566 *
     1567 * @param pDevIns               PDM instance
     1568 *
     1569 */
     1570DECLHIDDEN(int) virtioNetAttemptToRecover(PPDMDEVINS pDevIns)
     1571{
     1572    PVIRTIONET     pThis   = PDMDEVINS_2_DATA(pDevIns,  PVIRTIONET);
     1573    PVIRTIONETCC   pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PVIRTIONETCC);
     1574
     1575    if (IS_LINK_UP(pThis))
     1576    {
     1577        SET_LINK_DOWN(pThis);
     1578
     1579        /* Re-establish link in 10 seconds. */
     1580        int rc = PDMDevHlpTimerSetMillies(pDevIns, pThisCC->hLinkUpTimer, 10000);
     1581        AssertRC(rc);
     1582
     1583        LogRel(("[%s] Virtio disabled until device reset\n", pThis->szInst));
     1584        pThis->fVirtioReady = false;
     1585    }
     1586    virtioCoreResetAll(&pThis->Virtio);
     1587
     1588    if (ASMAtomicXchgBool(&pThis->Virtio.fRecovering, true))
     1589        LogRel(("[%s] Attempting recovery while in recovery!\n", pThis->szInst));
     1590
     1591    return VINF_SUCCESS;
     1592}
     1593#endif /* VIRTIO_REL_INFO_DUMP */
     1594
    15391595/**
    15401596 * Perform 16-bit 1's compliment checksum on provided packet in accordance with VirtIO specification,
     
    16511707        rc = VINF_SUCCESS;
    16521708    }
     1709#ifdef VIRTIO_REL_INFO_DUMP
     1710    if (ASMAtomicReadBool(&pThis->Virtio.fRecovering))
     1711        LogRel(("[%s] %sRX buffers available on %s\n", pThis->szInst, rc == VERR_INVALID_STATE ? "Enabling notify as no " : "", pRxVirtq->szName));
     1712#endif /* VIRTIO_REL_INFO_DUMP */
    16531713    virtioCoreVirtqEnableNotify(&pThis->Virtio, pRxVirtq->uIdx, rc == VERR_INVALID_STATE /* fEnable */);
    16541714    return rc;
     
    20092069            cbHdrEnqueued = cbPktHdr;
    20102070            int rc = virtioCoreR3VirtqAvailBufGet(pDevIns, &pThis->Virtio, pRxVirtq->uIdx, pVirtqBuf, true);
     2071#ifdef VIRTIO_REL_INFO_DUMP
     2072            if (rc == VERR_INVALID_STATE)
     2073                return virtioNetAttemptToRecover(pDevIns);
     2074            if (rc == VERR_NOT_AVAILABLE)
     2075                return VINF_SUCCESS;
     2076#endif /* VIRTIO_REL_INFO_DUMP */
    20112077            AssertMsgReturn(rc == VINF_SUCCESS || rc == VERR_NOT_AVAILABLE, ("%Rrc\n", rc), rc);
    20122078            AssertMsgReturn(rc == VINF_SUCCESS && pVirtqBuf->cbPhysReturn,
     
    20532119    PVIRTQBUF pVirtqBuf = &VirtqBuf;
    20542120    int rc = virtioCoreR3VirtqAvailBufGet(pDevIns, &pThis->Virtio, pRxVirtq->uIdx, pVirtqBuf, true);
     2121#ifdef VIRTIO_REL_INFO_DUMP
     2122    if (rc == VERR_INVALID_STATE)
     2123        return virtioNetAttemptToRecover(pDevIns);
     2124    if (rc == VERR_NOT_AVAILABLE)
     2125        return VINF_SUCCESS;
     2126#endif /* VIRTIO_REL_INFO_DUMP */
    20552127    AssertMsgReturn(rc == VINF_SUCCESS || rc == VERR_NOT_AVAILABLE, ("%Rrc\n", rc), rc);
    20562128    AssertMsgReturn(rc == VINF_SUCCESS && pVirtqBuf->cbPhysReturn,
     
    20802152    }
    20812153    STAM_PROFILE_STOP(&pThis->StatReceiveStore, a);
     2154#ifdef VIRTIO_REL_INFO_DUMP
     2155    if (ASMAtomicXchgBool(&pThis->Virtio.fRecovering, false))
     2156        LogRel(("[%s] Recovery complete on successfully receiving a packet\n", pThis->szInst));
     2157#endif /* VIRTIO_REL_INFO_DUMP */
    20822158    return VINF_SUCCESS;
    20832159}
     
    27212797    if (!cPkts)
    27222798    {
     2799#ifdef VIRTIO_REL_INFO_DUMP
     2800        if (ASMAtomicReadBool(&pThis->Virtio.fRecovering))
     2801            LogRel(("[%s] No packets to send found on %s\n", pThis->szInst, pTxVirtq->szName));
     2802#endif /* VIRTIO_REL_INFO_DUMP */
    27232803        LogFunc(("[%s] No packets to send found on %s\n", pThis->szInst, pTxVirtq->szName));
    27242804
     
    27292809        return VERR_MISSING;
    27302810    }
     2811#ifdef VIRTIO_REL_INFO_DUMP
     2812    if (ASMAtomicReadBool(&pThis->Virtio.fRecovering))
     2813        LogRel(("[%s] About to transmit %d pending packet%c\n", pThis->szInst, cPkts, cPkts == 1 ? ' ' : 's'));
     2814#endif /* VIRTIO_REL_INFO_DUMP */
    27312815    LogFunc(("[%s] About to transmit %d pending packet%c\n", pThis->szInst, cPkts, cPkts == 1 ? ' ' : 's'));
    27322816
     
    28592943            virtioCoreVirtqEnableNotify(&pThis->Virtio, pTxVirtq->uIdx, true /* fEnable */);
    28602944    }
     2945#ifdef VIRTIO_REL_INFO_DUMP
     2946    if (rc == VERR_INVALID_STATE)
     2947    {
     2948        /*
     2949         * Our best bet for recovering from a bad queue state is to do a device reset, but
     2950         * it is not enough because NetKVM driver does not complete NBLs on reset. We need to lower
     2951         * the link in order to prevent adding new descriptors to the TX queue first. Then we
     2952         * need to simulate processing of all outstanding descriptor chains by simply copying
     2953         * all head indices from avail to used ring. Note that we have only 'peeked' into the avail
     2954         * ring, so the avail index should not have moved yet. This is not the case for other queues.
     2955         */
     2956        virtioNetAttemptToRecover(pDevIns);
     2957        virtioCorePutAllAvailBufsToUsedRing(pDevIns, &pThis->Virtio, pTxVirtq->uIdx);
     2958    }
     2959    else if (ASMAtomicXchgBool(&pThis->Virtio.fRecovering, false))
     2960        LogRel(("[%s] Recovery complete on successfully transmitting a packet\n", pThis->szInst));
     2961#endif /* VIRTIO_REL_INFO_DUMP */
    28612962    virtioNetR3SetWriteLed(pThisCC, false);
    28622963
     
    28912992    PVIRTIONETCC pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PVIRTIONETCC);
    28922993
     2994#ifdef VIRTIO_REL_INFO_DUMP
     2995    if (RT_UNLIKELY(!pThis->fVirtioReady))
     2996    {
     2997        if (ASMAtomicXchgBool(&pThis->Virtio.fRecovering, false))
     2998        {
     2999            LogRel(("[%s] Recovery failed, VM reset is needed!\n", pThis->szInst));
     3000            return;
     3001        }
     3002    }
     3003#endif /* VIRTIO_REL_INFO_DUMP */
     3004
    28933005    SET_LINK_UP(pThis);
     3006#ifdef VIRTIO_REL_INFO_DUMP
     3007    if (ASMAtomicReadBool(&pThis->Virtio.fRecovering))
     3008        LogRel(("[%s] Link is up\n", pThis->szInst));
     3009#endif /* VIRTIO_REL_INFO_DUMP */
    28943010    virtioNetWakeupRxBufWaiter(pDevIns);
    28953011
     
    31403256            PVIRTQBUF pVirtqBuf = &VirtqBuf;
    31413257            int rc = virtioCoreR3VirtqAvailBufGet(pDevIns, &pThis->Virtio, pVirtq->uIdx, pVirtqBuf, true);
     3258#ifdef VIRTIO_REL_INFO_DUMP
     3259            if (rc == VERR_INVALID_STATE)
     3260            {
     3261                virtioNetAttemptToRecover(pDevIns);
     3262                continue;
     3263            }
     3264#endif /* VIRTIO_REL_INFO_DUMP */
    31423265            if (rc == VERR_NOT_AVAILABLE)
    31433266            {
     
    32053328    else
    32063329    {
     3330#ifdef VIRTIO_REL_INFO_DUMP
     3331        if (ASMAtomicReadBool(&pThis->Virtio.fRecovering))
     3332            LogRel(("[%s] Resetting...\n", pThis->szInst));
     3333#endif /* VIRTIO_REL_INFO_DUMP */
    32073334        Log(("\n%-23s: %s VirtIO is resetting ***\n", __FUNCTION__, pThis->szInst));
    32083335
     
    32333360        }
    32343361    }
     3362
     3363#ifdef VIRTIO_REL_INFO_DUMP
     3364    if (pThisCC->pDrv)
     3365        pThisCC->pDrv->pfnNotifyLinkChanged(pThisCC->pDrv, pThis->virtioNetConfig.uStatus ? PDMNETWORKLINKSTATE_UP : PDMNETWORKLINKSTATE_DOWN);
     3366#endif /* VIRTIO_REL_INFO_DUMP */
    32353367}
    32363368
     
    32433375
    32443376    LogFunc(("[Feature Negotiation Complete] Guest Driver version is: %s\n", fLegacy ? "legacy" : "modern"));
     3377#ifdef VIRTIO_REL_INFO_DUMP
     3378    if (ASMAtomicReadBool(&pThis->Virtio.fRecovering))
     3379        LogRel(("[%s] Feature Negotiation Complete for %s driver\n", pThis->szInst, fLegacy ? "legacy" : "modern"));
     3380#endif /* VIRTIO_REL_INFO_DUMP */
    32453381    virtioNetConfigurePktHdr(pThis, fLegacy);
    32463382    virtioNetR3SetVirtqNames(pThis, fLegacy);
Note: See TracChangeset for help on using the changeset viewer.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette