All of lore.kernel.org
 help / color / mirror / Atom feed
From: Jean-Philippe Brucker <jean-philippe.brucker@arm.com>
To: iommu@lists.linux-foundation.org, kvm@vger.kernel.org,
	virtualization@lists.linux-foundation.org,
	virtio-dev@lists.oasis-open.org
Cc: cdall@linaro.org, will.deacon@arm.com, robin.murphy@arm.com,
	lorenzo.pieralisi@arm.com, joro@8bytes.org, mst@redhat.com,
	jasowang@redhat.com, alex.williamson@redhat.com,
	marc.zyngier@arm.com
Subject: [RFC PATCH kvmtool 04/15] Add a simple IOMMU
Date: Fri,  7 Apr 2017 20:24:44 +0100	[thread overview]
Message-ID: <20170407192455.26814-5-jean-philippe.brucker@arm.com> (raw)
In-Reply-To: <20170407192455.26814-1-jean-philippe.brucker@arm.com>

Add a rb-tree based IOMMU with support for map, unmap and access
operations. It will be used to store mappings for virtio devices and MSI
doorbells. If needed, it could also be extended with a TLB implementation.

Signed-off-by: Jean-Philippe Brucker <jean-philippe.brucker@arm.com>
---
 Makefile            |   1 +
 include/kvm/iommu.h |   9 +++
 iommu.c             | 162 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 172 insertions(+)
 create mode 100644 iommu.c

diff --git a/Makefile b/Makefile
index 67953870..0c369206 100644
--- a/Makefile
+++ b/Makefile
@@ -73,6 +73,7 @@ OBJS	+= disk/blk.o
 OBJS	+= disk/qcow.o
 OBJS	+= disk/raw.o
 OBJS	+= ioeventfd.o
+OBJS	+= iommu.o
 OBJS	+= net/uip/core.o
 OBJS	+= net/uip/arp.o
 OBJS	+= net/uip/icmp.o
diff --git a/include/kvm/iommu.h b/include/kvm/iommu.h
index 925e1993..4164ba20 100644
--- a/include/kvm/iommu.h
+++ b/include/kvm/iommu.h
@@ -61,4 +61,13 @@ static inline struct device_header *iommu_get_device(u32 device_id)
 	return device__find_dev(bus, dev_num);
 }
 
+void *iommu_alloc_address_space(struct device_header *dev);
+void iommu_free_address_space(void *address_space);
+
+int iommu_map(void *address_space, u64 virt_addr, u64 phys_addr, u64 size,
+	      int prot);
+int iommu_unmap(void *address_space, u64 virt_addr, u64 size, int flags);
+u64 iommu_access(void *address_space, u64 addr, size_t size, size_t *out_size,
+		 int prot);
+
 #endif /* KVM_IOMMU_H */
diff --git a/iommu.c b/iommu.c
new file mode 100644
index 00000000..0a662404
--- /dev/null
+++ b/iommu.c
@@ -0,0 +1,162 @@
+/*
+ * Implement basic IOMMU operations - map, unmap and translate
+ */
+#include <errno.h>
+
+#include "kvm/iommu.h"
+#include "kvm/kvm.h"
+#include "kvm/mutex.h"
+#include "kvm/rbtree-interval.h"
+
+struct iommu_mapping {
+	struct rb_int_node	iova_range;
+	u64			phys;
+	int			prot;
+};
+
+struct iommu_ioas {
+	struct rb_root		mappings;
+	struct mutex		mutex;
+};
+
+void *iommu_alloc_address_space(struct device_header *unused)
+{
+	struct iommu_ioas *ioas = calloc(1, sizeof(*ioas));
+
+	if (!ioas)
+		return NULL;
+
+	ioas->mappings = (struct rb_root)RB_ROOT;
+	mutex_init(&ioas->mutex);
+
+	return ioas;
+}
+
+void iommu_free_address_space(void *address_space)
+{
+	struct iommu_ioas *ioas = address_space;
+	struct rb_int_node *int_node;
+	struct rb_node *node, *next;
+	struct iommu_mapping *map;
+
+        /* Postorder allows to free leaves first. */
+	node = rb_first_postorder(&ioas->mappings);
+	while (node) {
+		next = rb_next_postorder(node);
+
+		int_node = rb_int(node);
+		map = container_of(int_node, struct iommu_mapping, iova_range);
+		free(map);
+
+		node = next;
+	}
+
+	free(ioas);
+}
+
+int iommu_map(void *address_space, u64 virt_addr, u64 phys_addr,
+	      u64 size, int prot)
+{
+	struct iommu_ioas *ioas = address_space;
+	struct iommu_mapping *map;
+
+	if (!ioas)
+		return -ENODEV;
+
+	map = malloc(sizeof(struct iommu_mapping));
+	if (!map)
+		return -ENOMEM;
+
+	map->phys = phys_addr;
+	map->iova_range = RB_INT_INIT(virt_addr, virt_addr + size - 1);
+	map->prot = prot;
+
+	mutex_lock(&ioas->mutex);
+	rb_int_insert(&ioas->mappings, &map->iova_range);
+	mutex_unlock(&ioas->mutex);
+
+	return 0;
+}
+
+int iommu_unmap(void *address_space, u64 virt_addr, u64 size, int flags)
+{
+	int ret = 0;
+	struct rb_int_node *node;
+	struct iommu_mapping *map;
+	struct iommu_ioas *ioas = address_space;
+
+	if (!ioas)
+		return -ENODEV;
+
+	mutex_lock(&ioas->mutex);
+	node = rb_int_search_single(&ioas->mappings, virt_addr);
+	while (node && size) {
+		struct rb_node *next = rb_next(&node->node);
+		size_t node_size = node->high - node->low + 1;
+		map = container_of(node, struct iommu_mapping, iova_range);
+
+		if (node_size > size) {
+			pr_debug("cannot split mapping");
+			ret = -EINVAL;
+			break;
+		}
+
+		size -= node_size;
+		virt_addr += node_size;
+
+		rb_erase(&node->node, &ioas->mappings);
+		free(map);
+		node = next ? container_of(next, struct rb_int_node, node) : NULL;
+	}
+
+	if (size && !ret) {
+		pr_debug("mapping not found");
+		ret = -ENXIO;
+	}
+	mutex_unlock(&ioas->mutex);
+
+	return ret;
+}
+
+/*
+ * Translate a virtual address into a physical one. Perform an access of @size
+ * bytes with protection @prot. If @addr isn't mapped in @address_space, return
+ * 0. If the permissions of the mapping don't match, return 0. If the access
+ * range specified by (addr, size) spans over multiple mappings, only access the
+ * first mapping and return the accessed size in @out_size. It is up to the
+ * caller to complete the access by calling the function again on the remaining
+ * range. Subsequent accesses are not guaranteed to succeed.
+ */
+u64 iommu_access(void *address_space, u64 addr, size_t size, size_t *out_size,
+		 int prot)
+{
+	struct iommu_ioas *ioas = address_space;
+	struct iommu_mapping *map;
+	struct rb_int_node *node;
+	u64 out_addr = 0;
+
+	mutex_lock(&ioas->mutex);
+	node = rb_int_search_single(&ioas->mappings, addr);
+	if (!node) {
+		pr_err("fault at IOVA %#llx %zu", addr, size);
+		errno = EFAULT;
+		goto out_unlock; /* Segv incomming */
+	}
+
+	map = container_of(node, struct iommu_mapping, iova_range);
+	if (prot & ~map->prot) {
+		pr_err("permission fault at IOVA %#llx", addr);
+		errno = EPERM;
+		goto out_unlock;
+	}
+
+	out_addr = map->phys + (addr - node->low);
+	*out_size = min_t(size_t, node->high - addr + 1, size);
+
+	pr_debug("access %llx %zu/%zu %x -> %#llx", addr, *out_size, size,
+		 prot, out_addr);
+out_unlock:
+	mutex_unlock(&ioas->mutex);
+
+	return out_addr;
+}
-- 
2.12.1

  parent reply	other threads:[~2017-04-07 19:24 UTC|newest]

Thread overview: 99+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-04-07 19:17 [RFC 0/3] virtio-iommu: a paravirtualized IOMMU Jean-Philippe Brucker
2017-04-07 19:17 ` [RFC 1/3] virtio-iommu: firmware description of the virtual topology Jean-Philippe Brucker
2017-04-07 19:17 ` [RFC 2/3] virtio-iommu: device probing and operations Jean-Philippe Brucker
2017-04-18 10:26   ` Tian, Kevin
2017-04-18 18:45     ` Jean-Philippe Brucker
2017-04-18 18:45     ` Jean-Philippe Brucker
2017-04-21  9:02       ` Tian, Kevin
2017-04-24 15:05         ` Jean-Philippe Brucker
     [not found]         ` <AADFC41AFE54684AB9EE6CBC0274A5D190CB262D-0J0gbvR4kThpB2pF5aRoyrfspsVTdybXVpNB7YpNyf8@public.gmane.org>
2017-04-24 15:05           ` Jean-Philippe Brucker
2017-08-21  7:59             ` Tian, Kevin
2017-08-21 12:00               ` Jean-Philippe Brucker
2017-08-21 12:00               ` Jean-Philippe Brucker
2017-08-21 12:00                 ` [virtio-dev] " Jean-Philippe Brucker
     [not found]                 ` <454095c4-cae5-ad52-a459-5c9e2cce4047-5wv7dgnIgG8@public.gmane.org>
2017-08-22  6:24                   ` Tian, Kevin
2017-08-22 14:19                     ` Jean-Philippe Brucker
2017-08-22 14:19                     ` Jean-Philippe Brucker
2017-08-22 14:19                       ` [virtio-dev] " Jean-Philippe Brucker
2017-08-23  2:23                       ` Tian, Kevin
2017-08-23  2:23                       ` Tian, Kevin
2017-08-23  2:23                         ` [virtio-dev] " Tian, Kevin
2017-08-22  6:24                 ` Tian, Kevin
2017-04-18 10:26   ` Tian, Kevin
2017-04-07 19:17 ` Jean-Philippe Brucker
2017-04-07 19:17 ` [RFC 3/3] virtio-iommu: future work Jean-Philippe Brucker
2017-04-21  8:31   ` Tian, Kevin
     [not found]   ` <20170407191747.26618-4-jean-philippe.brucker-5wv7dgnIgG8@public.gmane.org>
2017-04-21  8:31     ` Tian, Kevin
2017-04-24 15:05       ` Jean-Philippe Brucker
2017-04-24 15:05       ` Jean-Philippe Brucker
2017-04-26 16:24     ` Michael S. Tsirkin
2017-04-26 16:24   ` Michael S. Tsirkin
2017-04-07 19:17 ` Jean-Philippe Brucker
2017-04-07 19:23 ` [RFC PATCH linux] iommu: Add virtio-iommu driver Jean-Philippe Brucker
2017-06-16  8:48   ` [virtio-dev] " Bharat Bhushan
2017-06-16 11:36     ` Jean-Philippe Brucker
2017-06-16 11:36     ` Jean-Philippe Brucker
2017-06-16  8:48   ` Bharat Bhushan
2017-04-07 19:24 ` [RFC PATCH kvmtool 00/15] Add virtio-iommu Jean-Philippe Brucker
2017-04-07 19:24   ` [RFC PATCH kvmtool 01/15] virtio: synchronize virtio-iommu headers with Linux Jean-Philippe Brucker
2017-04-07 19:24   ` Jean-Philippe Brucker
2017-04-07 19:24   ` [RFC PATCH kvmtool 02/15] FDT: (re)introduce a dynamic phandle allocator Jean-Philippe Brucker
2017-04-07 19:24   ` Jean-Philippe Brucker
2017-04-07 19:24   ` [RFC PATCH kvmtool 03/15] virtio: add virtio-iommu Jean-Philippe Brucker
2017-04-07 19:24   ` Jean-Philippe Brucker
2017-04-07 19:24   ` Jean-Philippe Brucker [this message]
2017-04-07 19:24   ` [RFC PATCH kvmtool 04/15] Add a simple IOMMU Jean-Philippe Brucker
2017-04-07 19:24   ` [RFC PATCH kvmtool 05/15] iommu: describe IOMMU topology in device-trees Jean-Philippe Brucker
2017-04-07 19:24   ` Jean-Philippe Brucker
2017-04-07 19:24   ` [RFC PATCH kvmtool 06/15] irq: register MSI doorbell addresses Jean-Philippe Brucker
2017-04-07 19:24   ` Jean-Philippe Brucker
2017-04-07 19:24   ` [RFC PATCH kvmtool 07/15] virtio: factor virtqueue initialization Jean-Philippe Brucker
2017-04-07 19:24   ` Jean-Philippe Brucker
2017-04-07 19:24   ` [RFC PATCH kvmtool 08/15] virtio: add vIOMMU instance for virtio devices Jean-Philippe Brucker
2017-04-07 19:24   ` Jean-Philippe Brucker
2017-04-07 19:24   ` [RFC PATCH kvmtool 09/15] virtio: access vring and buffers through IOMMU mappings Jean-Philippe Brucker
2017-04-07 19:24   ` Jean-Philippe Brucker
2017-04-07 19:24   ` [RFC PATCH kvmtool 10/15] virtio-pci: translate MSIs with the virtual IOMMU Jean-Philippe Brucker
2017-04-07 19:24   ` Jean-Philippe Brucker
2017-04-07 19:24   ` [RFC PATCH kvmtool 11/15] virtio: set VIRTIO_F_IOMMU_PLATFORM when necessary Jean-Philippe Brucker
2017-04-07 19:24   ` Jean-Philippe Brucker
2017-04-07 19:24   ` [RFC PATCH kvmtool 12/15] vfio: add support for virtual IOMMU Jean-Philippe Brucker
2017-04-07 19:24   ` Jean-Philippe Brucker
2017-04-07 19:24   ` [RFC PATCH kvmtool 13/15] virtio-iommu: debug via IPC Jean-Philippe Brucker
2017-04-07 19:24   ` Jean-Philippe Brucker
2017-04-07 19:24   ` [RFC PATCH kvmtool 14/15] virtio-iommu: implement basic debug commands Jean-Philippe Brucker
2017-04-07 19:24   ` Jean-Philippe Brucker
2017-04-07 19:24   ` [RFC PATCH kvmtool 15/15] virtio: use virtio-iommu when available Jean-Philippe Brucker
2017-04-07 19:24   ` Jean-Philippe Brucker
2017-05-22  8:26   ` [RFC PATCH kvmtool 00/15] Add virtio-iommu Bharat Bhushan
     [not found]   ` <20170407192455.26814-1-jean-philippe.brucker-5wv7dgnIgG8@public.gmane.org>
2017-05-22  8:26     ` Bharat Bhushan
2017-05-22 14:01       ` Jean-Philippe Brucker
     [not found]       ` <AM5PR0401MB2545FADDF2A7649DF0DB68309AF80-oQ3wXcTHOqrg6d/1FbYcvI3W/0Ik+aLCnBOFsp37pqbUKgpGm//BTAC/G2K4zDHf@public.gmane.org>
2017-05-22 14:01         ` Jean-Philippe Brucker
2017-04-07 21:19 ` [RFC 0/3] virtio-iommu: a paravirtualized IOMMU Michael S. Tsirkin
2017-04-07 21:19 ` Michael S. Tsirkin
2017-04-10 18:39   ` [virtio-dev] " Jean-Philippe Brucker
2017-04-10 18:39   ` Jean-Philippe Brucker
2017-04-10 20:04     ` [virtio-dev] " Michael S. Tsirkin
2017-04-10 20:04     ` Michael S. Tsirkin
2017-04-10  2:30 ` Need information on type 2 IOMMU valmiki
2017-04-12  9:06 ` [RFC 0/3] virtio-iommu: a paravirtualized IOMMU Jason Wang
2017-04-13  8:16   ` Tian, Kevin
     [not found]   ` <a0920e37-a11e-784c-7d90-be6617ea7686-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
2017-04-13  8:16     ` Tian, Kevin
     [not found]       ` <AADFC41AFE54684AB9EE6CBC0274A5D190CA990E-0J0gbvR4kThpB2pF5aRoyrfspsVTdybXVpNB7YpNyf8@public.gmane.org>
2017-04-13 13:12         ` Jean-Philippe Brucker
2017-04-13 13:12       ` Jean-Philippe Brucker
2017-04-12  9:06 ` Jason Wang
2017-04-13  8:41 ` Tian, Kevin
     [not found] ` <20170407191747.26618-1-jean-philippe.brucker-5wv7dgnIgG8@public.gmane.org>
2017-04-07 19:17   ` [RFC 1/3] virtio-iommu: firmware description of the virtual topology Jean-Philippe Brucker
     [not found]     ` <20170407191747.26618-2-jean-philippe.brucker-5wv7dgnIgG8@public.gmane.org>
2017-04-18  9:51       ` Tian, Kevin
2017-04-18 18:41         ` Jean-Philippe Brucker
2017-04-21  8:43           ` Tian, Kevin
     [not found]             ` <AADFC41AFE54684AB9EE6CBC0274A5D190CB2570-0J0gbvR4kThpB2pF5aRoyrfspsVTdybXVpNB7YpNyf8@public.gmane.org>
2017-04-24 15:05               ` Jean-Philippe Brucker
2017-04-24 15:05             ` Jean-Philippe Brucker
2017-04-18 18:41         ` Jean-Philippe Brucker
2017-04-18  9:51     ` Tian, Kevin
2017-04-10  2:30   ` Need information on type 2 IOMMU valmiki
     [not found]     ` <1b48daab-c9e1-84d1-78a9-84d3e2001f32-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
2017-04-10  4:19       ` Alex Williamson
2017-04-10  4:19     ` Alex Williamson
2017-04-13  8:41   ` [RFC 0/3] virtio-iommu: a paravirtualized IOMMU Tian, Kevin
2017-04-13 13:12     ` Jean-Philippe Brucker
2017-04-13 13:12     ` Jean-Philippe Brucker

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=20170407192455.26814-5-jean-philippe.brucker@arm.com \
    --to=jean-philippe.brucker@arm.com \
    --cc=alex.williamson@redhat.com \
    --cc=cdall@linaro.org \
    --cc=iommu@lists.linux-foundation.org \
    --cc=jasowang@redhat.com \
    --cc=joro@8bytes.org \
    --cc=kvm@vger.kernel.org \
    --cc=lorenzo.pieralisi@arm.com \
    --cc=marc.zyngier@arm.com \
    --cc=mst@redhat.com \
    --cc=robin.murphy@arm.com \
    --cc=virtio-dev@lists.oasis-open.org \
    --cc=virtualization@lists.linux-foundation.org \
    --cc=will.deacon@arm.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.