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