diff options
author | Alex Williamson <alex.williamson@redhat.com> | 2012-10-08 08:45:29 -0600 |
---|---|---|
committer | Alex Williamson <alex.williamson@redhat.com> | 2012-10-08 08:45:29 -0600 |
commit | 12af1344871aee4a8df011c3b0548f7c77332d54 (patch) | |
tree | 8c55332d36c5317e2ea18dec6ada2eb59cd3283b /hw | |
parent | af6bc27e39fafadbc03c8876ffa95851c5869683 (diff) | |
download | hqemu-12af1344871aee4a8df011c3b0548f7c77332d54.zip hqemu-12af1344871aee4a8df011c3b0548f7c77332d54.tar.gz |
vfio-pci: Unmap and retry DMA mapping
Occasionally we get regions added that overlap with existing mappings.
These always seems to be in the VGA ROM range. VFIO returns EBUSY
for these mapping attempts. We can try a little harder and assume
that the latest mapping is correct by removing any overlapping ranges
and retrying the original request.
Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
Diffstat (limited to 'hw')
-rw-r--r-- | hw/vfio_pci.c | 15 |
1 files changed, 11 insertions, 4 deletions
diff --git a/hw/vfio_pci.c b/hw/vfio_pci.c index 2d89d17..7413f2d 100644 --- a/hw/vfio_pci.c +++ b/hw/vfio_pci.c @@ -819,12 +819,19 @@ static int vfio_dma_map(VFIOContainer *container, target_phys_addr_t iova, map.flags |= VFIO_DMA_MAP_FLAG_WRITE; } - if (ioctl(container->fd, VFIO_IOMMU_MAP_DMA, &map)) { - DPRINTF("VFIO_MAP_DMA: %d\n", -errno); - return -errno; + /* + * Try the mapping, if it fails with EBUSY, unmap the region and try + * again. This shouldn't be necessary, but we sometimes see it in + * the the VGA ROM space. + */ + if (ioctl(container->fd, VFIO_IOMMU_MAP_DMA, &map) == 0 || + (errno == EBUSY && vfio_dma_unmap(container, iova, size) == 0 && + ioctl(container->fd, VFIO_IOMMU_MAP_DMA, &map) == 0)) { + return 0; } - return 0; + DPRINTF("VFIO_MAP_DMA: %d\n", -errno); + return -errno; } static void vfio_listener_dummy1(MemoryListener *listener) |