- Timestamp:
- Oct 27, 2009 9:46:51 PM (15 years ago)
- svn:sync-xref-src-repo-rev:
- 54027
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Network/DevVirtioNet.cpp
r23979 r24120 114 114 uint16_t uNextAvailIndex; 115 115 uint16_t uNextUsedIndex; 116 uint 16_t uPageNumber;116 uint32_t uPageNumber; 117 117 void (*pfnCallback)(void *pvState, struct VQueue *pQueue); 118 118 }; … … 499 499 } 500 500 501 /**502 * Arm a timer.503 *504 * @param pState Pointer to the device state structure.505 * @param pTimer Pointer to the timer.506 * @param uExpireIn Expiration interval in microseconds.507 */508 DECLINLINE(void) vpciArmTimer(VPCISTATE *pState, PTMTIMER pTimer, uint32_t uExpireIn)509 {510 Log2(("%s Arming timer to fire in %d usec...\n",511 INSTANCE(pState), uExpireIn));512 TMTimerSet(pTimer, TMTimerFromMicro(pTimer, uExpireIn) +513 TMTimerGet(pTimer));514 }515 516 501 517 502 DECLINLINE(int) vpciCsEnter(VPCISTATE *pState, int iBusyRc) … … 904 889 905 890 891 #ifdef DEBUG 892 static void vpciDumpState(PVPCISTATE pState, const char *pcszCaller) 893 { 894 Log2(("vpciDumpState: (called from %s)\n" 895 " uGuestFeatures = 0x%08x\n" 896 " uQueueSelector = 0x%04x\n" 897 " uStatus = 0x%02x\n" 898 " uISR = 0x%02x\n", 899 pcszCaller, 900 pState->uGuestFeatures, 901 pState->uQueueSelector, 902 pState->uStatus, 903 pState->uISR)); 904 905 for (unsigned i = 0; i < g_VPCIDevices[pState->enmDevType].nQueues; i++) 906 Log2((" %s queue:\n" 907 " VRing.uSize = %u\n" 908 " VRing.addrDescriptors = %p\n" 909 " VRing.addrAvail = %p\n" 910 " VRing.addrUsed = %p\n" 911 " uNextAvailIndex = %u\n" 912 " uNextUsedIndex = %u\n" 913 " uPageNumber = %x\n", 914 g_VPCIDevices[pState->enmDevType].pfnGetQueueName(pState, &pState->pQueues[i]), 915 pState->pQueues[i].VRing.uSize, 916 pState->pQueues[i].VRing.addrDescriptors, 917 pState->pQueues[i].VRing.addrAvail, 918 pState->pQueues[i].VRing.addrUsed, 919 pState->pQueues[i].uNextAvailIndex, 920 pState->pQueues[i].uNextUsedIndex, 921 pState->pQueues[i].uPageNumber)); 922 923 } 924 #else 925 #define vpciDumpState(x, s) 926 #endif 927 928 /** 929 * Saves the state of device. 930 * 931 * @returns VBox status code. 932 * @param pDevIns The device instance. 933 * @param pSSM The handle to the saved state. 934 */ 935 static DECLCALLBACK(int) vpciSaveExec(PVPCISTATE pState, PSSMHANDLE pSSM) 936 { 937 int rc; 938 939 vpciDumpState(pState, "vpciSaveExec"); 940 941 rc = SSMR3PutU32(pSSM, pState->uGuestFeatures); 942 AssertRCReturn(rc, rc); 943 rc = SSMR3PutU16(pSSM, pState->uQueueSelector); 944 AssertRCReturn(rc, rc); 945 rc = SSMR3PutU8( pSSM, pState->uStatus); 946 AssertRCReturn(rc, rc); 947 rc = SSMR3PutU8( pSSM, pState->uISR); 948 AssertRCReturn(rc, rc); 949 950 /* Save queue states */ 951 for (unsigned i = 0; i < g_VPCIDevices[pState->enmDevType].nQueues; i++) 952 { 953 rc = SSMR3PutU16(pSSM, pState->pQueues[i].VRing.uSize); 954 AssertRCReturn(rc, rc); 955 rc = SSMR3PutU32(pSSM, pState->pQueues[i].uPageNumber); 956 AssertRCReturn(rc, rc); 957 rc = SSMR3PutU16(pSSM, pState->pQueues[i].uNextAvailIndex); 958 AssertRCReturn(rc, rc); 959 rc = SSMR3PutU16(pSSM, pState->pQueues[i].uNextUsedIndex); 960 AssertRCReturn(rc, rc); 961 } 962 963 return VINF_SUCCESS; 964 } 965 966 /** 967 * Loads a saved device state. 968 * 969 * @returns VBox status code. 970 * @param pDevIns The device instance. 971 * @param pSSM The handle to the saved state. 972 * @param uVersion The data unit version number. 973 * @param uPass The data pass. 974 */ 975 static DECLCALLBACK(int) vpciLoadExec(PVPCISTATE pState, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass) 976 { 977 int rc; 978 979 if (uPass == SSM_PASS_FINAL) 980 { 981 /* Restore state data */ 982 rc = SSMR3GetU32(pSSM, &pState->uGuestFeatures); 983 AssertRCReturn(rc, rc); 984 rc = SSMR3GetU16(pSSM, &pState->uQueueSelector); 985 AssertRCReturn(rc, rc); 986 rc = SSMR3GetU8( pSSM, &pState->uStatus); 987 AssertRCReturn(rc, rc); 988 rc = SSMR3GetU8( pSSM, &pState->uISR); 989 AssertRCReturn(rc, rc); 990 991 /* Restore queues */ 992 for (unsigned i = 0; i < g_VPCIDevices[pState->enmDevType].nQueues; i++) 993 { 994 rc = SSMR3GetU16(pSSM, &pState->pQueues[i].VRing.uSize); 995 AssertRCReturn(rc, rc); 996 rc = SSMR3GetU32(pSSM, &pState->pQueues[i].uPageNumber); 997 AssertRCReturn(rc, rc); 998 999 if (pState->pQueues[i].uPageNumber) 1000 vqueueInit(&pState->pQueues[i], pState->pQueues[i].uPageNumber); 1001 1002 rc = SSMR3GetU16(pSSM, &pState->pQueues[i].uNextAvailIndex); 1003 AssertRCReturn(rc, rc); 1004 rc = SSMR3GetU16(pSSM, &pState->pQueues[i].uNextUsedIndex); 1005 AssertRCReturn(rc, rc); 1006 } 1007 } 1008 1009 vpciDumpState(pState, "vpciLoadExec"); 1010 1011 return VINF_SUCCESS; 1012 } 1013 906 1014 /** 907 1015 * Set PCI configuration space registers. … … 1125 1233 /** PCI config area holding MAC address as well as TBD. */ 1126 1234 struct VNetPCIConfig config; 1235 /** MAC address obtained from the configuration. */ 1236 RTMAC macConfigured; 1127 1237 /** True if physical cable is attached in configuration. */ 1128 1238 bool fCableConnected; … … 1198 1308 #endif /* DEBUG */ 1199 1309 1310 DECLINLINE(int) vnetCsEnter(PVNETSTATE pState, int rcBusy) 1311 { 1312 return vpciCsEnter(&pState->VPCI, rcBusy); 1313 } 1314 1315 DECLINLINE(void) vnetCsLeave(PVNETSTATE pState) 1316 { 1317 vpciCsLeave(&pState->VPCI); 1318 } 1319 1320 1200 1321 PDMBOTHCBDECL(uint32_t) vnetGetHostFeatures(void *pvState) 1201 1322 { … … 1283 1404 STATUS |= VNET_S_LINK_UP; 1284 1405 vpciRaiseInterrupt(&pState->VPCI, VERR_SEM_BUSY, VPCI_ISR_CONFIG); 1406 vnetWakeupReceive(pDevIns); 1285 1407 } 1286 1408 … … 1330 1452 * @returns VERR_NET_NO_BUFFER_SPACE if it cannot. 1331 1453 * @param pInterface Pointer to the interface structure containing the called function pointer. 1332 * @thread EMT1454 * @thread RX 1333 1455 */ 1334 1456 static int vnetCanReceive(VNETSTATE *pState) 1335 1457 { 1336 int rc ;1458 int rc = vpciCsEnter(&pState->VPCI, VERR_SEM_BUSY); 1337 1459 LogFlow(("%s vnetCanReceive\n", INSTANCE(pState))); 1338 1460 if (!(pState->VPCI.uStatus & VPCI_STATUS_DRV_OK)) … … 1352 1474 1353 1475 LogFlow(("%s vnetCanReceive -> %Vrc\n", INSTANCE(pState), rc)); 1476 vpciCsLeave(&pState->VPCI); 1354 1477 return rc; 1355 1478 } … … 1440 1563 * @param pvBuf The available data. 1441 1564 * @param cb Number of bytes available in the buffer. 1565 * @thread RX 1442 1566 */ 1443 1567 static int vnetHandleRxPacket(PVNETSTATE pState, const void *pvBuf, size_t cb) … … 1500 1624 * @param pvBuf The available data. 1501 1625 * @param cb Number of bytes available in the buffer. 1502 * @thread ???1626 * @thread RX 1503 1627 */ 1504 1628 static DECLCALLBACK(int) vnetReceive(PPDMINETWORKPORT pInterface, const void *pvBuf, size_t cb) … … 1657 1781 } 1658 1782 1783 /** 1784 * Saves the configuration. 1785 * 1786 * @param pState The VNET state. 1787 * @param pSSM The handle to the saved state. 1788 */ 1789 static void vnetSaveConfig(VNETSTATE *pState, PSSMHANDLE pSSM) 1790 { 1791 SSMR3PutMem(pSSM, &pState->macConfigured, sizeof(pState->macConfigured)); 1792 } 1793 1794 /** 1795 * Live save - save basic configuration. 1796 * 1797 * @returns VBox status code. 1798 * @param pDevIns The device instance. 1799 * @param pSSM The handle to the saved state. 1800 * @param uPass 1801 */ 1802 static DECLCALLBACK(int) vnetLiveExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, uint32_t uPass) 1803 { 1804 VNETSTATE *pState = PDMINS_2_DATA(pDevIns, VNETSTATE*); 1805 vnetSaveConfig(pState, pSSM); 1806 return VINF_SSM_DONT_CALL_AGAIN; 1807 } 1808 1809 /** 1810 * Prepares for state saving. 1811 * 1812 * @returns VBox status code. 1813 * @param pDevIns The device instance. 1814 * @param pSSM The handle to the saved state. 1815 */ 1816 static DECLCALLBACK(int) vnetSavePrep(PPDMDEVINS pDevIns, PSSMHANDLE pSSM) 1817 { 1818 VNETSTATE* pState = PDMINS_2_DATA(pDevIns, VNETSTATE*); 1819 1820 int rc = vnetCsEnter(pState, VERR_SEM_BUSY); 1821 if (RT_UNLIKELY(rc != VINF_SUCCESS)) 1822 return rc; 1823 vnetCsLeave(pState); 1824 return VINF_SUCCESS; 1825 } 1826 1827 /** 1828 * Saves the state of device. 1829 * 1830 * @returns VBox status code. 1831 * @param pDevIns The device instance. 1832 * @param pSSM The handle to the saved state. 1833 */ 1834 static DECLCALLBACK(int) vnetSaveExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM) 1835 { 1836 VNETSTATE* pState = PDMINS_2_DATA(pDevIns, VNETSTATE*); 1837 1838 /* Save config first */ 1839 vnetSaveConfig(pState, pSSM); 1840 1841 /* Save the common part */ 1842 int rc = vpciSaveExec(&pState->VPCI, pSSM); 1843 AssertRCReturn(rc, rc); 1844 /* Save device-specific part */ 1845 rc = SSMR3PutMem( pSSM, pState->config.mac.au8, sizeof(pState->config.mac)); 1846 AssertRCReturn(rc, rc); 1847 Log(("%s State has been saved\n", INSTANCE(pState))); 1848 return VINF_SUCCESS; 1849 } 1850 1851 1852 /** 1853 * Serializes the receive thread, it may be working inside the critsect. 1854 * 1855 * @returns VBox status code. 1856 * @param pDevIns The device instance. 1857 * @param pSSM The handle to the saved state. 1858 */ 1859 static DECLCALLBACK(int) vnetLoadPrep(PPDMDEVINS pDevIns, PSSMHANDLE pSSM) 1860 { 1861 VNETSTATE* pState = PDMINS_2_DATA(pDevIns, VNETSTATE*); 1862 1863 int rc = vnetCsEnter(pState, VERR_SEM_BUSY); 1864 if (RT_UNLIKELY(rc != VINF_SUCCESS)) 1865 return rc; 1866 vnetCsLeave(pState); 1867 return VINF_SUCCESS; 1868 } 1869 1870 /* Takes down the link temporarily if it's current status is up. 1871 * 1872 * This is used during restore and when replumbing the network link. 1873 * 1874 * The temporary link outage is supposed to indicate to the OS that all network 1875 * connections have been lost and that it for instance is appropriate to 1876 * renegotiate any DHCP lease. 1877 * 1878 * @param pThis The PCNet instance data. 1879 */ 1880 static void vnetTempLinkDown(PVNETSTATE pState) 1881 { 1882 if (STATUS & VNET_S_LINK_UP) 1883 { 1884 STATUS &= ~VNET_S_LINK_UP; 1885 vpciRaiseInterrupt(&pState->VPCI, VERR_SEM_BUSY, VPCI_ISR_CONFIG); 1886 /* Restore the link back in 5 seconds. */ 1887 int rc = TMTimerSetMillies(pState->pLinkUpTimer, 5000); 1888 AssertRC(rc); 1889 } 1890 } 1891 1892 1893 /** 1894 * Restore previously saved state of device. 1895 * 1896 * @returns VBox status code. 1897 * @param pDevIns The device instance. 1898 * @param pSSM The handle to the saved state. 1899 * @param uVersion The data unit version number. 1900 * @param uPass The data pass. 1901 */ 1902 static DECLCALLBACK(int) vnetLoadExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass) 1903 { 1904 VNETSTATE *pState = PDMINS_2_DATA(pDevIns, VNETSTATE*); 1905 int rc; 1906 1907 /* config checks */ 1908 RTMAC macConfigured; 1909 rc = SSMR3GetMem(pSSM, &macConfigured, sizeof(macConfigured)); 1910 AssertRCReturn(rc, rc); 1911 if ( memcmp(&macConfigured, &pState->macConfigured, sizeof(macConfigured)) 1912 && (uPass == 0 || !PDMDevHlpVMTeleportedAndNotFullyResumedYet(pDevIns)) ) 1913 LogRel(("%s: The mac address differs: config=%RTmac saved=%RTmac\n", INSTANCE(pState), &pState->macConfigured, &macConfigured)); 1914 1915 rc = vpciLoadExec(&pState->VPCI, pSSM, uVersion, uPass); 1916 AssertRCReturn(rc, rc); 1917 1918 if (uPass == SSM_PASS_FINAL) 1919 { 1920 rc = SSMR3GetMem( pSSM, pState->config.mac.au8, sizeof(pState->config.mac)); 1921 AssertRCReturn(rc, rc); 1922 /* Indicate link down to the guest OS that all network connections have 1923 been lost, unless we've been teleported here. */ 1924 if (!PDMDevHlpVMTeleportedAndNotFullyResumedYet(pDevIns)) 1925 vnetTempLinkDown(pState); 1926 } 1927 1928 return rc; 1929 } 1659 1930 1660 1931 /** … … 1696 1967 1697 1968 /* Get config params */ 1698 rc = CFGMR3QueryBytes(pCfgHandle, "MAC", pState-> config.mac.au8,1699 sizeof(pState-> config.mac.au8));1969 rc = CFGMR3QueryBytes(pCfgHandle, "MAC", pState->macConfigured.au8, 1970 sizeof(pState->macConfigured)); 1700 1971 if (RT_FAILURE(rc)) 1701 1972 return PDMDEV_SET_ERROR(pDevIns, rc, … … 1706 1977 N_("Configuration error: Failed to get the value of 'CableConnected'")); 1707 1978 1979 /* Initialize PCI config space */ 1980 memcpy(pState->config.mac.au8, pState->macConfigured.au8, sizeof(pState->config.mac.au8)); 1981 pState->config.uStatus = 0; 1982 1708 1983 /* Initialize state structure */ 1709 1984 pState->fLocked = false; … … 1718 1993 1719 1994 /* Register save/restore state handlers. */ 1720 // TODO: 1721 /* 1722 rc = PDMDevHlpSSMRegisterEx(pDevIns, VVNET_SAVEDSTATE_VERSION, sizeof(VNETSTATE), NULL, 1723 NULL, NULL, NULL, 1724 NULL, vnetSaveExec, NULL, 1725 NULL, vnetLoadExec, vnetLoadDone); 1995 rc = PDMDevHlpSSMRegisterEx(pDevIns, VNET_SAVEDSTATE_VERSION, sizeof(VNETSTATE), NULL, 1996 NULL, vnetLiveExec, NULL, 1997 vnetSavePrep, vnetSaveExec, NULL, 1998 vnetLoadPrep, vnetLoadExec, NULL); 1726 1999 if (RT_FAILURE(rc)) 1727 return rc; */2000 return rc; 1728 2001 1729 2002 /* Create the RX notifier signaller. */ … … 1924 2197 * network card 1925 2198 */ 1926 if ((STATUS & VNET_S_LINK_UP) && RT_SUCCESS(rc)) 1927 { 1928 STATUS &= ~VNET_S_LINK_UP; 1929 vpciRaiseInterrupt(&pState->VPCI, VERR_SEM_BUSY, VPCI_ISR_CONFIG); 1930 /* Restore the link back in 5 seconds. */ 1931 vpciArmTimer(&pState->VPCI, pState->pLinkUpTimer, 5000000); 1932 } 2199 if (RT_SUCCESS(rc)) 2200 vnetTempLinkDown(pState); 1933 2201 1934 2202 vpciCsLeave(&pState->VPCI);
Note:
See TracChangeset
for help on using the changeset viewer.