Statistics
| Branch: | Revision:

root / hw / xen_pt.h @ a1bc20df

History | View | Annotate | Download (8.8 kB)

1 eaab4d60 Allen Kay
#ifndef XEN_PT_H
2 eaab4d60 Allen Kay
#define XEN_PT_H
3 eaab4d60 Allen Kay
4 eaab4d60 Allen Kay
#include "qemu-common.h"
5 eaab4d60 Allen Kay
#include "xen_common.h"
6 eaab4d60 Allen Kay
#include "pci.h"
7 eaab4d60 Allen Kay
#include "xen-host-pci-device.h"
8 eaab4d60 Allen Kay
9 eaab4d60 Allen Kay
void xen_pt_log(const PCIDevice *d, const char *f, ...) GCC_FMT_ATTR(2, 3);
10 eaab4d60 Allen Kay
11 eaab4d60 Allen Kay
#define XEN_PT_ERR(d, _f, _a...) xen_pt_log(d, "%s: Error: "_f, __func__, ##_a)
12 eaab4d60 Allen Kay
13 eaab4d60 Allen Kay
#ifdef XEN_PT_LOGGING_ENABLED
14 eaab4d60 Allen Kay
#  define XEN_PT_LOG(d, _f, _a...)  xen_pt_log(d, "%s: " _f, __func__, ##_a)
15 eaab4d60 Allen Kay
#  define XEN_PT_WARN(d, _f, _a...) \
16 eaab4d60 Allen Kay
    xen_pt_log(d, "%s: Warning: "_f, __func__, ##_a)
17 eaab4d60 Allen Kay
#else
18 eaab4d60 Allen Kay
#  define XEN_PT_LOG(d, _f, _a...)
19 eaab4d60 Allen Kay
#  define XEN_PT_WARN(d, _f, _a...)
20 eaab4d60 Allen Kay
#endif
21 eaab4d60 Allen Kay
22 eaab4d60 Allen Kay
#ifdef XEN_PT_DEBUG_PCI_CONFIG_ACCESS
23 eaab4d60 Allen Kay
#  define XEN_PT_LOG_CONFIG(d, addr, val, len) \
24 eaab4d60 Allen Kay
    xen_pt_log(d, "%s: address=0x%04x val=0x%08x len=%d\n", \
25 eaab4d60 Allen Kay
               __func__, addr, val, len)
26 eaab4d60 Allen Kay
#else
27 eaab4d60 Allen Kay
#  define XEN_PT_LOG_CONFIG(d, addr, val, len)
28 eaab4d60 Allen Kay
#endif
29 eaab4d60 Allen Kay
30 eaab4d60 Allen Kay
31 eaab4d60 Allen Kay
/* Helper */
32 eaab4d60 Allen Kay
#define XEN_PFN(x) ((x) >> XC_PAGE_SHIFT)
33 eaab4d60 Allen Kay
34 eaab4d60 Allen Kay
typedef struct XenPTRegInfo XenPTRegInfo;
35 eaab4d60 Allen Kay
typedef struct XenPTReg XenPTReg;
36 eaab4d60 Allen Kay
37 eaab4d60 Allen Kay
typedef struct XenPCIPassthroughState XenPCIPassthroughState;
38 eaab4d60 Allen Kay
39 eaab4d60 Allen Kay
/* function type for config reg */
40 eaab4d60 Allen Kay
typedef int (*xen_pt_conf_reg_init)
41 eaab4d60 Allen Kay
    (XenPCIPassthroughState *, XenPTRegInfo *, uint32_t real_offset,
42 eaab4d60 Allen Kay
     uint32_t *data);
43 eaab4d60 Allen Kay
typedef int (*xen_pt_conf_dword_write)
44 eaab4d60 Allen Kay
    (XenPCIPassthroughState *, XenPTReg *cfg_entry,
45 eaab4d60 Allen Kay
     uint32_t *val, uint32_t dev_value, uint32_t valid_mask);
46 eaab4d60 Allen Kay
typedef int (*xen_pt_conf_word_write)
47 eaab4d60 Allen Kay
    (XenPCIPassthroughState *, XenPTReg *cfg_entry,
48 eaab4d60 Allen Kay
     uint16_t *val, uint16_t dev_value, uint16_t valid_mask);
49 eaab4d60 Allen Kay
typedef int (*xen_pt_conf_byte_write)
50 eaab4d60 Allen Kay
    (XenPCIPassthroughState *, XenPTReg *cfg_entry,
51 eaab4d60 Allen Kay
     uint8_t *val, uint8_t dev_value, uint8_t valid_mask);
52 eaab4d60 Allen Kay
typedef int (*xen_pt_conf_dword_read)
53 eaab4d60 Allen Kay
    (XenPCIPassthroughState *, XenPTReg *cfg_entry,
54 eaab4d60 Allen Kay
     uint32_t *val, uint32_t valid_mask);
55 eaab4d60 Allen Kay
typedef int (*xen_pt_conf_word_read)
56 eaab4d60 Allen Kay
    (XenPCIPassthroughState *, XenPTReg *cfg_entry,
57 eaab4d60 Allen Kay
     uint16_t *val, uint16_t valid_mask);
58 eaab4d60 Allen Kay
typedef int (*xen_pt_conf_byte_read)
59 eaab4d60 Allen Kay
    (XenPCIPassthroughState *, XenPTReg *cfg_entry,
60 eaab4d60 Allen Kay
     uint8_t *val, uint8_t valid_mask);
61 eaab4d60 Allen Kay
62 eaab4d60 Allen Kay
#define XEN_PT_BAR_ALLF 0xFFFFFFFF
63 eaab4d60 Allen Kay
#define XEN_PT_BAR_UNMAPPED (-1)
64 eaab4d60 Allen Kay
65 93d7ae8e Allen Kay
#define PCI_CAP_MAX 48
66 93d7ae8e Allen Kay
67 eaab4d60 Allen Kay
68 eaab4d60 Allen Kay
typedef enum {
69 eaab4d60 Allen Kay
    XEN_PT_GRP_TYPE_HARDWIRED = 0,  /* 0 Hardwired reg group */
70 eaab4d60 Allen Kay
    XEN_PT_GRP_TYPE_EMU,            /* emul reg group */
71 eaab4d60 Allen Kay
} XenPTRegisterGroupType;
72 eaab4d60 Allen Kay
73 eaab4d60 Allen Kay
typedef enum {
74 eaab4d60 Allen Kay
    XEN_PT_BAR_FLAG_MEM = 0,        /* Memory type BAR */
75 eaab4d60 Allen Kay
    XEN_PT_BAR_FLAG_IO,             /* I/O type BAR */
76 eaab4d60 Allen Kay
    XEN_PT_BAR_FLAG_UPPER,          /* upper 64bit BAR */
77 eaab4d60 Allen Kay
    XEN_PT_BAR_FLAG_UNUSED,         /* unused BAR */
78 eaab4d60 Allen Kay
} XenPTBarFlag;
79 eaab4d60 Allen Kay
80 eaab4d60 Allen Kay
81 eaab4d60 Allen Kay
typedef struct XenPTRegion {
82 eaab4d60 Allen Kay
    /* BAR flag */
83 eaab4d60 Allen Kay
    XenPTBarFlag bar_flag;
84 eaab4d60 Allen Kay
    /* Translation of the emulated address */
85 eaab4d60 Allen Kay
    union {
86 eaab4d60 Allen Kay
        uint64_t maddr;
87 eaab4d60 Allen Kay
        uint64_t pio_base;
88 eaab4d60 Allen Kay
        uint64_t u;
89 eaab4d60 Allen Kay
    } access;
90 eaab4d60 Allen Kay
} XenPTRegion;
91 eaab4d60 Allen Kay
92 eaab4d60 Allen Kay
/* XenPTRegInfo declaration
93 eaab4d60 Allen Kay
 * - only for emulated register (either a part or whole bit).
94 eaab4d60 Allen Kay
 * - for passthrough register that need special behavior (like interacting with
95 eaab4d60 Allen Kay
 *   other component), set emu_mask to all 0 and specify r/w func properly.
96 eaab4d60 Allen Kay
 * - do NOT use ALL F for init_val, otherwise the tbl will not be registered.
97 eaab4d60 Allen Kay
 */
98 eaab4d60 Allen Kay
99 0546b8c2 Stefan Weil
/* emulated register information */
100 eaab4d60 Allen Kay
struct XenPTRegInfo {
101 eaab4d60 Allen Kay
    uint32_t offset;
102 eaab4d60 Allen Kay
    uint32_t size;
103 eaab4d60 Allen Kay
    uint32_t init_val;
104 eaab4d60 Allen Kay
    /* reg read only field mask (ON:RO/ROS, OFF:other) */
105 eaab4d60 Allen Kay
    uint32_t ro_mask;
106 eaab4d60 Allen Kay
    /* reg emulate field mask (ON:emu, OFF:passthrough) */
107 eaab4d60 Allen Kay
    uint32_t emu_mask;
108 eaab4d60 Allen Kay
    /* no write back allowed */
109 eaab4d60 Allen Kay
    uint32_t no_wb;
110 eaab4d60 Allen Kay
    xen_pt_conf_reg_init init;
111 eaab4d60 Allen Kay
    /* read/write function pointer
112 eaab4d60 Allen Kay
     * for double_word/word/byte size */
113 eaab4d60 Allen Kay
    union {
114 eaab4d60 Allen Kay
        struct {
115 eaab4d60 Allen Kay
            xen_pt_conf_dword_write write;
116 eaab4d60 Allen Kay
            xen_pt_conf_dword_read read;
117 eaab4d60 Allen Kay
        } dw;
118 eaab4d60 Allen Kay
        struct {
119 eaab4d60 Allen Kay
            xen_pt_conf_word_write write;
120 eaab4d60 Allen Kay
            xen_pt_conf_word_read read;
121 eaab4d60 Allen Kay
        } w;
122 eaab4d60 Allen Kay
        struct {
123 eaab4d60 Allen Kay
            xen_pt_conf_byte_write write;
124 eaab4d60 Allen Kay
            xen_pt_conf_byte_read read;
125 eaab4d60 Allen Kay
        } b;
126 eaab4d60 Allen Kay
    } u;
127 eaab4d60 Allen Kay
};
128 eaab4d60 Allen Kay
129 eaab4d60 Allen Kay
/* emulated register management */
130 eaab4d60 Allen Kay
struct XenPTReg {
131 eaab4d60 Allen Kay
    QLIST_ENTRY(XenPTReg) entries;
132 eaab4d60 Allen Kay
    XenPTRegInfo *reg;
133 eaab4d60 Allen Kay
    uint32_t data; /* emulated value */
134 eaab4d60 Allen Kay
};
135 eaab4d60 Allen Kay
136 eaab4d60 Allen Kay
typedef struct XenPTRegGroupInfo XenPTRegGroupInfo;
137 eaab4d60 Allen Kay
138 eaab4d60 Allen Kay
/* emul reg group size initialize method */
139 eaab4d60 Allen Kay
typedef int (*xen_pt_reg_size_init_fn)
140 eaab4d60 Allen Kay
    (XenPCIPassthroughState *, const XenPTRegGroupInfo *,
141 eaab4d60 Allen Kay
     uint32_t base_offset, uint8_t *size);
142 eaab4d60 Allen Kay
143 0546b8c2 Stefan Weil
/* emulated register group information */
144 eaab4d60 Allen Kay
struct XenPTRegGroupInfo {
145 eaab4d60 Allen Kay
    uint8_t grp_id;
146 eaab4d60 Allen Kay
    XenPTRegisterGroupType grp_type;
147 eaab4d60 Allen Kay
    uint8_t grp_size;
148 eaab4d60 Allen Kay
    xen_pt_reg_size_init_fn size_init;
149 eaab4d60 Allen Kay
    XenPTRegInfo *emu_regs;
150 eaab4d60 Allen Kay
};
151 eaab4d60 Allen Kay
152 eaab4d60 Allen Kay
/* emul register group management table */
153 eaab4d60 Allen Kay
typedef struct XenPTRegGroup {
154 eaab4d60 Allen Kay
    QLIST_ENTRY(XenPTRegGroup) entries;
155 eaab4d60 Allen Kay
    const XenPTRegGroupInfo *reg_grp;
156 eaab4d60 Allen Kay
    uint32_t base_offset;
157 eaab4d60 Allen Kay
    uint8_t size;
158 eaab4d60 Allen Kay
    QLIST_HEAD(, XenPTReg) reg_tbl_list;
159 eaab4d60 Allen Kay
} XenPTRegGroup;
160 eaab4d60 Allen Kay
161 eaab4d60 Allen Kay
162 eaab4d60 Allen Kay
#define XEN_PT_UNASSIGNED_PIRQ (-1)
163 3854ca57 Jiang Yunhong
typedef struct XenPTMSI {
164 3854ca57 Jiang Yunhong
    uint16_t flags;
165 3854ca57 Jiang Yunhong
    uint32_t addr_lo;  /* guest message address */
166 3854ca57 Jiang Yunhong
    uint32_t addr_hi;  /* guest message upper address */
167 3854ca57 Jiang Yunhong
    uint16_t data;     /* guest message data */
168 3854ca57 Jiang Yunhong
    uint32_t ctrl_offset; /* saved control offset */
169 3854ca57 Jiang Yunhong
    int pirq;          /* guest pirq corresponding */
170 3854ca57 Jiang Yunhong
    bool initialized;  /* when guest MSI is initialized */
171 3854ca57 Jiang Yunhong
    bool mapped;       /* when pirq is mapped */
172 3854ca57 Jiang Yunhong
} XenPTMSI;
173 3854ca57 Jiang Yunhong
174 3854ca57 Jiang Yunhong
typedef struct XenPTMSIXEntry {
175 3854ca57 Jiang Yunhong
    int pirq;
176 3854ca57 Jiang Yunhong
    uint64_t addr;
177 3854ca57 Jiang Yunhong
    uint32_t data;
178 3854ca57 Jiang Yunhong
    uint32_t vector_ctrl;
179 3854ca57 Jiang Yunhong
    bool updated; /* indicate whether MSI ADDR or DATA is updated */
180 3854ca57 Jiang Yunhong
} XenPTMSIXEntry;
181 3854ca57 Jiang Yunhong
typedef struct XenPTMSIX {
182 3854ca57 Jiang Yunhong
    uint32_t ctrl_offset;
183 3854ca57 Jiang Yunhong
    bool enabled;
184 3854ca57 Jiang Yunhong
    int total_entries;
185 3854ca57 Jiang Yunhong
    int bar_index;
186 3854ca57 Jiang Yunhong
    uint64_t table_base;
187 3854ca57 Jiang Yunhong
    uint32_t table_offset_adjust; /* page align mmap */
188 3854ca57 Jiang Yunhong
    uint64_t mmio_base_addr;
189 3854ca57 Jiang Yunhong
    MemoryRegion mmio;
190 3854ca57 Jiang Yunhong
    void *phys_iomem_base;
191 3854ca57 Jiang Yunhong
    XenPTMSIXEntry msix_entry[0];
192 3854ca57 Jiang Yunhong
} XenPTMSIX;
193 eaab4d60 Allen Kay
194 eaab4d60 Allen Kay
struct XenPCIPassthroughState {
195 eaab4d60 Allen Kay
    PCIDevice dev;
196 eaab4d60 Allen Kay
197 eaab4d60 Allen Kay
    PCIHostDeviceAddress hostaddr;
198 eaab4d60 Allen Kay
    bool is_virtfn;
199 eaab4d60 Allen Kay
    XenHostPCIDevice real_device;
200 eaab4d60 Allen Kay
    XenPTRegion bases[PCI_NUM_REGIONS]; /* Access regions */
201 eaab4d60 Allen Kay
    QLIST_HEAD(, XenPTRegGroup) reg_grps;
202 eaab4d60 Allen Kay
203 eaab4d60 Allen Kay
    uint32_t machine_irq;
204 eaab4d60 Allen Kay
205 3854ca57 Jiang Yunhong
    XenPTMSI *msi;
206 3854ca57 Jiang Yunhong
    XenPTMSIX *msix;
207 3854ca57 Jiang Yunhong
208 eaab4d60 Allen Kay
    MemoryRegion bar[PCI_NUM_REGIONS - 1];
209 eaab4d60 Allen Kay
    MemoryRegion rom;
210 eaab4d60 Allen Kay
211 eaab4d60 Allen Kay
    MemoryListener memory_listener;
212 12b40e47 Avi Kivity
    MemoryListener io_listener;
213 eaab4d60 Allen Kay
};
214 eaab4d60 Allen Kay
215 eaab4d60 Allen Kay
int xen_pt_config_init(XenPCIPassthroughState *s);
216 eaab4d60 Allen Kay
void xen_pt_config_delete(XenPCIPassthroughState *s);
217 eaab4d60 Allen Kay
XenPTRegGroup *xen_pt_find_reg_grp(XenPCIPassthroughState *s, uint32_t address);
218 eaab4d60 Allen Kay
XenPTReg *xen_pt_find_reg(XenPTRegGroup *reg_grp, uint32_t address);
219 eaab4d60 Allen Kay
int xen_pt_bar_offset_to_index(uint32_t offset);
220 eaab4d60 Allen Kay
221 eaab4d60 Allen Kay
static inline pcibus_t xen_pt_get_emul_size(XenPTBarFlag flag, pcibus_t r_size)
222 eaab4d60 Allen Kay
{
223 eaab4d60 Allen Kay
    /* align resource size (memory type only) */
224 eaab4d60 Allen Kay
    if (flag == XEN_PT_BAR_FLAG_MEM) {
225 eaab4d60 Allen Kay
        return (r_size + XC_PAGE_SIZE - 1) & XC_PAGE_MASK;
226 eaab4d60 Allen Kay
    } else {
227 eaab4d60 Allen Kay
        return r_size;
228 eaab4d60 Allen Kay
    }
229 eaab4d60 Allen Kay
}
230 eaab4d60 Allen Kay
231 eaab4d60 Allen Kay
/* INTx */
232 eaab4d60 Allen Kay
/* The PCI Local Bus Specification, Rev. 3.0,
233 eaab4d60 Allen Kay
 * Section 6.2.4 Miscellaneous Registers, pp 223
234 eaab4d60 Allen Kay
 * outlines 5 valid values for the interrupt pin (intx).
235 eaab4d60 Allen Kay
 *  0: For devices (or device functions) that don't use an interrupt in
236 eaab4d60 Allen Kay
 *  1: INTA#
237 eaab4d60 Allen Kay
 *  2: INTB#
238 eaab4d60 Allen Kay
 *  3: INTC#
239 eaab4d60 Allen Kay
 *  4: INTD#
240 eaab4d60 Allen Kay
 *
241 eaab4d60 Allen Kay
 * Xen uses the following 4 values for intx
242 eaab4d60 Allen Kay
 *  0: INTA#
243 eaab4d60 Allen Kay
 *  1: INTB#
244 eaab4d60 Allen Kay
 *  2: INTC#
245 eaab4d60 Allen Kay
 *  3: INTD#
246 eaab4d60 Allen Kay
 *
247 eaab4d60 Allen Kay
 * Observing that these list of values are not the same, xen_pt_pci_read_intx()
248 eaab4d60 Allen Kay
 * uses the following mapping from hw to xen values.
249 eaab4d60 Allen Kay
 * This seems to reflect the current usage within Xen.
250 eaab4d60 Allen Kay
 *
251 eaab4d60 Allen Kay
 * PCI hardware    | Xen | Notes
252 eaab4d60 Allen Kay
 * ----------------+-----+----------------------------------------------------
253 eaab4d60 Allen Kay
 * 0               | 0   | No interrupt
254 eaab4d60 Allen Kay
 * 1               | 0   | INTA#
255 eaab4d60 Allen Kay
 * 2               | 1   | INTB#
256 eaab4d60 Allen Kay
 * 3               | 2   | INTC#
257 eaab4d60 Allen Kay
 * 4               | 3   | INTD#
258 eaab4d60 Allen Kay
 * any other value | 0   | This should never happen, log error message
259 eaab4d60 Allen Kay
 */
260 eaab4d60 Allen Kay
261 eaab4d60 Allen Kay
static inline uint8_t xen_pt_pci_read_intx(XenPCIPassthroughState *s)
262 eaab4d60 Allen Kay
{
263 eaab4d60 Allen Kay
    uint8_t v = 0;
264 eaab4d60 Allen Kay
    xen_host_pci_get_byte(&s->real_device, PCI_INTERRUPT_PIN, &v);
265 eaab4d60 Allen Kay
    return v;
266 eaab4d60 Allen Kay
}
267 eaab4d60 Allen Kay
268 eaab4d60 Allen Kay
static inline uint8_t xen_pt_pci_intx(XenPCIPassthroughState *s)
269 eaab4d60 Allen Kay
{
270 eaab4d60 Allen Kay
    uint8_t r_val = xen_pt_pci_read_intx(s);
271 eaab4d60 Allen Kay
272 eaab4d60 Allen Kay
    XEN_PT_LOG(&s->dev, "intx=%i\n", r_val);
273 eaab4d60 Allen Kay
    if (r_val < 1 || r_val > 4) {
274 eaab4d60 Allen Kay
        XEN_PT_LOG(&s->dev, "Interrupt pin read from hardware is out of range:"
275 eaab4d60 Allen Kay
                   " value=%i, acceptable range is 1 - 4\n", r_val);
276 eaab4d60 Allen Kay
        r_val = 0;
277 eaab4d60 Allen Kay
    } else {
278 eaab4d60 Allen Kay
        r_val -= 1;
279 eaab4d60 Allen Kay
    }
280 eaab4d60 Allen Kay
281 eaab4d60 Allen Kay
    return r_val;
282 eaab4d60 Allen Kay
}
283 eaab4d60 Allen Kay
284 3854ca57 Jiang Yunhong
/* MSI/MSI-X */
285 3854ca57 Jiang Yunhong
int xen_pt_msi_set_enable(XenPCIPassthroughState *s, bool en);
286 3854ca57 Jiang Yunhong
int xen_pt_msi_setup(XenPCIPassthroughState *s);
287 3854ca57 Jiang Yunhong
int xen_pt_msi_update(XenPCIPassthroughState *d);
288 3854ca57 Jiang Yunhong
void xen_pt_msi_disable(XenPCIPassthroughState *s);
289 3854ca57 Jiang Yunhong
290 3854ca57 Jiang Yunhong
int xen_pt_msix_init(XenPCIPassthroughState *s, uint32_t base);
291 3854ca57 Jiang Yunhong
void xen_pt_msix_delete(XenPCIPassthroughState *s);
292 3854ca57 Jiang Yunhong
int xen_pt_msix_update(XenPCIPassthroughState *s);
293 3854ca57 Jiang Yunhong
int xen_pt_msix_update_remap(XenPCIPassthroughState *s, int bar_index);
294 3854ca57 Jiang Yunhong
void xen_pt_msix_disable(XenPCIPassthroughState *s);
295 3854ca57 Jiang Yunhong
296 3854ca57 Jiang Yunhong
static inline bool xen_pt_has_msix_mapping(XenPCIPassthroughState *s, int bar)
297 3854ca57 Jiang Yunhong
{
298 3854ca57 Jiang Yunhong
    return s->msix && s->msix->bar_index == bar;
299 3854ca57 Jiang Yunhong
}
300 3854ca57 Jiang Yunhong
301 3854ca57 Jiang Yunhong
302 eaab4d60 Allen Kay
#endif /* !XEN_PT_H */