[PATCH] i915/gvt: Stop tracking the pages of page table when failing to do shadow.

Zhenyu Wang zhenyuw at linux.intel.com
Fri Dec 17 02:47:39 UTC 2021


On 2021.12.16 15:29:00 -0500, Zhi Wang wrote:
> The PPGTT page table inside a VM will be tracked when created. When a
> tracked page is modified, GVT-g will update the shadow page table
> accordingly.
> 
> Sometimes, the guest will free a page belongs to a PPGTT page table, but
> doesn't unbind the page from its upper level. So the page is still

That's bad, right? Is there real case the guest driver might do this?

> tracked. Later that page might be allocated to other clients, which causes
> a flood of garbage traps. As the page has been used for other purpose,
> doing the shadow on this page will always fail, which causes the error
> "guest page write error".
> 
> The patch will identify this case by counting the times of failure of
> doing shadow on a tracked page. If the times of failure is larger than
> 3, GVT-g will stop tracking the page and release the sub level of the
> shadow pages accordingly.
> 
> Signed-off-by: Zhi Wang <zhi.a.wang at intel.com>
> ---
>  drivers/gpu/drm/i915/gvt/gtt.c | 62 ++++++++++++++++++++++------------
>  drivers/gpu/drm/i915/gvt/gtt.h |  1 +
>  2 files changed, 41 insertions(+), 22 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/gvt/gtt.c b/drivers/gpu/drm/i915/gvt/gtt.c
> index d7054bfb3e7d..fbfa5b8f1544 100644
> --- a/drivers/gpu/drm/i915/gvt/gtt.c
> +++ b/drivers/gpu/drm/i915/gvt/gtt.c
> @@ -778,6 +778,21 @@ static void ppgtt_free_all_spt(struct intel_vgpu *vgpu)
>  		ppgtt_free_spt(spt);
>  }
>  
> +static int ppgtt_invalidate_spt(struct intel_vgpu_ppgtt_spt *spt, bool force);
> +
> +static void ppgtt_handle_invalid_spt(struct intel_vgpu_ppgtt_spt *spt)
> +{
> +	if (spt->fail_cnt > 3) {
> +		ppgtt_invalidate_spt(spt, true);
> +	} else
> +		spt->fail_cnt++;
> +}
> +
> +static void ppgtt_set_spt_valid(struct intel_vgpu_ppgtt_spt *spt)
> +{
> +	spt->fail_cnt = 0;
> +}
> +
>  static int ppgtt_handle_guest_write_page_table_bytes(
>  		struct intel_vgpu_ppgtt_spt *spt,
>  		u64 pa, void *p_data, int bytes);
> @@ -791,12 +806,18 @@ static int ppgtt_write_protection_handler(
>  	int ret;
>  
>  	if (bytes != 4 && bytes != 8)
> -		return -EINVAL;
> +		goto invalid_spt;
>  
>  	ret = ppgtt_handle_guest_write_page_table_bytes(spt, gpa, data, bytes);
>  	if (ret)
> -		return ret;
> -	return ret;
> +		goto invalid_spt;
> +
> +	ppgtt_set_spt_valid(spt);
> +	return 0;
> +
> +invalid_spt:
> +	ppgtt_handle_invalid_spt(spt);
> +	return 0;
>  }
>  
>  /* Find a spt by guest gfn. */
> @@ -941,10 +962,8 @@ static inline int ppgtt_put_spt(struct intel_vgpu_ppgtt_spt *spt)
>  	return atomic_dec_return(&spt->refcount);
>  }
>  
> -static int ppgtt_invalidate_spt(struct intel_vgpu_ppgtt_spt *spt);
> -
>  static int ppgtt_invalidate_spt_by_shadow_entry(struct intel_vgpu *vgpu,
> -		struct intel_gvt_gtt_entry *e)
> +		struct intel_gvt_gtt_entry *e, bool force)
>  {
>  	struct drm_i915_private *i915 = vgpu->gvt->gt->i915;
>  	const struct intel_gvt_gtt_pte_ops *ops = vgpu->gvt->gtt.pte_ops;
> @@ -973,11 +992,11 @@ static int ppgtt_invalidate_spt_by_shadow_entry(struct intel_vgpu *vgpu,
>  	}
>  	s = intel_vgpu_find_spt_by_mfn(vgpu, ops->get_pfn(e));
>  	if (!s) {
> -		gvt_vgpu_err("fail to find shadow page: mfn: 0x%lx\n",
> +		gvt_dbg_mm("fail to find shadow page: mfn: 0x%lx\n",
>  				ops->get_pfn(e));
> -		return -ENXIO;
> +		return 0;
>  	}
> -	return ppgtt_invalidate_spt(s);
> +	return ppgtt_invalidate_spt(s, force);
>  }
>  
>  static inline void ppgtt_invalidate_pte(struct intel_vgpu_ppgtt_spt *spt,
> @@ -998,9 +1017,8 @@ static inline void ppgtt_invalidate_pte(struct intel_vgpu_ppgtt_spt *spt,
>  	intel_gvt_hypervisor_dma_unmap_guest_page(vgpu, pfn << PAGE_SHIFT);
>  }
>  
> -static int ppgtt_invalidate_spt(struct intel_vgpu_ppgtt_spt *spt)
> +static int ppgtt_invalidate_spt(struct intel_vgpu_ppgtt_spt *spt, bool force)
>  {
> -	struct intel_vgpu *vgpu = spt->vgpu;
>  	struct intel_gvt_gtt_entry e;
>  	unsigned long index;
>  	int ret;
> @@ -1008,7 +1026,7 @@ static int ppgtt_invalidate_spt(struct intel_vgpu_ppgtt_spt *spt)
>  	trace_spt_change(spt->vgpu->id, "die", spt,
>  			spt->guest_page.gfn, spt->shadow_page.type);
>  
> -	if (ppgtt_put_spt(spt) > 0)
> +	if (!force && ppgtt_put_spt(spt) > 0)
>  		return 0;
>  
>  	for_each_present_shadow_entry(spt, &e, index) {
> @@ -1032,7 +1050,7 @@ static int ppgtt_invalidate_spt(struct intel_vgpu_ppgtt_spt *spt)
>  		case GTT_TYPE_PPGTT_PDE_ENTRY:
>  			gvt_vdbg_mm("invalidate PMUL4/PDP/PDE entry\n");
>  			ret = ppgtt_invalidate_spt_by_shadow_entry(
> -					spt->vgpu, &e);
> +					spt->vgpu, &e, force);
>  			if (ret)
>  				goto fail;
>  			break;
> @@ -1046,7 +1064,7 @@ static int ppgtt_invalidate_spt(struct intel_vgpu_ppgtt_spt *spt)
>  	ppgtt_free_spt(spt);
>  	return 0;
>  fail:
> -	gvt_vgpu_err("fail: shadow page %p shadow entry 0x%llx type %d\n",
> +	gvt_dbg_mm("fail: shadow page %p shadow entry 0x%llx type %d\n",
>  			spt, e.val64, e.type);
>  	return ret;
>  }
> @@ -1196,7 +1214,7 @@ static int split_2MB_gtt_entry(struct intel_vgpu *vgpu,
>  		ret = intel_gvt_hypervisor_dma_map_guest_page(vgpu,
>  				start_gfn + sub_index, PAGE_SIZE, &dma_addr);
>  		if (ret) {
> -			ppgtt_invalidate_spt(spt);
> +			ppgtt_invalidate_spt(spt, false);
>  			return ret;
>  		}
>  		sub_se.val64 = se->val64;
> @@ -1371,11 +1389,11 @@ static int ppgtt_handle_guest_entry_removal(struct intel_vgpu_ppgtt_spt *spt,
>  		struct intel_vgpu_ppgtt_spt *s =
>  			intel_vgpu_find_spt_by_mfn(vgpu, ops->get_pfn(se));
>  		if (!s) {
> -			gvt_vgpu_err("fail to find guest page\n");
> -			ret = -ENXIO;
> +			gvt_dbg_mm("fail to find guest page\n");
> +			ret = 0;
>  			goto fail;
>  		}
> -		ret = ppgtt_invalidate_spt(s);
> +		ret = ppgtt_invalidate_spt(s, false);
>  		if (ret)
>  			goto fail;
>  	} else {
> @@ -1387,7 +1405,7 @@ static int ppgtt_handle_guest_entry_removal(struct intel_vgpu_ppgtt_spt *spt,
>  
>  	return 0;
>  fail:
> -	gvt_vgpu_err("fail: shadow page %p guest entry 0x%llx type %d\n",
> +	gvt_dbg_mm("fail: shadow page %p guest entry 0x%llx type %d\n",
>  			spt, se->val64, se->type);
>  	return ret;
>  }
> @@ -1422,7 +1440,7 @@ static int ppgtt_handle_guest_entry_add(struct intel_vgpu_ppgtt_spt *spt,
>  	}
>  	return 0;
>  fail:
> -	gvt_vgpu_err("fail: spt %p guest entry 0x%llx type %d\n",
> +	gvt_dbg_mm("fail: spt %p guest entry 0x%llx type %d\n",
>  		spt, we->val64, we->type);
>  	return ret;
>  }
> @@ -1653,7 +1671,7 @@ static int ppgtt_handle_guest_write_page_table(
>  
>  	return 0;
>  fail:
> -	gvt_vgpu_err("fail: shadow page %p guest entry 0x%llx type %d.\n",
> +	gvt_dbg_mm("fail: shadow page %p guest entry 0x%llx type %d.\n",
>  			spt, we->val64, we->type);
>  	return ret;
>  }
> @@ -1798,7 +1816,7 @@ static void invalidate_ppgtt_mm(struct intel_vgpu_mm *mm)
>  		if (!ops->test_present(&se))
>  			continue;
>  
> -		ppgtt_invalidate_spt_by_shadow_entry(vgpu, &se);
> +		ppgtt_invalidate_spt_by_shadow_entry(vgpu, &se, false);
>  		se.val64 = 0;
>  		ppgtt_set_shadow_root_entry(mm, &se, index);
>  
> diff --git a/drivers/gpu/drm/i915/gvt/gtt.h b/drivers/gpu/drm/i915/gvt/gtt.h
> index a3b0f59ec8bd..8b02ff5d9651 100644
> --- a/drivers/gpu/drm/i915/gvt/gtt.h
> +++ b/drivers/gpu/drm/i915/gvt/gtt.h
> @@ -263,6 +263,7 @@ struct intel_vgpu_ppgtt_spt {
>  	} guest_page;
>  
>  	DECLARE_BITMAP(post_shadow_bitmap, GTT_ENTRY_NUM_IN_ONE_PAGE);
> +	unsigned long fail_cnt;
>  	struct list_head post_shadow_list;
>  };
>  
> -- 
> 2.17.1
> 
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 195 bytes
Desc: not available
URL: <https://lists.freedesktop.org/archives/intel-gvt-dev/attachments/20211217/b59300f9/attachment-0001.sig>


More information about the intel-gvt-dev mailing list