clear-pkgs-linux-iot-lts2018/1200-drm-i915-gvt-add-opreg...

188 lines
6.6 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: Wed, 13 Mar 2019 13:07:58 +0800
Subject: [PATCH] drm/i915/gvt: add opregion emulation for AcrnGT
Some OS failed to initialize display if there is no opregion detected.
So emulate opregion even if the host doesn't have a valid one. The faked
opregion has two sections, the information head and the vbt mailbox.
Both are populated with crafted values for display mode setting.
V4: remove wm register register access code
V3: revise commit message
V2: remove real opregion check code per Min's suggestion
Tracked-On: projectacrn/acrn-hypervisor#3106
Signed-off-by: Liu Xinyun <xinyun.liu@intel.com>
Reviewed-by: Zhao Yakui <yakui.zhao@intel.com>
---
drivers/gpu/drm/i915/gvt/acrngt.c | 28 ++++++++++++++++++++++++++++
drivers/gpu/drm/i915/gvt/cfg_space.c | 15 +++++++--------
drivers/gpu/drm/i915/gvt/gvt.h | 1 +
drivers/gpu/drm/i915/gvt/opregion.c | 23 +++++++++++++++++++++--
4 files changed, 57 insertions(+), 10 deletions(-)
diff --git a/drivers/gpu/drm/i915/gvt/acrngt.c b/drivers/gpu/drm/i915/gvt/acrngt.c
index defa892d8d52..80b4df4e16dd 100644
--- a/drivers/gpu/drm/i915/gvt/acrngt.c
+++ b/drivers/gpu/drm/i915/gvt/acrngt.c
@@ -985,6 +985,33 @@ static void acrngt_dma_unmap_guest_page(unsigned long handle,
{
}
+static int acrngt_set_opregion(void *p_vgpu)
+{
+ struct intel_vgpu *vgpu = (struct intel_vgpu *)p_vgpu;
+ void *base;
+ u32 asls;
+ int i;
+
+ gvt_dbg_dpy("acrngt set opregion\n");
+
+ base = vgpu_opregion(vgpu)->va;
+ if (!base)
+ return -ENOMEM;
+
+ /* hard code opregion to [0xDFFFD000, 0xE0000000]
+ * ToDo:
+ * 1. reserve the region in dm then use it in OVMF and kernel
+ * 2. pass the offset to acrngt through kernel parameter
+ */
+ asls = 0xDFFFD000;
+ *(u32 *)(vgpu_cfg_space(vgpu) + INTEL_GVT_PCI_OPREGION) = asls;
+
+ for (i = 0; i < INTEL_GVT_OPREGION_PAGES; i++)
+ vgpu_opregion(vgpu)->gfn[i] = (asls >> PAGE_SHIFT) + i;
+
+ return 0;
+}
+
struct intel_gvt_mpt acrn_gvt_mpt = {
//.detect_host = acrngt_detect_host,
.host_init = acrngt_host_init,
@@ -1004,6 +1031,7 @@ struct intel_gvt_mpt acrn_gvt_mpt = {
.set_trap_area = acrngt_set_trap_area,
.set_pvmmio = acrngt_set_pvmmio,
.dom0_ready = acrngt_dom0_ready,
+ .set_opregion = acrngt_set_opregion,
};
EXPORT_SYMBOL_GPL(acrn_gvt_mpt);
diff --git a/drivers/gpu/drm/i915/gvt/cfg_space.c b/drivers/gpu/drm/i915/gvt/cfg_space.c
index 71a815d81f2d..b59387d6235b 100644
--- a/drivers/gpu/drm/i915/gvt/cfg_space.c
+++ b/drivers/gpu/drm/i915/gvt/cfg_space.c
@@ -113,6 +113,13 @@ int intel_vgpu_emulate_cfg_read(struct intel_vgpu *vgpu, unsigned int offset,
if (WARN_ON(offset + bytes > vgpu->gvt->device_info.cfg_space_size))
return -EINVAL;
+ if (rounddown(offset, 4) == INTEL_GVT_PCI_OPREGION) {
+ if (!vgpu_opregion(vgpu)->mapped) {
+ gvt_dbg_dpy("set up virtual opregion mapping\n");
+ map_vgpu_opregion(vgpu, true);
+ }
+ }
+
memcpy(p_data, vgpu_cfg_space(vgpu) + offset, bytes);
return 0;
}
@@ -395,14 +402,6 @@ int intel_vgpu_emulate_cfg_write(struct intel_vgpu *vgpu, unsigned int offset,
if (WARN_ON(!IS_ALIGNED(offset, 4)))
return -EINVAL;
- /*
- * To support virtual display, we need to override the real VBT in the
- * OpRegion. So here we don't report OpRegion to guest.
- */
- if (IS_BROXTON(vgpu->gvt->dev_priv) ||
- IS_KABYLAKE(vgpu->gvt->dev_priv))
- return 0;
-
ret = intel_vgpu_opregion_base_write_handler(vgpu,
*(u32 *)p_data);
if (ret)
diff --git a/drivers/gpu/drm/i915/gvt/gvt.h b/drivers/gpu/drm/i915/gvt/gvt.h
index cf689150dbf7..5ee96126ab16 100644
--- a/drivers/gpu/drm/i915/gvt/gvt.h
+++ b/drivers/gpu/drm/i915/gvt/gvt.h
@@ -589,6 +589,7 @@ int map_gttmmio(struct intel_vgpu *vgpu, bool map);
void intel_vgpu_clean_opregion(struct intel_vgpu *vgpu);
int intel_vgpu_init_opregion(struct intel_vgpu *vgpu);
int intel_vgpu_opregion_base_write_handler(struct intel_vgpu *vgpu, u32 gpa);
+int map_vgpu_opregion(struct intel_vgpu *vgpu, bool map);
int intel_vgpu_emulate_opregion_request(struct intel_vgpu *vgpu, u32 swsci);
void populate_pvinfo_page(struct intel_vgpu *vgpu);
diff --git a/drivers/gpu/drm/i915/gvt/opregion.c b/drivers/gpu/drm/i915/gvt/opregion.c
index b0d3a43ccd03..3e676bf20248 100644
--- a/drivers/gpu/drm/i915/gvt/opregion.c
+++ b/drivers/gpu/drm/i915/gvt/opregion.c
@@ -257,7 +257,7 @@ int intel_vgpu_init_opregion(struct intel_vgpu *vgpu)
return 0;
}
-static int map_vgpu_opregion(struct intel_vgpu *vgpu, bool map)
+int map_vgpu_opregion(struct intel_vgpu *vgpu, bool map)
{
u64 mfn;
int i, ret;
@@ -269,6 +269,10 @@ static int map_vgpu_opregion(struct intel_vgpu *vgpu, bool map)
gvt_vgpu_err("fail to get MFN from VA\n");
return -EINVAL;
}
+
+ gvt_dbg_dpy("Round[%d] gfn: %x ==> mfn: %llx\n", i,
+ vgpu_opregion(vgpu)->gfn[i], mfn);
+
ret = intel_gvt_hypervisor_map_gfn_to_mfn(vgpu,
vgpu_opregion(vgpu)->gfn[i],
mfn, 1, map);
@@ -316,6 +320,18 @@ int intel_vgpu_opregion_base_write_handler(struct intel_vgpu *vgpu, u32 gpa)
for (i = 0; i < INTEL_GVT_OPREGION_PAGES; i++)
vgpu_opregion(vgpu)->gfn[i] = (gpa >> PAGE_SHIFT) + i;
+ ret = map_vgpu_opregion(vgpu, true);
+ break;
+ case INTEL_GVT_HYPERVISOR_ACRN:
+ if (gpa == 0)
+ return 0;
+
+ if (vgpu_opregion(vgpu)->mapped)
+ map_vgpu_opregion(vgpu, false);
+
+ for (i = 0; i < INTEL_GVT_OPREGION_PAGES; i++)
+ vgpu_opregion(vgpu)->gfn[i] = (gpa >> PAGE_SHIFT) + i;
+
ret = map_vgpu_opregion(vgpu, true);
break;
default:
@@ -338,7 +354,8 @@ void intel_vgpu_clean_opregion(struct intel_vgpu *vgpu)
if (!vgpu_opregion(vgpu)->va)
return;
- if (intel_gvt_host.hypervisor_type == INTEL_GVT_HYPERVISOR_XEN) {
+ if (intel_gvt_host.hypervisor_type == INTEL_GVT_HYPERVISOR_XEN ||
+ intel_gvt_host.hypervisor_type == INTEL_GVT_HYPERVISOR_ACRN) {
if (vgpu_opregion(vgpu)->mapped)
map_vgpu_opregion(vgpu, false);
} else if (intel_gvt_host.hypervisor_type == INTEL_GVT_HYPERVISOR_KVM) {
@@ -474,6 +491,7 @@ int intel_vgpu_emulate_opregion_request(struct intel_vgpu *vgpu, u32 swsci)
switch (intel_gvt_host.hypervisor_type) {
case INTEL_GVT_HYPERVISOR_XEN:
+ case INTEL_GVT_HYPERVISOR_ACRN:
scic = *((u32 *)vgpu_opregion(vgpu)->va +
INTEL_GVT_OPREGION_SCIC);
parm = *((u32 *)vgpu_opregion(vgpu)->va +
@@ -539,6 +557,7 @@ int intel_vgpu_emulate_opregion_request(struct intel_vgpu *vgpu, u32 swsci)
out:
switch (intel_gvt_host.hypervisor_type) {
case INTEL_GVT_HYPERVISOR_XEN:
+ case INTEL_GVT_HYPERVISOR_ACRN:
*((u32 *)vgpu_opregion(vgpu)->va +
INTEL_GVT_OPREGION_SCIC) = scic;
*((u32 *)vgpu_opregion(vgpu)->va +
--
https://clearlinux.org