Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * Copyright(c) 2011-2015 Intel Corporation. All rights reserved.
0003  *
0004  * Permission is hereby granted, free of charge, to any person obtaining a
0005  * copy of this software and associated documentation files (the "Software"),
0006  * to deal in the Software without restriction, including without limitation
0007  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
0008  * and/or sell copies of the Software, and to permit persons to whom the
0009  * Software is furnished to do so, subject to the following conditions:
0010  *
0011  * The above copyright notice and this permission notice (including the next
0012  * paragraph) shall be included in all copies or substantial portions of the
0013  * Software.
0014  *
0015  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
0016  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
0017  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
0018  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
0019  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
0020  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
0021  * SOFTWARE.
0022  */
0023 
0024 #include "i915_drv.h"
0025 #include "i915_pvinfo.h"
0026 #include "i915_vgpu.h"
0027 
0028 /**
0029  * DOC: Intel GVT-g guest support
0030  *
0031  * Intel GVT-g is a graphics virtualization technology which shares the
0032  * GPU among multiple virtual machines on a time-sharing basis. Each
0033  * virtual machine is presented a virtual GPU (vGPU), which has equivalent
0034  * features as the underlying physical GPU (pGPU), so i915 driver can run
0035  * seamlessly in a virtual machine. This file provides vGPU specific
0036  * optimizations when running in a virtual machine, to reduce the complexity
0037  * of vGPU emulation and to improve the overall performance.
0038  *
0039  * A primary function introduced here is so-called "address space ballooning"
0040  * technique. Intel GVT-g partitions global graphics memory among multiple VMs,
0041  * so each VM can directly access a portion of the memory without hypervisor's
0042  * intervention, e.g. filling textures or queuing commands. However with the
0043  * partitioning an unmodified i915 driver would assume a smaller graphics
0044  * memory starting from address ZERO, then requires vGPU emulation module to
0045  * translate the graphics address between 'guest view' and 'host view', for
0046  * all registers and command opcodes which contain a graphics memory address.
0047  * To reduce the complexity, Intel GVT-g introduces "address space ballooning",
0048  * by telling the exact partitioning knowledge to each guest i915 driver, which
0049  * then reserves and prevents non-allocated portions from allocation. Thus vGPU
0050  * emulation module only needs to scan and validate graphics addresses without
0051  * complexity of address translation.
0052  *
0053  */
0054 
0055 /**
0056  * intel_vgpu_detect - detect virtual GPU
0057  * @dev_priv: i915 device private
0058  *
0059  * This function is called at the initialization stage, to detect whether
0060  * running on a vGPU.
0061  */
0062 void intel_vgpu_detect(struct drm_i915_private *dev_priv)
0063 {
0064     struct pci_dev *pdev = to_pci_dev(dev_priv->drm.dev);
0065     u64 magic;
0066     u16 version_major;
0067     void __iomem *shared_area;
0068 
0069     BUILD_BUG_ON(sizeof(struct vgt_if) != VGT_PVINFO_SIZE);
0070 
0071     /*
0072      * This is called before we setup the main MMIO BAR mappings used via
0073      * the uncore structure, so we need to access the BAR directly. Since
0074      * we do not support VGT on older gens, return early so we don't have
0075      * to consider differently numbered or sized MMIO bars
0076      */
0077     if (GRAPHICS_VER(dev_priv) < 6)
0078         return;
0079 
0080     shared_area = pci_iomap_range(pdev, 0, VGT_PVINFO_PAGE, VGT_PVINFO_SIZE);
0081     if (!shared_area) {
0082         drm_err(&dev_priv->drm,
0083             "failed to map MMIO bar to check for VGT\n");
0084         return;
0085     }
0086 
0087     magic = readq(shared_area + vgtif_offset(magic));
0088     if (magic != VGT_MAGIC)
0089         goto out;
0090 
0091     version_major = readw(shared_area + vgtif_offset(version_major));
0092     if (version_major < VGT_VERSION_MAJOR) {
0093         drm_info(&dev_priv->drm, "VGT interface version mismatch!\n");
0094         goto out;
0095     }
0096 
0097     dev_priv->vgpu.caps = readl(shared_area + vgtif_offset(vgt_caps));
0098 
0099     dev_priv->vgpu.active = true;
0100     mutex_init(&dev_priv->vgpu.lock);
0101     drm_info(&dev_priv->drm, "Virtual GPU for Intel GVT-g detected.\n");
0102 
0103 out:
0104     pci_iounmap(pdev, shared_area);
0105 }
0106 
0107 void intel_vgpu_register(struct drm_i915_private *i915)
0108 {
0109     /*
0110      * Notify a valid surface after modesetting, when running inside a VM.
0111      */
0112     if (intel_vgpu_active(i915))
0113         intel_uncore_write(&i915->uncore, vgtif_reg(display_ready),
0114                    VGT_DRV_DISPLAY_READY);
0115 }
0116 
0117 bool intel_vgpu_active(struct drm_i915_private *dev_priv)
0118 {
0119     return dev_priv->vgpu.active;
0120 }
0121 
0122 bool intel_vgpu_has_full_ppgtt(struct drm_i915_private *dev_priv)
0123 {
0124     return dev_priv->vgpu.caps & VGT_CAPS_FULL_PPGTT;
0125 }
0126 
0127 bool intel_vgpu_has_hwsp_emulation(struct drm_i915_private *dev_priv)
0128 {
0129     return dev_priv->vgpu.caps & VGT_CAPS_HWSP_EMULATION;
0130 }
0131 
0132 bool intel_vgpu_has_huge_gtt(struct drm_i915_private *dev_priv)
0133 {
0134     return dev_priv->vgpu.caps & VGT_CAPS_HUGE_GTT;
0135 }
0136 
0137 struct _balloon_info_ {
0138     /*
0139      * There are up to 2 regions per mappable/unmappable graphic
0140      * memory that might be ballooned. Here, index 0/1 is for mappable
0141      * graphic memory, 2/3 for unmappable graphic memory.
0142      */
0143     struct drm_mm_node space[4];
0144 };
0145 
0146 static struct _balloon_info_ bl_info;
0147 
0148 static void vgt_deballoon_space(struct i915_ggtt *ggtt,
0149                 struct drm_mm_node *node)
0150 {
0151     struct drm_i915_private *dev_priv = ggtt->vm.i915;
0152     if (!drm_mm_node_allocated(node))
0153         return;
0154 
0155     drm_dbg(&dev_priv->drm,
0156         "deballoon space: range [0x%llx - 0x%llx] %llu KiB.\n",
0157         node->start,
0158         node->start + node->size,
0159         node->size / 1024);
0160 
0161     ggtt->vm.reserved -= node->size;
0162     drm_mm_remove_node(node);
0163 }
0164 
0165 /**
0166  * intel_vgt_deballoon - deballoon reserved graphics address trunks
0167  * @ggtt: the global GGTT from which we reserved earlier
0168  *
0169  * This function is called to deallocate the ballooned-out graphic memory, when
0170  * driver is unloaded or when ballooning fails.
0171  */
0172 void intel_vgt_deballoon(struct i915_ggtt *ggtt)
0173 {
0174     struct drm_i915_private *dev_priv = ggtt->vm.i915;
0175     int i;
0176 
0177     if (!intel_vgpu_active(ggtt->vm.i915))
0178         return;
0179 
0180     drm_dbg(&dev_priv->drm, "VGT deballoon.\n");
0181 
0182     for (i = 0; i < 4; i++)
0183         vgt_deballoon_space(ggtt, &bl_info.space[i]);
0184 }
0185 
0186 static int vgt_balloon_space(struct i915_ggtt *ggtt,
0187                  struct drm_mm_node *node,
0188                  unsigned long start, unsigned long end)
0189 {
0190     struct drm_i915_private *dev_priv = ggtt->vm.i915;
0191     unsigned long size = end - start;
0192     int ret;
0193 
0194     if (start >= end)
0195         return -EINVAL;
0196 
0197     drm_info(&dev_priv->drm,
0198          "balloon space: range [ 0x%lx - 0x%lx ] %lu KiB.\n",
0199          start, end, size / 1024);
0200     ret = i915_gem_gtt_reserve(&ggtt->vm, NULL, node,
0201                    size, start, I915_COLOR_UNEVICTABLE,
0202                    0);
0203     if (!ret)
0204         ggtt->vm.reserved += size;
0205 
0206     return ret;
0207 }
0208 
0209 /**
0210  * intel_vgt_balloon - balloon out reserved graphics address trunks
0211  * @ggtt: the global GGTT from which to reserve
0212  *
0213  * This function is called at the initialization stage, to balloon out the
0214  * graphic address space allocated to other vGPUs, by marking these spaces as
0215  * reserved. The ballooning related knowledge(starting address and size of
0216  * the mappable/unmappable graphic memory) is described in the vgt_if structure
0217  * in a reserved mmio range.
0218  *
0219  * To give an example, the drawing below depicts one typical scenario after
0220  * ballooning. Here the vGPU1 has 2 pieces of graphic address spaces ballooned
0221  * out each for the mappable and the non-mappable part. From the vGPU1 point of
0222  * view, the total size is the same as the physical one, with the start address
0223  * of its graphic space being zero. Yet there are some portions ballooned out(
0224  * the shadow part, which are marked as reserved by drm allocator). From the
0225  * host point of view, the graphic address space is partitioned by multiple
0226  * vGPUs in different VMs. ::
0227  *
0228  *                         vGPU1 view         Host view
0229  *              0 ------> +-----------+     +-----------+
0230  *                ^       |###########|     |   vGPU3   |
0231  *                |       |###########|     +-----------+
0232  *                |       |###########|     |   vGPU2   |
0233  *                |       +-----------+     +-----------+
0234  *         mappable GM    | available | ==> |   vGPU1   |
0235  *                |       +-----------+     +-----------+
0236  *                |       |###########|     |           |
0237  *                v       |###########|     |   Host    |
0238  *                +=======+===========+     +===========+
0239  *                ^       |###########|     |   vGPU3   |
0240  *                |       |###########|     +-----------+
0241  *                |       |###########|     |   vGPU2   |
0242  *                |       +-----------+     +-----------+
0243  *       unmappable GM    | available | ==> |   vGPU1   |
0244  *                |       +-----------+     +-----------+
0245  *                |       |###########|     |           |
0246  *                |       |###########|     |   Host    |
0247  *                v       |###########|     |           |
0248  *  total GM size ------> +-----------+     +-----------+
0249  *
0250  * Returns:
0251  * zero on success, non-zero if configuration invalid or ballooning failed
0252  */
0253 int intel_vgt_balloon(struct i915_ggtt *ggtt)
0254 {
0255     struct drm_i915_private *dev_priv = ggtt->vm.i915;
0256     struct intel_uncore *uncore = &dev_priv->uncore;
0257     unsigned long ggtt_end = ggtt->vm.total;
0258 
0259     unsigned long mappable_base, mappable_size, mappable_end;
0260     unsigned long unmappable_base, unmappable_size, unmappable_end;
0261     int ret;
0262 
0263     if (!intel_vgpu_active(ggtt->vm.i915))
0264         return 0;
0265 
0266     mappable_base =
0267       intel_uncore_read(uncore, vgtif_reg(avail_rs.mappable_gmadr.base));
0268     mappable_size =
0269       intel_uncore_read(uncore, vgtif_reg(avail_rs.mappable_gmadr.size));
0270     unmappable_base =
0271       intel_uncore_read(uncore, vgtif_reg(avail_rs.nonmappable_gmadr.base));
0272     unmappable_size =
0273       intel_uncore_read(uncore, vgtif_reg(avail_rs.nonmappable_gmadr.size));
0274 
0275     mappable_end = mappable_base + mappable_size;
0276     unmappable_end = unmappable_base + unmappable_size;
0277 
0278     drm_info(&dev_priv->drm, "VGT ballooning configuration:\n");
0279     drm_info(&dev_priv->drm,
0280          "Mappable graphic memory: base 0x%lx size %ldKiB\n",
0281          mappable_base, mappable_size / 1024);
0282     drm_info(&dev_priv->drm,
0283          "Unmappable graphic memory: base 0x%lx size %ldKiB\n",
0284          unmappable_base, unmappable_size / 1024);
0285 
0286     if (mappable_end > ggtt->mappable_end ||
0287         unmappable_base < ggtt->mappable_end ||
0288         unmappable_end > ggtt_end) {
0289         drm_err(&dev_priv->drm, "Invalid ballooning configuration!\n");
0290         return -EINVAL;
0291     }
0292 
0293     /* Unmappable graphic memory ballooning */
0294     if (unmappable_base > ggtt->mappable_end) {
0295         ret = vgt_balloon_space(ggtt, &bl_info.space[2],
0296                     ggtt->mappable_end, unmappable_base);
0297 
0298         if (ret)
0299             goto err;
0300     }
0301 
0302     if (unmappable_end < ggtt_end) {
0303         ret = vgt_balloon_space(ggtt, &bl_info.space[3],
0304                     unmappable_end, ggtt_end);
0305         if (ret)
0306             goto err_upon_mappable;
0307     }
0308 
0309     /* Mappable graphic memory ballooning */
0310     if (mappable_base) {
0311         ret = vgt_balloon_space(ggtt, &bl_info.space[0],
0312                     0, mappable_base);
0313 
0314         if (ret)
0315             goto err_upon_unmappable;
0316     }
0317 
0318     if (mappable_end < ggtt->mappable_end) {
0319         ret = vgt_balloon_space(ggtt, &bl_info.space[1],
0320                     mappable_end, ggtt->mappable_end);
0321 
0322         if (ret)
0323             goto err_below_mappable;
0324     }
0325 
0326     drm_info(&dev_priv->drm, "VGT balloon successfully\n");
0327     return 0;
0328 
0329 err_below_mappable:
0330     vgt_deballoon_space(ggtt, &bl_info.space[0]);
0331 err_upon_unmappable:
0332     vgt_deballoon_space(ggtt, &bl_info.space[3]);
0333 err_upon_mappable:
0334     vgt_deballoon_space(ggtt, &bl_info.space[2]);
0335 err:
0336     drm_err(&dev_priv->drm, "VGT balloon fail\n");
0337     return ret;
0338 }