aboutsummaryrefslogtreecommitdiff
path: root/include
diff options
context:
space:
mode:
authorRichard Henderson <richard.henderson@linaro.org>2024-06-24 21:30:34 -0700
committerRichard Henderson <richard.henderson@linaro.org>2024-06-24 21:30:34 -0700
commit3f044554b94fc0756d5b3cdbf84501e0eea0e629 (patch)
treedc72c14e1467149659a213942cd9259b2243738a /include
parent78c236a9edbef8f1d7652b47184a9cd173cea73d (diff)
parent96b7af4388b38bc1f66467a9c7c8ee9d3bff500f (diff)
Merge tag 'pull-vfio-20240624' of https://github.com/legoater/qemu into staging
vfio queue: * Add a host IOMMU device abstraction * VIRTIO-IOMMU/VFIO: Fix host iommu geometry handling * QOMify VFIOContainer # -----BEGIN PGP SIGNATURE----- # # iQIzBAABCAAdFiEEoPZlSPBIlev+awtgUaNDx8/77KEFAmZ541QACgkQUaNDx8/7 # 7KFdnQ/8Dih3HI2qtY93bTxg0lmJ+ZMibojTkEkTu3kSvwoI12wkiSMFKzzTWpZE # UtGyIqQQij8IfQtIz87uQskv7oFiZKG6JWMTAX4uJ8ZIgZiih29/e/38VGEbogBh # yO+1Pqr3ETlyLnQcu9ruBTJ293LXovmD4d9feoaVdURBNZ1EqIh7sv/y7YdUsR+i # tXa6kW1ZIlKBI54o/uuODHWQYyOHs39VtZ6JZvgxVVEQsNikcJsosK9ts9A1EByi # 0roQVXm2QAK/nPXlmMGLvJWzQcdeXQ6W6hzYkO2HqGnCLURnpW+y/ZVbNcxGOOiU # 2G6L0TASlqA3yqCJeLuZZqjM6S2VbnvrA8omyg4QnygIHppYjp2CdcCmUpg6wfze # rkgbVLNasX+le4ss2emuHPh55dLDP20yW83DeGeqSgE//foaJWhtOK/cnvs04zV2 # D6oSAVsOsZ6ozYlQckYnaxIBANDKLRnzCXVZLUCmHxCUhxHuiNJUsHfZYIv/Zxen # C5ZjD/JPgx3onkoKbNfTRTgwOCdXhVPjWnnp7Su49jymsekqdk1ntln4ixDT3Vol # ghQPQLjICBc8qXiOJAcFDwqLf/telPlzUUzvlDeC4BYMnpBAP6rQ3JJ8i0vCCiWv # zKCtmbcDqDRMDpWyJWM3XA/kVKP9i2tNa1R/ej2SleCFLgRapBw= # =3koe # -----END PGP SIGNATURE----- # gpg: Signature made Mon 24 Jun 2024 02:21:24 PM PDT # gpg: using RSA key A0F66548F04895EBFE6B0B6051A343C7CFFBECA1 # gpg: Good signature from "Cédric Le Goater <clg@kaod.org>" [undefined] # gpg: WARNING: This key is not certified with a trusted signature! # gpg: There is no indication that the signature belongs to the owner. # Primary key fingerprint: A0F6 6548 F048 95EB FE6B 0B60 51A3 43C7 CFFB ECA1 * tag 'pull-vfio-20240624' of https://github.com/legoater/qemu: (42 commits) vfio/container: Move vfio_container_destroy() to an instance_finalize() handler vfio/container: Introduce vfio_iommu_legacy_instance_init() vfio/container: Remove vfio_container_init() vfio/container: Remove VFIOContainerBase::ops vfio/container: Introduce an instance_init() handler vfio/container: Switch to QOM vfio/container: Change VFIOContainerBase to use QOM vfio/container: Discover IOMMU type before creating the container vfio/container: Introduce vfio_create_container() vfio/container: Introduce vfio_get_iommu_class_name() vfio/container: Modify vfio_get_iommu_type() to use a container fd vfio/container: Simplify vfio_container_init() vfio/container: Introduce vfio_address_space_insert() vfio/common: Extract vIOMMU code from vfio_sync_dirty_bitmap() vfio/common: Move dirty tracking ranges update to helper vfio: Remove unused declarations from vfio-common.h vfio: Make vfio_devices_dma_logging_start() return bool memory: Remove IOMMU MR iommu_set_iova_range API hw/vfio: Remove memory_region_iommu_set_iova_ranges() call virtio-iommu: Remove the implementation of iommu_set_iova_range ... Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Diffstat (limited to 'include')
-rw-r--r--include/exec/memory.h32
-rw-r--r--include/hw/i386/intel_iommu.h2
-rw-r--r--include/hw/pci/pci.h38
-rw-r--r--include/hw/vfio/vfio-common.h18
-rw-r--r--include/hw/vfio/vfio-container-base.h22
-rw-r--r--include/hw/virtio/virtio-iommu.h2
-rw-r--r--include/qemu/range.h11
-rw-r--r--include/sysemu/host_iommu_device.h102
-rw-r--r--include/sysemu/iommufd.h19
9 files changed, 193 insertions, 53 deletions
diff --git a/include/exec/memory.h b/include/exec/memory.h
index 2d7c278b9f..0903513d13 100644
--- a/include/exec/memory.h
+++ b/include/exec/memory.h
@@ -530,26 +530,6 @@ struct IOMMUMemoryRegionClass {
int (*iommu_set_page_size_mask)(IOMMUMemoryRegion *iommu,
uint64_t page_size_mask,
Error **errp);
- /**
- * @iommu_set_iova_ranges:
- *
- * Propagate information about the usable IOVA ranges for a given IOMMU
- * memory region. Used for example to propagate host physical device
- * reserved memory region constraints to the virtual IOMMU.
- *
- * Optional method: if this method is not provided, then the default IOVA
- * aperture is used.
- *
- * @iommu: the IOMMUMemoryRegion
- *
- * @iova_ranges: list of ordered IOVA ranges (at least one range)
- *
- * Returns 0 on success, or a negative error. In case of failure, the error
- * object must be created.
- */
- int (*iommu_set_iova_ranges)(IOMMUMemoryRegion *iommu,
- GList *iova_ranges,
- Error **errp);
};
typedef struct RamDiscardListener RamDiscardListener;
@@ -1952,18 +1932,6 @@ int memory_region_iommu_set_page_size_mask(IOMMUMemoryRegion *iommu_mr,
Error **errp);
/**
- * memory_region_iommu_set_iova_ranges - Set the usable IOVA ranges
- * for a given IOMMU MR region
- *
- * @iommu: IOMMU memory region
- * @iova_ranges: list of ordered IOVA ranges (at least one range)
- * @errp: pointer to Error*, to store an error if it happens.
- */
-int memory_region_iommu_set_iova_ranges(IOMMUMemoryRegion *iommu,
- GList *iova_ranges,
- Error **errp);
-
-/**
* memory_region_name: get a memory region's name
*
* Returns the string that was used to initialize the memory region.
diff --git a/include/hw/i386/intel_iommu.h b/include/hw/i386/intel_iommu.h
index 7fa0a695c8..1eb05c29fc 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/include/hw/pci/pci.h b/include/hw/pci/pci.h
index eaa3fc99d8..eb26cac810 100644
--- a/include/hw/pci/pci.h
+++ b/include/hw/pci/pci.h
@@ -3,6 +3,7 @@
#include "exec/memory.h"
#include "sysemu/dma.h"
+#include "sysemu/host_iommu_device.h"
/* PCI includes legacy ISA access. */
#include "hw/isa/isa.h"
@@ -383,10 +384,45 @@ typedef struct PCIIOMMUOps {
*
* @devfn: device and function number
*/
- AddressSpace * (*get_address_space)(PCIBus *bus, void *opaque, int devfn);
+ AddressSpace * (*get_address_space)(PCIBus *bus, void *opaque, int devfn);
+ /**
+ * @set_iommu_device: attach a HostIOMMUDevice to a vIOMMU
+ *
+ * Optional callback, if not implemented in vIOMMU, then vIOMMU can't
+ * retrieve host information from the associated HostIOMMUDevice.
+ *
+ * @bus: the #PCIBus of the PCI device.
+ *
+ * @opaque: the data passed to pci_setup_iommu().
+ *
+ * @devfn: device and function number of the PCI device.
+ *
+ * @dev: the #HostIOMMUDevice to attach.
+ *
+ * @errp: pass an Error out only when return false
+ *
+ * Returns: true if HostIOMMUDevice is attached or else false with errp set.
+ */
+ bool (*set_iommu_device)(PCIBus *bus, void *opaque, int devfn,
+ HostIOMMUDevice *dev, Error **errp);
+ /**
+ * @unset_iommu_device: detach a HostIOMMUDevice from a vIOMMU
+ *
+ * Optional callback.
+ *
+ * @bus: the #PCIBus of the PCI device.
+ *
+ * @opaque: the data passed to pci_setup_iommu().
+ *
+ * @devfn: device and function number of the PCI device.
+ */
+ void (*unset_iommu_device)(PCIBus *bus, void *opaque, int devfn);
} PCIIOMMUOps;
AddressSpace *pci_device_iommu_address_space(PCIDevice *dev);
+bool pci_device_set_iommu_device(PCIDevice *dev, HostIOMMUDevice *hiod,
+ Error **errp);
+void pci_device_unset_iommu_device(PCIDevice *dev);
/**
* pci_setup_iommu: Initialize specific IOMMU handlers for a PCIBus
diff --git a/include/hw/vfio/vfio-common.h b/include/hw/vfio/vfio-common.h
index 4cb1ab8645..e8ddf92bb1 100644
--- a/include/hw/vfio/vfio-common.h
+++ b/include/hw/vfio/vfio-common.h
@@ -31,6 +31,8 @@
#endif
#include "sysemu/sysemu.h"
#include "hw/vfio/vfio-container-base.h"
+#include "sysemu/host_iommu_device.h"
+#include "sysemu/iommufd.h"
#define VFIO_MSG_PREFIX "vfio %s: "
@@ -82,6 +84,8 @@ typedef struct VFIOContainer {
QLIST_HEAD(, VFIOGroup) group_list;
} VFIOContainer;
+OBJECT_DECLARE_SIMPLE_TYPE(VFIOContainer, VFIO_IOMMU_LEGACY);
+
typedef struct VFIOHostDMAWindow {
hwaddr min_iova;
hwaddr max_iova;
@@ -97,6 +101,8 @@ typedef struct VFIOIOMMUFDContainer {
uint32_t ioas_id;
} VFIOIOMMUFDContainer;
+OBJECT_DECLARE_SIMPLE_TYPE(VFIOIOMMUFDContainer, VFIO_IOMMU_IOMMUFD);
+
typedef struct VFIODeviceOps VFIODeviceOps;
typedef struct VFIODevice {
@@ -125,6 +131,7 @@ typedef struct VFIODevice {
OnOffAuto pre_copy_dirty_page_tracking;
bool dirty_pages_supported;
bool dirty_tracking;
+ HostIOMMUDevice *hiod;
int devid;
IOMMUFDBackend *iommufd;
} VFIODevice;
@@ -171,6 +178,10 @@ typedef struct VFIOGroup {
bool ram_block_discard_allowed;
} VFIOGroup;
+#define TYPE_HOST_IOMMU_DEVICE_LEGACY_VFIO TYPE_HOST_IOMMU_DEVICE "-legacy-vfio"
+#define TYPE_HOST_IOMMU_DEVICE_IOMMUFD_VFIO \
+ TYPE_HOST_IOMMU_DEVICE_IOMMUFD "-vfio"
+
typedef struct VFIODMABuf {
QemuDmaBuf *buf;
uint32_t pos_x, pos_y, pos_updates;
@@ -199,10 +210,8 @@ typedef struct VFIODisplay {
VFIOAddressSpace *vfio_get_address_space(AddressSpace *as);
void vfio_put_address_space(VFIOAddressSpace *space);
-
-/* SPAPR specific */
-int vfio_spapr_container_init(VFIOContainer *container, Error **errp);
-void vfio_spapr_container_deinit(VFIOContainer *container);
+void vfio_address_space_insert(VFIOAddressSpace *space,
+ VFIOContainerBase *bcontainer);
void vfio_disable_irqindex(VFIODevice *vbasedev, int index);
void vfio_unmask_single_irqindex(VFIODevice *vbasedev, int index);
@@ -283,4 +292,5 @@ bool vfio_device_get_name(VFIODevice *vbasedev, Error **errp);
void vfio_device_set_fd(VFIODevice *vbasedev, const char *str, Error **errp);
void vfio_device_init(VFIODevice *vbasedev, int type, VFIODeviceOps *ops,
DeviceState *dev, bool ram_discard);
+int vfio_device_get_aw_bits(VFIODevice *vdev);
#endif /* HW_VFIO_VFIO_COMMON_H */
diff --git a/include/hw/vfio/vfio-container-base.h b/include/hw/vfio/vfio-container-base.h
index 2776481fc9..419e45ee7a 100644
--- a/include/hw/vfio/vfio-container-base.h
+++ b/include/hw/vfio/vfio-container-base.h
@@ -34,7 +34,7 @@ typedef struct VFIOAddressSpace {
* This is the base object for vfio container backends
*/
typedef struct VFIOContainerBase {
- const VFIOIOMMUClass *ops;
+ Object parent;
VFIOAddressSpace *space;
MemoryListener listener;
Error *error;
@@ -86,28 +86,18 @@ int vfio_container_set_dirty_page_tracking(VFIOContainerBase *bcontainer,
int vfio_container_query_dirty_bitmap(const VFIOContainerBase *bcontainer,
VFIOBitmap *vbmap, hwaddr iova, hwaddr size, Error **errp);
-void vfio_container_init(VFIOContainerBase *bcontainer,
- VFIOAddressSpace *space,
- const VFIOIOMMUClass *ops);
-void vfio_container_destroy(VFIOContainerBase *bcontainer);
-
-
#define TYPE_VFIO_IOMMU "vfio-iommu"
#define TYPE_VFIO_IOMMU_LEGACY TYPE_VFIO_IOMMU "-legacy"
#define TYPE_VFIO_IOMMU_SPAPR TYPE_VFIO_IOMMU "-spapr"
#define TYPE_VFIO_IOMMU_IOMMUFD TYPE_VFIO_IOMMU "-iommufd"
-/*
- * VFIOContainerBase is not an abstract QOM object because it felt
- * unnecessary to expose all the IOMMU backends to the QEMU machine
- * and human interface. However, we can still abstract the IOMMU
- * backend handlers using a QOM interface class. This provides more
- * flexibility when referencing the various implementations.
- */
-DECLARE_CLASS_CHECKERS(VFIOIOMMUClass, VFIO_IOMMU, TYPE_VFIO_IOMMU)
+OBJECT_DECLARE_TYPE(VFIOContainerBase, VFIOIOMMUClass, VFIO_IOMMU)
struct VFIOIOMMUClass {
- InterfaceClass parent_class;
+ ObjectClass parent_class;
+
+ /* Properties */
+ const char *hiod_typename;
/* basic feature */
bool (*setup)(VFIOContainerBase *bcontainer, Error **errp);
diff --git a/include/hw/virtio/virtio-iommu.h b/include/hw/virtio/virtio-iommu.h
index 83a52cc446..bdb3da72d0 100644
--- a/include/hw/virtio/virtio-iommu.h
+++ b/include/hw/virtio/virtio-iommu.h
@@ -25,6 +25,7 @@
#include "hw/pci/pci.h"
#include "qom/object.h"
#include "qapi/qapi-types-virtio.h"
+#include "sysemu/host_iommu_device.h"
#define TYPE_VIRTIO_IOMMU "virtio-iommu-device"
#define TYPE_VIRTIO_IOMMU_PCI "virtio-iommu-pci"
@@ -57,6 +58,7 @@ struct VirtIOIOMMU {
struct virtio_iommu_config config;
uint64_t features;
GHashTable *as_by_busptr;
+ GHashTable *host_iommu_devices;
IOMMUPciBus *iommu_pcibus_by_bus_num[PCI_BUS_MAX];
PCIBus *primary_bus;
ReservedRegion *prop_resv_regions;
diff --git a/include/qemu/range.h b/include/qemu/range.h
index 205e1da76d..4ce694a398 100644
--- a/include/qemu/range.h
+++ b/include/qemu/range.h
@@ -20,6 +20,8 @@
#ifndef QEMU_RANGE_H
#define QEMU_RANGE_H
+#include "qemu/bitops.h"
+
/*
* Operations on 64 bit address ranges.
* Notes:
@@ -217,6 +219,15 @@ static inline int ranges_overlap(uint64_t first1, uint64_t len1,
return !(last2 < first1 || last1 < first2);
}
+/* Get highest non-zero bit position of a range */
+static inline int range_get_last_bit(Range *range)
+{
+ if (range_is_empty(range)) {
+ return -1;
+ }
+ return 63 - clz64(range->upb);
+}
+
/*
* Return -1 if @a < @b, 1 @a > @b, and 0 if they touch or overlap.
* Both @a and @b must not be empty.
diff --git a/include/sysemu/host_iommu_device.h b/include/sysemu/host_iommu_device.h
new file mode 100644
index 0000000000..ee6c813c8b
--- /dev/null
+++ b/include/sysemu/host_iommu_device.h
@@ -0,0 +1,102 @@
+/*
+ * Host IOMMU device abstract declaration
+ *
+ * Copyright (C) 2024 Intel Corporation.
+ *
+ * Authors: Zhenzhong Duan <zhenzhong.duan@intel.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2. See
+ * the COPYING file in the top-level directory.
+ */
+
+#ifndef HOST_IOMMU_DEVICE_H
+#define HOST_IOMMU_DEVICE_H
+
+#include "qom/object.h"
+#include "qapi/error.h"
+
+/**
+ * struct HostIOMMUDeviceCaps - Define host IOMMU device capabilities.
+ *
+ * @type: host platform IOMMU type.
+ *
+ * @aw_bits: host IOMMU address width. 0xff if no limitation.
+ */
+typedef struct HostIOMMUDeviceCaps {
+ uint32_t type;
+ uint8_t aw_bits;
+} HostIOMMUDeviceCaps;
+
+#define TYPE_HOST_IOMMU_DEVICE "host-iommu-device"
+OBJECT_DECLARE_TYPE(HostIOMMUDevice, HostIOMMUDeviceClass, HOST_IOMMU_DEVICE)
+
+struct HostIOMMUDevice {
+ Object parent_obj;
+
+ char *name;
+ void *agent; /* pointer to agent device, ie. VFIO or VDPA device */
+ PCIBus *aliased_bus;
+ int aliased_devfn;
+ HostIOMMUDeviceCaps caps;
+};
+
+/**
+ * struct HostIOMMUDeviceClass - The base class for all host IOMMU devices.
+ *
+ * Different types of host devices (e.g., VFIO or VDPA device) or devices
+ * with different backend (e.g., VFIO legacy container or IOMMUFD backend)
+ * will have different implementations of the HostIOMMUDeviceClass.
+ */
+struct HostIOMMUDeviceClass {
+ ObjectClass parent_class;
+
+ /**
+ * @realize: initialize host IOMMU device instance further.
+ *
+ * Mandatory callback.
+ *
+ * @hiod: pointer to a host IOMMU device instance.
+ *
+ * @opaque: pointer to agent device of this host IOMMU device,
+ * e.g., VFIO base device or VDPA device.
+ *
+ * @errp: pass an Error out when realize fails.
+ *
+ * Returns: true on success, false on failure.
+ */
+ bool (*realize)(HostIOMMUDevice *hiod, void *opaque, Error **errp);
+ /**
+ * @get_cap: check if a host IOMMU device capability is supported.
+ *
+ * Optional callback, if not implemented, hint not supporting query
+ * of @cap.
+ *
+ * @hiod: pointer to a host IOMMU device instance.
+ *
+ * @cap: capability to check.
+ *
+ * @errp: pass an Error out when fails to query capability.
+ *
+ * Returns: <0 on failure, 0 if a @cap is unsupported, or else
+ * 1 or some positive value for some special @cap,
+ * i.e., HOST_IOMMU_DEVICE_CAP_AW_BITS.
+ */
+ int (*get_cap)(HostIOMMUDevice *hiod, int cap, Error **errp);
+ /**
+ * @get_iova_ranges: Return the list of usable iova_ranges along with
+ * @hiod Host IOMMU device
+ *
+ * @hiod: handle to the host IOMMU device
+ * @errp: error handle
+ */
+ GList* (*get_iova_ranges)(HostIOMMUDevice *hiod, Error **errp);
+};
+
+/*
+ * Host IOMMU device capability list.
+ */
+#define HOST_IOMMU_DEVICE_CAP_IOMMU_TYPE 0
+#define HOST_IOMMU_DEVICE_CAP_AW_BITS 1
+
+#define HOST_IOMMU_DEVICE_CAP_AW_BITS_MAX 64
+#endif
diff --git a/include/sysemu/iommufd.h b/include/sysemu/iommufd.h
index 293bfbe967..9edfec6045 100644
--- a/include/sysemu/iommufd.h
+++ b/include/sysemu/iommufd.h
@@ -1,9 +1,23 @@
+/*
+ * iommufd container backend declaration
+ *
+ * Copyright (C) 2024 Intel Corporation.
+ * Copyright Red Hat, Inc. 2024
+ *
+ * Authors: Yi Liu <yi.l.liu@intel.com>
+ * Eric Auger <eric.auger@redhat.com>
+ * Zhenzhong Duan <zhenzhong.duan@intel.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
#ifndef SYSEMU_IOMMUFD_H
#define SYSEMU_IOMMUFD_H
#include "qom/object.h"
#include "exec/hwaddr.h"
#include "exec/cpu-common.h"
+#include "sysemu/host_iommu_device.h"
#define TYPE_IOMMUFD_BACKEND "iommufd"
OBJECT_DECLARE_TYPE(IOMMUFDBackend, IOMMUFDBackendClass, IOMMUFD_BACKEND)
@@ -33,4 +47,9 @@ int iommufd_backend_map_dma(IOMMUFDBackend *be, uint32_t ioas_id, hwaddr iova,
ram_addr_t size, void *vaddr, bool readonly);
int iommufd_backend_unmap_dma(IOMMUFDBackend *be, uint32_t ioas_id,
hwaddr iova, ram_addr_t size);
+bool iommufd_backend_get_device_info(IOMMUFDBackend *be, uint32_t devid,
+ uint32_t *type, void *data, uint32_t len,
+ Error **errp);
+
+#define TYPE_HOST_IOMMU_DEVICE_IOMMUFD TYPE_HOST_IOMMU_DEVICE "-iommufd"
#endif