Changeset 84351 in vbox
- Timestamp:
- May 19, 2020 5:26:12 AM (5 years ago)
- svn:sync-xref-src-repo-rev:
- 138040
- Location:
- trunk/src/VBox/Devices
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Network/DevVirtioNet_1_0.cpp
r84048 r84351 31 31 #define LOG_GROUP LOG_GROUP_DEV_VIRTIO 32 32 #define VIRTIONET_WITH_GSO 33 33 34 #include <iprt/types.h> 34 35 #include <iprt/errcore.h> 36 #include <iprt/assert.h> 37 #include <iprt/string.h> 38 39 #include <VBox/sup.h> 35 40 #include <VBox/vmm/pdmdev.h> 36 41 #include <VBox/vmm/stam.h> … … 39 44 #include <VBox/msi.h> 40 45 #include <VBox/version.h> 41 //#include <VBox/asm.h>42 46 #include <VBox/log.h> 43 #include <iprt/errcore.h> 44 #include <iprt/assert.h> 45 #include <iprt/string.h> 46 #include <VBox/sup.h> 47 47 48 #ifdef IN_RING3 48 #include <VBox/VBoxPktDmp.h> 49 #endif 50 #ifdef IN_RING3 49 # include <VBox/VBoxPktDmp.h> 51 50 # include <iprt/alloc.h> 52 51 # include <iprt/memcache.h> … … 61 60 62 61 /* After debugging single instance case, restore instance name logging */ 63 #define INSTANCE(pState) (char *)(pState->szInstanceName ? "": "") // Avoid requiring RT_NOREF in some funcs62 #define INSTANCE(pState) (char *)(pState->szInstanceName ? pState->szInstanceName : "") // Avoid requiring RT_NOREF in some funcs 64 63 65 64 #define VIRTIONET_SAVED_STATE_VERSION UINT32_C(1) … … 99 98 100 99 #define LUN0 0 100 101 #ifdef USING_CRITICAL_SECTION 102 # define ENTER_CRITICAL_SECTION \ 103 do { \ 104 int rc = virtioNetR3CsEnter(pDevIns, pThis, VERR_SEM_BUSY); \ 105 AssertRCReturnVoid(rc); \ 106 RT_NOREF(rc); 107 } while(0) 108 # define LEAVE_CRITICAL_SECTION \ 109 do { \ 110 virtioNetR3CsLeave(pDevIns, pThis); \ 111 } while(0) 112 #else 113 # define ENTER_CRITICAL_SECTION do { } while(0) 114 # define LEAVE_CRITICAL_SECTION do { } while(0) 115 #endif 101 116 102 117 /* … … 294 309 { 295 310 SUPSEMEVENT hEvtProcess; /**< handle of associated sleep/wake-up semaphore */ 311 bool volatile fSleeping; /**< Flags whether worker thread is sleeping or not */ 312 bool volatile fNotified; /**< Flags whether worker thread notified */ 296 313 } VIRTIONETWORKER; 297 314 /** Pointer to a VirtIO SCSI worker. */ … … 304 321 { 305 322 R3PTRTYPE(PPDMTHREAD) pThread; /**< pointer to worker thread's handle */ 306 bool volatile fSleeping; /**< Flags whether worker thread is sleeping or not */307 bool volatile fNotified; /**< Flags whether worker thread notified */308 323 uint16_t idxQueue; /**< Index of associated queue */ 309 324 } VIRTIONETWORKERR3; … … 530 545 typedef CTX_SUFF(PVIRTIONET) PVIRTIONETCC; 531 546 547 /** 548 * Wakeup the RX thread. 549 */ 550 static void virtioNetWakeupRxBufWaiter(PPDMDEVINS pDevIns) 551 { 552 PVIRTIONET pThis = PDMDEVINS_2_DATA(pDevIns, PVIRTIONET); 553 554 AssertReturnVoid(pThis->hEventRxDescAvail != NIL_SUPSEMEVENT); 555 556 STAM_COUNTER_INC(&pThis->StatRxOverflowWakeup); 557 558 Log10Func(("%s Waking downstream driver's Rx buf waiter thread\n", INSTANCE(pThis))); 559 int rc = PDMDevHlpSUPSemEventSignal(pDevIns, pThis->hEventRxDescAvail); 560 AssertRC(rc); 561 } 562 563 /** 564 * @callback_method_impl{VIRTIOCORER0,pfnQueueNotified} 565 */ 566 static DECLCALLBACK(void) virtioNetQueueNotified(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t idxQueue) 567 { 568 RT_NOREF(pVirtio); 569 PVIRTIONET pThis = PDMDEVINS_2_DATA(pDevIns, PVIRTIONET); 570 571 uint16_t idxWorker; 572 if (idxQueue == CTRLQIDX) 573 idxWorker = pThis->cWorkers - 1; 574 else 575 idxWorker = idxQueue / 2; 576 577 PVIRTIONETWORKER pWorker = &pThis->aWorkers[idxWorker]; 578 AssertReturnVoid(idxQueue < pThis->cVirtQueues); 579 580 #if defined (IN_RING3) && defined (LOG_ENABLED) 581 RTLogFlush(NULL); 582 #endif 583 584 Log10Func(("%s %s has available buffers\n", INSTANCE(pThis), VIRTQNAME(idxQueue))); 585 586 if (IS_RX_QUEUE(idxQueue)) 587 { 588 Log10Func(("%s Receive buffers have been added, waking Rx thread.\n", 589 INSTANCE(pThis))); 590 virtioNetWakeupRxBufWaiter(pDevIns); 591 } 592 else 593 { 594 /* Wake queue's worker thread up if sleeping (e.g. a Tx queue, or the control queue */ 595 if (!ASMAtomicXchgBool(&pWorker->fNotified, true)) 596 { 597 if (ASMAtomicReadBool(&pWorker->fSleeping)) 598 { 599 Log10Func(("%s waking %s worker.\n", INSTANCE(pThis), VIRTQNAME(idxQueue))); 600 int rc = PDMDevHlpSUPSemEventSignal(pDevIns, pWorker->hEvtProcess); 601 AssertRC(rc); 602 } 603 } 604 } 605 } 606 532 607 #ifdef IN_RING3 /* spans most of the file, at the moment. */ 533 608 … … 542 617 } 543 618 544 /**545 * Wakeup the RX thread.546 */547 static void virtioNetR3WakeupRxBufWaiter(PPDMDEVINS pDevIns)548 {549 PVIRTIONET pThis = PDMDEVINS_2_DATA(pDevIns, PVIRTIONET);550 551 AssertReturnVoid(pThis->hEventRxDescAvail != NIL_SUPSEMEVENT);552 553 STAM_COUNTER_INC(&pThis->StatRxOverflowWakeup);554 555 Log10Func(("%s Waking downstream driver's Rx buf waiter thread\n", INSTANCE(pThis)));556 int rc = PDMDevHlpSUPSemEventSignal(pDevIns, pThis->hEventRxDescAvail);557 AssertRC(rc);558 }559 619 560 620 DECLINLINE(void) virtioNetR3SetVirtqNames(PVIRTIONET pThis) … … 1033 1093 * to tell it that's going to happen... 1034 1094 */ 1035 virtioNet R3WakeupRxBufWaiter(pDevIns);1095 virtioNetWakeupRxBufWaiter(pDevIns); 1036 1096 1037 1097 PDMDevHlpSetAsyncNotification(pDevIns, virtioNetR3DeviceQuiesced); … … 1068 1128 1069 1129 virtioNetR3QuiesceDevice(pDevIns, enmType); 1070 virtioNet R3WakeupRxBufWaiter(pDevIns);1130 virtioNetWakeupRxBufWaiter(pDevIns); 1071 1131 } 1072 1132 … … 2158 2218 } 2159 2219 2160 int cPkts = virtioCoreR3QueuePendingCount(pVirtio->pDevIns , pVirtio, idxTxQueue);2220 int cPkts = virtioCoreR3QueuePendingCount(pVirtio->pDevInsR3, pVirtio, idxTxQueue); 2161 2221 if (!cPkts) 2162 2222 { … … 2175 2235 int rc; 2176 2236 PVIRTIO_DESC_CHAIN_T pDescChain = NULL; 2177 while ((rc = virtioCoreR3QueuePeek(pVirtio->pDevIns , pVirtio, idxTxQueue, &pDescChain)) == VINF_SUCCESS)2237 while ((rc = virtioCoreR3QueuePeek(pVirtio->pDevInsR3, pVirtio, idxTxQueue, &pDescChain)) == VINF_SUCCESS) 2178 2238 { 2179 2239 Log10Func(("%s fetched descriptor chain from %s\n", INSTANCE(pThis), VIRTQNAME(idxTxQueue))); … … 2205 2265 uint64_t uOffset; 2206 2266 2207 /** @todo Optimize away the extra copying! (lazy bird) */2208 2267 PPDMSCATTERGATHER pSgBufToPdmLeafDevice; 2209 2268 rc = pThisCC->pDrv->pfnAllocBuf(pThisCC->pDrv, uSize, pGso, &pSgBufToPdmLeafDevice); … … 2265 2324 2266 2325 /* No data to return to guest, but call is needed put elem (e.g. desc chain) on used ring */ 2267 virtioCoreR3QueuePut(pVirtio->pDevIns , pVirtio, idxTxQueue, NULL, pDescChain, false);2326 virtioCoreR3QueuePut(pVirtio->pDevInsR3, pVirtio, idxTxQueue, NULL, pDescChain, false); 2268 2327 2269 2328 /* Update used ring idx and notify guest that we've transmitted the data it sent */ 2270 virtioCoreQueueSync(pVirtio->pDevIns , pVirtio, idxTxQueue, false);2329 virtioCoreQueueSync(pVirtio->pDevInsR3, pVirtio, idxTxQueue, false); 2271 2330 } 2272 2331 … … 2297 2356 selection algorithm feasible or even necessary */ 2298 2357 virtioNetR3TransmitPendingPackets(pDevIns, pThis, pThisCC, TXQIDX(0), false /*fOnWorkerThread*/); 2299 }2300 2301 /**2302 * @callback_method_impl{VIRTIOCORER3,pfnQueueNotified}2303 */2304 static DECLCALLBACK(void) virtioNetR3QueueNotified(PVIRTIOCORE pVirtio, PVIRTIOCORECC pVirtioCC, uint16_t idxQueue)2305 {2306 PVIRTIONET pThis = RT_FROM_MEMBER(pVirtio, VIRTIONET, Virtio);2307 PVIRTIONETCC pThisCC = RT_FROM_MEMBER(pVirtioCC, VIRTIONETCC, Virtio);2308 PPDMDEVINS pDevIns = pThisCC->pDevIns;2309 2310 uint16_t idxWorker;2311 if (idxQueue == CTRLQIDX)2312 idxWorker = pThis->cWorkers - 1;2313 else2314 idxWorker = idxQueue / 2;2315 2316 PVIRTIONETWORKER pWorker = &pThis->aWorkers[idxWorker];2317 PVIRTIONETWORKERR3 pWorkerR3 = &pThisCC->aWorkers[idxWorker];2318 AssertReturnVoid(idxQueue < pThis->cVirtQueues);2319 2320 #ifdef LOG_ENABLED2321 RTLogFlush(NULL);2322 #endif2323 2324 Log10Func(("%s %s has available buffers\n", INSTANCE(pThis), VIRTQNAME(idxQueue)));2325 2326 if (IS_RX_QUEUE(idxQueue))2327 {2328 Log10Func(("%s Receive buffers have been added, waking Rx thread.\n",2329 INSTANCE(pThis)));2330 virtioNetR3WakeupRxBufWaiter(pDevIns);2331 }2332 else2333 {2334 /* Wake queue's worker thread up if sleeping (e.g. a Tx queue, or the control queue */2335 if (!ASMAtomicXchgBool(&pWorkerR3->fNotified, true))2336 {2337 if (ASMAtomicReadBool(&pWorkerR3->fSleeping))2338 {2339 Log10Func(("%s waking %s worker.\n", INSTANCE(pThis), VIRTQNAME(idxQueue)));2340 int rc = PDMDevHlpSUPSemEventSignal(pDevIns, pWorker->hEvtProcess);2341 AssertRC(rc);2342 }2343 }2344 }2345 2358 } 2346 2359 … … 2367 2380 if (virtioCoreQueueIsEmpty(pDevIns, &pThis->Virtio, idxQueue)) 2368 2381 { 2382 /* Atomic interlocks avoid missing alarm while going to sleep & notifier waking the awoken */ 2369 2383 virtioCoreQueueSetNotify(&pThis->Virtio, idxQueue, true); 2370 /* Atomic interlocks avoid missing alarm while going to sleep & notifier waking the awoken */ 2371 ASMAtomicWriteBool(&pWorkerR3->fSleeping, true); 2372 bool fNotificationSent = ASMAtomicXchgBool(&pWorkerR3->fNotified, false); 2384 ASMAtomicWriteBool(&pWorker->fSleeping, true); 2385 bool fNotificationSent = ASMAtomicXchgBool(&pWorker->fNotified, false); 2373 2386 if (!fNotificationSent) 2374 2387 { 2375 virtioCoreQueueSetNotify(&pThis->Virtio, idxQueue, true);2376 2388 Log10Func(("%s %s worker sleeping...\n", INSTANCE(pThis), VIRTQNAME(idxQueue))); 2377 Assert(ASMAtomicReadBool(&pWorker R3->fSleeping));2389 Assert(ASMAtomicReadBool(&pWorker->fSleeping)); 2378 2390 int rc = PDMDevHlpSUPSemEventWaitNoResume(pDevIns, pWorker->hEvtProcess, RT_INDEFINITE_WAIT); 2379 2391 STAM_COUNTER_INC(&pThis->StatTransmitByThread); … … 2387 2399 } 2388 2400 Log10Func(("%s %s worker woken\n", INSTANCE(pThis), VIRTQNAME(idxQueue))); 2389 ASMAtomicWriteBool(&pWorker R3->fNotified, false);2401 ASMAtomicWriteBool(&pWorker->fNotified, false); 2390 2402 } 2391 ASMAtomicWriteBool(&pWorker R3->fSleeping, false);2403 ASMAtomicWriteBool(&pWorker->fSleeping, false); 2392 2404 virtioCoreQueueSetNotify(&pThis->Virtio, idxQueue, false); 2393 2405 } … … 2414 2426 Log10Func(("%s Notified of data to transmit\n", INSTANCE(pThis))); 2415 2427 virtioNetR3TransmitPendingPackets(pDevIns, pThis, pThisCC, 2416 idxQueue, true /* fOnWorkerThread */);2428 idxQueue, false /* fOnWorkerThread */); 2417 2429 } 2418 2430 2419 2431 /* Rx queues aren't handled by our worker threads. Instead, the PDM network 2420 2432 * leaf driver invokes PDMINETWORKDOWN.pfnWaitReceiveAvail() callback, 2421 * which waits until notified directly by virtioNet R3QueueNotified()2433 * which waits until notified directly by virtioNetQueueNotified() 2422 2434 * that guest IN buffers have been added to receive virt queue. 2423 2435 */ … … 2427 2439 } 2428 2440 2441 #ifdef USING_CRITICAL_SECTION 2429 2442 DECLINLINE(int) virtioNetR3CsEnter(PPDMDEVINS pDevIns, PVIRTIONET pThis, int rcBusy) 2430 2443 { … … 2440 2453 LogFunc(("%s CS unimplemented. What does the critical section protect in orig driver??", INSTANCE(pThis))); 2441 2454 } 2442 2455 #endif /* USING_CRITICAL_SECTION */ 2443 2456 2444 2457 /** … … 2451 2464 RT_NOREF(pTimer, pvUser); 2452 2465 2453 int rc = virtioNetR3CsEnter(pDevIns, pThis, VERR_SEM_BUSY); 2454 AssertRCReturnVoid(rc); 2466 ENTER_CRITICAL_SECTION; 2455 2467 2456 2468 SET_LINK_UP(pThis); 2457 2469 2458 virtioNet R3WakeupRxBufWaiter(pDevIns);2459 2460 virtioNetR3CsLeave(pDevIns, pThis);2470 virtioNetWakeupRxBufWaiter(pDevIns); 2471 2472 LEAVE_CRITICAL_SECTION; 2461 2473 2462 2474 LogFunc(("%s Link is up\n", INSTANCE(pThis))); … … 2646 2658 (void) virtioCoreR3QueueAttach(&pThis->Virtio, idxQueue, VIRTQNAME(idxQueue)); 2647 2659 pThis->afQueueAttached[idxQueue] = true; 2648 virtioCoreQueueIsEmpty(pThisCC->pDevIns, &pThis->Virtio, idxQueue);2649 virtioCoreQueueSetNotify(&pThis->Virtio, idxQueue, true);2660 if (virtioCoreQueueIsEmpty(pThisCC->pDevIns, &pThis->Virtio, idxQueue)) 2661 virtioCoreQueueSetNotify(&pThis->Virtio, idxQueue, true); 2650 2662 } 2651 2663 } … … 2695 2707 AssertLogRelReturnVoid(iLUN == 0); 2696 2708 2697 int rc = virtioNetR3CsEnter(pDevIns, pThis, VERR_SEM_BUSY); 2698 AssertMsgRCReturnVoid(rc, ("Failed to enter critical section")); 2709 ENTER_CRITICAL_SECTION; 2710 2711 RT_NOREF(pThis); 2699 2712 2700 2713 /* … … 2704 2717 pThisCC->pDrv = NULL; 2705 2718 2706 virtioNetR3CsLeave(pDevIns, pThis);2719 LEAVE_CRITICAL_SECTION; 2707 2720 } 2708 2721 … … 2723 2736 AssertLogRelReturn(iLUN == 0, VERR_PDM_NO_SUCH_LUN); 2724 2737 2725 int rc = virtioNetR3CsEnter(pDevIns, pThis, VERR_SEM_BUSY); 2726 AssertMsgRCReturn(rc, ("Failed to enter critical section"), rc); 2727 2728 rc = PDMDevHlpDriverAttach(pDevIns, 0, &pDevIns->IBase, &pThisCC->pDrvBase, "Network Port"); 2738 ENTER_CRITICAL_SECTION; 2739 2740 RT_NOREF(pThis); 2741 2742 int rc = PDMDevHlpDriverAttach(pDevIns, 0, &pDevIns->IBase, &pThisCC->pDrvBase, "Network Port"); 2729 2743 if (RT_SUCCESS(rc)) 2730 2744 { … … 2737 2751 Log(("%s No attached driver!\n", INSTANCE(pThis))); 2738 2752 2739 virtioNetR3CsLeave(pDevIns, pThis);2753 LEAVE_CRITICAL_SECTION; 2740 2754 return rc; 2741 2755 … … 2811 2825 */ 2812 2826 Log7Func(("PDM device instance: %d\n", iInstance)); 2813 2814 2827 2815 2828 RTStrPrintf(pThis->szInstanceName, sizeof(pThis->szInstanceName), "VIRTIONET", iInstance); … … 2864 2877 memcpy(pThis->virtioNetConfig.uMacAddress.au8, pThis->macConfigured.au8, sizeof(pThis->virtioNetConfig.uMacAddress)); /* TBD */ 2865 2878 2879 2880 LogFunc(("RC=%RTbool R0=%RTbool\n", pDevIns->fRCEnabled, pDevIns->fR0Enabled)); 2881 2866 2882 /* 2867 2883 * Do core virtio initialization. … … 2877 2893 2878 2894 /* Initialize the generic Virtio core: */ 2895 pThisCC->Virtio.pfnQueueNotified = virtioNetQueueNotified; 2879 2896 pThisCC->Virtio.pfnStatusChanged = virtioNetR3StatusChanged; 2880 pThisCC->Virtio.pfnQueueNotified = virtioNetR3QueueNotified;2881 2897 pThisCC->Virtio.pfnDevCapRead = virtioNetR3DevCapRead; 2882 2898 pThisCC->Virtio.pfnDevCapWrite = virtioNetR3DevCapWrite; … … 3014 3030 PVIRTIONET pThis = PDMDEVINS_2_DATA(pDevIns, PVIRTIONET); 3015 3031 PVIRTIONETCC pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PVIRTIONETCC); 3016 3017 LogRelFunc(("\n")); 3018 return virtioCoreRZInit(pDevIns, &pThis->Virtio, &pThisCC->Virtio); 3032 pThisCC->Virtio.pfnQueueNotified = virtioNetQueueNotified; 3033 return virtioCoreRZInit(pDevIns, &pThis->Virtio); 3019 3034 } 3020 3035 3021 3036 #endif /* !IN_RING3 */ 3022 3037 3023 3024 3025 3038 /** 3026 3039 * The device registration structure. … … 3028 3041 const PDMDEVREG g_DeviceVirtioNet_1_0 = 3029 3042 { 3030 /* .uVersion = */ PDM_DEVREG_VERSION,3043 /* .uVersion = */ PDM_DEVREG_VERSION, 3031 3044 /* .uReserved0 = */ 0, 3032 3045 /* .szName = */ "virtio-net-1-dot-0", 3033 /* .fFlags = */ PDM_DEVREG_FLAGS_DEFAULT_BITS | PDM_DEVREG_FLAGS_NEW_STYLE | PDM_DEVREG_FLAGS_RZ 3034 | PDM_DEVREG_FLAGS_FIRST_SUSPEND_NOTIFICATION 3035 | PDM_DEVREG_FLAGS_FIRST_POWEROFF_NOTIFICATION, 3046 /* .fFlags = */ PDM_DEVREG_FLAGS_DEFAULT_BITS | PDM_DEVREG_FLAGS_NEW_STYLE | PDM_DEVREG_FLAGS_RZ, 3036 3047 /* .fClass = */ PDM_DEVREG_CLASS_NETWORK, 3037 3048 /* .cMaxInstances = */ ~0U, -
trunk/src/VBox/Devices/Storage/DevVirtioSCSI.cpp
r84003 r84351 343 343 { 344 344 SUPSEMEVENT hEvtProcess; /**< handle of associated sleep/wake-up semaphore */ 345 bool volatile fSleeping; /**< Flags whether worker thread is sleeping or not */ 346 bool volatile fNotified; /**< Flags whether worker thread notified */ 345 347 } VIRTIOSCSIWORKER; 346 348 /** Pointer to a VirtIO SCSI worker. */ … … 353 355 { 354 356 R3PTRTYPE(PPDMTHREAD) pThread; /**< pointer to worker thread's handle */ 355 bool volatile fSleeping; /**< Flags whether worker thread is sleeping or not */356 bool volatile fNotified; /**< Flags whether worker thread notified */357 357 uint16_t auRedoDescs[VIRTQ_MAX_SIZE];/**< List of previously suspended reqs to re-submit */ 358 358 uint16_t cRedoDescs; /**< Number of redo desc chain head desc idxes in list */ … … 567 567 } VIRTIOSCSIREQ; 568 568 typedef VIRTIOSCSIREQ *PVIRTIOSCSIREQ; 569 570 571 /** 572 * @callback_method_impl{VIRTIOCORER0,pfnQueueNotified} 573 */ 574 static DECLCALLBACK(void) virtioScsiNotified(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t qIdx) 575 { 576 577 RT_NOREF(pVirtio); 578 PVIRTIOSCSI pThis = PDMDEVINS_2_DATA(pDevIns, PVIRTIOSCSI); 579 580 AssertReturnVoid(qIdx < VIRTIOSCSI_QUEUE_CNT); 581 PVIRTIOSCSIWORKER pWorker = &pThis->aWorkers[qIdx]; 582 583 #if defined (IN_RING3) && defined (LOG_ENABLED) 584 RTLogFlush(NULL); 585 #endif 586 587 if (qIdx == CONTROLQ_IDX || IS_REQ_QUEUE(qIdx)) 588 { 589 Log6Func(("%s has available data\n", VIRTQNAME(qIdx))); 590 /* Wake queue's worker thread up if sleeping */ 591 if (!ASMAtomicXchgBool(&pWorker->fNotified, true)) 592 { 593 if (ASMAtomicReadBool(&pWorker->fSleeping)) 594 { 595 Log6Func(("waking %s worker.\n", VIRTQNAME(qIdx))); 596 int rc = PDMDevHlpSUPSemEventSignal(pDevIns, pWorker->hEvtProcess); 597 AssertRC(rc); 598 } 599 } 600 } 601 else if (qIdx == EVENTQ_IDX) 602 { 603 Log3Func(("Driver queued buffer(s) to %s\n", VIRTQNAME(qIdx))); 604 // if (ASMAtomicXchgBool(&pThis->fEventsMissed, false)) 605 // virtioScsiR3ReportEventsMissed(pDevIns, pThis, 0); 606 } 607 else 608 LogFunc(("Unexpected queue idx (ignoring): %d\n", qIdx)); 609 } 569 610 570 611 … … 1509 1550 { 1510 1551 /* Atomic interlocks avoid missing alarm while going to sleep & notifier waking the awoken */ 1511 ASMAtomicWriteBool(&pWorker R3->fSleeping, true);1512 bool fNotificationSent = ASMAtomicXchgBool(&pWorker R3->fNotified, false);1552 ASMAtomicWriteBool(&pWorker->fSleeping, true); 1553 bool fNotificationSent = ASMAtomicXchgBool(&pWorker->fNotified, false); 1513 1554 if (!fNotificationSent) 1514 1555 { 1515 1556 Log6Func(("%s worker sleeping...\n", VIRTQNAME(qIdx))); 1516 Assert(ASMAtomicReadBool(&pWorker R3->fSleeping));1557 Assert(ASMAtomicReadBool(&pWorker->fSleeping)); 1517 1558 int rc = PDMDevHlpSUPSemEventWaitNoResume(pDevIns, pWorker->hEvtProcess, RT_INDEFINITE_WAIT); 1518 1559 AssertLogRelMsgReturn(RT_SUCCESS(rc) || rc == VERR_INTERRUPTED, ("%Rrc\n", rc), rc); … … 1522 1563 continue; 1523 1564 Log6Func(("%s worker woken\n", VIRTQNAME(qIdx))); 1524 ASMAtomicWriteBool(&pWorker R3->fNotified, false);1565 ASMAtomicWriteBool(&pWorker->fNotified, false); 1525 1566 } 1526 ASMAtomicWriteBool(&pWorker R3->fSleeping, false);1567 ASMAtomicWriteBool(&pWorker->fSleeping, false); 1527 1568 } 1528 1569 … … 1624 1665 1625 1666 #endif 1626 1627 /**1628 * @callback_method_impl{VIRTIOCORER3,pfnQueueNotified}1629 */1630 static DECLCALLBACK(void) virtioScsiR3Notified(PVIRTIOCORE pVirtio, PVIRTIOCORECC pVirtioCC, uint16_t qIdx)1631 {1632 PVIRTIOSCSI pThis = RT_FROM_MEMBER(pVirtio, VIRTIOSCSI, Virtio);1633 PVIRTIOSCSICC pThisCC = RT_FROM_MEMBER(pVirtioCC, VIRTIOSCSICC, Virtio);1634 PPDMDEVINS pDevIns = pThisCC->pDevIns;1635 AssertReturnVoid(qIdx < VIRTIOSCSI_QUEUE_CNT);1636 PVIRTIOSCSIWORKER pWorker = &pThis->aWorkers[qIdx];1637 PVIRTIOSCSIWORKERR3 pWorkerR3 = &pThisCC->aWorkers[qIdx];1638 1639 #ifdef LOG_ENABLED1640 RTLogFlush(NULL);1641 #endif1642 1643 if (qIdx == CONTROLQ_IDX || IS_REQ_QUEUE(qIdx))1644 {1645 Log6Func(("%s has available data\n", VIRTQNAME(qIdx)));1646 /* Wake queue's worker thread up if sleeping */1647 if (!ASMAtomicXchgBool(&pWorkerR3->fNotified, true))1648 {1649 if (ASMAtomicReadBool(&pWorkerR3->fSleeping))1650 {1651 Log6Func(("waking %s worker.\n", VIRTQNAME(qIdx)));1652 int rc = PDMDevHlpSUPSemEventSignal(pDevIns, pWorker->hEvtProcess);1653 AssertRC(rc);1654 }1655 }1656 }1657 else if (qIdx == EVENTQ_IDX)1658 {1659 Log3Func(("Driver queued buffer(s) to %s\n", VIRTQNAME(qIdx)));1660 if (ASMAtomicXchgBool(&pThis->fEventsMissed, false))1661 virtioScsiR3ReportEventsMissed(pDevIns, pThis, 0);1662 }1663 else1664 LogFunc(("Unexpected queue idx (ignoring): %d\n", qIdx));1665 }1666 1667 1667 1668 /** … … 2320 2321 for (uint16_t qIdx = 0; qIdx < VIRTIOSCSI_REQ_QUEUE_CNT; qIdx++) 2321 2322 { 2322 if (ASMAtomicReadBool(&pThis CC->aWorkers[qIdx].fSleeping))2323 if (ASMAtomicReadBool(&pThis->aWorkers[qIdx].fSleeping)) 2323 2324 { 2324 2325 Log6Func(("waking %s worker.\n", VIRTQNAME(qIdx))); … … 2436 2437 */ 2437 2438 pThisCC->pDevIns = pDevIns; 2439 // pDevIns->pVirtio = &pThis->Virtio; 2438 2440 2439 2441 LogFunc(("PDM device instance: %d\n", iInstance)); … … 2481 2483 2482 2484 /* Initialize the generic Virtio core: */ 2485 pThisCC->Virtio.pfnQueueNotified = virtioScsiNotified; 2483 2486 pThisCC->Virtio.pfnStatusChanged = virtioScsiR3StatusChanged; 2484 pThisCC->Virtio.pfnQueueNotified = virtioScsiR3Notified;2485 2487 pThisCC->Virtio.pfnDevCapRead = virtioScsiR3DevCapRead; 2486 2488 pThisCC->Virtio.pfnDevCapWrite = virtioScsiR3DevCapWrite; … … 2642 2644 { 2643 2645 PDMDEV_CHECK_VERSIONS_RETURN(pDevIns); 2646 2644 2647 PVIRTIOSCSI pThis = PDMDEVINS_2_DATA(pDevIns, PVIRTIOSCSI); 2645 2648 PVIRTIOSCSICC pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PVIRTIOSCSICC); 2646 2649 2647 return virtioCoreRZInit(pDevIns, &pThis->Virtio, &pThisCC->Virtio); 2650 2651 pThisCC->Virtio.pfnQueueNotified = virtioScsiNotified; 2652 return virtioCoreRZInit(pDevIns, &pThis->Virtio); 2648 2653 } 2649 2654 -
trunk/src/VBox/Devices/VirtIO/Virtio_1_0.cpp
r83915 r84351 123 123 * @{ */ 124 124 125 #if 0 /* unused */126 DECLINLINE(int) virtqIsEventNeeded(uint16_t uEventIdx, uint16_t uDescIdxNew, uint16_t uDescIdxOld)127 {128 return (uint16_t)(uDescIdxNew - uEventIdx - 1) < (uint16_t)(uDescIdxNew - uDescIdxOld);129 }130 #endif131 132 125 /** 133 126 * Accessor for virtq descriptor … … 160 153 return uDescIdx; 161 154 } 162 #endif 163 164 DECLINLINE(uint16_t) virtioReadAvailRingIdx(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t idxQueue) 165 { 166 uint16_t uIdx = 0; 167 AssertMsg(pVirtio->uDeviceStatus & VIRTIO_STATUS_DRIVER_OK, ("Called with guest driver not ready\n")); 168 PDMDevHlpPCIPhysRead(pDevIns, 169 pVirtio->aGCPhysQueueAvail[idxQueue] + RT_UOFFSETOF(VIRTQ_AVAIL_T, uIdx), 170 &uIdx, sizeof(uIdx)); 171 return uIdx; 172 } 173 174 DECLINLINE(bool) virtqIsEmpty(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t idxQueue) 175 { 176 uint16_t uAvailGuestIdx = virtioReadAvailRingIdx(pDevIns, pVirtio, idxQueue); 177 bool fEmpty = uAvailGuestIdx == pVirtio->virtqState[idxQueue].uAvailIdx; 178 179 Log6Func(("%s idx=%u, shadow idx=%u (%s)\n", 180 VIRTQNAME(pVirtio, idxQueue), uAvailGuestIdx, pVirtio->virtqState[idxQueue].uAvailIdx, 181 fEmpty ? "Queue empty" : "Queue has available descriptors")); 182 return fEmpty; 183 } 184 185 #if 0 /* unused - Will be used when VIRTIO_F_EVENT_IDX optional feature is implemented, VirtIO 1.0, 2.4.7 */ 186 DECLINLINE(uint16_t) virtioReadAvailFlags(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t idxQueue) 187 { 188 uint16_t fFlags; 189 AssertMsg(pVirtio->uDeviceStatus & VIRTIO_STATUS_DRIVER_OK, ("Called with guest driver not ready\n")); 190 PDMDevHlpPCIPhysRead(pDevIns, 191 pVirtio->aGCPhysQueueAvail[idxQueue] + RT_UOFFSETOF(VIRTQ_AVAIL_T, fFlags), 192 &fFlags, sizeof(fFlags)); 193 return fFlags; 194 } 195 #endif 196 197 #ifdef IN_RING3 155 198 156 DECLINLINE(uint16_t) virtioReadAvailUsedEvent(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t idxQueue) 199 157 { … … 207 165 } 208 166 #endif 167 168 DECLINLINE(uint16_t) virtioReadAvailRingIdx(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t idxQueue) 169 { 170 uint16_t uIdx = 0; 171 AssertMsg(pVirtio->uDeviceStatus & VIRTIO_STATUS_DRIVER_OK, ("Called with guest driver not ready\n")); 172 PDMDevHlpPCIPhysRead(pDevIns, 173 pVirtio->aGCPhysQueueAvail[idxQueue] + RT_UOFFSETOF(VIRTQ_AVAIL_T, uIdx), 174 &uIdx, sizeof(uIdx)); 175 return uIdx; 176 } 177 178 DECLINLINE(bool) virtqIsEmpty(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t idxQueue) 179 { 180 uint16_t uAvailGuestIdx = virtioReadAvailRingIdx(pDevIns, pVirtio, idxQueue); 181 bool fEmpty = uAvailGuestIdx == pVirtio->virtqState[idxQueue].uAvailIdx; 182 183 Log6Func(("%s idx=%u, shadow idx=%u (%s)\n", 184 VIRTQNAME(pVirtio, idxQueue), uAvailGuestIdx, pVirtio->virtqState[idxQueue].uAvailIdx, 185 fEmpty ? "Queue empty" : "Queue has available descriptors")); 186 return fEmpty; 187 } 188 189 DECLINLINE(uint16_t) virtioReadAvailRingFlags(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t idxQueue) 190 { 191 uint16_t fFlags; 192 AssertMsg(pVirtio->uDeviceStatus & VIRTIO_STATUS_DRIVER_OK, ("Called with guest driver not ready\n")); 193 PDMDevHlpPCIPhysRead(pDevIns, 194 pVirtio->aGCPhysQueueAvail[idxQueue] + RT_UOFFSETOF(VIRTQ_AVAIL_T, fFlags), 195 &fFlags, sizeof(fFlags)); 196 return fFlags; 197 } 209 198 210 199 /** @} */ … … 422 411 for (unsigned i = 0; i < RT_ELEMENTS(s_aFeatures); ++i) 423 412 { 424 bool isOffered = !!(pVirtio->uDeviceFeatures& s_aFeatures[i].fFeatureBit);425 bool isNegotiated = !!(pVirtio->uDriverFeatures& s_aFeatures[i].fFeatureBit);413 bool isOffered = RT_BOOL(pVirtio->uDeviceFeatures & s_aFeatures[i].fFeatureBit); 414 bool isNegotiated = RT_BOOL(pVirtio->uDriverFeatures & s_aFeatures[i].fFeatureBit); 426 415 cp += RTStrPrintf(cp, cbBuf - (cp - pszBuf), " %s %s %s", 427 416 isOffered ? "+" : "-", isNegotiated ? "x" : " ", s_aFeatures[i].pcszDesc); … … 810 799 void virtioCoreNotifyConfigChanged(PVIRTIOCORE pVirtio) 811 800 { 812 virtioKick(pVirtio->pDevIns , pVirtio, VIRTIO_ISR_DEVICE_CONFIG, pVirtio->uMsixConfig, false);801 virtioKick(pVirtio->pDevInsR3, pVirtio, VIRTIO_ISR_DEVICE_CONFIG, pVirtio->uMsixConfig, false); 813 802 } 814 803 … … 824 813 if (pVirtio->uDeviceStatus & VIRTIO_STATUS_DRIVER_OK) 825 814 { 826 uint16_t fFlags = virtioReadUsedRingFlags(pVirtio->pDevIns , pVirtio, idxQueue);815 uint16_t fFlags = virtioReadUsedRingFlags(pVirtio->pDevInsR3, pVirtio, idxQueue); 827 816 828 817 if (fEnabled) … … 831 820 fFlags |= VIRTQ_USED_F_NO_NOTIFY; 832 821 833 virtioWriteUsedRingFlags(pVirtio->pDevIns , pVirtio, idxQueue, fFlags);822 virtioWriteUsedRingFlags(pVirtio->pDevInsR3, pVirtio, idxQueue, fFlags); 834 823 } 835 824 } … … 848 837 { 849 838 pVirtio->fGenUpdatePending = true; 850 virtioKick(pVirtio->pDevIns , pVirtio, VIRTIO_ISR_DEVICE_CONFIG, pVirtio->uMsixConfig, false /* fForce */);839 virtioKick(pVirtio->pDevInsR3, pVirtio, VIRTIO_ISR_DEVICE_CONFIG, pVirtio->uMsixConfig, false /* fForce */); 851 840 } 852 841 } … … 915 904 ("Guest driver not in ready state.\n"), VERR_INVALID_STATE); 916 905 917 if (virtioCoreQueueIsEmpty(pVirtio->pDevIns , pVirtio, idxQueue))906 if (virtioCoreQueueIsEmpty(pVirtio->pDevInsR3, pVirtio, idxQueue)) 918 907 return VERR_NOT_AVAILABLE; 919 908 … … 1024 1013 size_t cbTarget = virtioCoreSgBufCalcTotalLength(pSgPhysReturn); 1025 1014 cbRemain = cbTotal = RTSgBufCalcTotalLength(pSgVirtReturn); 1026 AssertMsgReturn(cbTarget >= cbRemain, ("No tspace to write data to phys memory"), VERR_BUFFER_OVERFLOW);1015 AssertMsgReturn(cbTarget >= cbRemain, ("No space to write data to phys memory"), VERR_BUFFER_OVERFLOW); 1027 1016 virtioCoreSgBufReset(pSgPhysReturn); /* Reset ptr because req data may have already been written */ 1028 1017 while (cbRemain) … … 1085 1074 int virtioCoreQueueSync(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t idxQueue, bool fForce) 1086 1075 { 1087 Assert(idxQueue < RT_ELEMENTS(pVirtio->virtqState));1076 Assert(idxQueue < RT_ELEMENTS(pVirtio->virtqState)); 1088 1077 PVIRTQSTATE pVirtq = &pVirtio->virtqState[idxQueue]; 1089 1078 … … 1100 1089 } 1101 1090 1102 #ifdef IN_RING3 1103 /** 1104 */ 1105 static void virtioR3QueueNotified(PVIRTIOCORE pVirtio, PVIRTIOCORECC pVirtioCC, uint16_t idxQueue, uint16_t uNotifyIdx) 1106 { 1091 /** 1092 */ 1093 static void virtioQueueNotified(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t idxQueue, uint16_t uNotifyIdx) 1094 { 1095 1096 PVIRTIOCORECC pVirtioCC = PDMDEVINS_2_DATA_CC(pDevIns, PVIRTIOCORECC); 1097 1107 1098 /* See VirtIO 1.0, section 4.1.5.2 It implies that idxQueue and uNotifyIdx should match. 1108 1099 * Disregarding this notification may cause throughput to stop, however there's no way to know … … 1118 1109 1119 1110 /* Inform client */ 1120 pVirtioCC->pfnQueueNotified(pVirtio, pVirtioCC, idxQueue); 1121 } 1122 #endif /* IN_RING3 */ 1111 pVirtioCC->pfnQueueNotified(pDevIns, pVirtio, idxQueue); 1112 } 1123 1113 1124 1114 /** … … 1152 1142 Log6Func(("...kicking guest %s, VIRTIO_F_EVENT_IDX set and threshold (%d) reached\n", 1153 1143 VIRTQNAME(pVirtio, idxQueue), (uint16_t)virtioReadAvailUsedEvent(pDevIns, pVirtio, idxQueue))); 1154 #else1155 Log6Func(("... kicking guest %s, VIRTIO_F_EVENT_IDX set and threshold reached\n",1156 VIRTQNAME(pVirtio, idxQueue)));1157 1144 #endif 1158 1145 virtioKick(pDevIns, pVirtio, VIRTIO_ISR_VIRTQ_INTERRUPT, pVirtio->uQueueMsixVector[idxQueue], fForce); … … 1163 1150 Log6Func(("...skipping interrupt %s, VIRTIO_F_EVENT_IDX set but threshold (%d) not reached (%d)\n", 1164 1151 VIRTQNAME(pVirtio, idxQueue),(uint16_t)virtioReadAvailUsedEvent(pDevIns, pVirtio, idxQueue), pVirtq->uUsedIdx)); 1165 #else1166 Log6Func(("...skipping interrupt %s, VIRTIO_F_EVENT_IDX set but threshold not reached\n",1167 VIRTQNAME(pVirtio, idxQueue)));1168 1152 #endif 1169 1153 } … … 1171 1155 { 1172 1156 /** If guest driver hasn't suppressed interrupts, interrupt */ 1173 if (fForce || !(virtioRead UsedRingFlags(pDevIns, pVirtio, idxQueue) & VIRTQ_AVAIL_F_NO_INTERRUPT))1157 if (fForce || !(virtioReadAvailRingFlags(pDevIns, pVirtio, idxQueue) & VIRTQ_AVAIL_F_NO_INTERRUPT)) 1174 1158 { 1175 1159 if (fForce) … … 1242 1226 pVirtio->uQueueMsixVector[idxQueue] = VIRTIO_MSI_NO_VECTOR; 1243 1227 1244 virtioLowerInterrupt(pVirtio->pDevIns , pVirtio->uQueueMsixVector[idxQueue]);1228 virtioLowerInterrupt(pVirtio->pDevInsR3, pVirtio->uQueueMsixVector[idxQueue]); 1245 1229 } 1246 1230 … … 1476 1460 { 1477 1461 uint8_t const fNewStatus = *(uint8_t *)pv; 1478 Log7Func(("Guest wrote uDeviceStatus (%#x, was %#x, change #%x) ................ (", 1479 fNewStatus, pVirtio->uDeviceStatus, fNewStatus ^ pVirtio->uDeviceStatus)); 1462 Log7Func(("Guest wrote uDeviceStatus ................ (", fNewStatus ^ pVirtio->uDeviceStatus)); 1480 1463 if (LogIs7Enabled()) 1481 1464 virtioLogDeviceStatus(fNewStatus); … … 1579 1562 * 1580 1563 * This MMIO handler specifically supports the VIRTIO_PCI_CAP_PCI_CFG capability defined 1581 * in the VirtIO 1.0 specification, section 4.1.4.7, and as such is limited to cb == 1, cb == 2, or cb==4 type reads. 1564 * in the VirtIO 1.0 specification, section 4.1.4.7, and as such is restricted to reads 1565 * of 1, 2 or 4 bytes, only. 1582 1566 * 1583 1567 */ … … 1588 1572 AssertReturn(cb == 1 || cb == 2 || cb == 4, VERR_INVALID_PARAMETER); 1589 1573 Assert(pVirtio == (PVIRTIOCORE)pvUser); RT_NOREF(pvUser); 1574 1590 1575 1591 1576 uint32_t offIntra; … … 1603 1588 * order to maintain the config generation (see VirtIO 1.0 spec, section 4.1.4.3.1) 1604 1589 */ 1605 bool fDevSpecificFieldChanged = !!memcmp(pVirtioCC->pbDevSpecificCfg + offIntra,1590 bool fDevSpecificFieldChanged = RT_BOOL(memcmp(pVirtioCC->pbDevSpecificCfg + offIntra, 1606 1591 pVirtioCC->pbPrevDevSpecificCfg + offIntra, 1607 RT_MIN(cb, pVirtioCC->cbDevSpecificCfg - offIntra)) ;1592 RT_MIN(cb, pVirtioCC->cbDevSpecificCfg - offIntra))); 1608 1593 1609 1594 memcpy(pVirtioCC->pbPrevDevSpecificCfg, pVirtioCC->pbDevSpecificCfg, pVirtioCC->cbDevSpecificCfg); … … 1647 1632 * 1648 1633 * This MMIO handler specifically supports the VIRTIO_PCI_CAP_PCI_CFG capability defined 1649 * in the VirtIO 1.0 specification, section 4.1.4.7, and as such is limited1650 * to cb == 1, cb == 2, or cb==4 type writes.1634 * in the VirtIO 1.0 specification, section 4.1.4.7, and as such is restricted to writes 1635 * of 1, 2 or 4 bytes, only. 1651 1636 */ 1652 1637 static DECLCALLBACK(VBOXSTRICTRC) virtioMmioWrite(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS off, void const *pv, unsigned cb) … … 1658 1643 1659 1644 Assert(pVirtio == (PVIRTIOCORE)pvUser); RT_NOREF(pvUser); 1660 1661 1645 uint32_t offIntra; 1662 1646 if (MATCHES_VIRTIO_CAP_STRUCT(off, cb, offIntra, pVirtio->LocDeviceCap)) … … 1688 1672 if (MATCHES_VIRTIO_CAP_STRUCT(off, cb, offIntra, pVirtio->LocNotifyCap) && cb == sizeof(uint16_t)) 1689 1673 { 1690 #ifdef IN_RING3 1691 virtioR3QueueNotified(pVirtio, pVirtioCC, offIntra / VIRTIO_NOTIFY_OFFSET_MULTIPLIER, *(uint16_t *)pv); 1674 virtioQueueNotified(pDevIns, pVirtio, offIntra / VIRTIO_NOTIFY_OFFSET_MULTIPLIER, *(uint16_t *)pv); 1692 1675 return VINF_SUCCESS; 1693 #else1694 return VINF_IOM_R3_MMIO_WRITE;1695 #endif1696 1676 } 1697 1677 … … 1721 1701 * (the virtio_pci_cfg_cap capability), and access data items. 1722 1702 */ 1723 uint32_t uLength = pVirtioCC->pPciCfgCap->pciCap.uLength; 1724 uint32_t uOffset = pVirtioCC->pPciCfgCap->pciCap.uOffset; 1725 uint8_t uBar = pVirtioCC->pPciCfgCap->pciCap.uBar; 1703 struct virtio_pci_cap *pPciCap = &pVirtioCC->pPciCfgCap->pciCap; 1704 uint32_t uLength = pPciCap->uLength; 1726 1705 1727 1706 if ( (uLength != 1 && uLength != 2 && uLength != 4) 1728 1707 || cb != uLength 1729 || uBar != VIRTIO_REGION_PCI_CAP)1708 || pPciCap->uBar != VIRTIO_REGION_PCI_CAP) 1730 1709 { 1731 1710 ASSERT_GUEST_MSG_FAILED(("Guest read virtio_pci_cfg_cap.pci_cfg_data using mismatching config. Ignoring\n")); … … 1734 1713 } 1735 1714 1736 VBOXSTRICTRC rcStrict = virtioMmioRead(pDevIns, pVirtio, uOffset, pu32Value, cb);1715 VBOXSTRICTRC rcStrict = virtioMmioRead(pDevIns, pVirtio, pPciCap->uOffset, pu32Value, cb); 1737 1716 Log2Func(("virtio: Guest read virtio_pci_cfg_cap.pci_cfg_data, bar=%d, offset=%d, length=%d, result=%d -> %Rrc\n", 1738 uBar,uOffset, uLength, *pu32Value, VBOXSTRICTRC_VAL(rcStrict)));1717 pPciCap->uBar, pPciCap->uOffset, uLength, *pu32Value, VBOXSTRICTRC_VAL(rcStrict))); 1739 1718 return rcStrict; 1740 1719 } … … 1759 1738 * (the virtio_pci_cfg_cap capability), and access data items. */ 1760 1739 1761 uint32_t uLength = pVirtioCC->pPciCfgCap->pciCap.uLength; 1762 uint32_t uOffset = pVirtioCC->pPciCfgCap->pciCap.uOffset; 1763 uint8_t uBar = pVirtioCC->pPciCfgCap->pciCap.uBar; 1740 struct virtio_pci_cap *pPciCap = &pVirtioCC->pPciCfgCap->pciCap; 1741 uint32_t uLength = pPciCap->uLength; 1764 1742 1765 1743 if ( (uLength != 1 && uLength != 2 && uLength != 4) 1766 1744 || cb != uLength 1767 || uBar != VIRTIO_REGION_PCI_CAP)1745 || pPciCap->uBar != VIRTIO_REGION_PCI_CAP) 1768 1746 { 1769 1747 ASSERT_GUEST_MSG_FAILED(("Guest write virtio_pci_cfg_cap.pci_cfg_data using mismatching config. Ignoring\n")); … … 1771 1749 } 1772 1750 1773 VBOXSTRICTRC rcStrict = virtioMmioWrite(pDevIns, pVirtio, uOffset, &u32Value, cb);1751 VBOXSTRICTRC rcStrict = virtioMmioWrite(pDevIns, pVirtio, pPciCap->uOffset, &u32Value, cb); 1774 1752 Log2Func(("Guest wrote virtio_pci_cfg_cap.pci_cfg_data, bar=%d, offset=%x, length=%x, value=%d -> %Rrc\n", 1775 uBar,uOffset, uLength, u32Value, VBOXSTRICTRC_VAL(rcStrict)));1753 pPciCap->uBar, pPciCap->uOffset, uLength, u32Value, VBOXSTRICTRC_VAL(rcStrict))); 1776 1754 return rcStrict; 1777 1755 } … … 1913 1891 break; 1914 1892 case kvirtIoVmStateChangedResume: 1915 virtioNotifyGuestDriver(pVirtio->pDevIns , pVirtio, 0 /* idxQueue */, true /* fForce */);1893 virtioNotifyGuestDriver(pVirtio->pDevInsR3, pVirtio, 0 /* idxQueue */, true /* fForce */); 1916 1894 break; 1917 1895 default: … … 1939 1917 1940 1918 1941 /** 1919 /**rr 1942 1920 * Setup PCI device controller and Virtio state 1943 1921 * … … 1969 1947 AssertLogRelReturn(pVirtioCC == PDMINS_2_DATA_CC(pDevIns, PVIRTIOCORECC), VERR_STATE_CHANGED); 1970 1948 1971 pVirtio->pDevIns = pDevIns;1949 pVirtio->pDevInsR3 = pDevIns; 1972 1950 1973 1951 /* … … 2057 2035 2058 2036 /* 2059 * Notify capability (VirtIO 1.0 spec, section 4.1.4.4). Note: uLength is based the choice2060 * of this implementation t hat each queue's uQueueNotifyOff is setequal to (QueueSelect) ordinal2061 * value of the queue 2037 * Notify capability (VirtIO 1.0 spec, section 4.1.4.4). Note: uLength is based on the choice 2038 * of this implementation to make each queue's uQueueNotifyOff equal to (QueueSelect) ordinal 2039 * value of the queue (different strategies are possible according to spec). 2062 2040 */ 2063 2041 pCfg = (PVIRTIO_PCI_CAP_T)&pPciDev->abConfig[pCfg->uCapNext]; … … 2165 2143 * out size, so pad with an extra page 2166 2144 */ 2145 int cbSize = RTStrPrintf(pVirtioCC->pcszMmioName, sizeof(pVirtioCC->pcszMmioName), "%s MMIO", pcszInstance); 2146 if (cbSize <= 0) 2147 return PDMDEV_SET_ERROR(pDevIns, rc, N_("virtio: out of memory allocating string")); /* can we put params in this error? */ 2148 2167 2149 rc = PDMDevHlpPCIIORegionCreateMmio(pDevIns, VIRTIO_REGION_PCI_CAP, RT_ALIGN_32(cbRegion + PAGE_SIZE, PAGE_SIZE), 2168 2150 PCI_ADDRESS_SPACE_MEM, virtioMmioWrite, virtioMmioRead, pVirtio, 2169 IOMMMIO_FLAGS_READ_PASSTHRU | IOMMMIO_FLAGS_WRITE_PASSTHRU, "virtio-scsi MMIO", 2151 IOMMMIO_FLAGS_READ_PASSTHRU | IOMMMIO_FLAGS_WRITE_PASSTHRU, 2152 pVirtioCC->pcszMmioName, 2170 2153 &pVirtio->hMmioPciCap); 2171 2154 AssertLogRelRCReturn(rc, PDMDEV_SET_ERROR(pDevIns, rc, N_("virtio: cannot register PCI Capabilities address space"))); 2172 2173 2155 /* 2174 2156 * Statistics. … … 2195 2177 * @param pVirtio Pointer to the shared virtio state. This must be the first 2196 2178 * member in the shared device instance data! 2197 * @param pVirtioCC Pointer to the current context virtio state. This must be the 2198 * first member in the currenct context's device instance data! 2199 */ 2200 int virtioCoreRZInit(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, PVIRTIOCORECC pVirtioCC) 2179 */ 2180 int virtioCoreRZInit(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio) 2201 2181 { 2202 2182 AssertLogRelReturn(pVirtio == PDMINS_2_DATA(pDevIns, PVIRTIOCORE), VERR_STATE_CHANGED); 2203 AssertLogRelReturn(pVirtioCC == PDMINS_2_DATA_CC(pDevIns, PVIRTIOCORECC), VERR_STATE_CHANGED); 2204 2183 2184 #ifdef FUTURE_OPTIMIZATION 2185 int rc = PDMDevHlpSetDeviceCritSect(pDevIns, PDMDevHlpCritSectGetNop(pDevIns)); 2186 AssertRCReturn(rc, rc); 2187 #endif 2205 2188 int rc = PDMDevHlpMmioSetUpContext(pDevIns, pVirtio->hMmioPciCap, virtioMmioWrite, virtioMmioRead, pVirtio); 2206 2189 AssertRCReturn(rc, rc); -
trunk/src/VBox/Devices/VirtIO/Virtio_1_0.h
r83913 r84351 81 81 typedef struct VIRTIOSGBUF 82 82 { 83 PVIRTIOSGSEG paSegs; /**< Pointer to the scatter/gather array */83 PVIRTIOSGSEG paSegs; /**< Pointer to the scatter/gather array */ 84 84 unsigned cSegs; /**< Number of segments */ 85 85 unsigned idxSeg; /**< Current segment we are in */ … … 251 251 { 252 252 char szInstance[16]; /**< Instance name, e.g. "VIRTIOSCSI0" */ 253 PPDMDEVINS pDevIns; /**< Client device instance */ 253 PPDMDEVINS pDevInsR0; /**< Client device instance */ 254 PPDMDEVINS pDevInsR3; /**< Client device instance */ 254 255 RTGCPHYS aGCPhysQueueDesc[VIRTQ_MAX_CNT]; /**< (MMIO) PhysAdr per-Q desc structs GUEST */ 255 256 RTGCPHYS aGCPhysQueueAvail[VIRTQ_MAX_CNT]; /**< (MMIO) PhysAdr per-Q avail structs GUEST */ … … 297 298 } VIRTIOCORE; 298 299 300 #define MAX_NAME 64 301 299 302 300 303 /** … … 317 320 318 321 /** 319 * When guest-to-host queue notifications are enabled, the guest driver notifies the host320 * that the avail queue has buffers, and this callback informs the client.321 *322 * @param pVirtio Pointer to the shared virtio state.323 * @param pVirtioCC Pointer to the ring-3 virtio state.324 * @param idxQueue Index of the notified queue325 */326 DECLCALLBACKMEMBER(void, pfnQueueNotified)(PVIRTIOCORE pVirtio, PVIRTIOCORECC pVirtioCC, uint16_t idxQueue);327 328 /**329 322 * Implementation-specific client callback to access VirtIO Device-specific capabilities 330 323 * (other VirtIO capabilities and features are handled in VirtIO implementation) … … 347 340 */ 348 341 DECLCALLBACKMEMBER(int, pfnDevCapWrite)(PPDMDEVINS pDevIns, uint32_t offCap, const void *pvBuf, uint32_t cbWrite); 342 343 344 /** 345 * When guest-to-host queue notifications are enabled, the guest driver notifies the host 346 * that the avail queue has buffers, and this callback informs the client. 347 * 348 * @param pVirtio Pointer to the shared virtio state. 349 * @param pVirtioCC Pointer to the ring-3 virtio state. 350 * @param idxQueue Index of the notified queue 351 */ 352 DECLCALLBACKMEMBER(void, pfnQueueNotified)(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t idxQueue); 353 349 354 /** @} */ 355 350 356 351 357 R3PTRTYPE(PVIRTIO_PCI_CFG_CAP_T) pPciCfgCap; /**< Pointer to struct in the PCI configuration area. */ … … 359 365 R3PTRTYPE(uint8_t *) pbPrevDevSpecificCfg; /**< Previous read dev-specific cfg of client */ 360 366 bool fGenUpdatePending; /**< If set, update cfg gen after driver reads */ 367 char pcszMmioName[MAX_NAME]; /**< MMIO mapping name */ 361 368 } VIRTIOCORER3; 362 369 … … 367 374 typedef struct VIRTIOCORER0 368 375 { 369 uint64_t uUnusedAtTheMoment; 376 377 /** 378 * When guest-to-host queue notifications are enabled, the guest driver notifies the host 379 * that the avail queue has buffers, and this callback informs the client. 380 * 381 * @param pVirtio Pointer to the shared virtio state. 382 * @param pVirtioCC Pointer to the ring-3 virtio state. 383 * @param idxQueue Index of the notified queue 384 */ 385 DECLCALLBACKMEMBER(void, pfnQueueNotified)(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t idxQueue); 386 370 387 } VIRTIOCORER0; 371 388 … … 511 528 int virtioCoreR3Init(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, PVIRTIOCORECC pVirtioCC, PVIRTIOPCIPARAMS pPciParams, 512 529 const char *pcszInstance, uint64_t fDevSpecificFeatures, void *pvDevSpecificCfg, uint16_t cbDevSpecificCfg); 513 int virtioCoreRZInit(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio , PVIRTIOCORECC pVirtioCC);530 int virtioCoreRZInit(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio); 514 531 const char *virtioCoreGetStateChangeText(VIRTIOVMSTATECHANGED enmState); 515 532
Note:
See TracChangeset
for help on using the changeset viewer.