All of lore.kernel.org
 help / color / mirror / Atom feed
From: Bharat Bhushan <bharat.bhushan@nxp.com>
To: "peter.maydell@linaro.org" <peter.maydell@linaro.org>,
	"alex.williamson@redhat.com" <alex.williamson@redhat.com>,
	"kevin.tian@intel.com" <kevin.tian@intel.com>,
	"mst@redhat.com" <mst@redhat.com>,
	"tn@semihalf.com" <tn@semihalf.com>,
	"drjones@redhat.com" <drjones@redhat.com>,
	"linu.cherian@cavium.com" <linu.cherian@cavium.com>,
	"linuc.decode@gmail.com" <linuc.decode@gmail.com>,
	"qemu-devel@nongnu.org" <qemu-devel@nongnu.org>,
	"qemu-arm@nongnu.org" <qemu-arm@nongnu.org>
Cc: "eric.auger.pro@gmail.com" <eric.auger.pro@gmail.com>,
	"peterx@redhat.com" <peterx@redhat.com>,
	"bharatb.yadav@gmail.com" <bharatb.yadav@gmail.com>,
	Bharat Bhushan <bharat.bhushan@nxp.com>
Subject: [Qemu-devel] [PATCH RFC v5 2/5] virtio-iommu: Add iommu notifier for iommu-map/unmap
Date: Tue, 27 Nov 2018 06:52:50 +0000	[thread overview]
Message-ID: <20181127064101.25887-3-Bharat.Bhushan@nxp.com> (raw)
In-Reply-To: <20181127064101.25887-1-Bharat.Bhushan@nxp.com>

This patch extends VIRTIO_IOMMU_T_MAP/UNMAP request
handling to notify registered iommu-notifier. These
iommu-notifier maps the requested region in IOMMU using vfio.

Signed-off-by: Bharat Bhushan <Bharat.Bhushan@nxp.com>
---
v4->v5:
 - Rebase to v9 version from Eric
 - PCIe device hotplug fix

 hw/virtio/trace-events           |  2 +
 hw/virtio/virtio-iommu.c         | 74 ++++++++++++++++++++++++++++++--
 include/hw/virtio/virtio-iommu.h |  6 +++
 3 files changed, 79 insertions(+), 3 deletions(-)

diff --git a/hw/virtio/trace-events b/hw/virtio/trace-events
index 053a07b3fc..420b1e471b 100644
--- a/hw/virtio/trace-events
+++ b/hw/virtio/trace-events
@@ -72,3 +72,5 @@ virtio_iommu_translate_out(uint64_t virt_addr, uint64_t phys_addr, uint32_t sid)
 virtio_iommu_fill_resv_property(uint32_t devid, uint8_t subtype, uint64_t start, uint64_t end, uint32_t flags, size_t filled) "dev= %d, subtype=%d start=0x%"PRIx64" end=0x%"PRIx64" flags=%d filled=0x%lx"
 virtio_iommu_fill_none_property(uint32_t devid) "devid=%d"
 virtio_iommu_report_fault(uint8_t reason, uint32_t flags, uint32_t endpoint, uint64_t addr) "FAULT reason=%d flags=%d endpoint=%d address =0x%"PRIx64
+virtio_iommu_notify_map(const char *name, uint64_t iova, uint64_t paddr, uint64_t map_size) "mr=%s iova=0x%"PRIx64" pa=0x%" PRIx64" size=0x%"PRIx64""
+virtio_iommu_notify_unmap(const char *name, uint64_t iova, uint64_t map_size) "mr=%s iova=0x%"PRIx64" size=0x%"PRIx64""
diff --git a/hw/virtio/virtio-iommu.c b/hw/virtio/virtio-iommu.c
index 2ec01f3b9e..613a77521d 100644
--- a/hw/virtio/virtio-iommu.c
+++ b/hw/virtio/virtio-iommu.c
@@ -99,6 +99,38 @@ static gint interval_cmp(gconstpointer a, gconstpointer b, gpointer user_data)
     }
 }
 
+static void virtio_iommu_notify_map(IOMMUMemoryRegion *mr, hwaddr iova,
+                                    hwaddr paddr, hwaddr size)
+{
+    IOMMUTLBEntry entry;
+
+    trace_virtio_iommu_notify_map(mr->parent_obj.name, iova, paddr, size);
+
+    entry.target_as = &address_space_memory;
+    entry.addr_mask = size - 1;
+    entry.iova = iova;
+    entry.perm = IOMMU_RW;
+    entry.translated_addr = paddr;
+
+    memory_region_notify_iommu(mr, 0, entry);
+}
+
+static void virtio_iommu_notify_unmap(IOMMUMemoryRegion *mr, hwaddr iova,
+                                      hwaddr size)
+{
+    IOMMUTLBEntry entry;
+
+    trace_virtio_iommu_notify_unmap(mr->parent_obj.name, iova, size);
+
+    entry.target_as = &address_space_memory;
+    entry.addr_mask = size - 1;
+    entry.iova = iova;
+    entry.perm = IOMMU_NONE;
+    entry.translated_addr = 0;
+
+    memory_region_notify_iommu(mr, 0, entry);
+}
+
 static void virtio_iommu_detach_endpoint_from_domain(viommu_endpoint *ep)
 {
     QLIST_REMOVE(ep, next);
@@ -301,9 +333,12 @@ static int virtio_iommu_map(VirtIOIOMMU *s,
     uint64_t virt_start = le64_to_cpu(req->virt_start);
     uint64_t virt_end = le64_to_cpu(req->virt_end);
     uint32_t flags = le32_to_cpu(req->flags);
+    VirtioIOMMUNotifierNode *node;
+    viommu_endpoint *ep;
     viommu_domain *domain;
     viommu_interval *interval;
     viommu_mapping *mapping;
+    uint32_t sid;
 
     interval = g_malloc0(sizeof(*interval));
 
@@ -331,9 +366,40 @@ static int virtio_iommu_map(VirtIOIOMMU *s,
 
     g_tree_insert(domain->mappings, interval, mapping);
 
+    /* All devices in an address-space share mapping */
+    QLIST_FOREACH(node, &s->notifiers_list, next) {
+        QLIST_FOREACH(ep, &domain->endpoint_list, next) {
+            sid = virtio_iommu_get_sid(node->iommu_dev);
+            if (ep->id == sid) {
+                virtio_iommu_notify_map(&node->iommu_dev->iommu_mr,
+                                        virt_start, phys_start, mapping->size);
+            }
+        }
+    }
+
     return VIRTIO_IOMMU_S_OK;
 }
 
+static void virtio_iommu_remove_mapping(VirtIOIOMMU *s, viommu_domain *domain,
+                                        viommu_interval *interval)
+{
+    VirtioIOMMUNotifierNode *node;
+    viommu_endpoint *ep;
+    uint32_t sid;
+
+    g_tree_remove(domain->mappings, (gpointer)(interval));
+    QLIST_FOREACH(node, &s->notifiers_list, next) {
+        QLIST_FOREACH(ep, &domain->endpoint_list, next) {
+            sid = virtio_iommu_get_sid(node->iommu_dev);
+            if (ep->id == sid) {
+                virtio_iommu_notify_unmap(&node->iommu_dev->iommu_mr,
+                                          interval->low,
+                                          interval->high - interval->low + 1);
+            }
+        }
+    }
+}
+
 static int virtio_iommu_unmap(VirtIOIOMMU *s,
                               struct virtio_iommu_req_unmap *req)
 {
@@ -366,18 +432,18 @@ static int virtio_iommu_unmap(VirtIOIOMMU *s,
         current.high = high;
 
         if (low == interval.low && size >= mapping->size) {
-            g_tree_remove(domain->mappings, (gpointer)(&current));
+            virtio_iommu_remove_mapping(s, domain, &current);
             interval.low = high + 1;
             trace_virtio_iommu_unmap_left_interval(current.low, current.high,
                 interval.low, interval.high);
         } else if (high == interval.high && size >= mapping->size) {
             trace_virtio_iommu_unmap_right_interval(current.low, current.high,
                 interval.low, interval.high);
-            g_tree_remove(domain->mappings, (gpointer)(&current));
+            virtio_iommu_remove_mapping(s, domain, &current);
             interval.high = low - 1;
         } else if (low > interval.low && high < interval.high) {
             trace_virtio_iommu_unmap_inc_interval(current.low, current.high);
-            g_tree_remove(domain->mappings, (gpointer)(&current));
+            virtio_iommu_remove_mapping(s, domain, &current);
         } else {
             break;
         }
@@ -907,6 +973,8 @@ 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));
 
diff --git a/include/hw/virtio/virtio-iommu.h b/include/hw/virtio/virtio-iommu.h
index 56c8b4e57f..65bda6d6fe 100644
--- a/include/hw/virtio/virtio-iommu.h
+++ b/include/hw/virtio/virtio-iommu.h
@@ -46,6 +46,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 *req_vq;
@@ -60,6 +65,7 @@ typedef struct VirtIOIOMMU {
     QemuMutex mutex;
     GTree *endpoints;
     bool msi_bypass;
+    QLIST_HEAD(, VirtioIOMMUNotifierNode) notifiers_list;
 } VirtIOIOMMU;
 
 #endif
-- 
2.19.1

  parent reply	other threads:[~2018-11-27  6:53 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-11-27  6:52 [Qemu-devel] [PATCH RFC v5 0/5] virtio-iommu: VFIO integration Bharat Bhushan
2018-11-27  6:52 ` [Qemu-devel] [PATCH RFC v5 1/5] hw/vfio/common: Do not print error when viommu translates into an mmio region Bharat Bhushan
2018-11-27  6:52 ` Bharat Bhushan [this message]
2018-11-27  6:52 ` [Qemu-devel] [PATCH RFC v5 3/5] virtio-iommu: Call iommu notifier on attach/detach Bharat Bhushan
2018-11-27  6:52 ` [Qemu-devel] [PATCH RFC v5 4/5] virtio-iommu: add virtio-iommu replay Bharat Bhushan
2018-11-27  6:53 ` [Qemu-devel] [PATCH RFC v5 5/5] virtio-iommu: handle IOMMU Notifier flag changes Bharat Bhushan
2020-02-28  9:36 ` [Qemu-devel] [PATCH RFC v5 0/5] virtio-iommu: VFIO integration Auger Eric
2020-03-02  5:12   ` Bharat Bhushan
2020-03-02  7:00     ` Auger Eric

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20181127064101.25887-3-Bharat.Bhushan@nxp.com \
    --to=bharat.bhushan@nxp.com \
    --cc=alex.williamson@redhat.com \
    --cc=bharatb.yadav@gmail.com \
    --cc=drjones@redhat.com \
    --cc=eric.auger.pro@gmail.com \
    --cc=kevin.tian@intel.com \
    --cc=linu.cherian@cavium.com \
    --cc=linuc.decode@gmail.com \
    --cc=mst@redhat.com \
    --cc=peter.maydell@linaro.org \
    --cc=peterx@redhat.com \
    --cc=qemu-arm@nongnu.org \
    --cc=qemu-devel@nongnu.org \
    --cc=tn@semihalf.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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.