intel_gvt.c 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325
  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. #include <linux/vmalloc.h>
  24. #include <drm/drm_print.h>
  25. #include "gem/i915_gem_dmabuf.h"
  26. #include "gt/intel_context.h"
  27. #include "gt/intel_ring.h"
  28. #include "gt/shmem_utils.h"
  29. #include "i915_drv.h"
  30. #include "i915_vgpu.h"
  31. #include "intel_gvt.h"
  32. /**
  33. * DOC: Intel GVT-g host support
  34. *
  35. * Intel GVT-g is a graphics virtualization technology which shares the
  36. * GPU among multiple virtual machines on a time-sharing basis. Each
  37. * virtual machine is presented a virtual GPU (vGPU), which has equivalent
  38. * features as the underlying physical GPU (pGPU), so i915 driver can run
  39. * seamlessly in a virtual machine.
  40. *
  41. * To virtualize GPU resources GVT-g driver depends on hypervisor technology
  42. * e.g KVM/VFIO/mdev, Xen, etc. to provide resource access trapping capability
  43. * and be virtualized within GVT-g device module. More architectural design
  44. * doc is available on https://github.com/intel/gvt-linux/wiki.
  45. */
  46. static LIST_HEAD(intel_gvt_devices);
  47. static const struct intel_vgpu_ops *intel_gvt_ops;
  48. static DEFINE_MUTEX(intel_gvt_mutex);
  49. static bool is_supported_device(struct drm_i915_private *dev_priv)
  50. {
  51. if (IS_BROADWELL(dev_priv))
  52. return true;
  53. if (IS_SKYLAKE(dev_priv))
  54. return true;
  55. if (IS_KABYLAKE(dev_priv))
  56. return true;
  57. if (IS_BROXTON(dev_priv))
  58. return true;
  59. if (IS_COFFEELAKE(dev_priv))
  60. return true;
  61. if (IS_COMETLAKE(dev_priv))
  62. return true;
  63. return false;
  64. }
  65. static void free_initial_hw_state(struct drm_i915_private *dev_priv)
  66. {
  67. struct i915_virtual_gpu *vgpu = &dev_priv->vgpu;
  68. vfree(vgpu->initial_mmio);
  69. vgpu->initial_mmio = NULL;
  70. kfree(vgpu->initial_cfg_space);
  71. vgpu->initial_cfg_space = NULL;
  72. }
  73. static void save_mmio(struct intel_gvt_mmio_table_iter *iter, u32 offset,
  74. u32 size)
  75. {
  76. struct drm_i915_private *dev_priv = iter->i915;
  77. u32 *mmio, i;
  78. for (i = offset; i < offset + size; i += 4) {
  79. mmio = iter->data + i;
  80. *mmio = intel_uncore_read_notrace(to_gt(dev_priv)->uncore,
  81. _MMIO(i));
  82. }
  83. }
  84. static int handle_mmio(struct intel_gvt_mmio_table_iter *iter,
  85. u32 offset, u32 size)
  86. {
  87. if (WARN_ON(!IS_ALIGNED(offset, 4)))
  88. return -EINVAL;
  89. save_mmio(iter, offset, size);
  90. return 0;
  91. }
  92. static int save_initial_hw_state(struct drm_i915_private *dev_priv)
  93. {
  94. struct pci_dev *pdev = to_pci_dev(dev_priv->drm.dev);
  95. struct i915_virtual_gpu *vgpu = &dev_priv->vgpu;
  96. struct intel_gvt_mmio_table_iter iter;
  97. void *mem;
  98. int i, ret;
  99. mem = kzalloc(PCI_CFG_SPACE_EXP_SIZE, GFP_KERNEL);
  100. if (!mem)
  101. return -ENOMEM;
  102. vgpu->initial_cfg_space = mem;
  103. for (i = 0; i < PCI_CFG_SPACE_EXP_SIZE; i += 4)
  104. pci_read_config_dword(pdev, i, mem + i);
  105. mem = vzalloc(2 * SZ_1M);
  106. if (!mem) {
  107. ret = -ENOMEM;
  108. goto err_mmio;
  109. }
  110. vgpu->initial_mmio = mem;
  111. iter.i915 = dev_priv;
  112. iter.data = vgpu->initial_mmio;
  113. iter.handle_mmio_cb = handle_mmio;
  114. ret = intel_gvt_iterate_mmio_table(&iter);
  115. if (ret)
  116. goto err_iterate;
  117. return 0;
  118. err_iterate:
  119. vfree(vgpu->initial_mmio);
  120. vgpu->initial_mmio = NULL;
  121. err_mmio:
  122. kfree(vgpu->initial_cfg_space);
  123. vgpu->initial_cfg_space = NULL;
  124. return ret;
  125. }
  126. static void intel_gvt_init_device(struct drm_i915_private *dev_priv)
  127. {
  128. if (!dev_priv->params.enable_gvt) {
  129. drm_dbg(&dev_priv->drm,
  130. "GVT-g is disabled by kernel params\n");
  131. return;
  132. }
  133. if (intel_vgpu_active(dev_priv)) {
  134. drm_info(&dev_priv->drm, "GVT-g is disabled for guest\n");
  135. return;
  136. }
  137. if (!is_supported_device(dev_priv)) {
  138. drm_info(&dev_priv->drm,
  139. "Unsupported device. GVT-g is disabled\n");
  140. return;
  141. }
  142. if (intel_uc_wants_guc_submission(&to_gt(dev_priv)->uc)) {
  143. drm_err(&dev_priv->drm,
  144. "Graphics virtualization is not yet supported with GuC submission\n");
  145. return;
  146. }
  147. if (save_initial_hw_state(dev_priv)) {
  148. drm_dbg(&dev_priv->drm, "Failed to save initial HW state\n");
  149. return;
  150. }
  151. if (intel_gvt_ops->init_device(dev_priv))
  152. drm_dbg(&dev_priv->drm, "Fail to init GVT device\n");
  153. }
  154. static void intel_gvt_clean_device(struct drm_i915_private *dev_priv)
  155. {
  156. if (dev_priv->gvt)
  157. intel_gvt_ops->clean_device(dev_priv);
  158. free_initial_hw_state(dev_priv);
  159. }
  160. int intel_gvt_set_ops(const struct intel_vgpu_ops *ops)
  161. {
  162. struct drm_i915_private *dev_priv;
  163. mutex_lock(&intel_gvt_mutex);
  164. if (intel_gvt_ops) {
  165. mutex_unlock(&intel_gvt_mutex);
  166. return -EINVAL;
  167. }
  168. intel_gvt_ops = ops;
  169. list_for_each_entry(dev_priv, &intel_gvt_devices, vgpu.entry)
  170. intel_gvt_init_device(dev_priv);
  171. mutex_unlock(&intel_gvt_mutex);
  172. return 0;
  173. }
  174. EXPORT_SYMBOL_NS_GPL(intel_gvt_set_ops, "I915_GVT");
  175. void intel_gvt_clear_ops(const struct intel_vgpu_ops *ops)
  176. {
  177. struct drm_i915_private *dev_priv;
  178. mutex_lock(&intel_gvt_mutex);
  179. if (intel_gvt_ops != ops) {
  180. mutex_unlock(&intel_gvt_mutex);
  181. return;
  182. }
  183. list_for_each_entry(dev_priv, &intel_gvt_devices, vgpu.entry)
  184. intel_gvt_clean_device(dev_priv);
  185. intel_gvt_ops = NULL;
  186. mutex_unlock(&intel_gvt_mutex);
  187. }
  188. EXPORT_SYMBOL_NS_GPL(intel_gvt_clear_ops, "I915_GVT");
  189. /**
  190. * intel_gvt_init - initialize GVT components
  191. * @dev_priv: drm i915 private data
  192. *
  193. * This function is called at the initialization stage to create a GVT device.
  194. *
  195. * Returns:
  196. * Zero on success, negative error code if failed.
  197. *
  198. */
  199. int intel_gvt_init(struct drm_i915_private *dev_priv)
  200. {
  201. mutex_lock(&intel_gvt_mutex);
  202. list_add_tail(&dev_priv->vgpu.entry, &intel_gvt_devices);
  203. if (intel_gvt_ops)
  204. intel_gvt_init_device(dev_priv);
  205. mutex_unlock(&intel_gvt_mutex);
  206. return 0;
  207. }
  208. /**
  209. * intel_gvt_driver_remove - cleanup GVT components when i915 driver is
  210. * unbinding
  211. * @dev_priv: drm i915 private *
  212. *
  213. * This function is called at the i915 driver unloading stage, to shutdown
  214. * GVT components and release the related resources.
  215. */
  216. void intel_gvt_driver_remove(struct drm_i915_private *dev_priv)
  217. {
  218. mutex_lock(&intel_gvt_mutex);
  219. intel_gvt_clean_device(dev_priv);
  220. list_del(&dev_priv->vgpu.entry);
  221. mutex_unlock(&intel_gvt_mutex);
  222. }
  223. /**
  224. * intel_gvt_resume - GVT resume routine wrapper
  225. *
  226. * @dev_priv: drm i915 private *
  227. *
  228. * This function is called at the i915 driver resume stage to restore required
  229. * HW status for GVT so that vGPU can continue running after resumed.
  230. */
  231. void intel_gvt_resume(struct drm_i915_private *dev_priv)
  232. {
  233. mutex_lock(&intel_gvt_mutex);
  234. if (dev_priv->gvt)
  235. intel_gvt_ops->pm_resume(dev_priv);
  236. mutex_unlock(&intel_gvt_mutex);
  237. }
  238. /*
  239. * Exported here so that the exports only get created when GVT support is
  240. * actually enabled.
  241. */
  242. EXPORT_SYMBOL_NS_GPL(i915_gem_object_alloc, "I915_GVT");
  243. EXPORT_SYMBOL_NS_GPL(i915_gem_object_create_shmem, "I915_GVT");
  244. EXPORT_SYMBOL_NS_GPL(i915_gem_object_init, "I915_GVT");
  245. EXPORT_SYMBOL_NS_GPL(i915_gem_object_ggtt_pin_ww, "I915_GVT");
  246. EXPORT_SYMBOL_NS_GPL(i915_gem_object_pin_map, "I915_GVT");
  247. EXPORT_SYMBOL_NS_GPL(i915_gem_object_set_to_cpu_domain, "I915_GVT");
  248. EXPORT_SYMBOL_NS_GPL(__i915_gem_object_flush_map, "I915_GVT");
  249. EXPORT_SYMBOL_NS_GPL(__i915_gem_object_set_pages, "I915_GVT");
  250. EXPORT_SYMBOL_NS_GPL(i915_gem_gtt_insert, "I915_GVT");
  251. EXPORT_SYMBOL_NS_GPL(i915_gem_prime_export, "I915_GVT");
  252. EXPORT_SYMBOL_NS_GPL(i915_gem_ww_ctx_init, "I915_GVT");
  253. EXPORT_SYMBOL_NS_GPL(i915_gem_ww_ctx_backoff, "I915_GVT");
  254. EXPORT_SYMBOL_NS_GPL(i915_gem_ww_ctx_fini, "I915_GVT");
  255. EXPORT_SYMBOL_NS_GPL(i915_ppgtt_create, "I915_GVT");
  256. EXPORT_SYMBOL_NS_GPL(i915_request_add, "I915_GVT");
  257. EXPORT_SYMBOL_NS_GPL(i915_request_create, "I915_GVT");
  258. EXPORT_SYMBOL_NS_GPL(i915_request_wait, "I915_GVT");
  259. EXPORT_SYMBOL_NS_GPL(i915_reserve_fence, "I915_GVT");
  260. EXPORT_SYMBOL_NS_GPL(i915_unreserve_fence, "I915_GVT");
  261. EXPORT_SYMBOL_NS_GPL(i915_vm_release, "I915_GVT");
  262. EXPORT_SYMBOL_NS_GPL(_i915_vma_move_to_active, "I915_GVT");
  263. EXPORT_SYMBOL_NS_GPL(intel_context_create, "I915_GVT");
  264. EXPORT_SYMBOL_NS_GPL(__intel_context_do_pin, "I915_GVT");
  265. EXPORT_SYMBOL_NS_GPL(__intel_context_do_unpin, "I915_GVT");
  266. EXPORT_SYMBOL_NS_GPL(intel_ring_begin, "I915_GVT");
  267. EXPORT_SYMBOL_NS_GPL(intel_runtime_pm_get, "I915_GVT");
  268. #if IS_ENABLED(CONFIG_DRM_I915_DEBUG_RUNTIME_PM)
  269. EXPORT_SYMBOL_NS_GPL(intel_runtime_pm_put, "I915_GVT");
  270. #endif
  271. EXPORT_SYMBOL_NS_GPL(intel_runtime_pm_put_unchecked, "I915_GVT");
  272. EXPORT_SYMBOL_NS_GPL(intel_uncore_forcewake_for_reg, "I915_GVT");
  273. EXPORT_SYMBOL_NS_GPL(intel_uncore_forcewake_get, "I915_GVT");
  274. EXPORT_SYMBOL_NS_GPL(intel_uncore_forcewake_put, "I915_GVT");
  275. EXPORT_SYMBOL_NS_GPL(shmem_pin_map, "I915_GVT");
  276. EXPORT_SYMBOL_NS_GPL(shmem_unpin_map, "I915_GVT");
  277. EXPORT_SYMBOL_NS_GPL(__px_dma, "I915_GVT");
  278. EXPORT_SYMBOL_NS_GPL(i915_fence_ops, "I915_GVT");