cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

intel_gvt.c (9550B)


      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
     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://01.org/group/2230/documentation-list.
     45 */
     46
     47static LIST_HEAD(intel_gvt_devices);
     48static const struct intel_vgpu_ops *intel_gvt_ops;
     49static DEFINE_MUTEX(intel_gvt_mutex);
     50
     51static bool is_supported_device(struct drm_i915_private *dev_priv)
     52{
     53	if (IS_BROADWELL(dev_priv))
     54		return true;
     55	if (IS_SKYLAKE(dev_priv))
     56		return true;
     57	if (IS_KABYLAKE(dev_priv))
     58		return true;
     59	if (IS_BROXTON(dev_priv))
     60		return true;
     61	if (IS_COFFEELAKE(dev_priv))
     62		return true;
     63	if (IS_COMETLAKE(dev_priv))
     64		return true;
     65
     66	return false;
     67}
     68
     69static void free_initial_hw_state(struct drm_i915_private *dev_priv)
     70{
     71	struct i915_virtual_gpu *vgpu = &dev_priv->vgpu;
     72
     73	vfree(vgpu->initial_mmio);
     74	vgpu->initial_mmio = NULL;
     75
     76	kfree(vgpu->initial_cfg_space);
     77	vgpu->initial_cfg_space = NULL;
     78}
     79
     80static void save_mmio(struct intel_gvt_mmio_table_iter *iter, u32 offset,
     81		      u32 size)
     82{
     83	struct drm_i915_private *dev_priv = iter->i915;
     84	u32 *mmio, i;
     85
     86	for (i = offset; i < offset + size; i += 4) {
     87		mmio = iter->data + i;
     88		*mmio = intel_uncore_read_notrace(to_gt(dev_priv)->uncore,
     89						  _MMIO(i));
     90	}
     91}
     92
     93static int handle_mmio(struct intel_gvt_mmio_table_iter *iter,
     94		       u32 offset, u32 size)
     95{
     96	if (WARN_ON(!IS_ALIGNED(offset, 4)))
     97		return -EINVAL;
     98
     99	save_mmio(iter, offset, size);
    100	return 0;
    101}
    102
    103static int save_initial_hw_state(struct drm_i915_private *dev_priv)
    104{
    105	struct pci_dev *pdev = to_pci_dev(dev_priv->drm.dev);
    106	struct i915_virtual_gpu *vgpu = &dev_priv->vgpu;
    107	struct intel_gvt_mmio_table_iter iter;
    108	void *mem;
    109	int i, ret;
    110
    111	mem = kzalloc(PCI_CFG_SPACE_EXP_SIZE, GFP_KERNEL);
    112	if (!mem)
    113		return -ENOMEM;
    114
    115	vgpu->initial_cfg_space = mem;
    116
    117	for (i = 0; i < PCI_CFG_SPACE_EXP_SIZE; i += 4)
    118		pci_read_config_dword(pdev, i, mem + i);
    119
    120	mem = vzalloc(2 * SZ_1M);
    121	if (!mem) {
    122		ret = -ENOMEM;
    123		goto err_mmio;
    124	}
    125
    126	vgpu->initial_mmio = mem;
    127
    128	iter.i915 = dev_priv;
    129	iter.data = vgpu->initial_mmio;
    130	iter.handle_mmio_cb = handle_mmio;
    131
    132	ret = intel_gvt_iterate_mmio_table(&iter);
    133	if (ret)
    134		goto err_iterate;
    135
    136	return 0;
    137
    138err_iterate:
    139	vfree(vgpu->initial_mmio);
    140	vgpu->initial_mmio = NULL;
    141err_mmio:
    142	kfree(vgpu->initial_cfg_space);
    143	vgpu->initial_cfg_space = NULL;
    144
    145	return ret;
    146}
    147
    148static void intel_gvt_init_device(struct drm_i915_private *dev_priv)
    149{
    150	if (!dev_priv->params.enable_gvt) {
    151		drm_dbg(&dev_priv->drm,
    152			"GVT-g is disabled by kernel params\n");
    153		return;
    154	}
    155
    156	if (intel_vgpu_active(dev_priv)) {
    157		drm_info(&dev_priv->drm, "GVT-g is disabled for guest\n");
    158		return;
    159	}
    160
    161	if (!is_supported_device(dev_priv)) {
    162		drm_info(&dev_priv->drm,
    163			 "Unsupported device. GVT-g is disabled\n");
    164		return;
    165	}
    166
    167	if (intel_uc_wants_guc_submission(&to_gt(dev_priv)->uc)) {
    168		drm_err(&dev_priv->drm,
    169			"Graphics virtualization is not yet supported with GuC submission\n");
    170		return;
    171	}
    172
    173	if (save_initial_hw_state(dev_priv)) {
    174		drm_dbg(&dev_priv->drm, "Failed to save initial HW state\n");
    175		return;
    176	}
    177
    178	if (intel_gvt_ops->init_device(dev_priv))
    179		drm_dbg(&dev_priv->drm, "Fail to init GVT device\n");
    180}
    181
    182static void intel_gvt_clean_device(struct drm_i915_private *dev_priv)
    183{
    184	if (dev_priv->gvt)
    185		intel_gvt_ops->clean_device(dev_priv);
    186	free_initial_hw_state(dev_priv);
    187}
    188
    189int intel_gvt_set_ops(const struct intel_vgpu_ops *ops)
    190{
    191	struct drm_i915_private *dev_priv;
    192
    193	mutex_lock(&intel_gvt_mutex);
    194	if (intel_gvt_ops) {
    195		mutex_unlock(&intel_gvt_mutex);
    196		return -EINVAL;
    197	}
    198	intel_gvt_ops = ops;
    199
    200	list_for_each_entry(dev_priv, &intel_gvt_devices, vgpu.entry)
    201		intel_gvt_init_device(dev_priv);
    202	mutex_unlock(&intel_gvt_mutex);
    203
    204	return 0;
    205}
    206EXPORT_SYMBOL_NS_GPL(intel_gvt_set_ops, I915_GVT);
    207
    208void intel_gvt_clear_ops(const struct intel_vgpu_ops *ops)
    209{
    210	struct drm_i915_private *dev_priv;
    211
    212	mutex_lock(&intel_gvt_mutex);
    213	if (intel_gvt_ops != ops) {
    214		mutex_unlock(&intel_gvt_mutex);
    215		return;
    216	}
    217
    218	list_for_each_entry(dev_priv, &intel_gvt_devices, vgpu.entry)
    219		intel_gvt_clean_device(dev_priv);
    220
    221	intel_gvt_ops = NULL;
    222	mutex_unlock(&intel_gvt_mutex);
    223}
    224EXPORT_SYMBOL_NS_GPL(intel_gvt_clear_ops, I915_GVT);
    225
    226/**
    227 * intel_gvt_init - initialize GVT components
    228 * @dev_priv: drm i915 private data
    229 *
    230 * This function is called at the initialization stage to create a GVT device.
    231 *
    232 * Returns:
    233 * Zero on success, negative error code if failed.
    234 *
    235 */
    236int intel_gvt_init(struct drm_i915_private *dev_priv)
    237{
    238	if (i915_inject_probe_failure(dev_priv))
    239		return -ENODEV;
    240
    241	mutex_lock(&intel_gvt_mutex);
    242	list_add_tail(&dev_priv->vgpu.entry, &intel_gvt_devices);
    243	if (intel_gvt_ops)
    244		intel_gvt_init_device(dev_priv);
    245	mutex_unlock(&intel_gvt_mutex);
    246
    247	return 0;
    248}
    249
    250/**
    251 * intel_gvt_driver_remove - cleanup GVT components when i915 driver is
    252 *			     unbinding
    253 * @dev_priv: drm i915 private *
    254 *
    255 * This function is called at the i915 driver unloading stage, to shutdown
    256 * GVT components and release the related resources.
    257 */
    258void intel_gvt_driver_remove(struct drm_i915_private *dev_priv)
    259{
    260	mutex_lock(&intel_gvt_mutex);
    261	intel_gvt_clean_device(dev_priv);
    262	list_del(&dev_priv->vgpu.entry);
    263	mutex_unlock(&intel_gvt_mutex);
    264}
    265
    266/**
    267 * intel_gvt_resume - GVT resume routine wapper
    268 *
    269 * @dev_priv: drm i915 private *
    270 *
    271 * This function is called at the i915 driver resume stage to restore required
    272 * HW status for GVT so that vGPU can continue running after resumed.
    273 */
    274void intel_gvt_resume(struct drm_i915_private *dev_priv)
    275{
    276	mutex_lock(&intel_gvt_mutex);
    277	if (dev_priv->gvt)
    278		intel_gvt_ops->pm_resume(dev_priv);
    279	mutex_unlock(&intel_gvt_mutex);
    280}
    281
    282/*
    283 * Exported here so that the exports only get created when GVT support is
    284 * actually enabled.
    285 */
    286EXPORT_SYMBOL_NS_GPL(i915_gem_object_alloc, I915_GVT);
    287EXPORT_SYMBOL_NS_GPL(i915_gem_object_create_shmem, I915_GVT);
    288EXPORT_SYMBOL_NS_GPL(i915_gem_object_init, I915_GVT);
    289EXPORT_SYMBOL_NS_GPL(i915_gem_object_ggtt_pin_ww, I915_GVT);
    290EXPORT_SYMBOL_NS_GPL(i915_gem_object_pin_map, I915_GVT);
    291EXPORT_SYMBOL_NS_GPL(i915_gem_object_set_to_cpu_domain, I915_GVT);
    292EXPORT_SYMBOL_NS_GPL(__i915_gem_object_flush_map, I915_GVT);
    293EXPORT_SYMBOL_NS_GPL(__i915_gem_object_set_pages, I915_GVT);
    294EXPORT_SYMBOL_NS_GPL(i915_gem_gtt_insert, I915_GVT);
    295EXPORT_SYMBOL_NS_GPL(i915_gem_prime_export, I915_GVT);
    296EXPORT_SYMBOL_NS_GPL(i915_gem_ww_ctx_init, I915_GVT);
    297EXPORT_SYMBOL_NS_GPL(i915_gem_ww_ctx_backoff, I915_GVT);
    298EXPORT_SYMBOL_NS_GPL(i915_gem_ww_ctx_fini, I915_GVT);
    299EXPORT_SYMBOL_NS_GPL(i915_ppgtt_create, I915_GVT);
    300EXPORT_SYMBOL_NS_GPL(i915_request_add, I915_GVT);
    301EXPORT_SYMBOL_NS_GPL(i915_request_create, I915_GVT);
    302EXPORT_SYMBOL_NS_GPL(i915_request_wait, I915_GVT);
    303EXPORT_SYMBOL_NS_GPL(i915_reserve_fence, I915_GVT);
    304EXPORT_SYMBOL_NS_GPL(i915_unreserve_fence, I915_GVT);
    305EXPORT_SYMBOL_NS_GPL(i915_vm_release, I915_GVT);
    306EXPORT_SYMBOL_NS_GPL(_i915_vma_move_to_active, I915_GVT);
    307EXPORT_SYMBOL_NS_GPL(intel_context_create, I915_GVT);
    308EXPORT_SYMBOL_NS_GPL(__intel_context_do_pin, I915_GVT);
    309EXPORT_SYMBOL_NS_GPL(__intel_context_do_unpin, I915_GVT);
    310EXPORT_SYMBOL_NS_GPL(intel_ring_begin, I915_GVT);
    311EXPORT_SYMBOL_NS_GPL(intel_runtime_pm_get, I915_GVT);
    312#if IS_ENABLED(CONFIG_DRM_I915_DEBUG_RUNTIME_PM)
    313EXPORT_SYMBOL_NS_GPL(intel_runtime_pm_put, I915_GVT);
    314#endif
    315EXPORT_SYMBOL_NS_GPL(intel_runtime_pm_put_unchecked, I915_GVT);
    316EXPORT_SYMBOL_NS_GPL(intel_uncore_forcewake_for_reg, I915_GVT);
    317EXPORT_SYMBOL_NS_GPL(intel_uncore_forcewake_get, I915_GVT);
    318EXPORT_SYMBOL_NS_GPL(intel_uncore_forcewake_put, I915_GVT);
    319EXPORT_SYMBOL_NS_GPL(shmem_pin_map, I915_GVT);
    320EXPORT_SYMBOL_NS_GPL(shmem_unpin_map, I915_GVT);
    321EXPORT_SYMBOL_NS_GPL(__px_dma, I915_GVT);
    322EXPORT_SYMBOL_NS_GPL(i915_fence_ops, I915_GVT);