VirtualBox

Changeset 85016 in vbox for trunk


Ignore:
Timestamp:
Jul 1, 2020 5:28:16 AM (4 years ago)
Author:
vboxsync
Message:

Network/DeviVirtioNet_1_0.cpp: More clean up and naming for readability and consistency. Also moved MMIO parsing/loggin/accessor macros into header file to use consistently among VirtioCore.cpp, DevVirtioNet_1_0.cpp, DevVirtioSCSI.cpp

Location:
trunk/src/VBox/Devices
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Devices/Network/DevVirtioNet_1_0.cpp

    r84882 r85016  
    5959#include "VBoxDD.h"
    6060
    61 #define VIRTIONET_SAVED_STATE_VERSION          UINT32_C(1)
    62 #define VIRTIONET_MAX_QPAIRS                   1
    63 #define VIRTIONET_MAX_VIRTQS                   (VIRTIONET_MAX_QPAIRS * 2 + 1)
    64 #define VIRTIONET_MAX_FRAME_SIZE               65535 + 18     /**< Max IP pkt size + Ethernet header with VLAN tag  */
    65 #define VIRTIONET_MAC_FILTER_LEN               32
    66 #define VIRTIONET_MAX_VLAN_ID                  (1 << 12)
    67 #define VIRTIONET_PREALLOCATE_RX_SEG_COUNT     32
    68 
    69 #define VIRTQNAME(uVirtqNbr)       (pThis->aVirtqs[uVirtqNbr]->szName)
    70 #define CBVIRTQNAME(uVirtqNbr)     RTStrNLen(VIRTQNAME(uVirtqNbr), sizeof(VIRTQNAME(uVirtqNbr)))
    71 #define FEATURE_ENABLED(feature)  RT_BOOL(pThis->fNegotiatedFeatures & VIRTIONET_F_##feature)
    72 #define FEATURE_DISABLED(feature) (!FEATURE_ENABLED(feature))
    73 #define FEATURE_OFFERED(feature)  VIRTIONET_HOST_FEATURES_OFFERED & VIRTIONET_F_##feature
    74 
    75 #define IS_VIRTQ_EMPTY(pDevIns, pVirtio, uVirtqNbr) \
    76             (virtioCoreVirtqAvailBufCount(pDevIns, pVirtio, uVirtqNbr) == 0)
    77 
     61#define LUN0                            0
     62
     63#define VIRTIONET_SAVED_STATE_VERSION   UINT32_C(1)
     64#define VIRTIONET_MAX_QPAIRS            1
     65#define VIRTIONET_MAX_VIRTQS            (VIRTIONET_MAX_QPAIRS * 2 + 1)
     66#define VIRTIONET_MAX_FRAME_SIZE        65535 + 18  /**< Max IP pkt size + Eth. header w/VLAN tag  */
     67#define VIRTIONET_MAC_FILTER_LEN        32
     68#define VIRTIONET_MAX_VLAN_ID           (1 << 12)
     69#define VIRTIONET_RX_SEG_COUNT          32
     70
     71#define VIRTQNAME(uVirtqNbr)            (pThis->aVirtqs[uVirtqNbr]->szName)
     72#define CBVIRTQNAME(uVirtqNbr)          RTStrNLen(VIRTQNAME(uVirtqNbr), sizeof(VIRTQNAME(uVirtqNbr)))
     73#define FEATURE_ENABLED(feature)        RT_BOOL(pThis->fNegotiatedFeatures & VIRTIONET_F_##feature)
     74#define FEATURE_DISABLED(feature)       (!FEATURE_ENABLED(feature))
     75#define FEATURE_OFFERED(feature)        VIRTIONET_HOST_FEATURES_OFFERED & VIRTIONET_F_##feature
     76
     77/* Macros to calculate queue specific index number VirtIO 1.0, 5.1.2 */
     78#define IS_TX_VIRTQ(n)                  ((n) != CTRLQIDX && ((n) & 1))
     79#define IS_RX_VIRTQ(n)                  ((n) != CTRLQIDX && !IS_TX_VIRTQ(n))
     80#define IS_CTRL_VIRTQ(n)                ((n) == CTRLQIDX)
     81#define RXQIDX(qPairIdx)                (qPairIdx * 2)
     82#define TXQIDX(qPairIdx)                (qPairIdx * 2 + 1)
     83#define CTRLQIDX                        (FEATURE_ENABLED(MQ) ? ((VIRTIONET_MAX_QPAIRS - 1) * 2 + 2) : 2)
     84
     85#define IS_LINK_UP(pState)              (pState->virtioNetConfig.uStatus & VIRTIONET_F_LINK_UP)
     86#define IS_LINK_DOWN(pState)            !IS_LINK_UP(pState)
     87
     88\
    7889#define SET_LINK_UP(pState) \
    7990            LogFunc(("SET_LINK_UP\n")); \
     
    8697            virtioCoreNotifyConfigChanged(&pThis->Virtio)
    8798
    88 #define IS_LINK_UP(pState)   (pState->virtioNetConfig.uStatus & VIRTIONET_F_LINK_UP)
    89 #define IS_LINK_DOWN(pState) !IS_LINK_UP(pState)
    90 
    91 /* Macros to calculate queue specific index number VirtIO 1.0, 5.1.2 */
    92 #define IS_TX_VIRTQ(n)    ((n) != CTRLQIDX && ((n) & 1))
    93 #define IS_RX_VIRTQ(n)    ((n) != CTRLQIDX && !IS_TX_VIRTQ(n))
    94 #define IS_CTRL_VIRTQ(n)  ((n) == CTRLQIDX)
    95 #define RXQIDX(qPairIdx)  (qPairIdx * 2)
    96 #define TXQIDX(qPairIdx)  (qPairIdx * 2 + 1)
    97 #define CTRLQIDX          (FEATURE_ENABLED(MQ) ? ((VIRTIONET_MAX_QPAIRS - 1) * 2 + 2) : 2)
    98 
    99 #define LUN0    0
     99#define IS_VIRTQ_EMPTY(pDevIns, pVirtio, uVirtqNbr) \
     100            (virtioCoreVirtqAvailBufCount(pDevIns, pVirtio, uVirtqNbr) == 0)
     101
    100102
    101103#ifdef USING_CRITICAL_SECTION
     
    183185*   Structures and Typedefs                                                                                                      *
    184186*********************************************************************************************************************************/
     187
    185188/**
    186189 * Virtio Net Host Device device-specific configuration (VirtIO 1.0, 5.1.4)
     
    188191 * MMIO accesses to device-specific configuration parameters.
    189192 */
    190 
    191193#pragma pack(1)
    192 typedef struct virtio_net_config
    193 {
    194     RTMAC  uMacAddress;                                         /**< mac                                            */
    195 #if FEATURE_OFFERED(STATUS)
    196     uint16_t uStatus;                                           /**< status                                         */
     194
     195    typedef struct virtio_net_config
     196    {
     197        RTMAC  uMacAddress;                                     /**< mac                                            */
     198
     199#if     FEATURE_OFFERED(STATUS)
     200               uint16_t uStatus;                                /**< status                                         */
    197201#endif
    198 #if FEATURE_OFFERED(MQ)
    199     uint16_t uMaxVirtqPairs;                                    /**< max_virtq_pairs                                */
     202
     203#if     FEATURE_OFFERED(MQ)
     204               uint16_t uMaxVirtqPairs;                         /**< max_virtq_pairs                                */
    200205#endif
    201 } VIRTIONET_CONFIG_T, PVIRTIONET_CONFIG_T;
     206
     207    } VIRTIONET_CONFIG_T, PVIRTIONET_CONFIG_T;
     208
    202209#pragma pack()
    203210
     
    770777#ifdef LOG_ENABLED
    771778void virtioNetDumpGcPhysRxBuf(PPDMDEVINS pDevIns, PVIRTIONETPKTHDR pRxPktHdr,
    772                      uint16_t cDescs, uint8_t *pvBuf, uint16_t cb, RTGCPHYS GCPhysRxBuf, uint8_t cbRxBuf)
     779                     uint16_t cVirtqBufs, uint8_t *pvBuf, uint16_t cb, RTGCPHYS GCPhysRxBuf, uint8_t cbRxBuf)
    773780{
    774781    PVIRTIONET pThis = PDMDEVINS_2_DATA(pDevIns, PVIRTIONET);
    775     pRxPktHdr->uNumBuffers = cDescs;
     782    pRxPktHdr->uNumBuffers = cVirtqBufs;
    776783    if (pRxPktHdr)
    777784    {
     
    916923        pHlp->pfnPrintf(pHlp, "    fMsiSupport ............... %d\n",   pThis->Virtio.fMsiSupport);
    917924        pHlp->pfnPrintf(pHlp, "    uConfigGeneration ......... %d\n",   pThis->Virtio.uConfigGeneration);
    918         pHlp->pfnPrintf(pHlp, "    uDeviceStatus ............. 0x%x\n", pThis->Virtio.uDeviceStatus);
     925        pHlp->pfnPrintf(pHlp, "    uDeviceStatus ............. 0x%x\n", pThis->Virtio.fDeviceStatus);
    919926        pHlp->pfnPrintf(pHlp, "    cVirtqPairs .,............. %d\n",   pThis->cVirtqPairs);
    920927        pHlp->pfnPrintf(pHlp, "    cVirtVirtqs .,............. %d\n",   pThis->cVirtVirtqs);
     
    10111018}
    10121019
    1013 /**
    1014  * Resolves to boolean true if uOffset matches a field offset and size exactly,
    1015  * (or if 64-bit field, if it accesses either 32-bit part as a 32-bit access)
    1016  * Assumption is this critereon is mandated by VirtIO 1.0, Section 4.1.3.1)
    1017  * (Easily re-written to allow unaligned bounded access to a field).
    1018  *
    1019  * @param   member   - Member of VIRTIO_PCI_COMMON_CFG_T
    1020  * @result           - true or false
    1021  */
    1022 #define MATCH_NET_CONFIG(member) \
    1023         (   (   RT_SIZEOFMEMB(VIRTIONET_CONFIG_T, member) == 8 \
    1024              && (   offConfig == RT_UOFFSETOF(VIRTIONET_CONFIG_T, member) \
    1025                  || offConfig == RT_UOFFSETOF(VIRTIONET_CONFIG_T, member) + sizeof(uint32_t)) \
    1026              && cb == sizeof(uint32_t)) \
    1027          || (offConfig + cb <= RT_UOFFSETOF(VIRTIONET_CONFIG_T, member) \
    1028                              + RT_SIZEOFMEMB(VIRTIONET_CONFIG_T, member)) )
    1029 
    1030 #ifdef LOG_ENABLED
    1031 # define LOG_NET_CONFIG_ACCESSOR(member) \
    1032         virtioCoreLogMappedIoValue(__FUNCTION__, #member, RT_SIZEOFMEMB(VIRTIONET_CONFIG_T, member), \
    1033                                pv, cb, offIntra, fWrite, false, 0);
    1034 #else
    1035 # define LOG_NET_CONFIG_ACCESSOR(member) do { } while (0)
    1036 #endif
    1037 
    1038 #define NET_CONFIG_ACCESSOR(member) \
    1039     do \
    1040     { \
    1041         uint32_t offIntra = offConfig - RT_UOFFSETOF(VIRTIONET_CONFIG_T, member); \
    1042         if (fWrite) \
    1043             memcpy((char *)&pThis->virtioNetConfig.member + offIntra, pv, cb); \
    1044         else \
    1045             memcpy(pv, (const char *)&pThis->virtioNetConfig.member + offIntra, cb); \
    1046         LOG_NET_CONFIG_ACCESSOR(member); \
    1047     } while(0)
    1048 
    1049 #define NET_CONFIG_ACCESSOR_READONLY(member) \
    1050     do \
    1051     { \
    1052         uint32_t offIntra = offConfig - RT_UOFFSETOF(VIRTIONET_CONFIG_T, member); \
    1053         if (fWrite) \
    1054             LogFunc(("%s Guest attempted to write readonly virtio_pci_common_cfg.%s\n", pThis->szInst, #member)); \
    1055         else \
    1056         { \
    1057             memcpy(pv, (const char *)&pThis->virtioNetConfig.member + offIntra, cb); \
    1058             LOG_NET_CONFIG_ACCESSOR(member); \
    1059         } \
    1060     } while(0)
    1061 
    1062 
    1063 static int virtioNetR3CfgAccessed(PVIRTIONET pThis, uint32_t offConfig, void *pv, uint32_t cb, bool fWrite)
     1020static int virtioNetR3CfgAccessed(PVIRTIONET pThis, uint32_t uOffsetOfAccess, void *pv, uint32_t cb, bool fWrite)
    10641021{
    10651022    AssertReturn(pv && cb <= sizeof(uint32_t), fWrite ? VINF_SUCCESS : VINF_IOM_MMIO_UNUSED_00);
    10661023
    1067     if (MATCH_NET_CONFIG(uMacAddress))
    1068         NET_CONFIG_ACCESSOR_READONLY(uMacAddress);
     1024    if (VIRTIO_DEV_CONFIG_SUBMATCH_MEMBER( uMacAddress,      VIRTIONET_CONFIG_T, uOffsetOfAccess))
     1025        VIRTIO_DEV_CONFIG_ACCESS_READONLY( uMacAddress,      VIRTIONET_CONFIG_T, uOffsetOfAccess, &pThis->virtioNetConfig);
    10691026#if FEATURE_OFFERED(STATUS)
    10701027    else
    1071     if (MATCH_NET_CONFIG(uStatus))
    1072         NET_CONFIG_ACCESSOR_READONLY(uStatus);
     1028    if (VIRTIO_DEV_CONFIG_MATCH_MEMBER(    uStatus,          VIRTIONET_CONFIG_T, uOffsetOfAccess))
     1029        VIRTIO_DEV_CONFIG_ACCESS_READONLY( uStatus,          VIRTIONET_CONFIG_T, uOffsetOfAccess, &pThis->virtioNetConfig);
    10731030#endif
    10741031#if FEATURE_OFFERED(MQ)
    10751032    else
    1076     if (MATCH_NET_CONFIG(uMaxVirtqPairs))
    1077         NET_CONFIG_ACCESSOR_READONLY(uMaxVirtqPairs);
     1033    if (VIRTIO_DEV_CONFIG_MATCH_MEMBER(    uMaxVirtqPairs,   VIRTIONET_CONFIG_T, uOffsetOfAccess))
     1034        VIRTIO_DEV_CONFIG_ACCESS_READONLY( uMaxVirtqPairs,   VIRTIONET_CONFIG_T, uOffsetOfAccess, &pThis->virtioNetConfig);
    10781035#endif
    10791036    else
    10801037    {
    1081         LogFunc(("%s Bad access by guest to virtio_net_config: off=%u (%#x), cb=%u\n", pThis->szInst, offConfig, offConfig, cb));
     1038        LogFunc(("%s Bad access by guest to virtio_net_config: off=%u (%#x), cb=%u\n",
     1039                pThis->szInst, uOffsetOfAccess, uOffsetOfAccess, cb));
    10821040        return fWrite ? VINF_SUCCESS : VINF_IOM_MMIO_UNUSED_00;
    10831041    }
     
    10851043}
    10861044
    1087 #undef NET_CONFIG_ACCESSOR_READONLY
    1088 #undef NET_CONFIG_ACCESSOR
    1089 #undef LOG_ACCESSOR
    1090 #undef MATCH_NET_CONFIG
    1091 
    10921045/**
    10931046 * @callback_method_impl{VIRTIOCORER3,pfnDevCapRead}
     
    10971050    PVIRTIONET pThis = PDMDEVINS_2_DATA(pDevIns, PVIRTIONET);
    10981051
    1099     LogFunc(("%s uOffset: %d, cb: %d\n",  pThis->szInst, uOffset, cb));
     1052    LogFunc((" %s uOffset: %d, cb: %d\n",  pThis->szInst, uOffset, cb));
    11001053    RT_NOREF(pThis);
    11011054    return virtioNetR3CfgAccessed(PDMDEVINS_2_DATA(pDevIns, PVIRTIONET), uOffset, pv, cb, false /*fRead*/);
     
    15451498        if (rc == VERR_TIMEOUT || rc == VERR_INTERRUPTED)
    15461499        {
    1547             LogFunc(("Waken due to %s\n", rc == VERR_TIMEOUT ? "timeout" : "interrupted"));
     1500            LogFunc(("Waken due to %s\n", rc == VERR_TIMEOUT ? "timeout" : "getting interrupted"));
    15481501            continue;
    15491502        }
     
    16621615            pszType = (char *)"Unicast";
    16631616
    1664         LogFunc(("%s node(%RTmac %s%s), pkt(%RTmac %s)",
     1617        LogFunc(("%s node(%RTmac %s%s), pkt(%RTmac %s)\n",
    16651618                 pThis->szInst, pThis->virtioNetConfig.uMacAddress.au8,
    16661619                 pThis->fPromiscuous ? "promiscuous" : "",
     
    17351688                                       PVIRTIONETVIRTQ pRxVirtq)
    17361689{
    1737     uint8_t fAddPktHdr = true;
    17381690    RTGCPHYS GCPhysPktHdrNumBuffers = 0;
    1739     uint16_t cDescs;
    1740     uint64_t uOffset;
    1741     for (cDescs = uOffset = 0; uOffset < cb; )
     1691    uint8_t  fAddPktHdr = true;
     1692    uint16_t cVirtqBufs  = 0;
     1693    uint64_t uOffset = 0;
     1694
     1695    while (uOffset < cb)
    17421696    {
    17431697        PVIRTQBUF pVirtqBuf = NULL;
     
    17611715                            VERR_INTERNAL_ERROR);
    17621716
    1763         size_t cbDescChainLeft = pVirtqBuf->cbPhysReturn;
     1717        size_t cbBufRemaining = pVirtqBuf->cbPhysReturn;
    17641718        uint8_t  cbHdr = sizeof(VIRTIONETPKTHDR);
    17651719
    17661720        /* Fill the Guest Rx buffer with data received from the interface */
    1767         for (uint16_t cSegs = 0; uOffset < cb && cbDescChainLeft; )
     1721        for (uint16_t cSegs = 0; uOffset < cb && cbBufRemaining; )
    17681722        {
    17691723            if (fAddPktHdr)
     
    17731727                paVirtSegsToGuest[0].pvSeg = RTMemAlloc(cbHdr);
    17741728                AssertReturn(paVirtSegsToGuest[0].pvSeg, VERR_NO_MEMORY);
    1775                 cbDescChainLeft -= cbHdr;
     1729                cbBufRemaining -= cbHdr;
    17761730
    17771731                memcpy(paVirtSegsToGuest[0].pvSeg, rxPktHdr, cbHdr);
     
    17941748
    17951749            /* Append remaining Rx pkt or as much current desc chain has room for */
    1796             size_t cbCropped = RT_MIN(cb, cbDescChainLeft);
    1797             paVirtSegsToGuest[cSegs].cbSeg = cbCropped;
     1750            size_t cbLimited = RT_MIN(cb, cbBufRemaining);
     1751            paVirtSegsToGuest[cSegs].cbSeg = cbLimited;
    17981752            paVirtSegsToGuest[cSegs].pvSeg = ((uint8_t *)pvBuf) + uOffset;
    1799             cbDescChainLeft -= cbCropped;
    1800             uOffset += cbCropped;
    1801             cDescs++;
     1753            cbBufRemaining -= cbLimited;
     1754            uOffset        += cbLimited;
     1755            cVirtqBufs++;
    18021756            cSegs++;
    18031757            RTSgBufInit(pVirtSegBufToGuest, paVirtSegsToGuest, cSegs);
     
    18051759            STAM_PROFILE_START(&pThis->StatReceiveStore, a);
    18061760            virtioCoreR3VirtqUsedBufPut(pDevIns, &pThis->Virtio, pRxVirtq->idx,
    1807                                     pVirtSegBufToGuest, pVirtqBuf, true /* fFence */);
     1761                                        pVirtSegBufToGuest, pVirtqBuf, true /* fFence */);
    18081762            STAM_PROFILE_STOP(&pThis->StatReceiveStore, a);
    18091763
     
    18111765                break;
    18121766        }
    1813 
    18141767        virtioCoreR3VirtqBufRelease(&pThis->Virtio, pVirtqBuf);
    18151768    }
     
    18231776    /* Fix-up pkthdr (in guest phys. memory) with number buffers (descriptors) processed */
    18241777
    1825     int rc = PDMDevHlpPCIPhysWrite(pDevIns, GCPhysPktHdrNumBuffers, &cDescs, sizeof(cDescs));
    1826     AssertMsgRCReturn(rc,
    1827                   ("Failure updating descriptor count in pkt hdr in guest physical memory\n"),
    1828                   rc);
     1778    int rc = PDMDevHlpPCIPhysWrite(pDevIns, GCPhysPktHdrNumBuffers, &cVirtqBufs, sizeof(cVirtqBufs));
     1779    AssertMsgRCReturn(rc, ("Failure updating descriptor count in pkt hdr in guest physical memory\n"), rc);
    18291780
    18301781    virtioCoreVirtqSyncUsedRing(pDevIns, &pThis->Virtio, pRxVirtq->idx);
     
    18921843    }
    18931844
    1894     uint16_t cSegsAllocated = VIRTIONET_PREALLOCATE_RX_SEG_COUNT;
     1845    uint16_t cSegsAllocated = VIRTIONET_RX_SEG_COUNT;
    18951846
    18961847    PRTSGBUF pVirtSegBufToGuest = (PRTSGBUF)RTMemAllocZ(sizeof(RTSGBUF));
     
    19981949}
    19991950
    2000 /* Read physical bytes from the out segment(s) of descriptor chain */
    2001 static void virtqNetR3PullBytesFromVirtqBuf(PPDMDEVINS pDevIns, PVIRTIONET pThis, PVIRTQBUF pVirtqBuf,
    2002                                               void *pv, size_t cb)
    2003 {
    2004     uint8_t *pb = (uint8_t *)pv;
    2005     size_t cbLim = RT_MIN(pVirtqBuf->cbPhysSend, cb);
    2006     while (cbLim)
    2007     {
    2008         size_t cbSeg = cbLim;
    2009         RTGCPHYS GCPhys = virtioCoreGCPhysChainGetNextSegment(pVirtqBuf->pSgPhysSend, &cbSeg);
    2010         PDMDevHlpPCIPhysRead(pDevIns, GCPhys, pb, cbSeg);
    2011         pb += cbSeg;
    2012         cbLim -= cbSeg;
    2013         pVirtqBuf->cbPhysSend -= cbSeg;
    2014     }
    2015     LogFunc(("%s Pulled %d/%d bytes from desc chain (%d bytes left)\n",
    2016              pThis->szInst, cb - cbLim, cb, pVirtqBuf->cbPhysSend));
    2017     RT_NOREF(pThis);
    2018 }
    2019 
    2020 static uint8_t virtioNetR3CtrlRx(PPDMDEVINS pDevIns, PVIRTIONET pThis, PVIRTIONETCC pThisCC,
     1951
     1952static uint8_t virtioNetR3CtrlRx(PVIRTIONET pThis, PVIRTIONETCC pThisCC,
    20211953                                 PVIRTIONET_CTRL_HDR_T pCtrlPktHdr, PVIRTQBUF pVirtqBuf)
    20221954{
     
    20251957
    20261958    LogFunc(("%s Processing CTRL Rx command\n", pThis->szInst));
    2027     RT_NOREF(pThis);
    20281959    switch(pCtrlPktHdr->uCmd)
    20291960    {
     
    20461977
    20471978    uint8_t fOn, fPromiscChanged = false;
    2048     virtqNetR3PullBytesFromVirtqBuf(pDevIns, pThis, pVirtqBuf, &fOn, (size_t)RT_MIN(pVirtqBuf->cbPhysSend, sizeof(fOn)));
     1979    virtioCoreR3VirtqBufDrain(&pThis->Virtio, pVirtqBuf, &fOn, (size_t)RT_MIN(pVirtqBuf->cbPhysSend, sizeof(fOn)));
    20491980
    20501981    switch(pCtrlPktHdr->uCmd)
     
    20792010
    20802011    if (pThisCC->pDrv && fPromiscChanged)
    2081     {
    2082         if (pThis->fPromiscuous | pThis->fAllMulticast)
    2083         {
    2084             pThisCC->pDrv->pfnSetPromiscuousMode(pThisCC->pDrv, true);
    2085         }
    2086         else
    2087         {
    2088             pThisCC->pDrv->pfnSetPromiscuousMode(pThisCC->pDrv, false);
    2089         }
    2090     }
     2012        pThisCC->pDrv->pfnSetPromiscuousMode(pThisCC->pDrv, (pThis->fPromiscuous || pThis->fAllMulticast));
    20912013
    20922014    return VIRTIONET_OK;
    20932015}
    20942016
    2095 static uint8_t virtioNetR3CtrlMac(PPDMDEVINS pDevIns, PVIRTIONET pThis, PVIRTIONETCC pThisCC,
    2096                                   PVIRTIONET_CTRL_HDR_T pCtrlPktHdr, PVIRTQBUF pVirtqBuf)
     2017static uint8_t virtioNetR3CtrlMac(PVIRTIONET pThis, PVIRTIONET_CTRL_HDR_T pCtrlPktHdr, PVIRTQBUF pVirtqBuf)
    20972018{
    20982019    LogFunc(("%s Processing CTRL MAC command\n", pThis->szInst));
    2099 
    2100     RT_NOREF(pThisCC);
    2101 
    2102 #define ASSERT_CTRL_ADDR_SET(v) \
    2103     AssertMsgReturn((v), ("DESC chain too small to process CTRL_MAC_ADDR_SET cmd\n"), VIRTIONET_ERROR)
    2104 
    2105 #define ASSERT_CTRL_TABLE_SET(v) \
    2106     AssertMsgReturn((v), ("DESC chain too small to process CTRL_MAC_TABLE_SET cmd\n"), VIRTIONET_ERROR)
    21072020
    21082021    AssertMsgReturn(pVirtqBuf->cbPhysSend >= sizeof(*pCtrlPktHdr),
     
    21162029        {
    21172030            /* Set default Rx filter MAC */
    2118             ASSERT_CTRL_ADDR_SET(cbRemaining >= sizeof(VIRTIONET_CTRL_MAC_TABLE_LEN));
    2119             virtqNetR3PullBytesFromVirtqBuf(pDevIns, pThis, pVirtqBuf, &pThis->rxFilterMacDefault, sizeof(VIRTIONET_CTRL_MAC_TABLE_LEN));
     2031            AssertMsgReturn(cbRemaining >= sizeof(pThis->rxFilterMacDefault),
     2032                            ("DESC chain too small to process CTRL_MAC_ADDR_SET cmd\n"), VIRTIONET_ERROR);
     2033
     2034            virtioCoreR3VirtqBufDrain(&pThis->Virtio, pVirtqBuf, &pThis->rxFilterMacDefault, sizeof(VIRTIONET_CTRL_MAC_TABLE_LEN));
    21202035            break;
    21212036        }
     
    21252040
    21262041            /* Load unicast MAC filter table */
    2127             ASSERT_CTRL_TABLE_SET(cbRemaining >= sizeof(cMacs));
    2128             virtqNetR3PullBytesFromVirtqBuf(pDevIns, pThis, pVirtqBuf, &cMacs, sizeof(cMacs));
     2042
     2043            AssertMsgReturn(cbRemaining >= sizeof(cMacs),
     2044                           ("DESC chain too small to process CTRL_MAC_TABLE_SET cmd\n"), VIRTIONET_ERROR);
     2045
     2046            /* Fetch count of unicast filter MACs from guest buffer */
     2047            virtioCoreR3VirtqBufDrain(&pThis->Virtio, pVirtqBuf, &cMacs, sizeof(cMacs));
     2048
    21292049            cbRemaining -= sizeof(cMacs);
     2050
    21302051            Log7Func(("%s Guest provided %d unicast MAC Table entries\n", pThis->szInst, cMacs));
     2052
    21312053            if (cMacs)
    21322054            {
    21332055                uint32_t cbMacs = cMacs * sizeof(RTMAC);
    2134                 ASSERT_CTRL_TABLE_SET(cbRemaining >= cbMacs);
    2135                 virtqNetR3PullBytesFromVirtqBuf(pDevIns, pThis, pVirtqBuf, &pThis->aMacUnicastFilter, cbMacs);
     2056
     2057                AssertMsgReturn(cbRemaining >= cbMacs,
     2058                                ("Virtq buffer too small to process CTRL_MAC_TABLE_SET cmd\n"), VIRTIONET_ERROR);
     2059
     2060                /* Fetch unicast table contents from guest buffer */
     2061                virtioCoreR3VirtqBufDrain(&pThis->Virtio, pVirtqBuf, &pThis->aMacUnicastFilter, cbMacs);
     2062
    21362063                cbRemaining -= cbMacs;
    21372064            }
     
    21392066
    21402067            /* Load multicast MAC filter table */
    2141             ASSERT_CTRL_TABLE_SET(cbRemaining >= sizeof(cMacs));
    2142             virtqNetR3PullBytesFromVirtqBuf(pDevIns, pThis, pVirtqBuf, &cMacs, sizeof(cMacs));
     2068            AssertMsgReturn(cbRemaining >= sizeof(cMacs),
     2069                            ("Virtq buffer too small to process CTRL_MAC_TABLE_SET cmd\n"), VIRTIONET_ERROR);
     2070
     2071            /* Fetch count of multicast filter MACs from guest buffer */
     2072            virtioCoreR3VirtqBufDrain(&pThis->Virtio, pVirtqBuf, &cMacs, sizeof(cMacs));
     2073
    21432074            cbRemaining -= sizeof(cMacs);
     2075
    21442076            Log10Func(("%s Guest provided %d multicast MAC Table entries\n", pThis->szInst, cMacs));
     2077
     2078
    21452079            if (cMacs)
    21462080            {
    21472081                uint32_t cbMacs = cMacs * sizeof(RTMAC);
    2148                 ASSERT_CTRL_TABLE_SET(cbRemaining >= cbMacs);
    2149                 virtqNetR3PullBytesFromVirtqBuf(pDevIns, pThis, pVirtqBuf, &pThis->aMacMulticastFilter, cbMacs);
     2082
     2083                AssertMsgReturn(cbRemaining >= cbMacs,
     2084                                ("Virtq buffer too small to process CTRL_MAC_TABLE_SET cmd\n"), VIRTIONET_ERROR);
     2085
     2086                /* Fetch multicast table contents from guest buffer */
     2087                virtioCoreR3VirtqBufDrain(&pThis->Virtio, pVirtqBuf, &pThis->aMacMulticastFilter, cbMacs);
     2088
    21502089                cbRemaining -= cbMacs;
    21512090            }
     
    21662105}
    21672106
    2168 static uint8_t virtioNetR3CtrlVlan(PPDMDEVINS pDevIns, PVIRTIONET pThis, PVIRTIONETCC pThisCC,
    2169                                    PVIRTIONET_CTRL_HDR_T pCtrlPktHdr, PVIRTQBUF pVirtqBuf)
     2107static uint8_t virtioNetR3CtrlVlan(PVIRTIONET pThis, PVIRTIONET_CTRL_HDR_T pCtrlPktHdr, PVIRTQBUF pVirtqBuf)
    21702108{
    21712109    LogFunc(("%s Processing CTRL VLAN command\n", pThis->szInst));
    2172 
    2173     RT_NOREF(pThisCC);
    21742110
    21752111    uint16_t uVlanId;
    21762112    size_t cbRemaining = pVirtqBuf->cbPhysSend - sizeof(*pCtrlPktHdr);
     2113
    21772114    AssertMsgReturn(cbRemaining > sizeof(uVlanId),
    21782115        ("DESC chain too small for VIRTIO_NET_CTRL_VLAN cmd processing"), VIRTIONET_ERROR);
    2179     virtqNetR3PullBytesFromVirtqBuf(pDevIns, pThis, pVirtqBuf, &uVlanId, sizeof(uVlanId));
     2116
     2117    /* Fetch VLAN ID from guest buffer */
     2118    virtioCoreR3VirtqBufDrain(&pThis->Virtio, pVirtqBuf, &uVlanId, sizeof(uVlanId));
     2119
    21802120    AssertMsgReturn(uVlanId > VIRTIONET_MAX_VLAN_ID,
    21812121        ("%s VLAN ID out of range (VLAN ID=%u)\n", pThis->szInst, uVlanId), VIRTIONET_ERROR);
     2122
    21822123    LogFunc(("%s uCommand=%u VLAN ID=%u\n", pThis->szInst, pCtrlPktHdr->uCmd, uVlanId));
     2124
    21832125    switch (pCtrlPktHdr->uCmd)
    21842126    {
     
    22212163                        ("DESC chain too small for CTRL pkt header"));
    22222164
    2223     virtqNetR3PullBytesFromVirtqBuf(pDevIns, pThis, pVirtqBuf, pCtrlPktHdr,
     2165    virtioCoreR3VirtqBufDrain(&pThis->Virtio, pVirtqBuf, pCtrlPktHdr,
    22242166                         RT_MIN(pVirtqBuf->cbPhysSend, sizeof(VIRTIONET_CTRL_HDR_T)));
    22252167
     
    22302172    {
    22312173        case VIRTIONET_CTRL_RX:
    2232             uAck = virtioNetR3CtrlRx(pDevIns, pThis, pThisCC, pCtrlPktHdr, pVirtqBuf);
     2174            uAck = virtioNetR3CtrlRx(pThis, pThisCC, pCtrlPktHdr, pVirtqBuf);
    22332175            break;
    22342176        case VIRTIONET_CTRL_MAC:
    2235             uAck = virtioNetR3CtrlMac(pDevIns, pThis, pThisCC, pCtrlPktHdr, pVirtqBuf);
     2177            uAck = virtioNetR3CtrlMac(pThis, pCtrlPktHdr, pVirtqBuf);
    22362178            break;
    22372179        case VIRTIONET_CTRL_VLAN:
    2238             uAck = virtioNetR3CtrlVlan(pDevIns, pThis, pThisCC, pCtrlPktHdr, pVirtqBuf);
     2180            uAck = virtioNetR3CtrlVlan(pThis, pCtrlPktHdr, pVirtqBuf);
    22392181            break;
    22402182        case VIRTIONET_CTRL_ANNOUNCE:
     
    29172859            PVIRTIONETVIRTQ pVirtq = &pThis->aVirtqs[uVirtqNbr];
    29182860            pVirtq->idx = uVirtqNbr;
    2919             (void) virtioCoreR3VirtqAttach(&pThis->Virtio, pVirtq->idx, pVirtq->szName);
     2861            (void) virtioCoreVirtqAttach(&pThis->Virtio, pVirtq->idx, pVirtq->szName);
    29202862            pVirtq->fAttachedToVirtioCore = true;
    29212863            if (IS_VIRTQ_EMPTY(pThisCC->pDevIns, &pThis->Virtio, pVirtq->idx))
  • trunk/src/VBox/Devices/Storage/DevVirtioSCSI.cpp

    r84876 r85016  
    164164{
    165165    // Device-writable part
    166     uint32_t uEvent;                                            /**< event                                          */
     166    uint32_t uEvent;                                            /**< event                                           */
    167167    uint8_t  abVirtioLun[8];                                    /**< lun                                             */
    168168    uint32_t uReason;                                           /**< reason                                          */
     
    216216    uint8_t  uCdb[1];                                           /**< cdb                                          */
    217217
    218     REQ_CMD_PI_T piHdr;                                         /**< T10 Pi block integrity (optional feature)     */
     218    REQ_CMD_PI_T piHdr;                                         /**< T10 Pi block integrity (optional feature)    */
    219219    uint8_t  uPiOut[1];                                         /**< pi_out[]          T10 pi block integrity     */
    220220    uint8_t  uDataOut[1];                                       /**< dataout                                      */
     
    11821182    {
    11831183        size_t cbSeg = cbReqHdr - offReq;
    1184         RTGCPHYS GCPhys = virtioCoreGCPhysChainGetNextSegment(pVirtqBuf->pSgPhysSend, &cbSeg);
     1184        RTGCPHYS GCPhys = virtioCoreGCPhysChainGetNextSeg(pVirtqBuf->pSgPhysSend, &cbSeg);
    11851185        PDMDevHlpPCIPhysReadMeta(pDevIns, GCPhys, &VirtqReq.ab[offReq], cbSeg);
    11861186        offReq += cbSeg;
     
    13451345        virtioScsiR3FreeReq(pTarget, pReq);
    13461346    }
    1347 
    13481347    return VINF_SUCCESS;
    13491348}
     
    13711370    RT_ZERO(ScsiCtrlUnion);
    13721371
    1373     size_t const cbCtrl = RT_MIN(pVirtqBuf->cbPhysSend, sizeof(VIRTIO_SCSI_CTRL_UNION_T));
    1374     for (size_t offCtrl = 0; offCtrl < cbCtrl; )
    1375     {
    1376         size_t cbSeg = cbCtrl - offCtrl;
    1377         RTGCPHYS GCPhys = virtioCoreGCPhysChainGetNextSegment(pVirtqBuf->pSgPhysSend, &cbSeg);
    1378         PDMDevHlpPCIPhysReadMeta(pDevIns, GCPhys, &ScsiCtrlUnion.ab[offCtrl], cbSeg);
    1379         offCtrl += cbSeg;
     1372    size_t const cb = RT_MIN(pVirtqBuf->cbPhysSend, sizeof(VIRTIO_SCSI_CTRL_UNION_T));
     1373    for (size_t uOffset = 0; uOffset < cb; )
     1374    {
     1375        size_t cbSeg = cb - uOffset;
     1376        RTGCPHYS GCPhys = virtioCoreGCPhysChainGetNextSeg(pVirtqBuf->pSgPhysSend, &cbSeg);
     1377        PDMDevHlpPCIPhysReadMeta(pDevIns, GCPhys, &ScsiCtrlUnion.ab[uOffset], cbSeg);
     1378        uOffset += cbSeg;
    13801379    }
    13811380
     
    15911590                  PVIRTQBUF pVirtqBuf;
    15921591                  int rc = virtioCoreR3VirtqAvailBufGet(pDevIns, &pThis->Virtio, uVirtqNbr,
    1593                                                     pWorkerR3->auRedoDescs[i], &pVirtqBuf);
     1592                                                        pWorkerR3->auRedoDescs[i], &pVirtqBuf);
    15941593                  if (RT_FAILURE(rc))
    15951594                      LogRel(("Error fetching desc chain to redo, %Rrc", rc));
     
    17801779
    17811780/**
    1782  * Resolves to boolean true if uOffset matches a field offset and size exactly,
    1783  * (or if 64-bit field, if it accesses either 32-bit part as a 32-bit access)
    1784  * Assumption is this critereon is mandated by VirtIO 1.0, Section 4.1.3.1)
    1785  * (Easily re-written to allow unaligned bounded access to a field).
    1786  *
    1787  * @param   member   - Member of VIRTIO_PCI_COMMON_CFG_T
    1788  * @result           - true or false
    1789  */
    1790 #define MATCH_SCSI_CONFIG(member) \
    1791         (   (   RT_SIZEOFMEMB(VIRTIOSCSI_CONFIG_T, member) == 8 \
    1792              && (   offConfig == RT_UOFFSETOF(VIRTIOSCSI_CONFIG_T, member) \
    1793                  || offConfig == RT_UOFFSETOF(VIRTIOSCSI_CONFIG_T, member) + sizeof(uint32_t)) \
    1794              && cb == sizeof(uint32_t)) \
    1795          || (   offConfig == RT_UOFFSETOF(VIRTIOSCSI_CONFIG_T, member) \
    1796              && cb == RT_SIZEOFMEMB(VIRTIOSCSI_CONFIG_T, member)) )
    1797 
    1798 #ifdef LOG_ENABLED
    1799 # define LOG_SCSI_CONFIG_ACCESSOR(member) \
    1800         virtioCoreLogMappedIoValue(__FUNCTION__, #member, RT_SIZEOFMEMB(VIRTIOSCSI_CONFIG_T, member), \
    1801                                pv, cb, offIntra, fWrite, false, 0);
    1802 #else
    1803 # define LOG_SCSI_CONFIG_ACCESSOR(member) do { } while (0)
    1804 #endif
    1805 
    1806 #define SCSI_CONFIG_ACCESSOR(member) \
    1807     do \
    1808     { \
    1809         uint32_t offIntra = offConfig - RT_UOFFSETOF(VIRTIOSCSI_CONFIG_T, member); \
    1810         if (fWrite) \
    1811             memcpy((char *)&pThis->virtioScsiConfig.member + offIntra, pv, cb); \
    1812         else \
    1813             memcpy(pv, (const char *)&pThis->virtioScsiConfig.member + offIntra, cb); \
    1814         LOG_SCSI_CONFIG_ACCESSOR(member); \
    1815     } while(0)
    1816 
    1817 #define SCSI_CONFIG_ACCESSOR_READONLY(member) \
    1818     do \
    1819     { \
    1820         uint32_t offIntra = offConfig - RT_UOFFSETOF(VIRTIOSCSI_CONFIG_T, member); \
    1821         if (fWrite) \
    1822             LogFunc(("Guest attempted to write readonly virtio_pci_common_cfg.%s\n", #member)); \
    1823         else \
    1824         { \
    1825             memcpy(pv, (const char *)&pThis->virtioScsiConfig.member + offIntra, cb); \
    1826             LOG_SCSI_CONFIG_ACCESSOR(member); \
    1827         } \
    1828     } while(0)
    1829 
    1830 /**
    18311781 * Worker for virtioScsiR3DevCapWrite and virtioScsiR3DevCapRead.
    18321782 */
    1833 static int virtioScsiR3CfgAccessed(PVIRTIOSCSI pThis, uint32_t offConfig, void *pv, uint32_t cb, bool fWrite)
     1783static int virtioScsiR3CfgAccessed(PVIRTIOSCSI pThis, uint32_t uOffsetOfAccess, void *pv, uint32_t cb, bool fWrite)
    18341784{
    18351785    AssertReturn(pv && cb <= sizeof(uint32_t), fWrite ? VINF_SUCCESS : VINF_IOM_MMIO_UNUSED_00);
    18361786
    1837     if (MATCH_SCSI_CONFIG(uNumVirtqs))
    1838         SCSI_CONFIG_ACCESSOR_READONLY(uNumVirtqs);
     1787    if (VIRTIO_DEV_CONFIG_MATCH_MEMBER(    uNumVirtqs,     VIRTIOSCSI_CONFIG_T, uOffsetOfAccess))
     1788        VIRTIO_DEV_CONFIG_ACCESS_READONLY( uNumVirtqs,     VIRTIOSCSI_CONFIG_T, uOffsetOfAccess, &pThis->virtioScsiConfig);
    18391789    else
    1840     if (MATCH_SCSI_CONFIG(uSegMax))
    1841         SCSI_CONFIG_ACCESSOR_READONLY(uSegMax);
     1790    if (VIRTIO_DEV_CONFIG_MATCH_MEMBER(    uSegMax,        VIRTIOSCSI_CONFIG_T, uOffsetOfAccess))
     1791        VIRTIO_DEV_CONFIG_ACCESS_READONLY( uSegMax,        VIRTIOSCSI_CONFIG_T, uOffsetOfAccess, &pThis->virtioScsiConfig);
    18421792    else
    1843     if (MATCH_SCSI_CONFIG(uMaxSectors))
    1844         SCSI_CONFIG_ACCESSOR_READONLY(uMaxSectors);
     1793    if (VIRTIO_DEV_CONFIG_MATCH_MEMBER(    uMaxSectors,    VIRTIOSCSI_CONFIG_T, uOffsetOfAccess))
     1794        VIRTIO_DEV_CONFIG_ACCESS_READONLY( uMaxSectors,    VIRTIOSCSI_CONFIG_T, uOffsetOfAccess, &pThis->virtioScsiConfig);
    18451795    else
    1846     if (MATCH_SCSI_CONFIG(uCmdPerLun))
    1847         SCSI_CONFIG_ACCESSOR_READONLY(uCmdPerLun);
     1796    if (VIRTIO_DEV_CONFIG_MATCH_MEMBER(    uCmdPerLun,     VIRTIOSCSI_CONFIG_T, uOffsetOfAccess))
     1797        VIRTIO_DEV_CONFIG_ACCESS_READONLY( uCmdPerLun,     VIRTIOSCSI_CONFIG_T, uOffsetOfAccess, &pThis->virtioScsiConfig);
    18481798    else
    1849     if (MATCH_SCSI_CONFIG(uEventInfoSize))
    1850         SCSI_CONFIG_ACCESSOR_READONLY(uEventInfoSize);
     1799    if (VIRTIO_DEV_CONFIG_MATCH_MEMBER(    uEventInfoSize, VIRTIOSCSI_CONFIG_T, uOffsetOfAccess))
     1800        VIRTIO_DEV_CONFIG_ACCESS_READONLY( uEventInfoSize, VIRTIOSCSI_CONFIG_T, uOffsetOfAccess, &pThis->virtioScsiConfig);
    18511801    else
    1852     if (MATCH_SCSI_CONFIG(uSenseSize))
    1853         SCSI_CONFIG_ACCESSOR(uSenseSize);
     1802    if (VIRTIO_DEV_CONFIG_MATCH_MEMBER(    uSenseSize,     VIRTIOSCSI_CONFIG_T, uOffsetOfAccess))
     1803        VIRTIO_DEV_CONFIG_ACCESS(          uSenseSize,     VIRTIOSCSI_CONFIG_T, uOffsetOfAccess, &pThis->virtioScsiConfig);
    18541804    else
    1855     if (MATCH_SCSI_CONFIG(uCdbSize))
    1856         SCSI_CONFIG_ACCESSOR(uCdbSize);
     1805    if (VIRTIO_DEV_CONFIG_MATCH_MEMBER(    uCdbSize,       VIRTIOSCSI_CONFIG_T, uOffsetOfAccess))
     1806        VIRTIO_DEV_CONFIG_ACCESS(          uCdbSize,       VIRTIOSCSI_CONFIG_T, uOffsetOfAccess, &pThis->virtioScsiConfig);
    18571807    else
    1858     if (MATCH_SCSI_CONFIG(uMaxChannel))
    1859         SCSI_CONFIG_ACCESSOR_READONLY(uMaxChannel);
     1808    if (VIRTIO_DEV_CONFIG_MATCH_MEMBER(    uMaxChannel,    VIRTIOSCSI_CONFIG_T, uOffsetOfAccess))
     1809        VIRTIO_DEV_CONFIG_ACCESS_READONLY( uMaxChannel,    VIRTIOSCSI_CONFIG_T, uOffsetOfAccess, &pThis->virtioScsiConfig);
    18601810    else
    1861     if (MATCH_SCSI_CONFIG(uMaxTarget))
    1862         SCSI_CONFIG_ACCESSOR_READONLY(uMaxTarget);
     1811    if (VIRTIO_DEV_CONFIG_MATCH_MEMBER(    uMaxTarget,     VIRTIOSCSI_CONFIG_T, uOffsetOfAccess))
     1812        VIRTIO_DEV_CONFIG_ACCESS_READONLY( uMaxTarget,     VIRTIOSCSI_CONFIG_T, uOffsetOfAccess, &pThis->virtioScsiConfig);
    18631813    else
    1864     if (MATCH_SCSI_CONFIG(uMaxLun))
    1865         SCSI_CONFIG_ACCESSOR_READONLY(uMaxLun);
     1814    if (VIRTIO_DEV_CONFIG_MATCH_MEMBER(    uMaxLun,        VIRTIOSCSI_CONFIG_T, uOffsetOfAccess))
     1815        VIRTIO_DEV_CONFIG_ACCESS_READONLY( uMaxLun,        VIRTIOSCSI_CONFIG_T, uOffsetOfAccess, &pThis->virtioScsiConfig);
    18661816    else
    18671817    {
    1868         LogFunc(("Bad access by guest to virtio_scsi_config: off=%u (%#x), cb=%u\n", offConfig, offConfig, cb));
     1818        LogFunc(("Bad access by guest to virtio_scsi_config: off=%u (%#x), cb=%u\n", uOffsetOfAccess, uOffsetOfAccess, cb));
    18691819        return fWrite ? VINF_SUCCESS : VINF_IOM_MMIO_UNUSED_00;
    18701820    }
    18711821    return VINF_SUCCESS;
    18721822}
    1873 
    1874 #undef SCSI_CONFIG_ACCESSOR_READONLY
    1875 #undef SCSI_CONFIG_ACCESSOR
    1876 #undef LOG_ACCESSOR
    1877 #undef MATCH_SCSI_CONFIG
    18781823
    18791824/**
     
    25282473    for (uint16_t uVirtqNbr = 0; uVirtqNbr < VIRTIOSCSI_VIRTQ_CNT; uVirtqNbr++)
    25292474    {
    2530         rc = virtioCoreR3VirtqAttach(&pThis->Virtio, uVirtqNbr, VIRTQNAME(uVirtqNbr));
     2475        rc = virtioCoreVirtqAttach(&pThis->Virtio, uVirtqNbr, VIRTQNAME(uVirtqNbr));
    25312476        if (RT_FAILURE(rc))
    25322477            continue;
  • trunk/src/VBox/Devices/VirtIO/VirtioCore.cpp

    r84882 r85016  
    4444#define INSTANCE(a_pVirtio)                 ((a_pVirtio)->szInstance)
    4545#define VIRTQNAME(a_pVirtio, a_uVirtqNbr)    ((a_pVirtio)->aVirtqState[(a_uVirtqNbr)].szVirtqName)
    46 #define IS_DRIVER_OK(a_pVirtio)             ((a_pVirtio)->uDeviceStatus & VIRTIO_STATUS_DRIVER_OK)
     46#define IS_DRIVER_OK(a_pVirtio)             ((a_pVirtio)->fDeviceStatus & VIRTIO_STATUS_DRIVER_OK)
    4747#define IS_VIRTQ_EMPTY(pDevIns, pVirtio, pVirtqState) \
    4848            (virtioCoreVirtqAvailBufCount(pDevIns, pVirtio, pVirtqState) == 0)
     
    5353 * @a a_LocCapData.
    5454 *
    55  * @param[in]  a_offAccess      The offset into the MMIO bar of the access.
    56  * @param[in]  a_cbAccess       The access size.
    57  * @param[out] a_offsetInMbr    The variable to return the intra-capability
    58  *                              offset into.  ASSUMES this is uint32_t.
    59  * @param[in]  a_LocCapData     The capability location info.
    60  */
    61 #define MATCHES_VIRTIO_CAP_STRUCT(a_offAccess, a_cbAccess, a_offsetInMbr, a_LocCapData) \
    62     (   ((a_offsetInMbr) = (uint32_t)((a_offAccess) - (a_LocCapData).offMmio)) < (uint32_t)(a_LocCapData).cbMmio \
    63      && (a_offsetInMbr) + (uint32_t)(a_cbAccess) <= (uint32_t)(a_LocCapData).cbMmio )
     55 *
     56 *
     57 * @param[in]  a_offAccess      Input:  The offset into the MMIO bar of the access.
     58 * @param[in]  a_cbAccess       Input:  The access size.
     59 * @param[out] a_offsetIntoCap  Output: uint32_t variable to return the intra-capability offset into.
     60 * @param[in]  a_LocCapData     Input:  The capability location info.
     61 */
     62#define MATCHES_VIRTIO_CAP_STRUCT(a_offAccess, a_cbAccess, a_offsetIntoCap, a_LocCapData) \
     63    (   ((a_offsetIntoCap) = (uint32_t)((a_offAccess) - (a_LocCapData).offMmio)) < (uint32_t)(a_LocCapData).cbMmio \
     64     && (a_offsetIntoCap) + (uint32_t)(a_cbAccess) <= (uint32_t)(a_LocCapData).cbMmio )
    6465
    6566
     
    103104    RT_FLEXIBLE_ARRAY_EXTENSION
    104105    uint16_t  auRing[RT_FLEXIBLE_ARRAY];                         /**< ring       Ring: avail drv to dev bufs    */
    105     /* uint16_t  uUsedEventIdx;                                     - used_event (if VIRTQ_USED_F_EVENT_IDX)    */
     106    //uint16_t  uUsedEventIdx;                                   /**< used_event (if VIRTQ_USED_F_EVENT_IDX)    */
    106107} VIRTQ_AVAIL_T, *PVIRTQ_AVAIL_T;
    107108
     
    118119    RT_FLEXIBLE_ARRAY_EXTENSION
    119120    VIRTQ_USED_ELEM_T aRing[RT_FLEXIBLE_ARRAY];                  /**< ring        Ring: used dev to drv bufs    */
    120     /* uint16_t  uAvailEventIdx;                                    - avail_event if (VIRTQ_USED_F_EVENT_IDX)   */
     121    //uint16_t  uAvailEventIdx;                                  /**< avail_event if (VIRTQ_USED_F_EVENT_IDX)   */
    121122} VIRTQ_USED_T, *PVIRTQ_USED_T;
    122123
     
    149150                                uint32_t idxDesc, PVIRTQ_DESC_T pDesc)
    150151{
    151     AssertMsg(pVirtio->uDeviceStatus & VIRTIO_STATUS_DRIVER_OK, ("Called with guest driver not ready\n"));
     152    AssertMsg(pVirtio->fDeviceStatus & VIRTIO_STATUS_DRIVER_OK, ("Called with guest driver not ready\n"));
    152153    uint16_t const cVirtqItems = RT_MAX(pVirtio->uVirtqSize[uVirtqNbr], 1); /* Make sure to avoid div-by-zero. */
    153154    PDMDevHlpPCIPhysRead(pDevIns,
     
    164165{
    165166    uint16_t uDescIdx;
    166     AssertMsg(pVirtio->uDeviceStatus & VIRTIO_STATUS_DRIVER_OK, ("Called with guest driver not ready\n"));
     167    AssertMsg(pVirtio->fDeviceStatus & VIRTIO_STATUS_DRIVER_OK, ("Called with guest driver not ready\n"));
    167168    uint16_t const cVirtqItems = RT_MAX(pVirtio->uVirtqSize[uVirtqNbr], 1); /* Make sure to avoid div-by-zero. */
    168169    PDMDevHlpPCIPhysRead(pDevIns,
     
    177178    uint16_t uUsedEventIdx;
    178179    /* VirtIO 1.0 uUsedEventIdx (used_event) immediately follows ring */
    179     AssertMsg(pVirtio->uDeviceStatus & VIRTIO_STATUS_DRIVER_OK, ("Called with guest driver not ready\n"));
     180    AssertMsg(pVirtio->fDeviceStatus & VIRTIO_STATUS_DRIVER_OK, ("Called with guest driver not ready\n"));
    180181    PDMDevHlpPCIPhysRead(pDevIns,
    181182                      pVirtio->aGCPhysVirtqAvail[uVirtqNbr] + RT_UOFFSETOF_DYN(VIRTQ_AVAIL_T, auRing[pVirtio->uVirtqSize[uVirtqNbr]]),
     
    188189{
    189190    uint16_t uIdx = 0;
    190     AssertMsg(pVirtio->uDeviceStatus & VIRTIO_STATUS_DRIVER_OK, ("Called with guest driver not ready\n"));
     191    AssertMsg(pVirtio->fDeviceStatus & VIRTIO_STATUS_DRIVER_OK, ("Called with guest driver not ready\n"));
    191192    PDMDevHlpPCIPhysRead(pDevIns,
    192193                      pVirtio->aGCPhysVirtqAvail[uVirtqNbr] + RT_UOFFSETOF(VIRTQ_AVAIL_T, uIdx),
     
    198199{
    199200    uint16_t fFlags = 0;
    200     AssertMsg(pVirtio->uDeviceStatus & VIRTIO_STATUS_DRIVER_OK, ("Called with guest driver not ready\n"));
     201    AssertMsg(pVirtio->fDeviceStatus & VIRTIO_STATUS_DRIVER_OK, ("Called with guest driver not ready\n"));
    201202    PDMDevHlpPCIPhysRead(pDevIns,
    202203                      pVirtio->aGCPhysVirtqAvail[uVirtqNbr] + RT_UOFFSETOF(VIRTQ_AVAIL_T, fFlags),
     
    216217{
    217218    VIRTQ_USED_ELEM_T elem = { uDescIdx,  uLen };
    218     AssertMsg(pVirtio->uDeviceStatus & VIRTIO_STATUS_DRIVER_OK, ("Called with guest driver not ready\n"));
     219    AssertMsg(pVirtio->fDeviceStatus & VIRTIO_STATUS_DRIVER_OK, ("Called with guest driver not ready\n"));
    219220    uint16_t const cVirtqItems = RT_MAX(pVirtio->uVirtqSize[uVirtqNbr], 1); /* Make sure to avoid div-by-zero. */
    220221    PDMDevHlpPCIPhysWrite(pDevIns,
     
    225226DECLINLINE(void) virtioWriteUsedRingFlags(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t uVirtqNbr, uint16_t fFlags)
    226227{
    227     AssertMsg(pVirtio->uDeviceStatus & VIRTIO_STATUS_DRIVER_OK, ("Called with guest driver not ready\n"));
     228    AssertMsg(pVirtio->fDeviceStatus & VIRTIO_STATUS_DRIVER_OK, ("Called with guest driver not ready\n"));
    228229    RT_UNTRUSTED_VALIDATED_FENCE(); /* VirtIO 1.0, Section 3.2.1.4.1 */
    229230    PDMDevHlpPCIPhysWrite(pDevIns,
     
    235236DECLINLINE(void) virtioWriteUsedRingIdx(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t uVirtqNbr, uint16_t uIdx)
    236237{
    237     AssertMsg(pVirtio->uDeviceStatus & VIRTIO_STATUS_DRIVER_OK, ("Called with guest driver not ready\n"));
     238    AssertMsg(pVirtio->fDeviceStatus & VIRTIO_STATUS_DRIVER_OK, ("Called with guest driver not ready\n"));
    238239    PDMDevHlpPCIPhysWrite(pDevIns,
    239240                          pVirtio->aGCPhysVirtqUsed[uVirtqNbr] + RT_UOFFSETOF(VIRTQ_USED_T, uIdx),
     
    247248{
    248249    uint16_t uIdx = 0;
    249     AssertMsg(pVirtio->uDeviceStatus & VIRTIO_STATUS_DRIVER_OK, ("Called with guest driver not ready\n"));
     250    AssertMsg(pVirtio->fDeviceStatus & VIRTIO_STATUS_DRIVER_OK, ("Called with guest driver not ready\n"));
    250251    PDMDevHlpPCIPhysRead(pDevIns,
    251252                      pVirtio->aGCPhysVirtqUsed[uVirtqNbr] + RT_UOFFSETOF(VIRTQ_USED_T, uIdx),
     
    257258{
    258259    uint16_t fFlags = 0;
    259     AssertMsg(pVirtio->uDeviceStatus & VIRTIO_STATUS_DRIVER_OK, ("Called with guest driver not ready\n"));
     260    AssertMsg(pVirtio->fDeviceStatus & VIRTIO_STATUS_DRIVER_OK, ("Called with guest driver not ready\n"));
    260261    PDMDevHlpPCIPhysRead(pDevIns,
    261262                      pVirtio->aGCPhysVirtqUsed[uVirtqNbr] + RT_UOFFSETOF(VIRTQ_USED_T, fFlags),
     
    267268{
    268269    /** VirtIO 1.0 uAvailEventIdx (avail_event) immediately follows ring */
    269     AssertMsg(pVirtio->uDeviceStatus & VIRTIO_STATUS_DRIVER_OK, ("Called with guest driver not ready\n"));
     270    AssertMsg(pVirtio->fDeviceStatus & VIRTIO_STATUS_DRIVER_OK, ("Called with guest driver not ready\n"));
    270271    PDMDevHlpPCIPhysWrite(pDevIns,
    271272                          pVirtio->aGCPhysVirtqUsed[uVirtqNbr] + RT_UOFFSETOF_DYN(VIRTQ_USED_T, aRing[pVirtio->uVirtqSize[uVirtqNbr]]),
     
    415416}
    416417
    417 RTGCPHYS virtioCoreGCPhysChainGetNextSegment(PVIRTIOSGBUF pGcSgBuf, size_t *pcbSeg)
     418RTGCPHYS virtioCoreGCPhysChainGetNextSeg(PVIRTIOSGBUF pGcSgBuf, size_t *pcbSeg)
    418419{
    419420    AssertReturn(pGcSgBuf, 0);
     
    598599        uValue.u = 0;
    599600        memcpy(uValue.au8, pv, cb);
    600         Log6(("%s: Guest %s %s %#0*RX64\n",
     601        Log6(("%-23s: Guest %s %s %#0*RX64\n",
    601602                  pszFunc, fWrite ? "wrote" : "read ", szDepiction, 2 + cb * 2, uValue.u));
    602603    }
    603604    else /* odd number or oversized access, ... log inline hex-dump style */
    604605    {
    605         Log6(("%s: Guest %s %s%s[%d:%d]: %.*Rhxs\n",
     606        Log6(("%-23s: Guest %s %s%s[%d:%d]: %.*Rhxs\n",
    606607                  pszFunc, fWrite ? "wrote" : "read ", pszMember,
    607608                  szIdx, uOffset, uOffset + cb, cb, pv));
     
    610611}
    611612
    612 
    613613/**
    614  * Makes the MMIO-mapped Virtio uDeviceStatus registers non-cryptic
    615  */
    616 DECLINLINE(void) virtioLogDeviceStatus(uint8_t bStatus)
    617 {
    618     if (bStatus == 0)
    619         Log6(("RESET"));
    620     else
    621     {
    622         int primed = 0;
    623         if (bStatus & VIRTIO_STATUS_ACKNOWLEDGE)
    624             Log6(("%sACKNOWLEDGE", primed++ ? "" : ""));
    625         if (bStatus & VIRTIO_STATUS_DRIVER)
    626             Log6(("%sDRIVER",      primed++ ? " | " : ""));
    627         if (bStatus & VIRTIO_STATUS_FEATURES_OK)
    628             Log6(("%sFEATURES_OK", primed++ ? " | " : ""));
    629         if (bStatus & VIRTIO_STATUS_DRIVER_OK)
    630             Log6(("%sDRIVER_OK",   primed++ ? " | " : ""));
    631         if (bStatus & VIRTIO_STATUS_FAILED)
    632             Log6(("%sFAILED",      primed++ ? " | " : ""));
    633         if (bStatus & VIRTIO_STATUS_DEVICE_NEEDS_RESET)
    634             Log6(("%sNEEDS_RESET", primed++ ? " | " : ""));
    635         (void)primed;
    636     }
     614 * Makes the MMIO-mapped Virtio fDeviceStatus registers non-cryptic (buffers to
     615 * keep the output clean during multi-threaded activity)
     616 */
     617DECLINLINE(void) virtioCoreFormatDeviceStatus(uint8_t bStatus, char *pszBuf, size_t uSize)
     618{
     619
     620#define ADJCURSOR(len) cp += len; uSize -= len; sep = (char *)" | ";
     621
     622    memset(pszBuf, 0, uSize);
     623    size_t len;
     624    char *cp = pszBuf;
     625    char *sep = (char *)"";
     626
     627    if (bStatus == 0) {
     628        RTStrPrintf(cp, uSize, "RESET");
     629        return;
     630    }
     631    if (bStatus & VIRTIO_STATUS_ACKNOWLEDGE)
     632    {
     633        len = RTStrPrintf(cp, uSize, "ACKNOWLEDGE");
     634        ADJCURSOR(len);
     635   }
     636    if (bStatus & VIRTIO_STATUS_DRIVER)
     637    {
     638        len = RTStrPrintf(cp, uSize, "%sDRIVER", sep);
     639        ADJCURSOR(len);
     640    }
     641    if (bStatus & VIRTIO_STATUS_FEATURES_OK)
     642    {
     643        len = RTStrPrintf(cp, uSize, "%sFEATURES_OK", sep);
     644        ADJCURSOR(len);
     645    }
     646    if (bStatus & VIRTIO_STATUS_DRIVER_OK)
     647    {
     648        len = RTStrPrintf(cp, uSize, "%sDRIVER_OK", sep);
     649        ADJCURSOR(len);
     650    }
     651    if (bStatus & VIRTIO_STATUS_FAILED)
     652    {
     653        len = RTStrPrintf(cp, uSize, "%sFAILED", sep);
     654        ADJCURSOR(len);
     655    }
     656    if (bStatus & VIRTIO_STATUS_DEVICE_NEEDS_RESET)
     657        RTStrPrintf(cp, uSize, "%sNEEDS_RESET", sep);
     658
     659#undef ADJCURSOR
     660}
     661
     662int virtioCoreVirtqAttach(PVIRTIOCORE pVirtio, uint16_t uVirtqNbr, const char *pcszName)
     663{
     664    LogFunc(("%s\n", pcszName));
     665    PVIRTQSTATE pVirtqState = &pVirtio->aVirtqState[uVirtqNbr];
     666    pVirtqState->uVirtqNbr = uVirtqNbr;
     667    pVirtqState->uAvailIdxShadow = 0;
     668    pVirtqState->uUsedIdxShadow  = 0;
     669    pVirtqState->fVirtqRingEventThreshold = false;
     670    RTStrCopy(pVirtqState->szVirtqName, sizeof(pVirtqState->szVirtqName), pcszName);
     671    return VINF_SUCCESS;
    637672}
    638673
     
    646681    PVIRTQSTATE pVirtqState = &pVirtio->aVirtqState[uVirtqNbr];
    647682
    648     /** @todo add ability to dump physical contents of any descriptor (using existing VirtIO core API function) */
     683    /** @todo add ability to dump physical contents described by any descriptor (using existing VirtIO core API function) */
    649684//    bool fDump      = pszArgs && (*pszArgs == 'd' || *pszArgs == 'D'); /* "dump" (avail phys descriptor)"
    650685
     
    704739        }
    705740        pHlp->pfnPrintf(pHlp, "\n");
    706         pHlp->pfnPrintf(pHlp,     "          guest-to-host (%d bytes)\n",   pVirtqBuf->cbPhysReturn);
     741        pHlp->pfnPrintf(pHlp,     "      guest-to-host (%d bytes)\n",       pVirtqBuf->cbPhysReturn);
    707742        pHlp->pfnPrintf(pHlp,     "             segs: .............. %d\n", cReturnSegs);
    708743        if (cReturnSegs)
     
    717752}
    718753
    719 int virtioCoreR3VirtqAttach(PVIRTIOCORE pVirtio, uint16_t uVirtqNbr, const char *pcszName)
    720 {
    721     LogFunc(("%s\n", pcszName));
    722     PVIRTQSTATE pVirtqState = &pVirtio->aVirtqState[uVirtqNbr];
    723     pVirtqState->uVirtqNbr = uVirtqNbr;
    724     pVirtqState->uAvailIdxShadow = 0;
    725     pVirtqState->uUsedIdxShadow  = 0;
    726     pVirtqState->fVirtqRingEventThreshold = false;
    727     RTStrCopy(pVirtqState->szVirtqName, sizeof(pVirtqState->szVirtqName), pcszName);
    728     return VINF_SUCCESS;
    729 }
    730 #endif /* IN_RING3 */
    731 
    732 
    733 #ifdef IN_RING3
    734754
    735755/** API Function: See header file */
     
    760780    pVirtqBuf->cRefs    = 1;
    761781    pVirtqBuf->uHeadIdx = uHeadIdx;
     782    pVirtqBuf->uVirtqNbr = uVirtqNbr;
    762783    *ppVirtqBuf = pVirtqBuf;
    763784
     
    888909void virtioCoreVirtqEnableNotify(PVIRTIOCORE pVirtio, uint16_t uVirtqNbr, bool fEnable)
    889910{
    890     if (pVirtio->uDeviceStatus & VIRTIO_STATUS_DRIVER_OK)
     911    if (pVirtio->fDeviceStatus & VIRTIO_STATUS_DRIVER_OK)
    891912    {
    892913        uint16_t fFlags = virtioReadUsedRingFlags(pVirtio->pDevInsR3, pVirtio, uVirtqNbr);
     
    905926{
    906927    LogFunc(("\n"));
    907     pVirtio->uDeviceStatus |= VIRTIO_STATUS_DEVICE_NEEDS_RESET;
    908     if (pVirtio->uDeviceStatus & VIRTIO_STATUS_DRIVER_OK)
     928    pVirtio->fDeviceStatus |= VIRTIO_STATUS_DEVICE_NEEDS_RESET;
     929    if (pVirtio->fDeviceStatus & VIRTIO_STATUS_DRIVER_OK)
    909930    {
    910931        pVirtio->fGenUpdatePending = true;
     
    10191040
    10201041    return VINF_SUCCESS;
     1042}
     1043
     1044/** API function: See Header file  */
     1045void virtioCoreR3VirqBufFill(PVIRTIOCORE pVirtio, PVIRTQBUF pVirtqBuf, void *pv, size_t cb)
     1046{
     1047    uint8_t *pb = (uint8_t *)pv;
     1048    size_t cbLim = RT_MIN(pVirtqBuf->cbPhysReturn, cb);
     1049    while (cbLim)
     1050    {
     1051        size_t cbSeg = cbLim;
     1052        RTGCPHYS GCPhys = virtioCoreGCPhysChainGetNextSeg(pVirtqBuf->pSgPhysReturn, &cbSeg);
     1053        PDMDevHlpPCIPhysWrite(pVirtio->pDevInsR3, GCPhys, pb, cbSeg);
     1054        pb += cbSeg;
     1055        cbLim -= cbSeg;
     1056        pVirtqBuf->cbPhysSend -= cbSeg;
     1057    }
     1058    LogFunc(("Added %d/%d bytes to %s buffer, head idx: %u (%d bytes remain)\n",
     1059             cb - cbLim, cb, VIRTQNAME(pVirtio, pVirtqBuf->uVirtqNbr),
     1060             pVirtqBuf->uHeadIdx, pVirtqBuf->cbPhysReturn));
     1061}
     1062
     1063
     1064/** API function: See Header file  */
     1065void virtioCoreR3VirtqBufDrain(PVIRTIOCORE pVirtio, PVIRTQBUF pVirtqBuf, void *pv, size_t cb)
     1066{
     1067    uint8_t *pb = (uint8_t *)pv;
     1068    size_t cbLim = RT_MIN(pVirtqBuf->cbPhysSend, cb);
     1069    while (cbLim)
     1070    {
     1071        size_t cbSeg = cbLim;
     1072        RTGCPHYS GCPhys = virtioCoreGCPhysChainGetNextSeg(pVirtqBuf->pSgPhysSend, &cbSeg);
     1073        PDMDevHlpPCIPhysRead(pVirtio->pDevInsR3, GCPhys, pb, cbSeg);
     1074        pb += cbSeg;
     1075        cbLim -= cbSeg;
     1076        pVirtqBuf->cbPhysSend -= cbSeg;
     1077    }
     1078    LogFunc(("Drained %d/%d bytes from %s buffer, head idx: %u (%d bytes left)\n",
     1079             cb - cbLim, cb, VIRTQNAME(pVirtio, pVirtqBuf->uVirtqNbr),
     1080             pVirtqBuf->uHeadIdx, pVirtqBuf->cbPhysSend));
    10211081}
    10221082
     
    11841244    pVirtio->uDriverFeaturesSelect  = 0;
    11851245    pVirtio->uConfigGeneration      = 0;
    1186     pVirtio->uDeviceStatus          = 0;
     1246    pVirtio->fDeviceStatus          = 0;
    11871247    pVirtio->uISR                   = 0;
    11881248
     
    12251285 * @returns VBox status code
    12261286 *
    1227  * @param   pDevIns     The device instance.
    1228  * @param   pVirtio     Pointer to the shared virtio state.
    1229  * @param   pVirtioCC   Pointer to the current context virtio state.
    1230  * @param   fWrite      Set if write access, clear if read access.
    1231  * @param   offCfg      The common configuration capability offset.
    1232  * @param   cb          Number of bytes to read or write
    1233  * @param   pv          Pointer to location to write to or read from
     1287 * @param   pDevIns          The device instance.
     1288 * @param   pVirtio          Pointer to the shared virtio state.
     1289 * @param   pVirtioCC        Pointer to the current context virtio state.
     1290 * @param   fWrite           Set if write access, clear if read access.
     1291 * @param   uOffsetOfAccess  The common configuration capability offset.
     1292 * @param   cb               Number of bytes to read or write
     1293 * @param   pv               Pointer to location to write to or read from
    12341294 */
    12351295static int virtioCommonCfgAccessed(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, PVIRTIOCORECC pVirtioCC,
    1236                                    int fWrite, uint32_t offCfg, unsigned cb, void *pv)
    1237 {
    1238 /**
    1239  * This macro resolves to boolean true if the implied parameters, offCfg and cb,
    1240  * match the field offset and size of a field in the Common Cfg struct, (or if
    1241  * it is a 64-bit field, if it accesses either 32-bit part as a 32-bit access)
    1242  * This is mandated by section 4.1.3.1 of the VirtIO 1.0 specification)
    1243  *
    1244  * @param   member  Member of VIRTIO_PCI_COMMON_CFG_T
    1245  * @param   offCfg  Implied parameter: Offset into VIRTIO_PCI_COMMON_CFG_T
    1246  * @param   cb      Implied parameter: Number of bytes to access
    1247  * @result true or false
    1248  */
    1249 #define MATCH_COMMON_CFG(member) \
    1250     (   (   RT_SIZEOFMEMB(VIRTIO_PCI_COMMON_CFG_T, member) == 8 \
    1251          && (   offCfg == RT_OFFSETOF(VIRTIO_PCI_COMMON_CFG_T, member) \
    1252              || offCfg == RT_OFFSETOF(VIRTIO_PCI_COMMON_CFG_T, member) + sizeof(uint32_t)) \
    1253          && cb == sizeof(uint32_t)) \
    1254      || (   offCfg == RT_OFFSETOF(VIRTIO_PCI_COMMON_CFG_T, member) \
    1255          && cb == RT_SIZEOFMEMB(VIRTIO_PCI_COMMON_CFG_T, member)) )
    1256 
    1257 #ifdef LOG_ENABLED
    1258 # define LOG_COMMON_CFG_ACCESS(member, uOffset) \
    1259     if (LogIs7Enabled()) { \
    1260         virtioCoreLogMappedIoValue(__FUNCTION__, #member, RT_SIZEOFMEMB(VIRTIO_PCI_COMMON_CFG_T, member), \
    1261                                    pv, cb, uOffset, fWrite, false, 0); \
    1262     }
    1263 # define LOG_COMMON_CFG_ACCESS_INDEXED(member, idx, uOffset) \
    1264     if (LogIs7Enabled()) { \
    1265         virtioCoreLogMappedIoValue(__FUNCTION__, #member, RT_SIZEOFMEMB(VIRTIO_PCI_COMMON_CFG_T, member), \
    1266                                    pv, cb, uOffset, fWrite, true, idx); \
    1267     }
    1268 #else
    1269 # define LOG_COMMON_CFG_ACCESS(member, uOffset)              do { } while (0)
    1270 # define LOG_COMMON_CFG_ACCESS_INDEXED(member, idx, uOffset) do { } while (0)
    1271 #endif
    1272 
    1273 #define COMMON_CFG_ACCESSOR(member) \
    1274     do \
    1275     { \
    1276         uint32_t uOffset = offCfg - RT_OFFSETOF(VIRTIO_PCI_COMMON_CFG_T, member); \
    1277         if (fWrite) \
    1278             memcpy((char *)&pVirtio->member + uOffset, (const char *)pv, cb); \
    1279         else \
    1280             memcpy(pv, (const char *)&pVirtio->member + uOffset, cb); \
    1281         LOG_COMMON_CFG_ACCESS(member, uOffset); \
    1282     } while(0)
    1283 
    1284 #define COMMON_CFG_ACCESSOR_INDEXED(member, idx) \
    1285     do \
    1286     { \
    1287         uint32_t uOffset = offCfg - RT_OFFSETOF(VIRTIO_PCI_COMMON_CFG_T, member); \
    1288         if (fWrite) \
    1289             memcpy((char *)&pVirtio->member[idx] + uOffset, pv, cb); \
    1290         else \
    1291             memcpy(pv, (const char *)&pVirtio->member[idx] + uOffset, cb); \
    1292         LOG_COMMON_CFG_ACCESS_INDEXED(member, idx, uOffset); \
    1293     } while(0)
    1294 
    1295 #define COMMON_CFG_ACCESSOR_READONLY(member) \
    1296     do \
    1297     { \
    1298         uint32_t uOffset = offCfg - RT_OFFSETOF(VIRTIO_PCI_COMMON_CFG_T, member); \
    1299         if (fWrite) \
    1300             LogFunc(("Guest attempted to write readonly virtio_pci_common_cfg.%s\n", #member)); \
    1301         else \
    1302         { \
    1303             memcpy(pv, (const char *)&pVirtio->member + uOffset, cb); \
    1304             LOG_COMMON_CFG_ACCESS(member, uOffset); \
    1305         } \
    1306     } while(0)
    1307 
    1308 #define COMMON_CFG_ACCESSOR_INDEXED_READONLY(member, idx) \
    1309     do \
    1310     { \
    1311         uint32_t uOffset = offCfg - RT_OFFSETOF(VIRTIO_PCI_COMMON_CFG_T, member); \
    1312         if (fWrite) \
    1313             LogFunc(("Guest attempted to write readonly virtio_pci_common_cfg.%s[%d]\n", #member, idx)); \
    1314         else \
    1315         { \
    1316             memcpy(pv, (char const *)&pVirtio->member[idx] + uOffset, cb); \
    1317             LOG_COMMON_CFG_ACCESS_INDEXED(member, idx, uOffset); \
    1318         } \
    1319     } while(0)
    1320 
    1321 
     1296                                   int fWrite, uint32_t uOffsetOfAccess, unsigned cb, void *pv)
     1297{
     1298    uint16_t uVirtqNbr = pVirtio->uVirtqSelect;
    13221299    int rc = VINF_SUCCESS;
    13231300    uint64_t val;
    1324     if (MATCH_COMMON_CFG(uDeviceFeatures))
     1301    if (VIRTIO_DEV_CONFIG_MATCH_MEMBER(uDeviceFeatures, VIRTIO_PCI_COMMON_CFG_T, uOffsetOfAccess))
    13251302    {
    13261303        if (fWrite) /* Guest WRITE pCommonCfg>uDeviceFeatures */
    13271304        {
    1328             LogFunc(("Guest attempted to write readonly virtio_pci_common_cfg.device_feature\n"));
    1329             return VINF_SUCCESS;
     1305            /* VirtIO 1.0, 4.1.4.3 states device_feature is a (guest) driver readonly field,
     1306             * yet the linux driver attempts to write/read it back twice */
     1307            VIRTIO_DEV_CONFIG_LOG_ACCESS(uDeviceFeatures, VIRTIO_PCI_COMMON_CFG_T, uOffsetOfAccess);
     1308            LogFunc(("... WARNING: Guest attempted to write readonly virtio_pci_common_cfg.device_feature (ignoring)\n"));
     1309//            return VINF_SUCCESS;
     1310            return VINF_IOM_MMIO_UNUSED_00; /** @todo which is right this or VINF_SUCCESS? */
    13301311        }
    13311312        else /* Guest READ pCommonCfg->uDeviceFeatures */
     
    13361317                    val = pVirtio->uDeviceFeatures & UINT32_C(0xffffffff);
    13371318                    memcpy(pv, &val, cb);
    1338                     LOG_COMMON_CFG_ACCESS(uDeviceFeatures, offCfg - RT_UOFFSETOF(VIRTIO_PCI_COMMON_CFG_T, uDeviceFeatures));
     1319                    VIRTIO_DEV_CONFIG_LOG_ACCESS(uDeviceFeatures, VIRTIO_PCI_COMMON_CFG_T, uOffsetOfAccess);
    13391320                    break;
    13401321                case 1:
    13411322                    val = pVirtio->uDeviceFeatures >> 32;
    13421323                    memcpy(pv, &val, cb);
    1343                     LOG_COMMON_CFG_ACCESS(uDeviceFeatures, offCfg - RT_UOFFSETOF(VIRTIO_PCI_COMMON_CFG_T, uDeviceFeatures) + 4);
     1324                    VIRTIO_DEV_CONFIG_LOG_ACCESS(uDeviceFeatures, VIRTIO_PCI_COMMON_CFG_T, uOffsetOfAccess + sizeof(uint32_t));
    13441325                    break;
    13451326                default:
     
    13501331        }
    13511332    }
    1352     else if (MATCH_COMMON_CFG(uDriverFeatures))
     1333    else
     1334    if (VIRTIO_DEV_CONFIG_MATCH_MEMBER(uDriverFeatures, VIRTIO_PCI_COMMON_CFG_T, uOffsetOfAccess))
    13531335    {
    13541336        if (fWrite) /* Guest WRITE pCommonCfg->udriverFeatures */
     
    13581340                case 0:
    13591341                    memcpy(&pVirtio->uDriverFeatures, pv, cb);
    1360                     LOG_COMMON_CFG_ACCESS(uDriverFeatures, offCfg - RT_UOFFSETOF(VIRTIO_PCI_COMMON_CFG_T, uDriverFeatures));
     1342                    VIRTIO_DEV_CONFIG_LOG_ACCESS(uDriverFeatures, VIRTIO_PCI_COMMON_CFG_T, uOffsetOfAccess);
    13611343                    break;
    13621344                case 1:
    13631345                    memcpy((char *)&pVirtio->uDriverFeatures + sizeof(uint32_t), pv, cb);
    1364                     LOG_COMMON_CFG_ACCESS(uDriverFeatures, offCfg - RT_UOFFSETOF(VIRTIO_PCI_COMMON_CFG_T, uDriverFeatures) + 4);
     1346                    VIRTIO_DEV_CONFIG_LOG_ACCESS(uDriverFeatures, VIRTIO_PCI_COMMON_CFG_T, uOffsetOfAccess + sizeof(uint32_t));
    13651347                    break;
    13661348                default:
     
    13701352            }
    13711353        }
    1372         else /* Guest READ pCommonCfg->udriverFeatures */
     1354        /* Guest READ pCommonCfg->udriverFeatures */
    13731355        {
    13741356            switch (pVirtio->uDriverFeaturesSelect)
     
    13771359                    val = pVirtio->uDriverFeatures & 0xffffffff;
    13781360                    memcpy(pv, &val, cb);
    1379                     LOG_COMMON_CFG_ACCESS(uDriverFeatures, offCfg - RT_UOFFSETOF(VIRTIO_PCI_COMMON_CFG_T, uDriverFeatures));
     1361                    VIRTIO_DEV_CONFIG_LOG_ACCESS(uDriverFeatures, VIRTIO_PCI_COMMON_CFG_T, uOffsetOfAccess);
    13801362                    break;
    13811363                case 1:
    13821364                    val = (pVirtio->uDriverFeatures >> 32) & 0xffffffff;
    13831365                    memcpy(pv, &val, cb);
    1384                     LOG_COMMON_CFG_ACCESS(uDriverFeatures, offCfg - RT_UOFFSETOF(VIRTIO_PCI_COMMON_CFG_T, uDriverFeatures) + 4);
     1366                    VIRTIO_DEV_CONFIG_LOG_ACCESS(uDriverFeatures, VIRTIO_PCI_COMMON_CFG_T, uOffsetOfAccess + 4);
    13851367                    break;
    13861368                default:
     
    13911373        }
    13921374    }
    1393     else if (MATCH_COMMON_CFG(uNumVirtqs))
     1375    else
     1376    if (VIRTIO_DEV_CONFIG_MATCH_MEMBER(uNumVirtqs, VIRTIO_PCI_COMMON_CFG_T, uOffsetOfAccess))
    13941377    {
    13951378        if (fWrite)
     
    13981381            return VINF_SUCCESS;
    13991382        }
    1400         else
    1401         {
    1402             *(uint16_t *)pv = VIRTQ_MAX_CNT;
    1403             LOG_COMMON_CFG_ACCESS(uNumVirtqs, 0);
    1404         }
    1405     }
    1406     else if (MATCH_COMMON_CFG(uDeviceStatus))
    1407     {
    1408         if (fWrite) /* Guest WRITE pCommonCfg->uDeviceStatus */
    1409         {
    1410             uint8_t const fNewStatus = *(uint8_t *)pv;
    1411             Log7Func(("Guest wrote uDeviceStatus ................ ("));
     1383        *(uint16_t *)pv = VIRTQ_MAX_CNT;
     1384        VIRTIO_DEV_CONFIG_LOG_ACCESS(uNumVirtqs, VIRTIO_PCI_COMMON_CFG_T, uOffsetOfAccess);
     1385    }
     1386    else
     1387    if (VIRTIO_DEV_CONFIG_MATCH_MEMBER(fDeviceStatus, VIRTIO_PCI_COMMON_CFG_T, uOffsetOfAccess))
     1388    {
     1389        if (fWrite) /* Guest WRITE pCommonCfg->fDeviceStatus */
     1390        {
     1391            pVirtio->fDeviceStatus = *(uint8_t *)pv;
     1392            bool fDeviceReset = pVirtio->fDeviceStatus == 0;
     1393
    14121394            if (LogIs7Enabled())
    1413                 virtioLogDeviceStatus(fNewStatus ^ pVirtio->uDeviceStatus);
    1414             Log7((")\n"));
    1415 
    1416             /* If the status changed or we were reset, we need to go to ring-3 as
    1417                it requires notifying the parent device. */
    1418             bool const fStatusChanged =    (fNewStatus & VIRTIO_STATUS_DRIVER_OK)
    1419                                         != (pVirtio->uPrevDeviceStatus & VIRTIO_STATUS_DRIVER_OK);
    1420 #ifndef IN_RING3
    1421             if (fStatusChanged || fNewStatus == 0)
    14221395            {
    1423                 Log6Func(("=>ring3\n"));
     1396                char szOut[80] = { 0 };
     1397                virtioCoreFormatDeviceStatus(pVirtio->fDeviceStatus, szOut, sizeof(szOut));
     1398                LogFunc(("Guest wrote fDeviceStatus ................ (%s)\n", szOut));
     1399            }
     1400            bool const fStatusChanged =
     1401                (pVirtio->fDeviceStatus & VIRTIO_STATUS_DRIVER_OK) != (pVirtio->uPrevDeviceStatus & VIRTIO_STATUS_DRIVER_OK);
     1402
     1403            if (fDeviceReset || fStatusChanged)
     1404            {
     1405#ifdef IN_RING0
     1406                /* Since VirtIO status changes are cumbersome by nature, e.g. not a benchmark priority,
     1407                 * handle the rest in R3 to facilitate logging or whatever dev-specific client needs to do */
     1408                Log6Func(("RING0 => RING3 (demote)\n"));
    14241409                return VINF_IOM_R3_MMIO_WRITE;
     1410#endif
    14251411            }
    1426 #endif
    1427             pVirtio->uDeviceStatus = fNewStatus;
    14281412
    14291413#ifdef IN_RING3
     
    14311415             * Notify client only if status actually changed from last time and when we're reset.
    14321416             */
    1433             if (pVirtio->uDeviceStatus == 0)
     1417            if (fDeviceReset)
    14341418                virtioGuestR3WasReset(pDevIns, pVirtio, pVirtioCC);
     1419
    14351420            if (fStatusChanged)
    1436                 pVirtioCC->pfnStatusChanged(pVirtio, pVirtioCC, fNewStatus & VIRTIO_STATUS_DRIVER_OK);
     1421                pVirtioCC->pfnStatusChanged(pVirtio, pVirtioCC, pVirtio->fDeviceStatus & VIRTIO_STATUS_DRIVER_OK);
    14371422#endif
    14381423            /*
    14391424             * Save the current status for the next write so we can see what changed.
    14401425             */
    1441             pVirtio->uPrevDeviceStatus = pVirtio->uDeviceStatus;
    1442         }
    1443         else /* Guest READ pCommonCfg->uDeviceStatus */
    1444         {
    1445             Log7Func(("Guest read  uDeviceStatus ................ ("));
    1446             *(uint8_t *)pv = pVirtio->uDeviceStatus;
     1426            pVirtio->uPrevDeviceStatus = pVirtio->fDeviceStatus;
     1427        }
     1428        else /* Guest READ pCommonCfg->fDeviceStatus */
     1429        {
     1430            *(uint8_t *)pv = pVirtio->fDeviceStatus;
     1431
    14471432            if (LogIs7Enabled())
    1448                 virtioLogDeviceStatus(pVirtio->uDeviceStatus);
    1449             Log7((")\n"));
    1450         }
    1451     }
    1452     else
    1453     if (MATCH_COMMON_CFG(uMsixConfig))
    1454         COMMON_CFG_ACCESSOR(uMsixConfig);
    1455     else
    1456     if (MATCH_COMMON_CFG(uDeviceFeaturesSelect))
    1457         COMMON_CFG_ACCESSOR(uDeviceFeaturesSelect);
    1458     else
    1459     if (MATCH_COMMON_CFG(uDriverFeaturesSelect))
    1460         COMMON_CFG_ACCESSOR(uDriverFeaturesSelect);
    1461     else
    1462     if (MATCH_COMMON_CFG(uConfigGeneration))
    1463         COMMON_CFG_ACCESSOR_READONLY(uConfigGeneration);
    1464     else
    1465     if (MATCH_COMMON_CFG(uVirtqSelect))
    1466         COMMON_CFG_ACCESSOR(uVirtqSelect);
    1467     else
    1468     if (MATCH_COMMON_CFG(uVirtqSize))
    1469         COMMON_CFG_ACCESSOR_INDEXED(uVirtqSize, pVirtio->uVirtqSelect);
    1470     else
    1471     if (MATCH_COMMON_CFG(uVirtqMsixVector))
    1472         COMMON_CFG_ACCESSOR_INDEXED(uVirtqMsixVector, pVirtio->uVirtqSelect);
    1473     else
    1474     if (MATCH_COMMON_CFG(uVirtqEnable))
    1475         COMMON_CFG_ACCESSOR_INDEXED(uVirtqEnable, pVirtio->uVirtqSelect);
    1476     else
    1477     if (MATCH_COMMON_CFG(uVirtqNotifyOff))
    1478         COMMON_CFG_ACCESSOR_INDEXED_READONLY(uVirtqNotifyOff, pVirtio->uVirtqSelect);
    1479     else
    1480     if (MATCH_COMMON_CFG(aGCPhysVirtqDesc))
    1481         COMMON_CFG_ACCESSOR_INDEXED(aGCPhysVirtqDesc, pVirtio->uVirtqSelect);
    1482     else
    1483     if (MATCH_COMMON_CFG(aGCPhysVirtqAvail))
    1484         COMMON_CFG_ACCESSOR_INDEXED(aGCPhysVirtqAvail, pVirtio->uVirtqSelect);
    1485     else
    1486     if (MATCH_COMMON_CFG(aGCPhysVirtqUsed))
    1487         COMMON_CFG_ACCESSOR_INDEXED(aGCPhysVirtqUsed, pVirtio->uVirtqSelect);
    1488     else
    1489     {
    1490         Log2Func(("Bad guest %s access to virtio_pci_common_cfg: offCfg=%#x (%d), cb=%d\n",
    1491                   fWrite ? "write" : "read ", offCfg, offCfg, cb));
     1433            {
     1434                char szOut[80] = { 0 };
     1435                virtioCoreFormatDeviceStatus(pVirtio->fDeviceStatus, szOut, sizeof(szOut));
     1436                LogFunc(("Guest read  fDeviceStatus ................ (%s)\n", szOut));
     1437            }
     1438        }
     1439    }
     1440    else
     1441    if (VIRTIO_DEV_CONFIG_MATCH_MEMBER(   uMsixConfig,                   VIRTIO_PCI_COMMON_CFG_T, uOffsetOfAccess))
     1442        VIRTIO_DEV_CONFIG_ACCESS(         uMsixConfig,                   VIRTIO_PCI_COMMON_CFG_T, uOffsetOfAccess, pVirtio);
     1443    else
     1444    if (VIRTIO_DEV_CONFIG_MATCH_MEMBER(   uDeviceFeaturesSelect,         VIRTIO_PCI_COMMON_CFG_T, uOffsetOfAccess))
     1445        VIRTIO_DEV_CONFIG_ACCESS(         uDeviceFeaturesSelect,         VIRTIO_PCI_COMMON_CFG_T, uOffsetOfAccess, pVirtio);
     1446    else
     1447    if (VIRTIO_DEV_CONFIG_MATCH_MEMBER(   uDriverFeaturesSelect,         VIRTIO_PCI_COMMON_CFG_T, uOffsetOfAccess))
     1448        VIRTIO_DEV_CONFIG_ACCESS(         uDriverFeaturesSelect,         VIRTIO_PCI_COMMON_CFG_T, uOffsetOfAccess, pVirtio);
     1449    else
     1450    if (VIRTIO_DEV_CONFIG_MATCH_MEMBER(   uConfigGeneration,             VIRTIO_PCI_COMMON_CFG_T, uOffsetOfAccess))
     1451        VIRTIO_DEV_CONFIG_ACCESS(         uConfigGeneration,             VIRTIO_PCI_COMMON_CFG_T, uOffsetOfAccess, pVirtio);
     1452    else
     1453    if (VIRTIO_DEV_CONFIG_MATCH_MEMBER(   uVirtqSelect,                  VIRTIO_PCI_COMMON_CFG_T, uOffsetOfAccess))
     1454        VIRTIO_DEV_CONFIG_ACCESS(         uVirtqSelect,                  VIRTIO_PCI_COMMON_CFG_T, uOffsetOfAccess, pVirtio);
     1455    else
     1456    if (VIRTIO_DEV_CONFIG_MATCH_MEMBER(   uVirtqSize,                    VIRTIO_PCI_COMMON_CFG_T, uOffsetOfAccess))
     1457        VIRTIO_DEV_CONFIG_ACCESS_INDEXED( uVirtqSize,        uVirtqNbr,  VIRTIO_PCI_COMMON_CFG_T, uOffsetOfAccess, pVirtio);
     1458    else
     1459    if (VIRTIO_DEV_CONFIG_MATCH_MEMBER(   uVirtqMsixVector,              VIRTIO_PCI_COMMON_CFG_T, uOffsetOfAccess))
     1460        VIRTIO_DEV_CONFIG_ACCESS_INDEXED( uVirtqMsixVector,  uVirtqNbr,  VIRTIO_PCI_COMMON_CFG_T, uOffsetOfAccess, pVirtio);
     1461    else
     1462    if (VIRTIO_DEV_CONFIG_MATCH_MEMBER(   uVirtqEnable,                  VIRTIO_PCI_COMMON_CFG_T, uOffsetOfAccess))
     1463        VIRTIO_DEV_CONFIG_ACCESS_INDEXED( uVirtqEnable,      uVirtqNbr,  VIRTIO_PCI_COMMON_CFG_T, uOffsetOfAccess, pVirtio);
     1464    else
     1465    if (VIRTIO_DEV_CONFIG_MATCH_MEMBER(   uVirtqNotifyOff,               VIRTIO_PCI_COMMON_CFG_T, uOffsetOfAccess))
     1466        VIRTIO_DEV_CONFIG_ACCESS_INDEXED( uVirtqNotifyOff,   uVirtqNbr,  VIRTIO_PCI_COMMON_CFG_T, uOffsetOfAccess, pVirtio);
     1467    else
     1468    if (VIRTIO_DEV_CONFIG_MATCH_MEMBER(   aGCPhysVirtqDesc,              VIRTIO_PCI_COMMON_CFG_T, uOffsetOfAccess))
     1469        VIRTIO_DEV_CONFIG_ACCESS_INDEXED( aGCPhysVirtqDesc,  uVirtqNbr,  VIRTIO_PCI_COMMON_CFG_T, uOffsetOfAccess, pVirtio);
     1470    else
     1471    if (VIRTIO_DEV_CONFIG_MATCH_MEMBER(   aGCPhysVirtqAvail,             VIRTIO_PCI_COMMON_CFG_T, uOffsetOfAccess))
     1472        VIRTIO_DEV_CONFIG_ACCESS_INDEXED( aGCPhysVirtqAvail, uVirtqNbr,  VIRTIO_PCI_COMMON_CFG_T, uOffsetOfAccess, pVirtio);
     1473    else
     1474    if (VIRTIO_DEV_CONFIG_MATCH_MEMBER(   aGCPhysVirtqUsed,              VIRTIO_PCI_COMMON_CFG_T, uOffsetOfAccess))
     1475        VIRTIO_DEV_CONFIG_ACCESS_INDEXED( aGCPhysVirtqUsed,  uVirtqNbr,  VIRTIO_PCI_COMMON_CFG_T, uOffsetOfAccess, pVirtio);
     1476    else
     1477    {
     1478        Log2Func(("Bad guest %s access to virtio_pci_common_cfg: uOffsetOfAccess=%#x (%d), cb=%d\n",
     1479                  fWrite ? "write" : "read ", uOffsetOfAccess, uOffsetOfAccess, cb));
    14921480        return fWrite ? VINF_SUCCESS : VINF_IOM_MMIO_UNUSED_00;
    14931481    }
    14941482
    1495 #undef COMMON_CFG_ACCESSOR_READONLY
    1496 #undef COMMON_CFG_ACCESSOR_INDEXED_READONLY
    1497 #undef COMMON_CFG_ACCESSOR_INDEXED
    1498 #undef COMMON_CFG_ACCESSOR
    1499 #undef LOG_COMMON_CFG_ACCESS_INDEXED
    1500 #undef LOG_COMMON_CFG_ACCESS
    1501 #undef MATCH_COMMON_CFG
    15021483#ifndef IN_RING3
    15031484    RT_NOREF(pDevIns, pVirtioCC);
     
    15271508    {
    15281509#ifdef IN_RING3
     1510LogFunc(("IN_RING3\n"));
    15291511        /*
    15301512         * Callback to client to manage device-specific configuration.
     
    15561538        return rcStrict;
    15571539#else
     1540Log7Func(("return VINF_IOM_R3_MMIO_READ\n"));
    15581541        return VINF_IOM_R3_MMIO_READ;
    15591542#endif
     
    15611544
    15621545    if (MATCHES_VIRTIO_CAP_STRUCT(off, cb, uOffset, pVirtio->LocCommonCfgCap))
     1546{
     1547#ifdef IN_RING3
    15631548        return virtioCommonCfgAccessed(pDevIns, pVirtio, pVirtioCC, false /* fWrite */, uOffset, cb, pv);
    1564 
     1549#else
     1550        return virtioCommonCfgAccessed(pDevIns, pVirtio, pVirtioCC, false /* fWrite */, uOffset, cb, pv);
     1551#endif
     1552}
    15651553    if (MATCHES_VIRTIO_CAP_STRUCT(off, cb, uOffset, pVirtio->LocIsrCap) && cb == sizeof(uint8_t))
    15661554    {
     
    16061594
    16071595    if (MATCHES_VIRTIO_CAP_STRUCT(off, cb, uOffset, pVirtio->LocCommonCfgCap))
     1596    {
     1597#ifdef IN_RING3
    16081598        return virtioCommonCfgAccessed(pDevIns, pVirtio, pVirtioCC, true /* fWrite */, uOffset, cb, (void *)pv);
    1609 
     1599#else
     1600        return virtioCommonCfgAccessed(pDevIns, pVirtio, pVirtioCC, true /* fWrite */, uOffset, cb, (void *)pv);
     1601#endif
     1602    }
    16101603    if (MATCHES_VIRTIO_CAP_STRUCT(off, cb, uOffset, pVirtio->LocIsrCap) && cb == sizeof(uint8_t))
    16111604    {
     
    16411634    RT_NOREF(pPciDev);
    16421635
    1643     Log7Func(("pDevIns=%p pPciDev=%p uAddress=%#x cb=%u pu32Value=%p\n",
    1644                  pDevIns, pPciDev, uAddress, cb, pu32Value));
     1636    Log7Func((" pDevIns=%p pPciDev=%p uAddress=%#x%s cb=%u pu32Value=%p\n",
     1637                 pDevIns, pPciDev, uAddress,  uAddress < 0x10 ? " " : "", cb, pu32Value));
    16451638    if (uAddress == pVirtio->uPciCfgDataOff)
    16461639    {
     
    16631656
    16641657        VBOXSTRICTRC rcStrict = virtioMmioRead(pDevIns, pVirtio, pPciCap->uOffset, pu32Value, cb);
    1665         Log2Func(("virtio: Guest read  virtio_pci_cfg_cap.pci_cfg_data, bar=%d, offset=%d, length=%d, result=%d -> %Rrc\n",
     1658        Log7Func(("virtio: Guest read  virtio_pci_cfg_cap.pci_cfg_data, bar=%d, offset=%d, length=%d, result=%d -> %Rrc\n",
    16661659                   pPciCap->uBar, pPciCap->uOffset, uLength, *pu32Value, VBOXSTRICTRC_VAL(rcStrict)));
    16671660        return rcStrict;
     
    16801673    RT_NOREF(pPciDev);
    16811674
    1682     Log7Func(("pDevIns=%p pPciDev=%p uAddress=%#x cb=%u u32Value=%#x\n", pDevIns, pPciDev, uAddress, cb, u32Value));
     1675    Log7Func(("pDevIns=%p pPciDev=%p uAddress=%#x %scb=%u u32Value=%#x\n", pDevIns, pPciDev, uAddress, uAddress < 0xf ? " " : "", cb, u32Value));
    16831676    if (uAddress == pVirtio->uPciCfgDataOff)
    16841677    {
     
    17261719
    17271720    pHlp->pfnSSMPutBool(pSSM,   pVirtio->fGenUpdatePending);
    1728     pHlp->pfnSSMPutU8(pSSM,     pVirtio->uDeviceStatus);
     1721    pHlp->pfnSSMPutU8(pSSM,     pVirtio->fDeviceStatus);
    17291722    pHlp->pfnSSMPutU8(pSSM,     pVirtio->uConfigGeneration);
    17301723    pHlp->pfnSSMPutU8(pSSM,     pVirtio->uPciCfgDataOff);
     
    17841777     */
    17851778    pHlp->pfnSSMGetBool(pSSM, &pVirtio->fGenUpdatePending);
    1786     pHlp->pfnSSMGetU8(pSSM,   &pVirtio->uDeviceStatus);
     1779    pHlp->pfnSSMGetU8(pSSM,   &pVirtio->fDeviceStatus);
    17871780    pHlp->pfnSSMGetU8(pSSM,   &pVirtio->uConfigGeneration);
    17881781    pHlp->pfnSSMGetU8(pSSM,   &pVirtio->uPciCfgDataOff);
     
    19201913    RTStrCopy(pVirtio->szInstance, sizeof(pVirtio->szInstance), pcszInstance);
    19211914
    1922     pVirtio->uDeviceStatus = 0;
     1915    pVirtio->fDeviceStatus = 0;
    19231916    pVirtioCC->cbDevSpecificCfg = cbDevSpecificCfg;
    19241917    pVirtioCC->pbDevSpecificCfg = (uint8_t *)pvDevSpecificCfg;
     
    19521945    /* Construct & map PCI vendor-specific capabilities for virtio host negotiation with guest driver */
    19531946
    1954     /* The following capability mapped via VirtIO 1.0: struct virtio_pci_cfg_cap (VIRTIO_PCI_CFG_CAP_T)
    1955      * as a mandatory but suboptimal alternative interface to host device capabilities, facilitating
    1956      * access the memory of any BAR. If the guest uses it (the VirtIO driver on Linux doesn't),
    1957      * Unlike Common, Notify, ISR and Device capabilities, it is accessed directly via PCI Config region.
    1958      * therefore does not contribute to the capabilities region (BAR) the other capabilities use.
    1959      */
    19601947#define CFG_ADDR_2_IDX(addr) ((uint8_t)(((uintptr_t)(addr) - (uintptr_t)&pPciDev->abConfig[0])))
    19611948#define SET_PCI_CAP_LOC(a_pPciDev, a_pCfg, a_LocCap, a_uMmioLengthAlign) \
     
    19771964    pCfg->uCapNext = CFG_ADDR_2_IDX(pCfg) + pCfg->uCapLen;
    19781965    pCfg->uBar     = VIRTIO_REGION_PCI_CAP;
    1979     pCfg->uOffset  = RT_ALIGN_32(0, 4); /* reminder, in case someone changes offset */
     1966    pCfg->uOffset  = RT_ALIGN_32(0, 4); /* Currently 0, but reminder to 32-bit align if changing this */
    19801967    pCfg->uLength  = sizeof(VIRTIO_PCI_COMMON_CFG_T);
    19811968    cbRegion += pCfg->uLength;
     
    19961983    pCfg->uOffset  = pVirtioCC->pCommonCfgCap->uOffset + pVirtioCC->pCommonCfgCap->uLength;
    19971984    pCfg->uOffset  = RT_ALIGN_32(pCfg->uOffset, 4);
    1998 
    1999 
    20001985    pCfg->uLength  = VIRTQ_MAX_CNT * VIRTIO_NOTIFY_OFFSET_MULTIPLIER + 2;  /* will change in VirtIO 1.1 */
    20011986    cbRegion += pCfg->uLength;
  • trunk/src/VBox/Devices/VirtIO/VirtioCore.h

    r84882 r85016  
    9292{
    9393    uint32_t            u32Magic;                                /**< Magic value, VIRTQBUF_MAGIC.             */
     94    uint16_t            uVirtqNbr;                               /**< VirtIO index of associated virtq         */
     95    uint16_t            pad;
    9496    uint32_t volatile   cRefs;                                   /**< Reference counter.                       */
    9597    uint32_t            uHeadIdx;                                /**< Head idx of associated desc chain        */
     
    211213    uint16_t  uMsixConfig;                                       /**< RW (driver sets MSI-X config vector)      */
    212214    uint16_t  uNumVirtqs;                                        /**< RO (device specifies max queues)          */
    213     uint8_t   uDeviceStatus;                                     /**< RW (driver writes device status, 0=reset) */
     215    uint8_t   fDeviceStatus;                                     /**< RW (driver writes device status, 0=reset) */
    214216    uint8_t   uConfigGeneration;                                 /**< RO (device changes when changing configs) */
    215217
     
    270272    uint32_t                    uDriverFeaturesSelect;             /**< (MMIO) hi/lo select uDriverFeatures GUEST */
    271273    uint32_t                    uMsixConfig;                       /**< (MMIO) MSI-X vector                 GUEST */
    272     uint8_t                     uDeviceStatus;                     /**< (MMIO) Device Status                GUEST */
     274    uint8_t                     fDeviceStatus;                     /**< (MMIO) Device Status                GUEST */
    273275    uint8_t                     uPrevDeviceStatus;                 /**< (MMIO) Prev Device Status           GUEST */
    274276    uint8_t                     uConfigGeneration;                 /**< (MMIO) Device config sequencer       HOST */
     
    422424 * @returns VBox status code.
    423425 */
    424 int  virtioCoreR3VirtqAttach(PVIRTIOCORE pVirtio, uint16_t uVirtqNbr, const char *pcszName);
     426int  virtioCoreVirtqAttach(PVIRTIOCORE pVirtio, uint16_t uVirtqNbr, const char *pcszName);
    425427
    426428/**
     
    561563 * @retval  VERR_NOT_AVAILABLE   If the queue is empty.
    562564 */
    563 int  virtioCoreR3VirtqAvailBufGet(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t uVirtqNbr,
     565int virtioCoreR3VirtqAvailBufGet(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t uVirtqNbr,
    564566                                  uint16_t uHeadIdx, PPVIRTQBUF ppVirtqBuf);
    565567
     
    601603 *          caller must take care of that.
    602604 */
    603 int  virtioCoreR3VirtqUsedBufPut(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t uVirtqNbr, PRTSGBUF pSgVirtReturn,
     605int virtioCoreR3VirtqUsedBufPut(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t uVirtqNbr, PRTSGBUF pSgVirtReturn,
    604606                                 PVIRTQBUF pVirtqBuf, bool fFence);
    605 
    606607/**
    607608 * Advance index of avail ring to next entry in specified virtq (see virtioCoreR3VirtqAvailBufPeek())
     
    610611 * @param   uVirtqNbr    Index of queue
    611612 */
    612 int  virtioCoreR3VirtqAvailBufNext(PVIRTIOCORE pVirtio, uint16_t uVirtqNbr);
     613int virtioCoreR3VirtqAvailBufNext(PVIRTIOCORE pVirtio, uint16_t uVirtqNbr);
     614
     615/**
     616 * Add some bytes out of a virtq (s/g) buffer, converting them from virtual memory to GCPhys
     617 *
     618 * To be performant it is left to the caller to validate the size of the buffer with regard
     619 * to data being pulled from it to avoid underruns.
     620 *
     621 * @param   pVirtio     Pointer to the shared virtio state.
     622 * @param   pVirtqBuf   output: virtq buffer
     623 * @param   pv          input: virtual memory buffer to receive bytes
     624 * @param   cb          number of bytes to add to the s/g buffer.
     625 */
     626void virtioCoreR3VirqBufFill(PVIRTIOCORE pVirtio, PVIRTQBUF pVirtqBuf, void *pv, size_t cb);
     627
     628/**
     629 * Extract some bytes out of a virtq (s/g) buffer, converting them from GCPhys to virtual memory
     630 *
     631 * To be performant it is left to the caller to validate the size of the buffer with regard
     632 * to data being pulled from it to avoid underruns.
     633 *
     634 * @param   pVirtio     Pointer to the shared virtio state.
     635 * @param   pVirtqBuf   input: virtq buffer
     636 * @param   pv          output: virtual memory buffer to receive bytes
     637 * @param   cb          number of bytes to Drain from buffer
     638 */
     639void virtioCoreR3VirtqBufDrain(PVIRTIOCORE pVirtio, PVIRTQBUF pVirtqBuf, void *pv, size_t cb);
    613640
    614641/**
     
    778805void     virtioCoreGCPhysChainInit(PVIRTIOSGBUF pGcSgBuf, PVIRTIOSGSEG paSegs, size_t cSegs);
    779806void     virtioCoreGCPhysChainReset(PVIRTIOSGBUF pGcSgBuf);
    780 RTGCPHYS virtioCoreGCPhysChainGetNextSegment(PVIRTIOSGBUF pGcSgBuf, size_t *pcbSeg);
     807RTGCPHYS virtioCoreGCPhysChainGetNextSeg(PVIRTIOSGBUF pGcSgBuf, size_t *pcbSeg);
    781808RTGCPHYS virtioCoreGCPhysChainAdvance(PVIRTIOSGBUF pGcSgBuf, size_t cbAdvance);
    782809void     virtioCoreGCPhysChainInit(PVIRTIOSGBUF pSgBuf, PVIRTIOSGSEG paSegs, size_t cSegs);
     
    794821const char *virtioCoreGetStateChangeText(VIRTIOVMSTATECHANGED enmState);
    795822
     823/*
     824 * The following macros assist with handling/logging MMIO accesses to VirtIO dev-specific config area,
     825 * in a way that enhances code readability and debug logging consistency.
     826 *
     827 * cb, pv and fWrite are implicit parameters and must be defined by the invoker.
     828 */
     829
     830#ifdef LOG_ENABLED
     831
     832# define VIRTIO_DEV_CONFIG_LOG_ACCESS(member, tCfgStruct, uOffsetOfAccess) \
     833    if (LogIs7Enabled()) { \
     834        uint32_t uMbrOffset = uOffsetOfAccess - RT_UOFFSETOF(tCfgStruct, member); \
     835        uint32_t uMbrSize   = RT_SIZEOFMEMB(tCfgStruct, member); \
     836        virtioCoreLogMappedIoValue(__FUNCTION__, #member, uMbrSize, pv, cb, uMbrOffset, fWrite, false, 0); \
     837    }
     838
     839# define VIRTIO_DEV_CONFIG_LOG_INDEXED_ACCESS(member, tCfgStruct, uOffsetOfAccess, uIdx) \
     840    if (LogIs7Enabled()) { \
     841        uint32_t uMbrOffset = uOffsetOfAccess - RT_UOFFSETOF(tCfgStruct, member); \
     842        uint32_t uMbrSize   = RT_SIZEOFMEMB(tCfgStruct, member); \
     843        virtioCoreLogMappedIoValue(__FUNCTION__, #member, uMbrSize,  pv, cb, uMbrOffset, fWrite, true, uIdx); \
     844    }
     845#else
     846# define VIRTIO_DEV_CONFIG_LOG_ACCESS(member, tCfgStruct, uMbrOffset) do { } while (0)
     847# define VIRTIO_DEV_CONFIG_LOG_INDEXED_ACCESS(member, tCfgStruct, uMbrOffset, uIdx) do { } while (0)
     848#endif
     849
     850DECLINLINE(bool) virtioCoreMatchMember(uint32_t uOffset, uint32_t cb, uint32_t uMemberOff,
     851                                       size_t uMemberSize, bool fSubFieldMatch)
     852{
     853    /* Test for 8-byte field always (accessed as two 32-bit components) */
     854    if (uMemberSize == 8)
     855        return (cb == sizeof(uint32_t)) && (uOffset == uMemberOff || uOffset == (uMemberOff + sizeof(uint32_t)));
     856
     857    if (fSubFieldMatch)
     858        return (uOffset >= uMemberOff) && (cb <= uMemberSize - (uOffset - uMemberOff));
     859
     860    /* Test for exact match */
     861    return (uOffset == uMemberOff) && (cb == uMemberSize);
     862}
     863
     864/**
     865 * Yields boolean true if uOffsetOfAccess falls within bytes of specified member of config struct
     866 */
     867#define VIRTIO_DEV_CONFIG_SUBMATCH_MEMBER(member, tCfgStruct, uOffsetOfAccess) \
     868            virtioCoreMatchMember(uOffsetOfAccess, cb, \
     869                                  RT_UOFFSETOF(tCfgStruct, member),  \
     870                                  RT_SIZEOFMEMB(tCfgStruct, member), true /* fSubfieldMatch */)
     871
     872#define VIRTIO_DEV_CONFIG_MATCH_MEMBER(member, tCfgStruct, uOffsetOfAccess) \
     873            virtioCoreMatchMember(uOffsetOfAccess, cb, \
     874                                  RT_UOFFSETOF(tCfgStruct, member),  \
     875                                  RT_SIZEOFMEMB(tCfgStruct, member), false /* fSubfieldMatch */)
     876
     877/**
     878 * Copy reads or copy writes specified member field of config struct (based on fWrite),
     879 * the memory described by cb and pv.
     880 *
     881 * cb, pv and fWrite are implicit parameters and must be defined by the invoker.
     882 */
     883#define VIRTIO_DEV_CONFIG_ACCESS(member, tCfgStruct, uOffsetOfAccess, pCfgStruct) \
     884    do \
     885    { \
     886        uint32_t uOffsetInMember = uOffsetOfAccess - RT_UOFFSETOF(tCfgStruct, member); \
     887        if (fWrite) \
     888            memcpy(((char *)&(pCfgStruct)->member) + uOffsetInMember, pv, cb); \
     889        else \
     890            memcpy(pv, ((const char *)&(pCfgStruct)->member) + uOffsetInMember, cb); \
     891        VIRTIO_DEV_CONFIG_LOG_ACCESS(member, tCfgStruct, uOffsetOfAccess); \
     892    } while(0)
     893
     894/**
     895 * Copies bytes into memory described by cb, pv from the specified member field of the config struct.
     896 * The operation is a nop and logs error if implied parameter fWrite is true.
     897 *
     898 * cb, pv and fWrite are implicit parameters and must be defined by the invoker.
     899 */
     900#define VIRTIO_DEV_CONFIG_ACCESS_READONLY(member, tCfgStruct, uOffsetOfAccess, pCfgStruct) \
     901    do \
     902    { \
     903        uint32_t uOffsetInMember = uOffsetOfAccess - RT_UOFFSETOF(tCfgStruct, member); \
     904        if (fWrite) \
     905            LogFunc(("Guest attempted to write readonly virtio config struct (member %s)\n", #member)); \
     906        else \
     907        { \
     908            memcpy(pv, ((const char *)&(pCfgStruct)->member) + uOffsetInMember, cb); \
     909            VIRTIO_DEV_CONFIG_LOG_ACCESS(member, tCfgStruct, uOffsetOfAccess); \
     910        } \
     911    } while(0)
     912
     913/**
     914 * Copies into or out of specified member field of config struct (based on fWrite),
     915 * the memory described by cb and pv.
     916 *
     917 * cb, pv and fWrite are implicit parameters and must be defined by the invoker.
     918 */
     919#define VIRTIO_DEV_CONFIG_ACCESS_INDEXED(member, uIdx, tCfgStruct, uOffsetOfAccess, pCfgStruct) \
     920    do \
     921    { \
     922        uint32_t uOffsetInMember = uOffsetOfAccess - RT_UOFFSETOF(tCfgStruct, member); \
     923        if (fWrite) \
     924            memcpy(((char *)&(pCfgStruct)->member[uIdx]) + uOffsetInMember, pv, cb); \
     925        else \
     926            memcpy(pv, ((const char *)&(pCfgStruct)->member[uIdx]) + uOffsetInMember, cb); \
     927        VIRTIO_DEV_CONFIG_LOG_INDEXED_ACCESS(member, tCfgStruct, uOffsetOfAccess, uIdx); \
     928    } while(0)
     929
     930/**
     931 * Copies bytes into memory described by cb, pv from the specified member field of the config struct.
     932 * The operation is a nop and logs error if implied parameter fWrite is true.
     933 *
     934 * cb, pv and fWrite are implicit parameters and must be defined by the invoker.
     935 */
     936#define VIRTIO_DEV_CONFIG_ACCESS_INDEXED_READONLY(member, uidx, tCfgStruct, uOffsetOfAccess, pCfgStruct) \
     937    do \
     938    { \
     939        uint32_t uOffsetInMember = uOffsetOfAccess - RT_UOFFSETOF(tCfgStruct, member); \
     940        if (fWrite) \
     941            LogFunc(("Guest attempted to write readonly virtio config struct (member %s)\n", #member)); \
     942        else \
     943        { \
     944            memcpy(pv, ((const char *)&(pCfgStruct)->member[uIdx]) + uOffsetInMember, cb); \
     945            VIRTIO_DEV_CONFIG_LOG_INDEXED_ACCESS(member, tCfgStruct, uOffsetOfAccess, uIdx); \
     946        } \
     947    } while(0)
     948
    796949/** @} */
    797950
     951/** @name API for VirtIO parent device
     952 * @{ */
     953
    798954#endif /* !VBOX_INCLUDED_SRC_VirtIO_VirtioCore_h */
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