diff --git a/lib/bdev/virtio/rte_virtio/virtio_pci.c b/lib/bdev/virtio/rte_virtio/virtio_pci.c index 73bf52e42..7c31604a0 100644 --- a/lib/bdev/virtio/rte_virtio/virtio_pci.c +++ b/lib/bdev/virtio/rte_virtio/virtio_pci.c @@ -576,13 +576,11 @@ vtpci_isr(struct virtio_dev *dev) } static void * -get_cfg_addr(struct spdk_pci_device *dev, struct virtio_pci_cap *cap) +get_cfg_addr(struct virtio_hw *hw, struct virtio_pci_cap *cap) { uint8_t bar = cap->bar; uint32_t length = cap->length; uint32_t offset = cap->offset; - uint8_t *bar_vaddr; - uint64_t bar_paddr, bar_len; if (bar > 5) { PMD_INIT_LOG(ERR, "invalid bar: %u", bar); @@ -595,43 +593,36 @@ get_cfg_addr(struct spdk_pci_device *dev, struct virtio_pci_cap *cap) return NULL; } - spdk_pci_device_map_bar(dev, bar, (void *) &bar_vaddr, &bar_paddr, &bar_len); - /* FIXME the bar should be also unmapped. - * However, current spdk_pci_device_map_bar - * implementation doesn't alloc anything, - * so there's no leak whatsoever. - */ - - if (offset + length > bar_len) { + if (offset + length > hw->pci_bar[bar].len) { PMD_INIT_LOG(ERR, "invalid cap: overflows bar space: %u > %" PRIu64, offset + length, dev->mem_resource[bar].len); return NULL; } - if (bar_vaddr == NULL) { + if (hw->pci_bar[bar].vaddr == NULL) { PMD_INIT_LOG(ERR, "bar %u base addr is NULL", bar); return NULL; } - return bar_vaddr + offset; + return hw->pci_bar[bar].vaddr + offset; } static int -virtio_read_caps(struct spdk_pci_device *dev, struct virtio_hw *hw) +virtio_read_caps(struct virtio_hw *hw) { uint8_t pos; struct virtio_pci_cap cap; int ret; - ret = spdk_pci_device_cfg_read(dev, &pos, 1, PCI_CAPABILITY_LIST); + ret = spdk_pci_device_cfg_read(hw->pci_dev, &pos, 1, PCI_CAPABILITY_LIST); if (ret < 0) { PMD_INIT_LOG(DEBUG, "failed to read pci capability list"); return -1; } while (pos) { - ret = spdk_pci_device_cfg_read(dev, &cap, sizeof(cap), pos); + ret = spdk_pci_device_cfg_read(hw->pci_dev, &cap, sizeof(cap), pos); if (ret < 0) { PMD_INIT_LOG(ERR, "failed to read pci cap at pos: %x", pos); @@ -654,18 +645,18 @@ virtio_read_caps(struct spdk_pci_device *dev, struct virtio_hw *hw) switch (cap.cfg_type) { case VIRTIO_PCI_CAP_COMMON_CFG: - hw->common_cfg = get_cfg_addr(dev, &cap); + hw->common_cfg = get_cfg_addr(hw, &cap); break; case VIRTIO_PCI_CAP_NOTIFY_CFG: - spdk_pci_device_cfg_read(dev, &hw->notify_off_multiplier, + spdk_pci_device_cfg_read(hw->pci_dev, &hw->notify_off_multiplier, 4, pos + sizeof(cap)); - hw->notify_base = get_cfg_addr(dev, &cap); + hw->notify_base = get_cfg_addr(hw, &cap); break; case VIRTIO_PCI_CAP_DEVICE_CFG: - hw->dev_cfg = get_cfg_addr(dev, &cap); + hw->dev_cfg = get_cfg_addr(hw, &cap); break; case VIRTIO_PCI_CAP_ISR_CFG: - hw->isr = get_cfg_addr(dev, &cap); + hw->isr = get_cfg_addr(hw, &cap); break; } @@ -695,18 +686,35 @@ pci_enum_virtio_probe_cb(void *ctx, struct spdk_pci_device *pci_dev) { struct virtio_hw *hw; struct virtio_dev *vdev; + uint8_t *bar_vaddr; + uint64_t bar_paddr, bar_len; + int rc; + unsigned i; hw = calloc(1, sizeof(*hw)); vdev = &hw->vdev; vdev->is_hw = 1; hw->pci_dev = pci_dev; + for (i = 0; i < 6; ++i) { + rc = spdk_pci_device_map_bar(pci_dev, i, (void *) &bar_vaddr, &bar_paddr, + &bar_len); + if (rc != 0) { + PMD_DRV_LOG(ERR, "failed to memmap PCI BAR %d", i); + free(hw); + return -1; + } + + hw->pci_bar[i].vaddr = bar_vaddr; + hw->pci_bar[i].len = bar_len; + } + /* * Try if we can succeed reading virtio pci caps, which exists * only on modern pci device. If failed, we fallback to legacy * virtio handling. */ - if (virtio_read_caps(pci_dev, hw) == 0) { + if (virtio_read_caps(hw) == 0) { PMD_INIT_LOG(INFO, "modern virtio pci detected."); VTPCI_OPS(vdev) = &modern_ops; vdev->modern = 1; diff --git a/lib/bdev/virtio/rte_virtio/virtio_pci.h b/lib/bdev/virtio/rte_virtio/virtio_pci.h index d9256ec81..bedc4c7bd 100644 --- a/lib/bdev/virtio/rte_virtio/virtio_pci.h +++ b/lib/bdev/virtio/rte_virtio/virtio_pci.h @@ -218,6 +218,15 @@ struct virtio_hw { uint32_t notify_off_multiplier; uint8_t *isr; uint16_t *notify_base; + + struct { + /** Mem-mapped resources from given PCI BAR */ + void *vaddr; + + /** Length of the address space */ + uint32_t len; + } pci_bar[6]; + struct virtio_pci_common_cfg *common_cfg; struct spdk_pci_device *pci_dev; struct virtio_scsi_config *dev_cfg;