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. Systems without LLC require an explicit flush. This commit also moves gen8_initialize_pt next to the other initialize page functions. v2: Handle scratch_pdp allocation failure correctly, and keep initialize_px functions together (Akash) Suggested-by: Akash Goel <akash.goel@xxxxxxxxx> Signed-off-by: Michel Thierry <michel.thierry@xxxxxxxxx> --- drivers/gpu/drm/i915/i915_gem_gtt.c | 108 ++++++++++++++++++++++++++++-------- drivers/gpu/drm/i915/i915_gem_gtt.h | 1 + 2 files changed, 86 insertions(+), 23 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index dbbf367..df37c84 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -365,24 +365,6 @@ static void unmap_and_free_pt(struct i915_page_table *pt, kfree(pt); } -static void gen8_initialize_pt(struct i915_address_space *vm, - struct i915_page_table *pt) -{ - gen8_pte_t *pt_vaddr, scratch_pte; - int i; - - pt_vaddr = kmap_atomic(pt->page); - scratch_pte = gen8_pte_encode(vm->scratch.addr, - I915_CACHE_LLC, true); - - for (i = 0; i < GEN8_PTES; i++) - pt_vaddr[i] = scratch_pte; - - if (!HAS_LLC(vm->dev)) - drm_clflush_virt_range(pt_vaddr, PAGE_SIZE); - kunmap_atomic(pt_vaddr); -} - static struct i915_page_table *alloc_pt_single(struct drm_device *dev) { struct i915_page_table *pt; @@ -521,7 +503,7 @@ i915_page_directory_pointer *alloc_pdp_single(struct i915_hw_ppgtt *ppgtt) if (!pdp) return ERR_PTR(-ENOMEM); - pdp->page = alloc_page(GFP_KERNEL | GFP_DMA32 | __GFP_ZERO); + pdp->page = alloc_page(GFP_KERNEL | GFP_DMA32); if (!pdp->page) { kfree(pdp); return ERR_PTR(-ENOMEM); @@ -761,6 +743,24 @@ static void __gen8_do_map_pt(gen8_pde_t * const pde, *pde = entry; } +static void gen8_initialize_pt(struct i915_address_space *vm, + struct i915_page_table *pt) +{ + gen8_pte_t *pt_vaddr, scratch_pte; + int i; + + pt_vaddr = kmap_atomic(pt->page); + scratch_pte = gen8_pte_encode(vm->scratch.addr, + I915_CACHE_LLC, true); + + for (i = 0; i < GEN8_PTES; i++) + pt_vaddr[i] = scratch_pte; + + if (!HAS_LLC(vm->dev)) + drm_clflush_virt_range(pt_vaddr, PAGE_SIZE); + kunmap_atomic(pt_vaddr); +} + static void gen8_initialize_pd(struct i915_address_space *vm, struct i915_page_directory *pd) { @@ -782,6 +782,55 @@ static void gen8_initialize_pd(struct i915_address_space *vm, kunmap_atomic(page_directory); } +static void gen8_initialize_pdp(struct i915_address_space *vm, + struct i915_page_directory_pointer *pdp) +{ + struct i915_hw_ppgtt *ppgtt = + container_of(vm, struct i915_hw_ppgtt, base); + gen8_ppgtt_pdpe_t *page_directorypo; + struct i915_page_directory *pd; + int i; + + page_directorypo = kmap_atomic(pdp->page); + pd = (struct i915_page_directory *)ppgtt->scratch_pd; + for (i = 0; i < I915_PDPES_PER_PDP(vm->dev); i++) { + /* Map the PDPE to the page directory */ + gen8_ppgtt_pdpe_t entry = + gen8_pdpe_encode(vm->dev, pd->daddr, I915_CACHE_LLC); + page_directorypo[i] = entry; + } + + if (!HAS_LLC(vm->dev)) + drm_clflush_virt_range(page_directorypo, PAGE_SIZE); + + kunmap_atomic(page_directorypo); +} + +static void gen8_initialize_pml4(struct i915_address_space *vm, + struct i915_pml4 *pml4) +{ + struct i915_hw_ppgtt *ppgtt = + container_of(vm, struct i915_hw_ppgtt, base); + gen8_ppgtt_pml4e_t *page_maplevel4; + struct i915_page_directory_pointer *pdp; + int i; + + page_maplevel4 = kmap_atomic(pml4->page); + pdp = (struct i915_page_directory_pointer *)ppgtt->scratch_pdp; + for (i = 0; i < GEN8_PML4ES_PER_PML4; i++) { + /* Map the PML4E to the page directory pointer */ + gen8_ppgtt_pml4e_t entry = + gen8_pml4e_encode(vm->dev, pdp->daddr, + I915_CACHE_LLC); + page_maplevel4[i] = entry; + } + + if (!HAS_LLC(vm->dev)) + drm_clflush_virt_range(page_maplevel4, PAGE_SIZE); + + kunmap_atomic(page_maplevel4); +} + static void pml4_fini(struct i915_pml4 *pml4) { struct i915_hw_ppgtt *ppgtt = @@ -795,10 +844,12 @@ static int pml4_init(struct i915_hw_ppgtt *ppgtt) { struct i915_pml4 *pml4 = &ppgtt->pml4; - pml4->page = alloc_page(GFP_KERNEL | __GFP_ZERO); + pml4->page = alloc_page(GFP_KERNEL | GFP_DMA32); if (!pml4->page) return -ENOMEM; + gen8_initialize_pml4(&ppgtt->base, pml4); + i915_dma_map_single(pml4, ppgtt->base.dev); return 0; @@ -913,6 +964,7 @@ static void gen8_ppgtt_cleanup_4lvl(struct i915_hw_ppgtt *ppgtt) } pml4_fini(&ppgtt->pml4); + unmap_and_free_pdp(ppgtt->scratch_pdp, ppgtt->base.dev); } static void gen8_ppgtt_cleanup(struct i915_address_space *vm) @@ -1220,12 +1272,12 @@ static int __gen8_alloc_vma_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_single(ppgtt); 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, @@ -1301,9 +1353,17 @@ static int gen8_ppgtt_init(struct i915_hw_ppgtt *ppgtt) gen8_initialize_pd(&ppgtt->base, ppgtt->scratch_pd); if (USES_FULL_48BIT_PPGTT(ppgtt->base.dev)) { + ppgtt->scratch_pdp = alloc_pdp_single(ppgtt); + if (IS_ERR(ppgtt->scratch_pdp)) { + ret = PTR_ERR(ppgtt->scratch_pdp); + goto err_out; + } + + gen8_initialize_pdp(&ppgtt->base, ppgtt->scratch_pdp); + ret = pml4_init(ppgtt); if (ret) - goto err_out; + goto err_pdp_out; ppgtt->base.total = 1ULL << 48; ppgtt->switch_mm = gen8_48b_mm_switch; @@ -1327,6 +1387,8 @@ static int gen8_ppgtt_init(struct i915_hw_ppgtt *ppgtt) return 0; +err_pdp_out: + unmap_and_free_pdp(ppgtt->scratch_pdp, ppgtt->base.dev); err_out: unmap_and_free_pd(ppgtt->scratch_pd, ppgtt->base.dev); unmap_and_free_pt(ppgtt->scratch_pt, ppgtt->base.dev); diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.h b/drivers/gpu/drm/i915/i915_gem_gtt.h index 9af33b2..6e2f39c 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.h +++ b/drivers/gpu/drm/i915/i915_gem_gtt.h @@ -358,6 +358,7 @@ struct i915_hw_ppgtt { struct i915_page_table *scratch_pt; struct i915_page_directory *scratch_pd; + struct i915_page_directory_pointer *scratch_pdp; struct drm_i915_file_private *file_priv; -- 2.4.0 _______________________________________________ Intel-gfx mailing list Intel-gfx@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/intel-gfx