Created
          June 30, 2015 16:12 
        
      - 
      
- 
        Save mthierry/2c35d5a77855e1168bd4 to your computer and use it in GitHub Desktop. 
  
    
      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
      Learn more about bidirectional Unicode characters
    
  
  
    
  | From 47f1f8baeba0e01891dd3219a880e2202b788bd2 Mon Sep 17 00:00:00 2001 | |
| From: Michel Thierry <[email protected]> | |
| Date: Wed, 18 Mar 2015 14:11:28 +0000 | |
| Subject: [PATCH] drm/i915/gen8: Initialize PDPs | |
| 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 <[email protected]> | |
| Signed-off-by: Michel Thierry <[email protected]> | |
| --- | |
| 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 fc9b87b..c61d5ac 100644 | |
| --- a/drivers/gpu/drm/i915/i915_gem_gtt.c | |
| +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c | |
| @@ -361,24 +361,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; | |
| @@ -517,7 +499,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); | |
| @@ -757,6 +739,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) | |
| { | |
| @@ -778,6 +778,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 = | |
| @@ -791,10 +840,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; | |
| @@ -909,6 +960,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) | |
| @@ -1216,12 +1268,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, | |
| @@ -1297,9 +1349,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; | |
| @@ -1323,6 +1383,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 be6e322..aa174aa 100644 | |
| --- a/drivers/gpu/drm/i915/i915_gem_gtt.h | |
| +++ b/drivers/gpu/drm/i915/i915_gem_gtt.h | |
| @@ -354,6 +354,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.5 | |
  
    Sign up for free
    to join this conversation on GitHub.
    Already have an account?
    Sign in to comment