diff options
Diffstat (limited to 'drivers/gpu/drm/i915/intel_gvt.c')
| -rw-r--r-- | drivers/gpu/drm/i915/intel_gvt.c | 252 | 
1 files changed, 205 insertions, 47 deletions
diff --git a/drivers/gpu/drm/i915/intel_gvt.c b/drivers/gpu/drm/i915/intel_gvt.c index cf6e98962d82..e98b6d69a91a 100644 --- a/drivers/gpu/drm/i915/intel_gvt.c +++ b/drivers/gpu/drm/i915/intel_gvt.c @@ -24,7 +24,10 @@  #include "i915_drv.h"  #include "i915_vgpu.h"  #include "intel_gvt.h" -#include "gvt/gvt.h" +#include "gem/i915_gem_dmabuf.h" +#include "gt/intel_context.h" +#include "gt/intel_ring.h" +#include "gt/shmem_utils.h"  /**   * DOC: Intel GVT-g host support @@ -41,6 +44,10 @@   * doc is available on https://01.org/group/2230/documentation-list.   */ +static LIST_HEAD(intel_gvt_devices); +static const struct intel_vgpu_ops *intel_gvt_ops; +static DEFINE_MUTEX(intel_gvt_mutex); +  static bool is_supported_device(struct drm_i915_private *dev_priv)  {  	if (IS_BROADWELL(dev_priv)) @@ -59,32 +66,162 @@ static bool is_supported_device(struct drm_i915_private *dev_priv)  	return false;  } -/** - * intel_gvt_sanitize_options - sanitize GVT related options - * @dev_priv: drm i915 private data - * - * This function is called at the i915 options sanitize stage. - */ -void intel_gvt_sanitize_options(struct drm_i915_private *dev_priv) +static void free_initial_hw_state(struct drm_i915_private *dev_priv) +{ +	struct i915_virtual_gpu *vgpu = &dev_priv->vgpu; + +	vfree(vgpu->initial_mmio); +	vgpu->initial_mmio = NULL; + +	kfree(vgpu->initial_cfg_space); +	vgpu->initial_cfg_space = NULL; +} + +static void save_mmio(struct intel_gvt_mmio_table_iter *iter, u32 offset, +		      u32 size) +{ +	struct drm_i915_private *dev_priv = iter->i915; +	u32 *mmio, i; + +	for (i = offset; i < offset + size; i += 4) { +		mmio = iter->data + i; +		*mmio = intel_uncore_read_notrace(to_gt(dev_priv)->uncore, +						  _MMIO(i)); +	} +} + +static int handle_mmio(struct intel_gvt_mmio_table_iter *iter, +		       u32 offset, u32 size) +{ +	if (WARN_ON(!IS_ALIGNED(offset, 4))) +		return -EINVAL; + +	save_mmio(iter, offset, size); +	return 0; +} + +static int save_initial_hw_state(struct drm_i915_private *dev_priv) +{ +	struct pci_dev *pdev = to_pci_dev(dev_priv->drm.dev); +	struct i915_virtual_gpu *vgpu = &dev_priv->vgpu; +	struct intel_gvt_mmio_table_iter iter; +	void *mem; +	int i, ret; + +	mem = kzalloc(PCI_CFG_SPACE_EXP_SIZE, GFP_KERNEL); +	if (!mem) +		return -ENOMEM; + +	vgpu->initial_cfg_space = mem; + +	for (i = 0; i < PCI_CFG_SPACE_EXP_SIZE; i += 4) +		pci_read_config_dword(pdev, i, mem + i); + +	mem = vzalloc(2 * SZ_1M); +	if (!mem) { +		ret = -ENOMEM; +		goto err_mmio; +	} + +	vgpu->initial_mmio = mem; + +	iter.i915 = dev_priv; +	iter.data = vgpu->initial_mmio; +	iter.handle_mmio_cb = handle_mmio; + +	ret = intel_gvt_iterate_mmio_table(&iter); +	if (ret) +		goto err_iterate; + +	return 0; + +err_iterate: +	vfree(vgpu->initial_mmio); +	vgpu->initial_mmio = NULL; +err_mmio: +	kfree(vgpu->initial_cfg_space); +	vgpu->initial_cfg_space = NULL; + +	return ret; +} + +static void intel_gvt_init_device(struct drm_i915_private *dev_priv)  { -	if (!dev_priv->params.enable_gvt) +	if (!dev_priv->params.enable_gvt) { +		drm_dbg(&dev_priv->drm, +			"GVT-g is disabled by kernel params\n");  		return; +	}  	if (intel_vgpu_active(dev_priv)) {  		drm_info(&dev_priv->drm, "GVT-g is disabled for guest\n"); -		goto bail; +		return;  	}  	if (!is_supported_device(dev_priv)) {  		drm_info(&dev_priv->drm,  			 "Unsupported device. GVT-g is disabled\n"); -		goto bail; +		return; +	} + +	if (intel_uc_wants_guc_submission(&to_gt(dev_priv)->uc)) { +		drm_err(&dev_priv->drm, +			"Graphics virtualization is not yet supported with GuC submission\n"); +		return;  	} -	return; -bail: -	dev_priv->params.enable_gvt = 0; +	if (save_initial_hw_state(dev_priv)) { +		drm_dbg(&dev_priv->drm, "Failed to save initial HW state\n"); +		return; +	} + +	if (intel_gvt_ops->init_device(dev_priv)) +		drm_dbg(&dev_priv->drm, "Fail to init GVT device\n"); +} + +static void intel_gvt_clean_device(struct drm_i915_private *dev_priv) +{ +	if (dev_priv->gvt) +		intel_gvt_ops->clean_device(dev_priv); +	free_initial_hw_state(dev_priv); +} + +int intel_gvt_set_ops(const struct intel_vgpu_ops *ops) +{ +	struct drm_i915_private *dev_priv; + +	mutex_lock(&intel_gvt_mutex); +	if (intel_gvt_ops) { +		mutex_unlock(&intel_gvt_mutex); +		return -EINVAL; +	} +	intel_gvt_ops = ops; + +	list_for_each_entry(dev_priv, &intel_gvt_devices, vgpu.entry) +		intel_gvt_init_device(dev_priv); +	mutex_unlock(&intel_gvt_mutex); + +	return 0; +} +EXPORT_SYMBOL_NS_GPL(intel_gvt_set_ops, I915_GVT); + +void intel_gvt_clear_ops(const struct intel_vgpu_ops *ops) +{ +	struct drm_i915_private *dev_priv; + +	mutex_lock(&intel_gvt_mutex); +	if (intel_gvt_ops != ops) { +		mutex_unlock(&intel_gvt_mutex); +		return; +	} + +	list_for_each_entry(dev_priv, &intel_gvt_devices, vgpu.entry) +		intel_gvt_clean_device(dev_priv); + +	intel_gvt_ops = NULL; +	mutex_unlock(&intel_gvt_mutex);  } +EXPORT_SYMBOL_NS_GPL(intel_gvt_clear_ops, I915_GVT);  /**   * intel_gvt_init - initialize GVT components @@ -98,41 +235,18 @@ bail:   */  int intel_gvt_init(struct drm_i915_private *dev_priv)  { -	int ret; -  	if (i915_inject_probe_failure(dev_priv))  		return -ENODEV; -	if (!dev_priv->params.enable_gvt) { -		drm_dbg(&dev_priv->drm, -			"GVT-g is disabled by kernel params\n"); -		return 0; -	} - -	if (intel_uc_wants_guc_submission(&to_gt(dev_priv)->uc)) { -		drm_err(&dev_priv->drm, -			"i915 GVT-g loading failed due to Graphics virtualization is not yet supported with GuC submission\n"); -		return -EIO; -	} - -	ret = intel_gvt_init_device(dev_priv); -	if (ret) { -		drm_dbg(&dev_priv->drm, "Fail to init GVT device\n"); -		goto bail; -	} - -	return 0; +	mutex_lock(&intel_gvt_mutex); +	list_add_tail(&dev_priv->vgpu.entry, &intel_gvt_devices); +	if (intel_gvt_ops) +		intel_gvt_init_device(dev_priv); +	mutex_unlock(&intel_gvt_mutex); -bail: -	dev_priv->params.enable_gvt = 0;  	return 0;  } -static inline bool intel_gvt_active(struct drm_i915_private *dev_priv) -{ -	return dev_priv->gvt; -} -  /**   * intel_gvt_driver_remove - cleanup GVT components when i915 driver is   *			     unbinding @@ -143,10 +257,10 @@ static inline bool intel_gvt_active(struct drm_i915_private *dev_priv)   */  void intel_gvt_driver_remove(struct drm_i915_private *dev_priv)  { -	if (!intel_gvt_active(dev_priv)) -		return; - +	mutex_lock(&intel_gvt_mutex);  	intel_gvt_clean_device(dev_priv); +	list_del(&dev_priv->vgpu.entry); +	mutex_unlock(&intel_gvt_mutex);  }  /** @@ -159,6 +273,50 @@ void intel_gvt_driver_remove(struct drm_i915_private *dev_priv)   */  void intel_gvt_resume(struct drm_i915_private *dev_priv)  { -	if (intel_gvt_active(dev_priv)) -		intel_gvt_pm_resume(dev_priv->gvt); +	mutex_lock(&intel_gvt_mutex); +	if (dev_priv->gvt) +		intel_gvt_ops->pm_resume(dev_priv); +	mutex_unlock(&intel_gvt_mutex);  } + +/* + * Exported here so that the exports only get created when GVT support is + * actually enabled. + */ +EXPORT_SYMBOL_NS_GPL(i915_gem_object_alloc, I915_GVT); +EXPORT_SYMBOL_NS_GPL(i915_gem_object_create_shmem, I915_GVT); +EXPORT_SYMBOL_NS_GPL(i915_gem_object_init, I915_GVT); +EXPORT_SYMBOL_NS_GPL(i915_gem_object_ggtt_pin_ww, I915_GVT); +EXPORT_SYMBOL_NS_GPL(i915_gem_object_pin_map, I915_GVT); +EXPORT_SYMBOL_NS_GPL(i915_gem_object_set_to_cpu_domain, I915_GVT); +EXPORT_SYMBOL_NS_GPL(__i915_gem_object_flush_map, I915_GVT); +EXPORT_SYMBOL_NS_GPL(__i915_gem_object_set_pages, I915_GVT); +EXPORT_SYMBOL_NS_GPL(i915_gem_gtt_insert, I915_GVT); +EXPORT_SYMBOL_NS_GPL(i915_gem_prime_export, I915_GVT); +EXPORT_SYMBOL_NS_GPL(i915_gem_ww_ctx_init, I915_GVT); +EXPORT_SYMBOL_NS_GPL(i915_gem_ww_ctx_backoff, I915_GVT); +EXPORT_SYMBOL_NS_GPL(i915_gem_ww_ctx_fini, I915_GVT); +EXPORT_SYMBOL_NS_GPL(i915_ppgtt_create, I915_GVT); +EXPORT_SYMBOL_NS_GPL(i915_request_add, I915_GVT); +EXPORT_SYMBOL_NS_GPL(i915_request_create, I915_GVT); +EXPORT_SYMBOL_NS_GPL(i915_request_wait, I915_GVT); +EXPORT_SYMBOL_NS_GPL(i915_reserve_fence, I915_GVT); +EXPORT_SYMBOL_NS_GPL(i915_unreserve_fence, I915_GVT); +EXPORT_SYMBOL_NS_GPL(i915_vm_release, I915_GVT); +EXPORT_SYMBOL_NS_GPL(_i915_vma_move_to_active, I915_GVT); +EXPORT_SYMBOL_NS_GPL(intel_context_create, I915_GVT); +EXPORT_SYMBOL_NS_GPL(__intel_context_do_pin, I915_GVT); +EXPORT_SYMBOL_NS_GPL(__intel_context_do_unpin, I915_GVT); +EXPORT_SYMBOL_NS_GPL(intel_ring_begin, I915_GVT); +EXPORT_SYMBOL_NS_GPL(intel_runtime_pm_get, I915_GVT); +#if IS_ENABLED(CONFIG_DRM_I915_DEBUG_RUNTIME_PM) +EXPORT_SYMBOL_NS_GPL(intel_runtime_pm_put, I915_GVT); +#endif +EXPORT_SYMBOL_NS_GPL(intel_runtime_pm_put_unchecked, I915_GVT); +EXPORT_SYMBOL_NS_GPL(intel_uncore_forcewake_for_reg, I915_GVT); +EXPORT_SYMBOL_NS_GPL(intel_uncore_forcewake_get, I915_GVT); +EXPORT_SYMBOL_NS_GPL(intel_uncore_forcewake_put, I915_GVT); +EXPORT_SYMBOL_NS_GPL(shmem_pin_map, I915_GVT); +EXPORT_SYMBOL_NS_GPL(shmem_unpin_map, I915_GVT); +EXPORT_SYMBOL_NS_GPL(__px_dma, I915_GVT); +EXPORT_SYMBOL_NS_GPL(i915_fence_ops, I915_GVT);  |