[Intel-gfx] [RFC 4/7] drm/i915: Introduce dynamic private PAT management

Zhi Wang zhi.a.wang at intel.com
Tue Aug 15 21:31:12 UTC 2017


To manage the dynamic private PAT entries, this patch introduces some
basic functionalities for getting and putting an expected private PAT
entry.

When building the private PAT mapping between virtual PPAT indexes and
physical PPAT indexes, GVT-g would check if there is already an usable
private PAT entry.

If it's a perfect match, it would be directly used.

If it's not a perfect match and there is still unused PPAT entry, GVT
will allocate a new PPAT entry index for a guest.

If it's not a perfect match and there is no available unused PPAT entry,
GVT will use the parital matched PPAT entry index.

Each dynamic PPAT entry is associated with a reference count. If no
vGPU is using it, it will be freed.

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

diff --git a/drivers/gpu/drm/i915/gvt/gtt.c b/drivers/gpu/drm/i915/gvt/gtt.c
index c630015..6e19d7a 100644
--- a/drivers/gpu/drm/i915/gvt/gtt.c
+++ b/drivers/gpu/drm/i915/gvt/gtt.c
@@ -2254,6 +2254,103 @@ static int setup_spt_oos(struct intel_gvt *gvt)
 	return ret;
 }
 
+static void setup_private_pat(struct intel_gvt *gvt)
+{
+	struct drm_i915_private *dev_priv = gvt->dev_priv;
+	struct intel_gvt_gtt *gtt = &gvt->gtt;
+	struct intel_gvt_gtt_pat_ops *ops = gtt->pat_ops;
+	int i;
+
+	i = find_first_bit(dev_priv->avail_ppat_bitmap, gtt->max_ppat_index);
+	if (i >= gtt->max_ppat_index) {
+		DRM_DEBUG_DRIVER("no private PAT support\n");
+		return;
+	}
+
+	gtt->has_ppat = true;
+
+	/* Save available PPAT bitmap from host */
+	bitmap_copy(gtt->avail_ppat_bitmap, dev_priv->avail_ppat_bitmap,
+			gtt->max_ppat_index);
+
+	/* Read host PPAT configuration */
+	for_each_clear_bit(i, gtt->avail_ppat_bitmap, gtt->max_ppat_index)
+		gtt->ppat_value[i] = ops->get_pat_value(NULL, i, gvt);
+}
+
+static int get_private_pat_index(struct intel_gvt *gvt, u32 value)
+{
+	struct drm_i915_private *dev_priv = gvt->dev_priv;
+	struct intel_gvt_gtt *gtt = &gvt->gtt;
+	struct intel_gvt_gtt_pat_ops *ops = gtt->pat_ops;
+	int i, index, used;
+	unsigned int score, best_score;
+
+	if (WARN_ON(!gtt->has_ppat))
+		return 0;
+
+	score = best_score = 0;
+	used = 0;
+
+	/* First, find a suitable value from available configurations */
+	for_each_clear_bit(i, gtt->avail_ppat_bitmap, gtt->max_ppat_index) {
+		score = ops->match_pat_value(gtt->ppat_value[i], value);
+		/* Perfect match */
+		if (score == ~0) {
+			index = i;
+			goto found;
+		}
+
+		if (score > best_score) {
+			index = i;
+			best_score = score;
+		}
+		used++;
+	}
+
+	if (!best_score && used == gtt->max_ppat_index) {
+		DRM_ERROR("cannot find a suitable PPAT entry\n");
+		return -ENOSPC;
+	}
+
+	/*
+	 * Found a matched entry which is not perfect,
+	 * but we don't have a available free entry
+	 */
+	if (best_score && used == gtt->max_ppat_index)
+		goto found;
+
+	/* Allocate a new one */
+	index = find_first_bit(gtt->avail_ppat_bitmap, gtt->max_ppat_index);
+	clear_bit(index, gtt->avail_ppat_bitmap);
+	gtt->ppat_value[index] = value;
+	ops->set_pat_value(NULL, index, gtt->ppat_value[index], gvt);
+
+found:
+	/* Not need to increase reference for host entries.*/
+	if (test_bit(index, dev_priv->avail_ppat_bitmap))
+		return index;
+
+	atomic_inc(&gtt->ppat_refc[index]);
+	return index;
+}
+
+static void put_private_pat_index(struct intel_gvt *gvt, unsigned int index)
+{
+	struct drm_i915_private *dev_priv = gvt->dev_priv;
+	struct intel_gvt_gtt *gtt = &gvt->gtt;
+
+	if (WARN_ON(!gtt->has_ppat))
+		return;
+
+	/* Nothing to do with host PPAT configuration */
+	if (test_bit(index, dev_priv->avail_ppat_bitmap))
+		return;
+
+	if (atomic_dec_and_test(&gtt->ppat_refc[index]))
+		set_bit(index, gtt->avail_ppat_bitmap);
+}
+
 /**
  * intel_vgpu_find_ppgtt_mm - find a PPGTT mm object
  * @vgpu: a vGPU
@@ -2386,12 +2483,15 @@ int intel_gvt_init_gtt(struct intel_gvt *gvt)
 		gvt->gtt.pte_ops = &gen8_gtt_pte_ops;
 		gvt->gtt.gma_ops = &gen8_gtt_gma_ops;
 		gvt->gtt.pat_ops = &gen8_pat_ops;
+		gvt->gtt.max_ppat_index = 8;
 		gvt->gtt.mm_alloc_page_table = gen8_mm_alloc_page_table;
 		gvt->gtt.mm_free_page_table = gen8_mm_free_page_table;
 	} else {
 		return -ENODEV;
 	}
 
+	setup_private_pat(gvt);
+
 	page = (void *)get_zeroed_page(GFP_KERNEL);
 	if (!page) {
 		gvt_err("fail to allocate scratch ggtt page\n");
diff --git a/drivers/gpu/drm/i915/gvt/gtt.h b/drivers/gpu/drm/i915/gvt/gtt.h
index 02f6bd9..6cd4fc7 100644
--- a/drivers/gpu/drm/i915/gvt/gtt.h
+++ b/drivers/gpu/drm/i915/gvt/gtt.h
@@ -100,6 +100,12 @@ struct intel_gvt_gtt {
 
 	struct page *scratch_ggtt_page;
 	unsigned long scratch_ggtt_mfn;
+
+	DECLARE_BITMAP(avail_ppat_bitmap, MAX_PPAT_INDEX);
+	unsigned int ppat_value[MAX_PPAT_INDEX];
+	atomic_t ppat_refc[MAX_PPAT_INDEX];
+	unsigned int max_ppat_index;
+	bool has_ppat;
 };
 
 enum {
-- 
2.7.4



More information about the Intel-gfx mailing list