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