From 499e53cce9445d23ee1bf54562de558562fc8d22 Mon Sep 17 00:00:00 2001 From: Cédric Le Goater Date: Wed, 26 Mar 2025 08:50:56 +0100 Subject: vfio: Introduce new files for VFIORegion definitions and declarations MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Gather all VFIORegion related declarations and definitions into their own files to reduce exposure of VFIO internals in "hw/vfio/vfio-common.h". They were introduced for 'vfio-platform' support in commits db0da029a185 ("vfio: Generalize region support") and a664477db8da ("hw/vfio/pci: Introduce VFIORegion"). To be noted that the 'vfio-platform' devices have been deprecated and will be removed in QEMU 10.2. Until then, make the declarations available externally for 'sysbus-fdt.c'. Cc: Eric Auger Reviewed-by: Zhenzhong Duan Link: https://lore.kernel.org/qemu-devel/20250326075122.1299361-12-clg@redhat.com Signed-off-by: Cédric Le Goater --- hw/vfio/helpers.c | 363 ------------------------------------------------------ 1 file changed, 363 deletions(-) (limited to 'hw/vfio/helpers.c') diff --git a/hw/vfio/helpers.c b/hw/vfio/helpers.c index 4b255d4f3a..89403943a7 100644 --- a/hw/vfio/helpers.c +++ b/hw/vfio/helpers.c @@ -147,118 +147,6 @@ bool vfio_set_irq_signaling(VFIODevice *vbasedev, int index, int subindex, return false; } -/* - * IO Port/MMIO - Beware of the endians, VFIO is always little endian - */ -void vfio_region_write(void *opaque, hwaddr addr, - uint64_t data, unsigned size) -{ - VFIORegion *region = opaque; - VFIODevice *vbasedev = region->vbasedev; - union { - uint8_t byte; - uint16_t word; - uint32_t dword; - uint64_t qword; - } buf; - - switch (size) { - case 1: - buf.byte = data; - break; - case 2: - buf.word = cpu_to_le16(data); - break; - case 4: - buf.dword = cpu_to_le32(data); - break; - case 8: - buf.qword = cpu_to_le64(data); - break; - default: - hw_error("vfio: unsupported write size, %u bytes", size); - break; - } - - if (pwrite(vbasedev->fd, &buf, size, region->fd_offset + addr) != size) { - error_report("%s(%s:region%d+0x%"HWADDR_PRIx", 0x%"PRIx64 - ",%d) failed: %m", - __func__, vbasedev->name, region->nr, - addr, data, size); - } - - trace_vfio_region_write(vbasedev->name, region->nr, addr, data, size); - - /* - * A read or write to a BAR always signals an INTx EOI. This will - * do nothing if not pending (including not in INTx mode). We assume - * that a BAR access is in response to an interrupt and that BAR - * accesses will service the interrupt. Unfortunately, we don't know - * which access will service the interrupt, so we're potentially - * getting quite a few host interrupts per guest interrupt. - */ - vbasedev->ops->vfio_eoi(vbasedev); -} - -uint64_t vfio_region_read(void *opaque, - hwaddr addr, unsigned size) -{ - VFIORegion *region = opaque; - VFIODevice *vbasedev = region->vbasedev; - union { - uint8_t byte; - uint16_t word; - uint32_t dword; - uint64_t qword; - } buf; - uint64_t data = 0; - - if (pread(vbasedev->fd, &buf, size, region->fd_offset + addr) != size) { - error_report("%s(%s:region%d+0x%"HWADDR_PRIx", %d) failed: %m", - __func__, vbasedev->name, region->nr, - addr, size); - return (uint64_t)-1; - } - switch (size) { - case 1: - data = buf.byte; - break; - case 2: - data = le16_to_cpu(buf.word); - break; - case 4: - data = le32_to_cpu(buf.dword); - break; - case 8: - data = le64_to_cpu(buf.qword); - break; - default: - hw_error("vfio: unsupported read size, %u bytes", size); - break; - } - - trace_vfio_region_read(vbasedev->name, region->nr, addr, size, data); - - /* Same as write above */ - vbasedev->ops->vfio_eoi(vbasedev); - - return data; -} - -const MemoryRegionOps vfio_region_ops = { - .read = vfio_region_read, - .write = vfio_region_write, - .endianness = DEVICE_LITTLE_ENDIAN, - .valid = { - .min_access_size = 1, - .max_access_size = 8, - }, - .impl = { - .min_access_size = 1, - .max_access_size = 8, - }, -}; - int vfio_bitmap_alloc(VFIOBitmap *vbmap, hwaddr size) { vbmap->pages = REAL_HOST_PAGE_ALIGN(size) / qemu_real_host_page_size(); @@ -306,257 +194,6 @@ vfio_get_device_info_cap(struct vfio_device_info *info, uint16_t id) return vfio_get_cap((void *)info, info->cap_offset, id); } -static int vfio_setup_region_sparse_mmaps(VFIORegion *region, - struct vfio_region_info *info) -{ - struct vfio_info_cap_header *hdr; - struct vfio_region_info_cap_sparse_mmap *sparse; - int i, j; - - hdr = vfio_get_region_info_cap(info, VFIO_REGION_INFO_CAP_SPARSE_MMAP); - if (!hdr) { - return -ENODEV; - } - - sparse = container_of(hdr, struct vfio_region_info_cap_sparse_mmap, header); - - trace_vfio_region_sparse_mmap_header(region->vbasedev->name, - region->nr, sparse->nr_areas); - - region->mmaps = g_new0(VFIOMmap, sparse->nr_areas); - - for (i = 0, j = 0; i < sparse->nr_areas; i++) { - if (sparse->areas[i].size) { - trace_vfio_region_sparse_mmap_entry(i, sparse->areas[i].offset, - sparse->areas[i].offset + - sparse->areas[i].size - 1); - region->mmaps[j].offset = sparse->areas[i].offset; - region->mmaps[j].size = sparse->areas[i].size; - j++; - } - } - - region->nr_mmaps = j; - region->mmaps = g_realloc(region->mmaps, j * sizeof(VFIOMmap)); - - return 0; -} - -int vfio_region_setup(Object *obj, VFIODevice *vbasedev, VFIORegion *region, - int index, const char *name) -{ - g_autofree struct vfio_region_info *info = NULL; - int ret; - - ret = vfio_get_region_info(vbasedev, index, &info); - if (ret) { - return ret; - } - - region->vbasedev = vbasedev; - region->flags = info->flags; - region->size = info->size; - region->fd_offset = info->offset; - region->nr = index; - - if (region->size) { - region->mem = g_new0(MemoryRegion, 1); - memory_region_init_io(region->mem, obj, &vfio_region_ops, - region, name, region->size); - - if (!vbasedev->no_mmap && - region->flags & VFIO_REGION_INFO_FLAG_MMAP) { - - ret = vfio_setup_region_sparse_mmaps(region, info); - - if (ret) { - region->nr_mmaps = 1; - region->mmaps = g_new0(VFIOMmap, region->nr_mmaps); - region->mmaps[0].offset = 0; - region->mmaps[0].size = region->size; - } - } - } - - trace_vfio_region_setup(vbasedev->name, index, name, - region->flags, region->fd_offset, region->size); - return 0; -} - -static void vfio_subregion_unmap(VFIORegion *region, int index) -{ - trace_vfio_region_unmap(memory_region_name(®ion->mmaps[index].mem), - region->mmaps[index].offset, - region->mmaps[index].offset + - region->mmaps[index].size - 1); - memory_region_del_subregion(region->mem, ®ion->mmaps[index].mem); - munmap(region->mmaps[index].mmap, region->mmaps[index].size); - object_unparent(OBJECT(®ion->mmaps[index].mem)); - region->mmaps[index].mmap = NULL; -} - -int vfio_region_mmap(VFIORegion *region) -{ - int i, ret, prot = 0; - char *name; - - if (!region->mem) { - return 0; - } - - prot |= region->flags & VFIO_REGION_INFO_FLAG_READ ? PROT_READ : 0; - prot |= region->flags & VFIO_REGION_INFO_FLAG_WRITE ? PROT_WRITE : 0; - - for (i = 0; i < region->nr_mmaps; i++) { - size_t align = MIN(1ULL << ctz64(region->mmaps[i].size), 1 * GiB); - void *map_base, *map_align; - - /* - * Align the mmap for more efficient mapping in the kernel. Ideally - * we'd know the PMD and PUD mapping sizes to use as discrete alignment - * intervals, but we don't. As of Linux v6.12, the largest PUD size - * supporting huge pfnmap is 1GiB (ARCH_SUPPORTS_PUD_PFNMAP is only set - * on x86_64). Align by power-of-two size, capped at 1GiB. - * - * NB. qemu_memalign() and friends actually allocate memory, whereas - * the region size here can exceed host memory, therefore we manually - * create an oversized anonymous mapping and clean it up for alignment. - */ - map_base = mmap(0, region->mmaps[i].size + align, PROT_NONE, - MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); - if (map_base == MAP_FAILED) { - ret = -errno; - goto no_mmap; - } - - map_align = (void *)ROUND_UP((uintptr_t)map_base, (uintptr_t)align); - munmap(map_base, map_align - map_base); - munmap(map_align + region->mmaps[i].size, - align - (map_align - map_base)); - - region->mmaps[i].mmap = mmap(map_align, region->mmaps[i].size, prot, - MAP_SHARED | MAP_FIXED, - region->vbasedev->fd, - region->fd_offset + - region->mmaps[i].offset); - if (region->mmaps[i].mmap == MAP_FAILED) { - ret = -errno; - goto no_mmap; - } - - name = g_strdup_printf("%s mmaps[%d]", - memory_region_name(region->mem), i); - memory_region_init_ram_device_ptr(®ion->mmaps[i].mem, - memory_region_owner(region->mem), - name, region->mmaps[i].size, - region->mmaps[i].mmap); - g_free(name); - memory_region_add_subregion(region->mem, region->mmaps[i].offset, - ®ion->mmaps[i].mem); - - trace_vfio_region_mmap(memory_region_name(®ion->mmaps[i].mem), - region->mmaps[i].offset, - region->mmaps[i].offset + - region->mmaps[i].size - 1); - } - - return 0; - -no_mmap: - trace_vfio_region_mmap_fault(memory_region_name(region->mem), i, - region->fd_offset + region->mmaps[i].offset, - region->fd_offset + region->mmaps[i].offset + - region->mmaps[i].size - 1, ret); - - region->mmaps[i].mmap = NULL; - - for (i--; i >= 0; i--) { - vfio_subregion_unmap(region, i); - } - - return ret; -} - -void vfio_region_unmap(VFIORegion *region) -{ - int i; - - if (!region->mem) { - return; - } - - for (i = 0; i < region->nr_mmaps; i++) { - if (region->mmaps[i].mmap) { - vfio_subregion_unmap(region, i); - } - } -} - -void vfio_region_exit(VFIORegion *region) -{ - int i; - - if (!region->mem) { - return; - } - - for (i = 0; i < region->nr_mmaps; i++) { - if (region->mmaps[i].mmap) { - memory_region_del_subregion(region->mem, ®ion->mmaps[i].mem); - } - } - - trace_vfio_region_exit(region->vbasedev->name, region->nr); -} - -void vfio_region_finalize(VFIORegion *region) -{ - int i; - - if (!region->mem) { - return; - } - - for (i = 0; i < region->nr_mmaps; i++) { - if (region->mmaps[i].mmap) { - munmap(region->mmaps[i].mmap, region->mmaps[i].size); - object_unparent(OBJECT(®ion->mmaps[i].mem)); - } - } - - object_unparent(OBJECT(region->mem)); - - g_free(region->mem); - g_free(region->mmaps); - - trace_vfio_region_finalize(region->vbasedev->name, region->nr); - - region->mem = NULL; - region->mmaps = NULL; - region->nr_mmaps = 0; - region->size = 0; - region->flags = 0; - region->nr = 0; -} - -void vfio_region_mmaps_set_enabled(VFIORegion *region, bool enabled) -{ - int i; - - if (!region->mem) { - return; - } - - for (i = 0; i < region->nr_mmaps; i++) { - if (region->mmaps[i].mmap) { - memory_region_set_enabled(®ion->mmaps[i].mem, enabled); - } - } - - trace_vfio_region_mmaps_set_enabled(memory_region_name(region->mem), - enabled); -} - int vfio_get_region_info(VFIODevice *vbasedev, int index, struct vfio_region_info **info) { -- cgit 1.4.1 From ac28680d5e7a84943cd9f55a4aae245d6d7fdcae Mon Sep 17 00:00:00 2001 From: Cédric Le Goater Date: Wed, 26 Mar 2025 08:51:01 +0100 Subject: vfio: Introduce a new header file for helper services MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Gather all helper routine declarations into "vfio-helpers.h" to reduce exposure of VFIO internals in "hw/vfio/vfio-common.h". Reviewed-by: John Levon Link: https://lore.kernel.org/qemu-devel/20250318095415.670319-16-clg@redhat.com Reviewed-by: Zhenzhong Duan Link: https://lore.kernel.org/qemu-devel/20250326075122.1299361-17-clg@redhat.com Signed-off-by: Cédric Le Goater --- hw/s390x/s390-pci-vfio.c | 1 + hw/vfio/common.c | 1 + hw/vfio/container.c | 1 + hw/vfio/helpers.c | 1 + hw/vfio/pci.c | 1 + hw/vfio/region.c | 1 + hw/vfio/vfio-helpers.h | 26 ++++++++++++++++++++++++++ include/hw/vfio/vfio-common.h | 7 ------- 8 files changed, 32 insertions(+), 7 deletions(-) create mode 100644 hw/vfio/vfio-helpers.h (limited to 'hw/vfio/helpers.c') diff --git a/hw/s390x/s390-pci-vfio.c b/hw/s390x/s390-pci-vfio.c index 748a51fd8c..aaf91319b4 100644 --- a/hw/s390x/s390-pci-vfio.c +++ b/hw/s390x/s390-pci-vfio.c @@ -21,6 +21,7 @@ #include "hw/s390x/s390-pci-vfio.h" #include "hw/vfio/pci.h" #include "hw/vfio/vfio-container.h" +#include "hw/vfio/vfio-helpers.h" /* * Get the current DMA available count from vfio. Returns true if vfio is diff --git a/hw/vfio/common.c b/hw/vfio/common.c index c099d4d24d..18e5aacbd1 100644 --- a/hw/vfio/common.c +++ b/hw/vfio/common.c @@ -44,6 +44,7 @@ #include "system/tcg.h" #include "system/tpm.h" #include "vfio-migration-internal.h" +#include "vfio-helpers.h" VFIODeviceList vfio_device_list = QLIST_HEAD_INITIALIZER(vfio_device_list); diff --git a/hw/vfio/container.c b/hw/vfio/container.c index 6ef53ee187..b2d72f5036 100644 --- a/hw/vfio/container.c +++ b/hw/vfio/container.c @@ -33,6 +33,7 @@ #include "qapi/error.h" #include "pci.h" #include "hw/vfio/vfio-container.h" +#include "vfio-helpers.h" #define TYPE_HOST_IOMMU_DEVICE_LEGACY_VFIO TYPE_HOST_IOMMU_DEVICE "-legacy-vfio" diff --git a/hw/vfio/helpers.c b/hw/vfio/helpers.c index 89403943a7..054ee6e31e 100644 --- a/hw/vfio/helpers.c +++ b/hw/vfio/helpers.c @@ -30,6 +30,7 @@ #include "qemu/error-report.h" #include "qemu/units.h" #include "monitor/monitor.h" +#include "vfio-helpers.h" /* * Common VFIO interrupt disable diff --git a/hw/vfio/pci.c b/hw/vfio/pci.c index b0aac2f3a0..bade3b80d7 100644 --- a/hw/vfio/pci.c +++ b/hw/vfio/pci.c @@ -45,6 +45,7 @@ #include "migration/qemu-file.h" #include "system/iommufd.h" #include "vfio-migration-internal.h" +#include "vfio-helpers.h" #define TYPE_VFIO_PCI_NOHOTPLUG "vfio-pci-nohotplug" diff --git a/hw/vfio/region.c b/hw/vfio/region.c index 08cd69e704..9049143abf 100644 --- a/hw/vfio/region.c +++ b/hw/vfio/region.c @@ -29,6 +29,7 @@ #include "qemu/error-report.h" #include "qemu/units.h" #include "monitor/monitor.h" +#include "vfio-helpers.h" /* * IO Port/MMIO - Beware of the endians, VFIO is always little endian diff --git a/hw/vfio/vfio-helpers.h b/hw/vfio/vfio-helpers.h new file mode 100644 index 0000000000..d7e4dcba51 --- /dev/null +++ b/hw/vfio/vfio-helpers.h @@ -0,0 +1,26 @@ +/* + * VFIO helpers + * + * Copyright Red Hat, Inc. 2025 + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#ifndef HW_VFIO_VFIO_HELPERS_H +#define HW_VFIO_VFIO_HELPERS_H + +#ifdef CONFIG_LINUX +#include + +struct vfio_info_cap_header * +vfio_get_cap(void *ptr, uint32_t cap_offset, uint16_t id); +struct vfio_info_cap_header * +vfio_get_device_info_cap(struct vfio_device_info *info, uint16_t id); +struct vfio_info_cap_header * +vfio_get_region_info_cap(struct vfio_region_info *info, uint16_t id); + +#endif + +int vfio_bitmap_alloc(VFIOBitmap *vbmap, hwaddr size); + +#endif /* HW_VFIO_VFIO_HELPERS_H */ diff --git a/include/hw/vfio/vfio-common.h b/include/hw/vfio/vfio-common.h index bb11b8215a..8e465111d2 100644 --- a/include/hw/vfio/vfio-common.h +++ b/include/hw/vfio/vfio-common.h @@ -147,17 +147,10 @@ int vfio_get_region_info(VFIODevice *vbasedev, int index, int vfio_get_dev_region_info(VFIODevice *vbasedev, uint32_t type, uint32_t subtype, struct vfio_region_info **info); bool vfio_has_region_cap(VFIODevice *vbasedev, int region, uint16_t cap_type); -struct vfio_info_cap_header * -vfio_get_region_info_cap(struct vfio_region_info *info, uint16_t id); bool vfio_get_info_dma_avail(struct vfio_iommu_type1_info *info, unsigned int *avail); -struct vfio_info_cap_header * -vfio_get_device_info_cap(struct vfio_device_info *info, uint16_t id); -struct vfio_info_cap_header * -vfio_get_cap(void *ptr, uint32_t cap_offset, uint16_t id); #endif -int vfio_bitmap_alloc(VFIOBitmap *vbmap, hwaddr size); bool vfio_devices_all_dirty_tracking_started( const VFIOContainerBase *bcontainer); bool -- cgit 1.4.1 From f6d7f5d02bbb57b5b469863afe89278d64598d81 Mon Sep 17 00:00:00 2001 From: Cédric Le Goater Date: Wed, 26 Mar 2025 08:51:02 +0100 Subject: vfio: Move vfio_get_info_dma_avail() into helpers.c MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit vfio_get_info_dma_avail() is a low level routine similar to the other routines extracting capabilities from 'struct vfio_iommu_type1_info'. It belongs to file "helpers.c". Reviewed-by: John Levon Link: https://lore.kernel.org/qemu-devel/20250318095415.670319-17-clg@redhat.com Reviewed-by: Zhenzhong Duan Link: https://lore.kernel.org/qemu-devel/20250326075122.1299361-18-clg@redhat.com Signed-off-by: Cédric Le Goater --- hw/vfio/container.c | 31 ------------------------------- hw/vfio/helpers.c | 31 +++++++++++++++++++++++++++++++ hw/vfio/vfio-helpers.h | 5 ++++- include/hw/vfio/vfio-common.h | 2 -- 4 files changed, 35 insertions(+), 34 deletions(-) (limited to 'hw/vfio/helpers.c') diff --git a/hw/vfio/container.c b/hw/vfio/container.c index b2d72f5036..3fdd5dac37 100644 --- a/hw/vfio/container.c +++ b/hw/vfio/container.c @@ -278,37 +278,6 @@ static int vfio_legacy_query_dirty_bitmap(const VFIOContainerBase *bcontainer, return ret; } -static struct vfio_info_cap_header * -vfio_get_iommu_type1_info_cap(struct vfio_iommu_type1_info *info, uint16_t id) -{ - if (!(info->flags & VFIO_IOMMU_INFO_CAPS)) { - return NULL; - } - - return vfio_get_cap((void *)info, info->cap_offset, id); -} - -bool vfio_get_info_dma_avail(struct vfio_iommu_type1_info *info, - unsigned int *avail) -{ - struct vfio_info_cap_header *hdr; - struct vfio_iommu_type1_info_dma_avail *cap; - - /* If the capability cannot be found, assume no DMA limiting */ - hdr = vfio_get_iommu_type1_info_cap(info, - VFIO_IOMMU_TYPE1_INFO_DMA_AVAIL); - if (!hdr) { - return false; - } - - if (avail != NULL) { - cap = (void *) hdr; - *avail = cap->avail; - } - - return true; -} - static bool vfio_get_info_iova_range(struct vfio_iommu_type1_info *info, VFIOContainerBase *bcontainer) { diff --git a/hw/vfio/helpers.c b/hw/vfio/helpers.c index 054ee6e31e..1a584ba5f0 100644 --- a/hw/vfio/helpers.c +++ b/hw/vfio/helpers.c @@ -222,6 +222,37 @@ retry: return 0; } +struct vfio_info_cap_header * +vfio_get_iommu_type1_info_cap(struct vfio_iommu_type1_info *info, uint16_t id) +{ + if (!(info->flags & VFIO_IOMMU_INFO_CAPS)) { + return NULL; + } + + return vfio_get_cap((void *)info, info->cap_offset, id); +} + +bool vfio_get_info_dma_avail(struct vfio_iommu_type1_info *info, + unsigned int *avail) +{ + struct vfio_info_cap_header *hdr; + struct vfio_iommu_type1_info_dma_avail *cap; + + /* If the capability cannot be found, assume no DMA limiting */ + hdr = vfio_get_iommu_type1_info_cap(info, + VFIO_IOMMU_TYPE1_INFO_DMA_AVAIL); + if (!hdr) { + return false; + } + + if (avail != NULL) { + cap = (void *) hdr; + *avail = cap->avail; + } + + return true; +} + int vfio_get_dev_region_info(VFIODevice *vbasedev, uint32_t type, uint32_t subtype, struct vfio_region_info **info) { diff --git a/hw/vfio/vfio-helpers.h b/hw/vfio/vfio-helpers.h index d7e4dcba51..9af43878b8 100644 --- a/hw/vfio/vfio-helpers.h +++ b/hw/vfio/vfio-helpers.h @@ -18,7 +18,10 @@ struct vfio_info_cap_header * vfio_get_device_info_cap(struct vfio_device_info *info, uint16_t id); struct vfio_info_cap_header * vfio_get_region_info_cap(struct vfio_region_info *info, uint16_t id); - +struct vfio_info_cap_header * +vfio_get_iommu_type1_info_cap(struct vfio_iommu_type1_info *info, uint16_t id); +bool vfio_get_info_dma_avail(struct vfio_iommu_type1_info *info, + unsigned int *avail); #endif int vfio_bitmap_alloc(VFIOBitmap *vbmap, hwaddr size); diff --git a/include/hw/vfio/vfio-common.h b/include/hw/vfio/vfio-common.h index 8e465111d2..be2558f7e4 100644 --- a/include/hw/vfio/vfio-common.h +++ b/include/hw/vfio/vfio-common.h @@ -147,8 +147,6 @@ int vfio_get_region_info(VFIODevice *vbasedev, int index, int vfio_get_dev_region_info(VFIODevice *vbasedev, uint32_t type, uint32_t subtype, struct vfio_region_info **info); bool vfio_has_region_cap(VFIODevice *vbasedev, int region, uint16_t cap_type); -bool vfio_get_info_dma_avail(struct vfio_iommu_type1_info *info, - unsigned int *avail); #endif bool vfio_devices_all_dirty_tracking_started( -- cgit 1.4.1 From 545256134fdcac6c342f8e7f45eb591e3b12c700 Mon Sep 17 00:00:00 2001 From: Cédric Le Goater Date: Wed, 26 Mar 2025 08:51:03 +0100 Subject: vfio: Move vfio_kvm_device_add/del_fd() to helpers.c MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit vfio_kvm_device_add/del_fd() are low level routines. Move them with the other helpers. Reviewed-by: Zhenzhong Duan Reviewed-by: John Levon Link: https://lore.kernel.org/qemu-devel/20250318095415.670319-18-clg@redhat.com Link: https://lore.kernel.org/qemu-devel/20250326075122.1299361-19-clg@redhat.com Signed-off-by: Cédric Le Goater --- hw/vfio/common.c | 58 ------------------------------------------ hw/vfio/helpers.c | 59 +++++++++++++++++++++++++++++++++++++++++++ hw/vfio/iommufd.c | 1 + hw/vfio/meson.build | 2 +- hw/vfio/vfio-helpers.h | 3 +++ include/hw/vfio/vfio-common.h | 3 --- 6 files changed, 64 insertions(+), 62 deletions(-) (limited to 'hw/vfio/helpers.c') diff --git a/hw/vfio/common.c b/hw/vfio/common.c index 18e5aacbd1..2b3af051cc 100644 --- a/hw/vfio/common.c +++ b/hw/vfio/common.c @@ -1333,64 +1333,6 @@ void vfio_reset_handler(void *opaque) } } -int vfio_kvm_device_add_fd(int fd, Error **errp) -{ -#ifdef CONFIG_KVM - struct kvm_device_attr attr = { - .group = KVM_DEV_VFIO_FILE, - .attr = KVM_DEV_VFIO_FILE_ADD, - .addr = (uint64_t)(unsigned long)&fd, - }; - - if (!kvm_enabled()) { - return 0; - } - - if (vfio_kvm_device_fd < 0) { - struct kvm_create_device cd = { - .type = KVM_DEV_TYPE_VFIO, - }; - - if (kvm_vm_ioctl(kvm_state, KVM_CREATE_DEVICE, &cd)) { - error_setg_errno(errp, errno, "Failed to create KVM VFIO device"); - return -errno; - } - - vfio_kvm_device_fd = cd.fd; - } - - if (ioctl(vfio_kvm_device_fd, KVM_SET_DEVICE_ATTR, &attr)) { - error_setg_errno(errp, errno, "Failed to add fd %d to KVM VFIO device", - fd); - return -errno; - } -#endif - return 0; -} - -int vfio_kvm_device_del_fd(int fd, Error **errp) -{ -#ifdef CONFIG_KVM - struct kvm_device_attr attr = { - .group = KVM_DEV_VFIO_FILE, - .attr = KVM_DEV_VFIO_FILE_DEL, - .addr = (uint64_t)(unsigned long)&fd, - }; - - if (vfio_kvm_device_fd < 0) { - error_setg(errp, "KVM VFIO device isn't created yet"); - return -EINVAL; - } - - if (ioctl(vfio_kvm_device_fd, KVM_SET_DEVICE_ATTR, &attr)) { - error_setg_errno(errp, errno, - "Failed to remove fd %d from KVM VFIO device", fd); - return -errno; - } -#endif - return 0; -} - struct vfio_device_info *vfio_get_device_info(int fd) { struct vfio_device_info *info; diff --git a/hw/vfio/helpers.c b/hw/vfio/helpers.c index 1a584ba5f0..e6b75baa80 100644 --- a/hw/vfio/helpers.c +++ b/hw/vfio/helpers.c @@ -22,6 +22,7 @@ #include "qemu/osdep.h" #include +#include "system/kvm.h" #include "hw/vfio/vfio-common.h" #include "hw/vfio/pci.h" #include "hw/hw.h" @@ -253,6 +254,64 @@ bool vfio_get_info_dma_avail(struct vfio_iommu_type1_info *info, return true; } +int vfio_kvm_device_add_fd(int fd, Error **errp) +{ +#ifdef CONFIG_KVM + struct kvm_device_attr attr = { + .group = KVM_DEV_VFIO_FILE, + .attr = KVM_DEV_VFIO_FILE_ADD, + .addr = (uint64_t)(unsigned long)&fd, + }; + + if (!kvm_enabled()) { + return 0; + } + + if (vfio_kvm_device_fd < 0) { + struct kvm_create_device cd = { + .type = KVM_DEV_TYPE_VFIO, + }; + + if (kvm_vm_ioctl(kvm_state, KVM_CREATE_DEVICE, &cd)) { + error_setg_errno(errp, errno, "Failed to create KVM VFIO device"); + return -errno; + } + + vfio_kvm_device_fd = cd.fd; + } + + if (ioctl(vfio_kvm_device_fd, KVM_SET_DEVICE_ATTR, &attr)) { + error_setg_errno(errp, errno, "Failed to add fd %d to KVM VFIO device", + fd); + return -errno; + } +#endif + return 0; +} + +int vfio_kvm_device_del_fd(int fd, Error **errp) +{ +#ifdef CONFIG_KVM + struct kvm_device_attr attr = { + .group = KVM_DEV_VFIO_FILE, + .attr = KVM_DEV_VFIO_FILE_DEL, + .addr = (uint64_t)(unsigned long)&fd, + }; + + if (vfio_kvm_device_fd < 0) { + error_setg(errp, "KVM VFIO device isn't created yet"); + return -EINVAL; + } + + if (ioctl(vfio_kvm_device_fd, KVM_SET_DEVICE_ATTR, &attr)) { + error_setg_errno(errp, errno, + "Failed to remove fd %d from KVM VFIO device", fd); + return -errno; + } +#endif + return 0; +} + int vfio_get_dev_region_info(VFIODevice *vbasedev, uint32_t type, uint32_t subtype, struct vfio_region_info **info) { diff --git a/hw/vfio/iommufd.c b/hw/vfio/iommufd.c index 2ec15bc269..85b5a8146a 100644 --- a/hw/vfio/iommufd.c +++ b/hw/vfio/iommufd.c @@ -26,6 +26,7 @@ #include "qemu/chardev_open.h" #include "pci.h" #include "vfio-iommufd.h" +#include "vfio-helpers.h" #define TYPE_HOST_IOMMU_DEVICE_IOMMUFD_VFIO \ TYPE_HOST_IOMMU_DEVICE_IOMMUFD "-vfio" diff --git a/hw/vfio/meson.build b/hw/vfio/meson.build index 07010c7c9e..21795b3d19 100644 --- a/hw/vfio/meson.build +++ b/hw/vfio/meson.build @@ -2,6 +2,7 @@ vfio_ss = ss.source_set() vfio_ss.add(files( 'common.c', 'container.c', + 'helpers.c', )) vfio_ss.add(when: 'CONFIG_PSERIES', if_true: files('spapr.c')) vfio_ss.add(when: 'CONFIG_VFIO_PCI', if_true: files( @@ -18,7 +19,6 @@ specific_ss.add_all(when: 'CONFIG_VFIO', if_true: vfio_ss) system_ss.add(when: 'CONFIG_VFIO_XGMAC', if_true: files('calxeda-xgmac.c')) system_ss.add(when: 'CONFIG_VFIO_AMD_XGBE', if_true: files('amd-xgbe.c')) system_ss.add(when: 'CONFIG_VFIO', if_true: files( - 'helpers.c', 'container-base.c', 'migration.c', 'migration-multifd.c', diff --git a/hw/vfio/vfio-helpers.h b/hw/vfio/vfio-helpers.h index 9af43878b8..5d91e33d27 100644 --- a/hw/vfio/vfio-helpers.h +++ b/hw/vfio/vfio-helpers.h @@ -26,4 +26,7 @@ bool vfio_get_info_dma_avail(struct vfio_iommu_type1_info *info, int vfio_bitmap_alloc(VFIOBitmap *vbmap, hwaddr size); +int vfio_kvm_device_add_fd(int fd, Error **errp); +int vfio_kvm_device_del_fd(int fd, Error **errp); + #endif /* HW_VFIO_VFIO_HELPERS_H */ diff --git a/include/hw/vfio/vfio-common.h b/include/hw/vfio/vfio-common.h index be2558f7e4..442ec287d7 100644 --- a/include/hw/vfio/vfio-common.h +++ b/include/hw/vfio/vfio-common.h @@ -130,9 +130,6 @@ bool vfio_attach_device(char *name, VFIODevice *vbasedev, void vfio_detach_device(VFIODevice *vbasedev); VFIODevice *vfio_get_vfio_device(Object *obj); -int vfio_kvm_device_add_fd(int fd, Error **errp); -int vfio_kvm_device_del_fd(int fd, Error **errp); - bool vfio_cpr_register_container(VFIOContainerBase *bcontainer, Error **errp); void vfio_cpr_unregister_container(VFIOContainerBase *bcontainer); -- cgit 1.4.1 From 005b8d10450d2d41e9c1bcf8da4085f23cb85b76 Mon Sep 17 00:00:00 2001 From: Cédric Le Goater Date: Wed, 26 Mar 2025 08:51:04 +0100 Subject: vfio: Move vfio_get_device_info() to helpers.c MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit vfio_get_device_info() is a low level routine. Move it with the other helpers. Reviewed-by: Zhenzhong Duan Reviewed-by: John Levon Link: https://lore.kernel.org/qemu-devel/20250318095415.670319-19-clg@redhat.com Link: https://lore.kernel.org/qemu-devel/20250326075122.1299361-20-clg@redhat.com Signed-off-by: Cédric Le Goater --- hw/vfio/common.c | 24 ------------------------ hw/vfio/helpers.c | 24 ++++++++++++++++++++++++ hw/vfio/vfio-helpers.h | 1 + include/hw/vfio/vfio-common.h | 1 - 4 files changed, 25 insertions(+), 25 deletions(-) (limited to 'hw/vfio/helpers.c') diff --git a/hw/vfio/common.c b/hw/vfio/common.c index 2b3af051cc..f80c0ef229 100644 --- a/hw/vfio/common.c +++ b/hw/vfio/common.c @@ -1333,30 +1333,6 @@ void vfio_reset_handler(void *opaque) } } -struct vfio_device_info *vfio_get_device_info(int fd) -{ - struct vfio_device_info *info; - uint32_t argsz = sizeof(*info); - - info = g_malloc0(argsz); - -retry: - info->argsz = argsz; - - if (ioctl(fd, VFIO_DEVICE_GET_INFO, info)) { - g_free(info); - return NULL; - } - - if (info->argsz > argsz) { - argsz = info->argsz; - info = g_realloc(info, argsz); - goto retry; - } - - return info; -} - bool vfio_attach_device(char *name, VFIODevice *vbasedev, AddressSpace *as, Error **errp) { diff --git a/hw/vfio/helpers.c b/hw/vfio/helpers.c index e6b75baa80..b7f75b47af 100644 --- a/hw/vfio/helpers.c +++ b/hw/vfio/helpers.c @@ -312,6 +312,30 @@ int vfio_kvm_device_del_fd(int fd, Error **errp) return 0; } +struct vfio_device_info *vfio_get_device_info(int fd) +{ + struct vfio_device_info *info; + uint32_t argsz = sizeof(*info); + + info = g_malloc0(argsz); + +retry: + info->argsz = argsz; + + if (ioctl(fd, VFIO_DEVICE_GET_INFO, info)) { + g_free(info); + return NULL; + } + + if (info->argsz > argsz) { + argsz = info->argsz; + info = g_realloc(info, argsz); + goto retry; + } + + return info; +} + int vfio_get_dev_region_info(VFIODevice *vbasedev, uint32_t type, uint32_t subtype, struct vfio_region_info **info) { diff --git a/hw/vfio/vfio-helpers.h b/hw/vfio/vfio-helpers.h index 5d91e33d27..dbcb68bbb0 100644 --- a/hw/vfio/vfio-helpers.h +++ b/hw/vfio/vfio-helpers.h @@ -25,6 +25,7 @@ bool vfio_get_info_dma_avail(struct vfio_iommu_type1_info *info, #endif int vfio_bitmap_alloc(VFIOBitmap *vbmap, hwaddr size); +struct vfio_device_info *vfio_get_device_info(int fd); int vfio_kvm_device_add_fd(int fd, Error **errp); int vfio_kvm_device_del_fd(int fd, Error **errp); diff --git a/include/hw/vfio/vfio-common.h b/include/hw/vfio/vfio-common.h index 442ec287d7..dca7a6a4b3 100644 --- a/include/hw/vfio/vfio-common.h +++ b/include/hw/vfio/vfio-common.h @@ -122,7 +122,6 @@ bool vfio_set_irq_signaling(VFIODevice *vbasedev, int index, int subindex, int action, int fd, Error **errp); void vfio_reset_handler(void *opaque); -struct vfio_device_info *vfio_get_device_info(int fd); bool vfio_device_is_mdev(VFIODevice *vbasedev); bool vfio_device_hiod_realize(VFIODevice *vbasedev, Error **errp); bool vfio_attach_device(char *name, VFIODevice *vbasedev, -- cgit 1.4.1 From 68c07d76359589c9de2aa190d247afca7eb8cb8f Mon Sep 17 00:00:00 2001 From: Cédric Le Goater Date: Wed, 26 Mar 2025 08:51:05 +0100 Subject: vfio: Introduce a new file for VFIODevice definitions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Move all VFIODevice related routines of "helpers.c" into a new "device.c" file. Reviewed-by: Zhenzhong Duan Reviewed-by: John Levon Link: https://lore.kernel.org/qemu-devel/20250326075122.1299361-21-clg@redhat.com Signed-off-by: Cédric Le Goater --- hw/vfio/device.c | 330 +++++++++++++++++++++++++++++++++++++++++++++++++++ hw/vfio/helpers.c | 303 ---------------------------------------------- hw/vfio/meson.build | 1 + hw/vfio/trace-events | 4 +- 4 files changed, 334 insertions(+), 304 deletions(-) create mode 100644 hw/vfio/device.c (limited to 'hw/vfio/helpers.c') diff --git a/hw/vfio/device.c b/hw/vfio/device.c new file mode 100644 index 0000000000..21c6824430 --- /dev/null +++ b/hw/vfio/device.c @@ -0,0 +1,330 @@ +/* + * VFIO device + * + * Copyright Red Hat, Inc. 2012 + * + * Authors: + * Alex Williamson + * + * This work is licensed under the terms of the GNU GPL, version 2. See + * the COPYING file in the top-level directory. + * + * Based on qemu-kvm device-assignment: + * Adapted for KVM by Qumranet. + * Copyright (c) 2007, Neocleus, Alex Novik (alex@neocleus.com) + * Copyright (c) 2007, Neocleus, Guy Zana (guy@neocleus.com) + * Copyright (C) 2008, Qumranet, Amit Shah (amit.shah@qumranet.com) + * Copyright (C) 2008, Red Hat, Amit Shah (amit.shah@redhat.com) + * Copyright (C) 2008, IBM, Muli Ben-Yehuda (muli@il.ibm.com) + */ + +#include "qemu/osdep.h" +#include + +#include "hw/vfio/vfio-common.h" +#include "hw/vfio/pci.h" +#include "hw/hw.h" +#include "trace.h" +#include "qapi/error.h" +#include "qemu/error-report.h" +#include "qemu/units.h" +#include "monitor/monitor.h" +#include "vfio-helpers.h" + +/* + * Common VFIO interrupt disable + */ +void vfio_disable_irqindex(VFIODevice *vbasedev, int index) +{ + struct vfio_irq_set irq_set = { + .argsz = sizeof(irq_set), + .flags = VFIO_IRQ_SET_DATA_NONE | VFIO_IRQ_SET_ACTION_TRIGGER, + .index = index, + .start = 0, + .count = 0, + }; + + ioctl(vbasedev->fd, VFIO_DEVICE_SET_IRQS, &irq_set); +} + +void vfio_unmask_single_irqindex(VFIODevice *vbasedev, int index) +{ + struct vfio_irq_set irq_set = { + .argsz = sizeof(irq_set), + .flags = VFIO_IRQ_SET_DATA_NONE | VFIO_IRQ_SET_ACTION_UNMASK, + .index = index, + .start = 0, + .count = 1, + }; + + ioctl(vbasedev->fd, VFIO_DEVICE_SET_IRQS, &irq_set); +} + +void vfio_mask_single_irqindex(VFIODevice *vbasedev, int index) +{ + struct vfio_irq_set irq_set = { + .argsz = sizeof(irq_set), + .flags = VFIO_IRQ_SET_DATA_NONE | VFIO_IRQ_SET_ACTION_MASK, + .index = index, + .start = 0, + .count = 1, + }; + + ioctl(vbasedev->fd, VFIO_DEVICE_SET_IRQS, &irq_set); +} + +static inline const char *action_to_str(int action) +{ + switch (action) { + case VFIO_IRQ_SET_ACTION_MASK: + return "MASK"; + case VFIO_IRQ_SET_ACTION_UNMASK: + return "UNMASK"; + case VFIO_IRQ_SET_ACTION_TRIGGER: + return "TRIGGER"; + default: + return "UNKNOWN ACTION"; + } +} + +static const char *index_to_str(VFIODevice *vbasedev, int index) +{ + if (vbasedev->type != VFIO_DEVICE_TYPE_PCI) { + return NULL; + } + + switch (index) { + case VFIO_PCI_INTX_IRQ_INDEX: + return "INTX"; + case VFIO_PCI_MSI_IRQ_INDEX: + return "MSI"; + case VFIO_PCI_MSIX_IRQ_INDEX: + return "MSIX"; + case VFIO_PCI_ERR_IRQ_INDEX: + return "ERR"; + case VFIO_PCI_REQ_IRQ_INDEX: + return "REQ"; + default: + return NULL; + } +} + +bool vfio_set_irq_signaling(VFIODevice *vbasedev, int index, int subindex, + int action, int fd, Error **errp) +{ + ERRP_GUARD(); + g_autofree struct vfio_irq_set *irq_set = NULL; + int argsz; + const char *name; + int32_t *pfd; + + argsz = sizeof(*irq_set) + sizeof(*pfd); + + irq_set = g_malloc0(argsz); + irq_set->argsz = argsz; + irq_set->flags = VFIO_IRQ_SET_DATA_EVENTFD | action; + irq_set->index = index; + irq_set->start = subindex; + irq_set->count = 1; + pfd = (int32_t *)&irq_set->data; + *pfd = fd; + + if (!ioctl(vbasedev->fd, VFIO_DEVICE_SET_IRQS, irq_set)) { + return true; + } + + error_setg_errno(errp, errno, "VFIO_DEVICE_SET_IRQS failure"); + + name = index_to_str(vbasedev, index); + if (name) { + error_prepend(errp, "%s-%d: ", name, subindex); + } else { + error_prepend(errp, "index %d-%d: ", index, subindex); + } + error_prepend(errp, + "Failed to %s %s eventfd signaling for interrupt ", + fd < 0 ? "tear down" : "set up", action_to_str(action)); + return false; +} + +int vfio_get_region_info(VFIODevice *vbasedev, int index, + struct vfio_region_info **info) +{ + size_t argsz = sizeof(struct vfio_region_info); + + *info = g_malloc0(argsz); + + (*info)->index = index; +retry: + (*info)->argsz = argsz; + + if (ioctl(vbasedev->fd, VFIO_DEVICE_GET_REGION_INFO, *info)) { + g_free(*info); + *info = NULL; + return -errno; + } + + if ((*info)->argsz > argsz) { + argsz = (*info)->argsz; + *info = g_realloc(*info, argsz); + + goto retry; + } + + return 0; +} + +int vfio_get_dev_region_info(VFIODevice *vbasedev, uint32_t type, + uint32_t subtype, struct vfio_region_info **info) +{ + int i; + + for (i = 0; i < vbasedev->num_regions; i++) { + struct vfio_info_cap_header *hdr; + struct vfio_region_info_cap_type *cap_type; + + if (vfio_get_region_info(vbasedev, i, info)) { + continue; + } + + hdr = vfio_get_region_info_cap(*info, VFIO_REGION_INFO_CAP_TYPE); + if (!hdr) { + g_free(*info); + continue; + } + + cap_type = container_of(hdr, struct vfio_region_info_cap_type, header); + + trace_vfio_get_dev_region(vbasedev->name, i, + cap_type->type, cap_type->subtype); + + if (cap_type->type == type && cap_type->subtype == subtype) { + return 0; + } + + g_free(*info); + } + + *info = NULL; + return -ENODEV; +} + +bool vfio_has_region_cap(VFIODevice *vbasedev, int region, uint16_t cap_type) +{ + g_autofree struct vfio_region_info *info = NULL; + bool ret = false; + + if (!vfio_get_region_info(vbasedev, region, &info)) { + if (vfio_get_region_info_cap(info, cap_type)) { + ret = true; + } + } + + return ret; +} + +bool vfio_device_get_name(VFIODevice *vbasedev, Error **errp) +{ + ERRP_GUARD(); + struct stat st; + + if (vbasedev->fd < 0) { + if (stat(vbasedev->sysfsdev, &st) < 0) { + error_setg_errno(errp, errno, "no such host device"); + error_prepend(errp, VFIO_MSG_PREFIX, vbasedev->sysfsdev); + return false; + } + /* User may specify a name, e.g: VFIO platform device */ + if (!vbasedev->name) { + vbasedev->name = g_path_get_basename(vbasedev->sysfsdev); + } + } else { + if (!vbasedev->iommufd) { + error_setg(errp, "Use FD passing only with iommufd backend"); + return false; + } + /* + * Give a name with fd so any function printing out vbasedev->name + * will not break. + */ + if (!vbasedev->name) { + vbasedev->name = g_strdup_printf("VFIO_FD%d", vbasedev->fd); + } + } + + return true; +} + +void vfio_device_set_fd(VFIODevice *vbasedev, const char *str, Error **errp) +{ + ERRP_GUARD(); + int fd = monitor_fd_param(monitor_cur(), str, errp); + + if (fd < 0) { + error_prepend(errp, "Could not parse remote object fd %s:", str); + return; + } + vbasedev->fd = fd; +} + +void vfio_device_init(VFIODevice *vbasedev, int type, VFIODeviceOps *ops, + DeviceState *dev, bool ram_discard) +{ + vbasedev->type = type; + vbasedev->ops = ops; + vbasedev->dev = dev; + vbasedev->fd = -1; + + vbasedev->ram_block_discard_allowed = ram_discard; +} + +int vfio_device_get_aw_bits(VFIODevice *vdev) +{ + /* + * iova_ranges is a sorted list. For old kernels that support + * VFIO but not support query of iova ranges, iova_ranges is NULL, + * in this case HOST_IOMMU_DEVICE_CAP_AW_BITS_MAX(64) is returned. + */ + GList *l = g_list_last(vdev->bcontainer->iova_ranges); + + if (l) { + Range *range = l->data; + return range_get_last_bit(range) + 1; + } + + return HOST_IOMMU_DEVICE_CAP_AW_BITS_MAX; +} + +bool vfio_device_is_mdev(VFIODevice *vbasedev) +{ + g_autofree char *subsys = NULL; + g_autofree char *tmp = NULL; + + if (!vbasedev->sysfsdev) { + return false; + } + + tmp = g_strdup_printf("%s/subsystem", vbasedev->sysfsdev); + subsys = realpath(tmp, NULL); + return subsys && (strcmp(subsys, "/sys/bus/mdev") == 0); +} + +bool vfio_device_hiod_realize(VFIODevice *vbasedev, Error **errp) +{ + HostIOMMUDevice *hiod = vbasedev->hiod; + + if (!hiod) { + return true; + } + + return HOST_IOMMU_DEVICE_GET_CLASS(hiod)->realize(hiod, vbasedev, errp); +} + +VFIODevice *vfio_get_vfio_device(Object *obj) +{ + if (object_dynamic_cast(obj, TYPE_VFIO_PCI)) { + return &VFIO_PCI(obj)->vbasedev; + } else { + return NULL; + } +} diff --git a/hw/vfio/helpers.c b/hw/vfio/helpers.c index b7f75b47af..7ddc9797ef 100644 --- a/hw/vfio/helpers.c +++ b/hw/vfio/helpers.c @@ -24,131 +24,10 @@ #include "system/kvm.h" #include "hw/vfio/vfio-common.h" -#include "hw/vfio/pci.h" #include "hw/hw.h" -#include "trace.h" #include "qapi/error.h" -#include "qemu/error-report.h" -#include "qemu/units.h" -#include "monitor/monitor.h" #include "vfio-helpers.h" -/* - * Common VFIO interrupt disable - */ -void vfio_disable_irqindex(VFIODevice *vbasedev, int index) -{ - struct vfio_irq_set irq_set = { - .argsz = sizeof(irq_set), - .flags = VFIO_IRQ_SET_DATA_NONE | VFIO_IRQ_SET_ACTION_TRIGGER, - .index = index, - .start = 0, - .count = 0, - }; - - ioctl(vbasedev->fd, VFIO_DEVICE_SET_IRQS, &irq_set); -} - -void vfio_unmask_single_irqindex(VFIODevice *vbasedev, int index) -{ - struct vfio_irq_set irq_set = { - .argsz = sizeof(irq_set), - .flags = VFIO_IRQ_SET_DATA_NONE | VFIO_IRQ_SET_ACTION_UNMASK, - .index = index, - .start = 0, - .count = 1, - }; - - ioctl(vbasedev->fd, VFIO_DEVICE_SET_IRQS, &irq_set); -} - -void vfio_mask_single_irqindex(VFIODevice *vbasedev, int index) -{ - struct vfio_irq_set irq_set = { - .argsz = sizeof(irq_set), - .flags = VFIO_IRQ_SET_DATA_NONE | VFIO_IRQ_SET_ACTION_MASK, - .index = index, - .start = 0, - .count = 1, - }; - - ioctl(vbasedev->fd, VFIO_DEVICE_SET_IRQS, &irq_set); -} - -static inline const char *action_to_str(int action) -{ - switch (action) { - case VFIO_IRQ_SET_ACTION_MASK: - return "MASK"; - case VFIO_IRQ_SET_ACTION_UNMASK: - return "UNMASK"; - case VFIO_IRQ_SET_ACTION_TRIGGER: - return "TRIGGER"; - default: - return "UNKNOWN ACTION"; - } -} - -static const char *index_to_str(VFIODevice *vbasedev, int index) -{ - if (vbasedev->type != VFIO_DEVICE_TYPE_PCI) { - return NULL; - } - - switch (index) { - case VFIO_PCI_INTX_IRQ_INDEX: - return "INTX"; - case VFIO_PCI_MSI_IRQ_INDEX: - return "MSI"; - case VFIO_PCI_MSIX_IRQ_INDEX: - return "MSIX"; - case VFIO_PCI_ERR_IRQ_INDEX: - return "ERR"; - case VFIO_PCI_REQ_IRQ_INDEX: - return "REQ"; - default: - return NULL; - } -} - -bool vfio_set_irq_signaling(VFIODevice *vbasedev, int index, int subindex, - int action, int fd, Error **errp) -{ - ERRP_GUARD(); - g_autofree struct vfio_irq_set *irq_set = NULL; - int argsz; - const char *name; - int32_t *pfd; - - argsz = sizeof(*irq_set) + sizeof(*pfd); - - irq_set = g_malloc0(argsz); - irq_set->argsz = argsz; - irq_set->flags = VFIO_IRQ_SET_DATA_EVENTFD | action; - irq_set->index = index; - irq_set->start = subindex; - irq_set->count = 1; - pfd = (int32_t *)&irq_set->data; - *pfd = fd; - - if (!ioctl(vbasedev->fd, VFIO_DEVICE_SET_IRQS, irq_set)) { - return true; - } - - error_setg_errno(errp, errno, "VFIO_DEVICE_SET_IRQS failure"); - - name = index_to_str(vbasedev, index); - if (name) { - error_prepend(errp, "%s-%d: ", name, subindex); - } else { - error_prepend(errp, "index %d-%d: ", index, subindex); - } - error_prepend(errp, - "Failed to %s %s eventfd signaling for interrupt ", - fd < 0 ? "tear down" : "set up", action_to_str(action)); - return false; -} - int vfio_bitmap_alloc(VFIOBitmap *vbmap, hwaddr size) { vbmap->pages = REAL_HOST_PAGE_ALIGN(size) / qemu_real_host_page_size(); @@ -196,33 +75,6 @@ vfio_get_device_info_cap(struct vfio_device_info *info, uint16_t id) return vfio_get_cap((void *)info, info->cap_offset, id); } -int vfio_get_region_info(VFIODevice *vbasedev, int index, - struct vfio_region_info **info) -{ - size_t argsz = sizeof(struct vfio_region_info); - - *info = g_malloc0(argsz); - - (*info)->index = index; -retry: - (*info)->argsz = argsz; - - if (ioctl(vbasedev->fd, VFIO_DEVICE_GET_REGION_INFO, *info)) { - g_free(*info); - *info = NULL; - return -errno; - } - - if ((*info)->argsz > argsz) { - argsz = (*info)->argsz; - *info = g_realloc(*info, argsz); - - goto retry; - } - - return 0; -} - struct vfio_info_cap_header * vfio_get_iommu_type1_info_cap(struct vfio_iommu_type1_info *info, uint16_t id) { @@ -335,158 +187,3 @@ retry: return info; } - -int vfio_get_dev_region_info(VFIODevice *vbasedev, uint32_t type, - uint32_t subtype, struct vfio_region_info **info) -{ - int i; - - for (i = 0; i < vbasedev->num_regions; i++) { - struct vfio_info_cap_header *hdr; - struct vfio_region_info_cap_type *cap_type; - - if (vfio_get_region_info(vbasedev, i, info)) { - continue; - } - - hdr = vfio_get_region_info_cap(*info, VFIO_REGION_INFO_CAP_TYPE); - if (!hdr) { - g_free(*info); - continue; - } - - cap_type = container_of(hdr, struct vfio_region_info_cap_type, header); - - trace_vfio_get_dev_region(vbasedev->name, i, - cap_type->type, cap_type->subtype); - - if (cap_type->type == type && cap_type->subtype == subtype) { - return 0; - } - - g_free(*info); - } - - *info = NULL; - return -ENODEV; -} - -bool vfio_has_region_cap(VFIODevice *vbasedev, int region, uint16_t cap_type) -{ - g_autofree struct vfio_region_info *info = NULL; - bool ret = false; - - if (!vfio_get_region_info(vbasedev, region, &info)) { - if (vfio_get_region_info_cap(info, cap_type)) { - ret = true; - } - } - - return ret; -} - -bool vfio_device_get_name(VFIODevice *vbasedev, Error **errp) -{ - ERRP_GUARD(); - struct stat st; - - if (vbasedev->fd < 0) { - if (stat(vbasedev->sysfsdev, &st) < 0) { - error_setg_errno(errp, errno, "no such host device"); - error_prepend(errp, VFIO_MSG_PREFIX, vbasedev->sysfsdev); - return false; - } - /* User may specify a name, e.g: VFIO platform device */ - if (!vbasedev->name) { - vbasedev->name = g_path_get_basename(vbasedev->sysfsdev); - } - } else { - if (!vbasedev->iommufd) { - error_setg(errp, "Use FD passing only with iommufd backend"); - return false; - } - /* - * Give a name with fd so any function printing out vbasedev->name - * will not break. - */ - if (!vbasedev->name) { - vbasedev->name = g_strdup_printf("VFIO_FD%d", vbasedev->fd); - } - } - - return true; -} - -void vfio_device_set_fd(VFIODevice *vbasedev, const char *str, Error **errp) -{ - ERRP_GUARD(); - int fd = monitor_fd_param(monitor_cur(), str, errp); - - if (fd < 0) { - error_prepend(errp, "Could not parse remote object fd %s:", str); - return; - } - vbasedev->fd = fd; -} - -void vfio_device_init(VFIODevice *vbasedev, int type, VFIODeviceOps *ops, - DeviceState *dev, bool ram_discard) -{ - vbasedev->type = type; - vbasedev->ops = ops; - vbasedev->dev = dev; - vbasedev->fd = -1; - - vbasedev->ram_block_discard_allowed = ram_discard; -} - -int vfio_device_get_aw_bits(VFIODevice *vdev) -{ - /* - * iova_ranges is a sorted list. For old kernels that support - * VFIO but not support query of iova ranges, iova_ranges is NULL, - * in this case HOST_IOMMU_DEVICE_CAP_AW_BITS_MAX(64) is returned. - */ - GList *l = g_list_last(vdev->bcontainer->iova_ranges); - - if (l) { - Range *range = l->data; - return range_get_last_bit(range) + 1; - } - - return HOST_IOMMU_DEVICE_CAP_AW_BITS_MAX; -} - -bool vfio_device_is_mdev(VFIODevice *vbasedev) -{ - g_autofree char *subsys = NULL; - g_autofree char *tmp = NULL; - - if (!vbasedev->sysfsdev) { - return false; - } - - tmp = g_strdup_printf("%s/subsystem", vbasedev->sysfsdev); - subsys = realpath(tmp, NULL); - return subsys && (strcmp(subsys, "/sys/bus/mdev") == 0); -} - -bool vfio_device_hiod_realize(VFIODevice *vbasedev, Error **errp) -{ - HostIOMMUDevice *hiod = vbasedev->hiod; - - if (!hiod) { - return true; - } - - return HOST_IOMMU_DEVICE_GET_CLASS(hiod)->realize(hiod, vbasedev, errp); -} - -VFIODevice *vfio_get_vfio_device(Object *obj) -{ - if (object_dynamic_cast(obj, TYPE_VFIO_PCI)) { - return &VFIO_PCI(obj)->vbasedev; - } else { - return NULL; - } -} diff --git a/hw/vfio/meson.build b/hw/vfio/meson.build index 21795b3d19..60caa36617 100644 --- a/hw/vfio/meson.build +++ b/hw/vfio/meson.build @@ -20,6 +20,7 @@ system_ss.add(when: 'CONFIG_VFIO_XGMAC', if_true: files('calxeda-xgmac.c')) system_ss.add(when: 'CONFIG_VFIO_AMD_XGBE', if_true: files('amd-xgbe.c')) system_ss.add(when: 'CONFIG_VFIO', if_true: files( 'container-base.c', + 'device.c', 'migration.c', 'migration-multifd.c', 'cpr.c', diff --git a/hw/vfio/trace-events b/hw/vfio/trace-events index 81f4130100..590d9674cf 100644 --- a/hw/vfio/trace-events +++ b/hw/vfio/trace-events @@ -105,7 +105,6 @@ vfio_disconnect_container(int fd) "close container->fd=%d" vfio_put_group(int fd) "close group->fd=%d" vfio_get_device(const char * name, unsigned int flags, unsigned int num_regions, unsigned int num_irqs) "Device %s flags: %u, regions: %u, irqs: %u" vfio_put_base_device(int fd) "close vdev->fd=%d" -vfio_get_dev_region(const char *name, int index, uint32_t type, uint32_t subtype) "%s index %d, %08x/%08x" vfio_legacy_dma_unmap_overflow_workaround(void) "" vfio_get_dirty_bitmap(uint64_t iova, uint64_t size, uint64_t bitmap_size, uint64_t start, uint64_t dirty_pages) "iova=0x%"PRIx64" size= 0x%"PRIx64" bitmap_size=0x%"PRIx64" start=0x%"PRIx64" dirty_pages=%"PRIu64 vfio_iommu_map_dirty_notify(uint64_t iova_start, uint64_t iova_end) "iommu dirty @ 0x%"PRIx64" - 0x%"PRIx64 @@ -194,3 +193,6 @@ iommufd_cdev_fail_attach_existing_container(const char *msg) " %s" iommufd_cdev_alloc_ioas(int iommufd, int ioas_id) " [iommufd=%d] new IOMMUFD container with ioasid=%d" iommufd_cdev_device_info(char *name, int devfd, int num_irqs, int num_regions, int flags) " %s (%d) num_irqs=%d num_regions=%d flags=%d" iommufd_cdev_pci_hot_reset_dep_devices(int domain, int bus, int slot, int function, int dev_id) "\t%04x:%02x:%02x.%x devid %d" + +# device.c +vfio_get_dev_region(const char *name, int index, uint32_t type, uint32_t subtype) "%s index %d, %08x/%08x" -- cgit 1.4.1 From c3fbdba15a8b3d80c1f5e6026e636030b3692437 Mon Sep 17 00:00:00 2001 From: Cédric Le Goater Date: Wed, 26 Mar 2025 08:51:07 +0100 Subject: vfio: Move vfio_kvm_device_fd() into helpers.c MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The vfio_kvm_device_add/del_fd() routines opening the VFIO pseudo device are defined in "helpers.c". Move 'vfio_kvm_device_fd' definition there and its declaration into "vfio-helpers.h" to reduce exposure of VFIO internals in "hw/vfio/vfio-common.h". Reviewed-by: John Levon Link: https://lore.kernel.org/qemu-devel/20250318095415.670319-22-clg@redhat.com Reviewed-by: Zhenzhong Duan Link: https://lore.kernel.org/qemu-devel/20250326075122.1299361-23-clg@redhat.com Signed-off-by: Cédric Le Goater --- hw/vfio/common.c | 11 ----------- hw/vfio/helpers.c | 11 +++++++++++ hw/vfio/spapr.c | 2 +- hw/vfio/vfio-helpers.h | 2 ++ include/hw/vfio/vfio-common.h | 1 - 5 files changed, 14 insertions(+), 13 deletions(-) (limited to 'hw/vfio/helpers.c') diff --git a/hw/vfio/common.c b/hw/vfio/common.c index f80c0ef229..84a9a37d9d 100644 --- a/hw/vfio/common.c +++ b/hw/vfio/common.c @@ -49,17 +49,6 @@ VFIODeviceList vfio_device_list = QLIST_HEAD_INITIALIZER(vfio_device_list); -#ifdef CONFIG_KVM -/* - * We have a single VFIO pseudo device per KVM VM. Once created it lives - * for the life of the VM. Closing the file descriptor only drops our - * reference to it and the device's reference to kvm. Therefore once - * initialized, this file descriptor is only released on QEMU exit and - * we'll re-use it should another vfio device be attached before then. - */ -int vfio_kvm_device_fd = -1; -#endif - /* * Device state interfaces */ diff --git a/hw/vfio/helpers.c b/hw/vfio/helpers.c index 7ddc9797ef..48bd61d528 100644 --- a/hw/vfio/helpers.c +++ b/hw/vfio/helpers.c @@ -106,6 +106,17 @@ bool vfio_get_info_dma_avail(struct vfio_iommu_type1_info *info, return true; } +#ifdef CONFIG_KVM +/* + * We have a single VFIO pseudo device per KVM VM. Once created it lives + * for the life of the VM. Closing the file descriptor only drops our + * reference to it and the device's reference to kvm. Therefore once + * initialized, this file descriptor is only released on QEMU exit and + * we'll re-use it should another vfio device be attached before then. + */ +int vfio_kvm_device_fd = -1; +#endif + int vfio_kvm_device_add_fd(int fd, Error **errp) { #ifdef CONFIG_KVM diff --git a/hw/vfio/spapr.c b/hw/vfio/spapr.c index 31e4dddc9e..95ccbad418 100644 --- a/hw/vfio/spapr.c +++ b/hw/vfio/spapr.c @@ -15,13 +15,13 @@ #include "system/hostmem.h" #include "system/address-spaces.h" -#include "hw/vfio/vfio-common.h" #include "hw/vfio/vfio-container.h" #include "hw/hw.h" #include "system/ram_addr.h" #include "qemu/error-report.h" #include "qapi/error.h" #include "trace.h" +#include "vfio-helpers.h" typedef struct VFIOHostDMAWindow { hwaddr min_iova; diff --git a/hw/vfio/vfio-helpers.h b/hw/vfio/vfio-helpers.h index dbcb68bbb0..54a327ffbc 100644 --- a/hw/vfio/vfio-helpers.h +++ b/hw/vfio/vfio-helpers.h @@ -12,6 +12,8 @@ #ifdef CONFIG_LINUX #include +extern int vfio_kvm_device_fd; + struct vfio_info_cap_header * vfio_get_cap(void *ptr, uint32_t cap_offset, uint16_t id); struct vfio_info_cap_header * diff --git a/include/hw/vfio/vfio-common.h b/include/hw/vfio/vfio-common.h index 2065c2f9e4..06178cf282 100644 --- a/include/hw/vfio/vfio-common.h +++ b/include/hw/vfio/vfio-common.h @@ -132,7 +132,6 @@ VFIODevice *vfio_get_vfio_device(Object *obj); typedef QLIST_HEAD(VFIODeviceList, VFIODevice) VFIODeviceList; extern VFIODeviceList vfio_device_list; extern const MemoryListener vfio_memory_listener; -extern int vfio_kvm_device_fd; #ifdef CONFIG_LINUX int vfio_get_region_info(VFIODevice *vbasedev, int index, -- cgit 1.4.1 From 11b8b9d53d8b30bf1823e9d2e303c28fe13acf34 Mon Sep 17 00:00:00 2001 From: Cédric Le Goater Date: Wed, 26 Mar 2025 08:51:20 +0100 Subject: vfio: Rename vfio-common.h to vfio-device.h MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit "hw/vfio/vfio-common.h" has been emptied of most of its declarations by the previous changes and the only declarations left are related to VFIODevice. Rename it to "hw/vfio/vfio-device.h" and make the necessary adjustments. Reviewed-by: Zhenzhong Duan Link: https://lore.kernel.org/qemu-devel/20250326075122.1299361-36-clg@redhat.com Signed-off-by: Cédric Le Goater --- backends/iommufd.c | 2 +- hw/vfio/ap.c | 2 +- hw/vfio/ccw.c | 2 +- hw/vfio/container-base.c | 2 +- hw/vfio/container.c | 2 +- hw/vfio/cpr.c | 2 +- hw/vfio/device.c | 2 +- hw/vfio/helpers.c | 2 +- hw/vfio/iommufd.c | 2 +- hw/vfio/listener.c | 2 +- hw/vfio/migration-multifd.c | 2 +- hw/vfio/migration-multifd.h | 2 +- hw/vfio/migration.c | 2 +- hw/vfio/pci.h | 2 +- hw/vfio/region.c | 4 +- include/hw/s390x/vfio-ccw.h | 2 +- include/hw/vfio/vfio-common.h | 149 ---------------------------------------- include/hw/vfio/vfio-device.h | 149 ++++++++++++++++++++++++++++++++++++++++ include/hw/vfio/vfio-platform.h | 2 +- 19 files changed, 167 insertions(+), 167 deletions(-) delete mode 100644 include/hw/vfio/vfio-common.h create mode 100644 include/hw/vfio/vfio-device.h (limited to 'hw/vfio/helpers.c') diff --git a/backends/iommufd.c b/backends/iommufd.c index d57da44755..9587e4d99b 100644 --- a/backends/iommufd.c +++ b/backends/iommufd.c @@ -18,7 +18,7 @@ #include "qemu/error-report.h" #include "monitor/monitor.h" #include "trace.h" -#include "hw/vfio/vfio-common.h" +#include "hw/vfio/vfio-device.h" #include #include diff --git a/hw/vfio/ap.c b/hw/vfio/ap.c index d6575d7c44..9e2251437e 100644 --- a/hw/vfio/ap.c +++ b/hw/vfio/ap.c @@ -15,7 +15,7 @@ #include #include #include "qapi/error.h" -#include "hw/vfio/vfio-common.h" +#include "hw/vfio/vfio-device.h" #include "system/iommufd.h" #include "hw/s390x/ap-device.h" #include "qemu/error-report.h" diff --git a/hw/vfio/ccw.c b/hw/vfio/ccw.c index 29e804e122..d0713ca4c7 100644 --- a/hw/vfio/ccw.c +++ b/hw/vfio/ccw.c @@ -21,7 +21,7 @@ #include #include "qapi/error.h" -#include "hw/vfio/vfio-common.h" +#include "hw/vfio/vfio-device.h" #include "system/iommufd.h" #include "hw/s390x/s390-ccw.h" #include "hw/s390x/vfio-ccw.h" diff --git a/hw/vfio/container-base.c b/hw/vfio/container-base.c index fb86bc41bf..c037bafe21 100644 --- a/hw/vfio/container-base.c +++ b/hw/vfio/container-base.c @@ -19,7 +19,7 @@ #include "qapi/error.h" #include "qemu/error-report.h" #include "hw/vfio/vfio-container-base.h" -#include "hw/vfio/vfio-common.h" /* vfio_reset_handler */ +#include "hw/vfio/vfio-device.h" /* vfio_reset_handler */ #include "system/reset.h" #include "vfio-helpers.h" diff --git a/hw/vfio/container.c b/hw/vfio/container.c index e4fcb1ad8b..ef14046072 100644 --- a/hw/vfio/container.c +++ b/hw/vfio/container.c @@ -22,7 +22,7 @@ #include #include -#include "hw/vfio/vfio-common.h" +#include "hw/vfio/vfio-device.h" #include "system/address-spaces.h" #include "system/memory.h" #include "system/ram_addr.h" diff --git a/hw/vfio/cpr.c b/hw/vfio/cpr.c index 696987006b..3214184f97 100644 --- a/hw/vfio/cpr.c +++ b/hw/vfio/cpr.c @@ -6,7 +6,7 @@ */ #include "qemu/osdep.h" -#include "hw/vfio/vfio-common.h" +#include "hw/vfio/vfio-device.h" #include "migration/misc.h" #include "qapi/error.h" #include "system/runstate.h" diff --git a/hw/vfio/device.c b/hw/vfio/device.c index e122c797c2..543750c3b1 100644 --- a/hw/vfio/device.c +++ b/hw/vfio/device.c @@ -21,7 +21,7 @@ #include "qemu/osdep.h" #include -#include "hw/vfio/vfio-common.h" +#include "hw/vfio/vfio-device.h" #include "hw/vfio/pci.h" #include "hw/hw.h" #include "trace.h" diff --git a/hw/vfio/helpers.c b/hw/vfio/helpers.c index 48bd61d528..d0dbab1d17 100644 --- a/hw/vfio/helpers.c +++ b/hw/vfio/helpers.c @@ -23,7 +23,7 @@ #include #include "system/kvm.h" -#include "hw/vfio/vfio-common.h" +#include "hw/vfio/vfio-device.h" #include "hw/hw.h" #include "qapi/error.h" #include "vfio-helpers.h" diff --git a/hw/vfio/iommufd.c b/hw/vfio/iommufd.c index e47720247d..48db105422 100644 --- a/hw/vfio/iommufd.c +++ b/hw/vfio/iommufd.c @@ -15,7 +15,7 @@ #include #include -#include "hw/vfio/vfio-common.h" +#include "hw/vfio/vfio-device.h" #include "qemu/error-report.h" #include "trace.h" #include "qapi/error.h" diff --git a/hw/vfio/listener.c b/hw/vfio/listener.c index d19674503c..6f77e18a7a 100644 --- a/hw/vfio/listener.c +++ b/hw/vfio/listener.c @@ -25,7 +25,7 @@ #endif #include -#include "hw/vfio/vfio-common.h" +#include "hw/vfio/vfio-device.h" #include "hw/vfio/pci.h" #include "system/address-spaces.h" #include "system/memory.h" diff --git a/hw/vfio/migration-multifd.c b/hw/vfio/migration-multifd.c index a3005226b9..850a319488 100644 --- a/hw/vfio/migration-multifd.c +++ b/hw/vfio/migration-multifd.c @@ -10,7 +10,7 @@ */ #include "qemu/osdep.h" -#include "hw/vfio/vfio-common.h" +#include "hw/vfio/vfio-device.h" #include "migration/misc.h" #include "qapi/error.h" #include "qemu/bswap.h" diff --git a/hw/vfio/migration-multifd.h b/hw/vfio/migration-multifd.h index a664051eb8..0bab63211d 100644 --- a/hw/vfio/migration-multifd.h +++ b/hw/vfio/migration-multifd.h @@ -12,7 +12,7 @@ #ifndef HW_VFIO_MIGRATION_MULTIFD_H #define HW_VFIO_MIGRATION_MULTIFD_H -#include "hw/vfio/vfio-common.h" +#include "hw/vfio/vfio-device.h" bool vfio_multifd_setup(VFIODevice *vbasedev, bool alloc_multifd, Error **errp); void vfio_multifd_cleanup(VFIODevice *vbasedev); diff --git a/hw/vfio/migration.c b/hw/vfio/migration.c index 4da0526325..1dceab1b19 100644 --- a/hw/vfio/migration.c +++ b/hw/vfio/migration.c @@ -16,7 +16,7 @@ #include #include "system/runstate.h" -#include "hw/vfio/vfio-common.h" +#include "hw/vfio/vfio-device.h" #include "hw/vfio/vfio-migration.h" #include "migration/misc.h" #include "migration/savevm.h" diff --git a/hw/vfio/pci.h b/hw/vfio/pci.h index 801ea445b8..f835b1dbc2 100644 --- a/hw/vfio/pci.h +++ b/hw/vfio/pci.h @@ -14,7 +14,7 @@ #include "system/memory.h" #include "hw/pci/pci_device.h" -#include "hw/vfio/vfio-common.h" +#include "hw/vfio/vfio-device.h" #include "hw/vfio/vfio-region.h" #include "qemu/event_notifier.h" #include "qemu/queue.h" diff --git a/hw/vfio/region.c b/hw/vfio/region.c index 9049143abf..010b5241e1 100644 --- a/hw/vfio/region.c +++ b/hw/vfio/region.c @@ -21,8 +21,8 @@ #include "qemu/osdep.h" #include -#include "hw/vfio/vfio-common.h" -#include "hw/vfio/pci.h" +#include "hw/vfio/vfio-region.h" +#include "hw/vfio/vfio-device.h" #include "hw/hw.h" #include "trace.h" #include "qapi/error.h" diff --git a/include/hw/s390x/vfio-ccw.h b/include/hw/s390x/vfio-ccw.h index 4209d27657..1e0922dca1 100644 --- a/include/hw/s390x/vfio-ccw.h +++ b/include/hw/s390x/vfio-ccw.h @@ -14,7 +14,7 @@ #ifndef HW_VFIO_CCW_H #define HW_VFIO_CCW_H -#include "hw/vfio/vfio-common.h" +#include "hw/vfio/vfio-device.h" #include "hw/s390x/s390-ccw.h" #include "hw/s390x/ccw-device.h" #include "qom/object.h" diff --git a/include/hw/vfio/vfio-common.h b/include/hw/vfio/vfio-common.h deleted file mode 100644 index 92381c6160..0000000000 --- a/include/hw/vfio/vfio-common.h +++ /dev/null @@ -1,149 +0,0 @@ -/* - * common header for vfio based device assignment support - * - * Copyright Red Hat, Inc. 2012 - * - * Authors: - * Alex Williamson - * - * This work is licensed under the terms of the GNU GPL, version 2. See - * the COPYING file in the top-level directory. - * - * Based on qemu-kvm device-assignment: - * Adapted for KVM by Qumranet. - * Copyright (c) 2007, Neocleus, Alex Novik (alex@neocleus.com) - * Copyright (c) 2007, Neocleus, Guy Zana (guy@neocleus.com) - * Copyright (C) 2008, Qumranet, Amit Shah (amit.shah@qumranet.com) - * Copyright (C) 2008, Red Hat, Amit Shah (amit.shah@redhat.com) - * Copyright (C) 2008, IBM, Muli Ben-Yehuda (muli@il.ibm.com) - */ - -#ifndef HW_VFIO_VFIO_COMMON_H -#define HW_VFIO_VFIO_COMMON_H - -#include "system/memory.h" -#include "qemu/queue.h" -#ifdef CONFIG_LINUX -#include -#endif -#include "system/system.h" -#include "hw/vfio/vfio-container-base.h" -#include "system/host_iommu_device.h" -#include "system/iommufd.h" - -#define VFIO_MSG_PREFIX "vfio %s: " - -enum { - VFIO_DEVICE_TYPE_PCI = 0, - VFIO_DEVICE_TYPE_PLATFORM = 1, - VFIO_DEVICE_TYPE_CCW = 2, - VFIO_DEVICE_TYPE_AP = 3, -}; - -typedef struct VFIODeviceOps VFIODeviceOps; -typedef struct VFIOMigration VFIOMigration; - -typedef struct IOMMUFDBackend IOMMUFDBackend; -typedef struct VFIOIOASHwpt VFIOIOASHwpt; - -typedef struct VFIODevice { - QLIST_ENTRY(VFIODevice) next; - QLIST_ENTRY(VFIODevice) container_next; - QLIST_ENTRY(VFIODevice) global_next; - struct VFIOGroup *group; - VFIOContainerBase *bcontainer; - char *sysfsdev; - char *name; - DeviceState *dev; - int fd; - int type; - bool mdev; - bool reset_works; - bool needs_reset; - bool no_mmap; - bool ram_block_discard_allowed; - OnOffAuto enable_migration; - OnOffAuto migration_multifd_transfer; - bool migration_events; - VFIODeviceOps *ops; - unsigned int num_irqs; - unsigned int num_regions; - unsigned int flags; - VFIOMigration *migration; - Error *migration_blocker; - OnOffAuto pre_copy_dirty_page_tracking; - OnOffAuto device_dirty_page_tracking; - bool dirty_pages_supported; - bool dirty_tracking; /* Protected by BQL */ - bool iommu_dirty_tracking; - HostIOMMUDevice *hiod; - int devid; - IOMMUFDBackend *iommufd; - VFIOIOASHwpt *hwpt; - QLIST_ENTRY(VFIODevice) hwpt_next; -} VFIODevice; - -struct VFIODeviceOps { - void (*vfio_compute_needs_reset)(VFIODevice *vdev); - int (*vfio_hot_reset_multi)(VFIODevice *vdev); - void (*vfio_eoi)(VFIODevice *vdev); - Object *(*vfio_get_object)(VFIODevice *vdev); - - /** - * @vfio_save_config - * - * Save device config state - * - * @vdev: #VFIODevice for which to save the config - * @f: #QEMUFile where to send the data - * @errp: pointer to Error*, to store an error if it happens. - * - * Returns zero to indicate success and negative for error - */ - int (*vfio_save_config)(VFIODevice *vdev, QEMUFile *f, Error **errp); - - /** - * @vfio_load_config - * - * Load device config state - * - * @vdev: #VFIODevice for which to load the config - * @f: #QEMUFile where to get the data - * - * Returns zero to indicate success and negative for error - */ - int (*vfio_load_config)(VFIODevice *vdev, QEMUFile *f); -}; - -void vfio_disable_irqindex(VFIODevice *vbasedev, int index); -void vfio_unmask_single_irqindex(VFIODevice *vbasedev, int index); -void vfio_mask_single_irqindex(VFIODevice *vbasedev, int index); -bool vfio_set_irq_signaling(VFIODevice *vbasedev, int index, int subindex, - int action, int fd, Error **errp); - -void vfio_reset_handler(void *opaque); -bool vfio_device_is_mdev(VFIODevice *vbasedev); -bool vfio_device_hiod_realize(VFIODevice *vbasedev, Error **errp); -bool vfio_attach_device(char *name, VFIODevice *vbasedev, - AddressSpace *as, Error **errp); -void vfio_detach_device(VFIODevice *vbasedev); -VFIODevice *vfio_get_vfio_device(Object *obj); - -typedef QLIST_HEAD(VFIODeviceList, VFIODevice) VFIODeviceList; -extern VFIODeviceList vfio_device_list; - -#ifdef CONFIG_LINUX -int vfio_get_region_info(VFIODevice *vbasedev, int index, - struct vfio_region_info **info); -int vfio_get_dev_region_info(VFIODevice *vbasedev, uint32_t type, - uint32_t subtype, struct vfio_region_info **info); -bool vfio_has_region_cap(VFIODevice *vbasedev, int region, uint16_t cap_type); -#endif - -/* Returns 0 on success, or a negative errno. */ -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-device.h b/include/hw/vfio/vfio-device.h new file mode 100644 index 0000000000..cfbe254e31 --- /dev/null +++ b/include/hw/vfio/vfio-device.h @@ -0,0 +1,149 @@ +/* + * VFIO Device interface + * + * Copyright Red Hat, Inc. 2012 + * + * Authors: + * Alex Williamson + * + * This work is licensed under the terms of the GNU GPL, version 2. See + * the COPYING file in the top-level directory. + * + * Based on qemu-kvm device-assignment: + * Adapted for KVM by Qumranet. + * Copyright (c) 2007, Neocleus, Alex Novik (alex@neocleus.com) + * Copyright (c) 2007, Neocleus, Guy Zana (guy@neocleus.com) + * Copyright (C) 2008, Qumranet, Amit Shah (amit.shah@qumranet.com) + * Copyright (C) 2008, Red Hat, Amit Shah (amit.shah@redhat.com) + * Copyright (C) 2008, IBM, Muli Ben-Yehuda (muli@il.ibm.com) + */ + +#ifndef HW_VFIO_VFIO_COMMON_H +#define HW_VFIO_VFIO_COMMON_H + +#include "system/memory.h" +#include "qemu/queue.h" +#ifdef CONFIG_LINUX +#include +#endif +#include "system/system.h" +#include "hw/vfio/vfio-container-base.h" +#include "system/host_iommu_device.h" +#include "system/iommufd.h" + +#define VFIO_MSG_PREFIX "vfio %s: " + +enum { + VFIO_DEVICE_TYPE_PCI = 0, + VFIO_DEVICE_TYPE_PLATFORM = 1, + VFIO_DEVICE_TYPE_CCW = 2, + VFIO_DEVICE_TYPE_AP = 3, +}; + +typedef struct VFIODeviceOps VFIODeviceOps; +typedef struct VFIOMigration VFIOMigration; + +typedef struct IOMMUFDBackend IOMMUFDBackend; +typedef struct VFIOIOASHwpt VFIOIOASHwpt; + +typedef struct VFIODevice { + QLIST_ENTRY(VFIODevice) next; + QLIST_ENTRY(VFIODevice) container_next; + QLIST_ENTRY(VFIODevice) global_next; + struct VFIOGroup *group; + VFIOContainerBase *bcontainer; + char *sysfsdev; + char *name; + DeviceState *dev; + int fd; + int type; + bool mdev; + bool reset_works; + bool needs_reset; + bool no_mmap; + bool ram_block_discard_allowed; + OnOffAuto enable_migration; + OnOffAuto migration_multifd_transfer; + bool migration_events; + VFIODeviceOps *ops; + unsigned int num_irqs; + unsigned int num_regions; + unsigned int flags; + VFIOMigration *migration; + Error *migration_blocker; + OnOffAuto pre_copy_dirty_page_tracking; + OnOffAuto device_dirty_page_tracking; + bool dirty_pages_supported; + bool dirty_tracking; /* Protected by BQL */ + bool iommu_dirty_tracking; + HostIOMMUDevice *hiod; + int devid; + IOMMUFDBackend *iommufd; + VFIOIOASHwpt *hwpt; + QLIST_ENTRY(VFIODevice) hwpt_next; +} VFIODevice; + +struct VFIODeviceOps { + void (*vfio_compute_needs_reset)(VFIODevice *vdev); + int (*vfio_hot_reset_multi)(VFIODevice *vdev); + void (*vfio_eoi)(VFIODevice *vdev); + Object *(*vfio_get_object)(VFIODevice *vdev); + + /** + * @vfio_save_config + * + * Save device config state + * + * @vdev: #VFIODevice for which to save the config + * @f: #QEMUFile where to send the data + * @errp: pointer to Error*, to store an error if it happens. + * + * Returns zero to indicate success and negative for error + */ + int (*vfio_save_config)(VFIODevice *vdev, QEMUFile *f, Error **errp); + + /** + * @vfio_load_config + * + * Load device config state + * + * @vdev: #VFIODevice for which to load the config + * @f: #QEMUFile where to get the data + * + * Returns zero to indicate success and negative for error + */ + int (*vfio_load_config)(VFIODevice *vdev, QEMUFile *f); +}; + +void vfio_disable_irqindex(VFIODevice *vbasedev, int index); +void vfio_unmask_single_irqindex(VFIODevice *vbasedev, int index); +void vfio_mask_single_irqindex(VFIODevice *vbasedev, int index); +bool vfio_set_irq_signaling(VFIODevice *vbasedev, int index, int subindex, + int action, int fd, Error **errp); + +void vfio_reset_handler(void *opaque); +bool vfio_device_is_mdev(VFIODevice *vbasedev); +bool vfio_device_hiod_realize(VFIODevice *vbasedev, Error **errp); +bool vfio_attach_device(char *name, VFIODevice *vbasedev, + AddressSpace *as, Error **errp); +void vfio_detach_device(VFIODevice *vbasedev); +VFIODevice *vfio_get_vfio_device(Object *obj); + +typedef QLIST_HEAD(VFIODeviceList, VFIODevice) VFIODeviceList; +extern VFIODeviceList vfio_device_list; + +#ifdef CONFIG_LINUX +int vfio_get_region_info(VFIODevice *vbasedev, int index, + struct vfio_region_info **info); +int vfio_get_dev_region_info(VFIODevice *vbasedev, uint32_t type, + uint32_t subtype, struct vfio_region_info **info); +bool vfio_has_region_cap(VFIODevice *vbasedev, int region, uint16_t cap_type); +#endif + +/* Returns 0 on success, or a negative errno. */ +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-platform.h b/include/hw/vfio/vfio-platform.h index 3191545717..256d8500b7 100644 --- a/include/hw/vfio/vfio-platform.h +++ b/include/hw/vfio/vfio-platform.h @@ -17,7 +17,7 @@ #define HW_VFIO_VFIO_PLATFORM_H #include "hw/sysbus.h" -#include "hw/vfio/vfio-common.h" +#include "hw/vfio/vfio-device.h" #include "qemu/event_notifier.h" #include "qemu/queue.h" #include "qom/object.h" -- cgit 1.4.1