[PATCH] drm/i915/gvt: Refine PPGTT lazy shadow

Wang, Zhi A zhi.a.wang at intel.com
Mon Oct 23 07:14:18 UTC 2017


Hi Terrence:
    Can you help to see if linux 4.14-rc5 guest works? It works on my side already.

Thanks,
Zhi.

-----Original Message-----
From: Zhi Wang [mailto:zhi.wang.linux at gmail.com] 
Sent: Sunday, October 22, 2017 11:36 PM
To: intel-gvt-dev at lists.freedesktop.org
Cc: Wang, Zhi A <zhi.a.wang at intel.com>
Subject: [PATCH] drm/i915/gvt: Refine PPGTT lazy shadow

A vGPU guest might fill a page of page table with garbage, or link an un-initialized page into page table due to some optimizations of page table manipulation.

Tracking these pages of garbage is expensive in GVT-g. To solve this issue, GVT-g will stop tracking these pages once it finds they are not being used as pages of page table, and the shadow of these pages will be synced and tracked again before GVT-g dispatches the workload.

Signed-off-by: Zhi Wang <zhi.a.wang at intel.com>
---
 drivers/gpu/drm/i915/gvt/gtt.c | 53 +++++++++++++++++++++++-------------------
 drivers/gpu/drm/i915/gvt/gtt.h |  3 ---
 2 files changed, 29 insertions(+), 27 deletions(-)

diff --git a/drivers/gpu/drm/i915/gvt/gtt.c b/drivers/gpu/drm/i915/gvt/gtt.c index 6fa9271..17e87df 100644
--- a/drivers/gpu/drm/i915/gvt/gtt.c
+++ b/drivers/gpu/drm/i915/gvt/gtt.c
@@ -762,6 +762,8 @@ static int ppgtt_handle_guest_write_page_table_bytes(
 		struct intel_vgpu_guest_page *gpt,
 		u64 pa, void *p_data, int bytes);
 
+static int ppgtt_set_post_shadow(struct intel_vgpu_ppgtt_spt *spt);
+
 static int ppgtt_write_protection_handler(void *data, u64 pa,
 		void *p_data, int bytes)
 {
@@ -770,7 +772,7 @@ static int ppgtt_write_protection_handler(void *data, u64 pa,
 	int ret;
 
 	if (bytes != 4 && bytes != 8)
-		return -EINVAL;
+		return ppgtt_set_post_shadow(guest_page_to_ppgtt_spt(p));
 
 	if (!t->tracked)
 		return -EINVAL;
@@ -1036,6 +1038,8 @@ static int ppgtt_populate_shadow_page(struct intel_vgpu_ppgtt_spt *spt)
 		for_each_guest_entry(spt, &ge, i) {
 			if (ops->test_present(&ge)) {
 				ret = gtt_entry_p2m(vgpu, &ge, &se);
+				if (ret == -ENXIO)
+					return ppgtt_set_post_shadow(spt);
 				if (ret)
 					goto fail;
 			} else {
@@ -1138,6 +1142,8 @@ static int ppgtt_handle_guest_entry_add(struct intel_vgpu_guest_page *gpt,
 		ppgtt_set_shadow_entry(spt, &m, index);
 	} else {
 		ret = gtt_entry_p2m(vgpu, we, &m);
+		if (ret == -ENXIO)
+			return ppgtt_set_post_shadow(spt);
 		if (ret)
 			goto fail;
 		ppgtt_set_shadow_entry(spt, &m, index); @@ -1173,8 +1179,7 @@ static int sync_oos_page(struct intel_vgpu *vgpu,
 		ops->get_entry(NULL, &new, index, true,
 			oos_page->guest_page->track.gfn << PAGE_SHIFT, vgpu);
 
-		if (old.val64 == new.val64
-			&& !test_and_clear_bit(index, spt->post_shadow_bitmap))
+		if (old.val64 == new.val64)
 			continue;
 
 		trace_oos_sync(vgpu->id, oos_page->id, @@ -1376,15 +1381,21 @@ static inline bool can_do_out_of_sync(struct intel_vgpu_guest_page *gpt)
 		&& gpt->write_cnt >= 2;
 }
 
-static void ppgtt_set_post_shadow(struct intel_vgpu_ppgtt_spt *spt,
-		unsigned long index)
+static int ppgtt_set_post_shadow(struct intel_vgpu_ppgtt_spt *spt)
 {
-	set_bit(index, spt->post_shadow_bitmap);
+	struct intel_vgpu *vgpu = spt->vgpu;
+	int ret;
+
+	ret = intel_gvt_hypervisor_disable_page_track(vgpu,
+			&spt->guest_page.track);
+	if (ret)
+		return ret;
+
 	if (!list_empty(&spt->post_shadow_list))
-		return;
+		return 0;
 
-	list_add_tail(&spt->post_shadow_list,
-			&spt->vgpu->gtt.post_shadow_list_head);
+	list_add_tail(&spt->post_shadow_list, &vgpu->gtt.post_shadow_list_head);
+	return 0;
 }
 
 /**
@@ -1409,16 +1420,18 @@ int intel_vgpu_flush_post_shadow(struct intel_vgpu *vgpu)
 		spt = container_of(pos, struct intel_vgpu_ppgtt_spt,
 				post_shadow_list);
 
-		for_each_set_bit(index, spt->post_shadow_bitmap,
-				GTT_ENTRY_NUM_IN_ONE_PAGE) {
-			ppgtt_get_guest_entry(spt, &ge, index);
+		ret = intel_gvt_hypervisor_enable_page_track(vgpu,
+				&spt->guest_page.track);
+		if (ret)
+			return ret;
 
+		for_each_guest_entry(spt, &ge, index)  {
 			ret = ppgtt_handle_guest_write_page_table(
 					&spt->guest_page, &ge, index);
 			if (ret)
 				return ret;
-			clear_bit(index, spt->post_shadow_bitmap);
 		}
+
 		list_del_init(&spt->post_shadow_list);
 	}
 	return 0;
@@ -1432,7 +1445,7 @@ static int ppgtt_handle_guest_write_page_table_bytes(
 	struct intel_vgpu *vgpu = spt->vgpu;
 	struct intel_gvt_gtt_pte_ops *ops = vgpu->gvt->gtt.pte_ops;
 	const struct intel_gvt_device_info *info = &vgpu->gvt->device_info;
-	struct intel_gvt_gtt_entry we, se;
+	struct intel_gvt_gtt_entry we;
 	unsigned long index;
 	int ret;
 
@@ -1446,16 +1459,8 @@ static int ppgtt_handle_guest_write_page_table_bytes(
 		ret = ppgtt_handle_guest_write_page_table(gpt, &we, index);
 		if (ret)
 			return ret;
-	} else {
-		if (!test_bit(index, spt->post_shadow_bitmap)) {
-			ppgtt_get_shadow_entry(spt, &se, index);
-			ret = ppgtt_handle_guest_entry_removal(gpt, &se, index);
-			if (ret)
-				return ret;
-		}
-
-		ppgtt_set_post_shadow(spt, index);
-	}
+	} else
+		ppgtt_set_post_shadow(spt);
 
 	if (!enable_out_of_sync)
 		return 0;
diff --git a/drivers/gpu/drm/i915/gvt/gtt.h b/drivers/gpu/drm/i915/gvt/gtt.h index 416b2f8..9a8506e 100644
--- a/drivers/gpu/drm/i915/gvt/gtt.h
+++ b/drivers/gpu/drm/i915/gvt/gtt.h
@@ -243,15 +243,12 @@ struct intel_vgpu_oos_page {
 	unsigned char mem[I915_GTT_PAGE_SIZE];  };
 
-#define GTT_ENTRY_NUM_IN_ONE_PAGE 512
-
 struct intel_vgpu_ppgtt_spt {
 	struct intel_vgpu_shadow_page shadow_page;
 	struct intel_vgpu_guest_page guest_page;
 	int guest_page_type;
 	atomic_t refcount;
 	struct intel_vgpu *vgpu;
-	DECLARE_BITMAP(post_shadow_bitmap, GTT_ENTRY_NUM_IN_ONE_PAGE);
 	struct list_head post_shadow_list;
 };
 
--
2.7.4



More information about the intel-gvt-dev mailing list