- Timestamp:
- Jul 1, 2020 5:28:16 AM (4 years ago)
- Location:
- trunk/src/VBox/Devices
- Files:
-
- 4 edited
-
Network/DevVirtioNet_1_0.cpp (modified) (30 diffs)
-
Storage/DevVirtioSCSI.cpp (modified) (8 diffs)
-
VirtIO/VirtioCore.cpp (modified) (48 diffs)
-
VirtIO/VirtioCore.h (modified) (9 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Network/DevVirtioNet_1_0.cpp
r84882 r85016 59 59 #include "VBoxDD.h" 60 60 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 \ 78 89 #define SET_LINK_UP(pState) \ 79 90 LogFunc(("SET_LINK_UP\n")); \ … … 86 97 virtioCoreNotifyConfigChanged(&pThis->Virtio) 87 98 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 100 102 101 103 #ifdef USING_CRITICAL_SECTION … … 183 185 * Structures and Typedefs * 184 186 *********************************************************************************************************************************/ 187 185 188 /** 186 189 * Virtio Net Host Device device-specific configuration (VirtIO 1.0, 5.1.4) … … 188 191 * MMIO accesses to device-specific configuration parameters. 189 192 */ 190 191 193 #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 */ 197 201 #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 */ 200 205 #endif 201 } VIRTIONET_CONFIG_T, PVIRTIONET_CONFIG_T; 206 207 } VIRTIONET_CONFIG_T, PVIRTIONET_CONFIG_T; 208 202 209 #pragma pack() 203 210 … … 770 777 #ifdef LOG_ENABLED 771 778 void virtioNetDumpGcPhysRxBuf(PPDMDEVINS pDevIns, PVIRTIONETPKTHDR pRxPktHdr, 772 uint16_t c Descs, 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) 773 780 { 774 781 PVIRTIONET pThis = PDMDEVINS_2_DATA(pDevIns, PVIRTIONET); 775 pRxPktHdr->uNumBuffers = c Descs;782 pRxPktHdr->uNumBuffers = cVirtqBufs; 776 783 if (pRxPktHdr) 777 784 { … … 916 923 pHlp->pfnPrintf(pHlp, " fMsiSupport ............... %d\n", pThis->Virtio.fMsiSupport); 917 924 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); 919 926 pHlp->pfnPrintf(pHlp, " cVirtqPairs .,............. %d\n", pThis->cVirtqPairs); 920 927 pHlp->pfnPrintf(pHlp, " cVirtVirtqs .,............. %d\n", pThis->cVirtVirtqs); … … 1011 1018 } 1012 1019 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) 1020 static int virtioNetR3CfgAccessed(PVIRTIONET pThis, uint32_t uOffsetOfAccess, void *pv, uint32_t cb, bool fWrite) 1064 1021 { 1065 1022 AssertReturn(pv && cb <= sizeof(uint32_t), fWrite ? VINF_SUCCESS : VINF_IOM_MMIO_UNUSED_00); 1066 1023 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); 1069 1026 #if FEATURE_OFFERED(STATUS) 1070 1027 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); 1073 1030 #endif 1074 1031 #if FEATURE_OFFERED(MQ) 1075 1032 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); 1078 1035 #endif 1079 1036 else 1080 1037 { 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)); 1082 1040 return fWrite ? VINF_SUCCESS : VINF_IOM_MMIO_UNUSED_00; 1083 1041 } … … 1085 1043 } 1086 1044 1087 #undef NET_CONFIG_ACCESSOR_READONLY1088 #undef NET_CONFIG_ACCESSOR1089 #undef LOG_ACCESSOR1090 #undef MATCH_NET_CONFIG1091 1092 1045 /** 1093 1046 * @callback_method_impl{VIRTIOCORER3,pfnDevCapRead} … … 1097 1050 PVIRTIONET pThis = PDMDEVINS_2_DATA(pDevIns, PVIRTIONET); 1098 1051 1099 LogFunc((" %s uOffset: %d, cb: %d\n", pThis->szInst, uOffset, cb));1052 LogFunc((" %s uOffset: %d, cb: %d\n", pThis->szInst, uOffset, cb)); 1100 1053 RT_NOREF(pThis); 1101 1054 return virtioNetR3CfgAccessed(PDMDEVINS_2_DATA(pDevIns, PVIRTIONET), uOffset, pv, cb, false /*fRead*/); … … 1545 1498 if (rc == VERR_TIMEOUT || rc == VERR_INTERRUPTED) 1546 1499 { 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")); 1548 1501 continue; 1549 1502 } … … 1662 1615 pszType = (char *)"Unicast"; 1663 1616 1664 LogFunc(("%s node(%RTmac %s%s), pkt(%RTmac %s) ",1617 LogFunc(("%s node(%RTmac %s%s), pkt(%RTmac %s)\n", 1665 1618 pThis->szInst, pThis->virtioNetConfig.uMacAddress.au8, 1666 1619 pThis->fPromiscuous ? "promiscuous" : "", … … 1735 1688 PVIRTIONETVIRTQ pRxVirtq) 1736 1689 { 1737 uint8_t fAddPktHdr = true;1738 1690 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) 1742 1696 { 1743 1697 PVIRTQBUF pVirtqBuf = NULL; … … 1761 1715 VERR_INTERNAL_ERROR); 1762 1716 1763 size_t cb DescChainLeft= pVirtqBuf->cbPhysReturn;1717 size_t cbBufRemaining = pVirtqBuf->cbPhysReturn; 1764 1718 uint8_t cbHdr = sizeof(VIRTIONETPKTHDR); 1765 1719 1766 1720 /* Fill the Guest Rx buffer with data received from the interface */ 1767 for (uint16_t cSegs = 0; uOffset < cb && cb DescChainLeft; )1721 for (uint16_t cSegs = 0; uOffset < cb && cbBufRemaining; ) 1768 1722 { 1769 1723 if (fAddPktHdr) … … 1773 1727 paVirtSegsToGuest[0].pvSeg = RTMemAlloc(cbHdr); 1774 1728 AssertReturn(paVirtSegsToGuest[0].pvSeg, VERR_NO_MEMORY); 1775 cb DescChainLeft-= cbHdr;1729 cbBufRemaining -= cbHdr; 1776 1730 1777 1731 memcpy(paVirtSegsToGuest[0].pvSeg, rxPktHdr, cbHdr); … … 1794 1748 1795 1749 /* Append remaining Rx pkt or as much current desc chain has room for */ 1796 size_t cb Cropped = RT_MIN(cb, cbDescChainLeft);1797 paVirtSegsToGuest[cSegs].cbSeg = cb Cropped;1750 size_t cbLimited = RT_MIN(cb, cbBufRemaining); 1751 paVirtSegsToGuest[cSegs].cbSeg = cbLimited; 1798 1752 paVirtSegsToGuest[cSegs].pvSeg = ((uint8_t *)pvBuf) + uOffset; 1799 cb DescChainLeft -= cbCropped;1800 uOffset += cbCropped;1801 c Descs++;1753 cbBufRemaining -= cbLimited; 1754 uOffset += cbLimited; 1755 cVirtqBufs++; 1802 1756 cSegs++; 1803 1757 RTSgBufInit(pVirtSegBufToGuest, paVirtSegsToGuest, cSegs); … … 1805 1759 STAM_PROFILE_START(&pThis->StatReceiveStore, a); 1806 1760 virtioCoreR3VirtqUsedBufPut(pDevIns, &pThis->Virtio, pRxVirtq->idx, 1807 pVirtSegBufToGuest, pVirtqBuf, true /* fFence */);1761 pVirtSegBufToGuest, pVirtqBuf, true /* fFence */); 1808 1762 STAM_PROFILE_STOP(&pThis->StatReceiveStore, a); 1809 1763 … … 1811 1765 break; 1812 1766 } 1813 1814 1767 virtioCoreR3VirtqBufRelease(&pThis->Virtio, pVirtqBuf); 1815 1768 } … … 1823 1776 /* Fix-up pkthdr (in guest phys. memory) with number buffers (descriptors) processed */ 1824 1777 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); 1829 1780 1830 1781 virtioCoreVirtqSyncUsedRing(pDevIns, &pThis->Virtio, pRxVirtq->idx); … … 1892 1843 } 1893 1844 1894 uint16_t cSegsAllocated = VIRTIONET_ PREALLOCATE_RX_SEG_COUNT;1845 uint16_t cSegsAllocated = VIRTIONET_RX_SEG_COUNT; 1895 1846 1896 1847 PRTSGBUF pVirtSegBufToGuest = (PRTSGBUF)RTMemAllocZ(sizeof(RTSGBUF)); … … 1998 1949 } 1999 1950 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 1952 static uint8_t virtioNetR3CtrlRx(PVIRTIONET pThis, PVIRTIONETCC pThisCC, 2021 1953 PVIRTIONET_CTRL_HDR_T pCtrlPktHdr, PVIRTQBUF pVirtqBuf) 2022 1954 { … … 2025 1957 2026 1958 LogFunc(("%s Processing CTRL Rx command\n", pThis->szInst)); 2027 RT_NOREF(pThis);2028 1959 switch(pCtrlPktHdr->uCmd) 2029 1960 { … … 2046 1977 2047 1978 uint8_t fOn, fPromiscChanged = false; 2048 virt qNetR3PullBytesFromVirtqBuf(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))); 2049 1980 2050 1981 switch(pCtrlPktHdr->uCmd) … … 2079 2010 2080 2011 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)); 2091 2013 2092 2014 return VIRTIONET_OK; 2093 2015 } 2094 2016 2095 static uint8_t virtioNetR3CtrlMac(PPDMDEVINS pDevIns, PVIRTIONET pThis, PVIRTIONETCC pThisCC, 2096 PVIRTIONET_CTRL_HDR_T pCtrlPktHdr, PVIRTQBUF pVirtqBuf) 2017 static uint8_t virtioNetR3CtrlMac(PVIRTIONET pThis, PVIRTIONET_CTRL_HDR_T pCtrlPktHdr, PVIRTQBUF pVirtqBuf) 2097 2018 { 2098 2019 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)2107 2020 2108 2021 AssertMsgReturn(pVirtqBuf->cbPhysSend >= sizeof(*pCtrlPktHdr), … … 2116 2029 { 2117 2030 /* 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)); 2120 2035 break; 2121 2036 } … … 2125 2040 2126 2041 /* 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 2129 2049 cbRemaining -= sizeof(cMacs); 2050 2130 2051 Log7Func(("%s Guest provided %d unicast MAC Table entries\n", pThis->szInst, cMacs)); 2052 2131 2053 if (cMacs) 2132 2054 { 2133 2055 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 2136 2063 cbRemaining -= cbMacs; 2137 2064 } … … 2139 2066 2140 2067 /* 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 2143 2074 cbRemaining -= sizeof(cMacs); 2075 2144 2076 Log10Func(("%s Guest provided %d multicast MAC Table entries\n", pThis->szInst, cMacs)); 2077 2078 2145 2079 if (cMacs) 2146 2080 { 2147 2081 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 2150 2089 cbRemaining -= cbMacs; 2151 2090 } … … 2166 2105 } 2167 2106 2168 static uint8_t virtioNetR3CtrlVlan(PPDMDEVINS pDevIns, PVIRTIONET pThis, PVIRTIONETCC pThisCC, 2169 PVIRTIONET_CTRL_HDR_T pCtrlPktHdr, PVIRTQBUF pVirtqBuf) 2107 static uint8_t virtioNetR3CtrlVlan(PVIRTIONET pThis, PVIRTIONET_CTRL_HDR_T pCtrlPktHdr, PVIRTQBUF pVirtqBuf) 2170 2108 { 2171 2109 LogFunc(("%s Processing CTRL VLAN command\n", pThis->szInst)); 2172 2173 RT_NOREF(pThisCC);2174 2110 2175 2111 uint16_t uVlanId; 2176 2112 size_t cbRemaining = pVirtqBuf->cbPhysSend - sizeof(*pCtrlPktHdr); 2113 2177 2114 AssertMsgReturn(cbRemaining > sizeof(uVlanId), 2178 2115 ("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 2180 2120 AssertMsgReturn(uVlanId > VIRTIONET_MAX_VLAN_ID, 2181 2121 ("%s VLAN ID out of range (VLAN ID=%u)\n", pThis->szInst, uVlanId), VIRTIONET_ERROR); 2122 2182 2123 LogFunc(("%s uCommand=%u VLAN ID=%u\n", pThis->szInst, pCtrlPktHdr->uCmd, uVlanId)); 2124 2183 2125 switch (pCtrlPktHdr->uCmd) 2184 2126 { … … 2221 2163 ("DESC chain too small for CTRL pkt header")); 2222 2164 2223 virt qNetR3PullBytesFromVirtqBuf(pDevIns, pThis, pVirtqBuf, pCtrlPktHdr,2165 virtioCoreR3VirtqBufDrain(&pThis->Virtio, pVirtqBuf, pCtrlPktHdr, 2224 2166 RT_MIN(pVirtqBuf->cbPhysSend, sizeof(VIRTIONET_CTRL_HDR_T))); 2225 2167 … … 2230 2172 { 2231 2173 case VIRTIONET_CTRL_RX: 2232 uAck = virtioNetR3CtrlRx(p DevIns, pThis, pThisCC, pCtrlPktHdr, pVirtqBuf);2174 uAck = virtioNetR3CtrlRx(pThis, pThisCC, pCtrlPktHdr, pVirtqBuf); 2233 2175 break; 2234 2176 case VIRTIONET_CTRL_MAC: 2235 uAck = virtioNetR3CtrlMac(p DevIns, pThis, pThisCC, pCtrlPktHdr, pVirtqBuf);2177 uAck = virtioNetR3CtrlMac(pThis, pCtrlPktHdr, pVirtqBuf); 2236 2178 break; 2237 2179 case VIRTIONET_CTRL_VLAN: 2238 uAck = virtioNetR3CtrlVlan(p DevIns, pThis, pThisCC, pCtrlPktHdr, pVirtqBuf);2180 uAck = virtioNetR3CtrlVlan(pThis, pCtrlPktHdr, pVirtqBuf); 2239 2181 break; 2240 2182 case VIRTIONET_CTRL_ANNOUNCE: … … 2917 2859 PVIRTIONETVIRTQ pVirtq = &pThis->aVirtqs[uVirtqNbr]; 2918 2860 pVirtq->idx = uVirtqNbr; 2919 (void) virtioCore R3VirtqAttach(&pThis->Virtio, pVirtq->idx, pVirtq->szName);2861 (void) virtioCoreVirtqAttach(&pThis->Virtio, pVirtq->idx, pVirtq->szName); 2920 2862 pVirtq->fAttachedToVirtioCore = true; 2921 2863 if (IS_VIRTQ_EMPTY(pThisCC->pDevIns, &pThis->Virtio, pVirtq->idx)) -
trunk/src/VBox/Devices/Storage/DevVirtioSCSI.cpp
r84876 r85016 164 164 { 165 165 // Device-writable part 166 uint32_t uEvent; /**< event */166 uint32_t uEvent; /**< event */ 167 167 uint8_t abVirtioLun[8]; /**< lun */ 168 168 uint32_t uReason; /**< reason */ … … 216 216 uint8_t uCdb[1]; /**< cdb */ 217 217 218 REQ_CMD_PI_T piHdr; /**< T10 Pi block integrity (optional feature) */218 REQ_CMD_PI_T piHdr; /**< T10 Pi block integrity (optional feature) */ 219 219 uint8_t uPiOut[1]; /**< pi_out[] T10 pi block integrity */ 220 220 uint8_t uDataOut[1]; /**< dataout */ … … 1182 1182 { 1183 1183 size_t cbSeg = cbReqHdr - offReq; 1184 RTGCPHYS GCPhys = virtioCoreGCPhysChainGetNextSeg ment(pVirtqBuf->pSgPhysSend, &cbSeg);1184 RTGCPHYS GCPhys = virtioCoreGCPhysChainGetNextSeg(pVirtqBuf->pSgPhysSend, &cbSeg); 1185 1185 PDMDevHlpPCIPhysReadMeta(pDevIns, GCPhys, &VirtqReq.ab[offReq], cbSeg); 1186 1186 offReq += cbSeg; … … 1345 1345 virtioScsiR3FreeReq(pTarget, pReq); 1346 1346 } 1347 1348 1347 return VINF_SUCCESS; 1349 1348 } … … 1371 1370 RT_ZERO(ScsiCtrlUnion); 1372 1371 1373 size_t const cb Ctrl= RT_MIN(pVirtqBuf->cbPhysSend, sizeof(VIRTIO_SCSI_CTRL_UNION_T));1374 for (size_t offCtrl = 0; offCtrl < cbCtrl; )1375 { 1376 size_t cbSeg = cb Ctrl - offCtrl;1377 RTGCPHYS GCPhys = virtioCoreGCPhysChainGetNextSeg ment(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; 1380 1379 } 1381 1380 … … 1591 1590 PVIRTQBUF pVirtqBuf; 1592 1591 int rc = virtioCoreR3VirtqAvailBufGet(pDevIns, &pThis->Virtio, uVirtqNbr, 1593 pWorkerR3->auRedoDescs[i], &pVirtqBuf);1592 pWorkerR3->auRedoDescs[i], &pVirtqBuf); 1594 1593 if (RT_FAILURE(rc)) 1595 1594 LogRel(("Error fetching desc chain to redo, %Rrc", rc)); … … 1780 1779 1781 1780 /** 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_T1788 * @result - true or false1789 */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_ENABLED1799 # define LOG_SCSI_CONFIG_ACCESSOR(member) \1800 virtioCoreLogMappedIoValue(__FUNCTION__, #member, RT_SIZEOFMEMB(VIRTIOSCSI_CONFIG_T, member), \1801 pv, cb, offIntra, fWrite, false, 0);1802 #else1803 # define LOG_SCSI_CONFIG_ACCESSOR(member) do { } while (0)1804 #endif1805 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 /**1831 1781 * Worker for virtioScsiR3DevCapWrite and virtioScsiR3DevCapRead. 1832 1782 */ 1833 static int virtioScsiR3CfgAccessed(PVIRTIOSCSI pThis, uint32_t offConfig, void *pv, uint32_t cb, bool fWrite)1783 static int virtioScsiR3CfgAccessed(PVIRTIOSCSI pThis, uint32_t uOffsetOfAccess, void *pv, uint32_t cb, bool fWrite) 1834 1784 { 1835 1785 AssertReturn(pv && cb <= sizeof(uint32_t), fWrite ? VINF_SUCCESS : VINF_IOM_MMIO_UNUSED_00); 1836 1786 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); 1839 1789 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); 1842 1792 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); 1845 1795 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); 1848 1798 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); 1851 1801 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); 1854 1804 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); 1857 1807 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); 1860 1810 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); 1863 1813 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); 1866 1816 else 1867 1817 { 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)); 1869 1819 return fWrite ? VINF_SUCCESS : VINF_IOM_MMIO_UNUSED_00; 1870 1820 } 1871 1821 return VINF_SUCCESS; 1872 1822 } 1873 1874 #undef SCSI_CONFIG_ACCESSOR_READONLY1875 #undef SCSI_CONFIG_ACCESSOR1876 #undef LOG_ACCESSOR1877 #undef MATCH_SCSI_CONFIG1878 1823 1879 1824 /** … … 2528 2473 for (uint16_t uVirtqNbr = 0; uVirtqNbr < VIRTIOSCSI_VIRTQ_CNT; uVirtqNbr++) 2529 2474 { 2530 rc = virtioCore R3VirtqAttach(&pThis->Virtio, uVirtqNbr, VIRTQNAME(uVirtqNbr));2475 rc = virtioCoreVirtqAttach(&pThis->Virtio, uVirtqNbr, VIRTQNAME(uVirtqNbr)); 2531 2476 if (RT_FAILURE(rc)) 2532 2477 continue; -
trunk/src/VBox/Devices/VirtIO/VirtioCore.cpp
r84882 r85016 44 44 #define INSTANCE(a_pVirtio) ((a_pVirtio)->szInstance) 45 45 #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) 47 47 #define IS_VIRTQ_EMPTY(pDevIns, pVirtio, pVirtqState) \ 48 48 (virtioCoreVirtqAvailBufCount(pDevIns, pVirtio, pVirtqState) == 0) … … 53 53 * @a a_LocCapData. 54 54 * 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 ) 64 65 65 66 … … 103 104 RT_FLEXIBLE_ARRAY_EXTENSION 104 105 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) */ 106 107 } VIRTQ_AVAIL_T, *PVIRTQ_AVAIL_T; 107 108 … … 118 119 RT_FLEXIBLE_ARRAY_EXTENSION 119 120 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) */ 121 122 } VIRTQ_USED_T, *PVIRTQ_USED_T; 122 123 … … 149 150 uint32_t idxDesc, PVIRTQ_DESC_T pDesc) 150 151 { 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")); 152 153 uint16_t const cVirtqItems = RT_MAX(pVirtio->uVirtqSize[uVirtqNbr], 1); /* Make sure to avoid div-by-zero. */ 153 154 PDMDevHlpPCIPhysRead(pDevIns, … … 164 165 { 165 166 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")); 167 168 uint16_t const cVirtqItems = RT_MAX(pVirtio->uVirtqSize[uVirtqNbr], 1); /* Make sure to avoid div-by-zero. */ 168 169 PDMDevHlpPCIPhysRead(pDevIns, … … 177 178 uint16_t uUsedEventIdx; 178 179 /* 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")); 180 181 PDMDevHlpPCIPhysRead(pDevIns, 181 182 pVirtio->aGCPhysVirtqAvail[uVirtqNbr] + RT_UOFFSETOF_DYN(VIRTQ_AVAIL_T, auRing[pVirtio->uVirtqSize[uVirtqNbr]]), … … 188 189 { 189 190 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")); 191 192 PDMDevHlpPCIPhysRead(pDevIns, 192 193 pVirtio->aGCPhysVirtqAvail[uVirtqNbr] + RT_UOFFSETOF(VIRTQ_AVAIL_T, uIdx), … … 198 199 { 199 200 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")); 201 202 PDMDevHlpPCIPhysRead(pDevIns, 202 203 pVirtio->aGCPhysVirtqAvail[uVirtqNbr] + RT_UOFFSETOF(VIRTQ_AVAIL_T, fFlags), … … 216 217 { 217 218 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")); 219 220 uint16_t const cVirtqItems = RT_MAX(pVirtio->uVirtqSize[uVirtqNbr], 1); /* Make sure to avoid div-by-zero. */ 220 221 PDMDevHlpPCIPhysWrite(pDevIns, … … 225 226 DECLINLINE(void) virtioWriteUsedRingFlags(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t uVirtqNbr, uint16_t fFlags) 226 227 { 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")); 228 229 RT_UNTRUSTED_VALIDATED_FENCE(); /* VirtIO 1.0, Section 3.2.1.4.1 */ 229 230 PDMDevHlpPCIPhysWrite(pDevIns, … … 235 236 DECLINLINE(void) virtioWriteUsedRingIdx(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t uVirtqNbr, uint16_t uIdx) 236 237 { 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")); 238 239 PDMDevHlpPCIPhysWrite(pDevIns, 239 240 pVirtio->aGCPhysVirtqUsed[uVirtqNbr] + RT_UOFFSETOF(VIRTQ_USED_T, uIdx), … … 247 248 { 248 249 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")); 250 251 PDMDevHlpPCIPhysRead(pDevIns, 251 252 pVirtio->aGCPhysVirtqUsed[uVirtqNbr] + RT_UOFFSETOF(VIRTQ_USED_T, uIdx), … … 257 258 { 258 259 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")); 260 261 PDMDevHlpPCIPhysRead(pDevIns, 261 262 pVirtio->aGCPhysVirtqUsed[uVirtqNbr] + RT_UOFFSETOF(VIRTQ_USED_T, fFlags), … … 267 268 { 268 269 /** 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")); 270 271 PDMDevHlpPCIPhysWrite(pDevIns, 271 272 pVirtio->aGCPhysVirtqUsed[uVirtqNbr] + RT_UOFFSETOF_DYN(VIRTQ_USED_T, aRing[pVirtio->uVirtqSize[uVirtqNbr]]), … … 415 416 } 416 417 417 RTGCPHYS virtioCoreGCPhysChainGetNextSeg ment(PVIRTIOSGBUF pGcSgBuf, size_t *pcbSeg)418 RTGCPHYS virtioCoreGCPhysChainGetNextSeg(PVIRTIOSGBUF pGcSgBuf, size_t *pcbSeg) 418 419 { 419 420 AssertReturn(pGcSgBuf, 0); … … 598 599 uValue.u = 0; 599 600 memcpy(uValue.au8, pv, cb); 600 Log6(("% s: Guest %s %s %#0*RX64\n",601 Log6(("%-23s: Guest %s %s %#0*RX64\n", 601 602 pszFunc, fWrite ? "wrote" : "read ", szDepiction, 2 + cb * 2, uValue.u)); 602 603 } 603 604 else /* odd number or oversized access, ... log inline hex-dump style */ 604 605 { 605 Log6(("% s: Guest %s %s%s[%d:%d]: %.*Rhxs\n",606 Log6(("%-23s: Guest %s %s%s[%d:%d]: %.*Rhxs\n", 606 607 pszFunc, fWrite ? "wrote" : "read ", pszMember, 607 608 szIdx, uOffset, uOffset + cb, cb, pv)); … … 610 611 } 611 612 612 613 613 /** 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 */ 617 DECLINLINE(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 662 int 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; 637 672 } 638 673 … … 646 681 PVIRTQSTATE pVirtqState = &pVirtio->aVirtqState[uVirtqNbr]; 647 682 648 /** @todo add ability to dump physical contents ofany 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) */ 649 684 // bool fDump = pszArgs && (*pszArgs == 'd' || *pszArgs == 'D'); /* "dump" (avail phys descriptor)" 650 685 … … 704 739 } 705 740 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); 707 742 pHlp->pfnPrintf(pHlp, " segs: .............. %d\n", cReturnSegs); 708 743 if (cReturnSegs) … … 717 752 } 718 753 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_RING3734 754 735 755 /** API Function: See header file */ … … 760 780 pVirtqBuf->cRefs = 1; 761 781 pVirtqBuf->uHeadIdx = uHeadIdx; 782 pVirtqBuf->uVirtqNbr = uVirtqNbr; 762 783 *ppVirtqBuf = pVirtqBuf; 763 784 … … 888 909 void virtioCoreVirtqEnableNotify(PVIRTIOCORE pVirtio, uint16_t uVirtqNbr, bool fEnable) 889 910 { 890 if (pVirtio-> uDeviceStatus & VIRTIO_STATUS_DRIVER_OK)911 if (pVirtio->fDeviceStatus & VIRTIO_STATUS_DRIVER_OK) 891 912 { 892 913 uint16_t fFlags = virtioReadUsedRingFlags(pVirtio->pDevInsR3, pVirtio, uVirtqNbr); … … 905 926 { 906 927 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) 909 930 { 910 931 pVirtio->fGenUpdatePending = true; … … 1019 1040 1020 1041 return VINF_SUCCESS; 1042 } 1043 1044 /** API function: See Header file */ 1045 void 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 */ 1065 void 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)); 1021 1081 } 1022 1082 … … 1184 1244 pVirtio->uDriverFeaturesSelect = 0; 1185 1245 pVirtio->uConfigGeneration = 0; 1186 pVirtio-> uDeviceStatus = 0;1246 pVirtio->fDeviceStatus = 0; 1187 1247 pVirtio->uISR = 0; 1188 1248 … … 1225 1285 * @returns VBox status code 1226 1286 * 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 offCfgThe common configuration capability offset.1232 * @param cb Number of bytes to read or write1233 * @param pv Pointer to location to write to or read from1287 * @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 1234 1294 */ 1235 1295 static 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; 1322 1299 int rc = VINF_SUCCESS; 1323 1300 uint64_t val; 1324 if ( MATCH_COMMON_CFG(uDeviceFeatures))1301 if (VIRTIO_DEV_CONFIG_MATCH_MEMBER(uDeviceFeatures, VIRTIO_PCI_COMMON_CFG_T, uOffsetOfAccess)) 1325 1302 { 1326 1303 if (fWrite) /* Guest WRITE pCommonCfg>uDeviceFeatures */ 1327 1304 { 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? */ 1330 1311 } 1331 1312 else /* Guest READ pCommonCfg->uDeviceFeatures */ … … 1336 1317 val = pVirtio->uDeviceFeatures & UINT32_C(0xffffffff); 1337 1318 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); 1339 1320 break; 1340 1321 case 1: 1341 1322 val = pVirtio->uDeviceFeatures >> 32; 1342 1323 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)); 1344 1325 break; 1345 1326 default: … … 1350 1331 } 1351 1332 } 1352 else if (MATCH_COMMON_CFG(uDriverFeatures)) 1333 else 1334 if (VIRTIO_DEV_CONFIG_MATCH_MEMBER(uDriverFeatures, VIRTIO_PCI_COMMON_CFG_T, uOffsetOfAccess)) 1353 1335 { 1354 1336 if (fWrite) /* Guest WRITE pCommonCfg->udriverFeatures */ … … 1358 1340 case 0: 1359 1341 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); 1361 1343 break; 1362 1344 case 1: 1363 1345 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)); 1365 1347 break; 1366 1348 default: … … 1370 1352 } 1371 1353 } 1372 else/* Guest READ pCommonCfg->udriverFeatures */1354 /* Guest READ pCommonCfg->udriverFeatures */ 1373 1355 { 1374 1356 switch (pVirtio->uDriverFeaturesSelect) … … 1377 1359 val = pVirtio->uDriverFeatures & 0xffffffff; 1378 1360 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); 1380 1362 break; 1381 1363 case 1: 1382 1364 val = (pVirtio->uDriverFeatures >> 32) & 0xffffffff; 1383 1365 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); 1385 1367 break; 1386 1368 default: … … 1391 1373 } 1392 1374 } 1393 else if (MATCH_COMMON_CFG(uNumVirtqs)) 1375 else 1376 if (VIRTIO_DEV_CONFIG_MATCH_MEMBER(uNumVirtqs, VIRTIO_PCI_COMMON_CFG_T, uOffsetOfAccess)) 1394 1377 { 1395 1378 if (fWrite) … … 1398 1381 return VINF_SUCCESS; 1399 1382 } 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 1412 1394 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 as1417 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_RING31421 if (fStatusChanged || fNewStatus == 0)1422 1395 { 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")); 1424 1409 return VINF_IOM_R3_MMIO_WRITE; 1410 #endif 1425 1411 } 1426 #endif1427 pVirtio->uDeviceStatus = fNewStatus;1428 1412 1429 1413 #ifdef IN_RING3 … … 1431 1415 * Notify client only if status actually changed from last time and when we're reset. 1432 1416 */ 1433 if ( pVirtio->uDeviceStatus == 0)1417 if (fDeviceReset) 1434 1418 virtioGuestR3WasReset(pDevIns, pVirtio, pVirtioCC); 1419 1435 1420 if (fStatusChanged) 1436 pVirtioCC->pfnStatusChanged(pVirtio, pVirtioCC, fNewStatus & VIRTIO_STATUS_DRIVER_OK);1421 pVirtioCC->pfnStatusChanged(pVirtio, pVirtioCC, pVirtio->fDeviceStatus & VIRTIO_STATUS_DRIVER_OK); 1437 1422 #endif 1438 1423 /* 1439 1424 * Save the current status for the next write so we can see what changed. 1440 1425 */ 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 1447 1432 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)); 1492 1480 return fWrite ? VINF_SUCCESS : VINF_IOM_MMIO_UNUSED_00; 1493 1481 } 1494 1482 1495 #undef COMMON_CFG_ACCESSOR_READONLY1496 #undef COMMON_CFG_ACCESSOR_INDEXED_READONLY1497 #undef COMMON_CFG_ACCESSOR_INDEXED1498 #undef COMMON_CFG_ACCESSOR1499 #undef LOG_COMMON_CFG_ACCESS_INDEXED1500 #undef LOG_COMMON_CFG_ACCESS1501 #undef MATCH_COMMON_CFG1502 1483 #ifndef IN_RING3 1503 1484 RT_NOREF(pDevIns, pVirtioCC); … … 1527 1508 { 1528 1509 #ifdef IN_RING3 1510 LogFunc(("IN_RING3\n")); 1529 1511 /* 1530 1512 * Callback to client to manage device-specific configuration. … … 1556 1538 return rcStrict; 1557 1539 #else 1540 Log7Func(("return VINF_IOM_R3_MMIO_READ\n")); 1558 1541 return VINF_IOM_R3_MMIO_READ; 1559 1542 #endif … … 1561 1544 1562 1545 if (MATCHES_VIRTIO_CAP_STRUCT(off, cb, uOffset, pVirtio->LocCommonCfgCap)) 1546 { 1547 #ifdef IN_RING3 1563 1548 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 } 1565 1553 if (MATCHES_VIRTIO_CAP_STRUCT(off, cb, uOffset, pVirtio->LocIsrCap) && cb == sizeof(uint8_t)) 1566 1554 { … … 1606 1594 1607 1595 if (MATCHES_VIRTIO_CAP_STRUCT(off, cb, uOffset, pVirtio->LocCommonCfgCap)) 1596 { 1597 #ifdef IN_RING3 1608 1598 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 } 1610 1603 if (MATCHES_VIRTIO_CAP_STRUCT(off, cb, uOffset, pVirtio->LocIsrCap) && cb == sizeof(uint8_t)) 1611 1604 { … … 1641 1634 RT_NOREF(pPciDev); 1642 1635 1643 Log7Func((" pDevIns=%p pPciDev=%p uAddress=%#xcb=%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)); 1645 1638 if (uAddress == pVirtio->uPciCfgDataOff) 1646 1639 { … … 1663 1656 1664 1657 VBOXSTRICTRC rcStrict = virtioMmioRead(pDevIns, pVirtio, pPciCap->uOffset, pu32Value, cb); 1665 Log 2Func(("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", 1666 1659 pPciCap->uBar, pPciCap->uOffset, uLength, *pu32Value, VBOXSTRICTRC_VAL(rcStrict))); 1667 1660 return rcStrict; … … 1680 1673 RT_NOREF(pPciDev); 1681 1674 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)); 1683 1676 if (uAddress == pVirtio->uPciCfgDataOff) 1684 1677 { … … 1726 1719 1727 1720 pHlp->pfnSSMPutBool(pSSM, pVirtio->fGenUpdatePending); 1728 pHlp->pfnSSMPutU8(pSSM, pVirtio-> uDeviceStatus);1721 pHlp->pfnSSMPutU8(pSSM, pVirtio->fDeviceStatus); 1729 1722 pHlp->pfnSSMPutU8(pSSM, pVirtio->uConfigGeneration); 1730 1723 pHlp->pfnSSMPutU8(pSSM, pVirtio->uPciCfgDataOff); … … 1784 1777 */ 1785 1778 pHlp->pfnSSMGetBool(pSSM, &pVirtio->fGenUpdatePending); 1786 pHlp->pfnSSMGetU8(pSSM, &pVirtio-> uDeviceStatus);1779 pHlp->pfnSSMGetU8(pSSM, &pVirtio->fDeviceStatus); 1787 1780 pHlp->pfnSSMGetU8(pSSM, &pVirtio->uConfigGeneration); 1788 1781 pHlp->pfnSSMGetU8(pSSM, &pVirtio->uPciCfgDataOff); … … 1920 1913 RTStrCopy(pVirtio->szInstance, sizeof(pVirtio->szInstance), pcszInstance); 1921 1914 1922 pVirtio-> uDeviceStatus = 0;1915 pVirtio->fDeviceStatus = 0; 1923 1916 pVirtioCC->cbDevSpecificCfg = cbDevSpecificCfg; 1924 1917 pVirtioCC->pbDevSpecificCfg = (uint8_t *)pvDevSpecificCfg; … … 1952 1945 /* Construct & map PCI vendor-specific capabilities for virtio host negotiation with guest driver */ 1953 1946 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, facilitating1956 * 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 */1960 1947 #define CFG_ADDR_2_IDX(addr) ((uint8_t)(((uintptr_t)(addr) - (uintptr_t)&pPciDev->abConfig[0]))) 1961 1948 #define SET_PCI_CAP_LOC(a_pPciDev, a_pCfg, a_LocCap, a_uMmioLengthAlign) \ … … 1977 1964 pCfg->uCapNext = CFG_ADDR_2_IDX(pCfg) + pCfg->uCapLen; 1978 1965 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 */ 1980 1967 pCfg->uLength = sizeof(VIRTIO_PCI_COMMON_CFG_T); 1981 1968 cbRegion += pCfg->uLength; … … 1996 1983 pCfg->uOffset = pVirtioCC->pCommonCfgCap->uOffset + pVirtioCC->pCommonCfgCap->uLength; 1997 1984 pCfg->uOffset = RT_ALIGN_32(pCfg->uOffset, 4); 1998 1999 2000 1985 pCfg->uLength = VIRTQ_MAX_CNT * VIRTIO_NOTIFY_OFFSET_MULTIPLIER + 2; /* will change in VirtIO 1.1 */ 2001 1986 cbRegion += pCfg->uLength; -
trunk/src/VBox/Devices/VirtIO/VirtioCore.h
r84882 r85016 92 92 { 93 93 uint32_t u32Magic; /**< Magic value, VIRTQBUF_MAGIC. */ 94 uint16_t uVirtqNbr; /**< VirtIO index of associated virtq */ 95 uint16_t pad; 94 96 uint32_t volatile cRefs; /**< Reference counter. */ 95 97 uint32_t uHeadIdx; /**< Head idx of associated desc chain */ … … 211 213 uint16_t uMsixConfig; /**< RW (driver sets MSI-X config vector) */ 212 214 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) */ 214 216 uint8_t uConfigGeneration; /**< RO (device changes when changing configs) */ 215 217 … … 270 272 uint32_t uDriverFeaturesSelect; /**< (MMIO) hi/lo select uDriverFeatures GUEST */ 271 273 uint32_t uMsixConfig; /**< (MMIO) MSI-X vector GUEST */ 272 uint8_t uDeviceStatus; /**< (MMIO) Device Status GUEST */274 uint8_t fDeviceStatus; /**< (MMIO) Device Status GUEST */ 273 275 uint8_t uPrevDeviceStatus; /**< (MMIO) Prev Device Status GUEST */ 274 276 uint8_t uConfigGeneration; /**< (MMIO) Device config sequencer HOST */ … … 422 424 * @returns VBox status code. 423 425 */ 424 int virtioCore R3VirtqAttach(PVIRTIOCORE pVirtio, uint16_t uVirtqNbr, const char *pcszName);426 int virtioCoreVirtqAttach(PVIRTIOCORE pVirtio, uint16_t uVirtqNbr, const char *pcszName); 425 427 426 428 /** … … 561 563 * @retval VERR_NOT_AVAILABLE If the queue is empty. 562 564 */ 563 int virtioCoreR3VirtqAvailBufGet(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t uVirtqNbr,565 int virtioCoreR3VirtqAvailBufGet(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t uVirtqNbr, 564 566 uint16_t uHeadIdx, PPVIRTQBUF ppVirtqBuf); 565 567 … … 601 603 * caller must take care of that. 602 604 */ 603 int virtioCoreR3VirtqUsedBufPut(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t uVirtqNbr, PRTSGBUF pSgVirtReturn,605 int virtioCoreR3VirtqUsedBufPut(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t uVirtqNbr, PRTSGBUF pSgVirtReturn, 604 606 PVIRTQBUF pVirtqBuf, bool fFence); 605 606 607 /** 607 608 * Advance index of avail ring to next entry in specified virtq (see virtioCoreR3VirtqAvailBufPeek()) … … 610 611 * @param uVirtqNbr Index of queue 611 612 */ 612 int virtioCoreR3VirtqAvailBufNext(PVIRTIOCORE pVirtio, uint16_t uVirtqNbr); 613 int 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 */ 626 void 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 */ 639 void virtioCoreR3VirtqBufDrain(PVIRTIOCORE pVirtio, PVIRTQBUF pVirtqBuf, void *pv, size_t cb); 613 640 614 641 /** … … 778 805 void virtioCoreGCPhysChainInit(PVIRTIOSGBUF pGcSgBuf, PVIRTIOSGSEG paSegs, size_t cSegs); 779 806 void virtioCoreGCPhysChainReset(PVIRTIOSGBUF pGcSgBuf); 780 RTGCPHYS virtioCoreGCPhysChainGetNextSeg ment(PVIRTIOSGBUF pGcSgBuf, size_t *pcbSeg);807 RTGCPHYS virtioCoreGCPhysChainGetNextSeg(PVIRTIOSGBUF pGcSgBuf, size_t *pcbSeg); 781 808 RTGCPHYS virtioCoreGCPhysChainAdvance(PVIRTIOSGBUF pGcSgBuf, size_t cbAdvance); 782 809 void virtioCoreGCPhysChainInit(PVIRTIOSGBUF pSgBuf, PVIRTIOSGSEG paSegs, size_t cSegs); … … 794 821 const char *virtioCoreGetStateChangeText(VIRTIOVMSTATECHANGED enmState); 795 822 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 850 DECLINLINE(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 796 949 /** @} */ 797 950 951 /** @name API for VirtIO parent device 952 * @{ */ 953 798 954 #endif /* !VBOX_INCLUDED_SRC_VirtIO_VirtioCore_h */
Note:
See TracChangeset
for help on using the changeset viewer.

