summaryrefslogtreecommitdiffstats
path: root/hw/remote/iommu.c
diff options
context:
space:
mode:
authorRichard Henderson2022-06-15 18:47:24 +0200
committerRichard Henderson2022-06-15 18:47:24 +0200
commit9ac873a46963098441be920ef7a2eaf244a3352d (patch)
tree86bb7301ad0f534513a53984d0d3c17a1740f453 /hw/remote/iommu.c
parentMerge tag 'kraxel-20220614-pull-request' of git://git.kraxel.org/qemu into st... (diff)
parentlinux-aio: explain why max batch is checked in laio_io_unplug() (diff)
downloadqemu-9ac873a46963098441be920ef7a2eaf244a3352d.tar.gz
qemu-9ac873a46963098441be920ef7a2eaf244a3352d.tar.xz
qemu-9ac873a46963098441be920ef7a2eaf244a3352d.zip
Merge tag 'block-pull-request' of https://gitlab.com/stefanha/qemu into staging
Pull request This pull request includes an important aio=native I/O stall fix, the experimental vifo-user server, the io_uring_register_ring_fd() optimization for aio=io_uring, and an update to Vladimir Sementsov-Ogievskiy's maintainership details. # -----BEGIN PGP SIGNATURE----- # # iQEzBAABCAAdFiEEhpWov9P5fNqsNXdanKSrs4Grc8gFAmKp/+AACgkQnKSrs4Gr # c8gg9wf/ZG1+eGR2NA0T1szlhtgy2bnp95hrLbKzP7tVxueFq7QCcsIsLGWqfnMd # RREUi6Tgx1v7Agk2oIyUcrjn5rt4LPVOKolVbK6e5Pyou2/Sf/ApkhRjRnzzfACE # J56H8gPU7fS4/8sJYCYGlWEr7pMmJMVJFPl2tNsErPwuZMSjo27n6UqDE/ZSZF1p # w1a+cwo+6YSjtJg4AFB/+izBam4+U6w1YhgZM6p6hx5a7GLoq/w59W6Yb119GANO # tg5qzmSHtMKTieORJmYAt83T1xS5d/iyca4w1PiYQxJsHsqwAaPpoyEhgGT+u+CA # hfb3HDdQCFyVKwlKD5H1a+WD/Hr11w== # =zcl8 # -----END PGP SIGNATURE----- # gpg: Signature made Wed 15 Jun 2022 08:50:56 AM PDT # gpg: using RSA key 8695A8BFD3F97CDAAC35775A9CA4ABB381AB73C8 # gpg: Good signature from "Stefan Hajnoczi <stefanha@redhat.com>" [full] # gpg: aka "Stefan Hajnoczi <stefanha@gmail.com>" [full] * tag 'block-pull-request' of https://gitlab.com/stefanha/qemu: linux-aio: explain why max batch is checked in laio_io_unplug() linux-aio: fix unbalanced plugged counter in laio_io_unplug() vfio-user: handle reset of remote device vfio-user: handle device interrupts vfio-user: handle PCI BAR accesses vfio-user: handle DMA mappings vfio-user: IOMMU support for remote device vfio-user: handle PCI config space accesses vfio-user: run vfio-user context vfio-user: find and init PCI device vfio-user: instantiate vfio-user context vfio-user: define vfio-user-server object vfio-user: build library remote/machine: add vfio-user property remote/machine: add HotplugHandler for remote machine qdev: unplug blocker for devices Use io_uring_register_ring_fd() to skip fd operations MAINTAINERS: update Vladimir's address and repositories Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Diffstat (limited to 'hw/remote/iommu.c')
-rw-r--r--hw/remote/iommu.c131
1 files changed, 131 insertions, 0 deletions
diff --git a/hw/remote/iommu.c b/hw/remote/iommu.c
new file mode 100644
index 0000000000..fd723d91f3
--- /dev/null
+++ b/hw/remote/iommu.c
@@ -0,0 +1,131 @@
+/**
+ * IOMMU for remote device
+ *
+ * Copyright © 2022 Oracle and/or its affiliates.
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ *
+ */
+
+#include "qemu/osdep.h"
+
+#include "hw/remote/iommu.h"
+#include "hw/pci/pci_bus.h"
+#include "hw/pci/pci.h"
+#include "exec/memory.h"
+#include "exec/address-spaces.h"
+#include "trace.h"
+
+/**
+ * IOMMU for TYPE_REMOTE_MACHINE - manages DMA address space isolation
+ * for remote machine. It is used by TYPE_VFIO_USER_SERVER.
+ *
+ * - Each TYPE_VFIO_USER_SERVER instance handles one PCIDevice on a PCIBus.
+ * There is one RemoteIommu per PCIBus, so the RemoteIommu tracks multiple
+ * PCIDevices by maintaining a ->elem_by_devfn mapping.
+ *
+ * - memory_region_init_iommu() is not used because vfio-user MemoryRegions
+ * will be added to the elem->mr container instead. This is more natural
+ * than implementing the IOMMUMemoryRegionClass APIs since vfio-user
+ * provides something that is close to a full-fledged MemoryRegion and
+ * not like an IOMMU mapping.
+ *
+ * - When a device is hot unplugged, the elem->mr reference is dropped so
+ * all vfio-user MemoryRegions associated with this vfio-user server are
+ * destroyed.
+ */
+
+static AddressSpace *remote_iommu_find_add_as(PCIBus *pci_bus,
+ void *opaque, int devfn)
+{
+ RemoteIommu *iommu = opaque;
+ RemoteIommuElem *elem = NULL;
+
+ qemu_mutex_lock(&iommu->lock);
+
+ elem = g_hash_table_lookup(iommu->elem_by_devfn, INT2VOIDP(devfn));
+
+ if (!elem) {
+ elem = g_malloc0(sizeof(RemoteIommuElem));
+ g_hash_table_insert(iommu->elem_by_devfn, INT2VOIDP(devfn), elem);
+ }
+
+ if (!elem->mr) {
+ elem->mr = MEMORY_REGION(object_new(TYPE_MEMORY_REGION));
+ memory_region_set_size(elem->mr, UINT64_MAX);
+ address_space_init(&elem->as, elem->mr, NULL);
+ }
+
+ qemu_mutex_unlock(&iommu->lock);
+
+ return &elem->as;
+}
+
+void remote_iommu_unplug_dev(PCIDevice *pci_dev)
+{
+ AddressSpace *as = pci_device_iommu_address_space(pci_dev);
+ RemoteIommuElem *elem = NULL;
+
+ if (as == &address_space_memory) {
+ return;
+ }
+
+ elem = container_of(as, RemoteIommuElem, as);
+
+ address_space_destroy(&elem->as);
+
+ object_unref(elem->mr);
+
+ elem->mr = NULL;
+}
+
+static void remote_iommu_init(Object *obj)
+{
+ RemoteIommu *iommu = REMOTE_IOMMU(obj);
+
+ iommu->elem_by_devfn = g_hash_table_new_full(NULL, NULL, NULL, g_free);
+
+ qemu_mutex_init(&iommu->lock);
+}
+
+static void remote_iommu_finalize(Object *obj)
+{
+ RemoteIommu *iommu = REMOTE_IOMMU(obj);
+
+ qemu_mutex_destroy(&iommu->lock);
+
+ g_hash_table_destroy(iommu->elem_by_devfn);
+
+ iommu->elem_by_devfn = NULL;
+}
+
+void remote_iommu_setup(PCIBus *pci_bus)
+{
+ RemoteIommu *iommu = NULL;
+
+ g_assert(pci_bus);
+
+ iommu = REMOTE_IOMMU(object_new(TYPE_REMOTE_IOMMU));
+
+ pci_setup_iommu(pci_bus, remote_iommu_find_add_as, iommu);
+
+ object_property_add_child(OBJECT(pci_bus), "remote-iommu", OBJECT(iommu));
+
+ object_unref(OBJECT(iommu));
+}
+
+static const TypeInfo remote_iommu_info = {
+ .name = TYPE_REMOTE_IOMMU,
+ .parent = TYPE_OBJECT,
+ .instance_size = sizeof(RemoteIommu),
+ .instance_init = remote_iommu_init,
+ .instance_finalize = remote_iommu_finalize,
+};
+
+static void remote_iommu_register_types(void)
+{
+ type_register_static(&remote_iommu_info);
+}
+
+type_init(remote_iommu_register_types)