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

Zhi Wang zhi.wang.linux at gmail.com
Sun Oct 22 20:32:13 UTC 2017


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 | 59 +++++++++++++++++++++++-------------------
 drivers/gpu/drm/i915/gvt/gtt.h |  3 ---
 2 files changed, 32 insertions(+), 30 deletions(-)

diff --git a/drivers/gpu/drm/i915/gvt/gtt.c b/drivers/gpu/drm/i915/gvt/gtt.c
index 6fa9271..13d7e03 100644
--- a/drivers/gpu/drm/i915/gvt/gtt.c
+++ b/drivers/gpu/drm/i915/gvt/gtt.c
@@ -709,9 +709,6 @@ static inline struct intel_vgpu_shadow_page *find_shadow_page(
 #define page_track_to_guest_page(ptr) \
 	container_of(ptr, struct intel_vgpu_guest_page, track)
 
-#define guest_page_to_ppgtt_spt(ptr) \
-	container_of(ptr, struct intel_vgpu_ppgtt_spt, guest_page)
-
 #define shadow_page_to_ppgtt_spt(ptr) \
 	container_of(ptr, struct intel_vgpu_ppgtt_spt, shadow_page)
 
@@ -762,6 +759,11 @@ 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);
+
+#define guest_page_to_ppgtt_spt(ptr) \
+	container_of(ptr, struct intel_vgpu_ppgtt_spt, guest_page)
+
 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