xen_pt.h 11 KB

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