VirtualBox

Changeset 81402 in vbox


Ignore:
Timestamp:
Oct 21, 2019 12:23:24 PM (5 years ago)
Author:
vboxsync
Message:

VirtIO: Fix access to the VirtIO registers through the PCI config space window

File:
1 edited

Legend:

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

    r81348 r81402  
    884884{
    885885    PVIRTIOSTATE pVirtio = *PDMINS_2_DATA(pDevIns, PVIRTIOSTATE *);
    886     RT_NOREF(pPciDev, cb);
    887 
    888     uint64_t uWindowOff = (uint64_t)uAddress - (uint64_t)pVirtio->pPciCfgCap->uPciCfgData;
    889     if (uWindowOff < sizeof(uint32_t))
     886    RT_NOREF(pPciDev);
     887
     888    LogFlowFunc(("pDevIns=%p pPciDev=%p uAddress=%#x cb=%u pu32Value=%p\n",
     889                 pDevIns, pPciDev, uAddress, cb, pu32Value));
     890    if (uAddress == pVirtio->uPciCfgDataOff)
     891    {
     892        /*
     893         * VirtIO 1.0 spec section 4.1.4.7 describes a required alternative access capability
     894         * whereby the guest driver can specify a bar, offset, and length via the PCI configuration space
     895         * (the virtio_pci_cfg_cap capability), and access data items.
     896         */
     897        uint32_t uLength = pVirtio->pPciCfgCap->pciCap.uLength;
     898        uint32_t uOffset = pVirtio->pPciCfgCap->pciCap.uOffset;
     899        uint8_t  uBar    = pVirtio->pPciCfgCap->pciCap.uBar;
     900
     901        if (   (uLength != 1 && uLength != 2 && uLength != 4)
     902            || cb != uLength
     903            || uBar != VIRTIO_REGION_PCI_CAP)
     904        {
     905            Log2Func(("Guest read virtio_pci_cfg_cap.pci_cfg_data using mismatching config. Ignoring\n"));
     906            *pu32Value = UINT32_MAX;
     907            return VINF_SUCCESS;
     908        }
     909
     910        int rc = virtioR3MmioRead(pDevIns, NULL, pVirtio->pGcPhysPciCapBase + uOffset, pu32Value, cb);
     911        Log2Func(("virtio: Guest read  virtio_pci_cfg_cap.pci_cfg_data, bar=%d, offset=%d, length=%d, result=%d -> %Rrc\n",
     912                  uBar, uOffset, uLength, *pu32Value, rc));
     913        return rc;
     914    }
     915    return VINF_PDM_PCI_DO_DEFAULT;
     916}
     917
     918/**
     919 * @callback_method_impl{FNPCICONFIGWRITE}
     920 */
     921static DECLCALLBACK(VBOXSTRICTRC) virtioR3PciConfigWrite(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev,
     922                                                         uint32_t uAddress, unsigned cb, uint32_t u32Value)
     923{
     924    PVIRTIOSTATE pVirtio = *PDMINS_2_DATA(pDevIns, PVIRTIOSTATE *);
     925    RT_NOREF(pPciDev);
     926
     927    LogFlowFunc(("pDevIns=%p pPciDev=%p uAddress=%#x cb=%u u32Value=%#x\n",
     928                 pDevIns, pPciDev, uAddress, cb, u32Value));
     929    if (uAddress == pVirtio->uPciCfgDataOff)
    890930    {
    891931        /* VirtIO 1.0 spec section 4.1.4.7 describes a required alternative access capability
     
    897937        uint8_t  uBar    = pVirtio->pPciCfgCap->pciCap.uBar;
    898938
    899         AssertReturn(uLength == 1 || uLength == 2 || uLength == 4, VERR_INVALID_PARAMETER);
    900         AssertReturn(cb + uWindowOff <= uLength, VERR_INVALID_PARAMETER);
    901 
    902         *pu32Value = 0xffffffff;
    903         if (uBar == VIRTIO_REGION_PCI_CAP)
    904         {
    905             uint32_t pu32tmp = 0;
    906             virtioR3MmioRead(pDevIns, NULL, (RTGCPHYS)((uint32_t)pVirtio->pGcPhysPciCapBase + uOffset), &pu32tmp, uLength);
    907             memcpy(pu32Value + uWindowOff, &pu32tmp + uWindowOff, cb);
    908             Log2Func(("virtio: Guest read  virtio_pci_cfg_cap.pci_cfg_data, bar=%d, offset=%d, length=%d, result=%d\n",
    909                       uBar, uOffset, uLength, *pu32Value));
    910         }
    911         else
    912             Log2Func(("Guest read virtio_pci_cfg_cap.pci_cfg_data using unconfigured BAR. Ignoring"));
    913         return VINF_SUCCESS;
    914     }
    915     return VINF_PDM_PCI_DO_DEFAULT;
    916 }
    917 
    918 /**
    919  * @callback_method_impl{FNPCICONFIGWRITE}
    920  */
    921 static DECLCALLBACK(VBOXSTRICTRC) virtioR3PciConfigWrite(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev,
    922                                                          uint32_t uAddress, unsigned cb, uint32_t u32Value)
    923 {
    924     PVIRTIOSTATE pVirtio = *PDMINS_2_DATA(pDevIns, PVIRTIOSTATE *);
    925     RT_NOREF(pPciDev, cb);
    926 
    927     uint64_t uWindowOff = (uint64_t)uAddress - (uint64_t)pVirtio->pPciCfgCap->uPciCfgData;
    928     if (uWindowOff < sizeof(uint32_t))
    929     {
    930         /* VirtIO 1.0 spec section 4.1.4.7 describes a required alternative access capability
    931          * whereby the guest driver can specify a bar, offset, and length via the PCI configuration space
    932          * (the virtio_pci_cfg_cap capability), and access data items. */
    933 
    934         uint32_t uLength = pVirtio->pPciCfgCap->pciCap.uLength;
    935         uint32_t uOffset = pVirtio->pPciCfgCap->pciCap.uOffset;
    936         uint8_t  uBar    = pVirtio->pPciCfgCap->pciCap.uBar;
    937 
    938         AssertReturn(uLength == 1 || uLength == 2 || uLength == 4, VERR_INVALID_PARAMETER);
    939         AssertReturn(cb == uLength && uWindowOff == 0, VERR_INVALID_PARAMETER);
    940 
    941         if (uBar == VIRTIO_REGION_PCI_CAP)
    942         {
    943             Assert(uLength <= sizeof(u32Value));
    944             virtioR3MmioWrite(pDevIns, NULL, (RTGCPHYS)((uint32_t)pVirtio->pGcPhysPciCapBase + uOffset), &u32Value, uLength);
    945         }
    946         else
    947         {
    948             Log2Func(("Guest wrote virtio_pci_cfg_cap.pci_cfg_data using unconfigured BAR. Ignoring"));
     939        if (   (uLength != 1 && uLength != 2 && uLength != 4)
     940            || cb != uLength
     941            || uBar != VIRTIO_REGION_PCI_CAP)
     942        {
     943            Log2Func(("Guest write virtio_pci_cfg_cap.pci_cfg_data using mismatching config. Ignoring\n"));
    949944            return VINF_SUCCESS;
    950945        }
    951         Log2Func(("Guest wrote  virtio_pci_cfg_cap.pci_cfg_data, bar=%d, offset=%x, length=%x, value=%d\n",
    952                 uBar, uOffset, uLength, u32Value));
    953         return VINF_SUCCESS;
     946
     947        int rc = virtioR3MmioWrite(pDevIns, NULL, pVirtio->pGcPhysPciCapBase + uOffset, &u32Value, cb);
     948        Log2Func(("Guest wrote  virtio_pci_cfg_cap.pci_cfg_data, bar=%d, offset=%x, length=%x, value=%d -> %Rrc\n",
     949                uBar, uOffset, uLength, u32Value, rc));
     950        return rc;
    954951    }
    955952    return VINF_PDM_PCI_DO_DEFAULT;
     
    11731170     *  initializing. */
    11741171
     1172    pVirtio->uPciCfgDataOff = pCfg->uCapNext + RT_OFFSETOF(VIRTIO_PCI_CFG_CAP_T, uPciCfgData);
    11751173    pCfg = (PVIRTIO_PCI_CAP_T)&pPciDev->abConfig[pCfg->uCapNext];
    11761174    pCfg->uCfgType = VIRTIO_PCI_CAP_PCI_CFG;
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