drm/i915/gvt: reset the GGTT entry when vGPU created
authorPing Gao <ping.a.gao@intel.com>
Thu, 8 Dec 2016 02:14:48 +0000 (10:14 +0800)
committerZhenyu Wang <zhenyuw@linux.intel.com>
Mon, 26 Dec 2016 01:45:29 +0000 (09:45 +0800)
The GGTT space is partitioned between vGPUs, it could be reused by
next vGPU after previous one is release, the stale entries need
point to scratch page when vGPU created.

v2: Reset logic move to vGPU create.
v3: Correct the commit msg.
v4: Move the reset function to vGPU init gtt function, as result it's no
    need explicitly in vGPU reset logic as vGPU init gtt called during
    reset.

Signed-off-by: Ping Gao <ping.a.gao@intel.com>
Signed-off-by: Zhenyu Wang <zhenyuw@linux.intel.com>
drivers/gpu/drm/i915/gvt/gtt.c
drivers/gpu/drm/i915/gvt/gtt.h

index 7eaaf1c9ed2bf47e935bf0592a4c00658838086d..6c5fdf5b2ce2a9d407839a3a28a7e067a5630d8d 100644 (file)
@@ -1998,6 +1998,8 @@ int intel_vgpu_init_gtt(struct intel_vgpu *vgpu)
        INIT_LIST_HEAD(&gtt->oos_page_list_head);
        INIT_LIST_HEAD(&gtt->post_shadow_list_head);
 
+       intel_vgpu_reset_ggtt(vgpu);
+
        ggtt_mm = intel_vgpu_create_mm(vgpu, INTEL_GVT_MM_GGTT,
                        NULL, 1, 0);
        if (IS_ERR(ggtt_mm)) {
@@ -2206,6 +2208,7 @@ int intel_vgpu_g2v_destroy_ppgtt_mm(struct intel_vgpu *vgpu,
 int intel_gvt_init_gtt(struct intel_gvt *gvt)
 {
        int ret;
+       void *page_addr;
 
        gvt_dbg_core("init gtt\n");
 
@@ -2218,6 +2221,23 @@ int intel_gvt_init_gtt(struct intel_gvt *gvt)
                return -ENODEV;
        }
 
+       gvt->gtt.scratch_ggtt_page =
+               alloc_page(GFP_KERNEL | GFP_ATOMIC | __GFP_ZERO);
+       if (!gvt->gtt.scratch_ggtt_page) {
+               gvt_err("fail to allocate scratch ggtt page\n");
+               return -ENOMEM;
+       }
+
+       page_addr = page_address(gvt->gtt.scratch_ggtt_page);
+
+       gvt->gtt.scratch_ggtt_mfn =
+               intel_gvt_hypervisor_virt_to_mfn(page_addr);
+       if (gvt->gtt.scratch_ggtt_mfn == INTEL_GVT_INVALID_ADDR) {
+               gvt_err("fail to translate scratch ggtt page\n");
+               __free_page(gvt->gtt.scratch_ggtt_page);
+               return -EFAULT;
+       }
+
        if (enable_out_of_sync) {
                ret = setup_spt_oos(gvt);
                if (ret) {
@@ -2239,6 +2259,41 @@ int intel_gvt_init_gtt(struct intel_gvt *gvt)
  */
 void intel_gvt_clean_gtt(struct intel_gvt *gvt)
 {
+       __free_page(gvt->gtt.scratch_ggtt_page);
+
        if (enable_out_of_sync)
                clean_spt_oos(gvt);
 }
+
+/**
+ * intel_vgpu_reset_ggtt - reset the GGTT entry
+ * @vgpu: a vGPU
+ *
+ * This function is called at the vGPU create stage
+ * to reset all the GGTT entries.
+ *
+ */
+void intel_vgpu_reset_ggtt(struct intel_vgpu *vgpu)
+{
+       struct intel_gvt *gvt = vgpu->gvt;
+       struct intel_gvt_gtt_pte_ops *ops = vgpu->gvt->gtt.pte_ops;
+       u32 index;
+       u32 offset;
+       u32 num_entries;
+       struct intel_gvt_gtt_entry e;
+
+       memset(&e, 0, sizeof(struct intel_gvt_gtt_entry));
+       e.type = GTT_TYPE_GGTT_PTE;
+       ops->set_pfn(&e, gvt->gtt.scratch_ggtt_mfn);
+       e.val64 |= _PAGE_PRESENT;
+
+       index = vgpu_aperture_gmadr_base(vgpu) >> PAGE_SHIFT;
+       num_entries = vgpu_aperture_sz(vgpu) >> PAGE_SHIFT;
+       for (offset = 0; offset < num_entries; offset++)
+               ops->set_entry(NULL, &e, index + offset, false, 0, vgpu);
+
+       index = vgpu_hidden_gmadr_base(vgpu) >> PAGE_SHIFT;
+       num_entries = vgpu_hidden_sz(vgpu) >> PAGE_SHIFT;
+       for (offset = 0; offset < num_entries; offset++)
+               ops->set_entry(NULL, &e, index + offset, false, 0, vgpu);
+}
index d250013bc37b053f45b3b747668d791fa477de26..b315ab3593ec37f2e73faf564a6d6c9fee9e7c81 100644 (file)
@@ -81,6 +81,9 @@ struct intel_gvt_gtt {
        struct list_head oos_page_use_list_head;
        struct list_head oos_page_free_list_head;
        struct list_head mm_lru_list_head;
+
+       struct page *scratch_ggtt_page;
+       unsigned long scratch_ggtt_mfn;
 };
 
 enum {
@@ -202,6 +205,7 @@ struct intel_vgpu_gtt {
 
 extern int intel_vgpu_init_gtt(struct intel_vgpu *vgpu);
 extern void intel_vgpu_clean_gtt(struct intel_vgpu *vgpu);
+void intel_vgpu_reset_ggtt(struct intel_vgpu *vgpu);
 
 extern int intel_gvt_init_gtt(struct intel_gvt *gvt);
 extern void intel_gvt_clean_gtt(struct intel_gvt *gvt);