[PATCH v2] drm/i915/gvt: Use KVM r/w to access guest opregion

Zhang, Tina tina.zhang at intel.com
Fri Jan 26 08:23:50 UTC 2018


This patch is partial tested, as VFIO doesn't need emulated GVT_PCI_SWSCI currently.
This patch needs to be tested with XenGT.
Thanks.


BR,
Tina

> -----Original Message-----
> From: Zhang, Tina
> Sent: Friday, January 26, 2018 4:10 PM
> To: zhenyuw at linux.intel.com
> Cc: Zhang, Tina <tina.zhang at intel.com>; intel-gvt-dev at lists.freedesktop.org;
> Zhao, Yan Y <yan.y.zhao at intel.com>; Zhang, Xiong Y
> <xiong.y.zhang at intel.com>
> Subject: [PATCH v2] drm/i915/gvt: Use KVM r/w to access guest opregion
> 
> For KVMGT, the guest opregion, which is handled by VFIO, is actually a piece of
> guest memory which won't be accessed by devices. So, its mfn shouldn't be
> obtained through VFIO interface. This patch uses KVM r/w interface to access
> the data in guest opregion.
> 
> Fix the guest opregion accessing issue when host "intel_iommu=on".
> 
> v2:
> - Set the gpa correctly when invoking KVM r/w operations. (Zhenyu)
> 
> Signed-off-by: Tina Zhang <tina.zhang at intel.com>
> Cc: Yan Zhao <yan.y.zhao at intel.com>
> Cc: Xiong Zhang <xiong.y.zhang at intel.com>
> ---
>  drivers/gpu/drm/i915/gvt/gvt.h      |  1 -
>  drivers/gpu/drm/i915/gvt/opregion.c | 97 ++++++++++++++++++++++++++---
> --------
>  2 files changed, 70 insertions(+), 28 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/gvt/gvt.h b/drivers/gpu/drm/i915/gvt/gvt.h
> index 7dc7a80..205d88d 100644
> --- a/drivers/gpu/drm/i915/gvt/gvt.h
> +++ b/drivers/gpu/drm/i915/gvt/gvt.h
> @@ -127,7 +127,6 @@ struct intel_vgpu_irq {  struct intel_vgpu_opregion {
>  	bool mapped;
>  	void *va;
> -	void *va_gopregion;
>  	u32 gfn[INTEL_GVT_OPREGION_PAGES];
>  };
> 
> diff --git a/drivers/gpu/drm/i915/gvt/opregion.c
> b/drivers/gpu/drm/i915/gvt/opregion.c
> index 8420d1f..1e6972b 100644
> --- a/drivers/gpu/drm/i915/gvt/opregion.c
> +++ b/drivers/gpu/drm/i915/gvt/opregion.c
> @@ -299,20 +299,13 @@ int intel_vgpu_opregion_base_write_handler(struct
> intel_vgpu *vgpu, u32 gpa)  {
> 
>  	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;
> -		}
> +		for (i = 0; i < INTEL_GVT_OPREGION_PAGES; i++)
> +			vgpu_opregion(vgpu)->gfn[i] = (gpa >> PAGE_SHIFT) +
> i;
>  		vgpu_opregion(vgpu)->mapped = true;
>  		break;
>  	case INTEL_GVT_HYPERVISOR_XEN:
> @@ -352,10 +345,7 @@ void intel_vgpu_clean_opregion(struct intel_vgpu
> *vgpu)
>  		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;
> -		}
> +		/* Guest opregion is released by VFIO */
>  	}
>  	free_pages((unsigned long)vgpu_opregion(vgpu)->va,
>  		   get_order(INTEL_GVT_OPREGION_SIZE));
> @@ -480,19 +470,40 @@ static bool querying_capabilities(u32 scic)
>   */
>  int intel_vgpu_emulate_opregion_request(struct intel_vgpu *vgpu, u32 swsci)
> {
> -	u32 *scic, *parm;
> +	u32 scic, parm;
>  	u32 func, subfunc;
> +	u64 scic_pa = 0, parm_pa = 0;
> +	int ret;
> 
>  	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;
> +		scic = *((u32 *)vgpu_opregion(vgpu)->va +
> +					INTEL_GVT_OPREGION_SCIC);
> +		parm = *((u32 *)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;
> +		scic_pa = (vgpu_opregion(vgpu)->gfn[0] << PAGE_SHIFT) +
> +					INTEL_GVT_OPREGION_SCIC;
> +		parm_pa = (vgpu_opregion(vgpu)->gfn[0] << PAGE_SHIFT) +
> +					INTEL_GVT_OPREGION_PARM;
> +
> +		ret = intel_gvt_hypervisor_read_gpa(vgpu, scic_pa,
> +						    &scic, sizeof(scic));
> +		if (ret) {
> +			gvt_vgpu_err("guest opregion read error %d, gpa
> 0x%llx, len %lu\n",
> +				ret, scic_pa, sizeof(scic));
> +			return ret;
> +		}
> +
> +		ret = intel_gvt_hypervisor_read_gpa(vgpu, parm_pa,
> +						    &parm, sizeof(parm));
> +		if (ret) {
> +			gvt_vgpu_err("guest opregion read error %d, gpa
> 0x%llx, len %lu\n",
> +				ret, scic_pa, sizeof(scic));
> +			return ret;
> +		}
> +
>  		break;
>  	default:
>  		gvt_vgpu_err("not supported hypervisor\n"); @@ -510,9
> +521,9 @@ int intel_vgpu_emulate_opregion_request(struct intel_vgpu *vgpu,
> u32 swsci)
>  		return 0;
>  	}
> 
> -	func = GVT_OPREGION_FUNC(*scic);
> -	subfunc = GVT_OPREGION_SUBFUNC(*scic);
> -	if (!querying_capabilities(*scic)) {
> +	func = GVT_OPREGION_FUNC(scic);
> +	subfunc = GVT_OPREGION_SUBFUNC(scic);
> +	if (!querying_capabilities(scic)) {
>  		gvt_vgpu_err("requesting runtime service: func \"%s\","
>  				" subfunc \"%s\"\n",
>  				opregion_func_name(func),
> @@ -521,11 +532,43 @@ int intel_vgpu_emulate_opregion_request(struct
> intel_vgpu *vgpu, u32 swsci)
>  		 * emulate exit status of function call, '0' means
>  		 * "failure, generic, unsupported or unknown cause"
>  		 */
> -		*scic &= ~OPREGION_SCIC_EXIT_MASK;
> -		return 0;
> +		scic &= ~OPREGION_SCIC_EXIT_MASK;
> +		goto out;
> +	}
> +
> +	scic = 0;
> +	parm = 0;
> +
> +out:
> +	switch (intel_gvt_host.hypervisor_type) {
> +	case INTEL_GVT_HYPERVISOR_XEN:
> +		*((u32 *)vgpu_opregion(vgpu)->va +
> +					INTEL_GVT_OPREGION_SCIC) = scic;
> +		*((u32 *)vgpu_opregion(vgpu)->va +
> +					INTEL_GVT_OPREGION_PARM) =
> parm;
> +		break;
> +	case INTEL_GVT_HYPERVISOR_KVM:
> +		ret = intel_gvt_hypervisor_write_gpa(vgpu, scic_pa,
> +						    &scic, sizeof(scic));
> +		if (ret) {
> +			gvt_vgpu_err("guest opregion write error %d, gpa
> 0x%llx, len %lu\n",
> +				ret, scic_pa, sizeof(scic));
> +			return ret;
> +		}
> +
> +		ret = intel_gvt_hypervisor_write_gpa(vgpu, parm_pa,
> +						    &parm, sizeof(parm));
> +		if (ret) {
> +			gvt_vgpu_err("guest opregion write error %d, gpa
> 0x%llx, len %lu\n",
> +				ret, scic_pa, sizeof(scic));
> +			return ret;
> +		}
> +
> +		break;
> +	default:
> +		gvt_vgpu_err("not supported hypervisor\n");
> +		return -EINVAL;
>  	}
> 
> -	*scic = 0;
> -	*parm = 0;
>  	return 0;
>  }
> --
> 2.7.4



More information about the intel-gvt-dev mailing list