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