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