- Timestamp:
- Nov 13, 2009 4:20:15 PM (15 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Network/DevVirtioNet.cpp
r24623 r24641 57 57 //- TODO: Move to Virtio.h ---------------------------------------------------- 58 58 59 /* 60 * The saved state version is changed if either common or any of specific 61 * parts are changed. That is, it is perfectly possible that the version 62 * of saved vnet state will increase as a result of change in vblk structure 63 * for example. 64 */ 65 #define VIRTIO_SAVEDSTATE_VERSION_3_1_BETA1 1 66 #define VIRTIO_SAVEDSTATE_VERSION 2 67 59 68 #define VPCI_F_NOTIFY_ON_EMPTY 0x01000000 60 69 #define VPCI_F_BAD_FEATURE 0x40000000 … … 158 167 }; 159 168 160 #define VIRTIO_NET_NQUEUES 3161 169 #define VIRTIO_MAX_NQUEUES 3 170 #define VNET_NQUEUES 3 162 171 163 172 struct VPCIState_st … … 197 206 uint8_t uISR; /**< Interrupt Status Register. */ 198 207 199 #if HC_ARCH_BITS == 64 200 uint32_t padding3; 201 #endif 202 208 // #if HC_ARCH_BITS == 64 209 // uint32_t padding3; 210 // #endif 211 212 uint32_t nQueues; /**< Actual number of queues used. */ 203 213 VQUEUE Queues[VIRTIO_MAX_NQUEUES]; 204 214 … … 253 263 /* Vendor Device SSVendor SubSys Class NQ Name Instance */ 254 264 { /* Virtio Network Device */ 255 0x1AF4, 0x1000, 0x1AF4, 1 + VIRTIO_NET_ID, 0x0200, V IRTIO_NET_NQUEUES,265 0x1AF4, 0x1000, 0x1AF4, 1 + VIRTIO_NET_ID, 0x0200, VNET_NQUEUES, 256 266 "virtio-net", "vnet%d", 257 267 vnetGetHostFeatures, vnetGetHostMinimalFeatures, vnetSetHostFeatures, … … 517 527 pState->uISR = 0; 518 528 519 for (unsigned i = 0; i < g_VPCIDevices[pState->enmDevType].nQueues; i++)529 for (unsigned i = 0; i < pState->nQueues; i++) 520 530 vqueueReset(&pState->Queues[i]); 521 531 } … … 727 737 728 738 case VPCI_QUEUE_SEL: 729 #ifdef IN_RING3730 739 Assert(cb == 2); 731 740 u32 &= 0xFFFF; 732 if (u32 < g_VPCIDevices[pState->enmDevType].nQueues)741 if (u32 < pState->nQueues) 733 742 pState->uQueueSelector = u32; 734 743 else 735 744 Log3(("%s virtioIOPortOut: Invalid queue selector %08x\n", szInst, u32)); 736 #else737 rc = VINF_IOM_HC_IOPORT_WRITE;738 #endif739 745 break; 740 746 … … 743 749 Assert(cb == 2); 744 750 u32 &= 0xFFFF; 745 if (u32 < g_VPCIDevices[pState->enmDevType].nQueues)751 if (u32 < pState->nQueues) 746 752 if (pState->Queues[u32].VRing.addrDescriptors) 747 753 pState->Queues[u32].pfnCallback(pState, &pState->Queues[u32]); … … 962 968 pState->uISR)); 963 969 964 for (unsigned i = 0; i < g_VPCIDevices[pState->enmDevType].nQueues; i++)970 for (unsigned i = 0; i < pState->nQueues; i++) 965 971 Log2((" %s queue:\n" 966 972 " VRing.uSize = %u\n" … … 1007 1013 1008 1014 /* Save queue states */ 1009 for (unsigned i = 0; i < g_VPCIDevices[pState->enmDevType].nQueues; i++) 1015 rc = SSMR3PutU32(pSSM, pState->nQueues); 1016 AssertRCReturn(rc, rc); 1017 for (unsigned i = 0; i < pState->nQueues; i++) 1010 1018 { 1011 1019 rc = SSMR3PutU16(pSSM, pState->Queues[i].VRing.uSize); … … 1048 1056 1049 1057 /* Restore queues */ 1050 for (unsigned i = 0; i < g_VPCIDevices[pState->enmDevType].nQueues; i++) 1058 if (uVersion > VIRTIO_SAVEDSTATE_VERSION_3_1_BETA1) 1059 { 1060 rc = SSMR3GetU32(pSSM, &pState->nQueues); 1061 AssertRCReturn(rc, rc); 1062 } 1063 else 1064 pState->nQueues = g_VPCIDevices[pState->enmDevType].nQueues; 1065 for (unsigned i = 0; i < pState->nQueues; i++) 1051 1066 { 1052 1067 rc = SSMR3GetU16(pSSM, &pState->Queues[i].VRing.uSize); … … 1136 1151 pState->pLedsConnector = (PPDMILEDCONNECTORS)pBase->pfnQueryInterface(pBase, PDMINTERFACE_LED_CONNECTORS); 1137 1152 1153 pState->nQueues = g_VPCIDevices[pState->enmDevType].nQueues; 1154 1138 1155 #if defined(VBOX_WITH_STATISTICS) 1139 1156 PDMDevHlpSTAMRegisterF(pDevIns, &pState->StatIOReadGC, STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_TICKS_PER_CALL, "Profiling IO reads in GC", "/Devices/VNet%d/IO/ReadGC", iInstance); … … 1194 1211 PVQUEUE pQueue = NULL; 1195 1212 /* Find an empty queue slot */ 1196 for (unsigned i = 0; i < g_VPCIDevices[pState->enmDevType].nQueues; i++)1213 for (unsigned i = 0; i < pState->nQueues; i++) 1197 1214 { 1198 1215 if (pState->Queues[i].VRing.uSize == 0) … … 1228 1245 //- TODO: Move to VirtioNet.h ------------------------------------------------- 1229 1246 1247 #define VNET_TX_DELAY 150 /* 150 microseconds */ 1230 1248 #define VNET_MAX_FRAME_SIZE 65536 // TODO: Is it the right limit? 1231 #define VNET_SAVEDSTATE_VERSION 11232 1249 1233 1250 /* Virtio net features */ … … 1290 1307 /**< Link Up(/Restore) Timer. */ 1291 1308 PTMTIMERR3 pLinkUpTimer; 1309 #ifdef VNET_TX_DELAY 1310 /**< Transmit Delay Timer - R3. */ 1311 PTMTIMERR3 pTxTimerR3; 1312 /**< Transmit Delay Timer - R0. */ 1313 PTMTIMERR0 pTxTimerR0; 1314 /**< Transmit Delay Timer - GC. */ 1315 PTMTIMERRC pTxTimerRC; 1316 #if HC_ARCH_BITS == 64 1317 uint32_t padding2; 1318 #endif 1319 1320 #endif /* VNET_TX_DELAY */ 1292 1321 1293 1322 /** PCI config area holding MAC address as well as TBD. */ … … 1775 1804 } 1776 1805 1777 static DECLCALLBACK(void) vnetQueueTransmit(void *pvState, PVQUEUE pQueue) 1778 { 1779 VNETSTATE *pState = (VNETSTATE*)pvState; 1806 static DECLCALLBACK(void) vnetTransmitPendingPackets(PVNETSTATE pState, PVQUEUE pQueue) 1807 { 1780 1808 if ((pState->VPCI.uStatus & VPCI_STATUS_DRV_OK) == 0) 1781 1809 { … … 1824 1852 } 1825 1853 1854 #ifdef VNET_TX_DELAY 1855 static DECLCALLBACK(void) vnetQueueTransmit(void *pvState, PVQUEUE pQueue) 1856 { 1857 VNETSTATE *pState = (VNETSTATE*)pvState; 1858 1859 if (TMTimerIsActive(pState->CTX_SUFF(pTxTimer))) 1860 { 1861 int rc = TMTimerStop(pState->CTX_SUFF(pTxTimer)); 1862 vringSetNotification(&pState->VPCI, &pState->pTxQueue->VRing, true); 1863 Log3(("%s vnetQueueTransmit: Got kicked with notification disabled, " 1864 "re-enable notification and flush TX queue\n", INSTANCE(pState))); 1865 vnetTransmitPendingPackets(pState, pQueue); 1866 } 1867 else 1868 { 1869 TMTimerSetMicro(pState->CTX_SUFF(pTxTimer), VNET_TX_DELAY); 1870 vringSetNotification(&pState->VPCI, &pState->pTxQueue->VRing, false); 1871 } 1872 } 1873 1874 /** 1875 * Transmit Delay Timer handler. 1876 * 1877 * @remarks We only get here when the timer expires. 1878 * 1879 * @param pDevIns Pointer to device instance structure. 1880 * @param pTimer Pointer to the timer. 1881 * @param pvUser NULL. 1882 * @thread EMT 1883 */ 1884 static DECLCALLBACK(void) vnetTxTimer(PPDMDEVINS pDevIns, PTMTIMER pTimer, void *pvUser) 1885 { 1886 VNETSTATE *pState = (VNETSTATE*)pvUser; 1887 1888 vringSetNotification(&pState->VPCI, &pState->pTxQueue->VRing, true); 1889 Log3(("%s vnetTxTimer: Expired, %d packets pending\n", INSTANCE(pState), 1890 vringReadAvailIndex(&pState->VPCI, &pState->pTxQueue->VRing) - pState->pTxQueue->uNextAvailIndex)); 1891 vnetTransmitPendingPackets(pState, pState->pTxQueue); 1892 } 1893 1894 #else /* !VNET_TX_DELAY */ 1895 static DECLCALLBACK(void) vnetQueueTransmit(void *pvState, PVQUEUE pQueue) 1896 { 1897 VNETSTATE *pState = (VNETSTATE*)pvState; 1898 1899 vnetTransmitPendingPackets(pState, pQueue); 1900 } 1901 #endif /* !VNET_TX_DELAY */ 1902 1826 1903 static DECLCALLBACK(void) vnetQueueControl(void *pvState, PVQUEUE pQueue) 1827 1904 { … … 1969 2046 rc = SSMR3GetMem( pSSM, pState->config.mac.au8, sizeof(pState->config.mac)); 1970 2047 AssertRCReturn(rc, rc); 1971 /* Indicate link down to the guest OS that all network connections have1972 been lost, unless we've been teleported here. */1973 if (!PDMDevHlpVMTeleportedAndNotFullyResumedYet(pDevIns))1974 vnetTempLinkDown(pState);1975 2048 } 1976 2049 1977 2050 return rc; 2051 } 2052 2053 /** 2054 * Link status adjustments after loading. 2055 * 2056 * @returns VBox status code. 2057 * @param pDevIns The device instance. 2058 * @param pSSM The handle to the saved state. 2059 */ 2060 static DECLCALLBACK(int) vnetLoadDone(PPDMDEVINS pDevIns, PSSMHANDLE pSSM) 2061 { 2062 VNETSTATE *pState = PDMINS_2_DATA(pDevIns, VNETSTATE*); 2063 2064 /* 2065 * Indicate link down to the guest OS that all network connections have 2066 * been lost, unless we've been teleported here. 2067 */ 2068 if (!PDMDevHlpVMTeleportedAndNotFullyResumedYet(pDevIns)) 2069 vnetTempLinkDown(pState); 2070 2071 return VINF_SUCCESS; 1978 2072 } 1979 2073 … … 2046 2140 2047 2141 /* Register save/restore state handlers. */ 2048 rc = PDMDevHlpSSMRegisterEx(pDevIns, V NET_SAVEDSTATE_VERSION, sizeof(VNETSTATE), NULL,2142 rc = PDMDevHlpSSMRegisterEx(pDevIns, VIRTIO_SAVEDSTATE_VERSION, sizeof(VNETSTATE), NULL, 2049 2143 NULL, vnetLiveExec, NULL, 2050 2144 vnetSavePrep, vnetSaveExec, NULL, 2051 vnetLoadPrep, vnetLoadExec, NULL);2145 vnetLoadPrep, vnetLoadExec, vnetLoadDone); 2052 2146 if (RT_FAILURE(rc)) 2053 2147 return rc; … … 2067 2161 if (RT_FAILURE(rc)) 2068 2162 return rc; 2163 2164 #ifdef VNET_TX_DELAY 2165 /* Create Transmit Delay Timer */ 2166 rc = PDMDevHlpTMTimerCreate(pDevIns, TMCLOCK_VIRTUAL, vnetTxTimer, pState, 2167 TMTIMER_FLAGS_DEFAULT_CRIT_SECT, /** @todo check locking here. */ 2168 "VirtioNet TX Delay Timer", &pState->pTxTimerR3); 2169 if (RT_FAILURE(rc)) 2170 return rc; 2171 pState->pTxTimerR0 = TMTimerR0Ptr(pState->pTxTimerR3); 2172 pState->pTxTimerRC = TMTimerRCPtr(pState->pTxTimerR3); 2173 #endif /* VNET_TX_DELAY */ 2069 2174 2070 2175 rc = PDMDevHlpDriverAttach(pDevIns, 0, &pState->VPCI.IBase, &pState->pDrvBase, "Network Port"); … … 2161 2266 vpciRelocate(pDevIns, offDelta); 2162 2267 pState->pCanRxQueueRC = PDMQueueRCPtr(pState->pCanRxQueueR3); 2268 #ifdef VNET_TX_DELAY 2269 pState->pTxTimerRC = TMTimerRCPtr(pState->pTxTimerR3); 2270 #endif /* VNET_TX_DELAY */ 2163 2271 // TBD 2164 2272 }
Note:
See TracChangeset
for help on using the changeset viewer.