2 * Copyright(c) 2011-2016 Intel Corporation. All rights reserved.
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:
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
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
25 #include "i915_vgpu.h"
26 #include "intel_gvt.h"
27 #include "gem/i915_gem_dmabuf.h"
28 #include "gt/intel_context.h"
29 #include "gt/intel_ring.h"
30 #include "gt/shmem_utils.h"
31 #include <linux/vmalloc.h>
34 * DOC: Intel GVT-g host support
36 * Intel GVT-g is a graphics virtualization technology which shares the
37 * GPU among multiple virtual machines on a time-sharing basis. Each
38 * virtual machine is presented a virtual GPU (vGPU), which has equivalent
39 * features as the underlying physical GPU (pGPU), so i915 driver can run
40 * seamlessly in a virtual machine.
42 * To virtualize GPU resources GVT-g driver depends on hypervisor technology
43 * e.g KVM/VFIO/mdev, Xen, etc. to provide resource access trapping capability
44 * and be virtualized within GVT-g device module. More architectural design
45 * doc is available on https://github.com/intel/gvt-linux/wiki.
48 static LIST_HEAD(intel_gvt_devices
);
49 static const struct intel_vgpu_ops
*intel_gvt_ops
;
50 static DEFINE_MUTEX(intel_gvt_mutex
);
52 static bool is_supported_device(struct drm_i915_private
*dev_priv
)
54 if (IS_BROADWELL(dev_priv
))
56 if (IS_SKYLAKE(dev_priv
))
58 if (IS_KABYLAKE(dev_priv
))
60 if (IS_BROXTON(dev_priv
))
62 if (IS_COFFEELAKE(dev_priv
))
64 if (IS_COMETLAKE(dev_priv
))
70 static void free_initial_hw_state(struct drm_i915_private
*dev_priv
)
72 struct i915_virtual_gpu
*vgpu
= &dev_priv
->vgpu
;
74 vfree(vgpu
->initial_mmio
);
75 vgpu
->initial_mmio
= NULL
;
77 kfree(vgpu
->initial_cfg_space
);
78 vgpu
->initial_cfg_space
= NULL
;
81 static void save_mmio(struct intel_gvt_mmio_table_iter
*iter
, u32 offset
,
84 struct drm_i915_private
*dev_priv
= iter
->i915
;
87 for (i
= offset
; i
< offset
+ size
; i
+= 4) {
88 mmio
= iter
->data
+ i
;
89 *mmio
= intel_uncore_read_notrace(to_gt(dev_priv
)->uncore
,
94 static int handle_mmio(struct intel_gvt_mmio_table_iter
*iter
,
97 if (WARN_ON(!IS_ALIGNED(offset
, 4)))
100 save_mmio(iter
, offset
, size
);
104 static int save_initial_hw_state(struct drm_i915_private
*dev_priv
)
106 struct pci_dev
*pdev
= to_pci_dev(dev_priv
->drm
.dev
);
107 struct i915_virtual_gpu
*vgpu
= &dev_priv
->vgpu
;
108 struct intel_gvt_mmio_table_iter iter
;
112 mem
= kzalloc(PCI_CFG_SPACE_EXP_SIZE
, GFP_KERNEL
);
116 vgpu
->initial_cfg_space
= mem
;
118 for (i
= 0; i
< PCI_CFG_SPACE_EXP_SIZE
; i
+= 4)
119 pci_read_config_dword(pdev
, i
, mem
+ i
);
121 mem
= vzalloc(2 * SZ_1M
);
127 vgpu
->initial_mmio
= mem
;
129 iter
.i915
= dev_priv
;
130 iter
.data
= vgpu
->initial_mmio
;
131 iter
.handle_mmio_cb
= handle_mmio
;
133 ret
= intel_gvt_iterate_mmio_table(&iter
);
140 vfree(vgpu
->initial_mmio
);
141 vgpu
->initial_mmio
= NULL
;
143 kfree(vgpu
->initial_cfg_space
);
144 vgpu
->initial_cfg_space
= NULL
;
149 static void intel_gvt_init_device(struct drm_i915_private
*dev_priv
)
151 if (!dev_priv
->params
.enable_gvt
) {
152 drm_dbg(&dev_priv
->drm
,
153 "GVT-g is disabled by kernel params\n");
157 if (intel_vgpu_active(dev_priv
)) {
158 drm_info(&dev_priv
->drm
, "GVT-g is disabled for guest\n");
162 if (!is_supported_device(dev_priv
)) {
163 drm_info(&dev_priv
->drm
,
164 "Unsupported device. GVT-g is disabled\n");
168 if (intel_uc_wants_guc_submission(&to_gt(dev_priv
)->uc
)) {
169 drm_err(&dev_priv
->drm
,
170 "Graphics virtualization is not yet supported with GuC submission\n");
174 if (save_initial_hw_state(dev_priv
)) {
175 drm_dbg(&dev_priv
->drm
, "Failed to save initial HW state\n");
179 if (intel_gvt_ops
->init_device(dev_priv
))
180 drm_dbg(&dev_priv
->drm
, "Fail to init GVT device\n");
183 static void intel_gvt_clean_device(struct drm_i915_private
*dev_priv
)
186 intel_gvt_ops
->clean_device(dev_priv
);
187 free_initial_hw_state(dev_priv
);
190 int intel_gvt_set_ops(const struct intel_vgpu_ops
*ops
)
192 struct drm_i915_private
*dev_priv
;
194 mutex_lock(&intel_gvt_mutex
);
196 mutex_unlock(&intel_gvt_mutex
);
201 list_for_each_entry(dev_priv
, &intel_gvt_devices
, vgpu
.entry
)
202 intel_gvt_init_device(dev_priv
);
203 mutex_unlock(&intel_gvt_mutex
);
207 EXPORT_SYMBOL_NS_GPL(intel_gvt_set_ops
, "I915_GVT");
209 void intel_gvt_clear_ops(const struct intel_vgpu_ops
*ops
)
211 struct drm_i915_private
*dev_priv
;
213 mutex_lock(&intel_gvt_mutex
);
214 if (intel_gvt_ops
!= ops
) {
215 mutex_unlock(&intel_gvt_mutex
);
219 list_for_each_entry(dev_priv
, &intel_gvt_devices
, vgpu
.entry
)
220 intel_gvt_clean_device(dev_priv
);
222 intel_gvt_ops
= NULL
;
223 mutex_unlock(&intel_gvt_mutex
);
225 EXPORT_SYMBOL_NS_GPL(intel_gvt_clear_ops
, "I915_GVT");
228 * intel_gvt_init - initialize GVT components
229 * @dev_priv: drm i915 private data
231 * This function is called at the initialization stage to create a GVT device.
234 * Zero on success, negative error code if failed.
237 int intel_gvt_init(struct drm_i915_private
*dev_priv
)
239 if (i915_inject_probe_failure(dev_priv
))
242 mutex_lock(&intel_gvt_mutex
);
243 list_add_tail(&dev_priv
->vgpu
.entry
, &intel_gvt_devices
);
245 intel_gvt_init_device(dev_priv
);
246 mutex_unlock(&intel_gvt_mutex
);
252 * intel_gvt_driver_remove - cleanup GVT components when i915 driver is
254 * @dev_priv: drm i915 private *
256 * This function is called at the i915 driver unloading stage, to shutdown
257 * GVT components and release the related resources.
259 void intel_gvt_driver_remove(struct drm_i915_private
*dev_priv
)
261 mutex_lock(&intel_gvt_mutex
);
262 intel_gvt_clean_device(dev_priv
);
263 list_del(&dev_priv
->vgpu
.entry
);
264 mutex_unlock(&intel_gvt_mutex
);
268 * intel_gvt_resume - GVT resume routine wapper
270 * @dev_priv: drm i915 private *
272 * This function is called at the i915 driver resume stage to restore required
273 * HW status for GVT so that vGPU can continue running after resumed.
275 void intel_gvt_resume(struct drm_i915_private
*dev_priv
)
277 mutex_lock(&intel_gvt_mutex
);
279 intel_gvt_ops
->pm_resume(dev_priv
);
280 mutex_unlock(&intel_gvt_mutex
);
284 * Exported here so that the exports only get created when GVT support is
287 EXPORT_SYMBOL_NS_GPL(i915_gem_object_alloc
, "I915_GVT");
288 EXPORT_SYMBOL_NS_GPL(i915_gem_object_create_shmem
, "I915_GVT");
289 EXPORT_SYMBOL_NS_GPL(i915_gem_object_init
, "I915_GVT");
290 EXPORT_SYMBOL_NS_GPL(i915_gem_object_ggtt_pin_ww
, "I915_GVT");
291 EXPORT_SYMBOL_NS_GPL(i915_gem_object_pin_map
, "I915_GVT");
292 EXPORT_SYMBOL_NS_GPL(i915_gem_object_set_to_cpu_domain
, "I915_GVT");
293 EXPORT_SYMBOL_NS_GPL(__i915_gem_object_flush_map
, "I915_GVT");
294 EXPORT_SYMBOL_NS_GPL(__i915_gem_object_set_pages
, "I915_GVT");
295 EXPORT_SYMBOL_NS_GPL(i915_gem_gtt_insert
, "I915_GVT");
296 EXPORT_SYMBOL_NS_GPL(i915_gem_prime_export
, "I915_GVT");
297 EXPORT_SYMBOL_NS_GPL(i915_gem_ww_ctx_init
, "I915_GVT");
298 EXPORT_SYMBOL_NS_GPL(i915_gem_ww_ctx_backoff
, "I915_GVT");
299 EXPORT_SYMBOL_NS_GPL(i915_gem_ww_ctx_fini
, "I915_GVT");
300 EXPORT_SYMBOL_NS_GPL(i915_ppgtt_create
, "I915_GVT");
301 EXPORT_SYMBOL_NS_GPL(i915_request_add
, "I915_GVT");
302 EXPORT_SYMBOL_NS_GPL(i915_request_create
, "I915_GVT");
303 EXPORT_SYMBOL_NS_GPL(i915_request_wait
, "I915_GVT");
304 EXPORT_SYMBOL_NS_GPL(i915_reserve_fence
, "I915_GVT");
305 EXPORT_SYMBOL_NS_GPL(i915_unreserve_fence
, "I915_GVT");
306 EXPORT_SYMBOL_NS_GPL(i915_vm_release
, "I915_GVT");
307 EXPORT_SYMBOL_NS_GPL(_i915_vma_move_to_active
, "I915_GVT");
308 EXPORT_SYMBOL_NS_GPL(intel_context_create
, "I915_GVT");
309 EXPORT_SYMBOL_NS_GPL(__intel_context_do_pin
, "I915_GVT");
310 EXPORT_SYMBOL_NS_GPL(__intel_context_do_unpin
, "I915_GVT");
311 EXPORT_SYMBOL_NS_GPL(intel_ring_begin
, "I915_GVT");
312 EXPORT_SYMBOL_NS_GPL(intel_runtime_pm_get
, "I915_GVT");
313 #if IS_ENABLED(CONFIG_DRM_I915_DEBUG_RUNTIME_PM)
314 EXPORT_SYMBOL_NS_GPL(intel_runtime_pm_put
, "I915_GVT");
316 EXPORT_SYMBOL_NS_GPL(intel_runtime_pm_put_unchecked
, "I915_GVT");
317 EXPORT_SYMBOL_NS_GPL(intel_uncore_forcewake_for_reg
, "I915_GVT");
318 EXPORT_SYMBOL_NS_GPL(intel_uncore_forcewake_get
, "I915_GVT");
319 EXPORT_SYMBOL_NS_GPL(intel_uncore_forcewake_put
, "I915_GVT");
320 EXPORT_SYMBOL_NS_GPL(shmem_pin_map
, "I915_GVT");
321 EXPORT_SYMBOL_NS_GPL(shmem_unpin_map
, "I915_GVT");
322 EXPORT_SYMBOL_NS_GPL(__px_dma
, "I915_GVT");
323 EXPORT_SYMBOL_NS_GPL(i915_fence_ops
, "I915_GVT");