[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PULL 16/42] intel_iommu: Implement [set|unset]_iommu_device() callbacks
From: |
Cédric Le Goater |
Subject: |
[PULL 16/42] intel_iommu: Implement [set|unset]_iommu_device() callbacks |
Date: |
Mon, 24 Jun 2024 23:24:30 +0200 |
From: Yi Liu <yi.l.liu@intel.com>
Implement [set|unset]_iommu_device() callbacks in Intel vIOMMU.
In set call, we take a reference of HostIOMMUDevice and store it
in hash table indexed by PCI BDF.
Note this BDF index is device's real BDF not the aliased one which
is different from the index of VTDAddressSpace. There can be multiple
assigned devices under same virtual iommu group and share same
VTDAddressSpace, but each has its own HostIOMMUDevice.
Signed-off-by: Yi Liu <yi.l.liu@intel.com>
Signed-off-by: Yi Sun <yi.y.sun@linux.intel.com>
Signed-off-by: Zhenzhong Duan <zhenzhong.duan@intel.com>
Reviewed-by: Eric Auger <eric.auger@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
---
include/hw/i386/intel_iommu.h | 2 +
hw/i386/intel_iommu.c | 81 +++++++++++++++++++++++++++++++++++
2 files changed, 83 insertions(+)
diff --git a/include/hw/i386/intel_iommu.h b/include/hw/i386/intel_iommu.h
index
7fa0a695c87bb8569fd6985e299fc0a1cc4b0c0c..1eb05c29fc9c703a61f06d90616694e74fb61c15
100644
--- a/include/hw/i386/intel_iommu.h
+++ b/include/hw/i386/intel_iommu.h
@@ -292,6 +292,8 @@ struct IntelIOMMUState {
/* list of registered notifiers */
QLIST_HEAD(, VTDAddressSpace) vtd_as_with_notifiers;
+ GHashTable *vtd_host_iommu_dev; /* HostIOMMUDevice */
+
/* interrupt remapping */
bool intr_enabled; /* Whether guest enabled IR */
dma_addr_t intr_root; /* Interrupt remapping table pointer */
diff --git a/hw/i386/intel_iommu.c b/hw/i386/intel_iommu.c
index
c69c0d285b1fa85da22440934178243942fe42ab..019d1c9c800cde1d84f50e29eac02bea0e3329f3
100644
--- a/hw/i386/intel_iommu.c
+++ b/hw/i386/intel_iommu.c
@@ -61,6 +61,12 @@ struct vtd_as_key {
uint32_t pasid;
};
+/* bus/devfn is PCI device's real BDF not the aliased one */
+struct vtd_hiod_key {
+ PCIBus *bus;
+ uint8_t devfn;
+};
+
struct vtd_iotlb_key {
uint64_t gfn;
uint32_t pasid;
@@ -250,6 +256,25 @@ static guint vtd_as_hash(gconstpointer v)
return (guint)(value << 8 | key->devfn);
}
+/* Same implementation as vtd_as_hash() */
+static guint vtd_hiod_hash(gconstpointer v)
+{
+ return vtd_as_hash(v);
+}
+
+static gboolean vtd_hiod_equal(gconstpointer v1, gconstpointer v2)
+{
+ const struct vtd_hiod_key *key1 = v1;
+ const struct vtd_hiod_key *key2 = v2;
+
+ return (key1->bus == key2->bus) && (key1->devfn == key2->devfn);
+}
+
+static void vtd_hiod_destroy(gpointer v)
+{
+ object_unref(v);
+}
+
static gboolean vtd_hash_remove_by_domain(gpointer key, gpointer value,
gpointer user_data)
{
@@ -3812,6 +3837,58 @@ VTDAddressSpace *vtd_find_add_as(IntelIOMMUState *s,
PCIBus *bus,
return vtd_dev_as;
}
+static bool vtd_dev_set_iommu_device(PCIBus *bus, void *opaque, int devfn,
+ HostIOMMUDevice *hiod, Error **errp)
+{
+ IntelIOMMUState *s = opaque;
+ struct vtd_as_key key = {
+ .bus = bus,
+ .devfn = devfn,
+ };
+ struct vtd_as_key *new_key;
+
+ assert(hiod);
+
+ vtd_iommu_lock(s);
+
+ if (g_hash_table_lookup(s->vtd_host_iommu_dev, &key)) {
+ error_setg(errp, "Host IOMMU device already exist");
+ vtd_iommu_unlock(s);
+ return false;
+ }
+
+ new_key = g_malloc(sizeof(*new_key));
+ new_key->bus = bus;
+ new_key->devfn = devfn;
+
+ object_ref(hiod);
+ g_hash_table_insert(s->vtd_host_iommu_dev, new_key, hiod);
+
+ vtd_iommu_unlock(s);
+
+ return true;
+}
+
+static void vtd_dev_unset_iommu_device(PCIBus *bus, void *opaque, int devfn)
+{
+ IntelIOMMUState *s = opaque;
+ struct vtd_as_key key = {
+ .bus = bus,
+ .devfn = devfn,
+ };
+
+ vtd_iommu_lock(s);
+
+ if (!g_hash_table_lookup(s->vtd_host_iommu_dev, &key)) {
+ vtd_iommu_unlock(s);
+ return;
+ }
+
+ g_hash_table_remove(s->vtd_host_iommu_dev, &key);
+
+ vtd_iommu_unlock(s);
+}
+
/* Unmap the whole range in the notifier's scope. */
static void vtd_address_space_unmap(VTDAddressSpace *as, IOMMUNotifier *n)
{
@@ -4116,6 +4193,8 @@ static AddressSpace *vtd_host_dma_iommu(PCIBus *bus, void
*opaque, int devfn)
static PCIIOMMUOps vtd_iommu_ops = {
.get_address_space = vtd_host_dma_iommu,
+ .set_iommu_device = vtd_dev_set_iommu_device,
+ .unset_iommu_device = vtd_dev_unset_iommu_device,
};
static bool vtd_decide_config(IntelIOMMUState *s, Error **errp)
@@ -4235,6 +4314,8 @@ static void vtd_realize(DeviceState *dev, Error **errp)
g_free, g_free);
s->vtd_address_spaces = g_hash_table_new_full(vtd_as_hash, vtd_as_equal,
g_free, g_free);
+ s->vtd_host_iommu_dev = g_hash_table_new_full(vtd_hiod_hash,
vtd_hiod_equal,
+ g_free, vtd_hiod_destroy);
vtd_init(s);
pci_setup_iommu(bus, &vtd_iommu_ops, dev);
/* Pseudo address space under root PCI bus. */
--
2.45.2
- [PULL 06/42] vfio/container: Implement HostIOMMUDeviceClass::realize() handler, (continued)
- [PULL 06/42] vfio/container: Implement HostIOMMUDeviceClass::realize() handler, Cédric Le Goater, 2024/06/24
- [PULL 07/42] backends/iommufd: Introduce helper function iommufd_backend_get_device_info(), Cédric Le Goater, 2024/06/24
- [PULL 08/42] vfio/iommufd: Implement HostIOMMUDeviceClass::realize() handler, Cédric Le Goater, 2024/06/24
- [PULL 09/42] vfio/container: Implement HostIOMMUDeviceClass::get_cap() handler, Cédric Le Goater, 2024/06/24
- [PULL 10/42] backends/iommufd: Implement HostIOMMUDeviceClass::get_cap() handler, Cédric Le Goater, 2024/06/24
- [PULL 11/42] vfio: Create host IOMMU device instance, Cédric Le Goater, 2024/06/24
- [PULL 12/42] hw/pci: Introduce helper function pci_device_get_iommu_bus_devfn(), Cédric Le Goater, 2024/06/24
- [PULL 13/42] hw/pci: Introduce pci_device_[set|unset]_iommu_device(), Cédric Le Goater, 2024/06/24
- [PULL 14/42] vfio/pci: Pass HostIOMMUDevice to vIOMMU, Cédric Le Goater, 2024/06/24
- [PULL 15/42] intel_iommu: Extract out vtd_cap_init() to initialize cap/ecap, Cédric Le Goater, 2024/06/24
- [PULL 16/42] intel_iommu: Implement [set|unset]_iommu_device() callbacks,
Cédric Le Goater <=
- [PULL 17/42] intel_iommu: Check compatibility with host IOMMU capabilities, Cédric Le Goater, 2024/06/24
- [PULL 18/42] HostIOMMUDevice: Store the VFIO/VDPA agent, Cédric Le Goater, 2024/06/24
- [PULL 19/42] virtio-iommu: Implement set|unset]_iommu_device() callbacks, Cédric Le Goater, 2024/06/24
- [PULL 20/42] HostIOMMUDevice: Introduce get_iova_ranges callback, Cédric Le Goater, 2024/06/24
- [PULL 21/42] HostIOMMUDevice: Store the aliased bus and devfn, Cédric Le Goater, 2024/06/24
- [PULL 22/42] virtio-iommu: Compute host reserved regions, Cédric Le Goater, 2024/06/24
- [PULL 23/42] virtio-iommu: Remove the implementation of iommu_set_iova_range, Cédric Le Goater, 2024/06/24
- [PULL 24/42] hw/vfio: Remove memory_region_iommu_set_iova_ranges() call, Cédric Le Goater, 2024/06/24
- [PULL 26/42] vfio: Make vfio_devices_dma_logging_start() return bool, Cédric Le Goater, 2024/06/24
- [PULL 25/42] memory: Remove IOMMU MR iommu_set_iova_range API, Cédric Le Goater, 2024/06/24