VirtualBox

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


Ignore:
Timestamp:
Jul 30, 2019 8:17:49 AM (6 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
132495
Message:

Virtio 1.0 capabilities are now showing up and some negotiation hurdles are being accomplished with the Linux guest driver counterpart. (See #9440, Comment #38)

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

Legend:

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

    r79973 r80058  
    3535# define QUEUENAME(s, q) (q->pcszName)
    3636#endif
     37
     38/* These ACCESSOR macros handle the most basic kinds of MMIO accesses to fields
     39 * virtio 1.0 spec's virtio_pci_common_cfg  avoiding a lot of visual bloat.
     40 */
     41
     42 /**
     43  * If the physical address and access length is within the mapped capability struct
     44  * the ptrByType will be set to the mapped capability start. Otherwise ptrByType will be NULL.
     45  *
     46  * Implied parameters:
     47  *     GPhysAddr   - Physical address accessed (via MMIO callback)
     48  *     cb          - Number of bytes to access
     49  *
     50  * Actual Parameters:
     51  *     [IN]  pCapStruct - Pointer to MMIO mapped capability struct
     52  *     [IN]  type       - Capability struct type
     53  *     [OUT] result     - A pointer of type capType that will be set to a mapped capability
     54  *                       if phys. addr / access len is within it's span.
     55  *     [OUT] offset     - The offset of the physical address into the capability if applicable.
     56  */
     57
     58#define MATCH_VIRTIO_CAP_STRUCT(pCapStruct, type, result, offset) \
     59        type *result = NULL; \
     60        if (   GCPhysAddr >= (RTGCPHYS)pCapStruct \
     61            && GCPhysAddr < ((RTGCPHYS)pCapStruct + sizeof(type)) \
     62            && cb <= sizeof(type)) \
     63        { \
     64            offset = GCPhysAddr - (RTGCPHYS)pCapStruct; \
     65            result = (type *)pCapStruct; \
     66        }
     67
     68#define LOG_ACCESSOR(member, type) \
     69        LogFunc(("Guest %s 0x%x %s %s\n", fWrite ? "wrote" : "read ", \
     70                 *(type *)pv, fWrite ? "  to" : "from", #member));
     71
     72#define LOG_INDEXED_ACCESSOR(member, type, idx) \
     73        LogFunc(("Guest %s 0x%x %s %s[%d]\n", fWrite ? "wrote" : "read ", \
     74                 *(type *)pv, fWrite ? "  to" : "from", #member, idx));
     75
     76#define ACCESSOR(member, type) \
     77    { \
     78        if (fWrite) \
     79        { \
     80            pVirtio->member = *(type *)pv; \
     81        } \
     82        else \
     83        { \
     84            *(type *)pv = pVirtio->member; \
     85        } \
     86        LOG_ACCESSOR(member, type); \
     87    }
     88#define ACCESSOR_WITH_IDX(member, type, idx) \
     89    { \
     90        if (fWrite) \
     91        { \
     92            pVirtio->member[idx] = *(type *)pv; \
     93        } \
     94        else \
     95        { \
     96            *(type *)pv = pVirtio->member[idx]; \
     97        } \
     98        LOG_INDEXED_ACCESSOR(member, type, idx); \
     99    }
     100
     101#define ACCESSOR_READONLY(member, type) \
     102    { \
     103        if (fWrite) \
     104        { \
     105            LogFunc(("Guest attempted to write readonly virtio_pci_common_cfg.%s\n", #member)); \
     106            AssertMsgFailed(("bad access\n")); \
     107        } \
     108        else \
     109        { \
     110            *(type *)pv = pVirtio->member; \
     111            LOG_ACCESSOR(member, type); \
     112        } \
     113    }
     114
     115#define ACCESSOR_READONLY_WITH_IDX(member, type, idx) \
     116    { \
     117        if (fWrite) \
     118        { \
     119            LogFunc(("Guest attempted to write readonly virtio_pci_common_cfg.%s[%d]\n", #member, idx)); \
     120            AssertMsgFailed(("bad access\n")); \
     121        } \
     122        else \
     123        { \
     124            *(type *)pv = pVirtio->member[idx]; \
     125            LOG_INDEXED_ACCESSOR(member, type, idx); \
     126        } \
     127    }
     128
    37129
    38130#ifdef VBOX_DEVICE_STRUCT_TESTCASE
     
    316408}
    317409
    318 void virtioReset(PVIRTIOSTATE pState)
    319 {
    320 
    321     RT_NOREF(pState);
    322 /* PK TODO Adapt to VirtIO 1.0
     410int virtioReset(PVIRTIOSTATE pVirtio)
     411{
     412    RT_NOREF(pVirtio);
     413/* PK TODO Adapt to VirtIO 1.09
    323414    pState->uGuestFeatures = 0;
    324415    pState->uQueueSelector = 0;
     
    329420        virtQueueReset(&pState->Queues[i]);
    330421*/
     422    virtioNotify(pVirtio);
     423    return VINF_SUCCESS;
    331424}
    332425
     
    374467
    375468#ifdef IN_RING3
    376 
    377 /**
    378  * Gets the pointer to the status LED of a unit.
    379  *
    380  * @returns VBox status code.
    381  * @param   pInterface      Pointer to the interface structure.
    382  * @param   iLUN            The unit which status LED we desire.
    383  * @param   ppLed           Where to store the LED pointer.
    384  * @thread  EMT
    385  */
    386 static DECLCALLBACK(int) virtioQueryStatusLed(PPDMILEDPORTS pInterface, unsigned iLUN, PPDMLED *ppLed)
    387 {
    388     VIRTIOSTATE *pState = IFACE_TO_STATE(pInterface, ILeds);
    389     int rc = VERR_PDM_LUN_NOT_FOUND;
    390 
    391     if (iLUN == 0)
    392     {
    393         *ppLed = &pState->led;
    394         rc     = VINF_SUCCESS;
    395     }
    396     return rc;
    397 }
    398 
    399 /**
    400  * Turns on/off the write status LED.
    401  *
    402  * @returns VBox status code.
    403  * @param   pState          Pointer to the device state structure.
    404  * @param   fOn             New LED state.
    405  */
    406 void virtioSetWriteLed(PVIRTIOSTATE pState, bool fOn)
    407 {
    408     LogFlow(("%s virtioSetWriteLed: %s\n", INSTANCE(pState), fOn ? "on" : "off"));
    409     if (fOn)
    410         pState->led.Asserted.s.fWriting = pState->led.Actual.s.fWriting = 1;
    411     else
    412         pState->led.Actual.s.fWriting = fOn;
    413 }
    414 
    415 /**
    416  * Turns on/off the read status LED.
    417  *
    418  * @returns VBox status code.
    419  * @param   pState          Pointer to the device state structure.
    420  * @param   fOn             New LED state.
    421  */
    422 void virtioSetReadLed(PVIRTIOSTATE pState, bool fOn)
    423 {
    424     LogFlow(("%s virtioSetReadLed: %s\n", INSTANCE(pState), fOn ? "on" : "off"));
    425     if (fOn)
    426         pState->led.Asserted.s.fReading = pState->led.Actual.s.fReading = 1;
    427     else
    428         pState->led.Actual.s.fReading = fOn;
    429 }
    430469
    431470
     
    575614}
    576615
     616void virtioNotify(PVIRTIOSTATE pVirtio)
     617{
     618    RT_NOREF(pVirtio);
     619}
     620
     621static void virtioResetDevice(PVIRTIOSTATE pVirtio)
     622{
     623    RT_NOREF(pVirtio);
     624    LogFunc((""));
     625    pVirtio->uDeviceStatus = 0;
     626}
     627
     628/**
     629 * Handle accesses to Common Configuration capability
     630 *
     631 * @returns VBox status code
     632 *
     633 * @param   pVirtio     Virtio instance state
     634 * @param   fWrite      If write access (otherwise read access)
     635 * @param   pv          Pointer to location to write to or read from
     636 * @param   cb          Number of bytes to read or write
     637 */
     638int virtioCommonCfgAccessed(PVIRTIOSTATE pVirtio, int fWrite, off_t uoff, void const *pv)
     639{
     640    int rv = VINF_SUCCESS;
     641    if (uoff == RT_OFFSETOF(VIRTIO_PCI_COMMON_CFG_T, uDeviceFeature))
     642    {
     643        if (fWrite) /* Guest WRITE pCommonCfg->uDeviceFeature */
     644        {
     645            AssertMsgFailed(("Guest attempted to write readonly virtio_pci_common_cfg.device_feature\n"));
     646        }
     647        else /* Guest WRITE pCommonCfg->uDeviceFeature */
     648        {
     649            switch(pVirtio->uFeaturesOfferedSelect)
     650            {
     651                case 0:
     652                    pVirtio->uFeaturesOffered = *(uint32_t *)pv;
     653                    LOG_ACCESSOR(uFeaturesOffered, uint32_t);
     654                    break;
     655                case 1:
     656                    pVirtio->uFeaturesOffered = (uint64_t)(*(uint32_t *)pv) << 32;
     657                    LOG_ACCESSOR(uFeaturesOffered, uint32_t);
     658                    break;
     659                default:
     660                    Log(("Guest selected out of range pVirtio->uDeviceFeature (%d), returning 0\n",
     661                        pVirtio->uFeaturesOfferedSelect));
     662            }
     663        }
     664    }
     665    else if (uoff == RT_OFFSETOF(VIRTIO_PCI_COMMON_CFG_T, uDriverFeature))
     666    {
     667        if (fWrite) /* Guest WRITE pCommonCfg->uDriverFeature */
     668        {
     669            switch(pVirtio->uFeaturesOfferedSelect)
     670            {
     671                case 0:
     672                    pVirtio->uFeaturesAccepted = *(uint32_t *)pv;
     673                    LOG_ACCESSOR(uFeaturesAccepted, uint32_t);
     674                    break;
     675                case 1:
     676                    pVirtio->uFeaturesAccepted = (uint64_t)(*(uint32_t *)pv) << 32;
     677                    LOG_ACCESSOR(uFeaturesAccepted, uint32_t);
     678                    break;
     679            }
     680        }
     681        else /* Guest READ pCommonCfg->uDriverFeature */
     682        {
     683            switch(pVirtio->uFeaturesOfferedSelect)
     684            {
     685                case 0:
     686                    *(uint32_t *)pv = pVirtio->uFeaturesAccepted & 0xffffffff;
     687                    LOG_ACCESSOR(uFeaturesAccepted, uint32_t);
     688                    break;
     689                case 1:
     690                    *(uint32_t *)pv = (pVirtio->uFeaturesAccepted >> 32) & 0xffffffff;
     691                    LOG_ACCESSOR(uFeaturesAccepted, uint32_t);
     692                    break;
     693            }
     694        }
     695    }
     696    else if (uoff == RT_OFFSETOF(VIRTIO_PCI_COMMON_CFG_T, uNumQueues))
     697    {
     698        if (fWrite)
     699        {
     700            AssertMsgFailed(("Guest attempted to write readonly virtio_pci_common_cfg.num_queues\n"));
     701        }
     702        else
     703        {
     704            *(uint16_t *)pv = MAX_QUEUES;
     705            Log(("Guest read 0x%x from pVirtio->uNumQueues\n", MAX_QUEUES));
     706        }
     707    }
     708    else if (uoff == RT_OFFSETOF(VIRTIO_PCI_COMMON_CFG_T, uDeviceStatus))
     709    {
     710        if (fWrite) /* Guest WRITE pCommonCfg->uDeviceStatus */
     711        {
     712            pVirtio->uDeviceStatus = *(uint8_t *)pv;
     713            LogFunc(("Driver wrote uDeviceStatus:\n"));
     714            showDeviceStatus(pVirtio->uDeviceStatus);
     715            if (pVirtio->uDeviceStatus == 0)
     716                virtioResetDevice(pVirtio);
     717        }
     718        else /* Guest READ pCommonCfg->uDeviceStatus */
     719        {
     720            LogFunc(("Driver read uDeviceStatus:\n"));
     721            *(uint32_t *)pv = pVirtio->uDeviceStatus;
     722            showDeviceStatus(pVirtio->uDeviceStatus);
     723        }
     724    }
     725    else if (uoff == RT_OFFSETOF(VIRTIO_PCI_COMMON_CFG_T, uMsixConfig))
     726    {
     727        ACCESSOR(uMsixConfig, uint32_t);
     728    }
     729    else if (uoff == RT_OFFSETOF(VIRTIO_PCI_COMMON_CFG_T, uDeviceFeatureSelect))
     730    {
     731        ACCESSOR(uFeaturesOfferedSelect, uint32_t);
     732    }
     733    else if (uoff == RT_OFFSETOF(VIRTIO_PCI_COMMON_CFG_T, uDriverFeatureSelect))
     734    {
     735        ACCESSOR(uFeaturesAcceptedSelect, uint32_t);
     736    }
     737    else if (uoff == RT_OFFSETOF(VIRTIO_PCI_COMMON_CFG_T, uConfigGeneration))
     738    {
     739        ACCESSOR_READONLY(uConfigGeneration, uint8_t);
     740    }
     741    else if (uoff == RT_OFFSETOF(VIRTIO_PCI_COMMON_CFG_T, uQueueSelect))
     742    {
     743        ACCESSOR(uQueueSelect, uint16_t);
     744    }
     745    else if (uoff == RT_OFFSETOF(VIRTIO_PCI_COMMON_CFG_T, uQueueSize))
     746    {
     747        ACCESSOR_WITH_IDX(uQueueSize, uint16_t, pVirtio->uQueueSelect);
     748    }
     749    else if (uoff == RT_OFFSETOF(VIRTIO_PCI_COMMON_CFG_T, uQueueMsixVector))
     750    {
     751        ACCESSOR_WITH_IDX(uQueueMsixVector, uint16_t, pVirtio->uQueueSelect);
     752    }
     753    else if (uoff == RT_OFFSETOF(VIRTIO_PCI_COMMON_CFG_T, uQueueEnable))
     754    {
     755        ACCESSOR_WITH_IDX(uQueueEnable, uint16_t, pVirtio->uQueueSelect);
     756    }
     757    else if (uoff == RT_OFFSETOF(VIRTIO_PCI_COMMON_CFG_T, uQueueNotifyOff))
     758    {
     759        ACCESSOR_READONLY_WITH_IDX(uQueueNotifyOff, uint16_t, pVirtio->uQueueSelect);
     760    }
     761    else if (uoff == RT_OFFSETOF(VIRTIO_PCI_COMMON_CFG_T, uQueueDesc))
     762    {
     763        ACCESSOR_WITH_IDX(uQueueDesc, uint64_t, pVirtio->uQueueSelect);
     764    }
     765    else if (uoff == RT_OFFSETOF(VIRTIO_PCI_COMMON_CFG_T, uQueueAvail))
     766    {
     767        ACCESSOR_WITH_IDX(uQueueAvail, uint64_t, pVirtio->uQueueSelect);
     768    }
     769    else if (uoff == RT_OFFSETOF(VIRTIO_PCI_COMMON_CFG_T, uQueueUsed))
     770    {
     771        ACCESSOR_WITH_IDX(uQueueUsed, uint64_t, pVirtio->uQueueSelect);
     772    }
     773    else
     774    {
     775
     776        AssertMsgFailed(("virtio: Bad common cfg offset   \n"));
     777    }
     778    return rv;
     779}
    577780
    578781/**
     
    587790 * @param   cb          Number of bytes read.
    588791 */
    589 PDMBOTHCBDECL(int) virtioPciCapMemRead(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS GCPhysAddr, void *pv, unsigned cb)
    590 {
    591 /* PK New feature! */
    592 
     792PDMBOTHCBDECL(int) virtioR3MmioRead(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS GCPhysAddr, void *pv, unsigned cb)
     793{
    593794    RT_NOREF(pvUser);
     795    PVIRTIOSTATE pVirtio = PDMINS_2_DATA(pDevIns, PVIRTIOSTATE);
    594796    int rc = VINF_SUCCESS;
    595797
    596     LogFunc(("Read (MMIO) VirtIO capabilities\n"));
    597     PVIRTIOSTATE pThis = PDMINS_2_DATA(pDevIns, PVIRTIOSTATE);
    598 
    599     /* TBD: This should be called only if VIRTIO_PCI_CAP_DEVICE_CFG capability is being accessed */
    600     rc = pThis->pfnVirtioDevCapRead(pDevIns, GCPhysAddr, pv, cb);
     798//#ifdef LOG_ENABLED
     799//    LogFlowFunc(("pVirtio=%#p GCPhysAddr=%RGp pv=%#p{%.*Rhxs} cb=%u\n", pVirtio, GCPhysAddr, pv, cb, pv, cb));
     800//#endif
     801    off_t uoff = 0;
     802    MATCH_VIRTIO_CAP_STRUCT(pVirtio->pGcPhysCommonCfg, VIRTIO_PCI_COMMON_CFG_T, pCommonCfg,  uoff);
     803    MATCH_VIRTIO_CAP_STRUCT(pVirtio->pGcPhysIsrCap,    VIRTIO_PCI_ISR_CAP_T,    pIsrCap,     uoff);
     804#if HAVE_VIRTIO_DEVICE_SPECIFIC_CAP
     805    MATCH_VIRTIO_CAP_STRUCT(pVirtio->pGcPhysDeviceCap, VIRTIO_PCI_DEVICE_CAP_T, pDeviceCap,  uoff);
     806#endif
     807    /* Note: The notify capability is handled differently as per VirtIO 1.0 spec 4.1.4.4 */
     808
     809    if (pCommonCfg)
     810        virtioCommonCfgAccessed(pVirtio, 0 /* fWrite */, uoff, pv);
     811    else if (pIsrCap)
     812    {
     813        *(uint8_t *)pv = pVirtio->fQueueInterrupt | pVirtio->fDeviceConfigInterrupt << 1;
     814        LogFunc(("Read 0x%s from pIsrCap\n", *(uint8_t *)pv));
     815    }
     816#if HAVE_VIRTIO_DEVICE_SPECIFIC_CAP
     817    else if (pDeviceCap)
     818        rc = pThis->pfnVirtioDevCapRead(pDevIns, GCPhysAddr, pv, cb);
     819#endif
     820    else
     821        AssertMsgFailed(("virtio: Write outside of capabilities region\n"));
     822
    601823    return rc;
    602824}
    603 
    604 
     825#if TBD
     826/**
     827  * Callback function for reading from the PCI configuration space.
     828  *
     829  * @returns The register value.
     830  * @param   pDevIns         Pointer to the device instance the PCI device
     831  *                          belongs to.
     832  * @param   pPciDev         Pointer to PCI device. Use pPciDev->pDevIns to get the device instance.
     833  * @param   uAddress        The configuration space register address. [0..4096]
     834  * @param   cb              The register size. [1,2,4]
     835  *
     836  * @remarks Called with the PDM lock held.  The device lock is NOT take because
     837  *          that is very likely be a lock order violation.
     838  */
     839static DECLCALLBACK(uint32_t) virtioPciConfigRead(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev,
     840                                       uint32_t uAddress, unsigned cb)
     841{
     842    PVIRTIOSTATE pVirtio = PDMINS_2_DATA(pDevIns, PVIRTIOSTATE);
     843    int rc = VINF_SUCCESS;
     844
     845    LogFunc(("uAddress: %d, uPciConfigDataOffset: %d\n", uAddress, pVirtio->uPciConfigDataOffset));
     846
     847    if (uAddress == pVirtio->uPciConfigDataOffset)
     848        Log(("Read uPciConfigDataOffset\n"));
     849    rc = pVirtio->pfnPciConfigReadOld(pDevIns, pPciDev, uAddress, cb);
     850    return rc;
     851
     852}
     853
     854/**
     855 * Callback function for writing to the PCI configuration space.
     856 *
     857 * @returns VINF_SUCCESS or PDMDevHlpDBGFStop status.
     858 *
     859 * @param   pDevIns         Pointer to the device instance the PCI device
     860 *                          belongs to.
     861 * @param   pPciDev         Pointer to PCI device. Use pPciDev->pDevIns to get the device instance.
     862 * @param   uAddress        The configuration space register address. [0..4096]
     863 * @param   u32Value        The value that's being written. The number of bits actually used from
     864 *                          this value is determined by the cb parameter.
     865 * @param   cb              The register size. [1,2,4]
     866 *
     867 * @remarks Called with the PDM lock held.  The device lock is NOT take because
     868 *          that is very likely be a lock order violation.
     869 */
     870static DECLCALLBACK(VBOXSTRICTRC) virtioPciConfigWrite(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev,
     871                                        uint32_t uAddress, uint32_t u32Value, unsigned cb)
     872{
     873    PVIRTIOSTATE pVirtio = PDMINS_2_DATA(pDevIns, PVIRTIOSTATE);
     874    VBOXSTRICTRC strictRc;
     875
     876    LogFunc(("uAddress: %d, uPciConfigDataOffset: %d\n", uAddress, pVirtio->uPciConfigDataOffset));
     877    if (uAddress == pVirtio->uPciConfigDataOffset)
     878        Log(("Wrote uPciConfigDataOffset\n"));
     879    strictRc = pVirtio->pfnPciConfigWriteOld(pDevIns, pPciDev, uAddress, u32Value, cb);
     880    return strictRc;
     881}
     882#endif
    605883/**
    606884 * Memory mapped I/O Handler for PCI Capabilities write operations.
     
    614892 * @param   cb          Number of bytes to write.
    615893 */
    616 PDMBOTHCBDECL(int) virtioPciCapMemWrite(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS GCPhysAddr, void const *pv, unsigned cb)
    617 {
    618 
    619 /* PK New feature! */
     894PDMBOTHCBDECL(int) virtioR3MmioWrite(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS GCPhysAddr, void const *pv, unsigned cb)
     895{
     896
    620897    RT_NOREF(pvUser);
     898    PVIRTIOSTATE pVirtio = PDMINS_2_DATA(pDevIns, PVIRTIOSTATE);
    621899    int rc = VINF_SUCCESS;
    622     LogFunc(("Write (MMIO) Virtio capabilities\n"));
    623     PVIRTIOSTATE pThis = PDMINS_2_DATA(pDevIns, PVIRTIOSTATE);
    624 
    625     /* TBD: This should be called only if VIRTIO_PCI_CAP_DEVICE_CFG capability is being accessed */
    626     rc = pThis->pfnVirtioDevCapWrite(pDevIns, GCPhysAddr, pv,cb);
     900
     901#ifdef LOG_ENABLED
     902//    LogFunc(("pVirtio=%#p GCPhysAddr=%RGp pv=%#p{%.*Rhxs} cb=%u\n", pVirtio, GCPhysAddr, pv, cb, pv, cb));
     903#endif
     904    off_t uoff = 0;
     905
     906    MATCH_VIRTIO_CAP_STRUCT(pVirtio->pGcPhysCommonCfg, VIRTIO_PCI_COMMON_CFG_T, pCommonCfg,  uoff);
     907    MATCH_VIRTIO_CAP_STRUCT(pVirtio->pGcPhysIsrCap,    VIRTIO_PCI_ISR_CAP_T,    pIsrCap,     uoff);
     908#if HAVE_VIRTIO_DEVICE_SPECIFIC_CAP
     909    MATCH_VIRTIO_CAP_STRUCT(pVirtio->pGcPhysDeviceCap, VIRTIO_PCI_DEVICE_CAP_T, pDeviceCap,  uoff);
     910#endif
     911
     912    if (pCommonCfg)
     913        virtioCommonCfgAccessed(pVirtio, 1 /* fWrite */, uoff, pv);
     914    else if (pIsrCap)
     915    {
     916        pVirtio->fQueueInterrupt = (*(uint8_t *)pv) & 1;
     917        pVirtio->fDeviceConfigInterrupt = !!(*((uint8_t *)pv) & 2);
     918        Log(("pIsrCap... setting fQueueInterrupt=%d fDeviceConfigInterrupt=%d\n",
     919              pVirtio->fQueueInterrupt, pVirtio->fDeviceConfigInterrupt));
     920    }
     921#if HAVE_VIRTIO_DEVICE_SPECIFIC_CAP
     922    else if (pDeviceCap)
     923        rc = pThis->pfnVirtioDevCapWrite(pDevIns, GCPhysAddr, pv, cb);
     924#endif
     925    else
     926        AssertMsgFailed(("virtio: Write outside of capabilities region\n"));
    627927
    628928    return rc;
    629929}
     930
    630931
    631932/**
     
    636937{
    637938    RT_NOREF3(pPciDev, iRegion, enmType);
    638     PVIRTIOSTATE  pThis = PDMINS_2_DATA(pDevIns, PVIRTIOSTATE);
     939    PVIRTIOSTATE  pVirtio = PDMINS_2_DATA(pDevIns, PVIRTIOSTATE);
    639940    int rc = VINF_SUCCESS;
    640941
    641942    Assert(cb >= 32);
    642 
    643     LogFunc(("virtIO controller PCI Capabilities mapped at GCPhysAddr=%RGp cb=%RGp\n", GCPhysAddress, cb));
    644943
    645944    /* We use the assigned size here, because we currently only support page aligned MMIO ranges. */
    646945    rc = PDMDevHlpMMIORegister(pDevIns, GCPhysAddress, cb, NULL /*pvUser*/,
    647946                           IOMMMIO_FLAGS_READ_PASSTHRU | IOMMMIO_FLAGS_WRITE_PASSTHRU,
    648                            virtioPciCapMemWrite, virtioPciCapMemRead,
     947                           virtioR3MmioWrite, virtioR3MmioRead,
    649948                           "virtio-scsi MMIO");
    650     pThis->GCPhysPciCapBase = RT_SUCCESS(rc) ? GCPhysAddress : 0;
     949
     950    LogFunc(("virtio: PCI Capabilities mapped at GCPhysAddr=%RGp cb=%RGp, region=%d\n", GCPhysAddress, cb, iRegion));
     951
     952    if (RT_SUCCESS(rc))
     953    {
     954        pVirtio->GCPhysPciCapBase = GCPhysAddress;
     955        pVirtio->pGcPhysCommonCfg = (PVIRTIO_PCI_COMMON_CFG_T)(GCPhysAddress + pVirtio->uCommonCfgOffset);
     956        pVirtio->pGcPhysNotifyCap = (PVIRTIO_PCI_NOTIFY_CAP_T)(GCPhysAddress + pVirtio->uNotifyCapOffset);
     957        pVirtio->pGcPhysIsrCap    = (PVIRTIO_PCI_ISR_CAP_T)(GCPhysAddress + pVirtio->uIsrCapOffset);
     958        pVirtio->pGcPhysPciCfgCap = (PVIRTIO_PCI_CFG_CAP_T)(GCPhysAddress + pVirtio->uPciCfgCapOffset);
     959#ifdef HAVE_VIRTIO_DEVICE_SPECIFIC_CAP
     960        pVirtio->pGcPhysDeviceCap = (PVIRTIO_PCI_DEVICE_CAP_T)(GCPhysAddress + pVirtio->uuDeviceCapOffset);
     961#endif
     962    }
    651963    return rc;
    652964}
     
    656968 * @interface_method_impl{PDMIBASE,pfnQueryInterface}
    657969 */
    658 void *virtioQueryInterface(struct PDMIBASE *pInterface, const char *pszIID)
     970void *virtioQueryInterface(PPDMIBASE pInterface, const char *pszIID)
    659971{
    660972    VIRTIOSTATE *pThis = IFACE_TO_STATE(pInterface, IBase);
     
    662974
    663975    PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASE, &pThis->IBase);
    664     PDMIBASE_RETURN_INTERFACE(pszIID, PDMILEDPORTS, &pThis->ILeds);
    665976    return NULL;
    666977}
    667978
     979/**
     980 * Get VirtIO available host-side features
     981 *
     982 * @returns feature bits selected or 0 if selector out of range.
     983 *
     984 * @param   pState          Virtio state
     985 * @param   uSelect         Selects which 32-bit set of feature information to return
     986 */
     987
     988static uint64_t virtioGetHostFeatures(PVIRTIOSTATE pVirtio)
     989{
     990    return pVirtio->uFeaturesOffered;
     991}
     992
     993/**
     994 *
     995 * Set VirtIO available host-side features
     996 *
     997 * @returns VBox status code
     998 *
     999 * @param   pState              Virtio state
     1000 * @param   uFeaturesOffered    Feature bits (0-63) to set
     1001 */
     1002
     1003static int virtioSetHostFeatures(PVIRTIOSTATE pVirtio, uint64_t uFeaturesOffered)
     1004{
     1005    pVirtio->uFeaturesOffered = VIRTIO_F_VERSION_1 | uFeaturesOffered;
     1006    return VINF_SUCCESS;
     1007}
    6681008
    6691009/**
     
    6781018{
    6791019    Log(("%s Destroying PCI instance\n", INSTANCE(pState)));
    680 
    6811020    return VINF_SUCCESS;
    6821021}
     
    7121051 * @param   devCapWriteCallback   Client function to call back to handle device specific capabilities
    7131052 * @param   cbDevSpecificCap      Size of device specific struct
    714  */
    715 int   virtioConstruct(PPDMDEVINS pDevIns, PVIRTIOSTATE pVirtio, int iInstance,
    716                     PVIRTIOPCIPARAMS pPciParams, const char *pcszNameFmt,
    717                     uint32_t nQueues, uint32_t uVirtioRegion,
     1053 * @param   uNotifyOffMultiplier  See VirtIO 1.0 spec 4.1.4.4 re: virtio_pci_notify_cap
     1054 */
     1055
     1056int   virtioConstruct(PPDMDEVINS pDevIns, PVIRTIOSTATE pVirtio, int iInstance, PVIRTIOPCIPARAMS pPciParams,
     1057                    PPVIRTIOCALLBACKS ppVirtioCallbacks, const char *pcszNameFmt, uint32_t nQueues, uint32_t uVirtioRegion,
    7181058                    PFNVIRTIODEVCAPREAD devCapReadCallback, PFNVIRTIODEVCAPWRITE devCapWriteCallback,
    719                     uint16_t cbDevSpecificCap)
    720 {
    721     RT_NOREF(nQueues);
     1059                    uint16_t cbDevSpecificCap, uint32_t uNotifyOffMultiplier)
     1060{
     1061    pVirtio->nQueues = nQueues;
     1062    pVirtio->uNotifyOffMultiplier = uNotifyOffMultiplier;
    7221063
    7231064    /* Init handles and log related stuff. */
    7241065    RTStrPrintf(pVirtio->szInstance, sizeof(pVirtio->szInstance), pcszNameFmt, iInstance);
    7251066
    726     pVirtio->pDevInsR3    = pDevIns;
    727     pVirtio->pDevInsR0    = PDMDEVINS_2_R0PTR(pDevIns);
    728     pVirtio->pDevInsRC    = PDMDEVINS_2_RCPTR(pDevIns);
    729     pVirtio->led.u32Magic = PDMLED_MAGIC;
    730     pVirtio->ILeds.pfnQueryStatusLed = virtioQueryStatusLed;
     1067    VIRTIOCALLBACKS virtioCallbacks;
     1068    virtioCallbacks.pfnSetHostFeatures = virtioSetHostFeatures;
     1069    virtioCallbacks.pfnGetHostFeatures = virtioGetHostFeatures;
     1070    virtioCallbacks.pfnReset = virtioReset;
     1071    *ppVirtioCallbacks = &virtioCallbacks;
     1072
     1073    pVirtio->pDevInsR3 = pDevIns;
     1074    pVirtio->pDevInsR0 = PDMDEVINS_2_R0PTR(pDevIns);
     1075    pVirtio->pDevInsRC = PDMDEVINS_2_RCPTR(pDevIns);
     1076    pVirtio->uDeviceStatus = 0;
    7311077    pVirtio->pfnVirtioDevCapRead     = devCapReadCallback;
    7321078    pVirtio->pfnVirtioDevCapWrite    = devCapWriteCallback;
     
    7531099    pVirtio->IBase = pDevIns->IBase;
    7541100
    755     rc = PDMDevHlpPCIIORegionRegister(pDevIns, uVirtioRegion, 32, PCI_ADDRESS_SPACE_MEM, virtioR3Map);
    756     if (RT_FAILURE(rc))
    757         return PDMDEV_SET_ERROR(pDevIns, rc,
    758             N_("virtio: cannot register PCI Capabilities address space")); /* can we put params in this error? */
    759 
    760     /** Build PCI vendor-specific capabilities list for exchanging
    761      *  VirtIO device capabilities with driver */
    762 
     1101    /** Construct & map PCI vendor-specific capabilities for virtio host negotiation with guest driver */
     1102
     1103#if 0 && defined(VBOX_WITH_MSI_DEVICES)  /* T.B.D. */
     1104    uint8_t fMsiSupport = true;
     1105#else
    7631106    uint8_t fMsiSupport = false;
    764 #if 0 && defined(VBOX_WITH_MSI_DEVICES)  /* T.B.D. */
    765         fMsiSupport = true;
    7661107#endif
     1108
    7671109    uint8_t uCfgCapOffset = 0x40;
    768     /* Capability will be mapped via VirtIO 1.0: struct virtio_pci_common_cfg (VIRTIOCOMMONCFG)*/
    769     PVIRTIOPCICAP pCfg = pVirtio->pCommonCfg = (PVIRTIOPCICAP)&pVirtio->dev.abConfig[uCfgCapOffset];
     1110    PVIRTIO_PCI_NOTIFY_CAP_T pNotifyCap;
     1111    PVIRTIO_PCI_CAP_T pCommonCfg, pIsrCap;
     1112#ifdef HAVE_VIRTIO_DEVICE_SPECIFIC_CAP
     1113    PVIRTIO_PCI_CAP_T pDeviceCap;
     1114#endif
     1115    uint32_t cbVirtioCaps = 0;
     1116
     1117    /* Capability will be mapped via VirtIO 1.0: struct virtio_pci_cfg_cap (VIRTIO_PCI_CAP_T) */
     1118    pVirtio->pPciCfgCap = (PVIRTIO_PCI_CFG_CAP_T)&pVirtio->dev.abConfig[uCfgCapOffset];
     1119    pVirtio->uPciConfigDataOffset = 0x40 + sizeof(VIRTIO_PCI_CAP_T);
     1120    PVIRTIO_PCI_CAP_T pCfg = (PVIRTIO_PCI_CAP_T)pVirtio->pPciCfgCap;
    7701121    pCfg->uCapVndr = VIRTIO_PCI_CAP_ID_VENDOR;
    771     pCfg->uCapNext = uCfgCapOffset += sizeof(VIRTIOPCICAP);
     1122    pCfg->uCapNext = uCfgCapOffset += sizeof(VIRTIO_PCI_CFG_CAP_T);
     1123    pCfg->uCapLen  = sizeof(VIRTIO_PCI_CFG_CAP_T);
     1124    pCfg->uCfgType = VIRTIO_PCI_CAP_PCI_CFG;
     1125    pCfg->uBar     = uVirtioRegion;
     1126    pCfg->uOffset  = pVirtio->uPciCfgCapOffset = 0;
     1127    pCfg->uLength  = sizeof(VIRTIO_PCI_CFG_CAP_T);
     1128    cbVirtioCaps  += pCfg->uLength;
     1129
     1130    /* Capability will be mapped via VirtIO 1.0: struct virtio_pci_common_cfg (VIRTIO_PCI_COMMON_CFG_T)*/
     1131    pCfg = pCommonCfg = (PVIRTIO_PCI_CAP_T)&pVirtio->dev.abConfig[uCfgCapOffset];
     1132    pCfg->uCapVndr = VIRTIO_PCI_CAP_ID_VENDOR;
     1133    pCfg->uCapNext = uCfgCapOffset += sizeof(VIRTIO_PCI_CAP_T);
     1134    pCfg->uCapLen  = sizeof(VIRTIO_PCI_CAP_T);
    7721135    pCfg->uCfgType = VIRTIO_PCI_CAP_COMMON_CFG;
    7731136    pCfg->uBar     = uVirtioRegion;
    774     pCfg->uOffset  = 0;
    775     pCfg->uLength  = sizeof(VIRTIOPCICAP);
    776 
    777     /* Capability will be mapped via VirtIO 1.0: struct virtio_pci_notify_cap (VIRTIONOTIFYCAP)*/
    778     pCfg = pVirtio->pNotifyCap = (PVIRTIOPCICAP)&pVirtio->dev.abConfig[uCfgCapOffset];
     1137    pCfg->uOffset  = pVirtio->uCommonCfgOffset = pVirtio->pPciCfgCap->pciCap.uOffset + sizeof(VIRTIO_PCI_CFG_CAP_T);
     1138    pCfg->uLength  = sizeof(VIRTIO_PCI_COMMON_CFG_T);
     1139    cbVirtioCaps  += pCfg->uLength;
     1140
     1141    /* Capability will be mapped via VirtIO 1.0: struct virtio_pci_notify_cap (VIRTIO_PCI_NOTIFY_CAP_T)*/
     1142    pNotifyCap = (PVIRTIO_PCI_NOTIFY_CAP_T)&pVirtio->dev.abConfig[uCfgCapOffset];
     1143    pCfg = (PVIRTIO_PCI_CAP_T)pNotifyCap;
    7791144    pCfg->uCapVndr = VIRTIO_PCI_CAP_ID_VENDOR;
    780     pCfg->uCapNext = uCfgCapOffset += sizeof(VIRTIOPCICAP);
     1145    pCfg->uCapNext = uCfgCapOffset += sizeof(VIRTIO_PCI_NOTIFY_CAP_T);
     1146    pCfg->uCapLen  = sizeof(VIRTIO_PCI_NOTIFY_CAP_T);
    7811147    pCfg->uCfgType = VIRTIO_PCI_CAP_NOTIFY_CFG;
    7821148    pCfg->uBar     = uVirtioRegion;
    783     pCfg->uOffset  = pVirtio->pCommonCfg->uOffset + sizeof(VIRTIOCOMMONCFG);
    784     pCfg->uLength  = sizeof(VIRTIOPCICAP);
    785 
    786     /* Capability will be mapped via VirtIO 1.0: uint8_t (VIRTIOISRCAP)  */
    787     pCfg = pVirtio->pISRCap = (PVIRTIOPCICAP)&pVirtio->dev.abConfig[uCfgCapOffset];
     1149    pCfg->uOffset  = pVirtio->uNotifyCapOffset = pCommonCfg->uOffset + sizeof(VIRTIO_PCI_COMMON_CFG_T);
     1150    pCfg->uLength  = sizeof(VIRTIO_PCI_NOTIFY_CAP_T);
     1151    pNotifyCap->uNotifyOffMultiplier = uNotifyOffMultiplier;
     1152    cbVirtioCaps  += pCfg->uLength;
     1153
     1154    /* Capability will be mapped via VirtIO 1.0: uint8_t (VIRTIO_PCI_ISR_CAP_T)  */
     1155    pCfg = pIsrCap = (PVIRTIO_PCI_CAP_T)&pVirtio->dev.abConfig[uCfgCapOffset];
    7881156    pCfg->uCapVndr = VIRTIO_PCI_CAP_ID_VENDOR;
    789     pCfg->uCapNext = uCfgCapOffset += sizeof(VIRTIOPCICAP);
     1157    pCfg->uCapNext = (uint8_t)(fMsiSupport || cbDevSpecificCap ? (uCfgCapOffset += sizeof(VIRTIO_PCI_ISR_CAP_T)) : 0);
     1158    pCfg->uCapLen  = sizeof(VIRTIO_PCI_CAP_T);
    7901159    pCfg->uCfgType = VIRTIO_PCI_CAP_ISR_CFG;
    7911160    pCfg->uBar     = uVirtioRegion;
    792     pCfg->uOffset  = pVirtio->pNotifyCap->uOffset + sizeof(VIRTIONOTIFYCAP);
    793     pCfg->uLength  = sizeof(VIRTIOPCICAP);
    794 
    795     /* Capability will be mapped via VirtIO 1.0: struct virtio_pci_cfg_cap (VIRTIOPCICAP) */
    796     pCfg = pVirtio->pPCICfgCap = (PVIRTIOPCICAP)&pVirtio->dev.abConfig[uCfgCapOffset];
     1161    pCfg->uOffset  = pVirtio->uIsrCapOffset = pNotifyCap->pciCap.uOffset + sizeof(VIRTIO_PCI_NOTIFY_CAP_T);
     1162    pCfg->uLength  = sizeof(VIRTIO_PCI_ISR_CAP_T);
     1163    cbVirtioCaps  += pCfg->uLength;
     1164
     1165#ifdef HAVE_VIRTIO_DEVICE_SPECIFIC_CAP
     1166    /* Capability will be mapped via VirtIO 1.0: struct virtio_pci_dev_cap (VIRTIODEVCAP)*/
     1167    pCfg = pDeviceCap = (PVIRTIO_PCI_CAP_T)&pVirtio->dev.abConfig[uCfgCapOffset];
    7971168    pCfg->uCapVndr = VIRTIO_PCI_CAP_ID_VENDOR;
    798     pCfg->uCapNext = (uint8_t)(fMsiSupport || cbDevSpecificCap ? (uCfgCapOffset += sizeof(VIRTIOPCICAP)): 0);
    799     pCfg->uCfgType = VIRTIO_PCI_CAP_PCI_CFG;
     1169    pCfg->uCapNext = (uint8_t)(fMsiSupport ? (uCfgCapOffset += sizeof(VIRTIO_PCI_CAP_T)) : 0);
     1170    pCfg->uCapLen  = sizeof(VIRTIO_PCI_CAP_T);
     1171    pCfg->uCfgType = VIRTIO_PCI_CAP_DEVICE_CFG;
    8001172    pCfg->uBar     = uVirtioRegion;
    801     pCfg->uOffset  = pVirtio->pISRCap->uOffset + sizeof(VIRTIOISRCAP);
    802     pCfg->uLength  = sizeof(VIRTIOPCICAP);
    803 
    804     if (cbDevSpecificCap)
    805     {
    806      /* Capability will be mapped via VirtIO 1.0: struct virtio_pci_dev_cap (VIRTIODEVCAP)*/
    807         pCfg = pVirtio->pDeviceCap = (PVIRTIOPCICAP)&pVirtio->dev.abConfig[uCfgCapOffset];
    808         pCfg->uCapVndr = VIRTIO_PCI_CAP_ID_VENDOR;
    809         pCfg->uCapNext = (uint8_t)(fMsiSupport ? (uCfgCapOffset += sizeof(VIRTIOPCICAP)) : 0);
    810         pCfg->uCfgType = VIRTIO_PCI_CAP_DEVICE_CFG;
    811         pCfg->uBar     = uVirtioRegion;
    812         pCfg->uOffset  = pVirtio->pPCICfgCap->uOffset + sizeof(VIRTIOPCICAP);
    813         pCfg->uLength  = sizeof(VIRTIOPCICAP);
    814     }
     1173    pCfg->uOffset  = uDeviceCapOffset->uOffset + sizeof(VIRTIO_PCI_ISR_CAP_T);
     1174    pCfg->uLength  = cbDevSpecificCap;
     1175    cbVirtioCaps  += pCfg->uLength;
     1176#endif
    8151177
    8161178    /* Set offset to first capability and enable PCI dev capabilities */
     
    8211183    {
    8221184        PDMMSIREG aMsiReg;
    823 
    8241185        RT_ZERO(aMsiReg);
    8251186        aMsiReg.iMsixCapOffset  = uCfgCapOffset;
     
    8291190        rc = PDMDevHlpPCIRegisterMsi(pDevIns, &aMsiReg); /* see MsixR3init() */
    8301191        if (RT_FAILURE (rc))
    831         {
    8321192            /* PK TODO: The following is moot, we need to flag no MSI-X support */
    8331193            PCIDevSetCapabilityList(&pVirtio->dev, 0x40);
    834         }
    835     }
    836 
    837     /* Status driver */
    838     PPDMIBASE pUpstreamBase;
    839 
    840     rc = PDMDevHlpDriverAttach(pDevIns, PDM_STATUS_LUN, &pVirtio->IBase, &pUpstreamBase, "Status Port");
     1194    }
     1195/*
     1196    PDMDevHlpPCISetConfigCallbacks(pDevIns, &pVirtio->dev,
     1197                virtioPciConfigRead,  &pVirtio->pfnPciConfigReadOld,
     1198                virtioPciConfigWrite, &pVirtio->pfnPciConfigWriteOld);
     1199*/
     1200    rc = PDMDevHlpPCIIORegionRegister(pDevIns, uVirtioRegion, cbVirtioCaps,
     1201                                      PCI_ADDRESS_SPACE_MEM, virtioR3Map);
    8411202    if (RT_FAILURE(rc))
    842         return PDMDEV_SET_ERROR(pDevIns, rc, N_("Failed to attach the status LUN"));
    843     pVirtio->pLedsConnector = PDMIBASE_QUERY_INTERFACE(&pVirtio->IBase, PDMILEDCONNECTORS);
     1203        return PDMDEV_SET_ERROR(pDevIns, rc,
     1204            N_("virtio: cannot register PCI Capabilities address space"));
    8441205
    8451206    return rc;
    8461207}
    8471208
    848 
    849 
    8501209#endif /* IN_RING3 */
    8511210
  • trunk/src/VBox/Devices/VirtIO/Virtio_1_0.h

    r79973 r80058  
    3434/** @} */
    3535
     36
     37/** Reserved Feature Bits */
     38#define VIRTIO_F_RING_INDIRECT_DESC         RT_BIT_64(28)
     39#define VIRTIO_F_RING_IDX                   RT_BIT_64(29)
     40#define VIRTIO_F_VERSION_1                  RT_BIT_64(32)
     41
     42#define MAX_QUEUES                          5       /** Maximum number of queues we support     */
     43
    3644/** Mandatory for Virtio PCI device identification, per spec */
    3745#define DEVICE_PCI_VENDOR_ID_VIRTIO         0x1AF4
     
    6977typedef DECLCALLBACK(uint32_t) FNGETHOSTFEATURES(void *pvState);
    7078typedef FNGETHOSTFEATURES *PFNGETHOSTFEATURES;
    71 
    72 /** @name VirtIO port I/O callbacks.
    73  * @{ */
    74 typedef struct VIRTIOIOCALLBACKS
    75 {
    76      DECLCALLBACKMEMBER(uint32_t, pfnGetHostFeatures)(void *pvState);
    77      DECLCALLBACKMEMBER(uint32_t, pfnGetHostMinimalFeatures)(void *pvState);
    78      DECLCALLBACKMEMBER(void,     pfnSetHostFeatures)(void *pvState, uint32_t fFeatures);
    79      DECLCALLBACKMEMBER(int,      pfnGetConfig)(void *pvState, uint32_t offCfg, uint32_t cb, void *pvData);
    80      DECLCALLBACKMEMBER(int,      pfnSetConfig)(void *pvState, uint32_t offCfg, uint32_t cb, void *pvData);
    81      DECLCALLBACKMEMBER(int,      pfnReset)(void *pvState);
    82      DECLCALLBACKMEMBER(void,     pfnReady)(void *pvState);
    83 } VIRTIOIOCALLBACKS;
    84 /** Pointer to a const VirtIO port I/O callback structure. */
    85 typedef const VIRTIOIOCALLBACKS *PCVIRTIOIOCALLBACKS;
    86 /** @} */
    8779
    8880
     
    140132    uint32_t  uOffset;                /** Offset within bar.  (L.E.)                  */
    141133    uint32_t  uLength;                /** Length of struct, in bytes. (L.E.)          */
    142 }  VIRTIOPCICAP, *PVIRTIOPCICAP;
     134}  VIRTIO_PCI_CAP_T, *PVIRTIO_PCI_CAP_T;
    143135
    144136typedef struct virtio_pci_common_cfg /* VirtIO 1.0 specification name of this struct  */
     
    165157    uint16_t  uQueueMsixVector;       /** RW (driver selects MSI-X queue vector)      */
    166158    uint16_t  uQueueEnable;           /** RW (driver controls usability of queue)     */
    167     uint16_t  uQueueNotifyOff;        /** RO (offset to virtqueue; see spec)          */
     159    uint16_t  uQueueNotifyOff;        /** RO (offset uto virtqueue; see spec)          */
    168160    uint64_t  uQueueDesc;             /** RW (driver writes desc table phys addr)     */
    169161    uint64_t  uQueueAvail;            /** RW (driver writes avail ring phys addr)     */
    170162    uint64_t  uQueueUsed;             /** RW (driver writes used ring  phys addr)     */
    171 } VIRTIOCOMMONCFG, *PVIRTIOCOMMONCFG;
     163} VIRTIO_PCI_COMMON_CFG_T, *PVIRTIO_PCI_COMMON_CFG_T;
    172164
    173165typedef struct virtio_pci_notify_cap
    174166{
    175         struct virtio_pci_cap cap;
     167        struct virtio_pci_cap pciCap;
    176168        uint32_t uNotifyOffMultiplier; /* notify_off_multiplier                        */
    177 } VIRTIONOTIFYCAP, *PVIRTIONOTIFYCAP;
    178 
    179 typedef uint8_t VIRTIOISRCAP, *PVIRTIOISRCAP;
    180 
    181 /* Device-specific configuration (if any) ... T.B.D. (if and when neeed), provide an
    182  * interface/callback that lets the client of this code manage it, if and when needed.
    183  * probably just passing in a struct length and a callback from our capabilities
    184  * region handler */
    185 typedef struct virtio_pci_dev_cfg
    186 {
    187 } VIRTIODEVCAP, *PVIRTIODEVCAP;
     169} VIRTIO_PCI_NOTIFY_CAP_T, *PVIRTIO_PCI_NOTIFY_CAP_T;
     170
     171typedef uint8_t VIRTIO_PCI_ISR_CAP_T, *PVIRTIO_PCI_ISR_CAP_T;
     172
     173/*
     174 * If the client of this library has any device-specific capabilities, it must define
     175 * and implement this struct and the macro
     176 */
     177#ifdef HAVE_VIRTIO_DEVICE_SPECIFIC_CAP
     178typedef struct virtio_pci_dev_cfg     VIRTIO_PCI_DEVICE_CAP_T, *PVIRTIO_PCI_DEVICE_CAP_T;
     179#endif
    188180
    189181typedef struct virtio_pci_cfg_cap {
    190         struct virtio_pci_cap cap;
    191         uint8_t pci_cfg_data[4]; /* Data for BAR access. */
    192 } VIRTIOPCICFGCAP, *PVIRTIOPCICFGCAP;
     182        struct virtio_pci_cap pciCap;
     183        uint8_t uPciCfgData[4]; /* Data for BAR access. */
     184} VIRTIO_PCI_CFG_CAP_T, *PVIRTIO_PCI_CFG_CAP_T;
    193185
    194186typedef struct virtq_desc  /* VirtIO 1.0 specification formal name of this struct     */
     
    306298    /** Status LUN: Base interface. */
    307299    PDMIBASE               IBase;
     300
    308301    /** Status LUN: LED port interface. */
    309     PDMILEDPORTS           ILeds;
    310     /** Status LUN: LED connector (peer). */
    311     R3PTRTYPE(PPDMILEDCONNECTORS) pLedsConnector;
    312 
    313     PPDMDEVINSR3           pDevInsR3;              /**< Device instance - R3. */
    314     PPDMDEVINSR0           pDevInsR0;              /**< Device instance - R0. */
    315     PPDMDEVINSRC           pDevInsRC;              /**< Device instance - RC. */
    316 
    317     /** Base address of PCI capabilities */
    318     RTGCPHYS               GCPhysPciCapBase;
    319 
    320     VIRTIOCOMMONCFG        pGcPhysVirtioCommonCfg;
    321     VIRTIONOTIFYCAP        pGcPhysVirtioNotifyCap;
    322     VIRTIOISRCAP           pGcPhysVirtioIsrCap;
    323     VIRTIODEVCAP           pGcPhysVirtioDevCap;
    324     VIRTIOPCICFGCAP        pGcPhysVirtioPciCap;
    325 
    326     /** Callbacks when guest driver reads or writes VirtIO device-specific capabilities(s) */
    327 
    328     PFNVIRTIODEVCAPWRITE   pfnVirtioDevCapWrite;
    329     PFNVIRTIODEVCAPREAD    pfnVirtioDevCapRead;
    330 
    331 #if HC_ARCH_BITS == 64
    332     uint32_t               padding2;
    333 #endif
    334 
    335     /** Base port of I/O space region. */
    336     RTIOPORT               IOPortBase;
     302    PDMILEDPORTS           ILed;
    337303
    338304    /* Read/write part, protected with critical section. */
     
    340306    PDMLED                 led;
    341307
    342     uint32_t               uGuestFeatures;
    343     uint16_t               uQueueSelector;         /**< An index in aQueues array. */
    344     uint8_t                uStatus;                /**< Device Status (bits are device-specific). */
    345     uint8_t                uISR;                   /**< Interrupt Status Register. */
     308
     309    /** Status LUN: LED connector (peer). */
     310    R3PTRTYPE(PPDMILEDCONNECTORS) pLedsConnector;
     311
     312    PPDMDEVINSR3                pDevInsR3;              /**< Device instance - R3. */
     313    PPDMDEVINSR0                pDevInsR0;              /**< Device instance - R0. */
     314    PPDMDEVINSRC                pDevInsRC;              /**< Device instance - RC. */
     315
     316    /** Base address of PCI capabilities */
     317    RTGCPHYS                    GCPhysPciCapBase;
     318
     319
     320    /** Callbacks when guest driver reads or writes VirtIO device-specific capabilities(s) */
     321
     322    PFNVIRTIODEVCAPWRITE         pfnVirtioDevCapWrite;
     323    PFNVIRTIODEVCAPREAD          pfnVirtioDevCapRead;
     324    PFNPCICONFIGREAD             pfnPciConfigReadOld;
     325    PFNPCICONFIGWRITE            pfnPciConfigWriteOld;
     326
     327    uint8_t                      uPciConfigDataOffset;
     328#if HC_ARCH_BITS == 64
     329    uint32_t                     padding2;
     330#endif
     331
     332    /** Base port of I/O space region. */
     333    RTIOPORT                     IOPortBase;
     334
     335    uint32_t                     uGuestFeatures;
     336    uint16_t                     uQueueSelector;             /** An index in aQueues array. */
     337    uint8_t                      uStatus;                    /** Device Status (bits are device-specific). */
     338    uint8_t                      uISR;                       /** Interrupt Status Register. */
    346339
    347340#if HC_ARCH_BITS != 64
    348     uint32_t               padding3;
    349 #endif
    350 
    351     uint32_t               nQueues;       /**< Actual number of queues used. */
    352     VQUEUE                 Queues[VIRTIO_MAX_NQUEUES];
    353 
    354     PVIRTIOPCICAP pCommonCfg;
    355     PVIRTIOPCICAP pNotifyCap;
    356     PVIRTIOPCICAP pISRCap;
    357     PVIRTIOPCICAP pPCICfgCap;
    358     PVIRTIOPCICAP pDeviceCap;
     341    uint32_t                     padding3;
     342#endif
     343
     344    uint32_t                     nQueues;                    /** Actual number of queues used. */
     345    VQUEUE                       Queues[VIRTIO_MAX_NQUEUES];
     346
     347    uint32_t                     uFeaturesOfferedSelect;     /** Select hi/lo 32-bit uFeaturesOffered to r/w */
     348    uint64_t                     uFeaturesOffered;           /** Host features offered */
     349    uint32_t                     uFeaturesAcceptedSelect;    /** Selects hi/lo 32-bit uFeaturesAccepted to r/w*/
     350    uint64_t                     uFeaturesAccepted;          /** Host features accepted by guest */
     351
     352    uint32_t                     uMsixConfig;
     353    uint8_t                      uDeviceStatus;
     354    uint8_t                      uConfigGeneration;
     355    uint32_t                     uNotifyOffMultiplier;       /* Multiplier for uQueueNotifyOff[idx] */
     356
     357    uint16_t                     uQueueSelect;
     358    uint16_t                     uQueueSize[MAX_QUEUES];
     359    uint16_t                     uQueueMsixVector[MAX_QUEUES];
     360    uint16_t                     uQueueEnable[MAX_QUEUES];
     361    uint16_t                     uQueueNotifyOff[MAX_QUEUES];
     362    uint64_t                     uQueueDesc[MAX_QUEUES];
     363    uint64_t                     uQueueAvail[MAX_QUEUES];
     364    uint64_t                     uQueueUsed[MAX_QUEUES];
     365
     366    uint32_t                     uNotifyCapOffset;
     367    uint32_t                     uIsrCapOffset;
     368    uint32_t                     uPciCfgCapOffset;
     369    uint32_t                     uDeviceCapOffset;
     370    uint32_t                     uCommonCfgOffset;
     371
     372    PVIRTIO_PCI_CFG_CAP_T        pPciCfgCap;            /** Pointer to struct in configuration area */
     373
     374    PVIRTIO_PCI_COMMON_CFG_T     pGcPhysCommonCfg;      /** Pointer to MMIO mapped struct */
     375    PVIRTIO_PCI_NOTIFY_CAP_T     pGcPhysNotifyCap;      /** Pointer to MMIO mapped struct */
     376    PVIRTIO_PCI_ISR_CAP_T        pGcPhysIsrCap;         /** Pointer to MMIO mapped struct */
     377    PVIRTIO_PCI_CFG_CAP_T        pGcPhysPciCfgCap;      /** Pointer to MMIO mapped struct */
     378#ifdef HAVE_VIRTIO_DEVICE_SPECIFIC_CAP
     379    PVIRTIO_PCI_DEVICE_CAP_T     pGcPhysDeviceCap;      /** Pointer to MMIO mapped struct */
     380#endif
     381
     382    bool fDeviceConfigInterrupt;
     383    bool fQueueInterrupt;
     384
    359385} VIRTIOSTATE, *PVIRTIOSTATE;
     386
     387/** @name VirtIO port I/O callbacks.
     388 * @{ */
     389typedef struct VIRTIOIOCALLBACKS
     390{
     391     DECLCALLBACKMEMBER(uint64_t, pfnGetHostFeatures)(PVIRTIOSTATE pVirtio);
     392     DECLCALLBACKMEMBER(int,      pfnSetHostFeatures)(PVIRTIOSTATE pVirtio, uint64_t uFeaturesOffered);
     393     DECLCALLBACKMEMBER(int,      pfnReset)(PVIRTIOSTATE pVirtio);
     394/*   DECLCALLBACKMEMBER(uint32_t, pfnGetHostMinimalFeatures)(void *pvState); */
     395/*   DECLCALLBACKMEMBER(int,      pfnGetConfig)(void *pvState, uint32_t offCfg, uint32_t cb, void *pvData); */
     396/*   DECLCALLBACKMEMBER(int,      pfnSetConfig)(void *pvState, uint32_t offCfg, uint32_t cb, void *pvData); */
     397/*   DECLCALLBACKMEMBER(void,     pfnReady)(void *pvState); */
     398} VIRTIOCALLBACKS, *PVIRTIOCALLBACKS, **PPVIRTIOCALLBACKS;
     399/** @} */
    360400
    361401void    virtioRelocate(PPDMDEVINS pDevIns, RTGCINTPTR offDelta);
    362402void   *virtioQueryInterface(struct PDMIBASE *pInterface, const char *pszIID);
    363403
    364 int     virtioIOPortIn(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT port,
    365                         uint32_t *pu32, unsigned cb, PCVIRTIOIOCALLBACKS pCallbacks);
    366 
    367 int     virtioIOPortOut(PPDMDEVINS pDevIns, void  *pvUser, RTIOPORT port,
    368                         uint32_t u32, unsigned cb, PCVIRTIOIOCALLBACKS pCallbacks);
    369 
    370 int     virtioConstruct(PPDMDEVINS pDevIns, PVIRTIOSTATE pVirtio, int iInstance,
    371                     PVIRTIOPCIPARAMS pPciParams, const char *pcszNameFmt,
    372                     uint32_t nQueues, uint32_t uVirtioRegion,
     404int     virtioConstruct(PPDMDEVINS pDevIns, PVIRTIOSTATE pVirtio, int iInstance, PVIRTIOPCIPARAMS pPciParams,
     405                    PPVIRTIOCALLBACKS ppVirtioCallbacks, const char *pcszNameFmt, uint32_t nQueues, uint32_t uVirtioRegion,
    373406                    PFNVIRTIODEVCAPREAD devCapReadCallback, PFNVIRTIODEVCAPWRITE devCapWriteCallback,
    374                     uint16_t cbDevSpecificCap);
    375 
    376 
    377 int     virtioDestruct(       PVIRTIOSTATE pState);
    378 void    virtioReset(          PVIRTIOSTATE pState);
    379 int     virtioSaveExec(       PVIRTIOSTATE pState, PSSMHANDLE pSSM);
    380 int     virtioLoadExec(       PVIRTIOSTATE pState, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass, uint32_t nQueues);
    381 void    virtioSetReadLed(     PVIRTIOSTATE pState, bool fOn);
    382 void    virtioSetWriteLed(    PVIRTIOSTATE pState, bool fOn);
    383 int     virtioRaiseInterrupt( PVIRTIOSTATE pState, int rcBusy, uint8_t uint8_tIntCause);
    384 
    385 PVQUEUE virtioAddQueue(       PVIRTIOSTATE pState, unsigned uSize, PFNVIRTIOQUEUECALLBACK pfnCallback, const char *pcszName);
    386 bool    virtQueueSkip(        PVIRTIOSTATE pState, PVQUEUE pQueue);
    387 bool    virtQueueGet(         PVIRTIOSTATE pState, PVQUEUE pQueue, PVQUEUEELEM pElem, bool fRemove = true);
    388 void    virtQueuePut(         PVIRTIOSTATE pState, PVQUEUE pQueue, PVQUEUEELEM pElem, uint32_t len, uint32_t uReserved = 0);
    389 void    virtQueueNotify(      PVIRTIOSTATE pState, PVQUEUE pQueue);
    390 void    virtQueueSync(        PVIRTIOSTATE pState, PVQUEUE pQueue);
    391 void    vringSetNotification( PVIRTIOSTATE pState, PVIRTQUEUE pVirtQueue, bool fEnabled);
    392 
    393 
    394 /*
     407                    uint16_t cbDevSpecificCap, uint32_t uNotifyOffMultiplier);
     408
     409int     virtioDestruct(PVIRTIOSTATE pVirtio);
     410int     virtioReset(PVIRTIOSTATE pVirtio);
     411int     virtioSaveExec(PVIRTIOSTATE pVirtio, PSSMHANDLE pSSM);
     412int     virtioLoadExec(PVIRTIOSTATE pVirtio, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass, uint32_t nQueues);
     413void    virtioSetReadLed(PVIRTIOSTATE pVirtio, bool fOn);
     414void    virtioSetWriteLed(PVIRTIOSTATE pVirtio, bool fOn);
     415int     virtioRaiseInterrupt(PVIRTIOSTATE pVirtio, int rcBusy, uint8_t uint8_tIntCause);
     416void    virtioNotify(PVIRTIOSTATE pVirtio);
     417
     418PVQUEUE virtioAddQueue(PVIRTIOSTATE pVirtio, unsigned uSize, PFNVIRTIOQUEUECALLBACK pfnCallback, const char *pcszName);
     419bool    virtQueueSkip(PVIRTIOSTATE pVirtio, PVQUEUE pQueue);
     420bool    virtQueueGet(PVIRTIOSTATE pVirtio, PVQUEUE pQueue, PVQUEUEELEM pElem, bool fRemove = true);
     421void    virtQueuePut(PVIRTIOSTATE pVirtio, PVQUEUE pQueue, PVQUEUEELEM pElem, uint32_t len, uint32_t uReserved = 0);
     422void    virtQueueNotify(PVIRTIOSTATE pVirtio, PVQUEUE pQueue);
     423void    virtQueueSync(PVIRTIOSTATE pVirtio, PVQUEUE pQueue);
     424void    vringSetNotification( PVIRTIOSTATE pVirtio, PVIRTQUEUE pVirtQueue, bool fEnabled);
     425
     426DECLINLINE(void) showDeviceStatus(uint8_t status)
     427{
     428    if (status & VIRTIO_STATUS_ACKNOWLEDGE)
     429        Log(("                        ACKNOWLEDGE\n"));
     430    if (status & VIRTIO_STATUS_DRIVER)
     431        Log(("                        DRIVER\n"));
     432    if (status & VIRTIO_STATUS_DRIVER_OK)
     433        Log(("                        DRIVER_OK\n"));
     434    if (status & VIRTIO_STATUS_FEATURES_OK)
     435        Log(("                        FEATURES_OK\n"));
     436    if (status & VIRTIO_STATUS_FAILED)
     437        Log(("                        FAILED\n"));
     438    if (status & VIRTIO_STATUS_DEVICE_NEEDS_RESET)
     439        Log(("                        ACKNOWLEDGE\n"));
     440    if (status == 0)
     441        Log(("                        RESET\n"));
     442    Log(("\n"));
     443}
     444
     445/*  FROM Virtio 1.0 SPEC, NYI
    395446      static inline int virtq_need_event(uint16_t event_idx, uint16_t new_idx, uint16_t old_idx)
    396447            return (uint16_t)(new_idx - event_idx - 1) < (uint16_t)(new_idx - old_idx);
     
    435486}
    436487
    437 DECLINLINE(int) virtioLock(VIRTIOSTATE *pState, int rcBusy)
    438 {
    439     int rc = PDMCritSectEnter(&pState->cs, rcBusy);
    440     return rc;
    441 }
    442 
    443 DECLINLINE(void) virtioUnlock(VIRTIOSTATE *pState)
    444 {
    445     PDMCritSectLeave(&pState->cs);
    446 }
    447 
    448488#endif /* !VBOX_INCLUDED_SRC_VirtIO_Virtio_1_0_h */
Note: See TracChangeset for help on using the changeset viewer.

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