Changeset 81122 in vbox for trunk/src/VBox/Devices/VirtIO
- Timestamp:
- Oct 7, 2019 8:54:00 AM (5 years ago)
- Location:
- trunk/src/VBox/Devices/VirtIO
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/VirtIO/Virtio_1_0.cpp
r81031 r81122 366 366 367 367 AssertMsgReturnVoid(DRIVER_OK(pVirtio), ("Guest driver not in ready state.\n")); 368 369 if (pVirtio->uMsixConfig == VIRTIO_MSI_NO_VECTOR) 370 { 371 if (pVirtio->uDriverFeatures & VIRTIO_F_EVENT_IDX) 372 { 373 if (pVirtq->fEventThresholdReached) 374 { 375 virtioRaiseInterrupt(pVirtio, VIRTIO_ISR_VIRTQ_INTERRUPT, fForce); 376 pVirtq->fEventThresholdReached = false; 377 return; 378 } 379 Log6Func(("...skipping interrupt: VIRTIO_F_EVENT_IDX set but threshold not reached\n")); 380 } 381 else 382 { 383 /** If guest driver hasn't suppressed interrupts, interrupt */ 384 if (fForce || !(virtioReadUsedFlags(pVirtio, qIdx) & VIRTQ_AVAIL_F_NO_INTERRUPT)) 385 { 386 virtioRaiseInterrupt(pVirtio, VIRTIO_ISR_VIRTQ_INTERRUPT, fForce); 387 return; 388 } 389 Log6Func(("...skipping interrupt. Guest flagged VIRTQ_AVAIL_F_NO_INTERRUPT for queue\n")); 390 } 391 } 392 else 393 { 394 /* TBD, do MSI notification if criteria met */ 368 if (pVirtio->uDriverFeatures & VIRTIO_F_EVENT_IDX) 369 { 370 if (pVirtq->fEventThresholdReached) 371 { 372 virtioKick(pVirtio, VIRTIO_ISR_VIRTQ_INTERRUPT, pVirtio->uQueueMsixVector[qIdx], fForce); 373 pVirtq->fEventThresholdReached = false; 374 return; 375 } 376 Log6Func(("...skipping interrupt: VIRTIO_F_EVENT_IDX set but threshold not reached\n")); 377 } 378 else 379 { 380 /** If guest driver hasn't suppressed interrupts, interrupt */ 381 if (fForce || !(virtioReadUsedFlags(pVirtio, qIdx) & VIRTQ_AVAIL_F_NO_INTERRUPT)) 382 { 383 virtioKick(pVirtio, VIRTIO_ISR_VIRTQ_INTERRUPT, pVirtio->uQueueMsixVector[qIdx], fForce); 384 return; 385 } 386 Log6Func(("...skipping interrupt. Guest flagged VIRTQ_AVAIL_F_NO_INTERRUPT for queue\n")); 395 387 } 396 388 } … … 425 417 } 426 418 427 /** 428 * Raise interrupt. 419 420 /** 421 * Raise interrupt or MSI-X 429 422 * 430 423 * @param pVirtio The device state structure. 431 424 * @param uCause Interrupt cause bit mask to set in PCI ISR port. 432 */ 433 static int virtioRaiseInterrupt(PVIRTIOSTATE pVirtio, uint8_t uCause, bool fForce) 425 * @param uVec MSI-X vector, if enabled 426 * @param uForce True of out-of-band 427 */ 428 static int virtioKick(PVIRTIOSTATE pVirtio, uint8_t uCause, uint16_t uMsixVector, bool fForce) 434 429 { 435 430 … … 443 438 Log6Func(("reason: device config change\n")); 444 439 445 pVirtio->uISR |= uCause; 446 PDMDevHlpPCISetIrq(pVirtio->CTX_SUFF(pDevIns), 0, 1); 440 if (!pVirtio->fMsiSupport) 441 { 442 pVirtio->uISR |= uCause; 443 PDMDevHlpPCISetIrq(pVirtio->CTX_SUFF(pDevIns), 0, PDM_IRQ_LEVEL_HIGH); 444 } 445 else if (uMsixVector != VIRTIO_MSI_NO_VECTOR) 446 { 447 Log6Func(("MSI-X enabled, calling PDMDevHlpPCISetIrq with vector: 0x%x\n", uMsixVector)); 448 PDMDevHlpPCISetIrq(pVirtio->CTX_SUFF(pDevIns), uMsixVector, 1); 449 } 447 450 return VINF_SUCCESS; 448 451 } … … 455 458 static void virtioLowerInterrupt(PVIRTIOSTATE pVirtio) 456 459 { 457 PDMDevHlpPCISetIrq(pVirtio->CTX_SUFF(pDevIns), 0, 0);460 PDMDevHlpPCISetIrq(pVirtio->CTX_SUFF(pDevIns), 0, PDM_IRQ_LEVEL_LOW); 458 461 } 459 462 … … 466 469 pVirtio->uQueueSize[qIdx] = VIRTQ_MAX_SIZE; 467 470 pVirtio->uQueueNotifyOff[qIdx] = qIdx; 468 } 469 471 472 pVirtio->uQueueMsixVector[qIdx] = qIdx + 2; 473 if (!pVirtio->fMsiSupport) /* VirtIO 1.0, 4.1.4.3 and 4.1.5.1.2 */ 474 pVirtio->uQueueMsixVector[qIdx] = VIRTIO_MSI_NO_VECTOR; 475 } 470 476 471 477 static void virtioResetDevice(PVIRTIOSTATE pVirtio) … … 478 484 pVirtio->uISR = 0; 479 485 480 #ifndef MSIX_SUPPORT 481 /** This is required by VirtIO 1.0 specification, section 4.1.5.1.2 */ 482 pVirtio->uMsixConfig = VIRTIO_MSI_NO_VECTOR; 483 for (int i = 0; i < VIRTQ_MAX_CNT; i++) 484 pVirtio->uQueueMsixVector[i] = VIRTIO_MSI_NO_VECTOR; 485 #endif 486 487 if (!pVirtio->fMsiSupport) /* VirtIO 1.0, 4.1.4.3 and 4.1.5.1.2 */ 488 pVirtio->uMsixConfig = VIRTIO_MSI_NO_VECTOR; 486 489 487 490 pVirtio->uNumQueues = VIRTQ_MAX_CNT; … … 523 526 { 524 527 pVirtio->fGenUpdatePending = true; 525 virtio RaiseInterrupt(pVirtio, VIRTIO_ISR_DEVICE_CONFIG, false /* fForce */);528 virtioKick(pVirtio, VIRTIO_ISR_DEVICE_CONFIG, pVirtio->uMsixConfig, false /* fForce */); 526 529 } 527 530 } … … 529 532 /** 530 533 * Invoked by this implementation when guest driver resets the device. 531 * The driver itself will not resetuntil the device has read the status change.534 * The driver itself will not until the device has read the status change. 532 535 */ 533 536 static void virtioGuestResetted(PVIRTIOSTATE pVirtio) … … 1015 1018 VIRTIOHANDLE *phVirtio, 1016 1019 PVIRTIOPCIPARAMS pPciParams, 1017 const char 1020 const char *pcszInstance, 1018 1021 uint64_t uDevSpecificFeatures, 1019 1022 PFNVIRTIODEVCAPREAD devCapReadCallback, … … 1028 1031 void *pDevSpecificCfg) 1029 1032 { 1033 1034 extern PDMDEVREG g_DeviceVirtioSCSI; 1035 1030 1036 PVIRTIOSTATE pVirtio = (PVIRTIOSTATE)RTMemAllocZ(sizeof(VIRTIOSTATE)); 1031 1037 if (!pVirtio) … … 1034 1040 return VERR_NO_MEMORY; 1035 1041 } 1042 1043 #ifdef VBOX_WITH_MSI_DEVICES 1044 pVirtio->fMsiSupport = true; 1045 #endif 1036 1046 1037 1047 pVirtio->pClientContext = pClientContext; … … 1109 1119 1110 1120 /* Construct & map PCI vendor-specific capabilities for virtio host negotiation with guest driver */ 1111 1112 #if 0 && defined(VBOX_WITH_MSI_DEVICES) /* T.B.D. */1113 uint8_t fMsiSupport = true;1114 #else1115 uint8_t fMsiSupport = false;1116 #endif1117 1121 1118 1122 /* The following capability mapped via VirtIO 1.0: struct virtio_pci_cfg_cap (VIRTIO_PCI_CFG_CAP_T) … … 1184 1188 pCfg->uCapVndr = VIRTIO_PCI_CAP_ID_VENDOR; 1185 1189 pCfg->uCapLen = sizeof(VIRTIO_PCI_CFG_CAP_T); 1186 pCfg->uCapNext = ( fMsiSupport || pVirtio->pDevSpecificCfg) ? CFGADDR2IDX(pCfg) + pCfg->uCapLen : 0;1190 pCfg->uCapNext = (pVirtio->fMsiSupport || pVirtio->pDevSpecificCfg) ? CFGADDR2IDX(pCfg) + pCfg->uCapLen : 0; 1187 1191 pCfg->uBar = 0; 1188 1192 pCfg->uOffset = 0; … … 1199 1203 pCfg->uCapVndr = VIRTIO_PCI_CAP_ID_VENDOR; 1200 1204 pCfg->uCapLen = sizeof(VIRTIO_PCI_CAP_T); 1201 pCfg->uCapNext = fMsiSupport ? CFGADDR2IDX(pCfg) + pCfg->uCapLen : 0;1205 pCfg->uCapNext = pVirtio->fMsiSupport ? CFGADDR2IDX(pCfg) + pCfg->uCapLen : 0; 1202 1206 pCfg->uBar = VIRTIO_REGION_PCI_CAP; 1203 1207 pCfg->uOffset = pVirtio->pIsrCap->uOffset + pVirtio->pIsrCap->uLength; … … 1208 1212 } 1209 1213 1210 /* Set offset to first capability and enable PCI dev capabilities */ 1211 PDMPciDevSetCapabilityList(pPciDev, 0x40); 1212 PDMPciDevSetStatus(pPciDev, VBOX_PCI_STATUS_CAP_LIST); 1213 1214 if (fMsiSupport) 1214 if (pVirtio->fMsiSupport) 1215 1215 { 1216 1216 PDMMSIREG aMsiReg; … … 1218 1218 aMsiReg.iMsixCapOffset = pCfg->uCapNext; 1219 1219 aMsiReg.iMsixNextOffset = 0; 1220 aMsiReg.iMsixBar = 0;1221 aMsiReg.cMsixVectors = 1;1220 aMsiReg.iMsixBar = VIRTIO_REGION_MSIX_CAP; 1221 aMsiReg.cMsixVectors = g_DeviceVirtioSCSI.cMaxMsixVectors; 1222 1222 rc = PDMDevHlpPCIRegisterMsi(pDevIns, &aMsiReg); /* see MsixR3init() */ 1223 if (RT_FAILURE (rc)) 1224 /* The following is moot, we need to flag no MSI-X support */ 1225 PDMPciDevSetCapabilityList(pPciDev, 0x40); 1226 } 1223 if (RT_FAILURE(rc)) 1224 { 1225 /* See PDMDevHlp.cpp:pdmR3DevHlp_PCIRegisterMsi */ 1226 Log(("Failed to configure MSI-X (%Rrc). Reverting to INTx\n")); 1227 pVirtio->fMsiSupport = false; 1228 } 1229 else 1230 Log(("Using MSI-X for guest driver notification\n")); 1231 } 1232 else 1233 Log(("MSI-X not available for VBox, using INTx notification\n")); 1234 1235 1236 /* Set offset to first capability and enable PCI dev capabilities */ 1237 PDMPciDevSetCapabilityList(pPciDev, 0x40); 1238 PDMPciDevSetStatus(pPciDev, VBOX_PCI_STATUS_CAP_LIST); 1227 1239 1228 1240 /* Linux drivers/virtio/virtio_pci_modern.c tries to map at least a page for the -
trunk/src/VBox/Devices/VirtIO/Virtio_1_0.h
r80931 r81122 39 39 #define VIRTIO_NOTIFY_OFFSET_MULTIPLIER 2 /**< VirtIO Notify Cap. MMIO config param */ 40 40 #define VIRTIO_REGION_PCI_CAP 2 /**< BAR for VirtIO Cap. MMIO (impl specific) */ 41 #define VIRTIO_REGION_MSIX_CAP 0 /**< Bar for MSI-X handling */ 41 42 42 43 #define VIRTIO_HEX_DUMP(logLevel, pv, cb, base, title) \ … … 163 164 /** 164 165 * Allocate client context for client to work with VirtIO-provided with queue 165 * As a side effect creates a buffer vector a client can get a pointer to166 * with a call to virtioQueueDescChain()167 166 * 168 167 * @param hVirtio - Handle to VirtIO framework … … 211 210 * The caller passes in a pointer to a scatter-gather buffer of virtual memory segments 212 211 * and a pointer to the descriptor chain context originally derived from the pulled 213 * queue entry, and this function will putwrite the virtual memory s/g buffer into the212 * queue entry, and this function will write the virtual memory s/g buffer into the 214 213 * guest's physical memory free the descriptor chain. The caller handles the freeing 215 214 * (as needed) of the virtual memory buffer. -
trunk/src/VBox/Devices/VirtIO/Virtio_1_0_impl.h
r81031 r81122 189 189 uint8_t uPciCfgDataOff; 190 190 uint8_t uISR; /**< Interrupt Status Register. */ 191 uint8_t fMsiSupport; 191 192 192 193 } VIRTIOSTATE, *PVIRTIOSTATE; … … 520 521 static void virtioResetQueue (PVIRTIOSTATE pVirtio, uint16_t qIdx); 521 522 static void virtioNotifyGuestDriver (PVIRTIOSTATE pVirtio, uint16_t qIdx, bool fForce); 522 static int virtioRaiseInterrupt (PVIRTIOSTATE pVirtio, uint8_t uCause, bool fForce); 523 static void virtioLowerInterrupt (PVIRTIOSTATE pVirtio); 523 static int virtioKick(PVIRTIOSTATE pVirtio, uint8_t uCause, uint16_t uVec, bool fForce); 524 524 static void virtioQueueNotified (PVIRTIOSTATE pVirtio, uint16_t qidx, uint16_t uDescIdx); 525 525 static void virtioGuestResetted (PVIRTIOSTATE pVirtio);
Note:
See TracChangeset
for help on using the changeset viewer.