xen_pt.h 11 KB

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