[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH v12 06/13] virtio-iommu: Implement attach/detach command
From: |
Eric Auger |
Subject: |
[PATCH v12 06/13] virtio-iommu: Implement attach/detach command |
Date: |
Thu, 9 Jan 2020 15:43:12 +0100 |
This patch implements the endpoint attach/detach to/from
a domain.
Signed-off-by: Eric Auger <address@hidden>
---
v11 -> v12:
- check the device is protected by the iommu on attach
- on detach, check the domain id the device is attached to matches
the one used in the detach command
- fix mapping ref counter and destroy the domain when no end-points
are attached anymore
---
hw/virtio/virtio-iommu.c | 65 +++++++++++++++++++++++++++++++++++-----
1 file changed, 58 insertions(+), 7 deletions(-)
diff --git a/hw/virtio/virtio-iommu.c b/hw/virtio/virtio-iommu.c
index 6a03c3d7ae..63b2d30f28 100644
--- a/hw/virtio/virtio-iommu.c
+++ b/hw/virtio/virtio-iommu.c
@@ -119,11 +119,12 @@ static gint interval_cmp(gconstpointer a, gconstpointer
b, gpointer user_data)
static void virtio_iommu_detach_endpoint_from_domain(VirtIOIOMMUEndpoint *ep)
{
QLIST_REMOVE(ep, next);
+ g_tree_unref(ep->domain->mappings);
ep->domain = NULL;
}
-VirtIOIOMMUEndpoint *virtio_iommu_get_endpoint(VirtIOIOMMU *s, uint32_t ep_id);
-VirtIOIOMMUEndpoint *virtio_iommu_get_endpoint(VirtIOIOMMU *s, uint32_t ep_id)
+static VirtIOIOMMUEndpoint *virtio_iommu_get_endpoint(VirtIOIOMMU *s,
+ uint32_t ep_id)
{
VirtIOIOMMUEndpoint *ep;
@@ -151,8 +152,8 @@ static void virtio_iommu_put_endpoint(gpointer data)
g_free(ep);
}
-VirtIOIOMMUDomain *virtio_iommu_get_domain(VirtIOIOMMU *s, uint32_t domain_id);
-VirtIOIOMMUDomain *virtio_iommu_get_domain(VirtIOIOMMU *s, uint32_t domain_id)
+static VirtIOIOMMUDomain *virtio_iommu_get_domain(VirtIOIOMMU *s,
+ uint32_t domain_id)
{
VirtIOIOMMUDomain *domain;
@@ -179,7 +180,6 @@ static void virtio_iommu_put_domain(gpointer data)
QLIST_FOREACH_SAFE(iter, &domain->endpoint_list, next, tmp) {
virtio_iommu_detach_endpoint_from_domain(iter);
}
- g_tree_destroy(domain->mappings);
trace_virtio_iommu_put_domain(domain->id);
g_free(domain);
}
@@ -228,10 +228,37 @@ static int virtio_iommu_attach(VirtIOIOMMU *s,
{
uint32_t domain_id = le32_to_cpu(req->domain);
uint32_t ep_id = le32_to_cpu(req->endpoint);
+ VirtIOIOMMUDomain *domain;
+ VirtIOIOMMUEndpoint *ep;
trace_virtio_iommu_attach(domain_id, ep_id);
- return VIRTIO_IOMMU_S_UNSUPP;
+ ep = virtio_iommu_get_endpoint(s, ep_id);
+ if (!ep) {
+ return VIRTIO_IOMMU_S_NOENT;
+ }
+
+ if (ep->domain) {
+ VirtIOIOMMUDomain *previous_domain = ep->domain;
+ /*
+ * the device is already attached to a domain,
+ * detach it first
+ */
+ virtio_iommu_detach_endpoint_from_domain(ep);
+ if (QLIST_EMPTY(&previous_domain->endpoint_list)) {
+ g_tree_remove(s->domains, GUINT_TO_POINTER(previous_domain->id));
+ }
+ }
+
+ domain = virtio_iommu_get_domain(s, domain_id);
+ if (!QLIST_EMPTY(&domain->endpoint_list)) {
+ g_tree_ref(domain->mappings);
+ }
+ QLIST_INSERT_HEAD(&domain->endpoint_list, ep, next);
+
+ ep->domain = domain;
+
+ return VIRTIO_IOMMU_S_OK;
}
static int virtio_iommu_detach(VirtIOIOMMU *s,
@@ -239,10 +266,34 @@ static int virtio_iommu_detach(VirtIOIOMMU *s,
{
uint32_t domain_id = le32_to_cpu(req->domain);
uint32_t ep_id = le32_to_cpu(req->endpoint);
+ VirtIOIOMMUDomain *domain;
+ VirtIOIOMMUEndpoint *ep;
trace_virtio_iommu_detach(domain_id, ep_id);
- return VIRTIO_IOMMU_S_UNSUPP;
+ ep = g_tree_lookup(s->endpoints, GUINT_TO_POINTER(ep_id));
+ if (!ep) {
+ return VIRTIO_IOMMU_S_NOENT;
+ }
+
+ domain = ep->domain;
+
+ if (!domain || domain->id != domain_id) {
+ return VIRTIO_IOMMU_S_INVAL;
+ }
+
+ virtio_iommu_detach_endpoint_from_domain(ep);
+
+ /*
+ * when the last EP is detached, simply remove the domain for
+ * the domain list and destroy it. Note its mappings were already
+ * freed by the ref count mechanism. Next operation involving
+ * the same domain id will re-create one domain object.
+ */
+ if (QLIST_EMPTY(&domain->endpoint_list)) {
+ g_tree_remove(s->domains, GUINT_TO_POINTER(domain->id));
+ }
+ return VIRTIO_IOMMU_S_OK;
}
static int virtio_iommu_map(VirtIOIOMMU *s,
--
2.20.1
- Re: [PATCH v12 04/13] virtio-iommu: Add the iommu regions, (continued)
- [PATCH v12 05/13] virtio-iommu: Endpoint and domains structs and helpers, Eric Auger, 2020/01/09
- Re: [PATCH v12 05/13] virtio-iommu: Endpoint and domains structs and helpers, Peter Xu, 2020/01/13
- Re: [PATCH v12 05/13] virtio-iommu: Endpoint and domains structs and helpers, Auger Eric, 2020/01/14
- Re: [PATCH v12 05/13] virtio-iommu: Endpoint and domains structs and helpers, Peter Xu, 2020/01/14
- Re: [PATCH v12 05/13] virtio-iommu: Endpoint and domains structs and helpers, Auger Eric, 2020/01/15
- Re: [PATCH v12 05/13] virtio-iommu: Endpoint and domains structs and helpers, Peter Xu, 2020/01/15
- Re: [PATCH v12 05/13] virtio-iommu: Endpoint and domains structs and helpers, Auger Eric, 2020/01/15
- Re: [PATCH v12 05/13] virtio-iommu: Endpoint and domains structs and helpers, Auger Eric, 2020/01/15
[PATCH v12 06/13] virtio-iommu: Implement attach/detach command,
Eric Auger <=
[PATCH v12 07/13] virtio-iommu: Implement map/unmap, Eric Auger, 2020/01/09
[PATCH v12 08/13] virtio-iommu: Implement translate, Eric Auger, 2020/01/09
[PATCH v12 09/13] virtio-iommu: Implement fault reporting, Eric Auger, 2020/01/09
[PATCH v12 10/13] virtio-iommu-pci: Add virtio iommu pci support, Eric Auger, 2020/01/09
[PATCH v12 11/13] hw/arm/virt: Add the virtio-iommu device tree mappings, Eric Auger, 2020/01/09