clear-pkgs-linux-iot-lts2018/1223-drm-i915-gvt-enable-gv...

286 lines
8.8 KiB
Diff
Raw Permalink Normal View History

2020-10-28 12:31:19 +08:00
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Liu Xinyun <xinyun.liu@intel.com>
Date: Tue, 10 Sep 2019 00:22:51 +0800
Subject: [PATCH] drm/i915/gvt: enable gvt gop support
Reserve 8MB memory block as graphics memory and pass it to Gop driver as
the guest framebuffer. This framebuffer guest physical address starts
from 0xDF000000 and works with fixed display mode 1920x1080@32bpp
Tracked-On: projectacrn/acrn-hypervisor#3624
Co-developed-by: He Min <min.he@intel.com>
Signed-off-by: He Min <min.he@intel.com>
Signed-off-by: Liu Xinyun <xinyun.liu@intel.com>
Reviewed-by: Zhao Yakui <yakui.zhao@intel.com>
---
drivers/gpu/drm/i915/gvt/display.c | 141 ++++++++++++++++++++++++++++
drivers/gpu/drm/i915/gvt/display.h | 1 +
drivers/gpu/drm/i915/gvt/gtt.c | 14 +++
drivers/gpu/drm/i915/gvt/gvt.h | 4 +
drivers/gpu/drm/i915/gvt/handlers.c | 2 +
drivers/gpu/drm/i915/gvt/vgpu.c | 1 +
drivers/gpu/drm/i915/i915_pvinfo.h | 2 +
7 files changed, 165 insertions(+)
diff --git a/drivers/gpu/drm/i915/gvt/display.c b/drivers/gpu/drm/i915/gvt/display.c
index 290d5b380a3e..24c41c3c6973 100644
--- a/drivers/gpu/drm/i915/gvt/display.c
+++ b/drivers/gpu/drm/i915/gvt/display.c
@@ -686,3 +686,144 @@ void intel_vgpu_reset_display(struct intel_vgpu *vgpu)
{
emulate_monitor_status_change(vgpu);
}
+
+/*
+ * prepare_gop_fb will allocate a arrange of memory, then map them into the
+ * ggtt table of the guest partition in the aperture.
+ */
+static int prepare_gop_fb(struct intel_vgpu *vgpu, u32 size)
+{
+ struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv;
+ struct page **pages = NULL;
+ u32 count, npages = size >> PAGE_SHIFT;
+ struct i915_ggtt *ggtt = &dev_priv->ggtt;
+ struct i915_vma vma;
+ struct drm_mm_node *node = &vgpu->gm.high_gm_node;
+ struct sg_table st;
+ unsigned int cache_level = HAS_LLC(dev_priv) ?
+ I915_CACHE_LLC : I915_CACHE_NONE;
+ int ret = 0;
+
+ pages = kmalloc_array(npages, sizeof(struct page *), GFP_KERNEL);
+ if (!pages)
+ return -ENOMEM;
+
+ for (count = 0; count < npages; count++) {
+ struct page *page = alloc_page(GFP_KERNEL);
+
+ if (!page) {
+ ret = -ENOMEM;
+ goto free_pgs;
+ }
+ pages[count] = page;
+
+ intel_gvt_hypervisor_map_gfn_to_mfn(vgpu,
+ (GOP_FB_BASE >> PAGE_SHIFT) + count,
+ page_to_pfn(page), 1, true);
+ }
+
+ ret = sg_alloc_table_from_pages(&st, pages, npages,
+ 0, npages << PAGE_SHIFT, GFP_KERNEL);
+ if (ret)
+ goto free_pgs;
+
+ if (!dma_map_sg(&dev_priv->drm.pdev->dev, st.sgl, st.nents,
+ PCI_DMA_BIDIRECTIONAL)) {
+ ret = -ENOMEM;
+ goto free_sg;
+ }
+
+ memset(&vma, 0, sizeof(vma));
+ vma.node.start = node->start;
+ vma.node.size = size;
+ vma.pages = &st;
+ ggtt->vm.insert_entries(&ggtt->vm, &vma, cache_level, 0);
+ sg_free_table(&st);
+
+ vgpu->gm.gop_fb_pages = pages;
+ vgpu->gm.gop_fb_size = count;
+ return 0;
+
+free_sg:
+ sg_free_table(&st);
+
+free_pgs:
+ release_pages(pages, count);
+ kfree(pages);
+ return ret;
+}
+
+#define GOP_DISPLAY_WIDTH 1920
+#define GOP_DISPLAY_HEIGHT 1080
+static int setup_gop_display(struct intel_vgpu *vgpu)
+{
+ int ret = 0;
+ unsigned int pipe, plane;
+ struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv;
+ bool found = false;
+ u32 width = GOP_DISPLAY_WIDTH, height = GOP_DISPLAY_HEIGHT;
+ u32 stride, ctl, surf;
+ unsigned long irqflags;
+
+
+ /* we will display the gop output on the first plane the vgpu ownes */
+ for_each_pipe(dev_priv, pipe) {
+ for_each_universal_plane(dev_priv, pipe, plane) {
+ if (vgpu->gvt->pipe_info[pipe].plane_owner[plane]
+ == vgpu->id) {
+ found = true;
+ break;
+ }
+ }
+ if (found)
+ break;
+ }
+
+ if (!found) {
+ gvt_dbg_dpy("Failed to find owned plane for %d", vgpu->id);
+ return -ENODEV;
+ }
+
+ /* Sizes are 0 based */
+ stride = width * 4 / 64; /* 32bit per pixel */
+ width--;
+ height--;
+ surf = vgpu->gm.high_gm_node.start;
+ ctl = PLANE_CTL_ENABLE | PLANE_CTL_FORMAT_XRGB_8888;
+ ctl |= PLANE_CTL_PIPE_GAMMA_ENABLE |
+ PLANE_CTL_PIPE_CSC_ENABLE |
+ PLANE_CTL_PLANE_GAMMA_DISABLE;
+ spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
+ I915_WRITE_FW(PLANE_OFFSET(pipe, plane), 0);
+ I915_WRITE_FW(PLANE_STRIDE(pipe, plane), stride);
+ I915_WRITE_FW(PLANE_SIZE(pipe, plane), (height << 16) | width);
+ I915_WRITE_FW(PLANE_AUX_DIST(pipe, plane), 0xFFFFF000);
+ I915_WRITE_FW(PLANE_AUX_OFFSET(pipe, plane), 0);
+ I915_WRITE_FW(PLANE_POS(pipe, plane), 0);
+ I915_WRITE_FW(PLANE_CTL(pipe, plane), ctl);
+ I915_WRITE_FW(PLANE_SURF(pipe, plane), surf);
+ POSTING_READ_FW(PLANE_SURF(pipe, plane));
+ spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
+ return ret;
+}
+
+#define GOP_FB_SIZE 0x800000 /* 8M FB size */
+int intel_vgpu_g2v_setup_gop(struct intel_vgpu *vgpu)
+{
+ int ret = 0;
+
+ if (vgpu->gm.gop_fb_pages)
+ goto Done;
+
+ ret = prepare_gop_fb(vgpu, GOP_FB_SIZE);
+ if (ret) {
+ gvt_dbg_dpy("gop prepared failed %d\n", ret);
+ goto Done;
+ }
+
+ ret = setup_gop_display(vgpu);
+ if (ret)
+ gvt_dbg_dpy("gop display setup failed %d\n", ret);
+Done:
+ return 0;
+}
diff --git a/drivers/gpu/drm/i915/gvt/display.h b/drivers/gpu/drm/i915/gvt/display.h
index e6d3912bc730..ab938ade4045 100644
--- a/drivers/gpu/drm/i915/gvt/display.h
+++ b/drivers/gpu/drm/i915/gvt/display.h
@@ -182,4 +182,5 @@ void intel_vgpu_clean_display(struct intel_vgpu *vgpu);
int pipe_is_enabled(struct intel_vgpu *vgpu, int pipe);
+int intel_vgpu_g2v_setup_gop(struct intel_vgpu *vgpu);
#endif
diff --git a/drivers/gpu/drm/i915/gvt/gtt.c b/drivers/gpu/drm/i915/gvt/gtt.c
index d8a05a69848b..53d1ac3bb834 100644
--- a/drivers/gpu/drm/i915/gvt/gtt.c
+++ b/drivers/gpu/drm/i915/gvt/gtt.c
@@ -2660,6 +2660,18 @@ static void intel_vgpu_destroy_ggtt_mm(struct intel_vgpu *vgpu)
vgpu->gtt.ggtt_mm = NULL;
}
+static void clean_gvt_gop(struct intel_vgpu *vgpu)
+{
+ int i;
+
+ for (i = 0; i < vgpu->gm.gop_fb_size; i++)
+ intel_gvt_hypervisor_map_gfn_to_mfn(vgpu,
+ (GOP_FB_BASE >> PAGE_SHIFT) + i,
+ page_to_pfn(vgpu->gm.gop_fb_pages[i]), 1, false);
+
+ release_pages(vgpu->gm.gop_fb_pages, vgpu->gm.gop_fb_size);
+ kfree(vgpu->gm.gop_fb_pages);
+}
/**
* intel_vgpu_clean_gtt - clean up per-vGPU graphics memory virulization
* @vgpu: a vGPU
@@ -2675,6 +2687,8 @@ void intel_vgpu_clean_gtt(struct intel_vgpu *vgpu)
intel_vgpu_destroy_all_ppgtt_mm(vgpu);
intel_vgpu_destroy_ggtt_mm(vgpu);
kfree(vgpu->cached_guest_entry);
+ if (vgpu->gm.gop_fb_pages)
+ clean_gvt_gop(vgpu);
release_scratch_page_tree(vgpu);
}
diff --git a/drivers/gpu/drm/i915/gvt/gvt.h b/drivers/gpu/drm/i915/gvt/gvt.h
index 7a12fc6636a1..bc44716f9792 100644
--- a/drivers/gpu/drm/i915/gvt/gvt.h
+++ b/drivers/gpu/drm/i915/gvt/gvt.h
@@ -89,6 +89,8 @@ struct intel_vgpu_gm {
struct sg_table *st;
struct drm_mm_node low_gm_node;
struct drm_mm_node high_gm_node;
+ struct page **gop_fb_pages;
+ u32 gop_fb_size;
};
#define INTEL_GVT_MAX_NUM_FENCES 32
@@ -128,6 +130,8 @@ struct intel_vgpu_irq {
INTEL_GVT_EVENT_MAX);
};
+#define GOP_FB_BASE 0xDF000000
+
struct intel_vgpu_opregion {
bool mapped;
void *va;
diff --git a/drivers/gpu/drm/i915/gvt/handlers.c b/drivers/gpu/drm/i915/gvt/handlers.c
index d0939209a52b..01865702b5fb 100644
--- a/drivers/gpu/drm/i915/gvt/handlers.c
+++ b/drivers/gpu/drm/i915/gvt/handlers.c
@@ -1289,6 +1289,8 @@ static int handle_g2v_notification(struct intel_vgpu *vgpu, int notification)
case VGT_G2V_EXECLIST_CONTEXT_DESTROY:
case 1: /* Remove this in guest driver. */
break;
+ case VGT_G2V_GOP_SETUP:
+ return intel_vgpu_g2v_setup_gop(vgpu);
default:
gvt_vgpu_err("Invalid PV notification %d\n", notification);
}
diff --git a/drivers/gpu/drm/i915/gvt/vgpu.c b/drivers/gpu/drm/i915/gvt/vgpu.c
index 08e99dd14344..ef18802e2cea 100644
--- a/drivers/gpu/drm/i915/gvt/vgpu.c
+++ b/drivers/gpu/drm/i915/gvt/vgpu.c
@@ -52,6 +52,7 @@ void populate_pvinfo_page(struct intel_vgpu *vgpu)
vgpu_vreg_t(vgpu, vgtif_reg(vgt_caps)) = VGT_CAPS_FULL_48BIT_PPGTT;
vgpu_vreg_t(vgpu, vgtif_reg(vgt_caps)) |= VGT_CAPS_HWSP_EMULATION;
vgpu_vreg_t(vgpu, vgtif_reg(vgt_caps)) |= VGT_CAPS_HUGE_GTT;
+ vgpu_vreg_t(vgpu, vgtif_reg(vgt_caps)) |= VGT_CAPS_GOP_SUPPORT;
vgpu_vreg_t(vgpu, vgtif_reg(avail_rs.mappable_gmadr.base)) =
vgpu_aperture_gmadr_base(vgpu);
diff --git a/drivers/gpu/drm/i915/i915_pvinfo.h b/drivers/gpu/drm/i915/i915_pvinfo.h
index fd26872f15b6..f8ae2f37c9fa 100644
--- a/drivers/gpu/drm/i915/i915_pvinfo.h
+++ b/drivers/gpu/drm/i915/i915_pvinfo.h
@@ -57,6 +57,7 @@ enum vgt_g2v_type {
VGT_G2V_PPGTT_L4_INSERT,
VGT_G2V_GGTT_INSERT,
VGT_G2V_GGTT_CLEAR,
+ VGT_G2V_GOP_SETUP,
VGT_G2V_MAX,
};
@@ -135,6 +136,7 @@ enum pvmmio_levels {
#define VGT_CAPS_FULL_48BIT_PPGTT BIT(2)
#define VGT_CAPS_HWSP_EMULATION BIT(3)
#define VGT_CAPS_HUGE_GTT BIT(4)
+#define VGT_CAPS_GOP_SUPPORT BIT(5)
#define PVMMIO_LEVEL(dev_priv, level) \
(intel_vgpu_active(dev_priv) && (i915_modparams.enable_pvmmio & level))
--
https://clearlinux.org