[PATCH v3 1/2] drm/i915/gvt: Alloc and Init guest opregion at vgpu creation
Tina Zhang
tina.zhang at intel.com
Mon Nov 20 07:31:15 UTC 2017
From: Xiong Zhang <xiong.y.zhang at intel.com>
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 at intel.com>
Tested-by: Tina Zhang <tina.zhang at intel.com>
---
drivers/gpu/drm/i915/gvt/cfg_space.c | 3 +-
drivers/gpu/drm/i915/gvt/gvt.h | 4 +-
drivers/gpu/drm/i915/gvt/opregion.c | 90 ++++++++++++++++--------------------
drivers/gpu/drm/i915/gvt/vgpu.c | 8 +++-
4 files changed, 53 insertions(+), 52 deletions(-)
diff --git a/drivers/gpu/drm/i915/gvt/cfg_space.c b/drivers/gpu/drm/i915/gvt/cfg_space.c
index 4ce2e6b..97bfc00 100644
--- a/drivers/gpu/drm/i915/gvt/cfg_space.c
+++ b/drivers/gpu/drm/i915/gvt/cfg_space.c
@@ -335,7 +335,8 @@ int intel_vgpu_emulate_cfg_write(struct intel_vgpu *vgpu, unsigned int offset,
case INTEL_GVT_PCI_OPREGION:
if (WARN_ON(!IS_ALIGNED(offset, 4)))
return -EINVAL;
- ret = intel_vgpu_init_opregion(vgpu, *(u32 *)p_data);
+ ret = intel_vgpu_opregion_base_write_handler(vgpu,
+ *(u32 *)p_data);
if (ret)
return ret;
diff --git a/drivers/gpu/drm/i915/gvt/gvt.h b/drivers/gpu/drm/i915/gvt/gvt.h
index 3930667..07d3ba0 100644
--- a/drivers/gpu/drm/i915/gvt/gvt.h
+++ b/drivers/gpu/drm/i915/gvt/gvt.h
@@ -123,6 +123,7 @@ struct intel_vgpu_irq {
};
struct intel_vgpu_opregion {
+ bool mapped;
void *va;
u32 gfn[INTEL_GVT_OPREGION_PAGES];
};
@@ -505,7 +506,8 @@ static inline u64 intel_vgpu_get_bar_gpa(struct intel_vgpu *vgpu, int bar)
}
void intel_vgpu_clean_opregion(struct intel_vgpu *vgpu);
-int intel_vgpu_init_opregion(struct intel_vgpu *vgpu, u32 gpa);
+int intel_vgpu_init_opregion(struct intel_vgpu *vgpu);
+int intel_vgpu_opregion_base_write_handler(struct intel_vgpu *vgpu, u32 gpa);
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 80720e5..1205b20 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;
@@ -250,25 +258,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;
@@ -290,59 +279,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; \
diff --git a/drivers/gpu/drm/i915/gvt/vgpu.c b/drivers/gpu/drm/i915/gvt/vgpu.c
index c6b82d1..2896aaf 100644
--- a/drivers/gpu/drm/i915/gvt/vgpu.c
+++ b/drivers/gpu/drm/i915/gvt/vgpu.c
@@ -370,10 +370,14 @@ static struct intel_vgpu *__intel_gvt_create_vgpu(struct intel_gvt *gvt,
if (ret)
goto out_detach_hypervisor_vgpu;
- ret = intel_vgpu_init_display(vgpu, param->resolution);
+ ret = intel_vgpu_init_opregion(vgpu);
if (ret)
goto out_clean_gtt;
+ ret = intel_vgpu_init_display(vgpu, param->resolution);
+ if (ret)
+ goto out_clean_opregion;
+
ret = intel_vgpu_setup_submission(vgpu);
if (ret)
goto out_clean_display;
@@ -396,6 +400,8 @@ static struct intel_vgpu *__intel_gvt_create_vgpu(struct intel_gvt *gvt,
intel_vgpu_clean_submission(vgpu);
out_clean_display:
intel_vgpu_clean_display(vgpu);
+out_clean_opregion:
+ intel_vgpu_clean_opregion(vgpu);
out_clean_gtt:
intel_vgpu_clean_gtt(vgpu);
out_detach_hypervisor_vgpu:
--
2.7.4
More information about the intel-gvt-dev
mailing list