diff options
author | Richard Henderson <richard.henderson@linaro.org> | 2024-06-24 21:30:34 -0700 |
---|---|---|
committer | Richard Henderson <richard.henderson@linaro.org> | 2024-06-24 21:30:34 -0700 |
commit | 3f044554b94fc0756d5b3cdbf84501e0eea0e629 (patch) | |
tree | dc72c14e1467149659a213942cd9259b2243738a /include | |
parent | 78c236a9edbef8f1d7652b47184a9cd173cea73d (diff) | |
parent | 96b7af4388b38bc1f66467a9c7c8ee9d3bff500f (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.h | 32 | ||||
-rw-r--r-- | include/hw/i386/intel_iommu.h | 2 | ||||
-rw-r--r-- | include/hw/pci/pci.h | 38 | ||||
-rw-r--r-- | include/hw/vfio/vfio-common.h | 18 | ||||
-rw-r--r-- | include/hw/vfio/vfio-container-base.h | 22 | ||||
-rw-r--r-- | include/hw/virtio/virtio-iommu.h | 2 | ||||
-rw-r--r-- | include/qemu/range.h | 11 | ||||
-rw-r--r-- | include/sysemu/host_iommu_device.h | 102 | ||||
-rw-r--r-- | include/sysemu/iommufd.h | 19 |
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 |