{"id":815322,"url":"http://patchwork.ozlabs.org/api/patches/815322/?format=json","web_url":"http://patchwork.ozlabs.org/project/qemu-devel/patch/1505807208-9063-4-git-send-email-eric.auger@redhat.com/","project":{"id":14,"url":"http://patchwork.ozlabs.org/api/projects/14/?format=json","name":"QEMU Development","link_name":"qemu-devel","list_id":"qemu-devel.nongnu.org","list_email":"qemu-devel@nongnu.org","web_url":"","scm_url":"","webscm_url":"","list_archive_url":"","list_archive_url_format":"","commit_url_format":""},"msgid":"<1505807208-9063-4-git-send-email-eric.auger@redhat.com>","list_archive_url":null,"date":"2017-09-19T07:46:35","name":"[RFC,v4,03/16] virtio-iommu: add skeleton","commit_ref":null,"pull_url":null,"state":"new","archived":false,"hash":"182553556f1892c46b7a6ec599b079ab822e632c","submitter":{"id":69187,"url":"http://patchwork.ozlabs.org/api/people/69187/?format=json","name":"Eric Auger","email":"eric.auger@redhat.com"},"delegate":null,"mbox":"http://patchwork.ozlabs.org/project/qemu-devel/patch/1505807208-9063-4-git-send-email-eric.auger@redhat.com/mbox/","series":[{"id":3796,"url":"http://patchwork.ozlabs.org/api/series/3796/?format=json","web_url":"http://patchwork.ozlabs.org/project/qemu-devel/list/?series=3796","date":"2017-09-19T07:46:32","name":"VIRTIO-IOMMU device","version":4,"mbox":"http://patchwork.ozlabs.org/series/3796/mbox/"}],"comments":"http://patchwork.ozlabs.org/api/patches/815322/comments/","check":"pending","checks":"http://patchwork.ozlabs.org/api/patches/815322/checks/","tags":{},"related":[],"headers":{"Return-Path":"<qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org>","X-Original-To":"incoming@patchwork.ozlabs.org","Delivered-To":"patchwork-incoming@bilbo.ozlabs.org","Authentication-Results":["ozlabs.org;\n\tspf=pass (mailfrom) smtp.mailfrom=nongnu.org\n\t(client-ip=2001:4830:134:3::11; helo=lists.gnu.org;\n\tenvelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org;\n\treceiver=<UNKNOWN>)","ext-mx09.extmail.prod.ext.phx2.redhat.com;\n\tdmarc=none (p=none dis=none) header.from=redhat.com","ext-mx09.extmail.prod.ext.phx2.redhat.com;\n\tspf=fail smtp.mailfrom=eric.auger@redhat.com"],"Received":["from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11])\n\t(using TLSv1 with cipher AES256-SHA (256/256 bits))\n\t(No client certificate requested)\n\tby ozlabs.org (Postfix) with ESMTPS id 3xxFT93pg3z9s82\n\tfor <incoming@patchwork.ozlabs.org>;\n\tTue, 19 Sep 2017 17:52:13 +1000 (AEST)","from localhost ([::1]:40611 helo=lists.gnu.org)\n\tby lists.gnu.org with esmtp (Exim 4.71) (envelope-from\n\t<qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org>)\n\tid 1duDKF-0002WS-Io\n\tfor incoming@patchwork.ozlabs.org; Tue, 19 Sep 2017 03:52:11 -0400","from eggs.gnu.org ([2001:4830:134:3::10]:47170)\n\tby lists.gnu.org with esmtp (Exim 4.71)\n\t(envelope-from <eric.auger@redhat.com>) id 1duDFz-0007xx-TN\n\tfor qemu-devel@nongnu.org; Tue, 19 Sep 2017 03:47:52 -0400","from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71)\n\t(envelope-from <eric.auger@redhat.com>) id 1duDFx-0000di-Ta\n\tfor qemu-devel@nongnu.org; Tue, 19 Sep 2017 03:47:47 -0400","from mx1.redhat.com ([209.132.183.28]:45088)\n\tby eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32)\n\t(Exim 4.71) (envelope-from <eric.auger@redhat.com>)\n\tid 1duDFt-0000bD-Lb; Tue, 19 Sep 2017 03:47:41 -0400","from smtp.corp.redhat.com\n\t(int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11])\n\t(using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits))\n\t(No client certificate requested)\n\tby mx1.redhat.com (Postfix) with ESMTPS id 765784A702;\n\tTue, 19 Sep 2017 07:47:40 +0000 (UTC)","from localhost.localdomain.com (ovpn-116-197.ams2.redhat.com\n\t[10.36.116.197])\n\tby smtp.corp.redhat.com (Postfix) with ESMTP id 77C0161342;\n\tTue, 19 Sep 2017 07:47:34 +0000 (UTC)"],"DMARC-Filter":"OpenDMARC Filter v1.3.2 mx1.redhat.com 765784A702","From":"Eric Auger <eric.auger@redhat.com>","To":"eric.auger.pro@gmail.com, eric.auger@redhat.com, peter.maydell@linaro.org,\n\talex.williamson@redhat.com, mst@redhat.com, qemu-arm@nongnu.org,\n\tqemu-devel@nongnu.org, jean-philippe.brucker@arm.com","Date":"Tue, 19 Sep 2017 09:46:35 +0200","Message-Id":"<1505807208-9063-4-git-send-email-eric.auger@redhat.com>","In-Reply-To":"<1505807208-9063-1-git-send-email-eric.auger@redhat.com>","References":"<1505807208-9063-1-git-send-email-eric.auger@redhat.com>","X-Scanned-By":"MIMEDefang 2.79 on 10.5.11.11","X-Greylist":"Sender IP whitelisted, not delayed by milter-greylist-4.5.16\n\t(mx1.redhat.com [10.5.110.38]);\n\tTue, 19 Sep 2017 07:47:40 +0000 (UTC)","X-detected-operating-system":"by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic]\n\t[fuzzy]","X-Received-From":"209.132.183.28","Subject":"[Qemu-devel] [RFC v4 03/16] virtio-iommu: add skeleton","X-BeenThere":"qemu-devel@nongnu.org","X-Mailman-Version":"2.1.21","Precedence":"list","List-Id":"<qemu-devel.nongnu.org>","List-Unsubscribe":"<https://lists.nongnu.org/mailman/options/qemu-devel>,\n\t<mailto:qemu-devel-request@nongnu.org?subject=unsubscribe>","List-Archive":"<http://lists.nongnu.org/archive/html/qemu-devel/>","List-Post":"<mailto:qemu-devel@nongnu.org>","List-Help":"<mailto:qemu-devel-request@nongnu.org?subject=help>","List-Subscribe":"<https://lists.nongnu.org/mailman/listinfo/qemu-devel>,\n\t<mailto:qemu-devel-request@nongnu.org?subject=subscribe>","Cc":"wei@redhat.com, kevin.tian@intel.com, marc.zyngier@arm.com,\n\ttn@semihalf.com, \n\twill.deacon@arm.com, drjones@redhat.com, peterx@redhat.com,\n\tlinuc.decode@gmail.com, bharat.bhushan@nxp.com,\n\tchristoffer.dall@linaro.org","Errors-To":"qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org","Sender":"\"Qemu-devel\"\n\t<qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org>"},"content":"This patchs adds the skeleton for the virtio-iommu device.\n\nSigned-off-by: Eric Auger <eric.auger@redhat.com>\n\n---\n\nv3 -> v4:\n- use page_size_mask instead of page_sizes\n- added set_features()\n- added some traces (reset, set_status, set_features)\n- empty virtio_iommu_set_config() as the driver MUST NOT\n  write to device configuration fields\n- add get_config trace\n\nv2 -> v3:\n- rebase on 2.10-rc0, ie. use IOMMUMemoryRegion and remove\n  iommu_ops.\n- advertise VIRTIO_IOMMU_F_MAP_UNMAP feature\n- page_sizes set to TARGET_PAGE_SIZE\n---\n hw/virtio/Makefile.objs          |   1 +\n hw/virtio/trace-events           |   7 ++\n hw/virtio/virtio-iommu.c         | 255 +++++++++++++++++++++++++++++++++++++++\n include/hw/virtio/virtio-iommu.h |  59 +++++++++\n 4 files changed, 322 insertions(+)\n create mode 100644 hw/virtio/virtio-iommu.c\n create mode 100644 include/hw/virtio/virtio-iommu.h","diff":"diff --git a/hw/virtio/Makefile.objs b/hw/virtio/Makefile.objs\nindex 765d363..8967a4a 100644\n--- a/hw/virtio/Makefile.objs\n+++ b/hw/virtio/Makefile.objs\n@@ -6,6 +6,7 @@ common-obj-y += virtio-mmio.o\n \n obj-y += virtio.o virtio-balloon.o \n obj-$(CONFIG_LINUX) += vhost.o vhost-backend.o vhost-user.o\n+obj-$(CONFIG_LINUX) += virtio-iommu.o\n obj-$(CONFIG_VHOST_VSOCK) += vhost-vsock.o\n obj-y += virtio-crypto.o\n obj-$(CONFIG_VIRTIO_PCI) += virtio-crypto-pci.o\ndiff --git a/hw/virtio/trace-events b/hw/virtio/trace-events\nindex 775461a..98cf9a1 100644\n--- a/hw/virtio/trace-events\n+++ b/hw/virtio/trace-events\n@@ -25,3 +25,10 @@ virtio_balloon_handle_output(const char *name, uint64_t gpa) \"section name: %s g\n virtio_balloon_get_config(uint32_t num_pages, uint32_t actual) \"num_pages: %d actual: %d\"\n virtio_balloon_set_config(uint32_t actual, uint32_t oldactual) \"actual: %d oldactual: %d\"\n virtio_balloon_to_target(uint64_t target, uint32_t num_pages) \"balloon target: 0x%\"PRIx64\" num_pages: %d\"\n+\n+# hw/virtio/virtio-iommu.c\n+#\n+virtio_iommu_set_features(uint64_t features) \"features accepted by the driver =0x%\"PRIx64\n+virtio_iommu_device_reset(void) \"reset!\"\n+virtio_iommu_device_status(uint8_t status) \"driver status = %d\"\n+virtio_iommu_get_config(uint64_t page_size_mask, uint64_t start, uint64_t end, uint8_t ioasid_bits, uint32_t probe_size) \"page_size_mask=0x%\"PRIx64\" start=0x%\"PRIx64\" end=0x%\"PRIx64\" ioasid_bits=%d probe_size=0x%x\"\ndiff --git a/hw/virtio/virtio-iommu.c b/hw/virtio/virtio-iommu.c\nnew file mode 100644\nindex 0000000..36e5b5f\n--- /dev/null\n+++ b/hw/virtio/virtio-iommu.c\n@@ -0,0 +1,255 @@\n+/*\n+ * virtio-iommu device\n+ *\n+ * Copyright (c) 2017 Red Hat, Inc.\n+ *\n+ * This program is free software; you can redistribute it and/or modify it\n+ * under the terms and conditions of the GNU General Public License,\n+ * version 2 or later, as published by the Free Software Foundation.\n+ *\n+ * This program is distributed in the hope it will be useful, but WITHOUT\n+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or\n+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for\n+ * more details.\n+ *\n+ * You should have received a copy of the GNU General Public License along with\n+ * this program.  If not, see <http://www.gnu.org/licenses/>.\n+ *\n+ */\n+\n+#include \"qemu/osdep.h\"\n+#include \"qemu/iov.h\"\n+#include \"qemu-common.h\"\n+#include \"hw/virtio/virtio.h\"\n+#include \"sysemu/kvm.h\"\n+#include \"qapi-event.h\"\n+#include \"trace.h\"\n+\n+#include \"standard-headers/linux/virtio_ids.h\"\n+#include <linux/virtio_iommu.h>\n+\n+#include \"hw/virtio/virtio-bus.h\"\n+#include \"hw/virtio/virtio-access.h\"\n+#include \"hw/virtio/virtio-iommu.h\"\n+\n+/* Max size */\n+#define VIOMMU_DEFAULT_QUEUE_SIZE 256\n+\n+static int virtio_iommu_handle_attach(VirtIOIOMMU *s,\n+                                      struct iovec *iov,\n+                                      unsigned int iov_cnt)\n+{\n+    return -ENOENT;\n+}\n+static int virtio_iommu_handle_detach(VirtIOIOMMU *s,\n+                                      struct iovec *iov,\n+                                      unsigned int iov_cnt)\n+{\n+    return -ENOENT;\n+}\n+static int virtio_iommu_handle_map(VirtIOIOMMU *s,\n+                                   struct iovec *iov,\n+                                   unsigned int iov_cnt)\n+{\n+    return -ENOENT;\n+}\n+static int virtio_iommu_handle_unmap(VirtIOIOMMU *s,\n+                                     struct iovec *iov,\n+                                     unsigned int iov_cnt)\n+{\n+    return -ENOENT;\n+}\n+\n+static void virtio_iommu_handle_command(VirtIODevice *vdev, VirtQueue *vq)\n+{\n+    VirtIOIOMMU *s = VIRTIO_IOMMU(vdev);\n+    VirtQueueElement *elem;\n+    struct virtio_iommu_req_head head;\n+    struct virtio_iommu_req_tail tail;\n+    unsigned int iov_cnt;\n+    struct iovec *iov;\n+    size_t sz;\n+\n+    for (;;) {\n+        elem = virtqueue_pop(vq, sizeof(VirtQueueElement));\n+        if (!elem) {\n+            return;\n+        }\n+\n+        if (iov_size(elem->in_sg, elem->in_num) < sizeof(tail) ||\n+            iov_size(elem->out_sg, elem->out_num) < sizeof(head)) {\n+            virtio_error(vdev, \"virtio-iommu erroneous head or tail\");\n+            virtqueue_detach_element(vq, elem, 0);\n+            g_free(elem);\n+            break;\n+        }\n+\n+        iov_cnt = elem->out_num;\n+        iov = g_memdup(elem->out_sg, sizeof(struct iovec) * elem->out_num);\n+        sz = iov_to_buf(iov, iov_cnt, 0, &head, sizeof(head));\n+        if (sz != sizeof(head)) {\n+            tail.status = VIRTIO_IOMMU_S_UNSUPP;\n+        }\n+        qemu_mutex_lock(&s->mutex);\n+        switch (head.type) {\n+        case VIRTIO_IOMMU_T_ATTACH:\n+            tail.status = virtio_iommu_handle_attach(s, iov, iov_cnt);\n+            break;\n+        case VIRTIO_IOMMU_T_DETACH:\n+            tail.status = virtio_iommu_handle_detach(s, iov, iov_cnt);\n+            break;\n+        case VIRTIO_IOMMU_T_MAP:\n+            tail.status = virtio_iommu_handle_map(s, iov, iov_cnt);\n+            break;\n+        case VIRTIO_IOMMU_T_UNMAP:\n+            tail.status = virtio_iommu_handle_unmap(s, iov, iov_cnt);\n+            break;\n+        default:\n+            tail.status = VIRTIO_IOMMU_S_UNSUPP;\n+        }\n+        qemu_mutex_unlock(&s->mutex);\n+\n+        sz = iov_from_buf(elem->in_sg, elem->in_num, 0,\n+                          &tail, sizeof(tail));\n+        assert(sz == sizeof(tail));\n+\n+        virtqueue_push(vq, elem, sizeof(tail));\n+        virtio_notify(vdev, vq);\n+        g_free(elem);\n+    }\n+}\n+\n+static void virtio_iommu_get_config(VirtIODevice *vdev, uint8_t *config_data)\n+{\n+    VirtIOIOMMU *dev = VIRTIO_IOMMU(vdev);\n+    struct virtio_iommu_config *config = &dev->config;\n+\n+    trace_virtio_iommu_get_config(config->page_size_mask,\n+                                  config->input_range.start,\n+                                  config->input_range.end,\n+                                  config->ioasid_bits,\n+                                  config->probe_size);\n+    memcpy(config_data, &dev->config, sizeof(struct virtio_iommu_config));\n+}\n+\n+static void virtio_iommu_set_config(VirtIODevice *vdev,\n+                                      const uint8_t *config_data)\n+{\n+}\n+\n+static uint64_t virtio_iommu_get_features(VirtIODevice *vdev, uint64_t f,\n+                                            Error **errp)\n+{\n+    VirtIOIOMMU *dev = VIRTIO_IOMMU(vdev);\n+    f |= dev->host_features;\n+    virtio_add_feature(&f, VIRTIO_RING_F_EVENT_IDX);\n+    virtio_add_feature(&f, VIRTIO_RING_F_INDIRECT_DESC);\n+    virtio_add_feature(&f, VIRTIO_IOMMU_F_INPUT_RANGE);\n+    virtio_add_feature(&f, VIRTIO_IOMMU_F_MAP_UNMAP);\n+    return f;\n+}\n+\n+static void virtio_iommu_set_features(VirtIODevice *vdev, uint64_t val)\n+{\n+    trace_virtio_iommu_set_features(val);\n+}\n+\n+static int virtio_iommu_post_load_device(void *opaque, int version_id)\n+{\n+    return 0;\n+}\n+\n+static const VMStateDescription vmstate_virtio_iommu_device = {\n+    .name = \"virtio-iommu-device\",\n+    .version_id = 1,\n+    .minimum_version_id = 1,\n+    .post_load = virtio_iommu_post_load_device,\n+    .fields = (VMStateField[]) {\n+        VMSTATE_END_OF_LIST()\n+    },\n+};\n+\n+static void virtio_iommu_device_realize(DeviceState *dev, Error **errp)\n+{\n+    VirtIODevice *vdev = VIRTIO_DEVICE(dev);\n+    VirtIOIOMMU *s = VIRTIO_IOMMU(dev);\n+\n+    virtio_init(vdev, \"virtio-iommu\", VIRTIO_ID_IOMMU,\n+                sizeof(struct virtio_iommu_config));\n+\n+    s->vq = virtio_add_queue(vdev, VIOMMU_DEFAULT_QUEUE_SIZE,\n+                             virtio_iommu_handle_command);\n+\n+    s->config.page_size_mask = TARGET_PAGE_MASK;\n+    s->config.input_range.end = -1UL;\n+}\n+\n+static void virtio_iommu_device_unrealize(DeviceState *dev, Error **errp)\n+{\n+    VirtIODevice *vdev = VIRTIO_DEVICE(dev);\n+\n+    virtio_cleanup(vdev);\n+}\n+\n+static void virtio_iommu_device_reset(VirtIODevice *vdev)\n+{\n+    trace_virtio_iommu_device_reset();\n+}\n+\n+static void virtio_iommu_set_status(VirtIODevice *vdev, uint8_t status)\n+{\n+    trace_virtio_iommu_device_status(status);\n+}\n+\n+static void virtio_iommu_instance_init(Object *obj)\n+{\n+}\n+\n+static const VMStateDescription vmstate_virtio_iommu = {\n+    .name = \"virtio-iommu\",\n+    .minimum_version_id = 1,\n+    .version_id = 1,\n+    .fields = (VMStateField[]) {\n+        VMSTATE_VIRTIO_DEVICE,\n+        VMSTATE_END_OF_LIST()\n+    },\n+};\n+\n+static Property virtio_iommu_properties[] = {\n+    DEFINE_PROP_END_OF_LIST(),\n+};\n+\n+static void virtio_iommu_class_init(ObjectClass *klass, void *data)\n+{\n+    DeviceClass *dc = DEVICE_CLASS(klass);\n+    VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(klass);\n+\n+    dc->props = virtio_iommu_properties;\n+    dc->vmsd = &vmstate_virtio_iommu;\n+\n+    set_bit(DEVICE_CATEGORY_MISC, dc->categories);\n+    vdc->realize = virtio_iommu_device_realize;\n+    vdc->unrealize = virtio_iommu_device_unrealize;\n+    vdc->reset = virtio_iommu_device_reset;\n+    vdc->get_config = virtio_iommu_get_config;\n+    vdc->set_config = virtio_iommu_set_config;\n+    vdc->get_features = virtio_iommu_get_features;\n+    vdc->set_features = virtio_iommu_set_features;\n+    vdc->set_status = virtio_iommu_set_status;\n+    vdc->vmsd = &vmstate_virtio_iommu_device;\n+}\n+\n+static const TypeInfo virtio_iommu_info = {\n+    .name = TYPE_VIRTIO_IOMMU,\n+    .parent = TYPE_VIRTIO_DEVICE,\n+    .instance_size = sizeof(VirtIOIOMMU),\n+    .instance_init = virtio_iommu_instance_init,\n+    .class_init = virtio_iommu_class_init,\n+};\n+\n+static void virtio_register_types(void)\n+{\n+    type_register_static(&virtio_iommu_info);\n+}\n+\n+type_init(virtio_register_types)\ndiff --git a/include/hw/virtio/virtio-iommu.h b/include/hw/virtio/virtio-iommu.h\nnew file mode 100644\nindex 0000000..6716cdb\n--- /dev/null\n+++ b/include/hw/virtio/virtio-iommu.h\n@@ -0,0 +1,59 @@\n+/*\n+ * virtio-iommu device\n+ *\n+ * Copyright (c) 2017 Red Hat, Inc.\n+ *\n+ * This program is free software; you can redistribute it and/or modify it\n+ * under the terms and conditions of the GNU General Public License,\n+ * version 2 or later, as published by the Free Software Foundation.\n+ *\n+ * This program is distributed in the hope it will be useful, but WITHOUT\n+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or\n+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for\n+ * more details.\n+ *\n+ * You should have received a copy of the GNU General Public License along with\n+ * this program.  If not, see <http://www.gnu.org/licenses/>.\n+ *\n+ */\n+\n+#ifndef QEMU_VIRTIO_IOMMU_H\n+#define QEMU_VIRTIO_IOMMU_H\n+\n+#include \"standard-headers/linux/virtio_iommu.h\"\n+#include \"hw/virtio/virtio.h\"\n+#include \"hw/pci/pci.h\"\n+\n+#define TYPE_VIRTIO_IOMMU \"virtio-iommu-device\"\n+#define VIRTIO_IOMMU(obj) \\\n+        OBJECT_CHECK(VirtIOIOMMU, (obj), TYPE_VIRTIO_IOMMU)\n+\n+#define IOMMU_PCI_BUS_MAX      256\n+#define IOMMU_PCI_DEVFN_MAX    256\n+\n+typedef struct IOMMUDevice {\n+    void         *viommu;\n+    PCIBus       *bus;\n+    int           devfn;\n+    IOMMUMemoryRegion  iommu_mr;\n+    AddressSpace  as;\n+} IOMMUDevice;\n+\n+typedef struct IOMMUPciBus {\n+    PCIBus       *bus;\n+    IOMMUDevice  *pbdev[0]; /* Parent array is sparse, so dynamically alloc */\n+} IOMMUPciBus;\n+\n+typedef struct VirtIOIOMMU {\n+    VirtIODevice parent_obj;\n+    VirtQueue *vq;\n+    struct virtio_iommu_config config;\n+    uint32_t host_features;\n+    GHashTable *as_by_busptr;\n+    IOMMUPciBus *as_by_bus_num[IOMMU_PCI_BUS_MAX];\n+    GTree *address_spaces;\n+    QemuMutex mutex;\n+    GTree *devices;\n+} VirtIOIOMMU;\n+\n+#endif\n","prefixes":["RFC","v4","03/16"]}