qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [RFC PATCH 2/3] vfio/pci: Add support for mmapped sub-page


From: Yongji Xie
Subject: [Qemu-devel] [RFC PATCH 2/3] vfio/pci: Add support for mmapped sub-page MMIO BARs
Date: Fri, 11 Dec 2015 17:05:17 +0800

The VFIO-PCI ioctl flag VFIO_DEVICE_FLAGS_PCI_PAGE_ALIGNED indicates platform
support all PCI MMIO BARs to be page aligned and sub-page(size < PAGE_SIZE)
MMIO BARs can be mmapped.

But this has an issue for these mmapped sub-page MMIO BARs - KVM would not
allow to create memory slot for them via ioctl KVM_SET_USER_MEMORY_REGION
because these BARs' size are still less than PAGE_SIZE.

So this patch expands these sub-page MMIO BARs to page size in
vfio_pci_write_config(), so that the BARs could be passed to KVM
ioctl KVM_SET_USER_MEMORY_REGION with a valid size. And we also set the
priority of these BARs' memory regions to zero in case of overlap with
page unaligned BARs when guest doesn't support all PCI MMIO BARs to be
page aligned.

Signed-off-by: Yongji Xie <address@hidden>
---
 hw/vfio/pci.c |   46 ++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 46 insertions(+)

diff --git a/hw/vfio/pci.c b/hw/vfio/pci.c
index 1fb868c..a7c6171 100644
--- a/hw/vfio/pci.c
+++ b/hw/vfio/pci.c
@@ -1028,6 +1028,44 @@ static const MemoryRegionOps vfio_vga_ops = {
 };
 
 /*
+ * Expand sub-page(size < PAGE_SIZE) MMIO BARs to page size if host support
+ * all MMIO BARs to be page aligned. And we should set the priority of these
+ * BARs' memory regions to zero in case of overlap with page unaligned
+ * BARs when guest doesn't support all MMIO BARs to be page aligned.
+ */
+static void vfio_expand_bar_to_page_size(PCIDevice *pdev)
+{
+    VFIOPCIDevice *vdev = DO_UPCAST(VFIOPCIDevice, pdev, pdev);
+    MemoryRegion *mmap_mr;
+    MemoryRegion *mr;
+    PCIIORegion *r;
+    pcibus_t bar_addr;
+    int i;
+
+    memory_region_transaction_begin();
+    for (i = 0; i < PCI_NUM_REGIONS; i++) {
+        r = &pdev->io_regions[i];
+        if (r->size > 0 && r->size < qemu_real_host_page_size) {
+            bar_addr = r->addr;
+            if (bar_addr != PCI_BAR_UNMAPPED &&
+                !(bar_addr & ~qemu_real_host_page_mask)) {
+                mr = &vdev->bars[i].region.mem;
+                mmap_mr = &vdev->bars[i].region.mmap_mem;
+                if (memory_region_is_mapped(mr) && vdev->bars[i].region.mmap &&
+                    memory_region_size(mr) < qemu_real_host_page_size) {
+                    memory_region_del_subregion(r->address_space, mr);
+                    memory_region_set_size(mr, qemu_real_host_page_size);
+                    memory_region_set_size(mmap_mr, qemu_real_host_page_size);
+                    memory_region_add_subregion_overlap(r->address_space,
+                                                        bar_addr, mr, 0);
+                }
+            }
+        }
+    }
+    memory_region_transaction_commit();
+}
+
+/*
  * PCI config space
  */
 uint32_t vfio_pci_read_config(PCIDevice *pdev, uint32_t addr, int len)
@@ -1112,6 +1150,14 @@ void vfio_pci_write_config(PCIDevice *pdev,
         } else if (was_enabled && !is_enabled) {
             vfio_msix_disable(vdev);
         }
+    } else if (vdev->vbasedev.flags & VFIO_DEVICE_FLAGS_PCI_PAGE_ALIGNED &&
+        (ranges_overlap(addr, len, PCI_BASE_ADDRESS_0, 24) ||
+        ranges_overlap(addr, l, PCI_ROM_ADDRESS, 4) ||
+        ranges_overlap(addr, l, PCI_ROM_ADDRESS1, 4) ||
+        range_covers_byte(addr, len, PCI_COMMAND))) {
+        pci_default_write_config(pdev, addr, val, len);
+
+        vfio_expand_bar_to_page_size(pdev);
     } else {
         /* Write everything to QEMU to keep emulated bits correct */
         pci_default_write_config(pdev, addr, val, len);
-- 
1.7.9.5




reply via email to

[Prev in Thread] Current Thread [Next in Thread]