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 24 #include "i915_drv.h" 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> 32 33 /** 34 * DOC: Intel GVT-g host support 35 * 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. 41 * 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. 46 */ 47 48 static LIST_HEAD(intel_gvt_devices); 49 static const struct intel_vgpu_ops *intel_gvt_ops; 50 static DEFINE_MUTEX(intel_gvt_mutex); 51 52 static bool is_supported_device(struct drm_i915_private *dev_priv) 53 { 54 if (IS_BROADWELL(dev_priv)) 55 return true; 56 if (IS_SKYLAKE(dev_priv)) 57 return true; 58 if (IS_KABYLAKE(dev_priv)) 59 return true; 60 if (IS_BROXTON(dev_priv)) 61 return true; 62 if (IS_COFFEELAKE(dev_priv)) 63 return true; 64 if (IS_COMETLAKE(dev_priv)) 65 return true; 66 67 return false; 68 } 69 70 static void free_initial_hw_state(struct drm_i915_private *dev_priv) 71 { 72 struct i915_virtual_gpu *vgpu = &dev_priv->vgpu; 73 74 vfree(vgpu->initial_mmio); 75 vgpu->initial_mmio = NULL; 76 77 kfree(vgpu->initial_cfg_space); 78 vgpu->initial_cfg_space = NULL; 79 } 80 81 static void save_mmio(struct intel_gvt_mmio_table_iter *iter, u32 offset, 82 u32 size) 83 { 84 struct drm_i915_private *dev_priv = iter->i915; 85 u32 *mmio, i; 86 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, 90 _MMIO(i)); 91 } 92 } 93 94 static int handle_mmio(struct intel_gvt_mmio_table_iter *iter, 95 u32 offset, u32 size) 96 { 97 if (WARN_ON(!IS_ALIGNED(offset, 4))) 98 return -EINVAL; 99 100 save_mmio(iter, offset, size); 101 return 0; 102 } 103 104 static int save_initial_hw_state(struct drm_i915_private *dev_priv) 105 { 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; 109 void *mem; 110 int i, ret; 111 112 mem = kzalloc(PCI_CFG_SPACE_EXP_SIZE, GFP_KERNEL); 113 if (!mem) 114 return -ENOMEM; 115 116 vgpu->initial_cfg_space = mem; 117 118 for (i = 0; i < PCI_CFG_SPACE_EXP_SIZE; i += 4) 119 pci_read_config_dword(pdev, i, mem + i); 120 121 mem = vzalloc(2 * SZ_1M); 122 if (!mem) { 123 ret = -ENOMEM; 124 goto err_mmio; 125 } 126 127 vgpu->initial_mmio = mem; 128 129 iter.i915 = dev_priv; 130 iter.data = vgpu->initial_mmio; 131 iter.handle_mmio_cb = handle_mmio; 132 133 ret = intel_gvt_iterate_mmio_table(&iter); 134 if (ret) 135 goto err_iterate; 136 137 return 0; 138 139 err_iterate: 140 vfree(vgpu->initial_mmio); 141 vgpu->initial_mmio = NULL; 142 err_mmio: 143 kfree(vgpu->initial_cfg_space); 144 vgpu->initial_cfg_space = NULL; 145 146 return ret; 147 } 148 149 static void intel_gvt_init_device(struct drm_i915_private *dev_priv) 150 { 151 if (!dev_priv->params.enable_gvt) { 152 drm_dbg(&dev_priv->drm, 153 "GVT-g is disabled by kernel params\n"); 154 return; 155 } 156 157 if (intel_vgpu_active(dev_priv)) { 158 drm_info(&dev_priv->drm, "GVT-g is disabled for guest\n"); 159 return; 160 } 161 162 if (!is_supported_device(dev_priv)) { 163 drm_info(&dev_priv->drm, 164 "Unsupported device. GVT-g is disabled\n"); 165 return; 166 } 167 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"); 171 return; 172 } 173 174 if (save_initial_hw_state(dev_priv)) { 175 drm_dbg(&dev_priv->drm, "Failed to save initial HW state\n"); 176 return; 177 } 178 179 if (intel_gvt_ops->init_device(dev_priv)) 180 drm_dbg(&dev_priv->drm, "Fail to init GVT device\n"); 181 } 182 183 static void intel_gvt_clean_device(struct drm_i915_private *dev_priv) 184 { 185 if (dev_priv->gvt) 186 intel_gvt_ops->clean_device(dev_priv); 187 free_initial_hw_state(dev_priv); 188 } 189 190 int intel_gvt_set_ops(const struct intel_vgpu_ops *ops) 191 { 192 struct drm_i915_private *dev_priv; 193 194 mutex_lock(&intel_gvt_mutex); 195 if (intel_gvt_ops) { 196 mutex_unlock(&intel_gvt_mutex); 197 return -EINVAL; 198 } 199 intel_gvt_ops = ops; 200 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); 204 205 return 0; 206 } 207 EXPORT_SYMBOL_NS_GPL(intel_gvt_set_ops, I915_GVT); 208 209 void intel_gvt_clear_ops(const struct intel_vgpu_ops *ops) 210 { 211 struct drm_i915_private *dev_priv; 212 213 mutex_lock(&intel_gvt_mutex); 214 if (intel_gvt_ops != ops) { 215 mutex_unlock(&intel_gvt_mutex); 216 return; 217 } 218 219 list_for_each_entry(dev_priv, &intel_gvt_devices, vgpu.entry) 220 intel_gvt_clean_device(dev_priv); 221 222 intel_gvt_ops = NULL; 223 mutex_unlock(&intel_gvt_mutex); 224 } 225 EXPORT_SYMBOL_NS_GPL(intel_gvt_clear_ops, I915_GVT); 226 227 /** 228 * intel_gvt_init - initialize GVT components 229 * @dev_priv: drm i915 private data 230 * 231 * This function is called at the initialization stage to create a GVT device. 232 * 233 * Returns: 234 * Zero on success, negative error code if failed. 235 * 236 */ 237 int intel_gvt_init(struct drm_i915_private *dev_priv) 238 { 239 if (i915_inject_probe_failure(dev_priv)) 240 return -ENODEV; 241 242 mutex_lock(&intel_gvt_mutex); 243 list_add_tail(&dev_priv->vgpu.entry, &intel_gvt_devices); 244 if (intel_gvt_ops) 245 intel_gvt_init_device(dev_priv); 246 mutex_unlock(&intel_gvt_mutex); 247 248 return 0; 249 } 250 251 /** 252 * intel_gvt_driver_remove - cleanup GVT components when i915 driver is 253 * unbinding 254 * @dev_priv: drm i915 private * 255 * 256 * This function is called at the i915 driver unloading stage, to shutdown 257 * GVT components and release the related resources. 258 */ 259 void intel_gvt_driver_remove(struct drm_i915_private *dev_priv) 260 { 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); 265 } 266 267 /** 268 * intel_gvt_resume - GVT resume routine wapper 269 * 270 * @dev_priv: drm i915 private * 271 * 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. 274 */ 275 void intel_gvt_resume(struct drm_i915_private *dev_priv) 276 { 277 mutex_lock(&intel_gvt_mutex); 278 if (dev_priv->gvt) 279 intel_gvt_ops->pm_resume(dev_priv); 280 mutex_unlock(&intel_gvt_mutex); 281 } 282 283 /* 284 * Exported here so that the exports only get created when GVT support is 285 * actually enabled. 286 */ 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); 315 #endif 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); 324