Changeset 109188 in vbox for trunk/src/VBox/Devices/Network/DevVirtioNet.cpp
- Timestamp:
- May 7, 2025 7:42:49 AM (12 days ago)
- svn:sync-xref-src-repo-rev:
- 168752
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Network/DevVirtioNet.cpp
r107747 r109188 673 673 PVIRTIONETWORKER pWorker = &pThis->aWorkers[uVirtqNbr]; 674 674 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 */ 675 679 #if defined (IN_RING3) && defined (LOG_ENABLED) 676 680 RTLogFlush(NULL); … … 792 796 * @callback_method_impl{FNDBGFHANDLERDEV, virtio-net debugger info callback.} 793 797 */ 798 #ifdef VIRTIO_REL_INFO_DUMP 799 DECLCALLBACK(void) virtioNetR3Info(PPDMDEVINS pDevIns, PCDBGFINFOHLP pHlp, const char *pszArgs) 800 #else /* !VIRTIO_REL_INFO_DUMP */ 794 801 static DECLCALLBACK(void) virtioNetR3Info(PPDMDEVINS pDevIns, PCDBGFINFOHLP pHlp, const char *pszArgs) 802 #endif /* !VIRTIO_REL_INFO_DUMP */ 795 803 { 796 804 PVIRTIONET pThis = PDMDEVINS_2_DATA(pDevIns, PVIRTIONET); … … 804 812 bool fPointers = pszArgs && (*pszArgs == 'p' || *pszArgs == 'P'); /* "pointers" */ 805 813 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 */ 806 822 807 823 /* Show basic information. */ … … 1038 1054 return fWrite ? VINF_SUCCESS : VINF_IOM_MMIO_UNUSED_00; 1039 1055 } 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 */ 1040 1060 return VINF_SUCCESS; 1041 1061 } … … 1537 1557 #ifdef IN_RING3 1538 1558 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 */ 1570 DECLHIDDEN(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 1539 1595 /** 1540 1596 * Perform 16-bit 1's compliment checksum on provided packet in accordance with VirtIO specification, … … 1651 1707 rc = VINF_SUCCESS; 1652 1708 } 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 */ 1653 1713 virtioCoreVirtqEnableNotify(&pThis->Virtio, pRxVirtq->uIdx, rc == VERR_INVALID_STATE /* fEnable */); 1654 1714 return rc; … … 2009 2069 cbHdrEnqueued = cbPktHdr; 2010 2070 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 */ 2011 2077 AssertMsgReturn(rc == VINF_SUCCESS || rc == VERR_NOT_AVAILABLE, ("%Rrc\n", rc), rc); 2012 2078 AssertMsgReturn(rc == VINF_SUCCESS && pVirtqBuf->cbPhysReturn, … … 2053 2119 PVIRTQBUF pVirtqBuf = &VirtqBuf; 2054 2120 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 */ 2055 2127 AssertMsgReturn(rc == VINF_SUCCESS || rc == VERR_NOT_AVAILABLE, ("%Rrc\n", rc), rc); 2056 2128 AssertMsgReturn(rc == VINF_SUCCESS && pVirtqBuf->cbPhysReturn, … … 2080 2152 } 2081 2153 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 */ 2082 2158 return VINF_SUCCESS; 2083 2159 } … … 2721 2797 if (!cPkts) 2722 2798 { 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 */ 2723 2803 LogFunc(("[%s] No packets to send found on %s\n", pThis->szInst, pTxVirtq->szName)); 2724 2804 … … 2729 2809 return VERR_MISSING; 2730 2810 } 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 */ 2731 2815 LogFunc(("[%s] About to transmit %d pending packet%c\n", pThis->szInst, cPkts, cPkts == 1 ? ' ' : 's')); 2732 2816 … … 2859 2943 virtioCoreVirtqEnableNotify(&pThis->Virtio, pTxVirtq->uIdx, true /* fEnable */); 2860 2944 } 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 */ 2861 2962 virtioNetR3SetWriteLed(pThisCC, false); 2862 2963 … … 2891 2992 PVIRTIONETCC pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PVIRTIONETCC); 2892 2993 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 2893 3005 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 */ 2894 3010 virtioNetWakeupRxBufWaiter(pDevIns); 2895 3011 … … 3140 3256 PVIRTQBUF pVirtqBuf = &VirtqBuf; 3141 3257 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 */ 3142 3265 if (rc == VERR_NOT_AVAILABLE) 3143 3266 { … … 3205 3328 else 3206 3329 { 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 */ 3207 3334 Log(("\n%-23s: %s VirtIO is resetting ***\n", __FUNCTION__, pThis->szInst)); 3208 3335 … … 3233 3360 } 3234 3361 } 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 */ 3235 3367 } 3236 3368 … … 3243 3375 3244 3376 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 */ 3245 3381 virtioNetConfigurePktHdr(pThis, fLegacy); 3246 3382 virtioNetR3SetVirtqNames(pThis, fLegacy);
Note:
See TracChangeset
for help on using the changeset viewer.