From: Yulei Zhang <[email protected]>

This patch introduces the GVT-g resource allocator. Under virtualization
environment, GGTT and fences are partitioned. GGTT memory space and fences
for i915 are limited. Only a part of GGTT memory space and fences is owned
by host. The left resources are mananged by GVT-g resource allocators.

Signed-off-by: Yulei Zhang <[email protected]>
Signed-off-by: Zhi Wang <[email protected]>
---
 drivers/gpu/drm/i915/gvt/Makefile      |   2 +-
 drivers/gpu/drm/i915/gvt/aperture_gm.c | 225 +++++++++++++++++++++++++++++++++
 drivers/gpu/drm/i915/gvt/gvt.c         |   3 +
 drivers/gpu/drm/i915/gvt/gvt.h         | 105 +++++++++++++++
 drivers/gpu/drm/i915/gvt/params.c      |  12 ++
 drivers/gpu/drm/i915/gvt/params.h      |   8 ++
 6 files changed, 354 insertions(+), 1 deletion(-)
 create mode 100644 drivers/gpu/drm/i915/gvt/aperture_gm.c

diff --git a/drivers/gpu/drm/i915/gvt/Makefile 
b/drivers/gpu/drm/i915/gvt/Makefile
index 6935b78..6655929 100644
--- a/drivers/gpu/drm/i915/gvt/Makefile
+++ b/drivers/gpu/drm/i915/gvt/Makefile
@@ -1,4 +1,4 @@
-GVT_SOURCE := gvt.o params.o fb_decoder.o
+GVT_SOURCE := gvt.o params.o aperture_gm.o fb_decoder.o
 
 ccflags-y                      += -I$(src) -I$(src)/.. -Wall -Werror 
-Wno-unused-function
 i915_gvt-y                     := $(GVT_SOURCE)
diff --git a/drivers/gpu/drm/i915/gvt/aperture_gm.c 
b/drivers/gpu/drm/i915/gvt/aperture_gm.c
new file mode 100644
index 0000000..7cb15c1
--- /dev/null
+++ b/drivers/gpu/drm/i915/gvt/aperture_gm.c
@@ -0,0 +1,225 @@
+/*
+ * Copyright(c) 2011-2016 Intel Corporation. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 
THE
+ * SOFTWARE.
+ */
+
+#include "gvt.h"
+
+void init_gm_allocator(struct pgt_device *pdev,
+               u64 start, u64 size, bool mappable)
+{
+       struct drm_mm *mm = mappable ?
+               &pdev->gm_allocator.low_gm : &pdev->gm_allocator.high_gm;
+
+       drm_mm_init(mm, start, size);
+}
+
+void clean_gm_allocator(struct pgt_device *pdev)
+{
+       if (!drm_mm_initialized(&pdev->gm_allocator.low_gm)
+                       || !drm_mm_initialized(&pdev->gm_allocator.high_gm))
+               return;
+
+       drm_mm_takedown(&pdev->gm_allocator.low_gm);
+       drm_mm_takedown(&pdev->gm_allocator.high_gm);
+}
+
+struct drm_mm_node *alloc_gm_node(struct pgt_device *pdev, u32 size, bool 
mappable)
+{
+       struct drm_mm_node *node;
+       struct drm_mm *mm = mappable ?
+               &pdev->gm_allocator.low_gm : &pdev->gm_allocator.high_gm;
+       int ret;
+
+       if (!drm_mm_initialized(mm))
+               return NULL;
+
+       DRM_DEBUG_KMS("creating vgt %s object: size=%x\n",
+                       mappable ? "mappable" : "unmappable", size);
+       if (size == 0)
+               return NULL;
+
+       node = kzalloc(sizeof(*node), GFP_KERNEL);
+       if (!node)
+               return NULL;
+
+       ret = drm_mm_insert_node(mm, node, size,
+                       PAGE_SIZE, DRM_MM_SEARCH_DEFAULT);
+       if (ret) {
+               kfree(node);
+               return NULL;
+       }
+
+       return node;
+}
+
+void free_gm_node(struct drm_mm_node *node)
+{
+       drm_mm_remove_node(node);
+       kfree(node);
+}
+
+static bool check_instance_info(struct vgt_device *vgt,
+               struct gvt_instance_info *info)
+{
+       struct pgt_device *pdev = vgt->pdev;
+
+       if (gvt_aperture_base(vgt)) {
+               gvt_err("resources have already been allocated");
+               return false;
+       }
+
+       if (!info->low_gm_sz || !info->high_gm_sz || !info->fence_sz ||
+               info->low_gm_sz > phys_aperture_sz(pdev) ||
+               info->high_gm_sz > gm_sz(pdev) - phys_aperture_sz(pdev)) {
+               gvt_err("invalid resource configuration");
+               gvt_err("demand low GM size %u max low GM size %llu",
+                       info->low_gm_sz, phys_aperture_sz(pdev));
+               gvt_err("demand high GM size %u max high GM size %llu",
+                       info->high_gm_sz, gm_sz(pdev) - phys_aperture_sz(pdev));
+               gvt_err("fence size %u", info->fence_sz);
+               return false;
+       }
+
+       return true;
+}
+
+static void clear_fence(struct vgt_device *vgt)
+{
+       struct pgt_device *pdev = vgt->pdev;
+       int i;
+
+       for (i = 0; i < gvt_fence_sz(vgt); i++)
+               gvt_mmio_write64(pdev,
+                       i915_mmio_reg_offset(FENCE_REG_GEN6_LO(i + 
gvt_fence_base(vgt))), 0);
+}
+
+void gvt_free_gm_and_fence_resource(struct vgt_device *vgt)
+{
+       struct pgt_device *pdev = vgt->pdev;
+       unsigned long *fence_bitmap = pdev->fence_bitmap;
+
+       if (vgt->state.gm.node.low_gm_node) {
+               free_gm_node(vgt->state.gm.node.low_gm_node);
+               vgt->state.gm.node.low_gm_node = NULL;
+       }
+
+       if (vgt->state.gm.node.high_gm_node) {
+               free_gm_node(vgt->state.gm.node.high_gm_node);
+               vgt->state.gm.node.high_gm_node = NULL;
+       }
+
+       if (gvt_fence_sz(vgt) && gvt_fence_base(vgt)) {
+               bitmap_clear(fence_bitmap, gvt_fence_base(vgt), 
gvt_fence_sz(vgt));
+               clear_fence(vgt);
+               gvt_fence_sz(vgt) = gvt_fence_base(vgt) = 0;
+       }
+}
+
+int gvt_alloc_gm_and_fence_resource(struct vgt_device *vgt,
+       struct gvt_instance_info *info)
+{
+       struct pgt_device *pdev = vgt->pdev;
+       struct drm_mm_node *node;
+       unsigned long *fence_bitmap = pdev->fence_bitmap;
+       unsigned long fence_base;
+
+       if (!check_instance_info(vgt, info)) {
+               gvt_err("invalid resoure configuration");
+               return -EINVAL;
+       }
+
+       node = alloc_gm_node(pdev, info->low_gm_sz << 20, true);
+       if (!node) {
+               gvt_err("fail to allocate low GM space");
+               goto err;
+       }
+
+       vgt->state.gm.node.low_gm_node = node;
+
+       gvt_aperture_base(vgt) = phys_aperture_base(vgt->pdev) + node->start;
+       gvt_aperture_sz(vgt) = info->low_gm_sz << 20;
+
+       node = alloc_gm_node(pdev, info->high_gm_sz << 20, false);
+       if (!node) {
+               gvt_err("fail to allocate high GM space");
+               goto err;
+       }
+
+       vgt->state.gm.node.high_gm_node = node;
+
+       gvt_hidden_gm_offset(vgt) = node->start;
+       gvt_gm_sz(vgt) = (info->low_gm_sz + info->high_gm_sz) << 20;
+
+       fence_base = bitmap_find_next_zero_area(fence_bitmap,
+                               GVT_FENCE_BITMAP_BITS, 0, info->fence_sz, 0);
+       if (fence_base >= GVT_MAX_NUM_FENCES) {
+               gvt_err("fail to allocate fence");
+               goto err;
+       }
+
+       gvt_fence_base(vgt) = fence_base;
+       gvt_fence_sz(vgt) = info->fence_sz;
+
+       bitmap_set(fence_bitmap, fence_base, info->fence_sz);
+
+       clear_fence(vgt);
+
+       return 0;
+err:
+       gvt_free_gm_and_fence_resource(vgt);
+       return -ENOMEM;
+}
+
+void gvt_init_resource_allocator(struct pgt_device *pdev)
+{
+       struct gvt_device_info *info = &pdev->device_info;
+       int i;
+       unsigned long *fence_bitmap = pdev->fence_bitmap;
+
+       gvt_info("total aperture: 0x%llx bytes, total GM space: 0x%llx bytes\n",
+               phys_aperture_sz(pdev), gm_sz(pdev));
+
+       ASSERT(phys_aperture_sz(pdev) % (1 << 20) == 0);
+       ASSERT(gm_sz(pdev) % (1 << 20) == 0);
+       ASSERT(phys_aperture_sz(pdev) <= gm_sz(pdev) && gm_sz(pdev) <= 
info->max_gtt_gm_sz);
+       ASSERT(info->max_gtt_gm_sz <= GVT_MAX_GM_SIZE);
+
+       /* Basic memrange allocator for vgt low memory */
+       init_gm_allocator(pdev, gvt.dom0_low_gm_sz << 20,
+                       (phys_aperture_sz(pdev) - (gvt.dom0_low_gm_sz << 20)), 
true);
+
+       /* Basic memrange allocate for vgt high memory */
+       init_gm_allocator(pdev,
+                       (phys_aperture_sz(pdev) + (gvt.dom0_high_gm_sz << 20)),
+                       (gm_sz(pdev) - (gvt.dom0_high_gm_sz << 20)), false);
+
+       /* Reserve fence region for dom0 */
+       bitmap_set(fence_bitmap, 0, gvt.dom0_fence_sz);
+
+       for (i = 0; i < gvt.dom0_fence_sz; i++)
+               gvt_mmio_write64(pdev, 
i915_mmio_reg_offset(FENCE_REG_GEN6_LO(i)), 0);
+}
+
+void gvt_clean_resource_allocator(struct pgt_device *pdev)
+{
+       clean_gm_allocator(pdev);
+}
diff --git a/drivers/gpu/drm/i915/gvt/gvt.c b/drivers/gpu/drm/i915/gvt/gvt.c
index 041d10f..f31e9f7 100644
--- a/drivers/gpu/drm/i915/gvt/gvt.c
+++ b/drivers/gpu/drm/i915/gvt/gvt.c
@@ -234,6 +234,7 @@ static void clean_pgt_device(struct pgt_device *pdev)
 {
        clean_service_thread(pdev);
        clean_initial_mmio_state(pdev);
+       gvt_clean_resource_allocator(pdev);
 }
 
 static bool init_pgt_device(struct pgt_device *pdev, struct drm_i915_private 
*dev_priv)
@@ -246,6 +247,8 @@ static bool init_pgt_device(struct pgt_device *pdev, struct 
drm_i915_private *de
        if (!init_initial_mmio_state(pdev))
                goto err;
 
+       gvt_init_resource_allocator(pdev);
+
        if (!init_service_thread(pdev))
                goto err;
 
diff --git a/drivers/gpu/drm/i915/gvt/gvt.h b/drivers/gpu/drm/i915/gvt/gvt.h
index 6c85bba..aa4851c 100644
--- a/drivers/gpu/drm/i915/gvt/gvt.h
+++ b/drivers/gpu/drm/i915/gvt/gvt.h
@@ -36,6 +36,11 @@
 
 #define GVT_MAX_VGPU 8
 
+#define GVT_MAX_GM_SIZE                (1UL << 32)
+#define GVT_GM_BITMAP_BITS     (GVT_MAX_GM_SIZE >> 20)
+#define GVT_MAX_NUM_FENCES     32
+#define GVT_FENCE_BITMAP_BITS  GVT_MAX_NUM_FENCES
+
 enum {
        GVT_HYPERVISOR_TYPE_XEN = 0,
        GVT_HYPERVISOR_TYPE_KVM,
@@ -62,11 +67,38 @@ struct gvt_device_info {
        u32 gmadr_bytes_in_cmd;
 };
 
+struct gvt_gm_node {
+       struct drm_mm_node *low_gm_node;
+       struct drm_mm_node *high_gm_node;
+};
+
+struct gvt_virtual_gm_state {
+       u64 aperture_base;
+       void *aperture_base_va;
+       u64 aperture_sz;
+       u64 gm_sz;
+       u64 aperture_offset;        /* address fix for visible GM */
+       u64 hidden_gm_offset;       /* address fix for invisible GM */
+       int fence_base;
+       int fence_sz;
+       struct gvt_gm_node node;
+};
+
+struct gvt_virtual_device_state {
+       struct gvt_virtual_gm_state gm;
+};
+
 struct vgt_device {
        int id;
        int vm_id;
        struct pgt_device *pdev;
        bool warn_untrack;
+       struct gvt_virtual_device_state state;
+};
+
+struct gvt_gm_allocator {
+       struct drm_mm low_gm;
+       struct drm_mm high_gm;
 };
 
 struct pgt_device {
@@ -93,8 +125,81 @@ struct pgt_device {
        wait_queue_head_t service_thread_wq;
        struct task_struct *service_thread;
        unsigned long service_request;
+
+       /* 1 bit corresponds to 1MB in the GM space */
+       DECLARE_BITMAP(gm_bitmap, GVT_GM_BITMAP_BITS);
+
+       /* 1 bit corresponds to 1 fence register */
+       DECLARE_BITMAP(fence_bitmap, GVT_FENCE_BITMAP_BITS);
+
+       u64 total_gm_sz;
+       struct gvt_gm_allocator gm_allocator;
 };
 
+/* definitions for physical aperture/GM space */
+#define phys_aperture_sz(pdev)          (pdev->bar_size[1])
+#define phys_aperture_pages(pdev)       (phys_aperture_sz(pdev) >> 
GTT_PAGE_SHIFT)
+#define phys_aperture_base(pdev)        (pdev->gmadr_base)
+#define phys_aperture_vbase(pdev)       (pdev->gmadr_va)
+
+#define gm_sz(pdev)                     (pdev->total_gm_sz)
+#define gm_base(pdev)                   (0ULL)
+#define gm_pages(pdev)                  (gm_sz(pdev) >> GTT_PAGE_SHIFT)
+#define hidden_gm_base(pdev)            (phys_aperture_sz(pdev))
+
+#define aperture_2_gm(pdev, addr)       (addr - phys_aperture_base(pdev))
+#define v_aperture(pdev, addr)          (phys_aperture_vbase(pdev) + (addr))
+
+/* definitions for vgt's aperture/gm space */
+#define gvt_aperture_base(vgt)         (vgt->state.gm.aperture_base)
+#define gvt_aperture_vbase(vgt)                (vgt->state.gm.aperture_base_va)
+#define gvt_aperture_offset(vgt)       (vgt->state.gm.aperture_offset)
+#define gvt_hidden_gm_offset(vgt)      (vgt->state.gm.hidden_gm_offset)
+#define gvt_aperture_sz(vgt)           (vgt->state.gm.aperture_sz)
+#define gvt_gm_sz(vgt)                 (vgt->state.gm.gm_sz)
+#define gvt_hidden_gm_sz(vgt)          (gvt_gm_sz(vgt) - gvt_aperture_sz(vgt))
+#define gvt_fence_base(vgt)            (vgt->state.gm.fence_base)
+#define gvt_fence_sz(vgt)              (vgt->state.gm.fence_sz)
+
+#define gvt_aperture_end(vgt)           \
+       (gvt_aperture_base(vgt) + gvt_aperture_sz(vgt) - 1)
+#define gvt_visible_gm_base(vgt)        \
+       (gm_base(vgt->pdev) + gvt_aperture_offset(vgt))
+#define gvt_visible_gm_end(vgt)         \
+       (gvt_visible_gm_base(vgt) + gvt_aperture_sz(vgt) - 1)
+#define gvt_hidden_gm_base(vgt) \
+       (gm_base(vgt->pdev) + gvt_hidden_gm_offset(vgt))
+#define gvt_hidden_gm_end(vgt)          \
+       (gvt_hidden_gm_base(vgt) + gvt_hidden_gm_sz(vgt) - 1)
+
+/*
+ * the view of the aperture/gm space from the VM's p.o.v
+ *
+ * when the VM supports ballooning, this view is the same as the
+ * view of vGT driver.
+ *
+ * when the VM does not support ballooning, this view starts from
+ * GM space ZERO
+ */
+#define gvt_guest_aperture_base(vgt)    \
+       ((*((u32*)&vgt->state.cfg.space[GVT_REG_CFG_SPACE_BAR1]) & ~0xf) + 
gvt_aperture_offset(vgt))
+#define gvt_guest_aperture_end(vgt)     \
+        (gvt_guest_aperture_base(vgt) + gvt_aperture_sz(vgt) - 1)
+#define gvt_guest_visible_gm_base(vgt)  \
+        (gvt_visible_gm_base(vgt))
+#define gvt_guest_visible_gm_end(vgt)   \
+        (gvt_guest_visible_gm_base(vgt) + gvt_aperture_sz(vgt) - 1)
+#define gvt_guest_hidden_gm_base(vgt)   \
+       gvt_hidden_gm_base(vgt)
+#define gvt_guest_hidden_gm_end(vgt)    \
+        (gvt_guest_hidden_gm_base(vgt) + gvt_hidden_gm_sz(vgt) - 1)
+
+extern void gvt_init_resource_allocator(struct pgt_device *pdev);
+extern void gvt_clean_resource_allocator(struct pgt_device *pdev);
+extern int gvt_alloc_gm_and_fence_resource(struct vgt_device *vgt,
+               struct gvt_instance_info *info);
+extern void gvt_free_gm_and_fence_resource(struct vgt_device *vgt);
+
 static inline u32 gvt_mmio_read(struct pgt_device *pdev,
                u32 reg)
 {
diff --git a/drivers/gpu/drm/i915/gvt/params.c 
b/drivers/gpu/drm/i915/gvt/params.c
index dfc33c3..6cd324c 100644
--- a/drivers/gpu/drm/i915/gvt/params.c
+++ b/drivers/gpu/drm/i915/gvt/params.c
@@ -26,4 +26,16 @@
 struct gvt_kernel_params gvt = {
        .enable = true,
        .debug = 0,
+       .dom0_low_gm_sz = 96,
+       .dom0_high_gm_sz = 384,
+       .dom0_fence_sz = 4,
 };
+
+module_param_named(dom0_low_gm_sz, gvt.dom0_low_gm_sz, int, 0600);
+MODULE_PARM_DESC(dom0_low_gm_sz, "Amount of aperture size of DOM0");
+
+module_param_named(dom0_high_gm_sz, gvt.dom0_high_gm_sz, int, 0600);
+MODULE_PARM_DESC(dom0_high_gm_sz, "Amount of high memory size of DOM0");
+
+module_param_named(dom0_fence_sz, gvt.dom0_fence_sz, int, 0600);
+MODULE_PARM_DESC(dom0_fence_sz, "Amount of fence size of DOM0");
diff --git a/drivers/gpu/drm/i915/gvt/params.h 
b/drivers/gpu/drm/i915/gvt/params.h
index 0656a98..0507870 100644
--- a/drivers/gpu/drm/i915/gvt/params.h
+++ b/drivers/gpu/drm/i915/gvt/params.h
@@ -34,4 +34,12 @@ struct gvt_kernel_params {
 
 extern struct gvt_kernel_params gvt;
 
+struct gvt_instance_info {
+       u32 domid;
+       u32 low_gm_sz;
+       u32 high_gm_sz;
+       u32 fence_sz;
+       s32 primary;
+};
+
 #endif
-- 
1.9.1

_______________________________________________
Intel-gfx mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

Reply via email to