rte_virtio: save mem-mapped PCI resource regions

Added virtio_hw->pci_bar[6] to store information
about mapped memory regions. They have to be
stored to make it possible to unmap them.

The unmapping itself is done in a separate
patch.

Change-Id: I5dcffd0674e855a02086b3d8e4adc5fac451229a
Signed-off-by: Dariusz Stojaczyk <dariuszx.stojaczyk@intel.com>
Reviewed-on: https://review.gerrithub.io/380779
Tested-by: SPDK Automated Test System <sys_sgsw@intel.com>
Reviewed-by: Daniel Verkamp <daniel.verkamp@intel.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
This commit is contained in:
Dariusz Stojaczyk 2017-09-29 13:19:30 +02:00 committed by Jim Harris
parent b9ebf948ba
commit fad291df7b
2 changed files with 39 additions and 22 deletions

View File

@ -576,13 +576,11 @@ vtpci_isr(struct virtio_dev *dev)
} }
static void * 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; uint8_t bar = cap->bar;
uint32_t length = cap->length; uint32_t length = cap->length;
uint32_t offset = cap->offset; uint32_t offset = cap->offset;
uint8_t *bar_vaddr;
uint64_t bar_paddr, bar_len;
if (bar > 5) { if (bar > 5) {
PMD_INIT_LOG(ERR, "invalid bar: %u", bar); 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; return NULL;
} }
spdk_pci_device_map_bar(dev, bar, (void *) &bar_vaddr, &bar_paddr, &bar_len); if (offset + length > hw->pci_bar[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) {
PMD_INIT_LOG(ERR, PMD_INIT_LOG(ERR,
"invalid cap: overflows bar space: %u > %" PRIu64, "invalid cap: overflows bar space: %u > %" PRIu64,
offset + length, dev->mem_resource[bar].len); offset + length, dev->mem_resource[bar].len);
return NULL; return NULL;
} }
if (bar_vaddr == NULL) { if (hw->pci_bar[bar].vaddr == NULL) {
PMD_INIT_LOG(ERR, "bar %u base addr is NULL", bar); PMD_INIT_LOG(ERR, "bar %u base addr is NULL", bar);
return NULL; return NULL;
} }
return bar_vaddr + offset; return hw->pci_bar[bar].vaddr + offset;
} }
static int static int
virtio_read_caps(struct spdk_pci_device *dev, struct virtio_hw *hw) virtio_read_caps(struct virtio_hw *hw)
{ {
uint8_t pos; uint8_t pos;
struct virtio_pci_cap cap; struct virtio_pci_cap cap;
int ret; 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) { if (ret < 0) {
PMD_INIT_LOG(DEBUG, "failed to read pci capability list"); PMD_INIT_LOG(DEBUG, "failed to read pci capability list");
return -1; return -1;
} }
while (pos) { 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) { if (ret < 0) {
PMD_INIT_LOG(ERR, PMD_INIT_LOG(ERR,
"failed to read pci cap at pos: %x", pos); "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) { switch (cap.cfg_type) {
case VIRTIO_PCI_CAP_COMMON_CFG: case VIRTIO_PCI_CAP_COMMON_CFG:
hw->common_cfg = get_cfg_addr(dev, &cap); hw->common_cfg = get_cfg_addr(hw, &cap);
break; break;
case VIRTIO_PCI_CAP_NOTIFY_CFG: 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)); 4, pos + sizeof(cap));
hw->notify_base = get_cfg_addr(dev, &cap); hw->notify_base = get_cfg_addr(hw, &cap);
break; break;
case VIRTIO_PCI_CAP_DEVICE_CFG: case VIRTIO_PCI_CAP_DEVICE_CFG:
hw->dev_cfg = get_cfg_addr(dev, &cap); hw->dev_cfg = get_cfg_addr(hw, &cap);
break; break;
case VIRTIO_PCI_CAP_ISR_CFG: case VIRTIO_PCI_CAP_ISR_CFG:
hw->isr = get_cfg_addr(dev, &cap); hw->isr = get_cfg_addr(hw, &cap);
break; break;
} }
@ -695,18 +686,35 @@ pci_enum_virtio_probe_cb(void *ctx, struct spdk_pci_device *pci_dev)
{ {
struct virtio_hw *hw; struct virtio_hw *hw;
struct virtio_dev *vdev; struct virtio_dev *vdev;
uint8_t *bar_vaddr;
uint64_t bar_paddr, bar_len;
int rc;
unsigned i;
hw = calloc(1, sizeof(*hw)); hw = calloc(1, sizeof(*hw));
vdev = &hw->vdev; vdev = &hw->vdev;
vdev->is_hw = 1; vdev->is_hw = 1;
hw->pci_dev = pci_dev; 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 * Try if we can succeed reading virtio pci caps, which exists
* only on modern pci device. If failed, we fallback to legacy * only on modern pci device. If failed, we fallback to legacy
* virtio handling. * virtio handling.
*/ */
if (virtio_read_caps(pci_dev, hw) == 0) { if (virtio_read_caps(hw) == 0) {
PMD_INIT_LOG(INFO, "modern virtio pci detected."); PMD_INIT_LOG(INFO, "modern virtio pci detected.");
VTPCI_OPS(vdev) = &modern_ops; VTPCI_OPS(vdev) = &modern_ops;
vdev->modern = 1; vdev->modern = 1;

View File

@ -218,6 +218,15 @@ struct virtio_hw {
uint32_t notify_off_multiplier; uint32_t notify_off_multiplier;
uint8_t *isr; uint8_t *isr;
uint16_t *notify_base; 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 virtio_pci_common_cfg *common_cfg;
struct spdk_pci_device *pci_dev; struct spdk_pci_device *pci_dev;
struct virtio_scsi_config *dev_cfg; struct virtio_scsi_config *dev_cfg;