1#ifndef XEN_PT_H
2#define XEN_PT_H
3
4#include "hw/xen/xen_native.h"
5#include "xen-host-pci-device.h"
6#include "qom/object.h"
7
8bool xen_igd_gfx_pt_enabled(void);
9void xen_igd_gfx_pt_set(bool value, Error **errp);
10
11void xen_pt_log(const PCIDevice *d, const char *f, ...) G_GNUC_PRINTF(2, 3);
12
13#define XEN_PT_ERR(d, _f, _a...) xen_pt_log(d, "%s: Error: "_f, __func__, ##_a)
14
15#ifdef XEN_PT_LOGGING_ENABLED
16# define XEN_PT_LOG(d, _f, _a...) xen_pt_log(d, "%s: " _f, __func__, ##_a)
17# define XEN_PT_WARN(d, _f, _a...) \
18 xen_pt_log(d, "%s: Warning: "_f, __func__, ##_a)
19#else
20# define XEN_PT_LOG(d, _f, _a...)
21# define XEN_PT_WARN(d, _f, _a...)
22#endif
23
24#ifdef XEN_PT_DEBUG_PCI_CONFIG_ACCESS
25# define XEN_PT_LOG_CONFIG(d, addr, val, len) \
26 xen_pt_log(d, "%s: address=0x%04x val=0x%08x len=%d\n", \
27 __func__, addr, val, len)
28#else
29# define XEN_PT_LOG_CONFIG(d, addr, val, len)
30#endif
31
32
33
34#define XEN_PFN(x) ((x) >> XC_PAGE_SHIFT)
35
36typedef const struct XenPTRegInfo XenPTRegInfo;
37typedef struct XenPTReg XenPTReg;
38
39
40#define TYPE_XEN_PT_DEVICE "xen-pci-passthrough"
41OBJECT_DECLARE_SIMPLE_TYPE(XenPCIPassthroughState, XEN_PT_DEVICE)
42
43#define XEN_PT_DEVICE_CLASS(klass) \
44 OBJECT_CLASS_CHECK(XenPTDeviceClass, klass, TYPE_XEN_PT_DEVICE)
45#define XEN_PT_DEVICE_GET_CLASS(obj) \
46 OBJECT_GET_CLASS(XenPTDeviceClass, obj, TYPE_XEN_PT_DEVICE)
47
48typedef void (*XenPTQdevRealize)(DeviceState *qdev, Error **errp);
49
50typedef struct XenPTDeviceClass {
51 PCIDeviceClass parent_class;
52 XenPTQdevRealize pci_qdev_realize;
53} XenPTDeviceClass;
54
55uint32_t igd_read_opregion(XenPCIPassthroughState *s);
56void xen_igd_reserve_slot(PCIBus *pci_bus);
57void igd_write_opregion(XenPCIPassthroughState *s, uint32_t val);
58void xen_igd_passthrough_isa_bridge_create(XenPCIPassthroughState *s,
59 XenHostPCIDevice *dev);
60
61
62typedef int (*xen_pt_conf_reg_init)
63 (XenPCIPassthroughState *, XenPTRegInfo *, uint32_t real_offset,
64 uint32_t *data);
65typedef int (*xen_pt_conf_dword_write)
66 (XenPCIPassthroughState *, XenPTReg *cfg_entry,
67 uint32_t *val, uint32_t dev_value, uint32_t valid_mask);
68typedef int (*xen_pt_conf_word_write)
69 (XenPCIPassthroughState *, XenPTReg *cfg_entry,
70 uint16_t *val, uint16_t dev_value, uint16_t valid_mask);
71typedef int (*xen_pt_conf_byte_write)
72 (XenPCIPassthroughState *, XenPTReg *cfg_entry,
73 uint8_t *val, uint8_t dev_value, uint8_t valid_mask);
74typedef int (*xen_pt_conf_dword_read)
75 (XenPCIPassthroughState *, XenPTReg *cfg_entry,
76 uint32_t *val, uint32_t valid_mask);
77typedef int (*xen_pt_conf_word_read)
78 (XenPCIPassthroughState *, XenPTReg *cfg_entry,
79 uint16_t *val, uint16_t valid_mask);
80typedef int (*xen_pt_conf_byte_read)
81 (XenPCIPassthroughState *, XenPTReg *cfg_entry,
82 uint8_t *val, uint8_t valid_mask);
83
84#define XEN_PT_BAR_ALLF 0xFFFFFFFF
85#define XEN_PT_BAR_UNMAPPED (-1)
86
87#define XEN_PCI_CAP_MAX 48
88
89#define XEN_PCI_INTEL_OPREGION 0xfc
90
91#define XEN_PCI_IGD_DOMAIN 0
92#define XEN_PCI_IGD_BUS 0
93#define XEN_PCI_IGD_DEV 2
94#define XEN_PCI_IGD_FN 0
95#define XEN_PCI_IGD_SLOT_MASK \
96 (1UL << PCI_SLOT(PCI_DEVFN(XEN_PCI_IGD_DEV, XEN_PCI_IGD_FN)))
97
98typedef enum {
99 XEN_PT_GRP_TYPE_HARDWIRED = 0,
100 XEN_PT_GRP_TYPE_EMU,
101} XenPTRegisterGroupType;
102
103typedef enum {
104 XEN_PT_BAR_FLAG_MEM = 0,
105 XEN_PT_BAR_FLAG_IO,
106 XEN_PT_BAR_FLAG_UPPER,
107 XEN_PT_BAR_FLAG_UNUSED,
108} XenPTBarFlag;
109
110
111typedef struct XenPTRegion {
112
113 XenPTBarFlag bar_flag;
114
115 union {
116 uint64_t maddr;
117 uint64_t pio_base;
118 uint64_t u;
119 } access;
120} XenPTRegion;
121
122
123
124
125
126
127
128
129
130struct XenPTRegInfo {
131 uint32_t offset;
132 uint32_t size;
133 uint32_t init_val;
134
135 uint32_t res_mask;
136
137 uint32_t ro_mask;
138
139 uint32_t rw1c_mask;
140
141 uint32_t emu_mask;
142 xen_pt_conf_reg_init init;
143
144
145 union {
146 struct {
147 xen_pt_conf_dword_write write;
148 xen_pt_conf_dword_read read;
149 } dw;
150 struct {
151 xen_pt_conf_word_write write;
152 xen_pt_conf_word_read read;
153 } w;
154 struct {
155 xen_pt_conf_byte_write write;
156 xen_pt_conf_byte_read read;
157 } b;
158 } u;
159};
160
161
162struct XenPTReg {
163 QLIST_ENTRY(XenPTReg) entries;
164 XenPTRegInfo *reg;
165 union {
166 uint8_t *byte;
167 uint16_t *half_word;
168 uint32_t *word;
169 } ptr;
170};
171
172typedef const struct XenPTRegGroupInfo XenPTRegGroupInfo;
173
174
175typedef int (*xen_pt_reg_size_init_fn)
176 (XenPCIPassthroughState *, XenPTRegGroupInfo *,
177 uint32_t base_offset, uint8_t *size);
178
179
180struct XenPTRegGroupInfo {
181 uint8_t grp_id;
182 XenPTRegisterGroupType grp_type;
183 uint8_t grp_size;
184 xen_pt_reg_size_init_fn size_init;
185 XenPTRegInfo *emu_regs;
186};
187
188
189typedef struct XenPTRegGroup {
190 QLIST_ENTRY(XenPTRegGroup) entries;
191 XenPTRegGroupInfo *reg_grp;
192 uint32_t base_offset;
193 uint8_t size;
194 QLIST_HEAD(, XenPTReg) reg_tbl_list;
195} XenPTRegGroup;
196
197
198#define XEN_PT_UNASSIGNED_PIRQ (-1)
199typedef struct XenPTMSI {
200 uint16_t flags;
201 uint32_t addr_lo;
202 uint32_t addr_hi;
203 uint16_t data;
204 uint32_t ctrl_offset;
205 uint32_t mask;
206 int pirq;
207 bool initialized;
208 bool mapped;
209} XenPTMSI;
210
211typedef struct XenPTMSIXEntry {
212 int pirq;
213 uint64_t addr;
214 uint32_t data;
215 uint32_t latch[4];
216 bool updated;
217} XenPTMSIXEntry;
218typedef struct XenPTMSIX {
219 uint32_t ctrl_offset;
220 bool enabled;
221 bool maskall;
222 int total_entries;
223 int bar_index;
224 uint64_t table_base;
225 uint32_t table_offset_adjust;
226 uint64_t mmio_base_addr;
227 MemoryRegion mmio;
228 void *phys_iomem_base;
229 XenPTMSIXEntry msix_entry[];
230} XenPTMSIX;
231
232struct XenPCIPassthroughState {
233 PCIDevice dev;
234
235 PCIHostDeviceAddress hostaddr;
236 bool is_virtfn;
237 bool permissive;
238 bool permissive_warned;
239 XenHostPCIDevice real_device;
240 XenPTRegion bases[PCI_NUM_REGIONS];
241 QLIST_HEAD(, XenPTRegGroup) reg_grps;
242
243 uint32_t machine_irq;
244
245 XenPTMSI *msi;
246 XenPTMSIX *msix;
247
248 MemoryRegion bar[PCI_NUM_REGIONS - 1];
249 MemoryRegion rom;
250
251 MemoryListener memory_listener;
252 MemoryListener io_listener;
253 bool listener_set;
254};
255
256void xen_pt_config_init(XenPCIPassthroughState *s, Error **errp);
257void xen_pt_config_delete(XenPCIPassthroughState *s);
258XenPTRegGroup *xen_pt_find_reg_grp(XenPCIPassthroughState *s, uint32_t address);
259XenPTReg *xen_pt_find_reg(XenPTRegGroup *reg_grp, uint32_t address);
260int xen_pt_bar_offset_to_index(uint32_t offset);
261
262static inline pcibus_t xen_pt_get_emul_size(XenPTBarFlag flag, pcibus_t r_size)
263{
264
265 if (flag == XEN_PT_BAR_FLAG_MEM) {
266 return (r_size + XC_PAGE_SIZE - 1) & XC_PAGE_MASK;
267 } else {
268 return r_size;
269 }
270}
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302static inline uint8_t xen_pt_pci_read_intx(XenPCIPassthroughState *s)
303{
304 uint8_t v = 0;
305 xen_host_pci_get_byte(&s->real_device, PCI_INTERRUPT_PIN, &v);
306 return v;
307}
308
309static inline uint8_t xen_pt_pci_intx(XenPCIPassthroughState *s)
310{
311 uint8_t r_val = xen_pt_pci_read_intx(s);
312
313 XEN_PT_LOG(&s->dev, "intx=%i\n", r_val);
314 if (r_val < 1 || r_val > 4) {
315 XEN_PT_LOG(&s->dev, "Interrupt pin read from hardware is out of range:"
316 " value=%i, acceptable range is 1 - 4\n", r_val);
317 r_val = 0;
318 } else {
319
320 r_val -= 1;
321 }
322
323 return r_val;
324}
325
326
327int xen_pt_msi_setup(XenPCIPassthroughState *s);
328int xen_pt_msi_update(XenPCIPassthroughState *d);
329void xen_pt_msi_disable(XenPCIPassthroughState *s);
330
331int xen_pt_msix_init(XenPCIPassthroughState *s, uint32_t base);
332void xen_pt_msix_delete(XenPCIPassthroughState *s);
333void xen_pt_msix_unmap(XenPCIPassthroughState *s);
334int xen_pt_msix_update(XenPCIPassthroughState *s);
335int xen_pt_msix_update_remap(XenPCIPassthroughState *s, int bar_index);
336void xen_pt_msix_disable(XenPCIPassthroughState *s);
337
338static inline bool xen_pt_has_msix_mapping(XenPCIPassthroughState *s, int bar)
339{
340 return s->msix && s->msix->bar_index == bar;
341}
342
343extern void *pci_assign_dev_load_option_rom(PCIDevice *dev,
344 int *size,
345 unsigned int domain,
346 unsigned int bus, unsigned int slot,
347 unsigned int function);
348static inline bool is_igd_vga_passthrough(XenHostPCIDevice *dev)
349{
350 return (xen_igd_gfx_pt_enabled()
351 && ((dev->class_code >> 0x8) == PCI_CLASS_DISPLAY_VGA));
352}
353int xen_pt_register_vga_regions(XenHostPCIDevice *dev);
354int xen_pt_unregister_vga_regions(XenHostPCIDevice *dev);
355void xen_pt_setup_vga(XenPCIPassthroughState *s, XenHostPCIDevice *dev,
356 Error **errp);
357#endif
358