diff options
author | Alexey Kardashevskiy <aik@ozlabs.ru> | 2018-03-13 11:17:31 -0600 |
---|---|---|
committer | Alex Williamson <alex.williamson@redhat.com> | 2018-03-13 11:17:31 -0600 |
commit | ae0215b2bb56a9d5321a185dde133bfdd306a4c0 (patch) | |
tree | f1c9b9a0e00f478aabaeb163dcf42e9c41a908f5 | |
parent | 567b5b309abe744b1098018a2eb157e7109c9f30 (diff) | |
download | qemu-ae0215b2bb56a9d5321a185dde133bfdd306a4c0.zip qemu-ae0215b2bb56a9d5321a185dde133bfdd306a4c0.tar.gz qemu-ae0215b2bb56a9d5321a185dde133bfdd306a4c0.tar.bz2 |
vfio-pci: Allow mmap of MSIX BAR
At the moment we unconditionally avoid mapping MSIX data of a BAR and
emulate MSIX table in QEMU. However it is 1) not always necessary as
a platform may provide a paravirt interface for MSIX configuration;
2) can affect the speed of MMIO access by emulating them in QEMU when
frequently accessed registers share same system page with MSIX data,
this is particularly a problem for systems with the page size bigger
than 4KB.
A new capability - VFIO_REGION_INFO_CAP_MSIX_MAPPABLE - has been added
to the kernel [1] which tells the userspace that mapping of the MSIX data
is possible now. This makes use of it so from now on QEMU tries mapping
the entire BAR as a whole and emulate MSIX on top of that.
[1] https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=a32295c612c57990d17fb0f41e7134394b2f35f6
Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru>
Reviewed-by: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
-rw-r--r-- | hw/vfio/common.c | 15 | ||||
-rw-r--r-- | hw/vfio/pci.c | 9 | ||||
-rw-r--r-- | include/hw/vfio/vfio-common.h | 1 |
3 files changed, 25 insertions, 0 deletions
diff --git a/hw/vfio/common.c b/hw/vfio/common.c index 07c03d7..5e84716 100644 --- a/hw/vfio/common.c +++ b/hw/vfio/common.c @@ -1471,6 +1471,21 @@ int vfio_get_dev_region_info(VFIODevice *vbasedev, uint32_t type, return -ENODEV; } +bool vfio_has_region_cap(VFIODevice *vbasedev, int region, uint16_t cap_type) +{ + struct vfio_region_info *info = NULL; + bool ret = false; + + if (!vfio_get_region_info(vbasedev, region, &info)) { + if (vfio_get_region_info_cap(info, cap_type)) { + ret = true; + } + g_free(info); + } + + return ret; +} + /* * Interfaces for IBM EEH (Enhanced Error Handling) */ diff --git a/hw/vfio/pci.c b/hw/vfio/pci.c index b9d2c12..02974f4 100644 --- a/hw/vfio/pci.c +++ b/hw/vfio/pci.c @@ -1295,6 +1295,15 @@ static void vfio_pci_fixup_msix_region(VFIOPCIDevice *vdev) VFIORegion *region = &vdev->bars[vdev->msix->table_bar].region; /* + * If the host driver allows mapping of a MSIX data, we are going to + * do map the entire BAR and emulate MSIX table on top of that. + */ + if (vfio_has_region_cap(&vdev->vbasedev, region->nr, + VFIO_REGION_INFO_CAP_MSIX_MAPPABLE)) { + return; + } + + /* * We expect to find a single mmap covering the whole BAR, anything else * means it's either unsupported or already setup. */ diff --git a/include/hw/vfio/vfio-common.h b/include/hw/vfio/vfio-common.h index c5efa32..d936014 100644 --- a/include/hw/vfio/vfio-common.h +++ b/include/hw/vfio/vfio-common.h @@ -193,6 +193,7 @@ int vfio_get_region_info(VFIODevice *vbasedev, int index, struct vfio_region_info **info); int vfio_get_dev_region_info(VFIODevice *vbasedev, uint32_t type, uint32_t subtype, struct vfio_region_info **info); +bool vfio_has_region_cap(VFIODevice *vbasedev, int region, uint16_t cap_type); #endif extern const MemoryListener vfio_prereg_listener; |