master
h 270 lines 8.71 KB
Raw
1 /*
2 * VFIO BASE CONTAINER
3 *
4 * Copyright (C) 2023 Intel Corporation.
5 * Copyright Red Hat, Inc. 2023
6 *
7 * Authors: Yi Liu <yi.l.liu@intel.com>
8 * Eric Auger <eric.auger@redhat.com>
9 *
10 * SPDX-License-Identifier: GPL-2.0-or-later
11 */
12
13 #ifndef HW_VFIO_VFIO_CONTAINER_H
14 #define HW_VFIO_VFIO_CONTAINER_H
15
16 #include "system/memory.h"
17
18 typedef struct VFIODevice VFIODevice;
19 typedef struct VFIOIOMMUClass VFIOIOMMUClass;
20
21 typedef struct {
22 unsigned long *bitmap;
23 hwaddr size;
24 hwaddr pages;
25 } VFIOBitmap;
26
27 typedef struct VFIOAddressSpace {
28 AddressSpace *as;
29 QLIST_HEAD(, VFIOContainer) containers;
30 QLIST_ENTRY(VFIOAddressSpace) list;
31 } VFIOAddressSpace;
32
33 /*
34 * This is the base object for vfio container backends
35 */
36 struct VFIOContainer {
37 Object parent_obj;
38
39 VFIOAddressSpace *space;
40 MemoryListener listener;
41 Error *error;
42 bool initialized;
43 uint64_t dirty_pgsizes;
44 uint64_t max_dirty_bitmap_size;
45 unsigned long pgsizes;
46 unsigned int dma_max_mappings;
47 bool dirty_pages_supported;
48 bool dirty_pages_started; /* Protected by BQL */
49 QLIST_HEAD(, VFIOGuestIOMMU) giommu_list;
50 QLIST_HEAD(, VFIORamDiscardListener) vrdl_list;
51 QLIST_ENTRY(VFIOContainer) next;
52 QLIST_HEAD(, VFIODevice) device_list;
53 GList *iova_ranges;
54 NotifierWithReturn cpr_reboot_notifier;
55 bool bypass_ro;
56 };
57
58 #define TYPE_VFIO_IOMMU "vfio-iommu"
59 OBJECT_DECLARE_TYPE(VFIOContainer, VFIOIOMMUClass, VFIO_IOMMU)
60
61 typedef struct VFIOGuestIOMMU {
62 VFIOContainer *bcontainer;
63 IOMMUMemoryRegion *iommu_mr;
64 hwaddr iommu_offset;
65 IOMMUNotifier n;
66 QLIST_ENTRY(VFIOGuestIOMMU) giommu_next;
67 } VFIOGuestIOMMU;
68
69 typedef struct VFIORamDiscardListener {
70 VFIOContainer *bcontainer;
71 MemoryRegion *mr;
72 hwaddr offset_within_address_space;
73 hwaddr size;
74 uint64_t granularity;
75 RamDiscardListener listener;
76 QLIST_ENTRY(VFIORamDiscardListener) next;
77 } VFIORamDiscardListener;
78
79 VFIOAddressSpace *vfio_address_space_get(AddressSpace *as);
80 void vfio_address_space_put(VFIOAddressSpace *space);
81 void vfio_address_space_insert(VFIOAddressSpace *space,
82 VFIOContainer *bcontainer);
83
84 int vfio_container_dma_map(VFIOContainer *bcontainer,
85 hwaddr iova, uint64_t size,
86 void *vaddr, bool readonly, MemoryRegion *mr);
87 int vfio_container_dma_unmap(VFIOContainer *bcontainer,
88 hwaddr iova, uint64_t size,
89 IOMMUTLBEntry *iotlb, bool unmap_all);
90 bool vfio_container_add_section_window(VFIOContainer *bcontainer,
91 MemoryRegionSection *section,
92 Error **errp);
93 void vfio_container_del_section_window(VFIOContainer *bcontainer,
94 MemoryRegionSection *section);
95 int vfio_container_set_dirty_page_tracking(VFIOContainer *bcontainer,
96 bool start, Error **errp);
97 bool vfio_container_dirty_tracking_is_started(
98 const VFIOContainer *bcontainer);
99 bool vfio_container_devices_dirty_tracking_is_supported(
100 const VFIOContainer *bcontainer);
101 int vfio_container_query_dirty_bitmap(const VFIOContainer *bcontainer,
102 uint64_t iova, uint64_t size,
103 uint64_t backend_flag,
104 hwaddr translated_addr,
105 Error **errp);
106
107 GList *vfio_container_get_iova_ranges(const VFIOContainer *bcontainer);
108
109 static inline uint64_t
110 vfio_container_get_page_size_mask(const VFIOContainer *bcontainer)
111 {
112 assert(bcontainer);
113 return bcontainer->pgsizes;
114 }
115
116 #define TYPE_VFIO_IOMMU_LEGACY TYPE_VFIO_IOMMU "-legacy"
117 #define TYPE_VFIO_IOMMU_SPAPR TYPE_VFIO_IOMMU "-spapr"
118 #define TYPE_VFIO_IOMMU_IOMMUFD TYPE_VFIO_IOMMU "-iommufd"
119 #define TYPE_VFIO_IOMMU_USER TYPE_VFIO_IOMMU "-user"
120
121 struct VFIOIOMMUClass {
122 ObjectClass parent_class;
123
124 /**
125 * @setup
126 *
127 * Perform basic setup of the container, including configuring IOMMU
128 * capabilities, IOVA ranges, supported page sizes, etc.
129 *
130 * @bcontainer: #VFIOContainer
131 * @errp: pointer to Error*, to store an error if it happens.
132 *
133 * Returns true to indicate success and false for error.
134 */
135 bool (*setup)(VFIOContainer *bcontainer, Error **errp);
136
137 /**
138 * @listener_begin
139 *
140 * Called at the beginning of an address space update transaction.
141 * See #MemoryListener.
142 *
143 * @bcontainer: #VFIOContainer
144 */
145 void (*listener_begin)(VFIOContainer *bcontainer);
146
147 /**
148 * @listener_commit
149 *
150 * Called at the end of an address space update transaction,
151 * See #MemoryListener.
152 *
153 * @bcontainer: #VFIOContainer
154 */
155 void (*listener_commit)(VFIOContainer *bcontainer);
156
157 /**
158 * @dma_map
159 *
160 * Map an address range into the container. Note that the memory region is
161 * referenced within an RCU read lock region across this call.
162 *
163 * @bcontainer: #VFIOContainer to use
164 * @iova: start address to map
165 * @size: size of the range to map
166 * @vaddr: process virtual address of mapping
167 * @readonly: true if mapping should be readonly
168 * @mr: the memory region for this mapping
169 *
170 * Returns 0 to indicate success and -errno otherwise.
171 */
172 int (*dma_map)(const VFIOContainer *bcontainer,
173 hwaddr iova, uint64_t size,
174 void *vaddr, bool readonly, MemoryRegion *mr);
175 /**
176 * @dma_unmap
177 *
178 * Unmap an address range from the container.
179 *
180 * @bcontainer: #VFIOContainer to use for unmap
181 * @iova: start address to unmap
182 * @size: size of the range to unmap
183 * @iotlb: The IOMMU TLB mapping entry (or NULL)
184 * @unmap_all: if set, unmap the entire address space
185 *
186 * Returns 0 to indicate success and -errno otherwise.
187 */
188 int (*dma_unmap)(const VFIOContainer *bcontainer,
189 hwaddr iova, uint64_t size,
190 IOMMUTLBEntry *iotlb, bool unmap_all);
191
192
193 /**
194 * @attach_device
195 *
196 * Associate the given device with a container and do some related
197 * initialization of the device context.
198 *
199 * @name: name of the device
200 * @vbasedev: the device
201 * @as: address space to use
202 * @errp: pointer to Error*, to store an error if it happens.
203 *
204 * Returns true to indicate success and false for error.
205 */
206 bool (*attach_device)(const char *name, VFIODevice *vbasedev,
207 AddressSpace *as, Error **errp);
208
209 /*
210 * @detach_device
211 *
212 * Detach the given device from its container and clean up any necessary
213 * state.
214 *
215 * @vbasedev: the device to disassociate
216 */
217 void (*detach_device)(VFIODevice *vbasedev);
218
219 /* migration feature */
220
221 /**
222 * @set_dirty_page_tracking
223 *
224 * Start or stop dirty pages tracking on VFIO container
225 *
226 * @bcontainer: #VFIOContainer on which to de/activate dirty
227 * page tracking
228 * @start: indicates whether to start or stop dirty pages tracking
229 * @errp: pointer to Error*, to store an error if it happens.
230 *
231 * Returns zero to indicate success and negative for error.
232 */
233 int (*set_dirty_page_tracking)(const VFIOContainer *bcontainer,
234 bool start, Error **errp);
235 /**
236 * @query_dirty_bitmap
237 *
238 * Get bitmap of dirty pages from container
239 *
240 * @bcontainer: #VFIOContainer from which to get dirty pages
241 * @vbmap: #VFIOBitmap internal bitmap structure
242 * @iova: iova base address
243 * @size: size of iova range
244 * @backend_flag: flags for backend, opaque to upper layer container
245 * @errp: pointer to Error*, to store an error if it happens.
246 *
247 * Returns zero to indicate success and negative for error.
248 */
249 int (*query_dirty_bitmap)(const VFIOContainer *bcontainer,
250 VFIOBitmap *vbmap, hwaddr iova, hwaddr size,
251 uint64_t backend_flag, Error **errp);
252 /* PCI specific */
253 int (*pci_hot_reset)(VFIODevice *vbasedev, bool single);
254
255 /* SPAPR specific */
256 bool (*add_window)(VFIOContainer *bcontainer,
257 MemoryRegionSection *section,
258 Error **errp);
259 void (*del_window)(VFIOContainer *bcontainer,
260 MemoryRegionSection *section);
261 void (*release)(VFIOContainer *bcontainer);
262 };
263
264 VFIORamDiscardListener *vfio_find_ram_discard_listener(
265 VFIOContainer *bcontainer, const MemoryRegionSection *section);
266
267 void vfio_container_region_add(VFIOContainer *bcontainer,
268 MemoryRegionSection *section, bool cpr_remap);
269
270 #endif /* HW_VFIO_VFIO_CONTAINER_H */