Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. /*
  2.  * Copyright(c) 2011-2015 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 "intel_drv.h"
  25. #include "i915_vgpu.h"
  26.  
  27. /**
  28.  * DOC: Intel GVT-g guest support
  29.  *
  30.  * Intel GVT-g is a graphics virtualization technology which shares the
  31.  * GPU among multiple virtual machines on a time-sharing basis. Each
  32.  * virtual machine is presented a virtual GPU (vGPU), which has equivalent
  33.  * features as the underlying physical GPU (pGPU), so i915 driver can run
  34.  * seamlessly in a virtual machine. This file provides vGPU specific
  35.  * optimizations when running in a virtual machine, to reduce the complexity
  36.  * of vGPU emulation and to improve the overall performance.
  37.  *
  38.  * A primary function introduced here is so-called "address space ballooning"
  39.  * technique. Intel GVT-g partitions global graphics memory among multiple VMs,
  40.  * so each VM can directly access a portion of the memory without hypervisor's
  41.  * intervention, e.g. filling textures or queuing commands. However with the
  42.  * partitioning an unmodified i915 driver would assume a smaller graphics
  43.  * memory starting from address ZERO, then requires vGPU emulation module to
  44.  * translate the graphics address between 'guest view' and 'host view', for
  45.  * all registers and command opcodes which contain a graphics memory address.
  46.  * To reduce the complexity, Intel GVT-g introduces "address space ballooning",
  47.  * by telling the exact partitioning knowledge to each guest i915 driver, which
  48.  * then reserves and prevents non-allocated portions from allocation. Thus vGPU
  49.  * emulation module only needs to scan and validate graphics addresses without
  50.  * complexity of address translation.
  51.  *
  52.  */
  53.  
  54. /**
  55.  * i915_check_vgpu - detect virtual GPU
  56.  * @dev: drm device *
  57.  *
  58.  * This function is called at the initialization stage, to detect whether
  59.  * running on a vGPU.
  60.  */
  61. void i915_check_vgpu(struct drm_device *dev)
  62. {
  63.         struct drm_i915_private *dev_priv = to_i915(dev);
  64.         uint64_t magic;
  65.         uint32_t version;
  66.  
  67.         BUILD_BUG_ON(sizeof(struct vgt_if) != VGT_PVINFO_SIZE);
  68.  
  69.         if (!IS_HASWELL(dev))
  70.                 return;
  71.  
  72.         magic = readq(dev_priv->regs + vgtif_reg(magic));
  73.         if (magic != VGT_MAGIC)
  74.                 return;
  75.  
  76.         version = INTEL_VGT_IF_VERSION_ENCODE(
  77.                 readw(dev_priv->regs + vgtif_reg(version_major)),
  78.                 readw(dev_priv->regs + vgtif_reg(version_minor)));
  79.         if (version != INTEL_VGT_IF_VERSION) {
  80.                 DRM_INFO("VGT interface version mismatch!\n");
  81.                 return;
  82.         }
  83.  
  84.         dev_priv->vgpu.active = true;
  85.         DRM_INFO("Virtual GPU for Intel GVT-g detected.\n");
  86. }
  87.  
  88. struct _balloon_info_ {
  89.         /*
  90.          * There are up to 2 regions per mappable/unmappable graphic
  91.          * memory that might be ballooned. Here, index 0/1 is for mappable
  92.          * graphic memory, 2/3 for unmappable graphic memory.
  93.          */
  94.         struct drm_mm_node space[4];
  95. };
  96.  
  97. static struct _balloon_info_ bl_info;
  98.  
  99. /**
  100.  * intel_vgt_deballoon - deballoon reserved graphics address trunks
  101.  *
  102.  * This function is called to deallocate the ballooned-out graphic memory, when
  103.  * driver is unloaded or when ballooning fails.
  104.  */
  105. void intel_vgt_deballoon(void)
  106. {
  107.         int i;
  108.  
  109.         DRM_DEBUG("VGT deballoon.\n");
  110.  
  111.         for (i = 0; i < 4; i++) {
  112.                 if (bl_info.space[i].allocated)
  113.                         drm_mm_remove_node(&bl_info.space[i]);
  114.         }
  115.  
  116.         memset(&bl_info, 0, sizeof(bl_info));
  117. }
  118.  
  119. static int vgt_balloon_space(struct drm_mm *mm,
  120.                              struct drm_mm_node *node,
  121.                              unsigned long start, unsigned long end)
  122. {
  123.         unsigned long size = end - start;
  124.  
  125.         if (start == end)
  126.                 return -EINVAL;
  127.  
  128.         DRM_INFO("balloon space: range [ 0x%lx - 0x%lx ] %lu KiB.\n",
  129.                  start, end, size / 1024);
  130.  
  131.         node->start = start;
  132.         node->size = size;
  133.  
  134.         return drm_mm_reserve_node(mm, node);
  135. }
  136.  
  137. /**
  138.  * intel_vgt_balloon - balloon out reserved graphics address trunks
  139.  * @dev: drm device
  140.  *
  141.  * This function is called at the initialization stage, to balloon out the
  142.  * graphic address space allocated to other vGPUs, by marking these spaces as
  143.  * reserved. The ballooning related knowledge(starting address and size of
  144.  * the mappable/unmappable graphic memory) is described in the vgt_if structure
  145.  * in a reserved mmio range.
  146.  *
  147.  * To give an example, the drawing below depicts one typical scenario after
  148.  * ballooning. Here the vGPU1 has 2 pieces of graphic address spaces ballooned
  149.  * out each for the mappable and the non-mappable part. From the vGPU1 point of
  150.  * view, the total size is the same as the physical one, with the start address
  151.  * of its graphic space being zero. Yet there are some portions ballooned out(
  152.  * the shadow part, which are marked as reserved by drm allocator). From the
  153.  * host point of view, the graphic address space is partitioned by multiple
  154.  * vGPUs in different VMs.
  155.  *
  156.  *                        vGPU1 view         Host view
  157.  *             0 ------> +-----------+     +-----------+
  158.  *               ^       |///////////|     |   vGPU3   |
  159.  *               |       |///////////|     +-----------+
  160.  *               |       |///////////|     |   vGPU2   |
  161.  *               |       +-----------+     +-----------+
  162.  *        mappable GM    | available | ==> |   vGPU1   |
  163.  *               |       +-----------+     +-----------+
  164.  *               |       |///////////|     |           |
  165.  *               v       |///////////|     |   Host    |
  166.  *               +=======+===========+     +===========+
  167.  *               ^       |///////////|     |   vGPU3   |
  168.  *               |       |///////////|     +-----------+
  169.  *               |       |///////////|     |   vGPU2   |
  170.  *               |       +-----------+     +-----------+
  171.  *      unmappable GM    | available | ==> |   vGPU1   |
  172.  *               |       +-----------+     +-----------+
  173.  *               |       |///////////|     |           |
  174.  *               |       |///////////|     |   Host    |
  175.  *               v       |///////////|     |           |
  176.  * total GM size ------> +-----------+     +-----------+
  177.  *
  178.  * Returns:
  179.  * zero on success, non-zero if configuration invalid or ballooning failed
  180.  */
  181. int intel_vgt_balloon(struct drm_device *dev)
  182. {
  183.         struct drm_i915_private *dev_priv = to_i915(dev);
  184.         struct i915_address_space *ggtt_vm = &dev_priv->gtt.base;
  185.         unsigned long ggtt_vm_end = ggtt_vm->start + ggtt_vm->total;
  186.  
  187.         unsigned long mappable_base, mappable_size, mappable_end;
  188.         unsigned long unmappable_base, unmappable_size, unmappable_end;
  189.         int ret;
  190.  
  191.         mappable_base = I915_READ(vgtif_reg(avail_rs.mappable_gmadr.base));
  192.         mappable_size = I915_READ(vgtif_reg(avail_rs.mappable_gmadr.size));
  193.         unmappable_base = I915_READ(vgtif_reg(avail_rs.nonmappable_gmadr.base));
  194.         unmappable_size = I915_READ(vgtif_reg(avail_rs.nonmappable_gmadr.size));
  195.  
  196.         mappable_end = mappable_base + mappable_size;
  197.         unmappable_end = unmappable_base + unmappable_size;
  198.  
  199.         DRM_INFO("VGT ballooning configuration:\n");
  200.         DRM_INFO("Mappable graphic memory: base 0x%lx size %ldKiB\n",
  201.                  mappable_base, mappable_size / 1024);
  202.         DRM_INFO("Unmappable graphic memory: base 0x%lx size %ldKiB\n",
  203.                  unmappable_base, unmappable_size / 1024);
  204.  
  205.         if (mappable_base < ggtt_vm->start ||
  206.             mappable_end > dev_priv->gtt.mappable_end ||
  207.             unmappable_base < dev_priv->gtt.mappable_end ||
  208.             unmappable_end > ggtt_vm_end) {
  209.                 DRM_ERROR("Invalid ballooning configuration!\n");
  210.                 return -EINVAL;
  211.         }
  212.  
  213.         /* Unmappable graphic memory ballooning */
  214.         if (unmappable_base > dev_priv->gtt.mappable_end) {
  215.                 ret = vgt_balloon_space(&ggtt_vm->mm,
  216.                                         &bl_info.space[2],
  217.                                         dev_priv->gtt.mappable_end,
  218.                                         unmappable_base);
  219.  
  220.                 if (ret)
  221.                         goto err;
  222.         }
  223.  
  224.         /*
  225.          * No need to partition out the last physical page,
  226.          * because it is reserved to the guard page.
  227.          */
  228.         if (unmappable_end < ggtt_vm_end - PAGE_SIZE) {
  229.                 ret = vgt_balloon_space(&ggtt_vm->mm,
  230.                                         &bl_info.space[3],
  231.                                         unmappable_end,
  232.                                         ggtt_vm_end - PAGE_SIZE);
  233.                 if (ret)
  234.                         goto err;
  235.         }
  236.  
  237.         /* Mappable graphic memory ballooning */
  238.         if (mappable_base > ggtt_vm->start) {
  239.                 ret = vgt_balloon_space(&ggtt_vm->mm,
  240.                                         &bl_info.space[0],
  241.                                         ggtt_vm->start, mappable_base);
  242.  
  243.                 if (ret)
  244.                         goto err;
  245.         }
  246.  
  247.         if (mappable_end < dev_priv->gtt.mappable_end) {
  248.                 ret = vgt_balloon_space(&ggtt_vm->mm,
  249.                                         &bl_info.space[1],
  250.                                         mappable_end,
  251.                                         dev_priv->gtt.mappable_end);
  252.  
  253.                 if (ret)
  254.                         goto err;
  255.         }
  256.  
  257.         DRM_INFO("VGT balloon successfully\n");
  258.         return 0;
  259.  
  260. err:
  261.         DRM_ERROR("VGT balloon fail\n");
  262.         intel_vgt_deballoon();
  263.         return ret;
  264. }
  265.