]>
Commit | Line | Data |
---|---|---|
1 | /* | |
2 | * common header for vfio based device assignment support | |
3 | * | |
4 | * Copyright Red Hat, Inc. 2012 | |
5 | * | |
6 | * Authors: | |
7 | * Alex Williamson <alex.williamson@redhat.com> | |
8 | * | |
9 | * This work is licensed under the terms of the GNU GPL, version 2. See | |
10 | * the COPYING file in the top-level directory. | |
11 | * | |
12 | * Based on qemu-kvm device-assignment: | |
13 | * Adapted for KVM by Qumranet. | |
14 | * Copyright (c) 2007, Neocleus, Alex Novik (alex@neocleus.com) | |
15 | * Copyright (c) 2007, Neocleus, Guy Zana (guy@neocleus.com) | |
16 | * Copyright (C) 2008, Qumranet, Amit Shah (amit.shah@qumranet.com) | |
17 | * Copyright (C) 2008, Red Hat, Amit Shah (amit.shah@redhat.com) | |
18 | * Copyright (C) 2008, IBM, Muli Ben-Yehuda (muli@il.ibm.com) | |
19 | */ | |
20 | ||
21 | #ifndef HW_VFIO_VFIO_COMMON_H | |
22 | #define HW_VFIO_VFIO_COMMON_H | |
23 | ||
24 | #include "exec/memory.h" | |
25 | #include "qemu/queue.h" | |
26 | #include "qemu/notify.h" | |
27 | #include "ui/console.h" | |
28 | #include "hw/display/ramfb.h" | |
29 | #ifdef CONFIG_LINUX | |
30 | #include <linux/vfio.h> | |
31 | #endif | |
32 | ||
33 | #define VFIO_MSG_PREFIX "vfio %s: " | |
34 | ||
35 | enum { | |
36 | VFIO_DEVICE_TYPE_PCI = 0, | |
37 | VFIO_DEVICE_TYPE_PLATFORM = 1, | |
38 | VFIO_DEVICE_TYPE_CCW = 2, | |
39 | VFIO_DEVICE_TYPE_AP = 3, | |
40 | }; | |
41 | ||
42 | typedef struct VFIOMmap { | |
43 | MemoryRegion mem; | |
44 | void *mmap; | |
45 | off_t offset; | |
46 | size_t size; | |
47 | } VFIOMmap; | |
48 | ||
49 | typedef struct VFIORegion { | |
50 | struct VFIODevice *vbasedev; | |
51 | off_t fd_offset; /* offset of region within device fd */ | |
52 | MemoryRegion *mem; /* slow, read/write access */ | |
53 | size_t size; | |
54 | uint32_t flags; /* VFIO region flags (rd/wr/mmap) */ | |
55 | uint32_t nr_mmaps; | |
56 | VFIOMmap *mmaps; | |
57 | uint8_t nr; /* cache the region number for debug */ | |
58 | } VFIORegion; | |
59 | ||
60 | typedef struct VFIOAddressSpace { | |
61 | AddressSpace *as; | |
62 | QLIST_HEAD(, VFIOContainer) containers; | |
63 | QLIST_ENTRY(VFIOAddressSpace) list; | |
64 | } VFIOAddressSpace; | |
65 | ||
66 | struct VFIOGroup; | |
67 | ||
68 | typedef struct VFIOContainer { | |
69 | VFIOAddressSpace *space; | |
70 | int fd; /* /dev/vfio/vfio, empowered by the attached groups */ | |
71 | MemoryListener listener; | |
72 | MemoryListener prereg_listener; | |
73 | unsigned iommu_type; | |
74 | int error; | |
75 | bool initialized; | |
76 | unsigned long pgsizes; | |
77 | /* | |
78 | * This assumes the host IOMMU can support only a single | |
79 | * contiguous IOVA window. We may need to generalize that in | |
80 | * future | |
81 | */ | |
82 | QLIST_HEAD(, VFIOGuestIOMMU) giommu_list; | |
83 | QLIST_HEAD(, VFIOHostDMAWindow) hostwin_list; | |
84 | QLIST_HEAD(, VFIOGroup) group_list; | |
85 | QLIST_ENTRY(VFIOContainer) next; | |
86 | } VFIOContainer; | |
87 | ||
88 | typedef struct VFIOGuestIOMMU { | |
89 | VFIOContainer *container; | |
90 | IOMMUMemoryRegion *iommu; | |
91 | hwaddr iommu_offset; | |
92 | IOMMUNotifier n; | |
93 | QLIST_ENTRY(VFIOGuestIOMMU) giommu_next; | |
94 | } VFIOGuestIOMMU; | |
95 | ||
96 | typedef struct VFIOHostDMAWindow { | |
97 | hwaddr min_iova; | |
98 | hwaddr max_iova; | |
99 | uint64_t iova_pgsizes; | |
100 | QLIST_ENTRY(VFIOHostDMAWindow) hostwin_next; | |
101 | } VFIOHostDMAWindow; | |
102 | ||
103 | typedef struct VFIODeviceOps VFIODeviceOps; | |
104 | ||
105 | typedef struct VFIODevice { | |
106 | QLIST_ENTRY(VFIODevice) next; | |
107 | struct VFIOGroup *group; | |
108 | char *sysfsdev; | |
109 | char *name; | |
110 | DeviceState *dev; | |
111 | int fd; | |
112 | int type; | |
113 | bool reset_works; | |
114 | bool needs_reset; | |
115 | bool no_mmap; | |
116 | bool balloon_allowed; | |
117 | VFIODeviceOps *ops; | |
118 | unsigned int num_irqs; | |
119 | unsigned int num_regions; | |
120 | unsigned int flags; | |
121 | } VFIODevice; | |
122 | ||
123 | struct VFIODeviceOps { | |
124 | void (*vfio_compute_needs_reset)(VFIODevice *vdev); | |
125 | int (*vfio_hot_reset_multi)(VFIODevice *vdev); | |
126 | void (*vfio_eoi)(VFIODevice *vdev); | |
127 | }; | |
128 | ||
129 | typedef struct VFIOGroup { | |
130 | int fd; | |
131 | int groupid; | |
132 | VFIOContainer *container; | |
133 | QLIST_HEAD(, VFIODevice) device_list; | |
134 | QLIST_ENTRY(VFIOGroup) next; | |
135 | QLIST_ENTRY(VFIOGroup) container_next; | |
136 | bool balloon_allowed; | |
137 | } VFIOGroup; | |
138 | ||
139 | typedef struct VFIODMABuf { | |
140 | QemuDmaBuf buf; | |
141 | uint32_t pos_x, pos_y, pos_updates; | |
142 | uint32_t hot_x, hot_y, hot_updates; | |
143 | int dmabuf_id; | |
144 | QTAILQ_ENTRY(VFIODMABuf) next; | |
145 | } VFIODMABuf; | |
146 | ||
147 | typedef struct VFIODisplay { | |
148 | QemuConsole *con; | |
149 | RAMFBState *ramfb; | |
150 | struct vfio_region_info *edid_info; | |
151 | struct vfio_region_gfx_edid *edid_regs; | |
152 | uint8_t *edid_blob; | |
153 | QEMUTimer *edid_link_timer; | |
154 | struct { | |
155 | VFIORegion buffer; | |
156 | DisplaySurface *surface; | |
157 | } region; | |
158 | struct { | |
159 | QTAILQ_HEAD(, VFIODMABuf) bufs; | |
160 | VFIODMABuf *primary; | |
161 | VFIODMABuf *cursor; | |
162 | } dmabuf; | |
163 | } VFIODisplay; | |
164 | ||
165 | void vfio_put_base_device(VFIODevice *vbasedev); | |
166 | void vfio_disable_irqindex(VFIODevice *vbasedev, int index); | |
167 | void vfio_unmask_single_irqindex(VFIODevice *vbasedev, int index); | |
168 | void vfio_mask_single_irqindex(VFIODevice *vbasedev, int index); | |
169 | int vfio_set_irq_signaling(VFIODevice *vbasedev, int index, int subindex, | |
170 | int action, int fd, Error **errp); | |
171 | void vfio_region_write(void *opaque, hwaddr addr, | |
172 | uint64_t data, unsigned size); | |
173 | uint64_t vfio_region_read(void *opaque, | |
174 | hwaddr addr, unsigned size); | |
175 | int vfio_region_setup(Object *obj, VFIODevice *vbasedev, VFIORegion *region, | |
176 | int index, const char *name); | |
177 | int vfio_region_mmap(VFIORegion *region); | |
178 | void vfio_region_mmaps_set_enabled(VFIORegion *region, bool enabled); | |
179 | void vfio_region_exit(VFIORegion *region); | |
180 | void vfio_region_finalize(VFIORegion *region); | |
181 | void vfio_reset_handler(void *opaque); | |
182 | VFIOGroup *vfio_get_group(int groupid, AddressSpace *as, Error **errp); | |
183 | void vfio_put_group(VFIOGroup *group); | |
184 | int vfio_get_device(VFIOGroup *group, const char *name, | |
185 | VFIODevice *vbasedev, Error **errp); | |
186 | ||
187 | extern const MemoryRegionOps vfio_region_ops; | |
188 | typedef QLIST_HEAD(VFIOGroupList, VFIOGroup) VFIOGroupList; | |
189 | extern VFIOGroupList vfio_group_list; | |
190 | ||
191 | #ifdef CONFIG_LINUX | |
192 | int vfio_get_region_info(VFIODevice *vbasedev, int index, | |
193 | struct vfio_region_info **info); | |
194 | int vfio_get_dev_region_info(VFIODevice *vbasedev, uint32_t type, | |
195 | uint32_t subtype, struct vfio_region_info **info); | |
196 | bool vfio_has_region_cap(VFIODevice *vbasedev, int region, uint16_t cap_type); | |
197 | struct vfio_info_cap_header * | |
198 | vfio_get_region_info_cap(struct vfio_region_info *info, uint16_t id); | |
199 | #endif | |
200 | extern const MemoryListener vfio_prereg_listener; | |
201 | ||
202 | int vfio_spapr_create_window(VFIOContainer *container, | |
203 | MemoryRegionSection *section, | |
204 | hwaddr *pgsize); | |
205 | int vfio_spapr_remove_window(VFIOContainer *container, | |
206 | hwaddr offset_within_address_space); | |
207 | ||
208 | #endif /* HW_VFIO_VFIO_COMMON_H */ |