Home | History | Annotate | Line # | Download | only in i915
      1  1.6  riastrad /*	$NetBSD: i915_vgpu.c,v 1.6 2021/12/19 11:37:41 riastradh Exp $	*/
      2  1.1  riastrad 
      3  1.1  riastrad /*
      4  1.1  riastrad  * Copyright(c) 2011-2015 Intel Corporation. All rights reserved.
      5  1.1  riastrad  *
      6  1.1  riastrad  * Permission is hereby granted, free of charge, to any person obtaining a
      7  1.1  riastrad  * copy of this software and associated documentation files (the "Software"),
      8  1.1  riastrad  * to deal in the Software without restriction, including without limitation
      9  1.1  riastrad  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
     10  1.1  riastrad  * and/or sell copies of the Software, and to permit persons to whom the
     11  1.1  riastrad  * Software is furnished to do so, subject to the following conditions:
     12  1.1  riastrad  *
     13  1.1  riastrad  * The above copyright notice and this permission notice (including the next
     14  1.1  riastrad  * paragraph) shall be included in all copies or substantial portions of the
     15  1.1  riastrad  * Software.
     16  1.1  riastrad  *
     17  1.1  riastrad  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     18  1.1  riastrad  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     19  1.1  riastrad  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
     20  1.1  riastrad  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     21  1.1  riastrad  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
     22  1.1  riastrad  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
     23  1.1  riastrad  * SOFTWARE.
     24  1.1  riastrad  */
     25  1.1  riastrad 
     26  1.1  riastrad #include <sys/cdefs.h>
     27  1.6  riastrad __KERNEL_RCSID(0, "$NetBSD: i915_vgpu.c,v 1.6 2021/12/19 11:37:41 riastradh Exp $");
     28  1.1  riastrad 
     29  1.1  riastrad #include "i915_vgpu.h"
     30  1.1  riastrad 
     31  1.6  riastrad #include <linux/nbsd-namespace.h>
     32  1.6  riastrad 
     33  1.1  riastrad /**
     34  1.1  riastrad  * DOC: Intel GVT-g guest support
     35  1.1  riastrad  *
     36  1.1  riastrad  * Intel GVT-g is a graphics virtualization technology which shares the
     37  1.1  riastrad  * GPU among multiple virtual machines on a time-sharing basis. Each
     38  1.1  riastrad  * virtual machine is presented a virtual GPU (vGPU), which has equivalent
     39  1.1  riastrad  * features as the underlying physical GPU (pGPU), so i915 driver can run
     40  1.1  riastrad  * seamlessly in a virtual machine. This file provides vGPU specific
     41  1.1  riastrad  * optimizations when running in a virtual machine, to reduce the complexity
     42  1.1  riastrad  * of vGPU emulation and to improve the overall performance.
     43  1.1  riastrad  *
     44  1.1  riastrad  * A primary function introduced here is so-called "address space ballooning"
     45  1.1  riastrad  * technique. Intel GVT-g partitions global graphics memory among multiple VMs,
     46  1.1  riastrad  * so each VM can directly access a portion of the memory without hypervisor's
     47  1.1  riastrad  * intervention, e.g. filling textures or queuing commands. However with the
     48  1.1  riastrad  * partitioning an unmodified i915 driver would assume a smaller graphics
     49  1.1  riastrad  * memory starting from address ZERO, then requires vGPU emulation module to
     50  1.1  riastrad  * translate the graphics address between 'guest view' and 'host view', for
     51  1.1  riastrad  * all registers and command opcodes which contain a graphics memory address.
     52  1.1  riastrad  * To reduce the complexity, Intel GVT-g introduces "address space ballooning",
     53  1.1  riastrad  * by telling the exact partitioning knowledge to each guest i915 driver, which
     54  1.1  riastrad  * then reserves and prevents non-allocated portions from allocation. Thus vGPU
     55  1.1  riastrad  * emulation module only needs to scan and validate graphics addresses without
     56  1.1  riastrad  * complexity of address translation.
     57  1.1  riastrad  *
     58  1.1  riastrad  */
     59  1.1  riastrad 
     60  1.1  riastrad /**
     61  1.5  riastrad  * i915_detect_vgpu - detect virtual GPU
     62  1.5  riastrad  * @dev_priv: i915 device private
     63  1.1  riastrad  *
     64  1.1  riastrad  * This function is called at the initialization stage, to detect whether
     65  1.1  riastrad  * running on a vGPU.
     66  1.1  riastrad  */
     67  1.5  riastrad void i915_detect_vgpu(struct drm_i915_private *dev_priv)
     68  1.1  riastrad {
     69  1.5  riastrad 	struct pci_dev *pdev = dev_priv->drm.pdev;
     70  1.5  riastrad 	u64 magic;
     71  1.5  riastrad 	u16 version_major;
     72  1.6  riastrad #ifdef __NetBSD__
     73  1.6  riastrad 	bus_space_tag_t bst;
     74  1.6  riastrad 	bus_space_handle_t bsh;
     75  1.6  riastrad 	bus_size_t off = VGT_PVINFO_PAGE;
     76  1.6  riastrad 	bus_size_t size = VGT_PVINFO_SIZE;
     77  1.6  riastrad #else
     78  1.5  riastrad 	void __iomem *shared_area;
     79  1.6  riastrad #endif
     80  1.1  riastrad 
     81  1.1  riastrad 	BUILD_BUG_ON(sizeof(struct vgt_if) != VGT_PVINFO_SIZE);
     82  1.1  riastrad 
     83  1.5  riastrad 	/*
     84  1.5  riastrad 	 * This is called before we setup the main MMIO BAR mappings used via
     85  1.5  riastrad 	 * the uncore structure, so we need to access the BAR directly. Since
     86  1.5  riastrad 	 * we do not support VGT on older gens, return early so we don't have
     87  1.5  riastrad 	 * to consider differently numbered or sized MMIO bars
     88  1.5  riastrad 	 */
     89  1.5  riastrad 	if (INTEL_GEN(dev_priv) < 6)
     90  1.5  riastrad 		return;
     91  1.5  riastrad 
     92  1.6  riastrad #ifdef __NetBSD__
     93  1.6  riastrad 	bst = pdev->pd_pa.pa_memt;
     94  1.6  riastrad 	if (off > pdev->pd_resources[0].size ||
     95  1.6  riastrad 	    size > pdev->pd_resources[0].size - off ||
     96  1.6  riastrad 	    bus_space_map(bst, pdev->pd_resources[0].addr + off, size,
     97  1.6  riastrad 		pdev->pd_resources[0].flags, &bsh)) {
     98  1.5  riastrad 		DRM_ERROR("failed to map MMIO bar to check for VGT\n");
     99  1.1  riastrad 		return;
    100  1.5  riastrad 	}
    101  1.4  riastrad #  ifdef _LP64
    102  1.6  riastrad 	magic = bus_space_read_8(bst, bsh, (bus_size_t)vgtif_offset(magic));
    103  1.4  riastrad #  else
    104  1.6  riastrad 	magic = bus_space_read_4(bst, bsh, (bus_size_t)vgtif_offset(magic));
    105  1.6  riastrad 	magic |= (uint64_t)bus_space_read_4(bst, bsh,
    106  1.6  riastrad 	    (bus_size_t)vgtif_offset(magic) + 4)
    107  1.6  riastrad 	    << 32;
    108  1.4  riastrad #  endif
    109  1.3  riastrad #else
    110  1.6  riastrad 	shared_area = pci_iomap_range(pdev, 0, VGT_PVINFO_PAGE, VGT_PVINFO_SIZE);
    111  1.6  riastrad 	if (!shared_area) {
    112  1.6  riastrad 		DRM_ERROR("failed to map MMIO bar to check for VGT\n");
    113  1.6  riastrad 		return;
    114  1.6  riastrad 	}
    115  1.5  riastrad 	magic = readq(shared_area + vgtif_offset(magic));
    116  1.3  riastrad #endif
    117  1.6  riastrad 
    118  1.1  riastrad 	if (magic != VGT_MAGIC)
    119  1.5  riastrad 		goto out;
    120  1.1  riastrad 
    121  1.3  riastrad #ifdef __NetBSD__
    122  1.6  riastrad 	version_major = bus_space_read_2(bst, bsh,
    123  1.6  riastrad 	    (bus_size_t)vgtif_offset(version_major));
    124  1.3  riastrad #else
    125  1.5  riastrad 	version_major = readw(shared_area + vgtif_offset(version_major));
    126  1.3  riastrad #endif
    127  1.5  riastrad 	if (version_major < VGT_VERSION_MAJOR) {
    128  1.1  riastrad 		DRM_INFO("VGT interface version mismatch!\n");
    129  1.5  riastrad 		goto out;
    130  1.1  riastrad 	}
    131  1.1  riastrad 
    132  1.6  riastrad #ifdef __NetBSD__
    133  1.6  riastrad 	dev_priv->vgpu.caps = bus_space_read_4(bst, bsh,
    134  1.6  riastrad 	    (bus_size_t)vgtif_offset(vgt_caps));
    135  1.6  riastrad #else
    136  1.5  riastrad 	dev_priv->vgpu.caps = readl(shared_area + vgtif_offset(vgt_caps));
    137  1.6  riastrad #endif
    138  1.5  riastrad 
    139  1.1  riastrad 	dev_priv->vgpu.active = true;
    140  1.5  riastrad 	mutex_init(&dev_priv->vgpu.lock);
    141  1.1  riastrad 	DRM_INFO("Virtual GPU for Intel GVT-g detected.\n");
    142  1.5  riastrad 
    143  1.5  riastrad out:
    144  1.6  riastrad #ifdef __NetBSD__
    145  1.6  riastrad 	bus_space_unmap(bst, bsh, size);
    146  1.6  riastrad #else
    147  1.5  riastrad 	pci_iounmap(pdev, shared_area);
    148  1.6  riastrad #endif
    149  1.5  riastrad }
    150  1.5  riastrad 
    151  1.5  riastrad bool intel_vgpu_has_full_ppgtt(struct drm_i915_private *dev_priv)
    152  1.5  riastrad {
    153  1.5  riastrad 	return dev_priv->vgpu.caps & VGT_CAPS_FULL_PPGTT;
    154  1.1  riastrad }
    155  1.1  riastrad 
    156  1.1  riastrad struct _balloon_info_ {
    157  1.1  riastrad 	/*
    158  1.1  riastrad 	 * There are up to 2 regions per mappable/unmappable graphic
    159  1.1  riastrad 	 * memory that might be ballooned. Here, index 0/1 is for mappable
    160  1.1  riastrad 	 * graphic memory, 2/3 for unmappable graphic memory.
    161  1.1  riastrad 	 */
    162  1.1  riastrad 	struct drm_mm_node space[4];
    163  1.1  riastrad };
    164  1.1  riastrad 
    165  1.1  riastrad static struct _balloon_info_ bl_info;
    166  1.1  riastrad 
    167  1.5  riastrad static void vgt_deballoon_space(struct i915_ggtt *ggtt,
    168  1.5  riastrad 				struct drm_mm_node *node)
    169  1.5  riastrad {
    170  1.5  riastrad 	if (!drm_mm_node_allocated(node))
    171  1.5  riastrad 		return;
    172  1.5  riastrad 
    173  1.6  riastrad 	DRM_DEBUG_DRIVER("deballoon space: range [0x%"PRIx64" - 0x%"PRIx64"] %"PRIu64" KiB.\n",
    174  1.5  riastrad 			 node->start,
    175  1.5  riastrad 			 node->start + node->size,
    176  1.5  riastrad 			 node->size / 1024);
    177  1.5  riastrad 
    178  1.5  riastrad 	ggtt->vm.reserved -= node->size;
    179  1.5  riastrad 	drm_mm_remove_node(node);
    180  1.5  riastrad }
    181  1.5  riastrad 
    182  1.1  riastrad /**
    183  1.1  riastrad  * intel_vgt_deballoon - deballoon reserved graphics address trunks
    184  1.5  riastrad  * @ggtt: the global GGTT from which we reserved earlier
    185  1.1  riastrad  *
    186  1.1  riastrad  * This function is called to deallocate the ballooned-out graphic memory, when
    187  1.1  riastrad  * driver is unloaded or when ballooning fails.
    188  1.1  riastrad  */
    189  1.5  riastrad void intel_vgt_deballoon(struct i915_ggtt *ggtt)
    190  1.1  riastrad {
    191  1.1  riastrad 	int i;
    192  1.1  riastrad 
    193  1.5  riastrad 	if (!intel_vgpu_active(ggtt->vm.i915))
    194  1.5  riastrad 		return;
    195  1.5  riastrad 
    196  1.1  riastrad 	DRM_DEBUG("VGT deballoon.\n");
    197  1.1  riastrad 
    198  1.5  riastrad 	for (i = 0; i < 4; i++)
    199  1.5  riastrad 		vgt_deballoon_space(ggtt, &bl_info.space[i]);
    200  1.1  riastrad }
    201  1.1  riastrad 
    202  1.5  riastrad static int vgt_balloon_space(struct i915_ggtt *ggtt,
    203  1.1  riastrad 			     struct drm_mm_node *node,
    204  1.1  riastrad 			     unsigned long start, unsigned long end)
    205  1.1  riastrad {
    206  1.1  riastrad 	unsigned long size = end - start;
    207  1.5  riastrad 	int ret;
    208  1.1  riastrad 
    209  1.5  riastrad 	if (start >= end)
    210  1.1  riastrad 		return -EINVAL;
    211  1.1  riastrad 
    212  1.1  riastrad 	DRM_INFO("balloon space: range [ 0x%lx - 0x%lx ] %lu KiB.\n",
    213  1.1  riastrad 		 start, end, size / 1024);
    214  1.5  riastrad 	ret = i915_gem_gtt_reserve(&ggtt->vm, node,
    215  1.5  riastrad 				   size, start, I915_COLOR_UNEVICTABLE,
    216  1.5  riastrad 				   0);
    217  1.5  riastrad 	if (!ret)
    218  1.5  riastrad 		ggtt->vm.reserved += size;
    219  1.1  riastrad 
    220  1.5  riastrad 	return ret;
    221  1.1  riastrad }
    222  1.1  riastrad 
    223  1.1  riastrad /**
    224  1.1  riastrad  * intel_vgt_balloon - balloon out reserved graphics address trunks
    225  1.5  riastrad  * @ggtt: the global GGTT from which to reserve
    226  1.1  riastrad  *
    227  1.1  riastrad  * This function is called at the initialization stage, to balloon out the
    228  1.1  riastrad  * graphic address space allocated to other vGPUs, by marking these spaces as
    229  1.1  riastrad  * reserved. The ballooning related knowledge(starting address and size of
    230  1.1  riastrad  * the mappable/unmappable graphic memory) is described in the vgt_if structure
    231  1.1  riastrad  * in a reserved mmio range.
    232  1.1  riastrad  *
    233  1.1  riastrad  * To give an example, the drawing below depicts one typical scenario after
    234  1.1  riastrad  * ballooning. Here the vGPU1 has 2 pieces of graphic address spaces ballooned
    235  1.1  riastrad  * out each for the mappable and the non-mappable part. From the vGPU1 point of
    236  1.1  riastrad  * view, the total size is the same as the physical one, with the start address
    237  1.1  riastrad  * of its graphic space being zero. Yet there are some portions ballooned out(
    238  1.1  riastrad  * the shadow part, which are marked as reserved by drm allocator). From the
    239  1.1  riastrad  * host point of view, the graphic address space is partitioned by multiple
    240  1.5  riastrad  * vGPUs in different VMs. ::
    241  1.1  riastrad  *
    242  1.5  riastrad  *                         vGPU1 view         Host view
    243  1.5  riastrad  *              0 ------> +-----------+     +-----------+
    244  1.5  riastrad  *                ^       |###########|     |   vGPU3   |
    245  1.5  riastrad  *                |       |###########|     +-----------+
    246  1.5  riastrad  *                |       |###########|     |   vGPU2   |
    247  1.5  riastrad  *                |       +-----------+     +-----------+
    248  1.5  riastrad  *         mappable GM    | available | ==> |   vGPU1   |
    249  1.5  riastrad  *                |       +-----------+     +-----------+
    250  1.5  riastrad  *                |       |###########|     |           |
    251  1.5  riastrad  *                v       |###########|     |   Host    |
    252  1.5  riastrad  *                +=======+===========+     +===========+
    253  1.5  riastrad  *                ^       |###########|     |   vGPU3   |
    254  1.5  riastrad  *                |       |###########|     +-----------+
    255  1.5  riastrad  *                |       |###########|     |   vGPU2   |
    256  1.5  riastrad  *                |       +-----------+     +-----------+
    257  1.5  riastrad  *       unmappable GM    | available | ==> |   vGPU1   |
    258  1.5  riastrad  *                |       +-----------+     +-----------+
    259  1.5  riastrad  *                |       |###########|     |           |
    260  1.5  riastrad  *                |       |###########|     |   Host    |
    261  1.5  riastrad  *                v       |###########|     |           |
    262  1.5  riastrad  *  total GM size ------> +-----------+     +-----------+
    263  1.1  riastrad  *
    264  1.1  riastrad  * Returns:
    265  1.1  riastrad  * zero on success, non-zero if configuration invalid or ballooning failed
    266  1.1  riastrad  */
    267  1.5  riastrad int intel_vgt_balloon(struct i915_ggtt *ggtt)
    268  1.1  riastrad {
    269  1.5  riastrad 	struct intel_uncore *uncore = &ggtt->vm.i915->uncore;
    270  1.5  riastrad 	unsigned long ggtt_end = ggtt->vm.total;
    271  1.1  riastrad 
    272  1.1  riastrad 	unsigned long mappable_base, mappable_size, mappable_end;
    273  1.1  riastrad 	unsigned long unmappable_base, unmappable_size, unmappable_end;
    274  1.1  riastrad 	int ret;
    275  1.1  riastrad 
    276  1.5  riastrad 	if (!intel_vgpu_active(ggtt->vm.i915))
    277  1.5  riastrad 		return 0;
    278  1.5  riastrad 
    279  1.5  riastrad 	mappable_base =
    280  1.5  riastrad 	  intel_uncore_read(uncore, vgtif_reg(avail_rs.mappable_gmadr.base));
    281  1.5  riastrad 	mappable_size =
    282  1.5  riastrad 	  intel_uncore_read(uncore, vgtif_reg(avail_rs.mappable_gmadr.size));
    283  1.5  riastrad 	unmappable_base =
    284  1.5  riastrad 	  intel_uncore_read(uncore, vgtif_reg(avail_rs.nonmappable_gmadr.base));
    285  1.5  riastrad 	unmappable_size =
    286  1.5  riastrad 	  intel_uncore_read(uncore, vgtif_reg(avail_rs.nonmappable_gmadr.size));
    287  1.1  riastrad 
    288  1.1  riastrad 	mappable_end = mappable_base + mappable_size;
    289  1.1  riastrad 	unmappable_end = unmappable_base + unmappable_size;
    290  1.1  riastrad 
    291  1.1  riastrad 	DRM_INFO("VGT ballooning configuration:\n");
    292  1.1  riastrad 	DRM_INFO("Mappable graphic memory: base 0x%lx size %ldKiB\n",
    293  1.1  riastrad 		 mappable_base, mappable_size / 1024);
    294  1.1  riastrad 	DRM_INFO("Unmappable graphic memory: base 0x%lx size %ldKiB\n",
    295  1.1  riastrad 		 unmappable_base, unmappable_size / 1024);
    296  1.1  riastrad 
    297  1.5  riastrad 	if (mappable_end > ggtt->mappable_end ||
    298  1.5  riastrad 	    unmappable_base < ggtt->mappable_end ||
    299  1.5  riastrad 	    unmappable_end > ggtt_end) {
    300  1.1  riastrad 		DRM_ERROR("Invalid ballooning configuration!\n");
    301  1.1  riastrad 		return -EINVAL;
    302  1.1  riastrad 	}
    303  1.1  riastrad 
    304  1.1  riastrad 	/* Unmappable graphic memory ballooning */
    305  1.5  riastrad 	if (unmappable_base > ggtt->mappable_end) {
    306  1.5  riastrad 		ret = vgt_balloon_space(ggtt, &bl_info.space[2],
    307  1.5  riastrad 					ggtt->mappable_end, unmappable_base);
    308  1.1  riastrad 
    309  1.1  riastrad 		if (ret)
    310  1.1  riastrad 			goto err;
    311  1.1  riastrad 	}
    312  1.1  riastrad 
    313  1.5  riastrad 	if (unmappable_end < ggtt_end) {
    314  1.5  riastrad 		ret = vgt_balloon_space(ggtt, &bl_info.space[3],
    315  1.5  riastrad 					unmappable_end, ggtt_end);
    316  1.1  riastrad 		if (ret)
    317  1.5  riastrad 			goto err_upon_mappable;
    318  1.1  riastrad 	}
    319  1.1  riastrad 
    320  1.1  riastrad 	/* Mappable graphic memory ballooning */
    321  1.5  riastrad 	if (mappable_base) {
    322  1.5  riastrad 		ret = vgt_balloon_space(ggtt, &bl_info.space[0],
    323  1.5  riastrad 					0, mappable_base);
    324  1.1  riastrad 
    325  1.1  riastrad 		if (ret)
    326  1.5  riastrad 			goto err_upon_unmappable;
    327  1.1  riastrad 	}
    328  1.1  riastrad 
    329  1.5  riastrad 	if (mappable_end < ggtt->mappable_end) {
    330  1.5  riastrad 		ret = vgt_balloon_space(ggtt, &bl_info.space[1],
    331  1.5  riastrad 					mappable_end, ggtt->mappable_end);
    332  1.1  riastrad 
    333  1.1  riastrad 		if (ret)
    334  1.5  riastrad 			goto err_below_mappable;
    335  1.1  riastrad 	}
    336  1.1  riastrad 
    337  1.1  riastrad 	DRM_INFO("VGT balloon successfully\n");
    338  1.1  riastrad 	return 0;
    339  1.1  riastrad 
    340  1.5  riastrad err_below_mappable:
    341  1.5  riastrad 	vgt_deballoon_space(ggtt, &bl_info.space[0]);
    342  1.5  riastrad err_upon_unmappable:
    343  1.5  riastrad 	vgt_deballoon_space(ggtt, &bl_info.space[3]);
    344  1.5  riastrad err_upon_mappable:
    345  1.5  riastrad 	vgt_deballoon_space(ggtt, &bl_info.space[2]);
    346  1.1  riastrad err:
    347  1.1  riastrad 	DRM_ERROR("VGT balloon fail\n");
    348  1.1  riastrad 	return ret;
    349  1.1  riastrad }
    350