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@xxxxxxxxx> Signed-off-by: Michel Thierry <michel.thierry@xxxxxxxxx> --- 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(-) 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. -- 2.4.0 _______________________________________________ Intel-gfx mailing list Intel-gfx@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/intel-gfx