1f61dddd7SZhenzhong Duan /* 2f61dddd7SZhenzhong Duan * VFIO BASE CONTAINER 3f61dddd7SZhenzhong Duan * 4f61dddd7SZhenzhong Duan * Copyright (C) 2023 Intel Corporation. 5f61dddd7SZhenzhong Duan * Copyright Red Hat, Inc. 2023 6f61dddd7SZhenzhong Duan * 7f61dddd7SZhenzhong Duan * Authors: Yi Liu <yi.l.liu@intel.com> 8f61dddd7SZhenzhong Duan * Eric Auger <eric.auger@redhat.com> 9f61dddd7SZhenzhong Duan * 10f61dddd7SZhenzhong Duan * SPDX-License-Identifier: GPL-2.0-or-later 11f61dddd7SZhenzhong Duan */ 12f61dddd7SZhenzhong Duan 13f61dddd7SZhenzhong Duan #ifndef HW_VFIO_VFIO_CONTAINER_BASE_H 14f61dddd7SZhenzhong Duan #define HW_VFIO_VFIO_CONTAINER_BASE_H 15f61dddd7SZhenzhong Duan 16f61dddd7SZhenzhong Duan #include "exec/memory.h" 17f61dddd7SZhenzhong Duan 18f61dddd7SZhenzhong Duan typedef struct VFIODevice VFIODevice; 19fdaa774eSCédric Le Goater typedef struct VFIOIOMMUClass VFIOIOMMUClass; 20f61dddd7SZhenzhong Duan 21f61dddd7SZhenzhong Duan typedef struct { 22f61dddd7SZhenzhong Duan unsigned long *bitmap; 23f61dddd7SZhenzhong Duan hwaddr size; 24f61dddd7SZhenzhong Duan hwaddr pages; 25f61dddd7SZhenzhong Duan } VFIOBitmap; 26f61dddd7SZhenzhong Duan 27e5597063SEric Auger typedef struct VFIOAddressSpace { 28e5597063SEric Auger AddressSpace *as; 29e5597063SEric Auger QLIST_HEAD(, VFIOContainerBase) containers; 30e5597063SEric Auger QLIST_ENTRY(VFIOAddressSpace) list; 31e5597063SEric Auger } VFIOAddressSpace; 32e5597063SEric Auger 33f61dddd7SZhenzhong Duan /* 34f61dddd7SZhenzhong Duan * This is the base object for vfio container backends 35f61dddd7SZhenzhong Duan */ 36f61dddd7SZhenzhong Duan typedef struct VFIOContainerBase { 37*504d297eSCédric Le Goater Object parent; 38fdaa774eSCédric Le Goater const VFIOIOMMUClass *ops; 39e5597063SEric Auger VFIOAddressSpace *space; 40c7b313d3SEric Auger MemoryListener listener; 41c7b313d3SEric Auger Error *error; 42c7b313d3SEric Auger bool initialized; 434d6b9501SEric Auger uint64_t dirty_pgsizes; 444d6b9501SEric Auger uint64_t max_dirty_bitmap_size; 457ab1cb74SEric Auger unsigned long pgsizes; 467ab1cb74SEric Auger unsigned int dma_max_mappings; 47bb424490SEric Auger bool dirty_pages_supported; 48dddf83abSEric Auger QLIST_HEAD(, VFIOGuestIOMMU) giommu_list; 49dc74a4b0SZhenzhong Duan QLIST_HEAD(, VFIORamDiscardListener) vrdl_list; 50e5597063SEric Auger QLIST_ENTRY(VFIOContainerBase) next; 513e6015d1SZhenzhong Duan QLIST_HEAD(, VFIODevice) device_list; 52f79baf8cSZhenzhong Duan GList *iova_ranges; 530cb51c18SSteve Sistare NotifierWithReturn cpr_reboot_notifier; 54f61dddd7SZhenzhong Duan } VFIOContainerBase; 55f61dddd7SZhenzhong Duan 56dddf83abSEric Auger typedef struct VFIOGuestIOMMU { 57dddf83abSEric Auger VFIOContainerBase *bcontainer; 58dddf83abSEric Auger IOMMUMemoryRegion *iommu_mr; 59dddf83abSEric Auger hwaddr iommu_offset; 60dddf83abSEric Auger IOMMUNotifier n; 61dddf83abSEric Auger QLIST_ENTRY(VFIOGuestIOMMU) giommu_next; 62dddf83abSEric Auger } VFIOGuestIOMMU; 63dddf83abSEric Auger 64dc74a4b0SZhenzhong Duan typedef struct VFIORamDiscardListener { 65dc74a4b0SZhenzhong Duan VFIOContainerBase *bcontainer; 66dc74a4b0SZhenzhong Duan MemoryRegion *mr; 67dc74a4b0SZhenzhong Duan hwaddr offset_within_address_space; 68dc74a4b0SZhenzhong Duan hwaddr size; 69dc74a4b0SZhenzhong Duan uint64_t granularity; 70dc74a4b0SZhenzhong Duan RamDiscardListener listener; 71dc74a4b0SZhenzhong Duan QLIST_ENTRY(VFIORamDiscardListener) next; 72dc74a4b0SZhenzhong Duan } VFIORamDiscardListener; 73dc74a4b0SZhenzhong Duan 74b08501a9SEric Auger int vfio_container_dma_map(VFIOContainerBase *bcontainer, 75b08501a9SEric Auger hwaddr iova, ram_addr_t size, 76b08501a9SEric Auger void *vaddr, bool readonly); 77b08501a9SEric Auger int vfio_container_dma_unmap(VFIOContainerBase *bcontainer, 78b08501a9SEric Auger hwaddr iova, ram_addr_t size, 79b08501a9SEric Auger IOMMUTLBEntry *iotlb); 8033e4c22fSZhenzhong Duan bool vfio_container_add_section_window(VFIOContainerBase *bcontainer, 81233309e8SZhenzhong Duan MemoryRegionSection *section, 82233309e8SZhenzhong Duan Error **errp); 83233309e8SZhenzhong Duan void vfio_container_del_section_window(VFIOContainerBase *bcontainer, 84233309e8SZhenzhong Duan MemoryRegionSection *section); 85bb424490SEric Auger int vfio_container_set_dirty_page_tracking(VFIOContainerBase *bcontainer, 86836bb308SCédric Le Goater bool start, Error **errp); 874517c33cSZhenzhong Duan int vfio_container_query_dirty_bitmap(const VFIOContainerBase *bcontainer, 882da5f9e4SCédric Le Goater VFIOBitmap *vbmap, hwaddr iova, hwaddr size, Error **errp); 89b08501a9SEric Auger 90ed2f7f80SZhenzhong Duan void vfio_container_init(VFIOContainerBase *bcontainer, 91fdaa774eSCédric Le Goater const VFIOIOMMUClass *ops); 92ed2f7f80SZhenzhong Duan void vfio_container_destroy(VFIOContainerBase *bcontainer); 93ed2f7f80SZhenzhong Duan 94fdaa774eSCédric Le Goater 95fdaa774eSCédric Le Goater #define TYPE_VFIO_IOMMU "vfio-iommu" 969812feefSCédric Le Goater #define TYPE_VFIO_IOMMU_LEGACY TYPE_VFIO_IOMMU "-legacy" 97f221f641SCédric Le Goater #define TYPE_VFIO_IOMMU_SPAPR TYPE_VFIO_IOMMU "-spapr" 98ce5f6d49SCédric Le Goater #define TYPE_VFIO_IOMMU_IOMMUFD TYPE_VFIO_IOMMU "-iommufd" 99fdaa774eSCédric Le Goater 100*504d297eSCédric Le Goater OBJECT_DECLARE_TYPE(VFIOContainerBase, VFIOIOMMUClass, VFIO_IOMMU) 101fdaa774eSCédric Le Goater 102fdaa774eSCédric Le Goater struct VFIOIOMMUClass { 103*504d297eSCédric Le Goater ObjectClass parent_class; 104fdaa774eSCédric Le Goater 105a7fd91b8SZhenzhong Duan /* Properties */ 106a7fd91b8SZhenzhong Duan const char *hiod_typename; 107a7fd91b8SZhenzhong Duan 108f61dddd7SZhenzhong Duan /* basic feature */ 10935b25cf4SZhenzhong Duan bool (*setup)(VFIOContainerBase *bcontainer, Error **errp); 1104517c33cSZhenzhong Duan int (*dma_map)(const VFIOContainerBase *bcontainer, 111f61dddd7SZhenzhong Duan hwaddr iova, ram_addr_t size, 112f61dddd7SZhenzhong Duan void *vaddr, bool readonly); 1134517c33cSZhenzhong Duan int (*dma_unmap)(const VFIOContainerBase *bcontainer, 114f61dddd7SZhenzhong Duan hwaddr iova, ram_addr_t size, 115f61dddd7SZhenzhong Duan IOMMUTLBEntry *iotlb); 116b7754835SZhenzhong Duan bool (*attach_device)(const char *name, VFIODevice *vbasedev, 117f61dddd7SZhenzhong Duan AddressSpace *as, Error **errp); 118f61dddd7SZhenzhong Duan void (*detach_device)(VFIODevice *vbasedev); 119836bb308SCédric Le Goater 120f61dddd7SZhenzhong Duan /* migration feature */ 121836bb308SCédric Le Goater 122836bb308SCédric Le Goater /** 123836bb308SCédric Le Goater * @set_dirty_page_tracking 124836bb308SCédric Le Goater * 125836bb308SCédric Le Goater * Start or stop dirty pages tracking on VFIO container 126836bb308SCédric Le Goater * 127836bb308SCédric Le Goater * @bcontainer: #VFIOContainerBase on which to de/activate dirty 128836bb308SCédric Le Goater * page tracking 129836bb308SCédric Le Goater * @start: indicates whether to start or stop dirty pages tracking 130836bb308SCédric Le Goater * @errp: pointer to Error*, to store an error if it happens. 131836bb308SCédric Le Goater * 132836bb308SCédric Le Goater * Returns zero to indicate success and negative for error 133836bb308SCédric Le Goater */ 1344517c33cSZhenzhong Duan int (*set_dirty_page_tracking)(const VFIOContainerBase *bcontainer, 135836bb308SCédric Le Goater bool start, Error **errp); 1362da5f9e4SCédric Le Goater /** 1372da5f9e4SCédric Le Goater * @query_dirty_bitmap 1382da5f9e4SCédric Le Goater * 1392da5f9e4SCédric Le Goater * Get bitmap of dirty pages from container 1402da5f9e4SCédric Le Goater * 1412da5f9e4SCédric Le Goater * @bcontainer: #VFIOContainerBase from which to get dirty pages 1422da5f9e4SCédric Le Goater * @vbmap: #VFIOBitmap internal bitmap structure 1432da5f9e4SCédric Le Goater * @iova: iova base address 1442da5f9e4SCédric Le Goater * @size: size of iova range 1452da5f9e4SCédric Le Goater * @errp: pointer to Error*, to store an error if it happens. 1462da5f9e4SCédric Le Goater * 1472da5f9e4SCédric Le Goater * Returns zero to indicate success and negative for error 1482da5f9e4SCédric Le Goater */ 1494517c33cSZhenzhong Duan int (*query_dirty_bitmap)(const VFIOContainerBase *bcontainer, 1502da5f9e4SCédric Le Goater VFIOBitmap *vbmap, hwaddr iova, hwaddr size, Error **errp); 151c328e7e8SZhenzhong Duan /* PCI specific */ 152c328e7e8SZhenzhong Duan int (*pci_hot_reset)(VFIODevice *vbasedev, bool single); 153c328e7e8SZhenzhong Duan 1549b7d38bfSZhenzhong Duan /* SPAPR specific */ 15533e4c22fSZhenzhong Duan bool (*add_window)(VFIOContainerBase *bcontainer, 1569b7d38bfSZhenzhong Duan MemoryRegionSection *section, 1579b7d38bfSZhenzhong Duan Error **errp); 1589b7d38bfSZhenzhong Duan void (*del_window)(VFIOContainerBase *bcontainer, 1599b7d38bfSZhenzhong Duan MemoryRegionSection *section); 160001a013eSCédric Le Goater void (*release)(VFIOContainerBase *bcontainer); 161f61dddd7SZhenzhong Duan }; 162f61dddd7SZhenzhong Duan #endif /* HW_VFIO_VFIO_CONTAINER_BASE_H */ 163