VirtualBox

Changeset 81122 in vbox for trunk/src/VBox/Devices/VirtIO


Ignore:
Timestamp:
Oct 7, 2019 8:54:00 AM (5 years ago)
Author:
vboxsync
Message:

Storage/DevVirtioSCSI.cpp: Got MSI-X support implemented and a few other small inconsequential tweaks

Location:
trunk/src/VBox/Devices/VirtIO
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Devices/VirtIO/Virtio_1_0.cpp

    r81031 r81122  
    366366
    367367    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"));
    395387    }
    396388}
     
    425417}
    426418
    427 /**
    428  * Raise interrupt.
     419
     420/**
     421 * Raise interrupt or MSI-X
    429422 *
    430423 * @param   pVirtio         The device state structure.
    431424 * @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 */
     428static int virtioKick(PVIRTIOSTATE pVirtio, uint8_t uCause, uint16_t uMsixVector, bool fForce)
    434429{
    435430
     
    443438       Log6Func(("reason: device config change\n"));
    444439
    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    }
    447450    return VINF_SUCCESS;
    448451}
     
    455458static void virtioLowerInterrupt(PVIRTIOSTATE pVirtio)
    456459{
    457     PDMDevHlpPCISetIrq(pVirtio->CTX_SUFF(pDevIns), 0, 0);
     460    PDMDevHlpPCISetIrq(pVirtio->CTX_SUFF(pDevIns), 0, PDM_IRQ_LEVEL_LOW);
    458461}
    459462
     
    466469    pVirtio->uQueueSize[qIdx] = VIRTQ_MAX_SIZE;
    467470    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}
    470476
    471477static void virtioResetDevice(PVIRTIOSTATE pVirtio)
     
    478484    pVirtio->uISR                   = 0;
    479485
    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;
    486489
    487490    pVirtio->uNumQueues = VIRTQ_MAX_CNT;
     
    523526    {
    524527        pVirtio->fGenUpdatePending = true;
    525         virtioRaiseInterrupt(pVirtio, VIRTIO_ISR_DEVICE_CONFIG, false /* fForce */);
     528        virtioKick(pVirtio, VIRTIO_ISR_DEVICE_CONFIG, pVirtio->uMsixConfig, false /* fForce */);
    526529    }
    527530}
     
    529532/**
    530533 * Invoked by this implementation when guest driver resets the device.
    531  * The driver itself will not reset until the device has read the status change.
     534 * The driver itself will not until the device has read the status change.
    532535 */
    533536static void virtioGuestResetted(PVIRTIOSTATE pVirtio)
     
    10151018                      VIRTIOHANDLE          *phVirtio,
    10161019                      PVIRTIOPCIPARAMS       pPciParams,
    1017                       const char             *pcszInstance,
     1020                      const char            *pcszInstance,
    10181021                      uint64_t               uDevSpecificFeatures,
    10191022                      PFNVIRTIODEVCAPREAD    devCapReadCallback,
     
    10281031                      void                  *pDevSpecificCfg)
    10291032{
     1033
     1034    extern PDMDEVREG g_DeviceVirtioSCSI;
     1035
    10301036    PVIRTIOSTATE pVirtio = (PVIRTIOSTATE)RTMemAllocZ(sizeof(VIRTIOSTATE));
    10311037    if (!pVirtio)
     
    10341040        return VERR_NO_MEMORY;
    10351041    }
     1042
     1043#ifdef VBOX_WITH_MSI_DEVICES
     1044    pVirtio->fMsiSupport = true;
     1045#endif
    10361046
    10371047    pVirtio->pClientContext = pClientContext;
     
    11091119
    11101120    /* 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 #else
    1115     uint8_t fMsiSupport = false;
    1116 #endif
    11171121
    11181122    /* The following capability mapped via VirtIO 1.0: struct virtio_pci_cfg_cap (VIRTIO_PCI_CFG_CAP_T)
     
    11841188    pCfg->uCapVndr = VIRTIO_PCI_CAP_ID_VENDOR;
    11851189    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;
    11871191    pCfg->uBar     = 0;
    11881192    pCfg->uOffset  = 0;
     
    11991203        pCfg->uCapVndr = VIRTIO_PCI_CAP_ID_VENDOR;
    12001204        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;
    12021206        pCfg->uBar     = VIRTIO_REGION_PCI_CAP;
    12031207        pCfg->uOffset  = pVirtio->pIsrCap->uOffset + pVirtio->pIsrCap->uLength;
     
    12081212    }
    12091213
    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)
    12151215    {
    12161216        PDMMSIREG aMsiReg;
     
    12181218        aMsiReg.iMsixCapOffset  = pCfg->uCapNext;
    12191219        aMsiReg.iMsixNextOffset = 0;
    1220         aMsiReg.iMsixBar        = 0;
    1221         aMsiReg.cMsixVectors    = 1;
     1220        aMsiReg.iMsixBar        = VIRTIO_REGION_MSIX_CAP;
     1221        aMsiReg.cMsixVectors    = g_DeviceVirtioSCSI.cMaxMsixVectors;
    12221222        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);
    12271239
    12281240    /* 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  
    3939#define VIRTIO_NOTIFY_OFFSET_MULTIPLIER     2                    /**< VirtIO Notify Cap. MMIO config param     */
    4040#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                   */
    4142
    4243#define VIRTIO_HEX_DUMP(logLevel, pv, cb, base, title) \
     
    163164/**
    164165 * 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 to
    166  * with a call to virtioQueueDescChain()
    167166 *
    168167 * @param  hVirtio   - Handle to VirtIO framework
     
    211210 * The caller passes in a pointer to a scatter-gather buffer of virtual memory segments
    212211 * and a pointer to the descriptor chain context originally derived from the pulled
    213  * queue entry, and this function will put write the virtual memory s/g buffer into the
     212 * queue entry, and this function will write the virtual memory s/g buffer into the
    214213 * guest's physical memory free the descriptor chain. The caller handles the freeing
    215214 * (as needed) of the virtual memory buffer.
  • trunk/src/VBox/Devices/VirtIO/Virtio_1_0_impl.h

    r81031 r81122  
    189189    uint8_t                   uPciCfgDataOff;
    190190    uint8_t                   uISR;                              /**< Interrupt Status Register.                */
     191    uint8_t                   fMsiSupport;
    191192
    192193} VIRTIOSTATE, *PVIRTIOSTATE;
     
    520521static void virtioResetQueue        (PVIRTIOSTATE pVirtio, uint16_t qIdx);
    521522static 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);
     523static int  virtioKick(PVIRTIOSTATE pVirtio, uint8_t uCause, uint16_t uVec, bool fForce);
    524524static void virtioQueueNotified     (PVIRTIOSTATE pVirtio, uint16_t qidx, uint16_t uDescIdx);
    525525static void virtioGuestResetted     (PVIRTIOSTATE pVirtio);
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette