summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/i915/gvt/opregion.c
diff options
context:
space:
mode:
authorTina Zhang <tina.zhang@intel.com>2017-11-20 15:31:16 +0800
committerZhenyu Wang <zhenyuw@linux.intel.com>2017-12-04 11:24:32 +0800
commitb851adeac0858c7d257b32eee2142b1519d45ccf (patch)
tree534a3da8e352b407a386b541841fede93e8ca0d0 /drivers/gpu/drm/i915/gvt/opregion.c
parent4dff110b15aea2f7653957a70921a7be1f45d59b (diff)
downloadlinux-b851adeac0858c7d257b32eee2142b1519d45ccf.tar.bz2
drm/i915/gvt: Add opregion support
Windows guest driver needs vbt in opregion, to configure the setting for display. Without opregion support, the display registers won't be set and this blocks display model to get the correct information of the guest display plane. This patch is to provide a virtual opregion for guest. The original author of this patch is Xiaoguang Chen. This patch is split from the "Dma-buf support for GVT-g" patch set, with being rebased to the latest gvt-staging branch. v3: - add checking region index during intel_vgpu_rw. (Xiong) v2: - refine intel_vgpu_reg_release_opregion. (Xiong) Here are the previous version comments: v18: - unmap vgpu's opregion when destroying vgpu. v16: - rebase to 4.14.0-rc6. Signed-off-by: Bing Niu <bing.niu@intel.com> Signed-off-by: Tina Zhang <tina.zhang@intel.com> Tested-by: Xiong Zhang <xiong.y.zhang@intel.com> Cc: Zhenyu Wang <zhenyuw@linux.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.c74
1 files changed, 58 insertions, 16 deletions
diff --git a/drivers/gpu/drm/i915/gvt/opregion.c b/drivers/gpu/drm/i915/gvt/opregion.c
index 36172f33bd51..8420d1fc3ddb 100644
--- a/drivers/gpu/drm/i915/gvt/opregion.c
+++ b/drivers/gpu/drm/i915/gvt/opregion.c
@@ -297,19 +297,41 @@ static int map_vgpu_opregion(struct intel_vgpu *vgpu, bool map)
*/
int intel_vgpu_opregion_base_write_handler(struct intel_vgpu *vgpu, u32 gpa)
{
- int i, ret;
- /**
- * 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);
+ int i, ret = 0;
+ unsigned long pfn;
+
+ gvt_dbg_core("emulate opregion from kernel\n");
+
+ switch (intel_gvt_host.hypervisor_type) {
+ case INTEL_GVT_HYPERVISOR_KVM:
+ pfn = intel_gvt_hypervisor_gfn_to_mfn(vgpu, gpa >> PAGE_SHIFT);
+ vgpu_opregion(vgpu)->va_gopregion = memremap(pfn << PAGE_SHIFT,
+ INTEL_GVT_OPREGION_SIZE,
+ MEMREMAP_WB);
+ if (!vgpu_opregion(vgpu)->va_gopregion) {
+ gvt_vgpu_err("failed to map guest opregion\n");
+ ret = -EFAULT;
+ }
+ vgpu_opregion(vgpu)->mapped = true;
+ break;
+ case 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);
- for (i = 0; i < INTEL_GVT_OPREGION_PAGES; i++)
- vgpu_opregion(vgpu)->gfn[i] = (gpa >> PAGE_SHIFT) + i;
+ for (i = 0; i < INTEL_GVT_OPREGION_PAGES; i++)
+ vgpu_opregion(vgpu)->gfn[i] = (gpa >> PAGE_SHIFT) + i;
- ret = map_vgpu_opregion(vgpu, true);
+ ret = map_vgpu_opregion(vgpu, true);
+ break;
+ default:
+ ret = -EINVAL;
+ gvt_vgpu_err("not supported hypervisor\n");
+ }
return ret;
}
@@ -326,13 +348,20 @@ void intel_vgpu_clean_opregion(struct intel_vgpu *vgpu)
if (!vgpu_opregion(vgpu)->va)
return;
- if (vgpu_opregion(vgpu)->mapped)
- map_vgpu_opregion(vgpu, false);
-
+ if (intel_gvt_host.hypervisor_type == INTEL_GVT_HYPERVISOR_XEN) {
+ if (vgpu_opregion(vgpu)->mapped)
+ map_vgpu_opregion(vgpu, false);
+ } else if (intel_gvt_host.hypervisor_type == INTEL_GVT_HYPERVISOR_KVM) {
+ if (vgpu_opregion(vgpu)->mapped) {
+ memunmap(vgpu_opregion(vgpu)->va_gopregion);
+ vgpu_opregion(vgpu)->va_gopregion = NULL;
+ }
+ }
free_pages((unsigned long)vgpu_opregion(vgpu)->va,
- get_order(INTEL_GVT_OPREGION_SIZE));
+ get_order(INTEL_GVT_OPREGION_SIZE));
vgpu_opregion(vgpu)->va = NULL;
+
}
@@ -454,8 +483,21 @@ int intel_vgpu_emulate_opregion_request(struct intel_vgpu *vgpu, u32 swsci)
u32 *scic, *parm;
u32 func, subfunc;
- scic = vgpu_opregion(vgpu)->va + INTEL_GVT_OPREGION_SCIC;
- parm = vgpu_opregion(vgpu)->va + INTEL_GVT_OPREGION_PARM;
+ switch (intel_gvt_host.hypervisor_type) {
+ case INTEL_GVT_HYPERVISOR_XEN:
+ scic = vgpu_opregion(vgpu)->va + INTEL_GVT_OPREGION_SCIC;
+ parm = vgpu_opregion(vgpu)->va + INTEL_GVT_OPREGION_PARM;
+ break;
+ case INTEL_GVT_HYPERVISOR_KVM:
+ scic = vgpu_opregion(vgpu)->va_gopregion +
+ INTEL_GVT_OPREGION_SCIC;
+ parm = vgpu_opregion(vgpu)->va_gopregion +
+ INTEL_GVT_OPREGION_PARM;
+ break;
+ default:
+ gvt_vgpu_err("not supported hypervisor\n");
+ return -EINVAL;
+ }
if (!(swsci & SWSCI_SCI_SELECT)) {
gvt_vgpu_err("requesting SMI service\n");