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