[v2,12/18] drm/i915/gen8: Initialize PDPs

Submitted by Michel Thierry on June 10, 2015, 4:46 p.m.

Details

Message ID 1433954816-13787-13-git-send-email-michel.thierry@intel.com
State New
Headers show

Not browsing as part of any series.

Commit Message

Michel Thierry June 10, 2015, 4:46 p.m.
Similar to PDs, while setting up a page directory pointer, make all entries
of the pdp point to the scratch pdp before mapping (and make all its entries
point to the scratch page); this is to be safe in case of out of bound
access or  proactive prefetch.

Although the ggtt is always 32-bit, the scratch_pdp will be initialized/destroyed
at the same time as the other scratch pages, to keep it consistent.

v2: Handle scratch_pdp allocation failure correctly, and keep
initialize_px functions together (Akash)
v3: Rebase after Mika's ppgtt cleanup / scratch merge patch series. Rely on
the added macros to initialize the pdps.

Suggested-by: Akash Goel <akash.goel@intel.com>
Signed-off-by: Michel Thierry <michel.thierry@intel.com>
---
 drivers/gpu/drm/i915/i915_gem_gtt.c | 53 ++++++++++++++++++++++++++++++++++---
 drivers/gpu/drm/i915/i915_gem_gtt.h |  1 +
 2 files changed, 51 insertions(+), 3 deletions(-)

Patch hide | download patch | download mbox

diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c
index 9919c3b..65d0787 100644
--- a/drivers/gpu/drm/i915/i915_gem_gtt.c
+++ b/drivers/gpu/drm/i915/i915_gem_gtt.c
@@ -593,6 +593,27 @@  static void free_pdp(struct drm_device *dev,
 	}
 }
 
+static void gen8_initialize_pdp(struct i915_address_space *vm,
+				struct i915_page_directory_pointer *pdp)
+{
+	gen8_ppgtt_pdpe_t scratch_pdpe;
+
+	scratch_pdpe = gen8_pdpe_encode(px_dma(vm->scratch_pd), I915_CACHE_LLC);
+
+	fill_px(vm->dev, pdp, scratch_pdpe);
+}
+
+static void gen8_initialize_pml4(struct i915_address_space *vm,
+				 struct i915_pml4 *pml4)
+{
+	gen8_ppgtt_pml4e_t scratch_pml4e;
+
+	scratch_pml4e = gen8_pml4e_encode(px_dma(vm->scratch_pdp),
+					  I915_CACHE_LLC);
+
+	fill_px(vm->dev, pml4, scratch_pml4e);
+}
+
 static void
 gen8_setup_page_directory(struct i915_hw_ppgtt *ppgtt,
 			  struct i915_page_directory_pointer *pdp,
@@ -693,12 +714,30 @@  static int setup_scratch_ggtt(struct i915_address_space *vm)
 
 		WARN_ON(px_dma(vm->scratch_pt) == 0);
 		gen8_initialize_pd(vm, vm->scratch_pd);
+
+		/* although scratch_pdp is only needed for 48-bit ppgtt,
+		 * keep it with the other scratch pages for consistency.
+		 */
+		if (USES_FULL_48BIT_PPGTT(dev)) {
+			WARN_ON(vm->scratch_pdp);
+
+			vm->scratch_pdp = alloc_pdp(vm->dev);
+			if (IS_ERR(vm->scratch_pdp)) {
+				ret = PTR_ERR(vm->scratch_pdp);
+				goto err_pdp;
+			}
+
+			WARN_ON(px_dma(vm->scratch_pd) == 0);
+			gen8_initialize_pdp(vm, vm->scratch_pdp);
+		}
 	} else {
 		gen6_initialize_pt(vm, vm->scratch_pt);
 	}
 
 	return 0;
 
+err_pdp:
+	free_pd(vm->dev, vm->scratch_pd);
 err_pd:
 	free_pt(vm->dev, vm->scratch_pt);
 	return ret;
@@ -714,6 +753,7 @@  static int setup_scratch(struct i915_address_space *vm)
 	vm->scratch_page = ggtt_vm->scratch_page;
 	vm->scratch_pt = ggtt_vm->scratch_pt;
 	vm->scratch_pd = ggtt_vm->scratch_pd;
+	vm->scratch_pdp = ggtt_vm->scratch_pdp;
 
 	return 0;
 }
@@ -748,8 +788,12 @@  static void cleanup_scratch_ggtt(struct i915_address_space *vm)
 
 	free_pt(vm->dev, vm->scratch_pt);
 
-	if (INTEL_INFO(vm->dev)->gen >= 8)
+	if (INTEL_INFO(vm->dev)->gen >= 8) {
 		free_pd(vm->dev, vm->scratch_pd);
+
+		if (USES_FULL_48BIT_PPGTT(dev))
+			free_pdp(vm->dev, vm->scratch_pdp);
+	}
 }
 
 static void cleanup_scratch(struct i915_address_space *vm)
@@ -760,6 +804,7 @@  static void cleanup_scratch(struct i915_address_space *vm)
 	vm->scratch_page = NULL;
 	vm->scratch_pt = NULL;
 	vm->scratch_pd = NULL;
+	vm->scratch_pdp = NULL;
 }
 
 /* Broadwell Page Directory Pointer Descriptors */
@@ -1316,12 +1361,12 @@  static int gen8_alloc_va_range_4lvl(struct i915_address_space *vm,
 	 * and 4 level code. Just allocate the pdps.
 	 */
 	gen8_for_each_pml4e(pdp, pml4, start, length, temp, pml4e) {
-		if (!pdp) {
-			WARN_ON(test_bit(pml4e, pml4->used_pml4es));
+		if (!test_bit(pml4e, pml4->used_pml4es)) {
 			pdp = alloc_pdp(vm->dev);
 			if (IS_ERR(pdp))
 				goto err_out;
 
+			gen8_initialize_pdp(vm, pdp);
 			pml4->pdps[pml4e] = pdp;
 			__set_bit(pml4e, new_pdps);
 			trace_i915_page_directory_pointer_entry_alloc(&ppgtt->base, pml4e,
@@ -1446,6 +1491,8 @@  static int gen8_ppgtt_init(struct i915_hw_ppgtt *ppgtt)
 		if (ret)
 			goto clear_scratch;
 
+		gen8_initialize_pml4(&ppgtt->base, &ppgtt->pml4);
+
 		ppgtt->base.total = 1ULL << 48;
 		ppgtt->switch_mm = gen8_48b_mm_switch;
 	} else {
diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.h b/drivers/gpu/drm/i915/i915_gem_gtt.h
index 1803e91..c0a6487 100644
--- a/drivers/gpu/drm/i915/i915_gem_gtt.h
+++ b/drivers/gpu/drm/i915/i915_gem_gtt.h
@@ -272,6 +272,7 @@  struct i915_address_space {
 	struct i915_page_scratch *scratch_page;
 	struct i915_page_table *scratch_pt;
 	struct i915_page_directory *scratch_pd;
+	struct i915_page_directory_pointer *scratch_pdp; /* GEN8+ & 48b PPGTT */
 
 	/**
 	 * List of objects currently involved in rendering.