cfg_space.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412
  1. /*
  2. * Copyright(c) 2011-2016 Intel Corporation. All rights reserved.
  3. *
  4. * Permission is hereby granted, free of charge, to any person obtaining a
  5. * copy of this software and associated documentation files (the "Software"),
  6. * to deal in the Software without restriction, including without limitation
  7. * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  8. * and/or sell copies of the Software, and to permit persons to whom the
  9. * Software is furnished to do so, subject to the following conditions:
  10. *
  11. * The above copyright notice and this permission notice (including the next
  12. * paragraph) shall be included in all copies or substantial portions of the
  13. * Software.
  14. *
  15. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  18. * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  19. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  20. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  21. * SOFTWARE.
  22. *
  23. * Authors:
  24. * Eddie Dong <eddie.dong@intel.com>
  25. * Jike Song <jike.song@intel.com>
  26. *
  27. * Contributors:
  28. * Zhi Wang <zhi.a.wang@intel.com>
  29. * Min He <min.he@intel.com>
  30. * Bing Niu <bing.niu@intel.com>
  31. *
  32. */
  33. #include "i915_drv.h"
  34. #include "gvt.h"
  35. enum {
  36. INTEL_GVT_PCI_BAR_GTTMMIO = 0,
  37. INTEL_GVT_PCI_BAR_APERTURE,
  38. INTEL_GVT_PCI_BAR_PIO,
  39. INTEL_GVT_PCI_BAR_MAX,
  40. };
  41. /* bitmap for writable bits (RW or RW1C bits, but cannot co-exist in one
  42. * byte) byte by byte in standard pci configuration space. (not the full
  43. * 256 bytes.)
  44. */
  45. static const u8 pci_cfg_space_rw_bmp[PCI_INTERRUPT_LINE + 4] = {
  46. [PCI_COMMAND] = 0xff, 0x07,
  47. [PCI_STATUS] = 0x00, 0xf9, /* the only one RW1C byte */
  48. [PCI_CACHE_LINE_SIZE] = 0xff,
  49. [PCI_BASE_ADDRESS_0 ... PCI_CARDBUS_CIS - 1] = 0xff,
  50. [PCI_ROM_ADDRESS] = 0x01, 0xf8, 0xff, 0xff,
  51. [PCI_INTERRUPT_LINE] = 0xff,
  52. };
  53. /**
  54. * vgpu_pci_cfg_mem_write - write virtual cfg space memory
  55. *
  56. * Use this function to write virtual cfg space memory.
  57. * For standard cfg space, only RW bits can be changed,
  58. * and we emulates the RW1C behavior of PCI_STATUS register.
  59. */
  60. static void vgpu_pci_cfg_mem_write(struct intel_vgpu *vgpu, unsigned int off,
  61. u8 *src, unsigned int bytes)
  62. {
  63. u8 *cfg_base = vgpu_cfg_space(vgpu);
  64. u8 mask, new, old;
  65. int i = 0;
  66. for (; i < bytes && (off + i < sizeof(pci_cfg_space_rw_bmp)); i++) {
  67. mask = pci_cfg_space_rw_bmp[off + i];
  68. old = cfg_base[off + i];
  69. new = src[i] & mask;
  70. /**
  71. * The PCI_STATUS high byte has RW1C bits, here
  72. * emulates clear by writing 1 for these bits.
  73. * Writing a 0b to RW1C bits has no effect.
  74. */
  75. if (off + i == PCI_STATUS + 1)
  76. new = (~new & old) & mask;
  77. cfg_base[off + i] = (old & ~mask) | new;
  78. }
  79. /* For other configuration space directly copy as it is. */
  80. if (i < bytes)
  81. memcpy(cfg_base + off + i, src + i, bytes - i);
  82. }
  83. /**
  84. * intel_vgpu_emulate_cfg_read - emulate vGPU configuration space read
  85. *
  86. * Returns:
  87. * Zero on success, negative error code if failed.
  88. */
  89. int intel_vgpu_emulate_cfg_read(struct intel_vgpu *vgpu, unsigned int offset,
  90. void *p_data, unsigned int bytes)
  91. {
  92. if (WARN_ON(bytes > 4))
  93. return -EINVAL;
  94. if (WARN_ON(offset + bytes > vgpu->gvt->device_info.cfg_space_size))
  95. return -EINVAL;
  96. memcpy(p_data, vgpu_cfg_space(vgpu) + offset, bytes);
  97. return 0;
  98. }
  99. static int map_aperture(struct intel_vgpu *vgpu, bool map)
  100. {
  101. phys_addr_t aperture_pa = vgpu_aperture_pa_base(vgpu);
  102. unsigned long aperture_sz = vgpu_aperture_sz(vgpu);
  103. u64 first_gfn;
  104. u64 val;
  105. int ret;
  106. if (map == vgpu->cfg_space.bar[INTEL_GVT_PCI_BAR_APERTURE].tracked)
  107. return 0;
  108. val = vgpu_cfg_space(vgpu)[PCI_BASE_ADDRESS_2];
  109. if (val & PCI_BASE_ADDRESS_MEM_TYPE_64)
  110. val = *(u64 *)(vgpu_cfg_space(vgpu) + PCI_BASE_ADDRESS_2);
  111. else
  112. val = *(u32 *)(vgpu_cfg_space(vgpu) + PCI_BASE_ADDRESS_2);
  113. first_gfn = (val + vgpu_aperture_offset(vgpu)) >> PAGE_SHIFT;
  114. ret = intel_gvt_hypervisor_map_gfn_to_mfn(vgpu, first_gfn,
  115. aperture_pa >> PAGE_SHIFT,
  116. aperture_sz >> PAGE_SHIFT,
  117. map);
  118. if (ret)
  119. return ret;
  120. vgpu->cfg_space.bar[INTEL_GVT_PCI_BAR_APERTURE].tracked = map;
  121. return 0;
  122. }
  123. static int trap_gttmmio(struct intel_vgpu *vgpu, bool trap)
  124. {
  125. u64 start, end;
  126. u64 val;
  127. int ret;
  128. if (trap == vgpu->cfg_space.bar[INTEL_GVT_PCI_BAR_GTTMMIO].tracked)
  129. return 0;
  130. val = vgpu_cfg_space(vgpu)[PCI_BASE_ADDRESS_0];
  131. if (val & PCI_BASE_ADDRESS_MEM_TYPE_64)
  132. start = *(u64 *)(vgpu_cfg_space(vgpu) + PCI_BASE_ADDRESS_0);
  133. else
  134. start = *(u32 *)(vgpu_cfg_space(vgpu) + PCI_BASE_ADDRESS_0);
  135. start &= ~GENMASK(3, 0);
  136. end = start + vgpu->cfg_space.bar[INTEL_GVT_PCI_BAR_GTTMMIO].size - 1;
  137. ret = intel_gvt_hypervisor_set_trap_area(vgpu, start, end, trap);
  138. if (ret)
  139. return ret;
  140. vgpu->cfg_space.bar[INTEL_GVT_PCI_BAR_GTTMMIO].tracked = trap;
  141. return 0;
  142. }
  143. static int emulate_pci_command_write(struct intel_vgpu *vgpu,
  144. unsigned int offset, void *p_data, unsigned int bytes)
  145. {
  146. u8 old = vgpu_cfg_space(vgpu)[offset];
  147. u8 new = *(u8 *)p_data;
  148. u8 changed = old ^ new;
  149. int ret;
  150. vgpu_pci_cfg_mem_write(vgpu, offset, p_data, bytes);
  151. if (!(changed & PCI_COMMAND_MEMORY))
  152. return 0;
  153. if (old & PCI_COMMAND_MEMORY) {
  154. ret = trap_gttmmio(vgpu, false);
  155. if (ret)
  156. return ret;
  157. ret = map_aperture(vgpu, false);
  158. if (ret)
  159. return ret;
  160. } else {
  161. ret = trap_gttmmio(vgpu, true);
  162. if (ret)
  163. return ret;
  164. ret = map_aperture(vgpu, true);
  165. if (ret)
  166. return ret;
  167. }
  168. return 0;
  169. }
  170. static int emulate_pci_rom_bar_write(struct intel_vgpu *vgpu,
  171. unsigned int offset, void *p_data, unsigned int bytes)
  172. {
  173. u32 *pval = (u32 *)(vgpu_cfg_space(vgpu) + offset);
  174. u32 new = *(u32 *)(p_data);
  175. if ((new & PCI_ROM_ADDRESS_MASK) == PCI_ROM_ADDRESS_MASK)
  176. /* We don't have rom, return size of 0. */
  177. *pval = 0;
  178. else
  179. vgpu_pci_cfg_mem_write(vgpu, offset, p_data, bytes);
  180. return 0;
  181. }
  182. static int emulate_pci_bar_write(struct intel_vgpu *vgpu, unsigned int offset,
  183. void *p_data, unsigned int bytes)
  184. {
  185. u32 new = *(u32 *)(p_data);
  186. bool lo = IS_ALIGNED(offset, 8);
  187. u64 size;
  188. int ret = 0;
  189. bool mmio_enabled =
  190. vgpu_cfg_space(vgpu)[PCI_COMMAND] & PCI_COMMAND_MEMORY;
  191. struct intel_vgpu_pci_bar *bars = vgpu->cfg_space.bar;
  192. /*
  193. * Power-up software can determine how much address
  194. * space the device requires by writing a value of
  195. * all 1's to the register and then reading the value
  196. * back. The device will return 0's in all don't-care
  197. * address bits.
  198. */
  199. if (new == 0xffffffff) {
  200. switch (offset) {
  201. case PCI_BASE_ADDRESS_0:
  202. case PCI_BASE_ADDRESS_1:
  203. size = ~(bars[INTEL_GVT_PCI_BAR_GTTMMIO].size -1);
  204. intel_vgpu_write_pci_bar(vgpu, offset,
  205. size >> (lo ? 0 : 32), lo);
  206. /*
  207. * Untrap the BAR, since guest hasn't configured a
  208. * valid GPA
  209. */
  210. ret = trap_gttmmio(vgpu, false);
  211. break;
  212. case PCI_BASE_ADDRESS_2:
  213. case PCI_BASE_ADDRESS_3:
  214. size = ~(bars[INTEL_GVT_PCI_BAR_APERTURE].size -1);
  215. intel_vgpu_write_pci_bar(vgpu, offset,
  216. size >> (lo ? 0 : 32), lo);
  217. ret = map_aperture(vgpu, false);
  218. break;
  219. default:
  220. /* Unimplemented BARs */
  221. intel_vgpu_write_pci_bar(vgpu, offset, 0x0, false);
  222. }
  223. } else {
  224. switch (offset) {
  225. case PCI_BASE_ADDRESS_0:
  226. case PCI_BASE_ADDRESS_1:
  227. /*
  228. * Untrap the old BAR first, since guest has
  229. * re-configured the BAR
  230. */
  231. trap_gttmmio(vgpu, false);
  232. intel_vgpu_write_pci_bar(vgpu, offset, new, lo);
  233. ret = trap_gttmmio(vgpu, mmio_enabled);
  234. break;
  235. case PCI_BASE_ADDRESS_2:
  236. case PCI_BASE_ADDRESS_3:
  237. map_aperture(vgpu, false);
  238. intel_vgpu_write_pci_bar(vgpu, offset, new, lo);
  239. ret = map_aperture(vgpu, mmio_enabled);
  240. break;
  241. default:
  242. intel_vgpu_write_pci_bar(vgpu, offset, new, lo);
  243. }
  244. }
  245. return ret;
  246. }
  247. /**
  248. * intel_vgpu_emulate_cfg_read - emulate vGPU configuration space write
  249. *
  250. * Returns:
  251. * Zero on success, negative error code if failed.
  252. */
  253. int intel_vgpu_emulate_cfg_write(struct intel_vgpu *vgpu, unsigned int offset,
  254. void *p_data, unsigned int bytes)
  255. {
  256. int ret;
  257. if (WARN_ON(bytes > 4))
  258. return -EINVAL;
  259. if (WARN_ON(offset + bytes > vgpu->gvt->device_info.cfg_space_size))
  260. return -EINVAL;
  261. /* First check if it's PCI_COMMAND */
  262. if (IS_ALIGNED(offset, 2) && offset == PCI_COMMAND) {
  263. if (WARN_ON(bytes > 2))
  264. return -EINVAL;
  265. return emulate_pci_command_write(vgpu, offset, p_data, bytes);
  266. }
  267. switch (rounddown(offset, 4)) {
  268. case PCI_ROM_ADDRESS:
  269. if (WARN_ON(!IS_ALIGNED(offset, 4)))
  270. return -EINVAL;
  271. return emulate_pci_rom_bar_write(vgpu, offset, p_data, bytes);
  272. case PCI_BASE_ADDRESS_0 ... PCI_BASE_ADDRESS_5:
  273. if (WARN_ON(!IS_ALIGNED(offset, 4)))
  274. return -EINVAL;
  275. return emulate_pci_bar_write(vgpu, offset, p_data, bytes);
  276. case INTEL_GVT_PCI_SWSCI:
  277. if (WARN_ON(!IS_ALIGNED(offset, 4)))
  278. return -EINVAL;
  279. ret = intel_vgpu_emulate_opregion_request(vgpu, *(u32 *)p_data);
  280. if (ret)
  281. return ret;
  282. break;
  283. case INTEL_GVT_PCI_OPREGION:
  284. if (WARN_ON(!IS_ALIGNED(offset, 4)))
  285. return -EINVAL;
  286. ret = intel_vgpu_opregion_base_write_handler(vgpu,
  287. *(u32 *)p_data);
  288. if (ret)
  289. return ret;
  290. vgpu_pci_cfg_mem_write(vgpu, offset, p_data, bytes);
  291. break;
  292. default:
  293. vgpu_pci_cfg_mem_write(vgpu, offset, p_data, bytes);
  294. break;
  295. }
  296. return 0;
  297. }
  298. /**
  299. * intel_vgpu_init_cfg_space - init vGPU configuration space when create vGPU
  300. *
  301. * @vgpu: a vGPU
  302. * @primary: is the vGPU presented as primary
  303. *
  304. */
  305. void intel_vgpu_init_cfg_space(struct intel_vgpu *vgpu,
  306. bool primary)
  307. {
  308. struct intel_gvt *gvt = vgpu->gvt;
  309. const struct intel_gvt_device_info *info = &gvt->device_info;
  310. u16 *gmch_ctl;
  311. memcpy(vgpu_cfg_space(vgpu), gvt->firmware.cfg_space,
  312. info->cfg_space_size);
  313. if (!primary) {
  314. vgpu_cfg_space(vgpu)[PCI_CLASS_DEVICE] =
  315. INTEL_GVT_PCI_CLASS_VGA_OTHER;
  316. vgpu_cfg_space(vgpu)[PCI_CLASS_PROG] =
  317. INTEL_GVT_PCI_CLASS_VGA_OTHER;
  318. }
  319. /* Show guest that there isn't any stolen memory.*/
  320. gmch_ctl = (u16 *)(vgpu_cfg_space(vgpu) + INTEL_GVT_PCI_GMCH_CONTROL);
  321. *gmch_ctl &= ~(BDW_GMCH_GMS_MASK << BDW_GMCH_GMS_SHIFT);
  322. intel_vgpu_write_pci_bar(vgpu, PCI_BASE_ADDRESS_2,
  323. gvt_aperture_pa_base(gvt), true);
  324. vgpu_cfg_space(vgpu)[PCI_COMMAND] &= ~(PCI_COMMAND_IO
  325. | PCI_COMMAND_MEMORY
  326. | PCI_COMMAND_MASTER);
  327. /*
  328. * Clear the bar upper 32bit and let guest to assign the new value
  329. */
  330. memset(vgpu_cfg_space(vgpu) + PCI_BASE_ADDRESS_1, 0, 4);
  331. memset(vgpu_cfg_space(vgpu) + PCI_BASE_ADDRESS_3, 0, 4);
  332. memset(vgpu_cfg_space(vgpu) + PCI_BASE_ADDRESS_4, 0, 8);
  333. memset(vgpu_cfg_space(vgpu) + INTEL_GVT_PCI_OPREGION, 0, 4);
  334. vgpu->cfg_space.bar[INTEL_GVT_PCI_BAR_GTTMMIO].size =
  335. pci_resource_len(gvt->dev_priv->drm.pdev, 0);
  336. vgpu->cfg_space.bar[INTEL_GVT_PCI_BAR_APERTURE].size =
  337. pci_resource_len(gvt->dev_priv->drm.pdev, 2);
  338. memset(vgpu_cfg_space(vgpu) + PCI_ROM_ADDRESS, 0, 4);
  339. }
  340. /**
  341. * intel_vgpu_reset_cfg_space - reset vGPU configuration space
  342. *
  343. * @vgpu: a vGPU
  344. *
  345. */
  346. void intel_vgpu_reset_cfg_space(struct intel_vgpu *vgpu)
  347. {
  348. u8 cmd = vgpu_cfg_space(vgpu)[PCI_COMMAND];
  349. bool primary = vgpu_cfg_space(vgpu)[PCI_CLASS_DEVICE] !=
  350. INTEL_GVT_PCI_CLASS_VGA_OTHER;
  351. if (cmd & PCI_COMMAND_MEMORY) {
  352. trap_gttmmio(vgpu, false);
  353. map_aperture(vgpu, false);
  354. }
  355. /**
  356. * Currently we only do such reset when vGPU is not
  357. * owned by any VM, so we simply restore entire cfg
  358. * space to default value.
  359. */
  360. intel_vgpu_init_cfg_space(vgpu, primary);
  361. }