From: Xiong Zhang Date: Mon, 20 Nov 2017 07:31:15 +0000 (+0800) Subject: drm/i915/gvt: Alloc and Init guest opregion at vgpu creation X-Git-Tag: v4.19~298^2~46^2~859^2~30 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=4dff110b15aea2f7653957a70921a7be1f45d59b;p=platform%2Fkernel%2Flinux-rpi.git 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 Tested-by: Tina Zhang Signed-off-by: Zhenyu Wang --- 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 bf8e5c4..36172f3 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; \ 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 @@ out_clean_submission: 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: