Changeset 100400 in vbox for trunk/src/VBox/Devices/VirtIO
- Timestamp:
- Jul 6, 2023 8:58:02 AM (17 months ago)
- Location:
- trunk/src/VBox/Devices/VirtIO
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/VirtIO/VirtioCore.cpp
r100372 r100400 1230 1230 Log6Func(("Reason for interrupt - device config change\n")); 1231 1231 1232 if (!pVirtio->fMsiSupport) 1232 if (pVirtio->uIrqMmio) 1233 { 1234 pVirtio->uISR |= uCause; 1235 PDMDevHlpISASetIrq(pDevIns, pVirtio->uIrqMmio, PDM_IRQ_LEVEL_HIGH); 1236 } 1237 else if (!pVirtio->fMsiSupport) 1233 1238 { 1234 1239 pVirtio->uISR |= uCause; … … 1248 1253 { 1249 1254 PVIRTIOCORE pVirtio = PDMINS_2_DATA(pDevIns, PVIRTIOCORE); 1250 if (!pVirtio->fMsiSupport) 1255 if (pVirtio->uIrqMmio) 1256 PDMDevHlpISASetIrq(pDevIns, pVirtio->uIrqMmio, PDM_IRQ_LEVEL_LOW); 1257 else if (!pVirtio->fMsiSupport) 1251 1258 PDMDevHlpPCISetIrq(pDevIns, 0, PDM_IRQ_LEVEL_LOW); 1252 1259 else if (uMsixVector != VIRTIO_MSI_NO_VECTOR) … … 1347 1354 } 1348 1355 #endif 1356 1357 1358 /** 1359 * Handles a write to the device status register from the driver. 1360 * 1361 * @returns VBox status code 1362 * 1363 * @param pDevIns The device instance. 1364 * @param pVirtio Pointer to the shared virtio state. 1365 * @param pVirtioCC Pointer to the current context virtio state. 1366 * @param fDeviceStatus The device status to be written. 1367 */ 1368 DECLINLINE(int) virtioDeviceStatusWrite(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, PVIRTIOCORECC pVirtioCC, 1369 uint8_t fDeviceStatus) 1370 { 1371 pVirtio->fDeviceStatus = fDeviceStatus; 1372 bool fDeviceReset = pVirtio->fDeviceStatus == 0; 1373 #ifdef LOG_ENABLED 1374 if (LogIs7Enabled()) 1375 { 1376 char szOut[80] = { 0 }; 1377 virtioCoreFormatDeviceStatus(pVirtio->fDeviceStatus, szOut, sizeof(szOut)); 1378 Log(("%-23s: Guest wrote fDeviceStatus ................ (%s)\n", __FUNCTION__, szOut)); 1379 } 1380 #endif 1381 bool const fStatusChanged = IS_DRIVER_OK(pVirtio) != WAS_DRIVER_OK(pVirtio); 1382 1383 if (fDeviceReset || fStatusChanged) 1384 { 1385 #ifdef IN_RING0 1386 /* Since VirtIO status changes are cumbersome by nature, e.g. not a benchmark priority, 1387 * handle the rest in R3 to facilitate logging or whatever dev-specific client needs to do */ 1388 Log6(("%-23s: RING0 => RING3 (demote)\n", __FUNCTION__)); 1389 return VINF_IOM_R3_MMIO_WRITE; 1390 #endif 1391 } 1392 1393 #ifdef IN_RING3 1394 /* 1395 * Notify client only if status actually changed from last time and when we're reset. 1396 */ 1397 if (fDeviceReset) 1398 virtioGuestR3WasReset(pDevIns, pVirtio, pVirtioCC); 1399 1400 if (fStatusChanged) 1401 pVirtioCC->pfnStatusChanged(pVirtio, pVirtioCC, IS_DRIVER_OK(pVirtio)); 1402 #endif 1403 /* 1404 * Save the current status for the next write so we can see what changed. 1405 */ 1406 pVirtio->fPrevDeviceStatus = pVirtio->fDeviceStatus; 1407 return VINF_SUCCESS; 1408 } 1409 1410 1411 /** 1412 * Handles a read from the device status register from the driver. 1413 * 1414 * @returns The device status register value. 1415 * 1416 * @param pVirtio Pointer to the shared virtio state. 1417 */ 1418 DECLINLINE(uint8_t) virtioDeviceStatusRead(PVIRTIOCORE pVirtio) 1419 { 1420 #ifdef LOG_ENABLED 1421 if (LogIs7Enabled()) 1422 { 1423 char szOut[80] = { 0 }; 1424 virtioCoreFormatDeviceStatus(pVirtio->fDeviceStatus, szOut, sizeof(szOut)); 1425 LogFunc(("Guest read fDeviceStatus ................ (%s)\n", szOut)); 1426 } 1427 #endif 1428 return pVirtio->fDeviceStatus; 1429 } 1430 1349 1431 1350 1432 /** … … 1475 1557 { 1476 1558 if (fWrite) /* Guest WRITE pCommonCfg->fDeviceStatus */ 1477 { 1478 pVirtio->fDeviceStatus = *(uint8_t *)pv; 1479 bool fDeviceReset = pVirtio->fDeviceStatus == 0; 1480 #ifdef LOG_ENABLED 1481 if (LogIs7Enabled()) 1482 { 1483 char szOut[80] = { 0 }; 1484 virtioCoreFormatDeviceStatus(pVirtio->fDeviceStatus, szOut, sizeof(szOut)); 1485 Log(("%-23s: Guest wrote fDeviceStatus ................ (%s)\n", __FUNCTION__, szOut)); 1486 } 1487 #endif 1488 bool const fStatusChanged = IS_DRIVER_OK(pVirtio) != WAS_DRIVER_OK(pVirtio); 1489 1490 if (fDeviceReset || fStatusChanged) 1491 { 1492 #ifdef IN_RING0 1493 /* Since VirtIO status changes are cumbersome by nature, e.g. not a benchmark priority, 1494 * handle the rest in R3 to facilitate logging or whatever dev-specific client needs to do */ 1495 Log6(("%-23s: RING0 => RING3 (demote)\n", __FUNCTION__)); 1496 return VINF_IOM_R3_MMIO_WRITE; 1497 #endif 1498 } 1499 1500 #ifdef IN_RING3 1501 /* 1502 * Notify client only if status actually changed from last time and when we're reset. 1503 */ 1504 if (fDeviceReset) 1505 virtioGuestR3WasReset(pDevIns, pVirtio, pVirtioCC); 1506 1507 if (fStatusChanged) 1508 pVirtioCC->pfnStatusChanged(pVirtio, pVirtioCC, IS_DRIVER_OK(pVirtio)); 1509 #endif 1510 /* 1511 * Save the current status for the next write so we can see what changed. 1512 */ 1513 pVirtio->fPrevDeviceStatus = pVirtio->fDeviceStatus; 1514 } 1559 rc = virtioDeviceStatusWrite(pDevIns, pVirtio, pVirtioCC, *(uint8_t *)pv); 1515 1560 else /* Guest READ pCommonCfg->fDeviceStatus */ 1516 { 1517 *(uint8_t *)pv = pVirtio->fDeviceStatus; 1518 #ifdef LOG_ENABLED 1519 if (LogIs7Enabled()) 1520 { 1521 char szOut[80] = { 0 }; 1522 virtioCoreFormatDeviceStatus(pVirtio->fDeviceStatus, szOut, sizeof(szOut)); 1523 LogFunc(("Guest read fDeviceStatus ................ (%s)\n", szOut)); 1524 } 1525 #endif 1526 } 1561 *(uint8_t *)pv = virtioDeviceStatusRead(pVirtio); 1527 1562 } 1528 1563 else … … 1884 1919 1885 1920 /** 1886 * @callback_method_impl{FNIOMMMIONEWREAD, 1887 * Memory mapped I/O Handler for PCI Capabilities read operations.} 1888 * 1889 * This MMIO handler specifically supports the VIRTIO_PCI_CAP_PCI_CFG capability defined 1890 * in the VirtIO 1.0 specification, section 4.1.4.7, and as such is restricted to reads 1891 * of 1, 2 or 4 bytes, only. 1892 * 1893 */ 1894 static DECLCALLBACK(VBOXSTRICTRC) virtioMmioRead(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS off, void *pv, unsigned cb) 1895 { 1896 PVIRTIOCORE pVirtio = PDMINS_2_DATA(pDevIns, PVIRTIOCORE); 1897 PVIRTIOCORECC pVirtioCC = PDMINS_2_DATA_CC(pDevIns, PVIRTIOCORECC); 1898 AssertReturn(cb == 1 || cb == 2 || cb == 4, VERR_INVALID_PARAMETER); 1899 Assert(pVirtio == (PVIRTIOCORE)pvUser); RT_NOREF(pvUser); 1900 STAM_PROFILE_ADV_START(&pVirtio->CTX_SUFF(StatRead), a); 1901 1902 1903 uint32_t uOffset; 1904 if (MATCHES_VIRTIO_CAP_STRUCT(off, cb, uOffset, pVirtio->LocDeviceCap)) 1905 { 1921 * Read from the device specific configuration at the given offset. 1922 * 1923 * @returns VBox status code. 1924 * @param pDevIns 1925 */ 1926 DECLINLINE(VBOXSTRICTRC) virtioDeviceCfgRead(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, PVIRTIOCORECC pVirtioCC, 1927 uint32_t offDevCfg, void *pv, unsigned cb) 1928 { 1906 1929 #ifdef IN_RING3 1907 1930 /* 1908 1931 * Callback to client to manage device-specific configuration. 1909 1932 */ 1910 VBOXSTRICTRC rcStrict = pVirtioCC->pfnDevCapRead(pDevIns, uOffset, pv, cb);1933 VBOXSTRICTRC rcStrict = pVirtioCC->pfnDevCapRead(pDevIns, offDevCfg, pv, cb); 1911 1934 1912 1935 /* … … 1915 1938 * for deltas from previous read to maintain a config gen. seq. counter (VirtIO 1.0, section 4.1.4.3.1) 1916 1939 */ 1917 bool fDevSpecificFieldChanged = RT_BOOL(memcmp(pVirtioCC->pbDevSpecificCfg + uOffset,1918 pVirtioCC->pbPrevDevSpecificCfg + uOffset,1919 RT_MIN(cb, pVirtioCC->cbDevSpecificCfg - uOffset)));1940 bool fDevSpecificFieldChanged = RT_BOOL(memcmp(pVirtioCC->pbDevSpecificCfg + offDevCfg, 1941 pVirtioCC->pbPrevDevSpecificCfg + offDevCfg, 1942 RT_MIN(cb, pVirtioCC->cbDevSpecificCfg - offDevCfg))); 1920 1943 1921 1944 memcpy(pVirtioCC->pbPrevDevSpecificCfg, pVirtioCC->pbDevSpecificCfg, pVirtioCC->cbDevSpecificCfg); … … 1931 1954 1932 1955 virtioLowerInterrupt(pDevIns, 0); 1933 STAM_PROFILE_ADV_STOP(&pVirtio->CTX_SUFF(StatRead), a);1934 1956 return rcStrict; 1935 1957 #else 1936 STAM_PROFILE_ADV_STOP(&pVirtio->CTX_SUFF(StatRead), a);1937 1958 return VINF_IOM_R3_MMIO_READ; 1938 1959 #endif 1939 } 1940 1941 if (MATCHES_VIRTIO_CAP_STRUCT(off, cb, uOffset, pVirtio->LocCommonCfgCap)) 1942 return virtioCommonCfgAccessed(pDevIns, pVirtio, pVirtioCC, false /* fWrite */, uOffset, cb, pv); 1943 1944 if (MATCHES_VIRTIO_CAP_STRUCT(off, cb, uOffset, pVirtio->LocIsrCap)) 1960 } 1961 1962 1963 /** 1964 * @callback_method_impl{FNIOMMMIONEWREAD, 1965 * Memory mapped I/O Handler for PCI Capabilities read operations.} 1966 * 1967 * This MMIO handler specifically supports the VIRTIO_PCI_CAP_PCI_CFG capability defined 1968 * in the VirtIO 1.0 specification, section 4.1.4.7, and as such is restricted to reads 1969 * of 1, 2 or 4 bytes, only. 1970 * 1971 */ 1972 static DECLCALLBACK(VBOXSTRICTRC) virtioMmioRead(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS off, void *pv, unsigned cb) 1973 { 1974 PVIRTIOCORE pVirtio = PDMINS_2_DATA(pDevIns, PVIRTIOCORE); 1975 PVIRTIOCORECC pVirtioCC = PDMINS_2_DATA_CC(pDevIns, PVIRTIOCORECC); 1976 AssertReturn(cb == 1 || cb == 2 || cb == 4, VERR_INVALID_PARAMETER); 1977 Assert(pVirtio == (PVIRTIOCORE)pvUser); RT_NOREF(pvUser); 1978 1979 STAM_PROFILE_ADV_START(&pVirtio->CTX_SUFF(StatRead), a); 1980 1981 VBOXSTRICTRC rcStrict; 1982 uint32_t uOffset; 1983 if (MATCHES_VIRTIO_CAP_STRUCT(off, cb, uOffset, pVirtio->LocDeviceCap)) 1984 rcStrict = virtioDeviceCfgRead(pDevIns, pVirtio, pVirtioCC, uOffset, pv, cb); 1985 else if (MATCHES_VIRTIO_CAP_STRUCT(off, cb, uOffset, pVirtio->LocCommonCfgCap)) 1986 rcStrict = virtioCommonCfgAccessed(pDevIns, pVirtio, pVirtioCC, false /* fWrite */, uOffset, cb, pv); 1987 else if (MATCHES_VIRTIO_CAP_STRUCT(off, cb, uOffset, pVirtio->LocIsrCap)) 1945 1988 { 1946 1989 *(uint8_t *)pv = pVirtio->uISR; … … 1948 1991 pVirtio->uISR = 0; /* VirtIO spec requires reads of ISR to clear it */ 1949 1992 virtioLowerInterrupt(pDevIns, 0); 1950 STAM_PROFILE_ADV_STOP(&pVirtio->CTX_SUFF(StatRead), a); 1951 return VINF_SUCCESS; 1952 } 1953 1954 ASSERT_GUEST_MSG_FAILED(("Bad read access to mapped capabilities region: off=%RGp cb=%u\n", off, cb)); 1993 rcStrict = VINF_SUCCESS; 1994 } 1995 else 1996 { 1997 ASSERT_GUEST_MSG_FAILED(("Bad read access to mapped capabilities region: off=%RGp cb=%u\n", off, cb)); 1998 rcStrict = PDMDevHlpDBGFStop(pDevIns, RT_SRC_POS, 1999 "virtioMmioRead: Bad MMIO access to capabilities, offset=%RTiop cb=%08x\n", off, cb); 2000 } 2001 1955 2002 STAM_PROFILE_ADV_STOP(&pVirtio->CTX_SUFF(StatRead), a); 1956 int rc = PDMDevHlpDBGFStop(pDevIns, RT_SRC_POS, 1957 "virtioMmioRead: Bad MMIO access to capabilities, offset=%RTiop cb=%08x\n", off, cb); 1958 return rc; 2003 return rcStrict; 1959 2004 } 1960 2005 … … 1975 2020 STAM_PROFILE_ADV_START(&pVirtio->CTX_SUFF(StatWrite), a); 1976 2021 2022 VBOXSTRICTRC rcStrict; 1977 2023 uint32_t uOffset; 1978 2024 if (MATCHES_VIRTIO_CAP_STRUCT(off, cb, uOffset, pVirtio->LocDeviceCap)) … … 1982 2028 * Foreward this MMIO write access for client to deal with. 1983 2029 */ 1984 STAM_PROFILE_ADV_STOP(&pVirtio->CTX_SUFF(StatWrite), a); 1985 return pVirtioCC->pfnDevCapWrite(pDevIns, uOffset, pv, cb); 2030 rcStrict = pVirtioCC->pfnDevCapWrite(pDevIns, uOffset, pv, cb); 1986 2031 #else 1987 STAM_PROFILE_ADV_STOP(&pVirtio->CTX_SUFF(StatWrite), a);1988 2032 Log6(("%-23s: RING0 => RING3 (demote)\n", __FUNCTION__)); 1989 return VINF_IOM_R3_MMIO_WRITE; 1990 #endif 1991 } 1992 1993 if (MATCHES_VIRTIO_CAP_STRUCT(off, cb, uOffset, pVirtio->LocCommonCfgCap)) 1994 { 1995 STAM_PROFILE_ADV_STOP(&pVirtio->CTX_SUFF(StatWrite), a); 1996 return virtioCommonCfgAccessed(pDevIns, pVirtio, pVirtioCC, true /* fWrite */, uOffset, cb, (void *)pv); 1997 } 1998 1999 if (MATCHES_VIRTIO_CAP_STRUCT(off, cb, uOffset, pVirtio->LocIsrCap) && cb == sizeof(uint8_t)) 2033 rcStrict = VINF_IOM_R3_MMIO_WRITE; 2034 #endif 2035 } 2036 else if (MATCHES_VIRTIO_CAP_STRUCT(off, cb, uOffset, pVirtio->LocCommonCfgCap)) 2037 rcStrict = virtioCommonCfgAccessed(pDevIns, pVirtio, pVirtioCC, true /* fWrite */, uOffset, cb, (void *)pv); 2038 else if (MATCHES_VIRTIO_CAP_STRUCT(off, cb, uOffset, pVirtio->LocIsrCap) && cb == sizeof(uint8_t)) 2000 2039 { 2001 2040 pVirtio->uISR = *(uint8_t *)pv; … … 2004 2043 pVirtio->uISR & VIRTIO_ISR_VIRTQ_INTERRUPT, 2005 2044 RT_BOOL(pVirtio->uISR & VIRTIO_ISR_DEVICE_CONFIG))); 2045 rcStrict = VINF_SUCCESS; 2046 } 2047 else if (MATCHES_VIRTIO_CAP_STRUCT(off, cb, uOffset, pVirtio->LocNotifyCap) && cb == sizeof(uint16_t)) 2048 { 2049 /* This *should* be guest driver dropping index of a new descriptor in avail ring */ 2050 virtioCoreVirtqNotified(pDevIns, pVirtio, uOffset / VIRTIO_NOTIFY_OFFSET_MULTIPLIER, *(uint16_t *)pv); 2051 rcStrict = VINF_SUCCESS; 2052 } 2053 else 2054 { 2055 ASSERT_GUEST_MSG_FAILED(("Bad write access to mapped capabilities region: off=%RGp pv=%#p{%.*Rhxs} cb=%u\n", off, pv, cb, pv, cb)); 2056 rcStrict = PDMDevHlpDBGFStop(pDevIns, RT_SRC_POS, 2057 "virtioMmioRead: Bad MMIO access to capabilities, offset=%RTiop cb=%08x\n", off, cb); 2058 } 2059 2060 STAM_PROFILE_ADV_STOP(&pVirtio->CTX_SUFF(StatWrite), a); 2061 return rcStrict; 2062 } 2063 2064 2065 /** 2066 * @callback_method_impl{FNIOMMMIONEWREAD, 2067 * Memory mapped I/O Handler for Virtio over MMIO read operations.} 2068 * 2069 */ 2070 static DECLCALLBACK(VBOXSTRICTRC) virtioMmioTransportRead(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS off, void *pv, unsigned cb) 2071 { 2072 PVIRTIOCORE pVirtio = PDMINS_2_DATA(pDevIns, PVIRTIOCORE); 2073 PVIRTIOCORECC pVirtioCC = PDMINS_2_DATA_CC(pDevIns, PVIRTIOCORECC); 2074 RT_NOREF(pvUser); 2075 STAM_PROFILE_ADV_START(&pVirtio->CTX_SUFF(StatRead), a); 2076 2077 if (off >= VIRTIO_MMIO_SIZE) 2078 { 2079 VBOXSTRICTRC rcStrict = virtioDeviceCfgRead(pDevIns, pVirtio, pVirtioCC, (uint32_t)off - VIRTIO_MMIO_SIZE, pv, cb); 2080 STAM_PROFILE_ADV_STOP(&pVirtio->CTX_SUFF(StatRead), a); 2081 return rcStrict; 2082 } 2083 2084 /* All accesses below need to be aligned on a 32-bit boundary and must be 32-bit in size. */ 2085 ASSERT_GUEST_MSG_RETURN(!(off & 0x3) && cb == sizeof(uint32_t), 2086 ("Bad read access: off=%RGp pv=%#p{%.*Rhxs} cb=%u\n", off, pv, cb, pv, cb), 2087 VINF_IOM_MMIO_UNUSED_FF); 2088 2089 int rc = VINF_SUCCESS; 2090 uint32_t *pu32 = (uint32_t *)pv; 2091 switch (off) 2092 { 2093 case VIRTIO_MMIO_REG_MAGIC_OFF: 2094 *pu32 = RT_H2LE_U32(VIRTIO_MMIO_REG_MAGIC_VALUE); 2095 break; 2096 case VIRTIO_MMIO_REG_VERSION_OFF: 2097 *pu32 = RT_H2LE_U32(VIRTIO_MMIO_REG_VERSION_VALUE); 2098 break; 2099 case VIRTIO_MMIO_REG_DEVICEID_OFF: 2100 *pu32 = pVirtio->uDeviceType; 2101 break; 2102 case VIRTIO_MMIO_REG_VENDORID_OFF: 2103 *pu32 = RT_H2LE_U32(DEVICE_PCI_VENDOR_ID_VIRTIO); 2104 break; 2105 case VIRTIO_MMIO_REG_DEVICEFEAT_OFF: 2106 { 2107 switch (pVirtio->uDeviceFeaturesSelect) 2108 { 2109 case 0: 2110 *pu32 = pVirtio->uDeviceFeatures & UINT32_C(0xffffffff); 2111 break; 2112 case 1: 2113 *pu32 = pVirtio->uDeviceFeatures >> 32; 2114 break; 2115 default: 2116 LogFunc(("Guest read uDeviceFeatures with out of range selector (%#x), returning 0\n", 2117 pVirtio->uDeviceFeaturesSelect)); 2118 rc = VINF_IOM_MMIO_UNUSED_00; 2119 } 2120 break; 2121 } 2122 case VIRTIO_MMIO_REG_QUEUENUMMAX_OFF: 2123 *pu32 = VIRTQ_SIZE; /** @todo */ 2124 break; 2125 case VIRTIO_MMIO_REG_QUEUERDY_OFF: 2126 { 2127 Assert(pVirtio->uVirtqSelect < RT_ELEMENTS(pVirtio->aVirtqueues)); 2128 PVIRTQUEUE pVirtQueue = &pVirtio->aVirtqueues[pVirtio->uVirtqSelect]; 2129 *pu32 = pVirtQueue->uEnable; 2130 break; 2131 } 2132 case VIRTIO_MMIO_REG_INTRSTATUS_OFF: 2133 *pu32 = pVirtio->uISR; 2134 break; 2135 case VIRTIO_MMIO_REG_DEVSTATUS_OFF: 2136 *pu32 = virtioDeviceStatusRead(pVirtio); 2137 break; 2138 case VIRTIO_MMIO_REG_CFGGEN_OFF: 2139 *pu32 = pVirtio->uConfigGeneration; 2140 break; 2141 default: 2142 ASSERT_GUEST_MSG_FAILED(("Bad read access to mapped capabilities region: off=%RGp cb=%u\n", off, cb)); 2143 rc = PDMDevHlpDBGFStop(pDevIns, RT_SRC_POS, 2144 "virtioMmioTransportRead: Bad MMIO access to capabilities, offset=%RTiop cb=%08x\n", off, cb); 2145 } 2146 2147 STAM_PROFILE_ADV_STOP(&pVirtio->CTX_SUFF(StatRead), a); 2148 return rc; 2149 } 2150 2151 /** 2152 * @callback_method_impl{FNIOMMMIONEWREAD, 2153 * Memory mapped I/O Handler for Virtio over MMIO write operations.} 2154 */ 2155 static DECLCALLBACK(VBOXSTRICTRC) virtioMmioTransportWrite(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS off, void const *pv, unsigned cb) 2156 { 2157 PVIRTIOCORE pVirtio = PDMINS_2_DATA(pDevIns, PVIRTIOCORE); 2158 PVIRTIOCORECC pVirtioCC = PDMINS_2_DATA_CC(pDevIns, PVIRTIOCORECC); 2159 RT_NOREF(pvUser); 2160 STAM_PROFILE_ADV_START(&pVirtio->CTX_SUFF(StatWrite), a); 2161 2162 if (off >= VIRTIO_MMIO_SIZE) 2163 { 2164 #ifdef IN_RING3 2165 /* 2166 * Forward this MMIO write access for client to deal with. 2167 */ 2006 2168 STAM_PROFILE_ADV_STOP(&pVirtio->CTX_SUFF(StatWrite), a); 2007 return VINF_SUCCESS; 2008 } 2009 2010 /* This *should* be guest driver dropping index of a new descriptor in avail ring */ 2011 if (MATCHES_VIRTIO_CAP_STRUCT(off, cb, uOffset, pVirtio->LocNotifyCap) && cb == sizeof(uint16_t)) 2012 { 2013 virtioCoreVirtqNotified(pDevIns, pVirtio, uOffset / VIRTIO_NOTIFY_OFFSET_MULTIPLIER, *(uint16_t *)pv); 2169 return pVirtioCC->pfnDevCapWrite(pDevIns, (uint32_t)off - VIRTIO_MMIO_SIZE, pv, cb); 2170 #else 2014 2171 STAM_PROFILE_ADV_STOP(&pVirtio->CTX_SUFF(StatWrite), a); 2015 return VINF_SUCCESS; 2016 } 2017 2018 ASSERT_GUEST_MSG_FAILED(("Bad write access to mapped capabilities region: off=%RGp pv=%#p{%.*Rhxs} cb=%u\n", off, pv, cb, pv, cb)); 2172 Log6(("%-23s: RING0 => RING3 (demote)\n", __FUNCTION__)); 2173 return VINF_IOM_R3_MMIO_WRITE; 2174 #endif 2175 } 2176 2177 /* All accesses below need to be aligned on a 32-bit boundary and must be 32-bit in size. */ 2178 ASSERT_GUEST_MSG_RETURN(!(off & 0x3) && cb == sizeof(uint32_t), 2179 ("Bad write access: off=%RGp pv=%#p{%.*Rhxs} cb=%u\n", off, pv, cb, pv, cb), 2180 VINF_SUCCESS); 2181 2182 int rc = VINF_SUCCESS; 2183 uint32_t const u32Val = *(const uint32_t *)pv; 2184 switch (off) 2185 { 2186 case VIRTIO_MMIO_REG_DEVICEFEATSEL_OFF: 2187 { 2188 pVirtio->uDeviceFeaturesSelect = u32Val; 2189 break; 2190 } 2191 case VIRTIO_MMIO_REG_DRIVERFEAT_OFF: 2192 { 2193 switch (pVirtio->uDriverFeaturesSelect) 2194 { 2195 case 0: 2196 pVirtio->uDriverFeatures = (pVirtio->uDriverFeatures & UINT64_C(0xffffffff00000000)) | u32Val; 2197 pVirtio->fDriverFeaturesWritten |= DRIVER_FEATURES_0_WRITTEN; 2198 LogFunc(("Set DRIVER_FEATURES_0_WRITTEN. pVirtio->fDriverFeaturesWritten=%d\n", pVirtio->fDriverFeaturesWritten)); 2199 if ( (pVirtio->fDriverFeaturesWritten & DRIVER_FEATURES_0_AND_1_WRITTEN) == DRIVER_FEATURES_0_AND_1_WRITTEN 2200 && !(pVirtio->fDriverFeaturesWritten & DRIVER_FEATURES_COMPLETE_HANDLED)) 2201 #ifdef IN_RING0 2202 return VINF_IOM_R3_MMIO_WRITE; 2203 #endif 2204 #ifdef IN_RING3 2205 virtioR3DoFeaturesCompleteOnceOnly(pVirtio, pVirtioCC); 2206 #endif 2207 break; 2208 case 1: 2209 pVirtio->uDriverFeatures = (pVirtio->uDriverFeatures & UINT64_C(0x00000000ffffffff)) | ((uint64_t)u32Val << 32); 2210 pVirtio->fDriverFeaturesWritten |= DRIVER_FEATURES_1_WRITTEN; 2211 LogFunc(("Set DRIVER_FEATURES_1_WRITTEN. pVirtio->fDriverFeaturesWritten=%d\n", pVirtio->fDriverFeaturesWritten)); 2212 if ( (pVirtio->fDriverFeaturesWritten & DRIVER_FEATURES_0_AND_1_WRITTEN) == DRIVER_FEATURES_0_AND_1_WRITTEN 2213 && !(pVirtio->fDriverFeaturesWritten & DRIVER_FEATURES_COMPLETE_HANDLED)) 2214 #ifdef IN_RING0 2215 return VINF_IOM_R3_MMIO_WRITE; 2216 #endif 2217 #ifdef IN_RING3 2218 virtioR3DoFeaturesCompleteOnceOnly(pVirtio, pVirtioCC); 2219 #endif 2220 break; 2221 default: 2222 LogFunc(("Guest wrote uDriverFeatures with out of range selector (%#x), returning 0\n", 2223 pVirtio->uDriverFeaturesSelect)); 2224 return VINF_SUCCESS; 2225 } 2226 break; 2227 } 2228 case VIRTIO_MMIO_REG_DRIVERFEATSEL_OFF: 2229 { 2230 pVirtio->uDriverFeaturesSelect = u32Val; 2231 break; 2232 } 2233 case VIRTIO_MMIO_REG_QUEUESEL_OFF: 2234 { 2235 if (u32Val < RT_ELEMENTS(pVirtio->aVirtqueues)) 2236 pVirtio->uVirtqSelect = (uint16_t)u32Val; 2237 else 2238 LogFunc(("... WARNING: Guest attempted to write invalid virtq selector (ignoring)\n")); 2239 break; 2240 } 2241 case VIRTIO_MMIO_REG_QUEUENUM_OFF: 2242 { 2243 Assert(pVirtio->uVirtqSelect < RT_ELEMENTS(pVirtio->aVirtqueues)); 2244 PVIRTQUEUE pVirtQueue = &pVirtio->aVirtqueues[pVirtio->uVirtqSelect]; 2245 pVirtQueue->uQueueSize = (uint16_t)u32Val; 2246 break; 2247 } 2248 case VIRTIO_MMIO_REG_QUEUERDY_OFF: 2249 { 2250 Assert(pVirtio->uVirtqSelect < RT_ELEMENTS(pVirtio->aVirtqueues)); 2251 PVIRTQUEUE pVirtQueue = &pVirtio->aVirtqueues[pVirtio->uVirtqSelect]; 2252 pVirtQueue->uEnable = (uint16_t)u32Val; 2253 break; 2254 } 2255 case VIRTIO_MMIO_REG_QUEUENOTIFY_OFF: 2256 { 2257 virtioCoreVirtqNotified(pDevIns, pVirtio, u32Val, (uint16_t)u32Val); 2258 break; 2259 } 2260 case VIRTIO_MMIO_REG_INTRACK_OFF: 2261 { 2262 pVirtio->uISR &= ~u32Val; 2263 if (!pVirtio->uISR) 2264 virtioLowerInterrupt(pDevIns, 0); 2265 break; 2266 } 2267 case VIRTIO_MMIO_REG_DEVSTATUS_OFF: 2268 { 2269 rc = virtioDeviceStatusWrite(pDevIns, pVirtio, pVirtioCC, (uint8_t)u32Val); 2270 break; 2271 } 2272 case VIRTIO_MMIO_REG_QUEUEALIGN_LEGACY_OFF: 2273 { 2274 /* Written by edk2 even though we don't offer legacy mode, ignore. */ 2275 break; 2276 } 2277 case VIRTIO_MMIO_REG_QUEUEDESCLOW_OFF: 2278 { 2279 Assert(pVirtio->uVirtqSelect < RT_ELEMENTS(pVirtio->aVirtqueues)); 2280 PVIRTQUEUE pVirtQueue = &pVirtio->aVirtqueues[pVirtio->uVirtqSelect]; 2281 pVirtQueue->GCPhysVirtqDesc = (pVirtQueue->GCPhysVirtqDesc & UINT64_C(0xffffffff00000000)) | u32Val; 2282 break; 2283 } 2284 case VIRTIO_MMIO_REG_QUEUEDESCHIGH_OFF: 2285 { 2286 Assert(pVirtio->uVirtqSelect < RT_ELEMENTS(pVirtio->aVirtqueues)); 2287 PVIRTQUEUE pVirtQueue = &pVirtio->aVirtqueues[pVirtio->uVirtqSelect]; 2288 pVirtQueue->GCPhysVirtqDesc = (pVirtQueue->GCPhysVirtqDesc & UINT64_C(0x00000000ffffffff)) | ((uint64_t)u32Val << 32); 2289 break; 2290 } 2291 case VIRTIO_MMIO_REG_QUEUEDRVLOW_OFF: 2292 { 2293 Assert(pVirtio->uVirtqSelect < RT_ELEMENTS(pVirtio->aVirtqueues)); 2294 PVIRTQUEUE pVirtQueue = &pVirtio->aVirtqueues[pVirtio->uVirtqSelect]; 2295 pVirtQueue->GCPhysVirtqAvail = (pVirtQueue->GCPhysVirtqAvail & UINT64_C(0xffffffff00000000)) | u32Val; 2296 break; 2297 } 2298 case VIRTIO_MMIO_REG_QUEUEDRVHIGH_OFF: 2299 { 2300 Assert(pVirtio->uVirtqSelect < RT_ELEMENTS(pVirtio->aVirtqueues)); 2301 PVIRTQUEUE pVirtQueue = &pVirtio->aVirtqueues[pVirtio->uVirtqSelect]; 2302 pVirtQueue->GCPhysVirtqAvail = (pVirtQueue->GCPhysVirtqAvail & UINT64_C(0x00000000ffffffff)) | ((uint64_t)u32Val << 32); 2303 break; 2304 } 2305 case VIRTIO_MMIO_REG_QUEUEDEVLOW_OFF: 2306 { 2307 Assert(pVirtio->uVirtqSelect < RT_ELEMENTS(pVirtio->aVirtqueues)); 2308 PVIRTQUEUE pVirtQueue = &pVirtio->aVirtqueues[pVirtio->uVirtqSelect]; 2309 pVirtQueue->GCPhysVirtqUsed = (pVirtQueue->GCPhysVirtqUsed & UINT64_C(0xffffffff00000000)) | u32Val; 2310 break; 2311 } 2312 case VIRTIO_MMIO_REG_QUEUEDEVHIGH_OFF: 2313 { 2314 Assert(pVirtio->uVirtqSelect < RT_ELEMENTS(pVirtio->aVirtqueues)); 2315 PVIRTQUEUE pVirtQueue = &pVirtio->aVirtqueues[pVirtio->uVirtqSelect]; 2316 pVirtQueue->GCPhysVirtqUsed = (pVirtQueue->GCPhysVirtqUsed & UINT64_C(0x00000000ffffffff)) | ((uint64_t)u32Val << 32); 2317 break; 2318 } 2319 default: 2320 ASSERT_GUEST_MSG_FAILED(("Bad write access to mapped capabilities region: off=%RGp pv=%#p{%.*Rhxs} cb=%u\n", off, pv, cb, pv, cb)); 2321 rc = PDMDevHlpDBGFStop(pDevIns, RT_SRC_POS, 2322 "virtioMmioTransportWrite: Bad MMIO access to capabilities, offset=%RTiop cb=%08x\n", off, cb); 2323 } 2324 2019 2325 STAM_PROFILE_ADV_STOP(&pVirtio->CTX_SUFF(StatWrite), a); 2020 int rc = PDMDevHlpDBGFStop(pDevIns, RT_SRC_POS,2021 "virtioMmioRead: Bad MMIO access to capabilities, offset=%RTiop cb=%08x\n", off, cb);2022 2326 return rc; 2023 2327 } 2328 2024 2329 2025 2330 #ifdef IN_RING3 … … 2386 2691 } 2387 2692 2388 /** API Function: See header file */ 2389 DECLHIDDEN(int) virtioCoreR3Init(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, PVIRTIOCORECC pVirtioCC, PVIRTIOPCIPARAMS pPciParams, 2390 const char *pcszInstance, uint64_t fDevSpecificFeatures, uint32_t fOfferLegacy, 2391 void *pvDevSpecificCfg, uint16_t cbDevSpecificCfg) 2392 { 2393 /* 2394 * Virtio state must be the first member of shared device instance data, 2395 * otherwise can't get our bearings in PCI config callbacks. 2396 */ 2397 AssertLogRelReturn(pVirtio == PDMINS_2_DATA(pDevIns, PVIRTIOCORE), VERR_STATE_CHANGED); 2398 AssertLogRelReturn(pVirtioCC == PDMINS_2_DATA_CC(pDevIns, PVIRTIOCORECC), VERR_STATE_CHANGED); 2399 2400 pVirtio->pDevInsR3 = pDevIns; 2401 2402 /* 2403 * Caller must initialize these. 2404 */ 2405 AssertReturn(pVirtioCC->pfnStatusChanged, VERR_INVALID_POINTER); 2406 AssertReturn(pVirtioCC->pfnVirtqNotified, VERR_INVALID_POINTER); 2407 AssertReturn(VIRTQ_SIZE > 0 && VIRTQ_SIZE <= 32768, VERR_OUT_OF_RANGE); /* VirtIO specification-defined limit */ 2408 2409 #if 0 /* Until pdmR3DvHlp_PCISetIrq() impl is fixed and Assert that limits vec to 0 is removed 2410 * VBox legacy MSI support has not been implemented yet 2411 */ 2412 # ifdef VBOX_WITH_MSI_DEVICES 2413 pVirtio->fMsiSupport = true; 2414 # endif 2415 #endif 2416 2417 /* 2418 * Host features (presented as a smörgasbord for guest to select from) 2419 * include both dev-specific features & reserved dev-independent features (bitmask). 2420 */ 2421 pVirtio->uDeviceFeatures = VIRTIO_F_VERSION_1 2422 | VIRTIO_DEV_INDEPENDENT_FEATURES_OFFERED 2423 | fDevSpecificFeatures; 2424 2425 pVirtio->fLegacyDriver = pVirtio->fOfferLegacy = fOfferLegacy; 2426 2427 RTStrCopy(pVirtio->szInstance, sizeof(pVirtio->szInstance), pcszInstance); 2428 pVirtioCC->cbDevSpecificCfg = cbDevSpecificCfg; 2429 pVirtioCC->pbDevSpecificCfg = (uint8_t *)pvDevSpecificCfg; 2430 pVirtioCC->pbPrevDevSpecificCfg = (uint8_t *)RTMemDup(pvDevSpecificCfg, cbDevSpecificCfg); 2431 AssertLogRelReturn(pVirtioCC->pbPrevDevSpecificCfg, VERR_NO_MEMORY); 2432 2693 2694 /** 2695 * Setup the Virtio device as a PCI device. 2696 * 2697 * @returns VBox status code. 2698 * @param pDevIns Device instance. 2699 * @param pVirtio Pointer to the shared virtio state. This 2700 * must be the first member in the shared 2701 * device instance data! 2702 * @param pVirtioCC Pointer to the ring-3 virtio state. This 2703 * must be the first member in the ring-3 2704 * device instance data! 2705 * @param pPciParams Values to populate industry standard PCI Configuration Space data structure 2706 * @param pcszInstance Device instance name (format-specifier) 2707 * @param cbDevSpecificCfg Size of virtio_pci_device_cap device-specific struct 2708 */ 2709 static int virtioR3PciTransportInit(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, PVIRTIOCORECC pVirtioCC, PVIRTIOPCIPARAMS pPciParams, 2710 const char *pcszInstance, uint16_t cbDevSpecificCfg) 2711 { 2433 2712 /* Set PCI config registers (assume 32-bit mode) */ 2434 2713 PPDMPCIDEV pPciDev = pDevIns->apPciDevs[0]; … … 2603 2882 size_t cbSize = RTStrPrintf(pVirtioCC->szMmioName, sizeof(pVirtioCC->szMmioName), "%s (modern)", pcszInstance); 2604 2883 if (cbSize <= 0) 2605 return PDMDEV_SET_ERROR(pDevIns, rc, N_("virtio: out of memory allocating string")); /* can we put params in this error? */2884 return PDMDEV_SET_ERROR(pDevIns, VERR_BUFFER_OVERFLOW, N_("virtio: out of memory allocating string")); /* can we put params in this error? */ 2606 2885 2607 2886 cbSize = RTStrPrintf(pVirtioCC->szPortIoName, sizeof(pVirtioCC->szPortIoName), "%s (legacy)", pcszInstance); 2608 2887 if (cbSize <= 0) 2609 return PDMDEV_SET_ERROR(pDevIns, rc, N_("virtio: out of memory allocating string")); /* can we put params in this error? */2888 return PDMDEV_SET_ERROR(pDevIns, VERR_BUFFER_OVERFLOW, N_("virtio: out of memory allocating string")); /* can we put params in this error? */ 2610 2889 2611 2890 if (pVirtio->fOfferLegacy) … … 2632 2911 &pVirtio->hMmioPciCap); 2633 2912 AssertLogRelRCReturn(rc, PDMDEV_SET_ERROR(pDevIns, rc, N_("virtio: cannot register PCI Capabilities address space"))); 2913 return VINF_SUCCESS; 2914 } 2915 2916 2917 /** 2918 * Initializes the VirtIO device using the VirtIO over MMIO transport mode. 2919 * 2920 * @returns VBox status code. 2921 * @param pDevIns Device instance. 2922 * @param pVirtio Pointer to the shared virtio state. This 2923 * must be the first member in the shared 2924 * device instance data! 2925 * @param pVirtioCC Pointer to the ring-3 virtio state. This 2926 * must be the first member in the ring-3 2927 * device instance data! 2928 * @param pcszInstance Device instance name (format-specifier) 2929 * @param cbDevSpecificCfg Size of virtio_pci_device_cap device-specific struct 2930 * @param GCPhysMmioBase The physical guest address of the start of the MMIO area. 2931 * @param u16Irq The interrupt number to use for the virtio device. 2932 */ 2933 static int virtioR3MmioTransportInit(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, PVIRTIOCORECC pVirtioCC, const char *pcszInstance, 2934 uint16_t cbDevSpecificCfg, RTGCPHYS GCPhysMmioBase, uint16_t u16Irq) 2935 { 2936 pVirtio->uIrqMmio = u16Irq; 2937 2938 size_t cbSize = RTStrPrintf(pVirtioCC->szMmioName, sizeof(pVirtioCC->szMmioName), "%s (modern)", pcszInstance); 2939 if (cbSize <= 0) 2940 return PDMDEV_SET_ERROR(pDevIns, VERR_BUFFER_OVERFLOW, N_("virtio: out of memory allocating string")); /* can we put params in this error? */ 2941 2942 /* 2943 * Register and map the MMIO region. 2944 */ 2945 int rc = PDMDevHlpMmioCreateAndMap(pDevIns, GCPhysMmioBase, RT_ALIGN_32(cbDevSpecificCfg + VIRTIO_MMIO_SIZE, 512), 2946 virtioMmioTransportWrite, virtioMmioTransportRead, 2947 IOMMMIO_FLAGS_READ_PASSTHRU | IOMMMIO_FLAGS_WRITE_PASSTHRU, 2948 pVirtioCC->szMmioName, &pVirtio->hMmioPciCap); 2949 AssertLogRelRCReturn(rc, PDMDEV_SET_ERROR(pDevIns, rc, N_("virtio: cannot register PCI Capabilities address space"))); 2950 return VINF_SUCCESS; 2951 } 2952 2953 2954 /** API Function: See header file */ 2955 DECLHIDDEN(int) virtioCoreR3Init(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, PVIRTIOCORECC pVirtioCC, PVIRTIOPCIPARAMS pPciParams, 2956 const char *pcszInstance, uint64_t fDevSpecificFeatures, uint32_t fOfferLegacy, 2957 void *pvDevSpecificCfg, uint16_t cbDevSpecificCfg) 2958 { 2959 /* 2960 * Virtio state must be the first member of shared device instance data, 2961 * otherwise can't get our bearings in PCI config callbacks. 2962 */ 2963 AssertLogRelReturn(pVirtio == PDMINS_2_DATA(pDevIns, PVIRTIOCORE), VERR_STATE_CHANGED); 2964 AssertLogRelReturn(pVirtioCC == PDMINS_2_DATA_CC(pDevIns, PVIRTIOCORECC), VERR_STATE_CHANGED); 2965 2966 pVirtio->pDevInsR3 = pDevIns; 2967 2968 /* 2969 * Caller must initialize these. 2970 */ 2971 AssertReturn(pVirtioCC->pfnStatusChanged, VERR_INVALID_POINTER); 2972 AssertReturn(pVirtioCC->pfnVirtqNotified, VERR_INVALID_POINTER); 2973 AssertReturn(VIRTQ_SIZE > 0 && VIRTQ_SIZE <= 32768, VERR_OUT_OF_RANGE); /* VirtIO specification-defined limit */ 2974 2975 PCPDMDEVHLPR3 pHlp = pDevIns->pHlpR3; 2976 2977 uint16_t u16Irq = 0; 2978 int rc = pHlp->pfnCFGMQueryU16Def(pDevIns->pCfg, "Irq", &u16Irq, 0); 2979 if (RT_FAILURE(rc)) 2980 return PDMDEV_SET_ERROR(pDevIns, rc, N_("Configuration error: Failed to get the \"Irq\" value")); 2981 2982 RTGCPHYS GCPhysMmioBase = 0; 2983 rc = pHlp->pfnCFGMQueryU64Def(pDevIns->pCfg, "MmioBase", &GCPhysMmioBase, NIL_RTGCPHYS); 2984 if (RT_FAILURE(rc)) 2985 return PDMDEV_SET_ERROR(pDevIns, rc, 2986 N_("Configuration error: Failed to get the \"MmioBase\" value")); 2987 2988 #if 0 /* Until pdmR3DvHlp_PCISetIrq() impl is fixed and Assert that limits vec to 0 is removed 2989 * VBox legacy MSI support has not been implemented yet 2990 */ 2991 # ifdef VBOX_WITH_MSI_DEVICES 2992 pVirtio->fMsiSupport = true; 2993 # endif 2994 #endif 2995 2996 /* 2997 * Host features (presented as a buffet for guest to select from) 2998 * include both dev-specific features & reserved dev-independent features (bitmask). 2999 */ 3000 pVirtio->uDeviceType = pPciParams->uDeviceType; 3001 pVirtio->uDeviceFeatures = VIRTIO_F_VERSION_1 3002 | VIRTIO_DEV_INDEPENDENT_FEATURES_OFFERED 3003 | fDevSpecificFeatures; 3004 3005 pVirtio->fLegacyDriver = pVirtio->fOfferLegacy = fOfferLegacy; 3006 3007 RTStrCopy(pVirtio->szInstance, sizeof(pVirtio->szInstance), pcszInstance); 3008 pVirtioCC->cbDevSpecificCfg = cbDevSpecificCfg; 3009 pVirtioCC->pbDevSpecificCfg = (uint8_t *)pvDevSpecificCfg; 3010 pVirtioCC->pbPrevDevSpecificCfg = (uint8_t *)RTMemDup(pvDevSpecificCfg, cbDevSpecificCfg); 3011 AssertLogRelReturn(pVirtioCC->pbPrevDevSpecificCfg, VERR_NO_MEMORY); 3012 3013 if (GCPhysMmioBase != NIL_RTGCPHYS) 3014 rc = virtioR3MmioTransportInit(pDevIns, pVirtio, pVirtioCC, pcszInstance, cbDevSpecificCfg, 3015 GCPhysMmioBase, u16Irq); 3016 else 3017 rc = virtioR3PciTransportInit(pDevIns, pVirtio, pVirtioCC, pPciParams, pcszInstance, cbDevSpecificCfg); 3018 AssertLogRelRCReturn(rc, rc); 3019 2634 3020 /* 2635 3021 * Statistics. … … 2673 3059 AssertRCReturn(rc, rc); 2674 3060 #endif 2675 rc = PDMDevHlpMmioSetUpContext(pDevIns, pVirtio->hMmioPciCap, virtioMmioWrite, virtioMmioRead, pVirtio); 2676 AssertRCReturn(rc, rc); 2677 2678 if (pVirtio->fOfferLegacy) 2679 { 2680 rc = PDMDevHlpIoPortSetUpContext(pDevIns, pVirtio->hLegacyIoPorts, virtioLegacyIOPortOut, virtioLegacyIOPortIn, NULL /*pvUser*/); 3061 3062 if (pVirtio->uIrqMmio != 0) 3063 { 3064 rc = PDMDevHlpMmioSetUpContext(pDevIns, pVirtio->hMmioPciCap, virtioMmioTransportWrite, virtioMmioTransportRead, pVirtio); 2681 3065 AssertRCReturn(rc, rc); 2682 3066 } 3067 else 3068 { 3069 rc = PDMDevHlpMmioSetUpContext(pDevIns, pVirtio->hMmioPciCap, virtioMmioWrite, virtioMmioRead, pVirtio); 3070 AssertRCReturn(rc, rc); 3071 3072 if (pVirtio->fOfferLegacy) 3073 { 3074 rc = PDMDevHlpIoPortSetUpContext(pDevIns, pVirtio->hLegacyIoPorts, virtioLegacyIOPortOut, virtioLegacyIOPortIn, NULL /*pvUser*/); 3075 AssertRCReturn(rc, rc); 3076 } 3077 } 2683 3078 return rc; 2684 3079 } -
trunk/src/VBox/Devices/VirtIO/VirtioCore.h
r100372 r100400 70 70 #define VIRTIO_PAGE_SIZE 4096 /**< Page size used by VirtIO specification */ 71 71 72 /** Virtio-over-MMIO transport region size, excluding the device specific configuration area. */ 73 #define VIRTIO_MMIO_SIZE 256 74 /** Register containing a magic value identifying a VirtIO over MMIO device - readonly. */ 75 #define VIRTIO_MMIO_REG_MAGIC_OFF 0 76 /** Magic value read from the register. */ 77 # define VIRTIO_MMIO_REG_MAGIC_VALUE UINT32_C(0x74726976) 78 /** Register containing th version of the MMIO transport - readonly. */ 79 #define VIRTIO_MMIO_REG_VERSION_OFF 4 80 /** Version value read from the register. */ 81 # define VIRTIO_MMIO_REG_VERSION_VALUE UINT32_C(0x2) 82 /** Register containing the device ID of the device - readonly. */ 83 #define VIRTIO_MMIO_REG_DEVICEID_OFF 8 84 /** Register containing the vendor ID of the device - readonly. */ 85 #define VIRTIO_MMIO_REG_VENDORID_OFF 12 86 /** Register containing the features the device supports - readonly. */ 87 #define VIRTIO_MMIO_REG_DEVICEFEAT_OFF 16 88 /** Device features selection - writeonly. */ 89 #define VIRTIO_MMIO_REG_DEVICEFEATSEL_OFF 20 90 /** Features of the device selected by the driver - writeonly. */ 91 #define VIRTIO_MMIO_REG_DRIVERFEAT_OFF 32 92 /** - writeonly. */ 93 #define VIRTIO_MMIO_REG_DRIVERFEATSEL_OFF 36 94 /** Virtual queue selection - writeonly. */ 95 #define VIRTIO_MMIO_REG_QUEUESEL_OFF 48 96 /** - readonly */ 97 #define VIRTIO_MMIO_REG_QUEUENUMMAX_OFF 52 98 /** - writeonly */ 99 #define VIRTIO_MMIO_REG_QUEUENUM_OFF 56 100 /** - read/write. */ 101 #define VIRTIO_MMIO_REG_QUEUEALIGN_LEGACY_OFF 60 102 /** - read/write. */ 103 #define VIRTIO_MMIO_REG_QUEUERDY_OFF 68 104 /** - writeonly */ 105 #define VIRTIO_MMIO_REG_QUEUENOTIFY_OFF 80 106 /** - readonly */ 107 #define VIRTIO_MMIO_REG_INTRSTATUS_OFF 96 108 /** - writeonly */ 109 #define VIRTIO_MMIO_REG_INTRACK_OFF 100 110 /** - read/write */ 111 #define VIRTIO_MMIO_REG_DEVSTATUS_OFF 112 112 /** - writeonly */ 113 #define VIRTIO_MMIO_REG_QUEUEDESCLOW_OFF 128 114 /** - writeonly */ 115 #define VIRTIO_MMIO_REG_QUEUEDESCHIGH_OFF 132 116 /** - writeonly */ 117 #define VIRTIO_MMIO_REG_QUEUEDRVLOW_OFF 144 118 /** - writeonly */ 119 #define VIRTIO_MMIO_REG_QUEUEDRVHIGH_OFF 148 120 /** - writeonly */ 121 #define VIRTIO_MMIO_REG_QUEUEDEVLOW_OFF 160 122 /** - writeonly */ 123 #define VIRTIO_MMIO_REG_QUEUEDEVHIGH_OFF 164 124 /** - readonly */ 125 #define VIRTIO_MMIO_REG_CFGGEN_OFF 252 126 127 72 128 /** 73 129 * @todo Move the following virtioCoreGCPhysChain*() functions mimic the functionality of the related … … 154 210 uint16_t uInterruptLine; /**< PCI Cfg Interrupt line */ 155 211 uint16_t uInterruptPin; /**< PCI Cfg Interrupt pin */ 212 uint8_t uDeviceType; /**< Device type (used for Virtio-over-MMIO) */ 156 213 } VIRTIOPCIPARAMS, *PVIRTIOPCIPARAMS; 157 214 … … 207 264 */ 208 265 #define DEVICE_PCI_DEVICE_ID_VIRTIO_BASE 0x1040 266 267 /** 268 * @name Virtio Device types as outlined in chapter 5. 269 * @{ */ 270 #define VIRTIO_DEVICE_TYPE_INVALID 0 271 #define VIRTIO_DEVICE_TYPE_NETWORK 1 272 #define VIRTIO_DEVICE_TYPE_BLOCK 2 273 #define VIRTIO_DEVICE_TYPE_CONSOLE 3 274 #define VIRTIO_DEVICE_TYPE_ENTROPY_SOURCE 4 275 #define VIRTIO_DEVICE_TYPE_MEMORY_BALLOONING_TRAD 5 276 #define VIRTIO_DEVICE_TYPE_IOMEM 6 277 #define VIRTIO_DEVICE_TYPE_RPMSG 7 278 #define VIRTIO_DEVICE_TYPE_SCSI_HOST 8 279 #define VIRTIO_DEVICE_TYPE_9P_TRANSPORT 9 280 #define VIRTIO_DEVICE_TYPE_MAC80211_WLAN 10 281 #define VIRTIO_DEVICE_TYPE_RPROC_SERIAL 11 282 #define VIRTIO_DEVICE_TYPE_CAIF 12 283 #define VIRTIO_DEVICE_TYPE_MEMORY_BALLOONING 13 284 #define VIRTIO_DEVICE_TYPE_GPU 16 285 #define VIRTIO_DEVICE_TYPE_TIMER 17 286 #define VIRTIO_DEVICE_TYPE_INPUT 18 287 #define VIRTIO_DEVICE_TYPE_SOCKET 19 288 #define VIRTIO_DEVICE_TYPE_CRYPTO 20 289 #define VIRTIO_DEVICE_TYPE_SIGNAL_DIST_MOD 21 290 #define VIRTIO_DEVICE_TYPE_PSTORE 22 291 #define VIRTIO_DEVICE_TYPE_IOMMU 23 292 #define VIRTIO_DEVICE_TYPE_MEMORY 24 293 /** @} */ 209 294 210 295 /** Reserved (*negotiated*) Feature Bits (e.g. device independent features, VirtIO 1.0 spec,section 6) */ … … 371 456 uint32_t fLegacyDriver; /**< Set if guest drv < VirtIO 1.0 and allowed */ 372 457 uint32_t fOfferLegacy; /**< Set at init call from dev-specific code */ 458 uint16_t uIrqMmio; /**< The interrupt number when Virtio-over-MMIO is used */ 459 uint8_t uDeviceType; /**< The implemented device type for Virtio-over-MMIO */ 373 460 374 461 /** @name The locations of the capability structures in PCI config space and the BAR. … … 860 947 { 861 948 int rc; 862 if (virtioCoreIsLegacyMode(pVirtio)) 949 if ( virtioCoreIsLegacyMode(pVirtio) 950 || pVirtio->uIrqMmio) 863 951 rc = PDMDevHlpPhysWrite(pDevIns, GCPhys, pvBuf, cbWrite); 864 952 else … … 870 958 { 871 959 int rc; 872 if (virtioCoreIsLegacyMode(pVirtio)) 960 if ( virtioCoreIsLegacyMode(pVirtio) 961 || pVirtio->uIrqMmio) 873 962 rc = PDMDevHlpPhysRead(pDevIns, GCPhys, pvBuf, cbRead); 874 963 else … … 1076 1165 size_t cbSeg = cbLim; 1077 1166 RTGCPHYS GCPhys = virtioCoreGCPhysChainGetNextSeg(pVirtqBuf->pSgPhysSend, &cbSeg); 1078 PDMDevHlpPCIPhysRead(pVirtio->pDevInsR3, GCPhys, pb, cbSeg); 1167 if (pVirtio->uIrqMmio) 1168 PDMDevHlpPhysRead(pVirtio->pDevInsR3, GCPhys, pb, cbSeg); 1169 else 1170 PDMDevHlpPCIPhysRead(pVirtio->pDevInsR3, GCPhys, pb, cbSeg); 1079 1171 pb += cbSeg; 1080 1172 cbLim -= cbSeg;
Note:
See TracChangeset
for help on using the changeset viewer.