* [Qemu-devel] [RFC PATCH 0/2] VFIO integration @ 2017-07-13 6:38 ` Bharat Bhushan 0 siblings, 0 replies; 8+ messages in thread From: Bharat Bhushan @ 2017-07-13 6:38 UTC (permalink / raw) To: eric.auger, eric.auger.pro, peter.maydell, alex.williamson, mst, qemu-arm, qemu-devel Cc: wei, kevin.tian, Bharat Bhushan, marc.zyngier, tn, will.deacon, drjones, robin.murphy, christoffer.dall This patch series allows PCI pass-through using virtio-iommu. This series is based on: - virtio-iommu specification written by Jean-Philippe Brucker [RFC 0/3] virtio-iommu: a paravirtualized IOMMU, - virtio-iommu driver by Jean-Philippe Brucker [RFC PATCH linux] iommu: Add virtio-iommu driver - virtio-iommu device emulation by Eric Augur. [RFC v2 0/8] VIRTIO-IOMMU device PCI device pass-through and virtio-net-pci is tested with these chages using dma-ops This patch series does not implement RESV_MEM changes proposal by Jean-Philippe "https://lists.gnu.org/archive/html/qemu-devel/2017-07/msg01796.html" Bharat Bhushan (2): target/arm/kvm: Translate the MSI doorbell in kvm_arch_fixup_msi_route virtio-iommu: vfio integration with virtio-iommu hw/virtio/virtio-iommu.c | 127 +++++++++++++++++++++++++++++++++++++++ include/hw/virtio/virtio-iommu.h | 6 ++ target/arm/kvm.c | 21 +++++++ 3 files changed, 154 insertions(+) -- 1.9.3 ^ permalink raw reply [flat|nested] 8+ messages in thread
* [Qemu-devel] [RFC PATCH 0/2] VFIO integration @ 2017-07-13 6:38 ` Bharat Bhushan 0 siblings, 0 replies; 8+ messages in thread From: Bharat Bhushan @ 2017-07-13 6:38 UTC (permalink / raw) To: eric.auger, eric.auger.pro, peter.maydell, alex.williamson, mst, qemu-arm, qemu-devel Cc: wei, kevin.tian, marc.zyngier, tn, will.deacon, drjones, robin.murphy, christoffer.dall, Bharat Bhushan This patch series allows PCI pass-through using virtio-iommu. This series is based on: - virtio-iommu specification written by Jean-Philippe Brucker [RFC 0/3] virtio-iommu: a paravirtualized IOMMU, - virtio-iommu driver by Jean-Philippe Brucker [RFC PATCH linux] iommu: Add virtio-iommu driver - virtio-iommu device emulation by Eric Augur. [RFC v2 0/8] VIRTIO-IOMMU device PCI device pass-through and virtio-net-pci is tested with these chages using dma-ops This patch series does not implement RESV_MEM changes proposal by Jean-Philippe "https://lists.gnu.org/archive/html/qemu-devel/2017-07/msg01796.html" Bharat Bhushan (2): target/arm/kvm: Translate the MSI doorbell in kvm_arch_fixup_msi_route virtio-iommu: vfio integration with virtio-iommu hw/virtio/virtio-iommu.c | 127 +++++++++++++++++++++++++++++++++++++++ include/hw/virtio/virtio-iommu.h | 6 ++ target/arm/kvm.c | 21 +++++++ 3 files changed, 154 insertions(+) -- 1.9.3 ^ permalink raw reply [flat|nested] 8+ messages in thread
* [Qemu-arm] [RFC PATCH 1/2] target/arm/kvm: Translate the MSI doorbell in kvm_arch_fixup_msi_route 2017-07-13 6:38 ` Bharat Bhushan @ 2017-07-13 6:38 ` Bharat Bhushan -1 siblings, 0 replies; 8+ messages in thread From: Bharat Bhushan @ 2017-07-13 6:38 UTC (permalink / raw) To: eric.auger, eric.auger.pro, peter.maydell, alex.williamson, mst, qemu-arm, qemu-devel Cc: kevin.tian, Bharat Bhushan, marc.zyngier, tn, will.deacon, drjones, robin.murphy, christoffer.dall Fix-up MSI address if it translate via virtual iommu. This code is based on http://patchwork.ozlabs.org/patch/785951/ Signed-off-by: Bharat Bhushan <Bharat.Bhushan@nxp.com> --- target/arm/kvm.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/target/arm/kvm.c b/target/arm/kvm.c index 4555468..eff7e8f 100644 --- a/target/arm/kvm.c +++ b/target/arm/kvm.c @@ -22,6 +22,9 @@ #include "cpu.h" #include "internals.h" #include "hw/arm/arm.h" +#include "hw/pci/pci.h" +#include "hw/pci/msi.h" +#include "hw/virtio/virtio-iommu.h" #include "exec/memattrs.h" #include "exec/address-spaces.h" #include "hw/boards.h" @@ -611,6 +614,24 @@ int kvm_arm_vgic_probe(void) int kvm_arch_fixup_msi_route(struct kvm_irq_routing_entry *route, uint64_t address, uint32_t data, PCIDevice *dev) { + AddressSpace *as = pci_device_iommu_address_space(dev); + IOMMUTLBEntry entry; + IOMMUDevice *sdev; + VirtIOIOMMU *s; + + if (as == &address_space_memory) { + return 0; + } + + /* MSI doorbell address is translated by an IOMMU */ + sdev = container_of(as, IOMMUDevice, as); + s = sdev->viommu; + + entry = s->iommu_ops.translate(&sdev->iommu_mr, address, IOMMU_WO); + + route->u.msi.address_lo = entry.translated_addr; + route->u.msi.address_hi = entry.translated_addr >> 32; + return 0; } -- 1.9.3 ^ permalink raw reply related [flat|nested] 8+ messages in thread
* [Qemu-devel] [RFC PATCH 1/2] target/arm/kvm: Translate the MSI doorbell in kvm_arch_fixup_msi_route @ 2017-07-13 6:38 ` Bharat Bhushan 0 siblings, 0 replies; 8+ messages in thread From: Bharat Bhushan @ 2017-07-13 6:38 UTC (permalink / raw) To: eric.auger, eric.auger.pro, peter.maydell, alex.williamson, mst, qemu-arm, qemu-devel Cc: wei, kevin.tian, marc.zyngier, tn, will.deacon, drjones, robin.murphy, christoffer.dall, Bharat Bhushan Fix-up MSI address if it translate via virtual iommu. This code is based on http://patchwork.ozlabs.org/patch/785951/ Signed-off-by: Bharat Bhushan <Bharat.Bhushan@nxp.com> --- target/arm/kvm.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/target/arm/kvm.c b/target/arm/kvm.c index 4555468..eff7e8f 100644 --- a/target/arm/kvm.c +++ b/target/arm/kvm.c @@ -22,6 +22,9 @@ #include "cpu.h" #include "internals.h" #include "hw/arm/arm.h" +#include "hw/pci/pci.h" +#include "hw/pci/msi.h" +#include "hw/virtio/virtio-iommu.h" #include "exec/memattrs.h" #include "exec/address-spaces.h" #include "hw/boards.h" @@ -611,6 +614,24 @@ int kvm_arm_vgic_probe(void) int kvm_arch_fixup_msi_route(struct kvm_irq_routing_entry *route, uint64_t address, uint32_t data, PCIDevice *dev) { + AddressSpace *as = pci_device_iommu_address_space(dev); + IOMMUTLBEntry entry; + IOMMUDevice *sdev; + VirtIOIOMMU *s; + + if (as == &address_space_memory) { + return 0; + } + + /* MSI doorbell address is translated by an IOMMU */ + sdev = container_of(as, IOMMUDevice, as); + s = sdev->viommu; + + entry = s->iommu_ops.translate(&sdev->iommu_mr, address, IOMMU_WO); + + route->u.msi.address_lo = entry.translated_addr; + route->u.msi.address_hi = entry.translated_addr >> 32; + return 0; } -- 1.9.3 ^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [Qemu-arm] [RFC PATCH 1/2] target/arm/kvm: Translate the MSI doorbell in kvm_arch_fixup_msi_route 2017-07-13 6:38 ` [Qemu-devel] " Bharat Bhushan @ 2017-07-13 16:10 ` Michael S. Tsirkin -1 siblings, 0 replies; 8+ messages in thread From: Michael S. Tsirkin @ 2017-07-13 16:10 UTC (permalink / raw) To: Bharat Bhushan Cc: peter.maydell, kevin.tian, drjones, marc.zyngier, tn, will.deacon, qemu-devel, eric.auger, alex.williamson, qemu-arm, robin.murphy, christoffer.dall, eric.auger.pro On Thu, Jul 13, 2017 at 12:08:41PM +0530, Bharat Bhushan wrote: > Fix-up MSI address if it translate via virtual iommu. > This code is based on http://patchwork.ozlabs.org/patch/785951/ > > Signed-off-by: Bharat Bhushan <Bharat.Bhushan@nxp.com> Links go dead with time. And following links is hard on reviewers. Please copy the full description tweaking as appropriate and attribute in commit log. > --- > target/arm/kvm.c | 21 +++++++++++++++++++++ > 1 file changed, 21 insertions(+) > > diff --git a/target/arm/kvm.c b/target/arm/kvm.c > index 4555468..eff7e8f 100644 > --- a/target/arm/kvm.c > +++ b/target/arm/kvm.c > @@ -22,6 +22,9 @@ > #include "cpu.h" > #include "internals.h" > #include "hw/arm/arm.h" > +#include "hw/pci/pci.h" > +#include "hw/pci/msi.h" > +#include "hw/virtio/virtio-iommu.h" > #include "exec/memattrs.h" > #include "exec/address-spaces.h" > #include "hw/boards.h" > @@ -611,6 +614,24 @@ int kvm_arm_vgic_probe(void) > int kvm_arch_fixup_msi_route(struct kvm_irq_routing_entry *route, > uint64_t address, uint32_t data, PCIDevice *dev) > { > + AddressSpace *as = pci_device_iommu_address_space(dev); > + IOMMUTLBEntry entry; > + IOMMUDevice *sdev; > + VirtIOIOMMU *s; > + > + if (as == &address_space_memory) { > + return 0; > + } > + > + /* MSI doorbell address is translated by an IOMMU */ > + sdev = container_of(as, IOMMUDevice, as); > + s = sdev->viommu; > + > + entry = s->iommu_ops.translate(&sdev->iommu_mr, address, IOMMU_WO); > + > + route->u.msi.address_lo = entry.translated_addr; > + route->u.msi.address_hi = entry.translated_addr >> 32; > + > return 0; > } > > -- > 1.9.3 ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [Qemu-devel] [RFC PATCH 1/2] target/arm/kvm: Translate the MSI doorbell in kvm_arch_fixup_msi_route @ 2017-07-13 16:10 ` Michael S. Tsirkin 0 siblings, 0 replies; 8+ messages in thread From: Michael S. Tsirkin @ 2017-07-13 16:10 UTC (permalink / raw) To: Bharat Bhushan Cc: eric.auger, eric.auger.pro, peter.maydell, alex.williamson, qemu-arm, qemu-devel, wei, kevin.tian, marc.zyngier, tn, will.deacon, drjones, robin.murphy, christoffer.dall On Thu, Jul 13, 2017 at 12:08:41PM +0530, Bharat Bhushan wrote: > Fix-up MSI address if it translate via virtual iommu. > This code is based on http://patchwork.ozlabs.org/patch/785951/ > > Signed-off-by: Bharat Bhushan <Bharat.Bhushan@nxp.com> Links go dead with time. And following links is hard on reviewers. Please copy the full description tweaking as appropriate and attribute in commit log. > --- > target/arm/kvm.c | 21 +++++++++++++++++++++ > 1 file changed, 21 insertions(+) > > diff --git a/target/arm/kvm.c b/target/arm/kvm.c > index 4555468..eff7e8f 100644 > --- a/target/arm/kvm.c > +++ b/target/arm/kvm.c > @@ -22,6 +22,9 @@ > #include "cpu.h" > #include "internals.h" > #include "hw/arm/arm.h" > +#include "hw/pci/pci.h" > +#include "hw/pci/msi.h" > +#include "hw/virtio/virtio-iommu.h" > #include "exec/memattrs.h" > #include "exec/address-spaces.h" > #include "hw/boards.h" > @@ -611,6 +614,24 @@ int kvm_arm_vgic_probe(void) > int kvm_arch_fixup_msi_route(struct kvm_irq_routing_entry *route, > uint64_t address, uint32_t data, PCIDevice *dev) > { > + AddressSpace *as = pci_device_iommu_address_space(dev); > + IOMMUTLBEntry entry; > + IOMMUDevice *sdev; > + VirtIOIOMMU *s; > + > + if (as == &address_space_memory) { > + return 0; > + } > + > + /* MSI doorbell address is translated by an IOMMU */ > + sdev = container_of(as, IOMMUDevice, as); > + s = sdev->viommu; > + > + entry = s->iommu_ops.translate(&sdev->iommu_mr, address, IOMMU_WO); > + > + route->u.msi.address_lo = entry.translated_addr; > + route->u.msi.address_hi = entry.translated_addr >> 32; > + > return 0; > } > > -- > 1.9.3 ^ permalink raw reply [flat|nested] 8+ messages in thread
* [Qemu-arm] [RFC PATCH 2/2] virtio-iommu: vfio integration with virtio-iommu 2017-07-13 6:38 ` Bharat Bhushan @ 2017-07-13 6:38 ` Bharat Bhushan -1 siblings, 0 replies; 8+ messages in thread From: Bharat Bhushan @ 2017-07-13 6:38 UTC (permalink / raw) To: eric.auger, eric.auger.pro, peter.maydell, alex.williamson, mst, qemu-arm, qemu-devel Cc: kevin.tian, Bharat Bhushan, marc.zyngier, tn, will.deacon, drjones, robin.murphy, christoffer.dall This patch allows virtio-iommu protection for PCI device-passthrough. MSI region is mapped by current version of virtio-iommu driver. This MSI region mapping in not getting pushed on hw iommu vfio_get_vaddr() allows only ram-region. This RFC patch needed to be improved. Signed-off-by: Bharat Bhushan <Bharat.Bhushan@nxp.com> --- hw/virtio/virtio-iommu.c | 127 +++++++++++++++++++++++++++++++++++++++ include/hw/virtio/virtio-iommu.h | 6 ++ 2 files changed, 133 insertions(+) diff --git a/hw/virtio/virtio-iommu.c b/hw/virtio/virtio-iommu.c index cd188fc..08d5a2f 100644 --- a/hw/virtio/virtio-iommu.c +++ b/hw/virtio/virtio-iommu.c @@ -129,6 +129,46 @@ static gint interval_cmp(gconstpointer a, gconstpointer b, gpointer user_data) } } +static void virtio_iommu_map_region(VirtIOIOMMU *s, hwaddr iova, hwaddr paddr, + hwaddr size, int map) +{ + VirtioIOMMUNotifierNode *node; + IOMMUTLBEntry entry; + uint64_t map_size = (1 << 12); + int npages; + int i; + + npages = size / map_size; + entry.target_as = &address_space_memory; + entry.addr_mask = map_size - 1; + + for (i = 0; i < npages; i++) { + entry.iova = iova + (i * map_size); + if (map) { + entry.perm = IOMMU_RW; + entry.translated_addr = paddr + (i * map_size); + } else { + entry.perm = IOMMU_NONE; + entry.translated_addr = 0; + } + + QLIST_FOREACH(node, &s->notifiers_list, next) { + memory_region_notify_iommu(&node->iommu_dev->iommu_mr, entry); + } + } +} + +static gboolean virtio_iommu_unmap_single(gpointer key, gpointer value, + gpointer data) +{ + viommu_mapping *mapping = (viommu_mapping *) value; + VirtIOIOMMU *s = (VirtIOIOMMU *) data; + + virtio_iommu_map_region(s, mapping->virt_addr, 0, mapping->size, 0); + + return true; +} + static int virtio_iommu_attach(VirtIOIOMMU *s, struct virtio_iommu_req_attach *req) { @@ -170,10 +210,26 @@ static int virtio_iommu_detach(VirtIOIOMMU *s, { uint32_t devid = le32_to_cpu(req->device); uint32_t reserved = le32_to_cpu(req->reserved); + viommu_dev *dev; int ret; trace_virtio_iommu_detach(devid, reserved); + dev = g_tree_lookup(s->devices, GUINT_TO_POINTER(devid)); + if (!dev || !dev->as) { + return -EINVAL; + } + + dev->as->nr_devices--; + + /* Unmap all if this is last device detached */ + if (dev->as->nr_devices == 0) { + g_tree_foreach(dev->as->mappings, virtio_iommu_unmap_single, s); + + g_tree_remove(s->address_spaces, GUINT_TO_POINTER(dev->as->id)); + g_tree_destroy(dev->as->mappings); + } + ret = g_tree_remove(s->devices, GUINT_TO_POINTER(devid)); return ret ? VIRTIO_IOMMU_S_OK : VIRTIO_IOMMU_S_INVAL; @@ -217,6 +273,7 @@ static int virtio_iommu_map(VirtIOIOMMU *s, g_tree_insert(as->mappings, interval, mapping); + virtio_iommu_map_region(s, virt_addr, phys_addr, size, 1); return VIRTIO_IOMMU_S_OK; } @@ -267,7 +324,9 @@ static int virtio_iommu_unmap(VirtIOIOMMU *s, } else { break; } + if (interval.low >= interval.high) { + virtio_iommu_map_region(s, virt_addr, 0, size, 0); return VIRTIO_IOMMU_S_OK; } else { mapping = g_tree_lookup(as->mappings, (gpointer)&interval); @@ -410,6 +469,35 @@ static void virtio_iommu_handle_command(VirtIODevice *vdev, VirtQueue *vq) } } +static void virtio_iommu_notify_flag_changed(MemoryRegion *iommu, + IOMMUNotifierFlag old, + IOMMUNotifierFlag new) +{ + IOMMUDevice *sdev = container_of(iommu, IOMMUDevice, iommu_mr); + VirtIOIOMMU *s = sdev->viommu; + VirtioIOMMUNotifierNode *node = NULL; + VirtioIOMMUNotifierNode *next_node = NULL; + + if (old == IOMMU_NOTIFIER_NONE) { + node = g_malloc0(sizeof(*node)); + node->iommu_dev = sdev; + QLIST_INSERT_HEAD(&s->notifiers_list, node, next); + return; + } + + /* update notifier node with new flags */ + QLIST_FOREACH_SAFE(node, &s->notifiers_list, next, next_node) { + if (node->iommu_dev == sdev) { + if (new == IOMMU_NOTIFIER_NONE) { + QLIST_REMOVE(node, next); + g_free(node); + } + return; + } + } +} + + static IOMMUTLBEntry virtio_iommu_translate(MemoryRegion *mr, hwaddr addr, IOMMUAccessFlags flag) { @@ -523,11 +611,48 @@ static gint int_cmp(gconstpointer a, gconstpointer b, gpointer user_data) return (ua > ub) - (ua < ub); } +static gboolean virtio_iommu_remap(gpointer key, gpointer value, gpointer data) +{ + viommu_mapping *mapping = (viommu_mapping *) value; + VirtIOIOMMU *s = (VirtIOIOMMU *) data; + + /* unmap previous entry and map again */ + virtio_iommu_map_region(s, mapping->virt_addr, 0, mapping->size, 0); + + virtio_iommu_map_region(s, mapping->virt_addr, mapping->phys_addr, + mapping->size, 1); + return true; +} + +static void virtio_iommu_replay(MemoryRegion *mr, IOMMUNotifier *n) +{ + IOMMUDevice *sdev = container_of(mr, IOMMUDevice, iommu_mr); + VirtIOIOMMU *s = sdev->viommu; + uint32_t sid; + viommu_dev *dev; + + sid = smmu_get_sid(sdev); + + qemu_mutex_lock(&s->mutex); + + dev = g_tree_lookup(s->devices, GUINT_TO_POINTER(sid)); + if (!dev) { + goto unlock; + } + + g_tree_foreach(dev->as->mappings, virtio_iommu_remap, s); + +unlock: + qemu_mutex_unlock(&s->mutex); + return; +} + static void virtio_iommu_device_realize(DeviceState *dev, Error **errp) { VirtIODevice *vdev = VIRTIO_DEVICE(dev); VirtIOIOMMU *s = VIRTIO_IOMMU(dev); + QLIST_INIT(&s->notifiers_list); virtio_init(vdev, "virtio-iommu", VIRTIO_ID_IOMMU, sizeof(struct virtio_iommu_config)); @@ -538,6 +663,8 @@ static void virtio_iommu_device_realize(DeviceState *dev, Error **errp) s->config.input_range.end = -1UL; s->iommu_ops.translate = virtio_iommu_translate; + s->iommu_ops.notify_flag_changed = virtio_iommu_notify_flag_changed; + s->iommu_ops.replay = virtio_iommu_replay; memset(s->as_by_bus_num, 0, sizeof(s->as_by_bus_num)); s->as_by_busptr = g_hash_table_new_full(as_uint64_hash, as_uint64_equal, diff --git a/include/hw/virtio/virtio-iommu.h b/include/hw/virtio/virtio-iommu.h index 2259413..76c758d 100644 --- a/include/hw/virtio/virtio-iommu.h +++ b/include/hw/virtio/virtio-iommu.h @@ -44,6 +44,11 @@ typedef struct IOMMUPciBus { IOMMUDevice *pbdev[0]; /* Parent array is sparse, so dynamically alloc */ } IOMMUPciBus; +typedef struct VirtioIOMMUNotifierNode { + IOMMUDevice *iommu_dev; + QLIST_ENTRY(VirtioIOMMUNotifierNode) next; +} VirtioIOMMUNotifierNode; + typedef struct VirtIOIOMMU { VirtIODevice parent_obj; VirtQueue *vq; @@ -55,6 +60,7 @@ typedef struct VirtIOIOMMU { GTree *address_spaces; QemuMutex mutex; GTree *devices; + QLIST_HEAD(, VirtioIOMMUNotifierNode) notifiers_list; } VirtIOIOMMU; #endif -- 1.9.3 ^ permalink raw reply related [flat|nested] 8+ messages in thread
* [Qemu-devel] [RFC PATCH 2/2] virtio-iommu: vfio integration with virtio-iommu @ 2017-07-13 6:38 ` Bharat Bhushan 0 siblings, 0 replies; 8+ messages in thread From: Bharat Bhushan @ 2017-07-13 6:38 UTC (permalink / raw) To: eric.auger, eric.auger.pro, peter.maydell, alex.williamson, mst, qemu-arm, qemu-devel Cc: wei, kevin.tian, marc.zyngier, tn, will.deacon, drjones, robin.murphy, christoffer.dall, Bharat Bhushan This patch allows virtio-iommu protection for PCI device-passthrough. MSI region is mapped by current version of virtio-iommu driver. This MSI region mapping in not getting pushed on hw iommu vfio_get_vaddr() allows only ram-region. This RFC patch needed to be improved. Signed-off-by: Bharat Bhushan <Bharat.Bhushan@nxp.com> --- hw/virtio/virtio-iommu.c | 127 +++++++++++++++++++++++++++++++++++++++ include/hw/virtio/virtio-iommu.h | 6 ++ 2 files changed, 133 insertions(+) diff --git a/hw/virtio/virtio-iommu.c b/hw/virtio/virtio-iommu.c index cd188fc..08d5a2f 100644 --- a/hw/virtio/virtio-iommu.c +++ b/hw/virtio/virtio-iommu.c @@ -129,6 +129,46 @@ static gint interval_cmp(gconstpointer a, gconstpointer b, gpointer user_data) } } +static void virtio_iommu_map_region(VirtIOIOMMU *s, hwaddr iova, hwaddr paddr, + hwaddr size, int map) +{ + VirtioIOMMUNotifierNode *node; + IOMMUTLBEntry entry; + uint64_t map_size = (1 << 12); + int npages; + int i; + + npages = size / map_size; + entry.target_as = &address_space_memory; + entry.addr_mask = map_size - 1; + + for (i = 0; i < npages; i++) { + entry.iova = iova + (i * map_size); + if (map) { + entry.perm = IOMMU_RW; + entry.translated_addr = paddr + (i * map_size); + } else { + entry.perm = IOMMU_NONE; + entry.translated_addr = 0; + } + + QLIST_FOREACH(node, &s->notifiers_list, next) { + memory_region_notify_iommu(&node->iommu_dev->iommu_mr, entry); + } + } +} + +static gboolean virtio_iommu_unmap_single(gpointer key, gpointer value, + gpointer data) +{ + viommu_mapping *mapping = (viommu_mapping *) value; + VirtIOIOMMU *s = (VirtIOIOMMU *) data; + + virtio_iommu_map_region(s, mapping->virt_addr, 0, mapping->size, 0); + + return true; +} + static int virtio_iommu_attach(VirtIOIOMMU *s, struct virtio_iommu_req_attach *req) { @@ -170,10 +210,26 @@ static int virtio_iommu_detach(VirtIOIOMMU *s, { uint32_t devid = le32_to_cpu(req->device); uint32_t reserved = le32_to_cpu(req->reserved); + viommu_dev *dev; int ret; trace_virtio_iommu_detach(devid, reserved); + dev = g_tree_lookup(s->devices, GUINT_TO_POINTER(devid)); + if (!dev || !dev->as) { + return -EINVAL; + } + + dev->as->nr_devices--; + + /* Unmap all if this is last device detached */ + if (dev->as->nr_devices == 0) { + g_tree_foreach(dev->as->mappings, virtio_iommu_unmap_single, s); + + g_tree_remove(s->address_spaces, GUINT_TO_POINTER(dev->as->id)); + g_tree_destroy(dev->as->mappings); + } + ret = g_tree_remove(s->devices, GUINT_TO_POINTER(devid)); return ret ? VIRTIO_IOMMU_S_OK : VIRTIO_IOMMU_S_INVAL; @@ -217,6 +273,7 @@ static int virtio_iommu_map(VirtIOIOMMU *s, g_tree_insert(as->mappings, interval, mapping); + virtio_iommu_map_region(s, virt_addr, phys_addr, size, 1); return VIRTIO_IOMMU_S_OK; } @@ -267,7 +324,9 @@ static int virtio_iommu_unmap(VirtIOIOMMU *s, } else { break; } + if (interval.low >= interval.high) { + virtio_iommu_map_region(s, virt_addr, 0, size, 0); return VIRTIO_IOMMU_S_OK; } else { mapping = g_tree_lookup(as->mappings, (gpointer)&interval); @@ -410,6 +469,35 @@ static void virtio_iommu_handle_command(VirtIODevice *vdev, VirtQueue *vq) } } +static void virtio_iommu_notify_flag_changed(MemoryRegion *iommu, + IOMMUNotifierFlag old, + IOMMUNotifierFlag new) +{ + IOMMUDevice *sdev = container_of(iommu, IOMMUDevice, iommu_mr); + VirtIOIOMMU *s = sdev->viommu; + VirtioIOMMUNotifierNode *node = NULL; + VirtioIOMMUNotifierNode *next_node = NULL; + + if (old == IOMMU_NOTIFIER_NONE) { + node = g_malloc0(sizeof(*node)); + node->iommu_dev = sdev; + QLIST_INSERT_HEAD(&s->notifiers_list, node, next); + return; + } + + /* update notifier node with new flags */ + QLIST_FOREACH_SAFE(node, &s->notifiers_list, next, next_node) { + if (node->iommu_dev == sdev) { + if (new == IOMMU_NOTIFIER_NONE) { + QLIST_REMOVE(node, next); + g_free(node); + } + return; + } + } +} + + static IOMMUTLBEntry virtio_iommu_translate(MemoryRegion *mr, hwaddr addr, IOMMUAccessFlags flag) { @@ -523,11 +611,48 @@ static gint int_cmp(gconstpointer a, gconstpointer b, gpointer user_data) return (ua > ub) - (ua < ub); } +static gboolean virtio_iommu_remap(gpointer key, gpointer value, gpointer data) +{ + viommu_mapping *mapping = (viommu_mapping *) value; + VirtIOIOMMU *s = (VirtIOIOMMU *) data; + + /* unmap previous entry and map again */ + virtio_iommu_map_region(s, mapping->virt_addr, 0, mapping->size, 0); + + virtio_iommu_map_region(s, mapping->virt_addr, mapping->phys_addr, + mapping->size, 1); + return true; +} + +static void virtio_iommu_replay(MemoryRegion *mr, IOMMUNotifier *n) +{ + IOMMUDevice *sdev = container_of(mr, IOMMUDevice, iommu_mr); + VirtIOIOMMU *s = sdev->viommu; + uint32_t sid; + viommu_dev *dev; + + sid = smmu_get_sid(sdev); + + qemu_mutex_lock(&s->mutex); + + dev = g_tree_lookup(s->devices, GUINT_TO_POINTER(sid)); + if (!dev) { + goto unlock; + } + + g_tree_foreach(dev->as->mappings, virtio_iommu_remap, s); + +unlock: + qemu_mutex_unlock(&s->mutex); + return; +} + static void virtio_iommu_device_realize(DeviceState *dev, Error **errp) { VirtIODevice *vdev = VIRTIO_DEVICE(dev); VirtIOIOMMU *s = VIRTIO_IOMMU(dev); + QLIST_INIT(&s->notifiers_list); virtio_init(vdev, "virtio-iommu", VIRTIO_ID_IOMMU, sizeof(struct virtio_iommu_config)); @@ -538,6 +663,8 @@ static void virtio_iommu_device_realize(DeviceState *dev, Error **errp) s->config.input_range.end = -1UL; s->iommu_ops.translate = virtio_iommu_translate; + s->iommu_ops.notify_flag_changed = virtio_iommu_notify_flag_changed; + s->iommu_ops.replay = virtio_iommu_replay; memset(s->as_by_bus_num, 0, sizeof(s->as_by_bus_num)); s->as_by_busptr = g_hash_table_new_full(as_uint64_hash, as_uint64_equal, diff --git a/include/hw/virtio/virtio-iommu.h b/include/hw/virtio/virtio-iommu.h index 2259413..76c758d 100644 --- a/include/hw/virtio/virtio-iommu.h +++ b/include/hw/virtio/virtio-iommu.h @@ -44,6 +44,11 @@ typedef struct IOMMUPciBus { IOMMUDevice *pbdev[0]; /* Parent array is sparse, so dynamically alloc */ } IOMMUPciBus; +typedef struct VirtioIOMMUNotifierNode { + IOMMUDevice *iommu_dev; + QLIST_ENTRY(VirtioIOMMUNotifierNode) next; +} VirtioIOMMUNotifierNode; + typedef struct VirtIOIOMMU { VirtIODevice parent_obj; VirtQueue *vq; @@ -55,6 +60,7 @@ typedef struct VirtIOIOMMU { GTree *address_spaces; QemuMutex mutex; GTree *devices; + QLIST_HEAD(, VirtioIOMMUNotifierNode) notifiers_list; } VirtIOIOMMU; #endif -- 1.9.3 ^ permalink raw reply related [flat|nested] 8+ messages in thread
end of thread, other threads:[~2017-07-13 16:19 UTC | newest] Thread overview: 8+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2017-07-13 6:38 [Qemu-devel] [RFC PATCH 0/2] VFIO integration Bharat Bhushan 2017-07-13 6:38 ` Bharat Bhushan 2017-07-13 6:38 ` [Qemu-arm] [RFC PATCH 1/2] target/arm/kvm: Translate the MSI doorbell in kvm_arch_fixup_msi_route Bharat Bhushan 2017-07-13 6:38 ` [Qemu-devel] " Bharat Bhushan 2017-07-13 16:10 ` [Qemu-arm] " Michael S. Tsirkin 2017-07-13 16:10 ` [Qemu-devel] " Michael S. Tsirkin 2017-07-13 6:38 ` [Qemu-arm] [RFC PATCH 2/2] virtio-iommu: vfio integration with virtio-iommu Bharat Bhushan 2017-07-13 6:38 ` [Qemu-devel] " Bharat Bhushan
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.