[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [RFC PATCH qemu v2 4/5] vfio: Refactor memory listener to a
From: |
Alexey Kardashevskiy |
Subject: |
[Qemu-devel] [RFC PATCH qemu v2 4/5] vfio: Refactor memory listener to accommodate more IOMMU types |
Date: |
Tue, 14 Jul 2015 00:56:20 +1000 |
The vfio_memory_listener is registered for PCI address space. On Type1
IOMMU that falls back to @address_space_memory and the listener is
called on RAM blocks. On sPAPR IOMMU is guest visible and the listener
is called on DMA windows. Therefore Type1 IOMMU only handled RAM regions
and sPAPR IOMMU only handled IOMMU regions.
With the memory preregistration, there is need to handle RAM regions in
the listener for sPAPR IOMMU too. To make next patches simpler/nicer,
this moves DMA mapping/unmapping code to a case in a switch.
This separates actual listener events handlers from the callbacks;
these will be used later with another memory listener.
This should cause no change in behavior.
Signed-off-by: Alexey Kardashevskiy <address@hidden>
---
Changes:
v2:
* split vfio_listener_region_add and vfio_listener_region_del to
listener callbacks and actual handlers; the latter will be reused in
memory preregistration
---
hw/vfio/common.c | 77 ++++++++++++++++++++++++++++++++++++++------------------
1 file changed, 52 insertions(+), 25 deletions(-)
diff --git a/hw/vfio/common.c b/hw/vfio/common.c
index 510ab64..daff0d9 100644
--- a/hw/vfio/common.c
+++ b/hw/vfio/common.c
@@ -313,11 +313,10 @@ out:
rcu_read_unlock();
}
-static void vfio_listener_region_add(MemoryListener *listener,
- MemoryRegionSection *section)
+static void vfio_listener_region_do_add(VFIOContainer *container,
+ MemoryListener *listener,
+ MemoryRegionSection *section)
{
- VFIOContainer *container = container_of(listener, VFIOContainer,
- iommu_data.type1.listener);
hwaddr iova, end;
Int128 llend;
void *vaddr;
@@ -397,34 +396,43 @@ static void vfio_listener_region_add(MemoryListener
*listener,
section->offset_within_region +
(iova - section->offset_within_address_space);
- trace_vfio_listener_region_add_ram(iova, end - 1, vaddr);
+ switch (container->iommu_data.type) {
+ case VFIO_TYPE1_IOMMU:
+ case VFIO_TYPE1v2_IOMMU:
+ trace_vfio_listener_region_add_ram(iova, end - 1, vaddr);
- ret = vfio_dma_map(container, iova, end - iova, vaddr, section->readonly);
- if (ret) {
- error_report("vfio_dma_map(%p, 0x%"HWADDR_PRIx", "
- "0x%"HWADDR_PRIx", %p) = %d (%m)",
- container, iova, end - iova, vaddr, ret);
+ ret = vfio_dma_map(container, iova, end - iova, vaddr,
section->readonly);
+ if (ret) {
+ error_report("vfio_dma_map(%p, 0x%"HWADDR_PRIx", "
+ "0x%"HWADDR_PRIx", %p) = %d (%m)",
+ container, iova, end - iova, vaddr, ret);
+ goto error_exit;
+ }
+ break;
+ }
+
+ return;
+
+error_exit:
- /*
- * On the initfn path, store the first error in the container so we
- * can gracefully fail. Runtime, there's not much we can do other
- * than throw a hardware error.
- */
- if (!container->iommu_data.type1.initialized) {
- if (!container->iommu_data.type1.error) {
- container->iommu_data.type1.error = ret;
- }
- } else {
- hw_error("vfio: DMA mapping failed, unable to continue");
+ /*
+ * On the initfn path, store the first error in the container so we
+ * can gracefully fail. Runtime, there's not much we can do other
+ * than throw a hardware error.
+ */
+ if (!container->iommu_data.type1.initialized) {
+ if (!container->iommu_data.type1.error) {
+ container->iommu_data.type1.error = ret;
}
+ } else {
+ hw_error("vfio: DMA mapping failed, unable to continue");
}
}
-static void vfio_listener_region_del(MemoryListener *listener,
- MemoryRegionSection *section)
+static void vfio_listener_region_do_del(VFIOContainer *container,
+ MemoryListener *listener,
+ MemoryRegionSection *section)
{
- VFIOContainer *container = container_of(listener, VFIOContainer,
- iommu_data.type1.listener);
hwaddr iova, end;
int ret;
const bool is_iommu = memory_region_is_iommu(section->mr);
@@ -485,6 +493,25 @@ static void vfio_listener_region_del(MemoryListener
*listener,
}
}
+static void vfio_listener_region_add(MemoryListener *listener,
+ MemoryRegionSection *section)
+{
+ VFIOContainer *container = container_of(listener, VFIOContainer,
+ iommu_data.type1.listener);
+
+ vfio_listener_region_do_add(container, listener, section);
+}
+
+
+static void vfio_listener_region_del(MemoryListener *listener,
+ MemoryRegionSection *section)
+{
+ VFIOContainer *container = container_of(listener, VFIOContainer,
+ iommu_data.type1.listener);
+
+ vfio_listener_region_do_del(container, listener, section);
+}
+
static const MemoryListener vfio_memory_listener = {
.region_add = vfio_listener_region_add,
.region_del = vfio_listener_region_del,
--
2.4.0.rc3.8.gfb3e7d5
- [Qemu-devel] [RFC PATCH qemu v2 0/5] vfio: SPAPR IOMMU v2 (memory preregistration support), Alexey Kardashevskiy, 2015/07/13
- [Qemu-devel] [RFC PATCH qemu v2 1/5] vfio: Switch from TARGET_PAGE_MASK to qemu_real_host_page_mask, Alexey Kardashevskiy, 2015/07/13
- [Qemu-devel] [RFC PATCH qemu v2 5/5] vfio: spapr: Add SPAPR IOMMU v2 support (DMA memory preregistering), Alexey Kardashevskiy, 2015/07/13
- [Qemu-devel] [RFC PATCH qemu v2 4/5] vfio: Refactor memory listener to accommodate more IOMMU types,
Alexey Kardashevskiy <=
- [Qemu-devel] [RFC PATCH qemu v2 2/5] vfio: Skip PCI BARs in memory listener, Alexey Kardashevskiy, 2015/07/13
- [Qemu-devel] [RFC PATCH qemu v2 3/5] vfio: Store IOMMU type in container, Alexey Kardashevskiy, 2015/07/13
- Re: [Qemu-devel] [RFC PATCH qemu v2 0/5] vfio: SPAPR IOMMU v2 (memory preregistration support), Alex Williamson, 2015/07/13