summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/i915/gvt/opregion.c
diff options
context:
space:
mode:
authorXiong Zhang2017-11-20 08:31:15 +0100
committerZhenyu Wang2017-12-04 04:24:32 +0100
commit4dff110b15aea2f7653957a70921a7be1f45d59b (patch)
treec2cc5634066a2e16c4fc61e53b189c48a3bcccfb /drivers/gpu/drm/i915/gvt/opregion.c
parentdrm/i915/gvt: Fix out-of-bounds buffer write into opregion->signature[] (diff)
downloadkernel-qcow2-linux-4dff110b15aea2f7653957a70921a7be1f45d59b.tar.gz
kernel-qcow2-linux-4dff110b15aea2f7653957a70921a7be1f45d59b.tar.xz
kernel-qcow2-linux-4dff110b15aea2f7653957a70921a7be1f45d59b.zip
drm/i915/gvt: Alloc and Init guest opregion at vgpu creation
Currently guest opregion is allocated and initialised when guest write opregion base register. This is too late for kvmgt, so move it to vgpu_create time. Signed-off-by: Xiong Zhang <xiong.y.zhang@intel.com> Tested-by: Tina Zhang <tina.zhang@intel.com> Signed-off-by: Zhenyu Wang <zhenyuw@linux.intel.com>
Diffstat (limited to 'drivers/gpu/drm/i915/gvt/opregion.c')
-rw-r--r--drivers/gpu/drm/i915/gvt/opregion.c90
1 files changed, 41 insertions, 49 deletions
diff --git a/drivers/gpu/drm/i915/gvt/opregion.c b/drivers/gpu/drm/i915/gvt/opregion.c
index bf8e5c49a64a..36172f33bd51 100644
--- a/drivers/gpu/drm/i915/gvt/opregion.c
+++ b/drivers/gpu/drm/i915/gvt/opregion.c
@@ -213,7 +213,15 @@ static void virt_vbt_generation(struct vbt *v)
v->driver_features.lvds_config = BDB_DRIVER_FEATURE_NO_LVDS;
}
-static int alloc_and_init_virt_opregion(struct intel_vgpu *vgpu)
+/**
+ * intel_vgpu_init_opregion - initialize the stuff used to emulate opregion
+ * @vgpu: a vGPU
+ * @gpa: guest physical address of opregion
+ *
+ * Returns:
+ * Zero on success, negative error code if failed.
+ */
+int intel_vgpu_init_opregion(struct intel_vgpu *vgpu)
{
u8 *buf;
struct opregion_header *header;
@@ -251,25 +259,6 @@ static int alloc_and_init_virt_opregion(struct intel_vgpu *vgpu)
return 0;
}
-static int init_vgpu_opregion(struct intel_vgpu *vgpu, u32 gpa)
-{
- int i, ret;
-
- if (WARN((vgpu_opregion(vgpu)->va),
- "vgpu%d: opregion has been initialized already.\n",
- vgpu->id))
- return -EINVAL;
-
- ret = alloc_and_init_virt_opregion(vgpu);
- if (ret < 0)
- return ret;
-
- for (i = 0; i < INTEL_GVT_OPREGION_PAGES; i++)
- vgpu_opregion(vgpu)->gfn[i] = (gpa >> PAGE_SHIFT) + i;
-
- return 0;
-}
-
static int map_vgpu_opregion(struct intel_vgpu *vgpu, bool map)
{
u64 mfn;
@@ -291,59 +280,62 @@ static int map_vgpu_opregion(struct intel_vgpu *vgpu, bool map)
return ret;
}
}
+
+ vgpu_opregion(vgpu)->mapped = map;
+
return 0;
}
/**
- * intel_vgpu_clean_opregion - clean the stuff used to emulate opregion
+ * intel_vgpu_opregion_base_write_handler - Opregion base register write handler
+ *
* @vgpu: a vGPU
+ * @gpa: guest physical address of opregion
*
+ * Returns:
+ * Zero on success, negative error code if failed.
*/
-void intel_vgpu_clean_opregion(struct intel_vgpu *vgpu)
+int intel_vgpu_opregion_base_write_handler(struct intel_vgpu *vgpu, u32 gpa)
{
- gvt_dbg_core("vgpu%d: clean vgpu opregion\n", vgpu->id);
-
- if (!vgpu_opregion(vgpu)->va)
- return;
+ int i, ret;
- if (intel_gvt_host.hypervisor_type == INTEL_GVT_HYPERVISOR_XEN) {
+ /**
+ * Wins guest on Xengt will write this register twice: xen hvmloader and
+ * windows graphic driver.
+ */
+ if (vgpu_opregion(vgpu)->mapped)
map_vgpu_opregion(vgpu, false);
- free_pages((unsigned long)vgpu_opregion(vgpu)->va,
- get_order(INTEL_GVT_OPREGION_SIZE));
- vgpu_opregion(vgpu)->va = NULL;
- }
+ for (i = 0; i < INTEL_GVT_OPREGION_PAGES; i++)
+ vgpu_opregion(vgpu)->gfn[i] = (gpa >> PAGE_SHIFT) + i;
+
+ ret = map_vgpu_opregion(vgpu, true);
+
+ return ret;
}
/**
- * intel_vgpu_init_opregion - initialize the stuff used to emulate opregion
+ * intel_vgpu_clean_opregion - clean the stuff used to emulate opregion
* @vgpu: a vGPU
- * @gpa: guest physical address of opregion
*
- * Returns:
- * Zero on success, negative error code if failed.
*/
-int intel_vgpu_init_opregion(struct intel_vgpu *vgpu, u32 gpa)
+void intel_vgpu_clean_opregion(struct intel_vgpu *vgpu)
{
- int ret;
-
- gvt_dbg_core("vgpu%d: init vgpu opregion\n", vgpu->id);
+ gvt_dbg_core("vgpu%d: clean vgpu opregion\n", vgpu->id);
- if (intel_gvt_host.hypervisor_type == INTEL_GVT_HYPERVISOR_XEN) {
- gvt_dbg_core("emulate opregion from kernel\n");
+ if (!vgpu_opregion(vgpu)->va)
+ return;
- ret = init_vgpu_opregion(vgpu, gpa);
- if (ret)
- return ret;
+ if (vgpu_opregion(vgpu)->mapped)
+ map_vgpu_opregion(vgpu, false);
- ret = map_vgpu_opregion(vgpu, true);
- if (ret)
- return ret;
- }
+ free_pages((unsigned long)vgpu_opregion(vgpu)->va,
+ get_order(INTEL_GVT_OPREGION_SIZE));
- return 0;
+ vgpu_opregion(vgpu)->va = NULL;
}
+
#define GVT_OPREGION_FUNC(scic) \
({ \
u32 __ret; \