1#ifndef XEN_PT_H
2#define XEN_PT_H
3
4#include "qemu-common.h"
5#include "xen_common.h"
6#include "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 struct XenPTRegInfo XenPTRegInfo;
35typedef struct XenPTReg XenPTReg;
36
37typedef struct XenPCIPassthroughState XenPCIPassthroughState;
38
39
40typedef int (*xen_pt_conf_reg_init)
41 (XenPCIPassthroughState *, XenPTRegInfo *, uint32_t real_offset,
42 uint32_t *data);
43typedef int (*xen_pt_conf_dword_write)
44 (XenPCIPassthroughState *, XenPTReg *cfg_entry,
45 uint32_t *val, uint32_t dev_value, uint32_t valid_mask);
46typedef int (*xen_pt_conf_word_write)
47 (XenPCIPassthroughState *, XenPTReg *cfg_entry,
48 uint16_t *val, uint16_t dev_value, uint16_t valid_mask);
49typedef int (*xen_pt_conf_byte_write)
50 (XenPCIPassthroughState *, XenPTReg *cfg_entry,
51 uint8_t *val, uint8_t dev_value, uint8_t valid_mask);
52typedef int (*xen_pt_conf_dword_read)
53 (XenPCIPassthroughState *, XenPTReg *cfg_entry,
54 uint32_t *val, uint32_t valid_mask);
55typedef int (*xen_pt_conf_word_read)
56 (XenPCIPassthroughState *, XenPTReg *cfg_entry,
57 uint16_t *val, uint16_t valid_mask);
58typedef int (*xen_pt_conf_byte_read)
59 (XenPCIPassthroughState *, XenPTReg *cfg_entry,
60 uint8_t *val, uint8_t valid_mask);
61
62#define XEN_PT_BAR_ALLF 0xFFFFFFFF
63#define XEN_PT_BAR_UNMAPPED (-1)
64
65#define PCI_CAP_MAX 48
66
67
68typedef enum {
69 XEN_PT_GRP_TYPE_HARDWIRED = 0,
70 XEN_PT_GRP_TYPE_EMU,
71} XenPTRegisterGroupType;
72
73typedef enum {
74 XEN_PT_BAR_FLAG_MEM = 0,
75 XEN_PT_BAR_FLAG_IO,
76 XEN_PT_BAR_FLAG_UPPER,
77 XEN_PT_BAR_FLAG_UNUSED,
78} XenPTBarFlag;
79
80
81typedef struct XenPTRegion {
82
83 XenPTBarFlag bar_flag;
84
85 union {
86 uint64_t maddr;
87 uint64_t pio_base;
88 uint64_t u;
89 } access;
90} XenPTRegion;
91
92
93
94
95
96
97
98
99
100struct XenPTRegInfo {
101 uint32_t offset;
102 uint32_t size;
103 uint32_t init_val;
104
105 uint32_t ro_mask;
106
107 uint32_t emu_mask;
108
109 uint32_t no_wb;
110 xen_pt_conf_reg_init init;
111
112
113 union {
114 struct {
115 xen_pt_conf_dword_write write;
116 xen_pt_conf_dword_read read;
117 } dw;
118 struct {
119 xen_pt_conf_word_write write;
120 xen_pt_conf_word_read read;
121 } w;
122 struct {
123 xen_pt_conf_byte_write write;
124 xen_pt_conf_byte_read read;
125 } b;
126 } u;
127};
128
129
130struct XenPTReg {
131 QLIST_ENTRY(XenPTReg) entries;
132 XenPTRegInfo *reg;
133 uint32_t data;
134};
135
136typedef struct XenPTRegGroupInfo XenPTRegGroupInfo;
137
138
139typedef int (*xen_pt_reg_size_init_fn)
140 (XenPCIPassthroughState *, const XenPTRegGroupInfo *,
141 uint32_t base_offset, uint8_t *size);
142
143
144struct XenPTRegGroupInfo {
145 uint8_t grp_id;
146 XenPTRegisterGroupType grp_type;
147 uint8_t grp_size;
148 xen_pt_reg_size_init_fn size_init;
149 XenPTRegInfo *emu_regs;
150};
151
152
153typedef struct XenPTRegGroup {
154 QLIST_ENTRY(XenPTRegGroup) entries;
155 const XenPTRegGroupInfo *reg_grp;
156 uint32_t base_offset;
157 uint8_t size;
158 QLIST_HEAD(, XenPTReg) reg_tbl_list;
159} XenPTRegGroup;
160
161
162#define XEN_PT_UNASSIGNED_PIRQ (-1)
163typedef struct XenPTMSI {
164 uint16_t flags;
165 uint32_t addr_lo;
166 uint32_t addr_hi;
167 uint16_t data;
168 uint32_t ctrl_offset;
169 int pirq;
170 bool initialized;
171 bool mapped;
172} XenPTMSI;
173
174typedef struct XenPTMSIXEntry {
175 int pirq;
176 uint64_t addr;
177 uint32_t data;
178 uint32_t vector_ctrl;
179 bool updated;
180} XenPTMSIXEntry;
181typedef struct XenPTMSIX {
182 uint32_t ctrl_offset;
183 bool enabled;
184 int total_entries;
185 int bar_index;
186 uint64_t table_base;
187 uint32_t table_offset_adjust;
188 uint64_t mmio_base_addr;
189 MemoryRegion mmio;
190 void *phys_iomem_base;
191 XenPTMSIXEntry msix_entry[0];
192} XenPTMSIX;
193
194struct XenPCIPassthroughState {
195 PCIDevice dev;
196
197 PCIHostDeviceAddress hostaddr;
198 bool is_virtfn;
199 XenHostPCIDevice real_device;
200 XenPTRegion bases[PCI_NUM_REGIONS];
201 QLIST_HEAD(, XenPTRegGroup) reg_grps;
202
203 uint32_t machine_irq;
204
205 XenPTMSI *msi;
206 XenPTMSIX *msix;
207
208 MemoryRegion bar[PCI_NUM_REGIONS - 1];
209 MemoryRegion rom;
210
211 MemoryListener memory_listener;
212 MemoryListener io_listener;
213};
214
215int xen_pt_config_init(XenPCIPassthroughState *s);
216void xen_pt_config_delete(XenPCIPassthroughState *s);
217XenPTRegGroup *xen_pt_find_reg_grp(XenPCIPassthroughState *s, uint32_t address);
218XenPTReg *xen_pt_find_reg(XenPTRegGroup *reg_grp, uint32_t address);
219int xen_pt_bar_offset_to_index(uint32_t offset);
220
221static inline pcibus_t xen_pt_get_emul_size(XenPTBarFlag flag, pcibus_t r_size)
222{
223
224 if (flag == XEN_PT_BAR_FLAG_MEM) {
225 return (r_size + XC_PAGE_SIZE - 1) & XC_PAGE_MASK;
226 } else {
227 return r_size;
228 }
229}
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261static inline uint8_t xen_pt_pci_read_intx(XenPCIPassthroughState *s)
262{
263 uint8_t v = 0;
264 xen_host_pci_get_byte(&s->real_device, PCI_INTERRUPT_PIN, &v);
265 return v;
266}
267
268static inline uint8_t xen_pt_pci_intx(XenPCIPassthroughState *s)
269{
270 uint8_t r_val = xen_pt_pci_read_intx(s);
271
272 XEN_PT_LOG(&s->dev, "intx=%i\n", r_val);
273 if (r_val < 1 || r_val > 4) {
274 XEN_PT_LOG(&s->dev, "Interrupt pin read from hardware is out of range:"
275 " value=%i, acceptable range is 1 - 4\n", r_val);
276 r_val = 0;
277 } else {
278 r_val -= 1;
279 }
280
281 return r_val;
282}
283
284
285int xen_pt_msi_set_enable(XenPCIPassthroughState *s, bool en);
286int xen_pt_msi_setup(XenPCIPassthroughState *s);
287int xen_pt_msi_update(XenPCIPassthroughState *d);
288void xen_pt_msi_disable(XenPCIPassthroughState *s);
289
290int xen_pt_msix_init(XenPCIPassthroughState *s, uint32_t base);
291void xen_pt_msix_delete(XenPCIPassthroughState *s);
292int xen_pt_msix_update(XenPCIPassthroughState *s);
293int xen_pt_msix_update_remap(XenPCIPassthroughState *s, int bar_index);
294void xen_pt_msix_disable(XenPCIPassthroughState *s);
295
296static inline bool xen_pt_has_msix_mapping(XenPCIPassthroughState *s, int bar)
297{
298 return s->msix && s->msix->bar_index == bar;
299}
300
301
302#endif
303