Changeset 85109 in vbox for trunk/src/VBox/Devices/VirtIO
- Timestamp:
- Jul 8, 2020 2:03:45 PM (5 years ago)
- Location:
- trunk/src/VBox/Devices/VirtIO
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/VirtIO/VirtioCore.cpp
r85054 r85109 43 43 *********************************************************************************************************************************/ 44 44 #define INSTANCE(a_pVirtio) ((a_pVirtio)->szInstance) 45 #define VIRTQNAME(a_pVirtio, a_uVirtqNbr) ((a_pVirtio)->aVirtqState[(a_uVirtqNbr)].szVirtqName) 45 #define VIRTQNAME(a_pVirtio, a_uVirtq) ((a_pVirtio)->aVirtqueues[(a_uVirtq)].szName) 46 46 47 #define IS_DRIVER_OK(a_pVirtio) ((a_pVirtio)->fDeviceStatus & VIRTIO_STATUS_DRIVER_OK) 47 #define IS_VIRTQ_EMPTY(pDevIns, pVirtio, pVirtq State) \48 (virtioCoreVirtqAvailBufCount (pDevIns, pVirtio, pVirtqState) == 0)48 #define IS_VIRTQ_EMPTY(pDevIns, pVirtio, pVirtq) \ 49 (virtioCoreVirtqAvailBufCount_inline(pDevIns, pVirtio, pVirtq) == 0) 49 50 50 51 /** … … 53 54 * @a a_LocCapData. 54 55 * 55 *56 *57 56 * @param[in] a_offAccess Input: The offset into the MMIO bar of the access. 58 57 * @param[in] a_cbAccess Input: The access size. … … 78 77 /** @name virtq related flags 79 78 * @{ */ 80 #define VIRTQ _DESC_F_NEXT 1 /**< Indicates this descriptor chains to next */81 #define VIRTQ _DESC_F_WRITE 2 /**< Marks buffer as write-only (default ro) */82 #define VIRTQ _DESC_F_INDIRECT 4 /**< Buffer is list of buffer descriptors */83 84 #define VIRTQ _USED_F_NO_NOTIFY 1 /**< Dev to Drv: Don't notify when buf added */85 #define VIRTQ _AVAIL_F_NO_INTERRUPT 1 /**< Drv to Dev: Don't notify when buf eaten */79 #define VIRTQUEUE_DESC_F_NEXT 1 /**< Indicates this descriptor chains to next */ 80 #define VIRTQUEUE_DESC_F_WRITE 2 /**< Marks buffer as write-only (default ro) */ 81 #define VIRTQUEUE_DESC_F_INDIRECT 4 /**< Buffer is list of buffer descriptors */ 82 83 #define VIRTQUEUE_USED_F_NO_NOTIFY 1 /**< Dev to Drv: Don't notify when buf added */ 84 #define VIRTQUEUE_AVAIL_F_NO_INTERRUPT 1 /**< Drv to Dev: Don't notify when buf eaten */ 86 85 /** @} */ 87 86 … … 96 95 uint16_t fFlags; /**< flags Buffer specific flags */ 97 96 uint16_t uDescIdxNext; /**< next Idx set if VIRTIO_DESC_F_NEXT */ 98 } VIRTQ _DESC_T, *PVIRTQ_DESC_T;97 } VIRTQUEUE_DESC_T, *PVIRTQUEUE_DESC_T; 99 98 100 99 typedef struct virtq_avail … … 104 103 RT_FLEXIBLE_ARRAY_EXTENSION 105 104 uint16_t auRing[RT_FLEXIBLE_ARRAY]; /**< ring Ring: avail drv to dev bufs */ 106 //uint16_t uUsedEventIdx; /**< used_event (if VIRTQ _USED_F_EVENT_IDX) */107 } VIRTQ _AVAIL_T, *PVIRTQ_AVAIL_T;105 //uint16_t uUsedEventIdx; /**< used_event (if VIRTQUEUE_USED_F_EVENT_IDX) */ 106 } VIRTQUEUE_AVAIL_T, *PVIRTQUEUE_AVAIL_T; 108 107 109 108 typedef struct virtq_used_elem … … 111 110 uint32_t uDescIdx; /**< idx Start of used desc chain */ 112 111 uint32_t cbElem; /**< len Total len of used desc chain */ 113 } VIRTQ _USED_ELEM_T;112 } VIRTQUEUE_USED_ELEM_T; 114 113 115 114 typedef struct virt_used … … 118 117 uint16_t uIdx; /**< idx Index of next ring slot */ 119 118 RT_FLEXIBLE_ARRAY_EXTENSION 120 VIRTQ _USED_ELEM_T aRing[RT_FLEXIBLE_ARRAY]; /**< ring Ring: used dev to drv bufs */121 //uint16_t uAvailEventIdx; /**< avail_event if (VIRTQ _USED_F_EVENT_IDX) */122 } VIRTQ _USED_T, *PVIRTQ_USED_T;119 VIRTQUEUE_USED_ELEM_T aRing[RT_FLEXIBLE_ARRAY]; /**< ring Ring: used dev to drv bufs */ 120 //uint16_t uAvailEventIdx; /**< avail_event if (VIRTQUEUE_USED_F_EVENT_IDX) */ 121 } VIRTQUEUE_USED_T, *PVIRTQUEUE_USED_T; 123 122 124 123 … … 137 136 /* Internal Functions */ 138 137 139 static void virtioCoreNotifyGuestDriver(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t uVirtq Nbr);138 static void virtioCoreNotifyGuestDriver(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t uVirtq); 140 139 static int virtioKick(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint8_t uCause, uint16_t uVec); 141 140 … … 147 146 */ 148 147 #ifdef IN_RING3 149 DECLINLINE(void) virtioReadDesc(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t uVirtqNbr,150 uint32_t idxDesc, PVIRTQ _DESC_T pDesc)148 DECLINLINE(void) virtioReadDesc(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, PVIRTQUEUE pVirtq, 149 uint32_t idxDesc, PVIRTQUEUE_DESC_T pDesc) 151 150 { 152 151 AssertMsg(pVirtio->fDeviceStatus & VIRTIO_STATUS_DRIVER_OK, ("Called with guest driver not ready\n")); 153 uint16_t const cVirtqItems = RT_MAX(pVirtio->uVirtqSize[uVirtqNbr], 1); /* Make sure to avoid div-by-zero. */ 152 RT_NOREF(pVirtio); 153 uint16_t const cVirtqItems = RT_MAX(pVirtq->uSize, 1); /* Make sure to avoid div-by-zero. */ 154 154 PDMDevHlpPCIPhysRead(pDevIns, 155 pVirt io->aGCPhysVirtqDesc[uVirtqNbr] + sizeof(VIRTQ_DESC_T) * (idxDesc % cVirtqItems),156 pDesc, sizeof(VIRTQ _DESC_T));155 pVirtq->GCPhysVirtqDesc + sizeof(VIRTQUEUE_DESC_T) * (idxDesc % cVirtqItems), 156 pDesc, sizeof(VIRTQUEUE_DESC_T)); 157 157 } 158 158 #endif … … 162 162 */ 163 163 #ifdef IN_RING3 164 DECLINLINE(uint16_t) virtioReadAvailDescIdx(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t uVirtqNbr, uint32_t availIdx)164 DECLINLINE(uint16_t) virtioReadAvailDescIdx(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, PVIRTQUEUE pVirtq, uint32_t availIdx) 165 165 { 166 166 uint16_t uDescIdx; 167 167 AssertMsg(pVirtio->fDeviceStatus & VIRTIO_STATUS_DRIVER_OK, ("Called with guest driver not ready\n")); 168 uint16_t const cVirtqItems = RT_MAX(pVirtio->uVirtqSize[uVirtqNbr], 1); /* Make sure to avoid div-by-zero. */ 168 RT_NOREF(pVirtio); 169 uint16_t const cVirtqItems = RT_MAX(pVirtq->uSize, 1); /* Make sure to avoid div-by-zero. */ 169 170 PDMDevHlpPCIPhysRead(pDevIns, 170 pVirtio->aGCPhysVirtqAvail[uVirtqNbr] 171 + RT_UOFFSETOF_DYN(VIRTQ_AVAIL_T, auRing[availIdx % cVirtqItems]), 172 &uDescIdx, sizeof(uDescIdx)); 171 pVirtq->GCPhysVirtqAvail + RT_UOFFSETOF_DYN(VIRTQUEUE_AVAIL_T, auRing[availIdx % cVirtqItems]), 172 &uDescIdx, sizeof(uDescIdx)); 173 173 return uDescIdx; 174 174 } 175 175 176 DECLINLINE(uint16_t) virtioReadAvailUsedEvent(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t uVirtqNbr)176 DECLINLINE(uint16_t) virtioReadAvailUsedEvent(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, PVIRTQUEUE pVirtq) 177 177 { 178 178 uint16_t uUsedEventIdx; 179 179 /* VirtIO 1.0 uUsedEventIdx (used_event) immediately follows ring */ 180 180 AssertMsg(pVirtio->fDeviceStatus & VIRTIO_STATUS_DRIVER_OK, ("Called with guest driver not ready\n")); 181 RT_NOREF(pVirtio); 181 182 PDMDevHlpPCIPhysRead(pDevIns, 182 pVirtio->aGCPhysVirtqAvail[uVirtqNbr] + RT_UOFFSETOF_DYN(VIRTQ_AVAIL_T, auRing[pVirtio->uVirtqSize[uVirtqNbr]]),183 &uUsedEventIdx, sizeof(uUsedEventIdx));183 pVirtq->GCPhysVirtqAvail + RT_UOFFSETOF_DYN(VIRTQUEUE_AVAIL_T, auRing[pVirtq->uSize]), 184 &uUsedEventIdx, sizeof(uUsedEventIdx)); 184 185 return uUsedEventIdx; 185 186 } 186 187 #endif 187 188 188 DECLINLINE(uint16_t) virtioReadAvailRingIdx(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t uVirtqNbr)189 DECLINLINE(uint16_t) virtioReadAvailRingIdx(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, PVIRTQUEUE pVirtq) 189 190 { 190 191 uint16_t uIdx = 0; 191 192 AssertMsg(pVirtio->fDeviceStatus & VIRTIO_STATUS_DRIVER_OK, ("Called with guest driver not ready\n")); 193 RT_NOREF(pVirtio); 192 194 PDMDevHlpPCIPhysRead(pDevIns, 193 pVirtio->aGCPhysVirtqAvail[uVirtqNbr] + RT_UOFFSETOF(VIRTQ_AVAIL_T, uIdx),194 &uIdx, sizeof(uIdx));195 pVirtq->GCPhysVirtqAvail + RT_UOFFSETOF(VIRTQUEUE_AVAIL_T, uIdx), 196 &uIdx, sizeof(uIdx)); 195 197 return uIdx; 196 198 } 197 199 198 DECLINLINE(uint16_t) virtioReadAvailRingFlags(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t uVirtqNbr)200 DECLINLINE(uint16_t) virtioReadAvailRingFlags(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, PVIRTQUEUE pVirtq) 199 201 { 200 202 uint16_t fFlags = 0; 201 203 AssertMsg(pVirtio->fDeviceStatus & VIRTIO_STATUS_DRIVER_OK, ("Called with guest driver not ready\n")); 204 RT_NOREF(pVirtio); 202 205 PDMDevHlpPCIPhysRead(pDevIns, 203 pVirtio->aGCPhysVirtqAvail[uVirtqNbr] + RT_UOFFSETOF(VIRTQ_AVAIL_T, fFlags),204 &fFlags, sizeof(fFlags));206 pVirtq->GCPhysVirtqAvail + RT_UOFFSETOF(VIRTQUEUE_AVAIL_T, fFlags), 207 &fFlags, sizeof(fFlags)); 205 208 return fFlags; 206 209 } … … 213 216 214 217 #ifdef IN_RING3 215 DECLINLINE(void) virtioWriteUsedElem(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t uVirtqNbr,218 DECLINLINE(void) virtioWriteUsedElem(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, PVIRTQUEUE pVirtq, 216 219 uint32_t usedIdx, uint32_t uDescIdx, uint32_t uLen) 217 220 { 218 VIRTQ _USED_ELEM_T elem = { uDescIdx, uLen };221 VIRTQUEUE_USED_ELEM_T elem = { uDescIdx, uLen }; 219 222 AssertMsg(pVirtio->fDeviceStatus & VIRTIO_STATUS_DRIVER_OK, ("Called with guest driver not ready\n")); 220 uint16_t const cVirtqItems = RT_MAX(pVirtio->uVirtqSize[uVirtqNbr], 1); /* Make sure to avoid div-by-zero. */ 223 RT_NOREF(pVirtio); 224 uint16_t const cVirtqItems = RT_MAX(pVirtq->uSize, 1); /* Make sure to avoid div-by-zero. */ 221 225 PDMDevHlpPCIPhysWrite(pDevIns, 222 pVirtio->aGCPhysVirtqUsed[uVirtqNbr] + RT_UOFFSETOF_DYN(VIRTQ_USED_T, aRing[usedIdx % cVirtqItems]), 226 pVirtq->GCPhysVirtqUsed 227 + RT_UOFFSETOF_DYN(VIRTQUEUE_USED_T, aRing[usedIdx % cVirtqItems]), 223 228 &elem, sizeof(elem)); 224 229 } 225 230 226 DECLINLINE(void) virtioWriteUsedRingFlags(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t uVirtqNbr, uint16_t fFlags)231 DECLINLINE(void) virtioWriteUsedRingFlags(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, PVIRTQUEUE pVirtq, uint16_t fFlags) 227 232 { 228 233 AssertMsg(pVirtio->fDeviceStatus & VIRTIO_STATUS_DRIVER_OK, ("Called with guest driver not ready\n")); 234 RT_NOREF(pVirtio); 229 235 RT_UNTRUSTED_VALIDATED_FENCE(); /* VirtIO 1.0, Section 3.2.1.4.1 */ 230 236 PDMDevHlpPCIPhysWrite(pDevIns, 231 pVirt io->aGCPhysVirtqUsed[uVirtqNbr] + RT_UOFFSETOF(VIRTQ_USED_T, fFlags),237 pVirtq->GCPhysVirtqUsed + RT_UOFFSETOF(VIRTQUEUE_USED_T, fFlags), 232 238 &fFlags, sizeof(fFlags)); 233 239 } 234 240 #endif 235 241 236 DECLINLINE(void) virtioWriteUsedRingIdx(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t uVirtqNbr, uint16_t uIdx)242 DECLINLINE(void) virtioWriteUsedRingIdx(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, PVIRTQUEUE pVirtq, uint16_t uIdx) 237 243 { 238 244 AssertMsg(pVirtio->fDeviceStatus & VIRTIO_STATUS_DRIVER_OK, ("Called with guest driver not ready\n")); 245 RT_NOREF(pVirtio); 239 246 PDMDevHlpPCIPhysWrite(pDevIns, 240 pVirt io->aGCPhysVirtqUsed[uVirtqNbr] + RT_UOFFSETOF(VIRTQ_USED_T, uIdx),247 pVirtq->GCPhysVirtqUsed + RT_UOFFSETOF(VIRTQUEUE_USED_T, uIdx), 241 248 &uIdx, sizeof(uIdx)); 242 249 } … … 244 251 245 252 #ifdef IN_RING3 246 DECLINLINE(uint16_t) virtioReadUsedRingIdx(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t uVirtqNbr)253 DECLINLINE(uint16_t) virtioReadUsedRingIdx(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, PVIRTQUEUE pVirtq) 247 254 { 248 255 uint16_t uIdx = 0; 249 256 AssertMsg(pVirtio->fDeviceStatus & VIRTIO_STATUS_DRIVER_OK, ("Called with guest driver not ready\n")); 257 RT_NOREF(pVirtio); 250 258 PDMDevHlpPCIPhysRead(pDevIns, 251 pVirtio->aGCPhysVirtqUsed[uVirtqNbr] + RT_UOFFSETOF(VIRTQ_USED_T, uIdx),252 &uIdx, sizeof(uIdx));259 pVirtq->GCPhysVirtqUsed + RT_UOFFSETOF(VIRTQUEUE_USED_T, uIdx), 260 &uIdx, sizeof(uIdx)); 253 261 return uIdx; 254 262 } 255 263 256 DECLINLINE(uint16_t) virtioReadUsedRingFlags(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t uVirtqNbr)264 DECLINLINE(uint16_t) virtioReadUsedRingFlags(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, PVIRTQUEUE pVirtq) 257 265 { 258 266 uint16_t fFlags = 0; 259 267 AssertMsg(pVirtio->fDeviceStatus & VIRTIO_STATUS_DRIVER_OK, ("Called with guest driver not ready\n")); 268 RT_NOREF(pVirtio); 260 269 PDMDevHlpPCIPhysRead(pDevIns, 261 pVirtio->aGCPhysVirtqUsed[uVirtqNbr] + RT_UOFFSETOF(VIRTQ_USED_T, fFlags),262 &fFlags, sizeof(fFlags));270 pVirtq->GCPhysVirtqUsed + RT_UOFFSETOF(VIRTQUEUE_USED_T, fFlags), 271 &fFlags, sizeof(fFlags)); 263 272 return fFlags; 264 273 } 265 274 266 DECLINLINE(void) virtioWriteUsedAvailEvent(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t uVirtqNbr, uint32_t uAvailEventIdx)275 DECLINLINE(void) virtioWriteUsedAvailEvent(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, PVIRTQUEUE pVirtq, uint32_t uAvailEventIdx) 267 276 { 268 277 /** VirtIO 1.0 uAvailEventIdx (avail_event) immediately follows ring */ 269 278 AssertMsg(pVirtio->fDeviceStatus & VIRTIO_STATUS_DRIVER_OK, ("Called with guest driver not ready\n")); 279 RT_NOREF(pVirtio); 270 280 PDMDevHlpPCIPhysWrite(pDevIns, 271 pVirtio->aGCPhysVirtqUsed[uVirtqNbr] + RT_UOFFSETOF_DYN(VIRTQ_USED_T, aRing[pVirtio->uVirtqSize[uVirtqNbr]]), 281 pVirtq->GCPhysVirtqUsed 282 + RT_UOFFSETOF_DYN(VIRTQUEUE_USED_T, aRing[pVirtq->uSize]), 272 283 &uAvailEventIdx, sizeof(uAvailEventIdx)); 273 284 } 274 285 #endif 275 286 276 DECLINLINE(uint16_t) virtioCoreVirtqAvailBufCount (PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, PVIRTQSTATE pVirtqState)277 { 278 uint16_t uIdx = virtioReadAvailRingIdx(pDevIns, pVirtio, pVirtq State->uVirtqNbr);279 uint16_t uShadow = pVirtq State->uAvailIdxShadow;287 DECLINLINE(uint16_t) virtioCoreVirtqAvailBufCount_inline(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, PVIRTQUEUE pVirtq) 288 { 289 uint16_t uIdx = virtioReadAvailRingIdx(pDevIns, pVirtio, pVirtq); 290 uint16_t uShadow = pVirtq->uAvailIdxShadow; 280 291 281 292 uint16_t uDelta; … … 286 297 287 298 LogFunc(("%s has %u %s (idx=%u shadow=%u)\n", 288 VIRTQNAME(pVirtio, pVirtqState->uVirtqNbr), uDelta, uDelta == 1 ? "entry" : "entries",299 pVirtq->szName, uDelta, uDelta == 1 ? "entry" : "entries", 289 300 uIdx, uShadow)); 290 301 … … 296 307 * @param pDevIns The device instance. 297 308 * @param pVirtio Pointer to the shared virtio state. 298 * @param uVirtq NbrVirtq number309 * @param uVirtq Virtq number 299 310 * 300 311 * @returns how many entries have been added to ring as a delta of the consumer's 301 312 * avail index and the queue's guest-side current avail index. 302 313 */ 303 uint16_t virtioCoreVirtqAvailBufCount(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t uVirtqNbr) 304 { 305 if (!IS_DRIVER_OK(pVirtio) || !pVirtio->uVirtqEnable[uVirtqNbr]) 314 uint16_t virtioCoreVirtqAvailBufCount(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t uVirtq) 315 { 316 AssertMsgReturn(uVirtq < RT_ELEMENTS(pVirtio->aVirtqueues), ("uVirtq out of range"), 0); 317 PVIRTQUEUE pVirtq = &pVirtio->aVirtqueues[uVirtq]; 318 if (!IS_DRIVER_OK(pVirtio) || !pVirtq->uEnable) 306 319 { 307 320 LogRelFunc(("Driver not ready or queue not enabled\n")); 308 321 return 0; 309 322 } 310 return virtioCoreVirtqAvailBufCount(pDevIns, pVirtio, &pVirtio->aVirtqState[uVirtqNbr]); 323 324 return virtioCoreVirtqAvailBufCount_inline(pDevIns, pVirtio, pVirtq); 311 325 } 312 326 … … 444 458 } const s_aFeatures[] = 445 459 { 446 { VIRTIO_F_RING_INDIRECT_DESC, " RING_INDIRECT_DESC Driver can use descriptors with VIRTQ _DESC_F_INDIRECT flag set\n" },460 { VIRTIO_F_RING_INDIRECT_DESC, " RING_INDIRECT_DESC Driver can use descriptors with VIRTQUEUE_DESC_F_INDIRECT flag set\n" }, 447 461 { VIRTIO_F_RING_EVENT_IDX, " RING_EVENT_IDX Enables use_event and avail_event fields described in 2.4.7, 2.4.8\n" }, 448 462 { VIRTIO_F_VERSION_1, " VERSION Used to detect legacy drivers.\n" }, … … 659 673 #ifdef IN_RING3 660 674 661 int virtioCoreR3VirtqAttach(PVIRTIOCORE pVirtio, uint16_t uVirtq Nbr, const char *pcszName)675 int virtioCoreR3VirtqAttach(PVIRTIOCORE pVirtio, uint16_t uVirtq, const char *pcszName) 662 676 { 663 677 LogFunc(("%s\n", pcszName)); 664 PVIRTQ STATE pVirtqState = &pVirtio->aVirtqState[uVirtqNbr];665 pVirtq State->uVirtqNbr = uVirtqNbr;666 pVirtq State->uAvailIdxShadow = 0;667 pVirtq State->uUsedIdxShadow = 0;668 pVirtq State->fVirtqRingEventThreshold= false;669 RTStrCopy(pVirtq State->szVirtqName, sizeof(pVirtqState->szVirtqName), pcszName);678 PVIRTQUEUE pVirtq = &pVirtio->aVirtqueues[uVirtq]; 679 pVirtq->uVirtq = uVirtq; 680 pVirtq->uAvailIdxShadow = 0; 681 pVirtq->uUsedIdxShadow = 0; 682 pVirtq->fUsedRingEvent = false; 683 RTStrCopy(pVirtq->szName, sizeof(pVirtq->szName), pcszName); 670 684 return VINF_SUCCESS; 671 685 } 672 686 673 687 /** API Fuunction: See header file */ 674 void virtioCoreR3VirtqInfo(PPDMDEVINS pDevIns, PCDBGFINFOHLP pHlp, const char *pszArgs, int uVirtq Nbr)688 void virtioCoreR3VirtqInfo(PPDMDEVINS pDevIns, PCDBGFINFOHLP pHlp, const char *pszArgs, int uVirtq) 675 689 { 676 690 RT_NOREF(pszArgs); 677 691 PVIRTIOCORE pVirtio = PDMDEVINS_2_DATA(pDevIns, PVIRTIOCORE); 678 PVIRTQ STATE pVirtqState = &pVirtio->aVirtqState[uVirtqNbr];692 PVIRTQUEUE pVirtq = &pVirtio->aVirtqueues[uVirtq]; 679 693 680 694 /** @todo add ability to dump physical contents described by any descriptor (using existing VirtIO core API function) */ 681 695 // bool fDump = pszArgs && (*pszArgs == 'd' || *pszArgs == 'D'); /* "dump" (avail phys descriptor)" 682 696 683 uint16_t uAvailIdx = virtioReadAvailRingIdx(pDevIns, pVirtio, uVirtqNbr);684 uint16_t uAvailIdxShadow = pVirtq State->uAvailIdxShadow;685 686 uint16_t uUsedIdx = virtioReadUsedRingIdx(pDevIns, pVirtio, uVirtqNbr);687 uint16_t uUsedIdxShadow = pVirtq State->uUsedIdxShadow;697 uint16_t uAvailIdx = virtioReadAvailRingIdx(pDevIns, pVirtio, pVirtq); 698 uint16_t uAvailIdxShadow = pVirtq->uAvailIdxShadow; 699 700 uint16_t uUsedIdx = virtioReadUsedRingIdx(pDevIns, pVirtio, pVirtq); 701 uint16_t uUsedIdxShadow = pVirtq->uUsedIdxShadow; 688 702 689 703 PVIRTQBUF pVirtqBuf = NULL; 690 704 691 bool fEmpty = IS_VIRTQ_EMPTY(pDevIns, pVirtio, pVirtq State);692 693 LogFunc(("%s, empty = %s\n", VIRTQNAME(pVirtio, uVirtqNbr), fEmpty ? "true" : "false"));705 bool fEmpty = IS_VIRTQ_EMPTY(pDevIns, pVirtio, pVirtq); 706 707 LogFunc(("%s, empty = %s\n", pVirtq->szName, fEmpty ? "true" : "false")); 694 708 695 709 int cSendSegs = 0, cReturnSegs = 0; 696 710 if (!fEmpty) 697 711 { 698 virtioCoreR3VirtqAvailBufPeek(pDevIns, pVirtio, uVirtq Nbr, &pVirtqBuf);712 virtioCoreR3VirtqAvailBufPeek(pDevIns, pVirtio, uVirtq, &pVirtqBuf); 699 713 cSendSegs = pVirtqBuf->pSgPhysSend ? pVirtqBuf->pSgPhysSend->cSegs : 0; 700 714 cReturnSegs = pVirtqBuf->pSgPhysReturn ? pVirtqBuf->pSgPhysReturn->cSegs : 0; 701 715 } 702 716 703 bool fAvailNoInterrupt = virtioReadAvailRingFlags(pDevIns, pVirtio, uVirtqNbr) & VIRTQ_AVAIL_F_NO_INTERRUPT;704 bool fUsedNoNotify = virtioReadUsedRingFlags(pDevIns, pVirtio, uVirtqNbr) & VIRTQ_USED_F_NO_NOTIFY;705 706 707 pHlp->pfnPrintf(pHlp, " queue enabled: ........... %s\n", pVirt io->uVirtqEnable[uVirtqNbr]? "true" : "false");708 pHlp->pfnPrintf(pHlp, " size: .................... %d\n", pVirt io->uVirtqSize[uVirtqNbr]);709 pHlp->pfnPrintf(pHlp, " notify offset: ........... %d\n", pVirt io->uVirtqNotifyOff[uVirtqNbr]);717 bool fAvailNoInterrupt = virtioReadAvailRingFlags(pDevIns, pVirtio, pVirtq) & VIRTQUEUE_AVAIL_F_NO_INTERRUPT; 718 bool fUsedNoNotify = virtioReadUsedRingFlags(pDevIns, pVirtio, pVirtq) & VIRTQUEUE_USED_F_NO_NOTIFY; 719 720 721 pHlp->pfnPrintf(pHlp, " queue enabled: ........... %s\n", pVirtq->uEnable ? "true" : "false"); 722 pHlp->pfnPrintf(pHlp, " size: .................... %d\n", pVirtq->uSize); 723 pHlp->pfnPrintf(pHlp, " notify offset: ........... %d\n", pVirtq->uNotifyOffset); 710 724 if (pVirtio->fMsiSupport) 711 pHlp->pfnPrintf(pHlp, " MSIX vector: ....... %4.4x\n", pVirt io->uVirtqMsixVector[uVirtqNbr]);725 pHlp->pfnPrintf(pHlp, " MSIX vector: ....... %4.4x\n", pVirtq->uMsix); 712 726 pHlp->pfnPrintf(pHlp, "\n"); 713 727 pHlp->pfnPrintf(pHlp, " avail ring (%d entries):\n", uAvailIdx - uAvailIdxShadow); … … 750 764 751 765 /** API Function: See header file */ 752 int virtioCoreR3VirtqAvailBufGet(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t uVirtq Nbr,766 int virtioCoreR3VirtqAvailBufGet(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t uVirtq, 753 767 uint16_t uHeadIdx, PPVIRTQBUF ppVirtqBuf) 754 768 { … … 756 770 *ppVirtqBuf = NULL; 757 771 758 Assert(uVirtqNbr < RT_ELEMENTS(pVirtio->aVirtqState)); 759 760 PVIRTQSTATE pVirtqState = &pVirtio->aVirtqState[uVirtqNbr]; 761 762 AssertMsgReturn(IS_DRIVER_OK(pVirtio) && pVirtio->uVirtqEnable[uVirtqNbr], 772 AssertMsgReturn(uVirtq < RT_ELEMENTS(pVirtio->aVirtqueues), 773 ("uVirtq out of range"), VERR_INVALID_PARAMETER); 774 PVIRTQUEUE pVirtq = &pVirtio->aVirtqueues[uVirtq]; 775 776 if (!IS_DRIVER_OK(pVirtio) || !pVirtq->uEnable) 777 { 778 LogRelFunc(("Driver not ready or queue not enabled\n")); 779 return 0; 780 } 781 782 AssertMsgReturn(IS_DRIVER_OK(pVirtio) && pVirtq->uEnable, 763 783 ("Guest driver not in ready state.\n"), VERR_INVALID_STATE); 764 784 765 785 uint16_t uDescIdx = uHeadIdx; 766 786 767 Log6Func(("%s DESC CHAIN: (head) desc_idx=%u\n", pVirtqState->szVirtqName, uHeadIdx)); 768 RT_NOREF(pVirtqState); 787 Log6Func(("%s DESC CHAIN: (head) desc_idx=%u\n", pVirtq->szName, uHeadIdx)); 769 788 770 789 /* … … 773 792 PVIRTQBUF pVirtqBuf = (PVIRTQBUF)RTMemAllocZ(sizeof(VIRTQBUF_T)); 774 793 AssertReturn(pVirtqBuf, VERR_NO_MEMORY); 775 pVirtqBuf->u32Magic = VIRTQBUF_MAGIC;776 pVirtqBuf->cRefs = 1;777 pVirtqBuf->uHeadIdx = uHeadIdx;778 pVirtqBuf->uVirtq Nbr = uVirtqNbr;794 pVirtqBuf->u32Magic = VIRTQBUF_MAGIC; 795 pVirtqBuf->cRefs = 1; 796 pVirtqBuf->uHeadIdx = uHeadIdx; 797 pVirtqBuf->uVirtq = uVirtq; 779 798 *ppVirtqBuf = pVirtqBuf; 780 799 … … 782 801 * Gather segments. 783 802 */ 784 VIRTQ _DESC_T desc;803 VIRTQUEUE_DESC_T desc; 785 804 786 805 uint32_t cbIn = 0; … … 816 835 RT_UNTRUSTED_VALIDATED_FENCE(); 817 836 818 virtioReadDesc(pDevIns, pVirtio, uVirtqNbr, uDescIdx, &desc);819 820 if (desc.fFlags & VIRTQ _DESC_F_WRITE)821 { 822 Log6Func(("%s IN desc_idx=%u seg=%u addr=%RGp cb=%u\n", VIRTQNAME(pVirtio, uVirtqNbr), uDescIdx, cSegsIn, desc.GCPhysBuf, desc.cb));837 virtioReadDesc(pDevIns, pVirtio, pVirtq, uDescIdx, &desc); 838 839 if (desc.fFlags & VIRTQUEUE_DESC_F_WRITE) 840 { 841 Log6Func(("%s IN desc_idx=%u seg=%u addr=%RGp cb=%u\n", pVirtq->szName, uDescIdx, cSegsIn, desc.GCPhysBuf, desc.cb)); 823 842 cbIn += desc.cb; 824 843 pSeg = &paSegsIn[cSegsIn++]; … … 826 845 else 827 846 { 828 Log6Func(("%s OUT desc_idx=%u seg=%u addr=%RGp cb=%u\n", VIRTQNAME(pVirtio, uVirtqNbr), uDescIdx, cSegsOut, desc.GCPhysBuf, desc.cb));847 Log6Func(("%s OUT desc_idx=%u seg=%u addr=%RGp cb=%u\n", pVirtq->szName, uDescIdx, cSegsOut, desc.GCPhysBuf, desc.cb)); 829 848 cbOut += desc.cb; 830 849 pSeg = &paSegsOut[cSegsOut++]; … … 840 859 841 860 uDescIdx = desc.uDescIdxNext; 842 } while (desc.fFlags & VIRTQ _DESC_F_NEXT);861 } while (desc.fFlags & VIRTQUEUE_DESC_F_NEXT); 843 862 844 863 /* … … 862 881 863 882 STAM_REL_COUNTER_INC(&pVirtio->StatDescChainsAllocated); 864 Log6Func(("%s -- segs OUT: %u (%u bytes) IN: %u (%u bytes) --\n", pVirtqState->szVirtqName, cSegsOut, cbOut, cSegsIn, cbIn)); 883 Log6Func(("%s -- segs OUT: %u (%u bytes) IN: %u (%u bytes) --\n", 884 pVirtq->szName, cSegsOut, cbOut, cSegsIn, cbIn)); 865 885 866 886 return VINF_SUCCESS; … … 903 923 } 904 924 905 void virtioCoreVirtqEnableNotify(PVIRTIOCORE pVirtio, uint16_t uVirtqNbr, bool fEnable) 906 { 925 /** API Function: See header file */ 926 void virtioCoreVirtqEnableNotify(PVIRTIOCORE pVirtio, uint16_t uVirtq, bool fEnable) 927 { 928 929 Assert(uVirtq < RT_ELEMENTS(pVirtio->aVirtqueues)); 930 PVIRTQUEUE pVirtq = &pVirtio->aVirtqueues[uVirtq]; 931 907 932 if (pVirtio->fDeviceStatus & VIRTIO_STATUS_DRIVER_OK) 908 933 { 909 uint16_t fFlags = virtioReadUsedRingFlags(pVirtio->pDevInsR3, pVirtio, uVirtqNbr);934 uint16_t fFlags = virtioReadUsedRingFlags(pVirtio->pDevInsR3, pVirtio, pVirtq); 910 935 911 936 if (fEnable) 912 fFlags &= ~ VIRTQ _USED_F_NO_NOTIFY;937 fFlags &= ~ VIRTQUEUE_USED_F_NO_NOTIFY; 913 938 else 914 fFlags |= VIRTQ _USED_F_NO_NOTIFY;915 916 virtioWriteUsedRingFlags(pVirtio->pDevInsR3, pVirtio, uVirtqNbr, fFlags);939 fFlags |= VIRTQUEUE_USED_F_NO_NOTIFY; 940 941 virtioWriteUsedRingFlags(pVirtio->pDevInsR3, pVirtio, pVirtq, fFlags); 917 942 } 918 943 } … … 931 956 932 957 /** API function: See Header file */ 933 int virtioCoreR3VirtqAvailBufPeek(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t uVirtq Nbr,958 int virtioCoreR3VirtqAvailBufPeek(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t uVirtq, 934 959 PPVIRTQBUF ppVirtqBuf) 935 960 { 936 return virtioCoreR3VirtqAvailBufGet(pDevIns, pVirtio, uVirtq Nbr, ppVirtqBuf, false);961 return virtioCoreR3VirtqAvailBufGet(pDevIns, pVirtio, uVirtq, ppVirtqBuf, false); 937 962 } 938 963 939 964 /** API function: See Header file */ 940 int virtioCoreR3VirtqAvailBufNext(PVIRTIOCORE pVirtio, uint16_t uVirtq Nbr)941 { 942 Assert(uVirtq Nbr < RT_ELEMENTS(pVirtio->aVirtqState));943 PVIRTQ STATE pVirtqState = &pVirtio->aVirtqState[uVirtqNbr];944 945 AssertMsgReturn(IS_DRIVER_OK(pVirtio) && pVirt io->uVirtqEnable[uVirtqNbr],965 int virtioCoreR3VirtqAvailBufNext(PVIRTIOCORE pVirtio, uint16_t uVirtq) 966 { 967 Assert(uVirtq < RT_ELEMENTS(pVirtio->aVirtqueues)); 968 PVIRTQUEUE pVirtq = &pVirtio->aVirtqueues[uVirtq]; 969 970 AssertMsgReturn(IS_DRIVER_OK(pVirtio) && pVirtq->uEnable, 946 971 ("Guest driver not in ready state.\n"), VERR_INVALID_STATE); 947 972 948 if (IS_VIRTQ_EMPTY(pVirtio->pDevInsR3, pVirtio, pVirtq State))973 if (IS_VIRTQ_EMPTY(pVirtio->pDevInsR3, pVirtio, pVirtq)) 949 974 return VERR_NOT_AVAILABLE; 950 975 951 Log6Func(("%s avail shadow idx: %u\n", pVirtq State->szVirtqName, pVirtqState->uAvailIdxShadow));952 pVirtq State->uAvailIdxShadow++;976 Log6Func(("%s avail shadow idx: %u\n", pVirtq->szName, pVirtq->uAvailIdxShadow)); 977 pVirtq->uAvailIdxShadow++; 953 978 954 979 return VINF_SUCCESS; … … 956 981 957 982 /** API function: See Header file */ 958 int virtioCoreR3VirtqAvailBufGet(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t uVirtq Nbr,983 int virtioCoreR3VirtqAvailBufGet(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t uVirtq, 959 984 PPVIRTQBUF ppVirtqBuf, bool fRemove) 960 985 { 961 PVIRTQSTATE pVirtqState = &pVirtio->aVirtqState[uVirtqNbr]; 962 963 if (IS_VIRTQ_EMPTY(pDevIns, pVirtio, pVirtqState)) 986 Assert(uVirtq < RT_ELEMENTS(pVirtio->aVirtqueues)); 987 PVIRTQUEUE pVirtq = &pVirtio->aVirtqueues[uVirtq]; 988 989 if (IS_VIRTQ_EMPTY(pDevIns, pVirtio, pVirtq)) 964 990 return VERR_NOT_AVAILABLE; 965 991 966 uint16_t uHeadIdx = virtioReadAvailDescIdx(pDevIns, pVirtio, uVirtqNbr, pVirtqState->uAvailIdxShadow);992 uint16_t uHeadIdx = virtioReadAvailDescIdx(pDevIns, pVirtio, pVirtq, pVirtq->uAvailIdxShadow); 967 993 968 994 if (pVirtio->uDriverFeatures & VIRTIO_F_EVENT_IDX) 969 virtioWriteUsedAvailEvent(pDevIns,pVirtio, uVirtqNbr, pVirtqState->uAvailIdxShadow + 1);995 virtioWriteUsedAvailEvent(pDevIns,pVirtio, pVirtq, pVirtq->uAvailIdxShadow + 1); 970 996 971 997 if (fRemove) 972 pVirtq State->uAvailIdxShadow++;973 974 int rc = virtioCoreR3VirtqAvailBufGet(pDevIns, pVirtio, uVirtq Nbr, uHeadIdx, ppVirtqBuf);998 pVirtq->uAvailIdxShadow++; 999 1000 int rc = virtioCoreR3VirtqAvailBufGet(pDevIns, pVirtio, uVirtq, uHeadIdx, ppVirtqBuf); 975 1001 return rc; 976 1002 } 977 1003 978 1004 /** API function: See Header file */ 979 int virtioCoreR3VirtqUsedBufPut(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t uVirtq Nbr, PRTSGBUF pSgVirtReturn,1005 int virtioCoreR3VirtqUsedBufPut(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t uVirtq, PRTSGBUF pSgVirtReturn, 980 1006 PVIRTQBUF pVirtqBuf, bool fFence) 981 1007 { 982 Assert(uVirtqNbr < RT_ELEMENTS(pVirtio->aVirtqState)); 983 PVIRTQSTATE pVirtqState = &pVirtio->aVirtqState[uVirtqNbr]; 1008 Assert(uVirtq < RT_ELEMENTS(pVirtio->aVirtqueues)); 1009 PVIRTQUEUE pVirtq = &pVirtio->aVirtqueues[uVirtq]; 1010 984 1011 PVIRTIOSGBUF pSgPhysReturn = pVirtqBuf->pSgPhysReturn; 985 1012 … … 990 1017 991 1018 Log6Func(("Copying client data to %s, desc chain (head desc_idx %d)\n", 992 VIRTQNAME(pVirtio, uVirtq Nbr), virtioReadUsedRingIdx(pDevIns, pVirtio, uVirtqNbr)));1019 VIRTQNAME(pVirtio, uVirtq), virtioReadUsedRingIdx(pDevIns, pVirtio, pVirtq))); 993 1020 994 1021 /* Copy s/g buf (virtual memory) to guest phys mem (IN direction). */ … … 1020 1047 /* If this write-ahead crosses threshold where the driver wants to get an event flag it */ 1021 1048 if (pVirtio->uDriverFeatures & VIRTIO_F_EVENT_IDX) 1022 if (pVirtq State->uUsedIdxShadow == virtioReadAvailUsedEvent(pDevIns, pVirtio, uVirtqNbr))1023 pVirtq State->fVirtqRingEventThreshold= true;1049 if (pVirtq->uUsedIdxShadow == virtioReadAvailUsedEvent(pDevIns, pVirtio, pVirtq)) 1050 pVirtq->fUsedRingEvent = true; 1024 1051 1025 1052 /* 1026 1053 * Place used buffer's descriptor in used ring but don't update used ring's slot index. 1027 1054 * That will be done with a subsequent client call to virtioCoreVirtqSyncUsedRing() */ 1028 virtioWriteUsedElem(pDevIns, pVirtio, uVirtqNbr, pVirtqState->uUsedIdxShadow++, pVirtqBuf->uHeadIdx, (uint32_t)cbTotal);1055 virtioWriteUsedElem(pDevIns, pVirtio, pVirtq, pVirtq->uUsedIdxShadow++, pVirtqBuf->uHeadIdx, (uint32_t)cbTotal); 1029 1056 1030 1057 if (pSgVirtReturn) … … 1033 1060 1034 1061 Log6Func(("Write ahead used_idx=%u, %s used_idx=%u\n", 1035 pVirtq State->uUsedIdxShadow, VIRTQNAME(pVirtio, uVirtqNbr), virtioReadUsedRingIdx(pDevIns, pVirtio, uVirtqNbr)));1062 pVirtq->uUsedIdxShadow, VIRTQNAME(pVirtio, uVirtq), virtioReadUsedRingIdx(pDevIns, pVirtio, pVirtq))); 1036 1063 1037 1064 return VINF_SUCCESS; … … 1053 1080 } 1054 1081 LogFunc(("Added %d/%d bytes to %s buffer, head idx: %u (%d bytes remain)\n", 1055 cb - cbLim, cb, VIRTQNAME(pVirtio, pVirtqBuf->uVirtq Nbr),1082 cb - cbLim, cb, VIRTQNAME(pVirtio, pVirtqBuf->uVirtq), 1056 1083 pVirtqBuf->uHeadIdx, pVirtqBuf->cbPhysReturn)); 1057 1084 } … … 1073 1100 } 1074 1101 LogFunc(("Drained %d/%d bytes from %s buffer, head idx: %u (%d bytes left)\n", 1075 cb - cbLim, cb, VIRTQNAME(pVirtio, pVirtqBuf->uVirtq Nbr),1102 cb - cbLim, cb, VIRTQNAME(pVirtio, pVirtqBuf->uVirtq), 1076 1103 pVirtqBuf->uHeadIdx, pVirtqBuf->cbPhysSend)); 1077 1104 } … … 1080 1107 1081 1108 /** API function: See Header file */ 1082 int virtioCoreVirtqSyncUsedRing(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t uVirtq Nbr)1083 { 1084 Assert(uVirtq Nbr < RT_ELEMENTS(pVirtio->aVirtqState));1085 PVIRTQ STATE pVirtqState = &pVirtio->aVirtqState[uVirtqNbr];1086 1087 AssertMsgReturn(IS_DRIVER_OK(pVirtio) && pVirt io->uVirtqEnable[uVirtqNbr],1109 int virtioCoreVirtqSyncUsedRing(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t uVirtq) 1110 { 1111 Assert(uVirtq < RT_ELEMENTS(pVirtio->aVirtqueues)); 1112 PVIRTQUEUE pVirtq = &pVirtio->aVirtqueues[uVirtq]; 1113 1114 AssertMsgReturn(IS_DRIVER_OK(pVirtio) && pVirtq->uEnable, 1088 1115 ("Guest driver not in ready state.\n"), VERR_INVALID_STATE); 1089 1116 1090 Log6Func(("Updating %s used_idx to %u\n", 1091 VIRTQNAME(pVirtio, uVirtqNbr), pVirtqState->uUsedIdxShadow)); 1092 1093 virtioWriteUsedRingIdx(pDevIns, pVirtio, uVirtqNbr, pVirtqState->uUsedIdxShadow); 1094 virtioCoreNotifyGuestDriver(pDevIns, pVirtio, uVirtqNbr); 1117 Log6Func(("Updating %s used_idx to %u\n", pVirtq->szName, pVirtq->uUsedIdxShadow)); 1118 1119 virtioWriteUsedRingIdx(pDevIns, pVirtio, pVirtq, pVirtq->uUsedIdxShadow); 1120 virtioCoreNotifyGuestDriver(pDevIns, pVirtio, uVirtq); 1095 1121 1096 1122 return VINF_SUCCESS; … … 1104 1130 * @param pDevIns The device instance. 1105 1131 * @param pVirtio Pointer to the shared virtio state. 1106 * @param uVirtq NbrVirtq to check for guest interrupt handling preference1132 * @param uVirtq Virtq to check for guest interrupt handling preference 1107 1133 * @param uNotifyIdx Notification index 1108 1134 */ 1109 static void virtioCoreVirtqNotified(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t uVirtq Nbr, uint16_t uNotifyIdx)1135 static void virtioCoreVirtqNotified(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t uVirtq, uint16_t uNotifyIdx) 1110 1136 { 1111 1137 PVIRTIOCORECC pVirtioCC = PDMDEVINS_2_DATA_CC(pDevIns, PVIRTIOCORECC); 1112 1138 1113 /* See VirtIO 1.0, section 4.1.5.2 It implies that uVirtq Nbrand uNotifyIdx should match.1139 /* See VirtIO 1.0, section 4.1.5.2 It implies that uVirtq and uNotifyIdx should match. 1114 1140 * Disregarding this notification may cause throughput to stop, however there's no way to know 1115 1141 * which was queue was intended for wake-up if the two parameters disagree. */ 1116 1142 1117 AssertMsg(uNotifyIdx == uVirtq Nbr,1118 1119 uVirtqNbr, uNotifyIdx));1143 AssertMsg(uNotifyIdx == uVirtq, 1144 ("Guest kicked virtq %d's notify addr w/non-corresponding virtq idx %d\n", 1145 uVirtq, uNotifyIdx)); 1120 1146 RT_NOREF(uNotifyIdx); 1121 1147 1122 AssertReturnVoid(uVirtqNbr < RT_ELEMENTS(pVirtio->aVirtqState)); 1123 Log6Func(("%s (desc chains: %u)\n", 1124 pVirtio->aVirtqState[uVirtqNbr].szVirtqName, 1125 virtioCoreVirtqAvailBufCount(pDevIns, pVirtio, uVirtqNbr))); 1148 AssertReturnVoid(uVirtq < RT_ELEMENTS(pVirtio->aVirtqueues)); 1149 PVIRTQUEUE pVirtq = &pVirtio->aVirtqueues[uVirtq]; 1150 1151 Log6Func(("%s (desc chains: %u)\n", pVirtq->szName, 1152 virtioCoreVirtqAvailBufCount_inline(pDevIns, pVirtio, pVirtq))); 1126 1153 1127 1154 /* Inform client */ 1128 pVirtioCC->pfnVirtqNotified(pDevIns, pVirtio, uVirtqNbr); 1155 pVirtioCC->pfnVirtqNotified(pDevIns, pVirtio, uVirtq); 1156 RT_NOREF2(pVirtio, pVirtq); 1129 1157 } 1130 1158 … … 1138 1166 * @param pDevIns The device instance. 1139 1167 * @param pVirtio Pointer to the shared virtio state. 1140 * @param uVirtq NbrVirtq to check for guest interrupt handling preference1141 */ 1142 static void virtioCoreNotifyGuestDriver(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t uVirtq Nbr)1143 { 1144 Assert(uVirtq Nbr < RT_ELEMENTS(pVirtio->aVirtqState));1145 PVIRTQ STATE pVirtqState = &pVirtio->aVirtqState[uVirtqNbr];1168 * @param uVirtq Virtq to check for guest interrupt handling preference 1169 */ 1170 static void virtioCoreNotifyGuestDriver(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t uVirtq) 1171 { 1172 Assert(uVirtq < RT_ELEMENTS(pVirtio->aVirtqueues)); 1173 PVIRTQUEUE pVirtq = &pVirtio->aVirtqueues[uVirtq]; 1146 1174 1147 1175 if (!IS_DRIVER_OK(pVirtio)) … … 1153 1181 if (pVirtio->uDriverFeatures & VIRTIO_F_EVENT_IDX) 1154 1182 { 1155 if (pVirtq State->fVirtqRingEventThreshold)1183 if (pVirtq->fUsedRingEvent) 1156 1184 { 1157 1185 #ifdef IN_RING3 1158 1186 Log6Func(("...kicking guest %s, VIRTIO_F_EVENT_IDX set and threshold (%d) reached\n", 1159 VIRTQNAME(pVirtio, uVirtqNbr), (uint16_t)virtioReadAvailUsedEvent(pDevIns, pVirtio, uVirtqNbr)));1187 pVirtq->szName, (uint16_t)virtioReadAvailUsedEvent(pDevIns, pVirtio, pVirtq))); 1160 1188 #endif 1161 virtioKick(pDevIns, pVirtio, VIRTIO_ISR_VIRTQ_INTERRUPT, pVirt io->uVirtqMsixVector[uVirtqNbr]);1162 pVirtq State->fVirtqRingEventThreshold= false;1189 virtioKick(pDevIns, pVirtio, VIRTIO_ISR_VIRTQ_INTERRUPT, pVirtq->uMsix); 1190 pVirtq->fUsedRingEvent = false; 1163 1191 return; 1164 1192 } 1165 1193 #ifdef IN_RING3 1166 1194 Log6Func(("...skip interrupt %s, VIRTIO_F_EVENT_IDX set but threshold (%d) not reached (%d)\n", 1167 VIRTQNAME(pVirtio, uVirtqNbr),(uint16_t)virtioReadAvailUsedEvent(pDevIns, pVirtio, uVirtqNbr), pVirtqState->uUsedIdxShadow));1195 pVirtq->szName,(uint16_t)virtioReadAvailUsedEvent(pDevIns, pVirtio, pVirtq), pVirtq->uUsedIdxShadow)); 1168 1196 #endif 1169 1197 } … … 1171 1199 { 1172 1200 /** If guest driver hasn't suppressed interrupts, interrupt */ 1173 if (!(virtioReadAvailRingFlags(pDevIns, pVirtio, uVirtqNbr) & VIRTQ_AVAIL_F_NO_INTERRUPT))1174 { 1175 virtioKick(pDevIns, pVirtio, VIRTIO_ISR_VIRTQ_INTERRUPT, pVirt io->uVirtqMsixVector[uVirtqNbr]);1201 if (!(virtioReadAvailRingFlags(pDevIns, pVirtio, pVirtq) & VIRTQUEUE_AVAIL_F_NO_INTERRUPT)) 1202 { 1203 virtioKick(pDevIns, pVirtio, VIRTIO_ISR_VIRTQ_INTERRUPT, pVirtq->uMsix); 1176 1204 return; 1177 1205 } 1178 Log6Func(("...skipping interrupt for %s (guest set VIRTQ_AVAIL_F_NO_INTERRUPT)\n", 1179 VIRTQNAME(pVirtio, uVirtqNbr))); 1206 Log6Func(("...skipping interrupt for %s (guest set VIRTQUEUE_AVAIL_F_NO_INTERRUPT)\n", pVirtq->szName)); 1180 1207 } 1181 1208 } … … 1189 1216 * @param uVec MSI-X vector, if enabled 1190 1217 */ 1191 static int virtioKick(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint8_t uCause, uint16_t uMsix Vector)1218 static int virtioKick(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint8_t uCause, uint16_t uMsixtor) 1192 1219 { 1193 1220 if (uCause == VIRTIO_ISR_VIRTQ_INTERRUPT) … … 1202 1229 PDMDevHlpPCISetIrq(pDevIns, 0, PDM_IRQ_LEVEL_HIGH); 1203 1230 } 1204 else if (uMsix Vector != VIRTIO_MSI_NO_VECTOR)1205 PDMDevHlpPCISetIrq(pDevIns, uMsix Vector, 1);1231 else if (uMsixtor != VIRTIO_MSI_NO_VECTOR) 1232 PDMDevHlpPCISetIrq(pDevIns, uMsixtor, 1); 1206 1233 return VINF_SUCCESS; 1207 1234 } … … 1212 1239 * @param pDevIns The device instance. 1213 1240 */ 1214 static void virtioLowerInterrupt(PPDMDEVINS pDevIns, uint16_t uMsix Vector)1241 static void virtioLowerInterrupt(PPDMDEVINS pDevIns, uint16_t uMsixtor) 1215 1242 { 1216 1243 PVIRTIOCORE pVirtio = PDMINS_2_DATA(pDevIns, PVIRTIOCORE); 1217 1244 if (!pVirtio->fMsiSupport) 1218 1245 PDMDevHlpPCISetIrq(pDevIns, 0, PDM_IRQ_LEVEL_LOW); 1219 else if (uMsix Vector != VIRTIO_MSI_NO_VECTOR)1246 else if (uMsixtor != VIRTIO_MSI_NO_VECTOR) 1220 1247 PDMDevHlpPCISetIrq(pDevIns, pVirtio->uMsixConfig, PDM_IRQ_LEVEL_LOW); 1221 1248 } 1222 1249 1223 1250 #ifdef IN_RING3 1224 static void virtioResetVirtq(PVIRTIOCORE pVirtio, uint16_t uVirtqNbr) 1225 { 1226 Assert(uVirtqNbr < RT_ELEMENTS(pVirtio->aVirtqState)); 1227 PVIRTQSTATE pVirtqState = &pVirtio->aVirtqState[uVirtqNbr]; 1228 pVirtqState->uAvailIdxShadow = 0; 1229 pVirtqState->uUsedIdxShadow = 0; 1230 pVirtqState->fVirtqRingEventThreshold = false; 1231 pVirtio->uVirtqEnable[uVirtqNbr] = false; 1232 pVirtio->uVirtqSize[uVirtqNbr] = VIRTQ_MAX_ENTRIES; 1233 pVirtio->uVirtqNotifyOff[uVirtqNbr] = uVirtqNbr; 1234 pVirtio->uVirtqMsixVector[uVirtqNbr] = uVirtqNbr + 2; 1251 static void virtioResetVirtq(PVIRTIOCORE pVirtio, uint16_t uVirtq) 1252 { 1253 Assert(uVirtq < RT_ELEMENTS(pVirtio->aVirtqueues)); 1254 PVIRTQUEUE pVirtq = &pVirtio->aVirtqueues[uVirtq]; 1255 1256 pVirtq->uAvailIdxShadow = 0; 1257 pVirtq->uUsedIdxShadow = 0; 1258 pVirtq->uEnable = false; 1259 pVirtq->uSize = VIRTQ_MAX_ENTRIES; 1260 pVirtq->uNotifyOffset = uVirtq; 1261 pVirtq->uMsix = uVirtq + 2; 1262 pVirtq->fUsedRingEvent = false; 1263 1235 1264 if (!pVirtio->fMsiSupport) /* VirtIO 1.0, 4.1.4.3 and 4.1.5.1.2 */ 1236 pVirt io->uVirtqMsixVector[uVirtqNbr]= VIRTIO_MSI_NO_VECTOR;1237 1238 virtioLowerInterrupt(pVirtio->pDevInsR3, pVirt io->uVirtqMsixVector[uVirtqNbr]);1265 pVirtq->uMsix = VIRTIO_MSI_NO_VECTOR; 1266 1267 virtioLowerInterrupt(pVirtio->pDevInsR3, pVirtq->uMsix); 1239 1268 } 1240 1269 … … 1253 1282 { 1254 1283 virtioLowerInterrupt(pDevIns, pVirtio->uMsixConfig); 1255 for (int i = 0; i < VIRTQ_MAX_CNT; i++) 1256 { 1257 virtioLowerInterrupt(pDevIns, pVirtio->uVirtqMsixVector[i]); 1258 pVirtio->uVirtqMsixVector[i]; 1259 } 1284 for (int i = 0; i < VIRTQ_MAX_COUNT; i++) 1285 virtioLowerInterrupt(pDevIns, pVirtio->aVirtqueues[i].uMsix); 1260 1286 } 1261 1287 … … 1263 1289 pVirtio->uMsixConfig = VIRTIO_MSI_NO_VECTOR; 1264 1290 1265 for (uint16_t uVirtq Nbr = 0; uVirtqNbr < VIRTQ_MAX_CNT; uVirtqNbr++)1266 virtioResetVirtq(pVirtio, uVirtq Nbr);1291 for (uint16_t uVirtq = 0; uVirtq < VIRTQ_MAX_COUNT; uVirtq++) 1292 virtioResetVirtq(pVirtio, uVirtq); 1267 1293 } 1268 1294 … … 1297 1323 int fWrite, uint32_t uOffsetOfAccess, unsigned cb, void *pv) 1298 1324 { 1299 uint16_t uVirtq Nbr= pVirtio->uVirtqSelect;1325 uint16_t uVirtq = pVirtio->uVirtqSelect; 1300 1326 int rc = VINF_SUCCESS; 1301 1327 uint64_t val; … … 1381 1407 return VINF_SUCCESS; 1382 1408 } 1383 *(uint16_t *)pv = VIRTQ_MAX_C NT;1409 *(uint16_t *)pv = VIRTQ_MAX_COUNT; 1384 1410 VIRTIO_DEV_CONFIG_LOG_ACCESS(uNumVirtqs, VIRTIO_PCI_COMMON_CFG_T, uOffsetOfAccess); 1385 1411 } … … 1439 1465 } 1440 1466 else 1441 if (VIRTIO_DEV_CONFIG_MATCH_MEMBER( uMsixConfig, 1442 VIRTIO_DEV_CONFIG_ACCESS( uMsixConfig, 1443 else 1444 if (VIRTIO_DEV_CONFIG_MATCH_MEMBER( uDeviceFeaturesSelect, 1445 VIRTIO_DEV_CONFIG_ACCESS( uDeviceFeaturesSelect, 1446 else 1447 if (VIRTIO_DEV_CONFIG_MATCH_MEMBER( uDriverFeaturesSelect, 1448 VIRTIO_DEV_CONFIG_ACCESS( uDriverFeaturesSelect, 1449 else 1450 if (VIRTIO_DEV_CONFIG_MATCH_MEMBER( uConfigGeneration, 1451 VIRTIO_DEV_CONFIG_ACCESS( uConfigGeneration, 1452 else 1453 if (VIRTIO_DEV_CONFIG_MATCH_MEMBER( uVirtqSelect, 1454 VIRTIO_DEV_CONFIG_ACCESS( uVirtqSelect, 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( u VirtqNotifyOff,VIRTIO_PCI_COMMON_CFG_T, uOffsetOfAccess))1466 VIRTIO_DEV_CONFIG_ACCESS_INDEXED( u VirtqNotifyOff, 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);1467 if (VIRTIO_DEV_CONFIG_MATCH_MEMBER( uMsixConfig, VIRTIO_PCI_COMMON_CFG_T, uOffsetOfAccess)) 1468 VIRTIO_DEV_CONFIG_ACCESS( uMsixConfig, VIRTIO_PCI_COMMON_CFG_T, uOffsetOfAccess, pVirtio); 1469 else 1470 if (VIRTIO_DEV_CONFIG_MATCH_MEMBER( uDeviceFeaturesSelect, VIRTIO_PCI_COMMON_CFG_T, uOffsetOfAccess)) 1471 VIRTIO_DEV_CONFIG_ACCESS( uDeviceFeaturesSelect, VIRTIO_PCI_COMMON_CFG_T, uOffsetOfAccess, pVirtio); 1472 else 1473 if (VIRTIO_DEV_CONFIG_MATCH_MEMBER( uDriverFeaturesSelect, VIRTIO_PCI_COMMON_CFG_T, uOffsetOfAccess)) 1474 VIRTIO_DEV_CONFIG_ACCESS( uDriverFeaturesSelect, VIRTIO_PCI_COMMON_CFG_T, uOffsetOfAccess, pVirtio); 1475 else 1476 if (VIRTIO_DEV_CONFIG_MATCH_MEMBER( uConfigGeneration, VIRTIO_PCI_COMMON_CFG_T, uOffsetOfAccess)) 1477 VIRTIO_DEV_CONFIG_ACCESS( uConfigGeneration, VIRTIO_PCI_COMMON_CFG_T, uOffsetOfAccess, pVirtio); 1478 else 1479 if (VIRTIO_DEV_CONFIG_MATCH_MEMBER( uVirtqSelect, VIRTIO_PCI_COMMON_CFG_T, uOffsetOfAccess)) 1480 VIRTIO_DEV_CONFIG_ACCESS( uVirtqSelect, VIRTIO_PCI_COMMON_CFG_T, uOffsetOfAccess, pVirtio); 1481 else 1482 if (VIRTIO_DEV_CONFIG_MATCH_MEMBER( GCPhysVirtqDesc, VIRTIO_PCI_COMMON_CFG_T, uOffsetOfAccess)) 1483 VIRTIO_DEV_CONFIG_ACCESS_INDEXED( GCPhysVirtqDesc, uVirtq, VIRTIO_PCI_COMMON_CFG_T, uOffsetOfAccess, pVirtio->aVirtqueues); 1484 else 1485 if (VIRTIO_DEV_CONFIG_MATCH_MEMBER( GCPhysVirtqAvail, VIRTIO_PCI_COMMON_CFG_T, uOffsetOfAccess)) 1486 VIRTIO_DEV_CONFIG_ACCESS_INDEXED( GCPhysVirtqAvail, uVirtq, VIRTIO_PCI_COMMON_CFG_T, uOffsetOfAccess, pVirtio->aVirtqueues); 1487 else 1488 if (VIRTIO_DEV_CONFIG_MATCH_MEMBER( GCPhysVirtqUsed, VIRTIO_PCI_COMMON_CFG_T, uOffsetOfAccess)) 1489 VIRTIO_DEV_CONFIG_ACCESS_INDEXED( GCPhysVirtqUsed, uVirtq, VIRTIO_PCI_COMMON_CFG_T, uOffsetOfAccess, pVirtio->aVirtqueues); 1490 else 1491 if (VIRTIO_DEV_CONFIG_MATCH_MEMBER( uSize, VIRTIO_PCI_COMMON_CFG_T, uOffsetOfAccess)) 1492 VIRTIO_DEV_CONFIG_ACCESS_INDEXED( uSize, uVirtq, VIRTIO_PCI_COMMON_CFG_T, uOffsetOfAccess, pVirtio->aVirtqueues); 1493 else 1494 if (VIRTIO_DEV_CONFIG_MATCH_MEMBER( uEnable, VIRTIO_PCI_COMMON_CFG_T, uOffsetOfAccess)) 1495 VIRTIO_DEV_CONFIG_ACCESS_INDEXED( uEnable, uVirtq, VIRTIO_PCI_COMMON_CFG_T, uOffsetOfAccess, pVirtio->aVirtqueues); 1496 else 1497 if (VIRTIO_DEV_CONFIG_MATCH_MEMBER( uNotifyOffset, VIRTIO_PCI_COMMON_CFG_T, uOffsetOfAccess)) 1498 VIRTIO_DEV_CONFIG_ACCESS_INDEXED( uNotifyOffset, uVirtq, VIRTIO_PCI_COMMON_CFG_T, uOffsetOfAccess, pVirtio->aVirtqueues); 1499 else 1500 if (VIRTIO_DEV_CONFIG_MATCH_MEMBER( uMsix, VIRTIO_PCI_COMMON_CFG_T, uOffsetOfAccess)) 1501 VIRTIO_DEV_CONFIG_ACCESS_INDEXED( uMsix, uVirtq, VIRTIO_PCI_COMMON_CFG_T, uOffsetOfAccess, pVirtio->aVirtqueues); 1476 1502 else 1477 1503 { … … 1706 1732 pHlp->pfnSSMPutU32(pSSM, VIRTIO_SAVEDSTATE_VERSION); 1707 1733 1708 pHlp->pfnSSMPutBool(pSSM, pVirtio->fGenUpdatePending); 1709 pHlp->pfnSSMPutU8(pSSM, pVirtio->fDeviceStatus); 1710 pHlp->pfnSSMPutU8(pSSM, pVirtio->uConfigGeneration); 1711 pHlp->pfnSSMPutU8(pSSM, pVirtio->uPciCfgDataOff); 1712 pHlp->pfnSSMPutU8(pSSM, pVirtio->uISR); 1713 pHlp->pfnSSMPutU16(pSSM, pVirtio->uVirtqSelect); 1714 pHlp->pfnSSMPutU32(pSSM, pVirtio->uDeviceFeaturesSelect); 1715 pHlp->pfnSSMPutU32(pSSM, pVirtio->uDriverFeaturesSelect); 1716 pHlp->pfnSSMPutU64(pSSM, pVirtio->uDriverFeatures); 1717 1718 for (uint32_t i = 0; i < VIRTQ_MAX_CNT; i++) 1719 { 1720 pHlp->pfnSSMPutGCPhys64(pSSM, pVirtio->aGCPhysVirtqDesc[i]); 1721 pHlp->pfnSSMPutGCPhys64(pSSM, pVirtio->aGCPhysVirtqAvail[i]); 1722 pHlp->pfnSSMPutGCPhys64(pSSM, pVirtio->aGCPhysVirtqUsed[i]); 1723 pHlp->pfnSSMPutU16(pSSM, pVirtio->uVirtqNotifyOff[i]); 1724 pHlp->pfnSSMPutU16(pSSM, pVirtio->uVirtqMsixVector[i]); 1725 pHlp->pfnSSMPutU16(pSSM, pVirtio->uVirtqEnable[i]); 1726 pHlp->pfnSSMPutU16(pSSM, pVirtio->uVirtqSize[i]); 1727 pHlp->pfnSSMPutU16(pSSM, pVirtio->aVirtqState[i].uAvailIdxShadow); 1728 pHlp->pfnSSMPutU16(pSSM, pVirtio->aVirtqState[i].uUsedIdxShadow); 1729 int rc = pHlp->pfnSSMPutMem(pSSM, pVirtio->aVirtqState[i].szVirtqName, 32); 1734 pHlp->pfnSSMPutBool(pSSM, pVirtio->fGenUpdatePending); 1735 pHlp->pfnSSMPutU8( pSSM, pVirtio->fDeviceStatus); 1736 pHlp->pfnSSMPutU8( pSSM, pVirtio->uConfigGeneration); 1737 pHlp->pfnSSMPutU8( pSSM, pVirtio->uPciCfgDataOff); 1738 pHlp->pfnSSMPutU8( pSSM, pVirtio->uISR); 1739 pHlp->pfnSSMPutU16( pSSM, pVirtio->uVirtqSelect); 1740 pHlp->pfnSSMPutU32( pSSM, pVirtio->uDeviceFeaturesSelect); 1741 pHlp->pfnSSMPutU32( pSSM, pVirtio->uDriverFeaturesSelect); 1742 pHlp->pfnSSMPutU64( pSSM, pVirtio->uDriverFeatures); 1743 1744 for (uint32_t i = 0; i < VIRTQ_MAX_COUNT; i++) 1745 { 1746 PVIRTQUEUE pVirtq = &pVirtio->aVirtqueues[i]; 1747 1748 pHlp->pfnSSMPutGCPhys64( pSSM, pVirtq->GCPhysVirtqDesc); 1749 pHlp->pfnSSMPutGCPhys64( pSSM, pVirtq->GCPhysVirtqAvail); 1750 pHlp->pfnSSMPutGCPhys64( pSSM, pVirtq->GCPhysVirtqUsed); 1751 pHlp->pfnSSMPutU16( pSSM, pVirtq->uNotifyOffset); 1752 pHlp->pfnSSMPutU16( pSSM, pVirtq->uMsix); 1753 pHlp->pfnSSMPutU16( pSSM, pVirtq->uEnable); 1754 pHlp->pfnSSMPutU16( pSSM, pVirtq->uSize); 1755 pHlp->pfnSSMPutU16( pSSM, pVirtq->uAvailIdxShadow); 1756 pHlp->pfnSSMPutU16( pSSM, pVirtq->uUsedIdxShadow); 1757 int rc = pHlp->pfnSSMPutMem(pSSM, pVirtq->szName, 32); 1730 1758 AssertRCReturn(rc, rc); 1731 1759 } … … 1764 1792 * Load the state. 1765 1793 */ 1766 pHlp->pfnSSMGetBool(pSSM, &pVirtio->fGenUpdatePending); 1767 pHlp->pfnSSMGetU8(pSSM, &pVirtio->fDeviceStatus); 1768 pHlp->pfnSSMGetU8(pSSM, &pVirtio->uConfigGeneration); 1769 pHlp->pfnSSMGetU8(pSSM, &pVirtio->uPciCfgDataOff); 1770 pHlp->pfnSSMGetU8(pSSM, &pVirtio->uISR); 1771 pHlp->pfnSSMGetU16(pSSM, &pVirtio->uVirtqSelect); 1772 pHlp->pfnSSMGetU32(pSSM, &pVirtio->uDeviceFeaturesSelect); 1773 pHlp->pfnSSMGetU32(pSSM, &pVirtio->uDriverFeaturesSelect); 1774 pHlp->pfnSSMGetU64(pSSM, &pVirtio->uDriverFeatures); 1775 1776 for (uint32_t i = 0; i < VIRTQ_MAX_CNT; i++) 1777 { 1778 pHlp->pfnSSMGetGCPhys64(pSSM, &pVirtio->aGCPhysVirtqDesc[i]); 1779 pHlp->pfnSSMGetGCPhys64(pSSM, &pVirtio->aGCPhysVirtqAvail[i]); 1780 pHlp->pfnSSMGetGCPhys64(pSSM, &pVirtio->aGCPhysVirtqUsed[i]); 1781 pHlp->pfnSSMGetU16(pSSM, &pVirtio->uVirtqNotifyOff[i]); 1782 pHlp->pfnSSMGetU16(pSSM, &pVirtio->uVirtqMsixVector[i]); 1783 pHlp->pfnSSMGetU16(pSSM, &pVirtio->uVirtqEnable[i]); 1784 pHlp->pfnSSMGetU16(pSSM, &pVirtio->uVirtqSize[i]); 1785 pHlp->pfnSSMGetU16(pSSM, &pVirtio->aVirtqState[i].uAvailIdxShadow); 1786 pHlp->pfnSSMGetU16(pSSM, &pVirtio->aVirtqState[i].uUsedIdxShadow); 1787 rc = pHlp->pfnSSMGetMem(pSSM, pVirtio->aVirtqState[i].szVirtqName, 1788 sizeof(pVirtio->aVirtqState[i].szVirtqName)); 1794 pHlp->pfnSSMGetBool( pSSM, &pVirtio->fGenUpdatePending); 1795 pHlp->pfnSSMGetU8( pSSM, &pVirtio->fDeviceStatus); 1796 pHlp->pfnSSMGetU8( pSSM, &pVirtio->uConfigGeneration); 1797 pHlp->pfnSSMGetU8( pSSM, &pVirtio->uPciCfgDataOff); 1798 pHlp->pfnSSMGetU8( pSSM, &pVirtio->uISR); 1799 pHlp->pfnSSMGetU16( pSSM, &pVirtio->uVirtqSelect); 1800 pHlp->pfnSSMGetU32( pSSM, &pVirtio->uDeviceFeaturesSelect); 1801 pHlp->pfnSSMGetU32( pSSM, &pVirtio->uDriverFeaturesSelect); 1802 pHlp->pfnSSMGetU64( pSSM, &pVirtio->uDriverFeatures); 1803 1804 for (uint32_t i = 0; i < VIRTQ_MAX_COUNT; i++) 1805 { 1806 PVIRTQUEUE pVirtq = &pVirtio->aVirtqueues[i]; 1807 1808 pHlp->pfnSSMGetGCPhys64( pSSM, &pVirtq->GCPhysVirtqDesc); 1809 pHlp->pfnSSMGetGCPhys64( pSSM, &pVirtq->GCPhysVirtqAvail); 1810 pHlp->pfnSSMGetGCPhys64( pSSM, &pVirtq->GCPhysVirtqUsed); 1811 pHlp->pfnSSMGetU16( pSSM, &pVirtq->uNotifyOffset); 1812 pHlp->pfnSSMGetU16( pSSM, &pVirtq->uMsix); 1813 pHlp->pfnSSMGetU16( pSSM, &pVirtq->uEnable); 1814 pHlp->pfnSSMGetU16( pSSM, &pVirtq->uSize); 1815 pHlp->pfnSSMGetU16( pSSM, &pVirtq->uAvailIdxShadow); 1816 pHlp->pfnSSMGetU16( pSSM, &pVirtq->uUsedIdxShadow); 1817 rc = pHlp->pfnSSMGetMem( pSSM, pVirtq->szName, sizeof(pVirtq->szName)); 1789 1818 AssertRCReturn(rc, rc); 1790 1819 } … … 1821 1850 break; 1822 1851 case kvirtIoVmStateChangedResume: 1823 virtioCoreNotifyGuestDriver(pVirtio->pDevInsR3, pVirtio, 0 /* uVirtq Nbr*/);1852 virtioCoreNotifyGuestDriver(pVirtio->pDevInsR3, pVirtio, 0 /* uVirtq */); 1824 1853 break; 1825 1854 default: … … 1846 1875 } 1847 1876 1848 1849 /**rr 1877 /** 1850 1878 * Setup PCI device controller and Virtio state 1851 1879 * … … 1960 1988 /* 1961 1989 * Notify capability (VirtIO 1.0 spec, section 4.1.4.4). Note: uLength is based on the choice 1962 * of this implementation to make each queue's u VirtqNotifyOffequal to (VirtqSelect) ordinal1990 * of this implementation to make each queue's uNotifyOffset equal to (VirtqSelect) ordinal 1963 1991 * value of the queue (different strategies are possible according to spec). 1964 1992 */ … … 1971 1999 pCfg->uOffset = pVirtioCC->pCommonCfgCap->uOffset + pVirtioCC->pCommonCfgCap->uLength; 1972 2000 pCfg->uOffset = RT_ALIGN_32(pCfg->uOffset, 4); 1973 pCfg->uLength = VIRTQ_MAX_C NT * VIRTIO_NOTIFY_OFFSET_MULTIPLIER + 2; /* will change in VirtIO 1.1 */2001 pCfg->uLength = VIRTQ_MAX_COUNT * VIRTIO_NOTIFY_OFFSET_MULTIPLIER + 2; /* will change in VirtIO 1.1 */ 1974 2002 cbRegion += pCfg->uLength; 1975 2003 SET_PCI_CAP_LOC(pPciDev, pCfg, pVirtio->LocNotifyCap, 1); -
trunk/src/VBox/Devices/VirtIO/VirtioCore.h
r85045 r85109 49 49 #define VIRTIO_MAX_VIRTQ_NAME_SIZE 32 /**< Maximum length of a queue name */ 50 50 #define VIRTQ_MAX_ENTRIES 1024 /**< Max size (# desc elements) of a virtq */ 51 #define VIRTQ_MAX_C NT24 /**< Max queues we allow guest to create */51 #define VIRTQ_MAX_COUNT 24 /**< Max queues we allow guest to create */ 52 52 #define VIRTIO_NOTIFY_OFFSET_MULTIPLIER 2 /**< VirtIO Notify Cap. MMIO config param */ 53 53 #define VIRTIO_REGION_PCI_CAP 2 /**< BAR for VirtIO Cap. MMIO (impl specific) */ … … 92 92 { 93 93 uint32_t u32Magic; /**< Magic value, VIRTQBUF_MAGIC. */ 94 uint16_t uVirtq Nbr;/**< VirtIO index of associated virtq */94 uint16_t uVirtq; /**< VirtIO index of associated virtq */ 95 95 uint16_t pad; 96 96 uint32_t volatile cRefs; /**< Reference counter. */ … … 188 188 189 189 /** 190 * Local implementation's usage context of a queue (e.g. not part of VirtIO specification)191 */192 typedef struct VIRTQSTATE193 {194 uint16_t uVirtqNbr; /**< Index of this queue */195 char szVirtqName[32]; /**< Dev-specific name of queue */196 uint16_t uAvailIdxShadow; /**< Consumer's position in avail ring */197 uint16_t uUsedIdxShadow; /**< Consumer's position in used ring */198 bool fVirtqRingEventThreshold; /**< Don't lose track while queueing ahead */199 } VIRTQSTATE, *PVIRTQSTATE;200 201 /**202 190 * VirtIO 1.0 Capabilities' related MMIO-mapped structs: 203 191 * … … 218 206 /* Virtq-specific fields (values reflect (via MMIO) info related to queue indicated by uVirtqSelect. */ 219 207 uint16_t uVirtqSelect; /**< RW (selects queue focus for these fields) */ 220 uint16_t u VirtqSize;/**< RW (queue size, 0 - 2^n) */221 uint16_t u VirtqMsixVector;/**< RW (driver selects MSI-X queue vector) */222 uint16_t u VirtqEnable;/**< RW (driver controls usability of queue) */223 uint16_t u VirtqNotifyOff;/**< RO (offset into virtqueue; see spec) */224 uint64_t aGCPhysVirtqDesc;/**< RW (driver writes desc table phys addr) */225 uint64_t aGCPhysVirtqAvail;/**< RW (driver writes avail ring phys addr) */226 uint64_t aGCPhysVirtqUsed;/**< RW (driver writes used ring phys addr) */208 uint16_t uSize; /**< RW (queue size, 0 - 2^n) */ 209 uint16_t uMsix; /**< RW (driver selects MSI-X queue vector) */ 210 uint16_t uEnable; /**< RW (driver controls usability of queue) */ 211 uint16_t uNotifyOffset; /**< RO (offset into virtqueue; see spec) */ 212 uint64_t GCPhysVirtqDesc; /**< RW (driver writes desc table phys addr) */ 213 uint64_t GCPhysVirtqAvail; /**< RW (driver writes avail ring phys addr) */ 214 uint64_t GCPhysVirtqUsed; /**< RW (driver writes used ring phys addr) */ 227 215 } VIRTIO_PCI_COMMON_CFG_T, *PVIRTIO_PCI_COMMON_CFG_T; 228 216 … … 250 238 } VIRTIO_PCI_CAP_LOCATIONS_T; 251 239 240 typedef struct VIRTQUEUE 241 { 242 RTGCPHYS GCPhysVirtqDesc; /**< (MMIO) PhysAdr per-Q desc structs GUEST */ 243 RTGCPHYS GCPhysVirtqAvail; /**< (MMIO) PhysAdr per-Q avail structs GUEST */ 244 RTGCPHYS GCPhysVirtqUsed; /**< (MMIO) PhysAdr per-Q used structs GUEST */ 245 uint16_t uNotifyOffset; /**< (MMIO) per-Q notify offset HOST */ 246 uint16_t uMsix; /**< (MMIO) Per-queue vector for MSI-X GUEST */ 247 uint16_t uEnable; /**< (MMIO) Per-queue enable GUEST */ 248 uint16_t uSize; /**< (MMIO) Per-queue size HOST/GUEST */ 249 uint16_t uAvailIdxShadow; /**< Consumer's position in avail ring */ 250 uint16_t uUsedIdxShadow; /**< Consumer's position in used ring */ 251 bool fUsedRingEvent; /**< Flags if used idx to notify guest reached */ 252 uint16_t uVirtq; /**< Index of this queue */ 253 char szName[32]; /**< Dev-specific name of queue */ 254 uint8_t padding[3]; 255 } VIRTQUEUE, *PVIRTQUEUE; 256 252 257 /** 253 258 * The core/common state of the VirtIO PCI devices, shared edition. … … 255 260 typedef struct VIRTIOCORE 256 261 { 257 char szInstance[16]; /**< Instance name, e.g. "VIRTIOSCSI0" */ 258 PPDMDEVINS pDevInsR0; /**< Client device instance */ 259 PPDMDEVINS pDevInsR3; /**< Client device instance */ 260 RTGCPHYS aGCPhysVirtqDesc[VIRTQ_MAX_CNT]; /**< (MMIO) PhysAdr per-Q desc structs GUEST */ 261 RTGCPHYS aGCPhysVirtqAvail[VIRTQ_MAX_CNT]; /**< (MMIO) PhysAdr per-Q avail structs GUEST */ 262 RTGCPHYS aGCPhysVirtqUsed[VIRTQ_MAX_CNT]; /**< (MMIO) PhysAdr per-Q used structs GUEST */ 263 uint16_t uVirtqNotifyOff[VIRTQ_MAX_CNT]; /**< (MMIO) per-Q notify offset HOST */ 264 uint16_t uVirtqMsixVector[VIRTQ_MAX_CNT]; /**< (MMIO) Per-queue vector for MSI-X GUEST */ 265 uint16_t uVirtqEnable[VIRTQ_MAX_CNT]; /**< (MMIO) Per-queue enable GUEST */ 266 uint16_t uVirtqSize[VIRTQ_MAX_CNT]; /**< (MMIO) Per-queue size HOST/GUEST */ 267 uint16_t uVirtqSelect; /**< (MMIO) queue selector GUEST */ 268 uint16_t padding; 269 uint64_t uDeviceFeatures; /**< (MMIO) Host features offered HOST */ 270 uint64_t uDriverFeatures; /**< (MMIO) Host features accepted GUEST */ 271 uint32_t uDeviceFeaturesSelect; /**< (MMIO) hi/lo select uDeviceFeatures GUEST */ 272 uint32_t uDriverFeaturesSelect; /**< (MMIO) hi/lo select uDriverFeatures GUEST */ 273 uint32_t uMsixConfig; /**< (MMIO) MSI-X vector GUEST */ 274 uint8_t fDeviceStatus; /**< (MMIO) Device Status GUEST */ 275 uint8_t uPrevDeviceStatus; /**< (MMIO) Prev Device Status GUEST */ 276 uint8_t uConfigGeneration; /**< (MMIO) Device config sequencer HOST */ 277 VIRTQSTATE aVirtqState[VIRTQ_MAX_CNT]; /**< Local impl-specific queue context */ 262 char szInstance[16]; /**< Instance name, e.g. "VIRTIOSCSI0" */ 263 PPDMDEVINS pDevInsR0; /**< Client device instance */ 264 PPDMDEVINS pDevInsR3; /**< Client device instance */ 265 VIRTQUEUE aVirtqueues[VIRTQ_MAX_COUNT]; /**< (MMIO) VirtIO contexts for queues */ 266 uint64_t uDeviceFeatures; /**< (MMIO) Host features offered HOST */ 267 uint64_t uDriverFeatures; /**< (MMIO) Host features accepted GUEST */ 268 uint32_t uDeviceFeaturesSelect; /**< (MMIO) hi/lo select uDeviceFeatures GUEST */ 269 uint32_t uDriverFeaturesSelect; /**< (MMIO) hi/lo select uDriverFeatures GUEST */ 270 uint32_t uMsixConfig; /**< (MMIO) MSI-X vector GUEST */ 271 uint8_t fDeviceStatus; /**< (MMIO) Device Status GUEST */ 272 uint8_t uPrevDeviceStatus; /**< (MMIO) Prev Device Status GUEST */ 273 uint8_t uConfigGeneration; /**< (MMIO) Device config sequencer HOST */ 278 274 279 275 /** @name The locations of the capability structures in PCI config space and the BAR. 280 276 * @{ */ 281 VIRTIO_PCI_CAP_LOCATIONS_T LocPciCfgCap; 282 VIRTIO_PCI_CAP_LOCATIONS_T LocNotifyCap; 283 VIRTIO_PCI_CAP_LOCATIONS_T LocCommonCfgCap; 284 VIRTIO_PCI_CAP_LOCATIONS_T LocIsrCap; 285 VIRTIO_PCI_CAP_LOCATIONS_T LocDeviceCap; 277 VIRTIO_PCI_CAP_LOCATIONS_T LocPciCfgCap; /**< VIRTIO_PCI_CFG_CAP_T */ 278 VIRTIO_PCI_CAP_LOCATIONS_T LocNotifyCap; /**< VIRTIO_PCI_NOTIFY_CAP_T */ 279 VIRTIO_PCI_CAP_LOCATIONS_T LocCommonCfgCap; /**< VIRTIO_PCI_CAP_T */ 280 VIRTIO_PCI_CAP_LOCATIONS_T LocIsrCap; /**< VIRTIO_PCI_CAP_T */ 281 VIRTIO_PCI_CAP_LOCATIONS_T LocDeviceCap; /**< VIRTIO_PCI_CAP_T + custom data. */ 286 282 /** @} */ 287 283 288 bool fGenUpdatePending; /**< If set, update cfg gen after driver reads */ 289 uint8_t uPciCfgDataOff; /**< Offset to PCI configuration data area */ 290 uint8_t uISR; /**< Interrupt Status Register. */ 291 uint8_t fMsiSupport; /**< Flag set if using MSI instead of ISR */ 284 uint16_t uVirtqSelect; /**< (MMIO) queue selector GUEST */ 285 bool fGenUpdatePending; /**< If set, update cfg gen after driver reads */ 286 uint8_t uPciCfgDataOff; /**< Offset to PCI configuration data area */ 287 uint8_t uISR; /**< Interrupt Status Register. */ 288 uint8_t fMsiSupport; /**< Flag set if using MSI instead of ISR */ 292 289 /** The MMIO handle for the PCI capability region (\#2). */ 293 290 IOMMMIOHANDLE hMmioPciCap; … … 416 413 * queue management, informing the core of the name of the queue associated spec-defined 417 414 * device specific queue number (which also happens to be the index into VirtIO's array 418 * of queue structs]. 415 * of queue structs]. uVirtqNbr is used as the 'handle' for virt queues in this API. 416 * They are unambiguous (the VirtIO specification defines how virtq numbers are assigned 417 * for each device type), and it helps prevent muddying of the core state by devices 418 * and vice versa by eliminating direct access to otherwise private structs. 419 419 * 420 420 * @param pVirtio Pointer to the shared virtio state. … … 477 477 * using the command: "VboxManage debugvm <VM name or id> info <device name> [args]" 478 478 * 479 * Example: VBoxManage debugvm myVnetVm info "virtio-net" all479 * Example: VBoxManage debugvm myVnetVm info "virtio-net" help 480 480 * 481 481 * This is implemented currently to be invoked by the inheriting device-specific code … … 505 505 * operation if virtioCoreR3VirtqAvailRingNext() is called to consume the buffer from the avail ring, 506 506 * at which point virtioCoreR3VirtqUsedBufPut() must be called to complete the roundtrip 507 * transaction putting the descriptor on the used ring.507 * transaction by putting the descriptor on the used ring. 508 508 * 509 509 * … … 579 579 * intervening a roundtrip transaction, wherein I/O transactions are always initiated by 580 580 * the guest and completed by the host. In other words, for the host to send any data to the 581 * guest, the guest must provide buffers for the host to fill tothe avail ring of the581 * guest, the guest must provide buffers, for the host to fill, via the avail ring of the 582 582 * virtq. 583 583 * … … 697 697 DECLINLINE(bool) virtioCoreIsVirtqEnabled(PVIRTIOCORE pVirtio, uint16_t uVirtqNbr) 698 698 { 699 Assert(uVirtqNbr < RT_ELEMENTS(pVirtio->aVirtq State));700 return pVirtio-> uVirtqEnable[uVirtqNbr]!= 0;699 Assert(uVirtqNbr < RT_ELEMENTS(pVirtio->aVirtqueues)); 700 return pVirtio->aVirtqueues[uVirtqNbr].uEnable != 0; 701 701 } 702 702 … … 711 711 DECLINLINE(const char *) virtioCoreVirtqGetName(PVIRTIOCORE pVirtio, uint16_t uVirtqNbr) 712 712 { 713 Assert((size_t)uVirtqNbr < RT_ELEMENTS(pVirtio->aVirtq State));714 return pVirtio->aVirtq State[uVirtqNbr].szVirtqName;713 Assert((size_t)uVirtqNbr < RT_ELEMENTS(pVirtio->aVirtqueues)); 714 return pVirtio->aVirtqueues[uVirtqNbr].szName; 715 715 } 716 716 … … 813 813 RTGCPHYS virtioCoreGCPhysChainGetNextSeg(PVIRTIOSGBUF pGcSgBuf, size_t *pcbSeg); 814 814 RTGCPHYS virtioCoreGCPhysChainAdvance(PVIRTIOSGBUF pGcSgBuf, size_t cbAdvance); 815 void virtioCoreGCPhysChainInit(PVIRTIOSGBUF pSgBuf, PVIRTIOSGSEG paSegs, size_t cSegs);816 815 size_t virtioCoreGCPhysChainCalcBufSize(PCVIRTIOSGBUF pGcSgBuf); 817 816 … … 928 927 uint32_t uOffsetInMember = uOffsetOfAccess - RT_UOFFSETOF(tCfgStruct, member); \ 929 928 if (fWrite) \ 930 memcpy(((char *)&(pCfgStruct )->member[uIdx]) + uOffsetInMember, pv, cb); \929 memcpy(((char *)&(pCfgStruct[uIdx].member)) + uOffsetInMember, pv, cb); \ 931 930 else \ 932 memcpy(pv, ((const char *)&(pCfgStruct )->member[uIdx]) + uOffsetInMember, cb); \931 memcpy(pv, ((const char *)&(pCfgStruct[uIdx].member)) + uOffsetInMember, cb); \ 933 932 VIRTIO_DEV_CONFIG_LOG_INDEXED_ACCESS(member, tCfgStruct, uOffsetOfAccess, uIdx); \ 934 933 } while(0) … … 948 947 else \ 949 948 { \ 950 memcpy(pv, ((const char *)&(pCfgStruct )->member[uIdx]) + uOffsetInMember, cb); \949 memcpy(pv, ((const char *)&(pCfgStruct[uIdx].member)) + uOffsetInMember, cb); \ 951 950 VIRTIO_DEV_CONFIG_LOG_INDEXED_ACCESS(member, tCfgStruct, uOffsetOfAccess, uIdx); \ 952 951 } \
Note:
See TracChangeset
for help on using the changeset viewer.