VirtualBox

Changeset 100400 in vbox for trunk/src/VBox/Devices/VirtIO


Ignore:
Timestamp:
Jul 6, 2023 8:58:02 AM (17 months ago)
Author:
vboxsync
Message:

Devices/VirtIO: Add support for the VirtIO over MMIO transport mode useful for ARM, bugref:10459

Location:
trunk/src/VBox/Devices/VirtIO
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Devices/VirtIO/VirtioCore.cpp

    r100372 r100400  
    12301230       Log6Func(("Reason for interrupt - device config change\n"));
    12311231
    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)
    12331238    {
    12341239        pVirtio->uISR |= uCause;
     
    12481253{
    12491254    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)
    12511258        PDMDevHlpPCISetIrq(pDevIns, 0, PDM_IRQ_LEVEL_LOW);
    12521259    else if (uMsixVector != VIRTIO_MSI_NO_VECTOR)
     
    13471354}
    13481355#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 */
     1368DECLINLINE(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 */
     1418DECLINLINE(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
    13491431
    13501432/**
     
    14751557    {
    14761558        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);
    15151560        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);
    15271562    }
    15281563    else
     
    18841919
    18851920/**
    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 */
     1926DECLINLINE(VBOXSTRICTRC) virtioDeviceCfgRead(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, PVIRTIOCORECC pVirtioCC,
     1927                                              uint32_t offDevCfg, void *pv, unsigned cb)
     1928{
    19061929#ifdef IN_RING3
    19071930        /*
    19081931         * Callback to client to manage device-specific configuration.
    19091932         */
    1910         VBOXSTRICTRC rcStrict = pVirtioCC->pfnDevCapRead(pDevIns, uOffset, pv, cb);
     1933        VBOXSTRICTRC rcStrict = pVirtioCC->pfnDevCapRead(pDevIns, offDevCfg, pv, cb);
    19111934
    19121935        /*
     
    19151938         * for deltas from previous read to maintain a config gen. seq. counter (VirtIO 1.0, section 4.1.4.3.1)
    19161939         */
    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)));
    19201943
    19211944        memcpy(pVirtioCC->pbPrevDevSpecificCfg, pVirtioCC->pbDevSpecificCfg, pVirtioCC->cbDevSpecificCfg);
     
    19311954
    19321955        virtioLowerInterrupt(pDevIns, 0);
    1933         STAM_PROFILE_ADV_STOP(&pVirtio->CTX_SUFF(StatRead), a);
    19341956        return rcStrict;
    19351957#else
    1936         STAM_PROFILE_ADV_STOP(&pVirtio->CTX_SUFF(StatRead), a);
    19371958        return VINF_IOM_R3_MMIO_READ;
    19381959#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 */
     1972static 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))
    19451988    {
    19461989        *(uint8_t *)pv = pVirtio->uISR;
     
    19481991        pVirtio->uISR = 0; /* VirtIO spec requires reads of ISR to clear it */
    19491992        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
    19552002    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;
    19592004}
    19602005
     
    19752020    STAM_PROFILE_ADV_START(&pVirtio->CTX_SUFF(StatWrite), a);
    19762021
     2022    VBOXSTRICTRC rcStrict;
    19772023    uint32_t uOffset;
    19782024    if (MATCHES_VIRTIO_CAP_STRUCT(off, cb, uOffset, pVirtio->LocDeviceCap))
     
    19822028         * Foreward this MMIO write access for client to deal with.
    19832029         */
    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);
    19862031#else
    1987         STAM_PROFILE_ADV_STOP(&pVirtio->CTX_SUFF(StatWrite), a);
    19882032        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))
    20002039    {
    20012040        pVirtio->uISR = *(uint8_t *)pv;
     
    20042043                  pVirtio->uISR & VIRTIO_ISR_VIRTQ_INTERRUPT,
    20052044                  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 */
     2070static 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 */
     2155static 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         */
    20062168        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
    20142171        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
    20192325    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);
    20222326    return rc;
    20232327}
     2328
    20242329
    20252330#ifdef IN_RING3
     
    23862691}
    23872692
    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 */
     2709static int virtioR3PciTransportInit(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, PVIRTIOCORECC pVirtioCC, PVIRTIOPCIPARAMS pPciParams,
     2710                                    const char *pcszInstance, uint16_t cbDevSpecificCfg)
     2711{
    24332712    /* Set PCI config registers (assume 32-bit mode) */
    24342713    PPDMPCIDEV pPciDev = pDevIns->apPciDevs[0];
     
    26032882    size_t cbSize = RTStrPrintf(pVirtioCC->szMmioName, sizeof(pVirtioCC->szMmioName), "%s (modern)", pcszInstance);
    26042883    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? */
    26062885
    26072886    cbSize = RTStrPrintf(pVirtioCC->szPortIoName, sizeof(pVirtioCC->szPortIoName), "%s (legacy)", pcszInstance);
    26082887    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? */
    26102889
    26112890    if (pVirtio->fOfferLegacy)
     
    26322911                                        &pVirtio->hMmioPciCap);
    26332912    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 */
     2933static 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 */
     2955DECLHIDDEN(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
    26343020    /*
    26353021     * Statistics.
     
    26733059    AssertRCReturn(rc, rc);
    26743060#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);
    26813065        AssertRCReturn(rc, rc);
    26823066    }
     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    }
    26833078    return rc;
    26843079}
  • trunk/src/VBox/Devices/VirtIO/VirtioCore.h

    r100372 r100400  
    7070#define VIRTIO_PAGE_SIZE                 4096                    /**< Page size used by VirtIO specification   */
    7171
     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
    72128/**
    73129 * @todo Move the following virtioCoreGCPhysChain*() functions mimic the functionality of the related
     
    154210    uint16_t  uInterruptLine;                                    /**< PCI Cfg Interrupt line                    */
    155211    uint16_t  uInterruptPin;                                     /**< PCI Cfg Interrupt pin                     */
     212    uint8_t   uDeviceType;                                       /**< Device type (used for Virtio-over-MMIO)   */
    156213} VIRTIOPCIPARAMS, *PVIRTIOPCIPARAMS;
    157214
     
    207264 */
    208265#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/** @} */
    209294
    210295/** Reserved (*negotiated*) Feature Bits (e.g. device independent features, VirtIO 1.0 spec,section 6) */
     
    371456    uint32_t                    fLegacyDriver;                    /**< Set if guest drv < VirtIO 1.0 and allowed */
    372457    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   */
    373460
    374461    /** @name The locations of the capability structures in PCI config space and the BAR.
     
    860947{
    861948    int rc;
    862     if (virtioCoreIsLegacyMode(pVirtio))
     949    if (   virtioCoreIsLegacyMode(pVirtio)
     950        || pVirtio->uIrqMmio)
    863951        rc = PDMDevHlpPhysWrite(pDevIns, GCPhys, pvBuf, cbWrite);
    864952    else
     
    870958{
    871959    int rc;
    872     if (virtioCoreIsLegacyMode(pVirtio))
     960    if (   virtioCoreIsLegacyMode(pVirtio)
     961        || pVirtio->uIrqMmio)
    873962        rc = PDMDevHlpPhysRead(pDevIns, GCPhys, pvBuf, cbRead);
    874963    else
     
    10761165        size_t cbSeg = cbLim;
    10771166        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);
    10791171        pb += cbSeg;
    10801172        cbLim -= cbSeg;
Note: See TracChangeset for help on using the changeset viewer.

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