LCOV - code coverage report
Current view: top level - drivers/gpu/drm/i915/gt - intel_gtt.c (source / functions) Hit Total Coverage
Test: combined.info Lines: 0 264 0.0 %
Date: 2022-04-01 14:58:12 Functions: 0 24 0.0 %
Branches: 0 105 0.0 %

           Branch data     Line data    Source code
       1                 :            : // SPDX-License-Identifier: MIT
       2                 :            : /*
       3                 :            :  * Copyright © 2020 Intel Corporation
       4                 :            :  */
       5                 :            : 
       6                 :            : #include <linux/slab.h> /* fault-inject.h is not standalone! */
       7                 :            : 
       8                 :            : #include <linux/fault-inject.h>
       9                 :            : 
      10                 :            : #include "i915_trace.h"
      11                 :            : #include "intel_gt.h"
      12                 :            : #include "intel_gtt.h"
      13                 :            : 
      14                 :          0 : void stash_init(struct pagestash *stash)
      15                 :            : {
      16                 :          0 :         pagevec_init(&stash->pvec);
      17                 :          0 :         spin_lock_init(&stash->lock);
      18                 :          0 : }
      19                 :            : 
      20                 :          0 : static struct page *stash_pop_page(struct pagestash *stash)
      21                 :            : {
      22                 :          0 :         struct page *page = NULL;
      23                 :            : 
      24                 :          0 :         spin_lock(&stash->lock);
      25   [ #  #  #  # ]:          0 :         if (likely(stash->pvec.nr))
      26                 :          0 :                 page = stash->pvec.pages[--stash->pvec.nr];
      27                 :          0 :         spin_unlock(&stash->lock);
      28                 :            : 
      29                 :          0 :         return page;
      30                 :            : }
      31                 :            : 
      32                 :          0 : static void stash_push_pagevec(struct pagestash *stash, struct pagevec *pvec)
      33                 :            : {
      34                 :          0 :         unsigned int nr;
      35                 :            : 
      36                 :          0 :         spin_lock_nested(&stash->lock, SINGLE_DEPTH_NESTING);
      37                 :            : 
      38                 :          0 :         nr = min_t(typeof(nr), pvec->nr, pagevec_space(&stash->pvec));
      39                 :          0 :         memcpy(stash->pvec.pages + stash->pvec.nr,
      40                 :          0 :                pvec->pages + pvec->nr - nr,
      41                 :            :                sizeof(pvec->pages[0]) * nr);
      42                 :          0 :         stash->pvec.nr += nr;
      43                 :            : 
      44                 :          0 :         spin_unlock(&stash->lock);
      45                 :            : 
      46                 :          0 :         pvec->nr -= nr;
      47                 :          0 : }
      48                 :            : 
      49                 :          0 : static struct page *vm_alloc_page(struct i915_address_space *vm, gfp_t gfp)
      50                 :            : {
      51                 :          0 :         struct pagevec stack;
      52                 :          0 :         struct page *page;
      53                 :            : 
      54                 :          0 :         if (I915_SELFTEST_ONLY(should_fail(&vm->fault_attr, 1)))
      55                 :            :                 i915_gem_shrink_all(vm->i915);
      56                 :            : 
      57                 :          0 :         page = stash_pop_page(&vm->free_pages);
      58         [ #  # ]:          0 :         if (page)
      59                 :            :                 return page;
      60                 :            : 
      61         [ #  # ]:          0 :         if (!vm->pt_kmap_wc)
      62                 :          0 :                 return alloc_page(gfp);
      63                 :            : 
      64                 :            :         /* Look in our global stash of WC pages... */
      65                 :          0 :         page = stash_pop_page(&vm->i915->mm.wc_stash);
      66         [ #  # ]:          0 :         if (page)
      67                 :            :                 return page;
      68                 :            : 
      69                 :            :         /*
      70                 :            :          * Otherwise batch allocate pages to amortize cost of set_pages_wc.
      71                 :            :          *
      72                 :            :          * We have to be careful as page allocation may trigger the shrinker
      73                 :            :          * (via direct reclaim) which will fill up the WC stash underneath us.
      74                 :            :          * So we add our WB pages into a temporary pvec on the stack and merge
      75                 :            :          * them into the WC stash after all the allocations are complete.
      76                 :            :          */
      77                 :          0 :         pagevec_init(&stack);
      78                 :          0 :         do {
      79                 :          0 :                 struct page *page;
      80                 :            : 
      81                 :          0 :                 page = alloc_page(gfp);
      82         [ #  # ]:          0 :                 if (unlikely(!page))
      83                 :            :                         break;
      84                 :            : 
      85                 :          0 :                 stack.pages[stack.nr++] = page;
      86         [ #  # ]:          0 :         } while (pagevec_space(&stack));
      87                 :            : 
      88   [ #  #  #  # ]:          0 :         if (stack.nr && !set_pages_array_wc(stack.pages, stack.nr)) {
      89                 :          0 :                 page = stack.pages[--stack.nr];
      90                 :            : 
      91                 :            :                 /* Merge spare WC pages to the global stash */
      92         [ #  # ]:          0 :                 if (stack.nr)
      93                 :          0 :                         stash_push_pagevec(&vm->i915->mm.wc_stash, &stack);
      94                 :            : 
      95                 :            :                 /* Push any surplus WC pages onto the local VM stash */
      96         [ #  # ]:          0 :                 if (stack.nr)
      97                 :          0 :                         stash_push_pagevec(&vm->free_pages, &stack);
      98                 :            :         }
      99                 :            : 
     100                 :            :         /* Return unwanted leftovers */
     101         [ #  # ]:          0 :         if (unlikely(stack.nr)) {
     102   [ #  #  #  # ]:          0 :                 WARN_ON_ONCE(set_pages_array_wb(stack.pages, stack.nr));
     103                 :          0 :                 __pagevec_release(&stack);
     104                 :            :         }
     105                 :            : 
     106                 :            :         return page;
     107                 :            : }
     108                 :            : 
     109                 :          0 : static void vm_free_pages_release(struct i915_address_space *vm,
     110                 :            :                                   bool immediate)
     111                 :            : {
     112                 :          0 :         struct pagevec *pvec = &vm->free_pages.pvec;
     113                 :          0 :         struct pagevec stack;
     114                 :            : 
     115                 :          0 :         lockdep_assert_held(&vm->free_pages.lock);
     116                 :          0 :         GEM_BUG_ON(!pagevec_count(pvec));
     117                 :            : 
     118         [ #  # ]:          0 :         if (vm->pt_kmap_wc) {
     119                 :            :                 /*
     120                 :            :                  * When we use WC, first fill up the global stash and then
     121                 :            :                  * only if full immediately free the overflow.
     122                 :            :                  */
     123                 :          0 :                 stash_push_pagevec(&vm->i915->mm.wc_stash, pvec);
     124                 :            : 
     125                 :            :                 /*
     126                 :            :                  * As we have made some room in the VM's free_pages,
     127                 :            :                  * we can wait for it to fill again. Unless we are
     128                 :            :                  * inside i915_address_space_fini() and must
     129                 :            :                  * immediately release the pages!
     130                 :            :                  */
     131   [ #  #  #  # ]:          0 :                 if (pvec->nr <= (immediate ? 0 : PAGEVEC_SIZE - 1))
     132                 :          0 :                         return;
     133                 :            : 
     134                 :            :                 /*
     135                 :            :                  * We have to drop the lock to allow ourselves to sleep,
     136                 :            :                  * so take a copy of the pvec and clear the stash for
     137                 :            :                  * others to use it as we sleep.
     138                 :            :                  */
     139                 :          0 :                 stack = *pvec;
     140                 :          0 :                 pagevec_reinit(pvec);
     141                 :          0 :                 spin_unlock(&vm->free_pages.lock);
     142                 :            : 
     143                 :          0 :                 pvec = &stack;
     144                 :          0 :                 set_pages_array_wb(pvec->pages, pvec->nr);
     145                 :            : 
     146                 :          0 :                 spin_lock(&vm->free_pages.lock);
     147                 :            :         }
     148                 :            : 
     149                 :          0 :         __pagevec_release(pvec);
     150                 :            : }
     151                 :            : 
     152                 :          0 : static void vm_free_page(struct i915_address_space *vm, struct page *page)
     153                 :            : {
     154                 :            :         /*
     155                 :            :          * On !llc, we need to change the pages back to WB. We only do so
     156                 :            :          * in bulk, so we rarely need to change the page attributes here,
     157                 :            :          * but doing so requires a stop_machine() from deep inside arch/x86/mm.
     158                 :            :          * To make detection of the possible sleep more likely, use an
     159                 :            :          * unconditional might_sleep() for everybody.
     160                 :            :          */
     161                 :          0 :         might_sleep();
     162                 :          0 :         spin_lock(&vm->free_pages.lock);
     163         [ #  # ]:          0 :         while (!pagevec_space(&vm->free_pages.pvec))
     164                 :          0 :                 vm_free_pages_release(vm, false);
     165                 :          0 :         GEM_BUG_ON(pagevec_count(&vm->free_pages.pvec) >= PAGEVEC_SIZE);
     166                 :          0 :         pagevec_add(&vm->free_pages.pvec, page);
     167                 :          0 :         spin_unlock(&vm->free_pages.lock);
     168                 :          0 : }
     169                 :            : 
     170                 :          0 : void __i915_vm_close(struct i915_address_space *vm)
     171                 :            : {
     172                 :          0 :         struct i915_vma *vma, *vn;
     173                 :            : 
     174                 :          0 :         mutex_lock(&vm->mutex);
     175         [ #  # ]:          0 :         list_for_each_entry_safe(vma, vn, &vm->bound_list, vm_link) {
     176                 :          0 :                 struct drm_i915_gem_object *obj = vma->obj;
     177                 :            : 
     178                 :            :                 /* Keep the obj (and hence the vma) alive as _we_ destroy it */
     179         [ #  # ]:          0 :                 if (!kref_get_unless_zero(&obj->base.refcount))
     180                 :          0 :                         continue;
     181                 :            : 
     182                 :          0 :                 atomic_and(~I915_VMA_PIN_MASK, &vma->flags);
     183         [ #  # ]:          0 :                 WARN_ON(__i915_vma_unbind(vma));
     184                 :          0 :                 __i915_vma_put(vma);
     185                 :            : 
     186                 :          0 :                 i915_gem_object_put(obj);
     187                 :            :         }
     188                 :          0 :         GEM_BUG_ON(!list_empty(&vm->bound_list));
     189                 :          0 :         mutex_unlock(&vm->mutex);
     190                 :          0 : }
     191                 :            : 
     192                 :          0 : void i915_address_space_fini(struct i915_address_space *vm)
     193                 :            : {
     194                 :          0 :         spin_lock(&vm->free_pages.lock);
     195         [ #  # ]:          0 :         if (pagevec_count(&vm->free_pages.pvec))
     196                 :          0 :                 vm_free_pages_release(vm, true);
     197                 :          0 :         GEM_BUG_ON(pagevec_count(&vm->free_pages.pvec));
     198                 :          0 :         spin_unlock(&vm->free_pages.lock);
     199                 :            : 
     200                 :          0 :         drm_mm_takedown(&vm->mm);
     201                 :            : 
     202                 :          0 :         mutex_destroy(&vm->mutex);
     203                 :          0 : }
     204                 :            : 
     205                 :          0 : static void __i915_vm_release(struct work_struct *work)
     206                 :            : {
     207                 :          0 :         struct i915_address_space *vm =
     208                 :          0 :                 container_of(work, struct i915_address_space, rcu.work);
     209                 :            : 
     210                 :          0 :         vm->cleanup(vm);
     211                 :          0 :         i915_address_space_fini(vm);
     212                 :            : 
     213                 :          0 :         kfree(vm);
     214                 :          0 : }
     215                 :            : 
     216                 :          0 : void i915_vm_release(struct kref *kref)
     217                 :            : {
     218                 :          0 :         struct i915_address_space *vm =
     219                 :          0 :                 container_of(kref, struct i915_address_space, ref);
     220                 :            : 
     221                 :          0 :         GEM_BUG_ON(i915_is_ggtt(vm));
     222                 :          0 :         trace_i915_ppgtt_release(vm);
     223                 :            : 
     224                 :          0 :         queue_rcu_work(vm->i915->wq, &vm->rcu);
     225                 :          0 : }
     226                 :            : 
     227                 :          0 : void i915_address_space_init(struct i915_address_space *vm, int subclass)
     228                 :            : {
     229                 :          0 :         kref_init(&vm->ref);
     230                 :          0 :         INIT_RCU_WORK(&vm->rcu, __i915_vm_release);
     231                 :          0 :         atomic_set(&vm->open, 1);
     232                 :            : 
     233                 :            :         /*
     234                 :            :          * The vm->mutex must be reclaim safe (for use in the shrinker).
     235                 :            :          * Do a dummy acquire now under fs_reclaim so that any allocation
     236                 :            :          * attempt holding the lock is immediately reported by lockdep.
     237                 :            :          */
     238                 :          0 :         mutex_init(&vm->mutex);
     239                 :          0 :         lockdep_set_subclass(&vm->mutex, subclass);
     240                 :          0 :         i915_gem_shrinker_taints_mutex(vm->i915, &vm->mutex);
     241                 :            : 
     242                 :          0 :         GEM_BUG_ON(!vm->total);
     243                 :          0 :         drm_mm_init(&vm->mm, 0, vm->total);
     244                 :          0 :         vm->mm.head_node.color = I915_COLOR_UNEVICTABLE;
     245                 :            : 
     246                 :          0 :         stash_init(&vm->free_pages);
     247                 :            : 
     248                 :          0 :         INIT_LIST_HEAD(&vm->bound_list);
     249                 :          0 : }
     250                 :            : 
     251                 :          0 : void clear_pages(struct i915_vma *vma)
     252                 :            : {
     253                 :          0 :         GEM_BUG_ON(!vma->pages);
     254                 :            : 
     255         [ #  # ]:          0 :         if (vma->pages != vma->obj->mm.pages) {
     256                 :          0 :                 sg_free_table(vma->pages);
     257                 :          0 :                 kfree(vma->pages);
     258                 :            :         }
     259                 :          0 :         vma->pages = NULL;
     260                 :            : 
     261                 :          0 :         memset(&vma->page_sizes, 0, sizeof(vma->page_sizes));
     262                 :          0 : }
     263                 :            : 
     264                 :            : static int __setup_page_dma(struct i915_address_space *vm,
     265                 :            :                             struct i915_page_dma *p,
     266                 :            :                             gfp_t gfp)
     267                 :            : {
     268                 :            :         p->page = vm_alloc_page(vm, gfp | I915_GFP_ALLOW_FAIL);
     269                 :            :         if (unlikely(!p->page))
     270                 :            :                 return -ENOMEM;
     271                 :            : 
     272                 :            :         p->daddr = dma_map_page_attrs(vm->dma,
     273                 :            :                                       p->page, 0, PAGE_SIZE,
     274                 :            :                                       PCI_DMA_BIDIRECTIONAL,
     275                 :            :                                       DMA_ATTR_SKIP_CPU_SYNC |
     276                 :            :                                       DMA_ATTR_NO_WARN);
     277                 :            :         if (unlikely(dma_mapping_error(vm->dma, p->daddr))) {
     278                 :            :                 vm_free_page(vm, p->page);
     279                 :            :                 return -ENOMEM;
     280                 :            :         }
     281                 :            : 
     282                 :            :         return 0;
     283                 :            : }
     284                 :            : 
     285                 :          0 : int setup_page_dma(struct i915_address_space *vm, struct i915_page_dma *p)
     286                 :            : {
     287                 :          0 :         return __setup_page_dma(vm, p, __GFP_HIGHMEM);
     288                 :            : }
     289                 :            : 
     290                 :          0 : void cleanup_page_dma(struct i915_address_space *vm, struct i915_page_dma *p)
     291                 :            : {
     292                 :          0 :         dma_unmap_page(vm->dma, p->daddr, PAGE_SIZE, PCI_DMA_BIDIRECTIONAL);
     293                 :          0 :         vm_free_page(vm, p->page);
     294                 :          0 : }
     295                 :            : 
     296                 :            : void
     297                 :          0 : fill_page_dma(const struct i915_page_dma *p, const u64 val, unsigned int count)
     298                 :            : {
     299                 :          0 :         kunmap_atomic(memset64(kmap_atomic(p->page), val, count));
     300                 :          0 : }
     301                 :            : 
     302                 :          0 : int setup_scratch_page(struct i915_address_space *vm, gfp_t gfp)
     303                 :            : {
     304                 :          0 :         unsigned long size;
     305                 :            : 
     306                 :            :         /*
     307                 :            :          * In order to utilize 64K pages for an object with a size < 2M, we will
     308                 :            :          * need to support a 64K scratch page, given that every 16th entry for a
     309                 :            :          * page-table operating in 64K mode must point to a properly aligned 64K
     310                 :            :          * region, including any PTEs which happen to point to scratch.
     311                 :            :          *
     312                 :            :          * This is only relevant for the 48b PPGTT where we support
     313                 :            :          * huge-gtt-pages, see also i915_vma_insert(). However, as we share the
     314                 :            :          * scratch (read-only) between all vm, we create one 64k scratch page
     315                 :            :          * for all.
     316                 :            :          */
     317                 :          0 :         size = I915_GTT_PAGE_SIZE_4K;
     318         [ #  # ]:          0 :         if (i915_vm_is_4lvl(vm) &&
     319         [ #  # ]:          0 :             HAS_PAGE_SIZES(vm->i915, I915_GTT_PAGE_SIZE_64K)) {
     320                 :          0 :                 size = I915_GTT_PAGE_SIZE_64K;
     321                 :          0 :                 gfp |= __GFP_NOWARN;
     322                 :            :         }
     323                 :          0 :         gfp |= __GFP_ZERO | __GFP_RETRY_MAYFAIL;
     324                 :            : 
     325                 :          0 :         do {
     326                 :          0 :                 unsigned int order = get_order(size);
     327                 :          0 :                 struct page *page;
     328                 :          0 :                 dma_addr_t addr;
     329                 :            : 
     330                 :          0 :                 page = alloc_pages(gfp, order);
     331         [ #  # ]:          0 :                 if (unlikely(!page))
     332                 :          0 :                         goto skip;
     333                 :            : 
     334                 :          0 :                 addr = dma_map_page_attrs(vm->dma,
     335                 :            :                                           page, 0, size,
     336                 :            :                                           PCI_DMA_BIDIRECTIONAL,
     337                 :            :                                           DMA_ATTR_SKIP_CPU_SYNC |
     338                 :            :                                           DMA_ATTR_NO_WARN);
     339         [ #  # ]:          0 :                 if (unlikely(dma_mapping_error(vm->dma, addr)))
     340                 :          0 :                         goto free_page;
     341                 :            : 
     342         [ #  # ]:          0 :                 if (unlikely(!IS_ALIGNED(addr, size)))
     343                 :          0 :                         goto unmap_page;
     344                 :            : 
     345                 :          0 :                 vm->scratch[0].base.page = page;
     346                 :          0 :                 vm->scratch[0].base.daddr = addr;
     347                 :          0 :                 vm->scratch_order = order;
     348                 :          0 :                 return 0;
     349                 :            : 
     350                 :            : unmap_page:
     351                 :          0 :                 dma_unmap_page(vm->dma, addr, size, PCI_DMA_BIDIRECTIONAL);
     352                 :          0 : free_page:
     353                 :          0 :                 __free_pages(page, order);
     354                 :          0 : skip:
     355         [ #  # ]:          0 :                 if (size == I915_GTT_PAGE_SIZE_4K)
     356                 :            :                         return -ENOMEM;
     357                 :            : 
     358                 :          0 :                 size = I915_GTT_PAGE_SIZE_4K;
     359                 :          0 :                 gfp &= ~__GFP_NOWARN;
     360                 :          0 :         } while (1);
     361                 :            : }
     362                 :            : 
     363                 :          0 : void cleanup_scratch_page(struct i915_address_space *vm)
     364                 :            : {
     365                 :          0 :         struct i915_page_dma *p = px_base(&vm->scratch[0]);
     366                 :          0 :         unsigned int order = vm->scratch_order;
     367                 :            : 
     368                 :          0 :         dma_unmap_page(vm->dma, p->daddr, BIT(order) << PAGE_SHIFT,
     369                 :            :                        PCI_DMA_BIDIRECTIONAL);
     370                 :          0 :         __free_pages(p->page, order);
     371                 :          0 : }
     372                 :            : 
     373                 :          0 : void free_scratch(struct i915_address_space *vm)
     374                 :            : {
     375                 :          0 :         int i;
     376                 :            : 
     377         [ #  # ]:          0 :         if (!px_dma(&vm->scratch[0])) /* set to 0 on clones */
     378                 :            :                 return;
     379                 :            : 
     380         [ #  # ]:          0 :         for (i = 1; i <= vm->top; i++) {
     381         [ #  # ]:          0 :                 if (!px_dma(&vm->scratch[i]))
     382                 :            :                         break;
     383                 :          0 :                 cleanup_page_dma(vm, px_base(&vm->scratch[i]));
     384                 :            :         }
     385                 :            : 
     386                 :          0 :         cleanup_scratch_page(vm);
     387                 :            : }
     388                 :            : 
     389                 :          0 : void gtt_write_workarounds(struct intel_gt *gt)
     390                 :            : {
     391                 :          0 :         struct drm_i915_private *i915 = gt->i915;
     392                 :          0 :         struct intel_uncore *uncore = gt->uncore;
     393                 :            : 
     394                 :            :         /*
     395                 :            :          * This function is for gtt related workarounds. This function is
     396                 :            :          * called on driver load and after a GPU reset, so you can place
     397                 :            :          * workarounds here even if they get overwritten by GPU reset.
     398                 :            :          */
     399                 :            :         /* WaIncreaseDefaultTLBEntries:chv,bdw,skl,bxt,kbl,glk,cfl,cnl,icl */
     400         [ #  # ]:          0 :         if (IS_BROADWELL(i915))
     401                 :          0 :                 intel_uncore_write(uncore,
     402                 :            :                                    GEN8_L3_LRA_1_GPGPU,
     403                 :            :                                    GEN8_L3_LRA_1_GPGPU_DEFAULT_VALUE_BDW);
     404         [ #  # ]:          0 :         else if (IS_CHERRYVIEW(i915))
     405                 :          0 :                 intel_uncore_write(uncore,
     406                 :            :                                    GEN8_L3_LRA_1_GPGPU,
     407                 :            :                                    GEN8_L3_LRA_1_GPGPU_DEFAULT_VALUE_CHV);
     408   [ #  #  #  # ]:          0 :         else if (IS_GEN9_LP(i915))
     409                 :          0 :                 intel_uncore_write(uncore,
     410                 :            :                                    GEN8_L3_LRA_1_GPGPU,
     411                 :            :                                    GEN9_L3_LRA_1_GPGPU_DEFAULT_VALUE_BXT);
     412         [ #  # ]:          0 :         else if (INTEL_GEN(i915) >= 9 && INTEL_GEN(i915) <= 11)
     413                 :          0 :                 intel_uncore_write(uncore,
     414                 :            :                                    GEN8_L3_LRA_1_GPGPU,
     415                 :            :                                    GEN9_L3_LRA_1_GPGPU_DEFAULT_VALUE_SKL);
     416                 :            : 
     417                 :            :         /*
     418                 :            :          * To support 64K PTEs we need to first enable the use of the
     419                 :            :          * Intermediate-Page-Size(IPS) bit of the PDE field via some magical
     420                 :            :          * mmio, otherwise the page-walker will simply ignore the IPS bit. This
     421                 :            :          * shouldn't be needed after GEN10.
     422                 :            :          *
     423                 :            :          * 64K pages were first introduced from BDW+, although technically they
     424                 :            :          * only *work* from gen9+. For pre-BDW we instead have the option for
     425                 :            :          * 32K pages, but we don't currently have any support for it in our
     426                 :            :          * driver.
     427                 :            :          */
     428         [ #  # ]:          0 :         if (HAS_PAGE_SIZES(i915, I915_GTT_PAGE_SIZE_64K) &&
     429         [ #  # ]:          0 :             INTEL_GEN(i915) <= 10)
     430                 :          0 :                 intel_uncore_rmw(uncore,
     431                 :          0 :                                  GEN8_GAMW_ECO_DEV_RW_IA,
     432                 :            :                                  0,
     433                 :            :                                  GAMW_ECO_ENABLE_64K_IPS_FIELD);
     434                 :            : 
     435         [ #  # ]:          0 :         if (IS_GEN_RANGE(i915, 8, 11)) {
     436                 :          0 :                 bool can_use_gtt_cache = true;
     437                 :            : 
     438                 :            :                 /*
     439                 :            :                  * According to the BSpec if we use 2M/1G pages then we also
     440                 :            :                  * need to disable the GTT cache. At least on BDW we can see
     441                 :            :                  * visual corruption when using 2M pages, and not disabling the
     442                 :            :                  * GTT cache.
     443                 :            :                  */
     444         [ #  # ]:          0 :                 if (HAS_PAGE_SIZES(i915, I915_GTT_PAGE_SIZE_2M))
     445                 :          0 :                         can_use_gtt_cache = false;
     446                 :            : 
     447                 :            :                 /* WaGttCachingOffByDefault */
     448                 :          0 :                 intel_uncore_write(uncore,
     449                 :            :                                    HSW_GTT_CACHE_EN,
     450                 :            :                                    can_use_gtt_cache ? GTT_CACHE_EN_ALL : 0);
     451   [ #  #  #  #  :          0 :                 WARN_ON_ONCE(can_use_gtt_cache &&
             #  #  #  # ]
     452                 :            :                              intel_uncore_read(uncore,
     453                 :            :                                                HSW_GTT_CACHE_EN) == 0);
     454                 :            :         }
     455                 :          0 : }
     456                 :            : 
     457                 :          0 : u64 gen8_pte_encode(dma_addr_t addr,
     458                 :            :                     enum i915_cache_level level,
     459                 :            :                     u32 flags)
     460                 :            : {
     461                 :          0 :         gen8_pte_t pte = addr | _PAGE_PRESENT | _PAGE_RW;
     462                 :            : 
     463         [ #  # ]:          0 :         if (unlikely(flags & PTE_READ_ONLY))
     464                 :          0 :                 pte &= ~_PAGE_RW;
     465                 :            : 
     466      [ #  #  # ]:          0 :         switch (level) {
     467                 :          0 :         case I915_CACHE_NONE:
     468                 :          0 :                 pte |= PPAT_UNCACHED;
     469                 :          0 :                 break;
     470                 :          0 :         case I915_CACHE_WT:
     471                 :          0 :                 pte |= PPAT_DISPLAY_ELLC;
     472                 :          0 :                 break;
     473                 :          0 :         default:
     474                 :          0 :                 pte |= PPAT_CACHED;
     475                 :          0 :                 break;
     476                 :            :         }
     477                 :            : 
     478                 :          0 :         return pte;
     479                 :            : }
     480                 :            : 
     481                 :          0 : static void tgl_setup_private_ppat(struct intel_uncore *uncore)
     482                 :            : {
     483                 :            :         /* TGL doesn't support LLC or AGE settings */
     484                 :          0 :         intel_uncore_write(uncore, GEN12_PAT_INDEX(0), GEN8_PPAT_WB);
     485                 :          0 :         intel_uncore_write(uncore, GEN12_PAT_INDEX(1), GEN8_PPAT_WC);
     486                 :          0 :         intel_uncore_write(uncore, GEN12_PAT_INDEX(2), GEN8_PPAT_WT);
     487                 :          0 :         intel_uncore_write(uncore, GEN12_PAT_INDEX(3), GEN8_PPAT_UC);
     488                 :          0 :         intel_uncore_write(uncore, GEN12_PAT_INDEX(4), GEN8_PPAT_WB);
     489                 :          0 :         intel_uncore_write(uncore, GEN12_PAT_INDEX(5), GEN8_PPAT_WB);
     490                 :          0 :         intel_uncore_write(uncore, GEN12_PAT_INDEX(6), GEN8_PPAT_WB);
     491                 :          0 :         intel_uncore_write(uncore, GEN12_PAT_INDEX(7), GEN8_PPAT_WB);
     492                 :          0 : }
     493                 :            : 
     494                 :          0 : static void cnl_setup_private_ppat(struct intel_uncore *uncore)
     495                 :            : {
     496                 :          0 :         intel_uncore_write(uncore,
     497                 :            :                            GEN10_PAT_INDEX(0),
     498                 :            :                            GEN8_PPAT_WB | GEN8_PPAT_LLC);
     499                 :          0 :         intel_uncore_write(uncore,
     500                 :            :                            GEN10_PAT_INDEX(1),
     501                 :            :                            GEN8_PPAT_WC | GEN8_PPAT_LLCELLC);
     502                 :          0 :         intel_uncore_write(uncore,
     503                 :            :                            GEN10_PAT_INDEX(2),
     504                 :            :                            GEN8_PPAT_WT | GEN8_PPAT_LLCELLC);
     505                 :          0 :         intel_uncore_write(uncore,
     506                 :            :                            GEN10_PAT_INDEX(3),
     507                 :            :                            GEN8_PPAT_UC);
     508                 :          0 :         intel_uncore_write(uncore,
     509                 :            :                            GEN10_PAT_INDEX(4),
     510                 :            :                            GEN8_PPAT_WB | GEN8_PPAT_LLCELLC | GEN8_PPAT_AGE(0));
     511                 :          0 :         intel_uncore_write(uncore,
     512                 :            :                            GEN10_PAT_INDEX(5),
     513                 :            :                            GEN8_PPAT_WB | GEN8_PPAT_LLCELLC | GEN8_PPAT_AGE(1));
     514                 :          0 :         intel_uncore_write(uncore,
     515                 :            :                            GEN10_PAT_INDEX(6),
     516                 :            :                            GEN8_PPAT_WB | GEN8_PPAT_LLCELLC | GEN8_PPAT_AGE(2));
     517                 :          0 :         intel_uncore_write(uncore,
     518                 :            :                            GEN10_PAT_INDEX(7),
     519                 :            :                            GEN8_PPAT_WB | GEN8_PPAT_LLCELLC | GEN8_PPAT_AGE(3));
     520                 :          0 : }
     521                 :            : 
     522                 :            : /*
     523                 :            :  * The GGTT and PPGTT need a private PPAT setup in order to handle cacheability
     524                 :            :  * bits. When using advanced contexts each context stores its own PAT, but
     525                 :            :  * writing this data shouldn't be harmful even in those cases.
     526                 :            :  */
     527                 :          0 : static void bdw_setup_private_ppat(struct intel_uncore *uncore)
     528                 :            : {
     529                 :          0 :         u64 pat;
     530                 :            : 
     531                 :          0 :         pat = GEN8_PPAT(0, GEN8_PPAT_WB | GEN8_PPAT_LLC) |      /* for normal objects, no eLLC */
     532                 :            :               GEN8_PPAT(1, GEN8_PPAT_WC | GEN8_PPAT_LLCELLC) |  /* for something pointing to ptes? */
     533                 :            :               GEN8_PPAT(2, GEN8_PPAT_WT | GEN8_PPAT_LLCELLC) |  /* for scanout with eLLC */
     534                 :            :               GEN8_PPAT(3, GEN8_PPAT_UC) |                      /* Uncached objects, mostly for scanout */
     535                 :            :               GEN8_PPAT(4, GEN8_PPAT_WB | GEN8_PPAT_LLCELLC | GEN8_PPAT_AGE(0)) |
     536                 :            :               GEN8_PPAT(5, GEN8_PPAT_WB | GEN8_PPAT_LLCELLC | GEN8_PPAT_AGE(1)) |
     537                 :            :               GEN8_PPAT(6, GEN8_PPAT_WB | GEN8_PPAT_LLCELLC | GEN8_PPAT_AGE(2)) |
     538                 :            :               GEN8_PPAT(7, GEN8_PPAT_WB | GEN8_PPAT_LLCELLC | GEN8_PPAT_AGE(3));
     539                 :            : 
     540                 :          0 :         intel_uncore_write(uncore, GEN8_PRIVATE_PAT_LO, lower_32_bits(pat));
     541                 :          0 :         intel_uncore_write(uncore, GEN8_PRIVATE_PAT_HI, upper_32_bits(pat));
     542                 :          0 : }
     543                 :            : 
     544                 :          0 : static void chv_setup_private_ppat(struct intel_uncore *uncore)
     545                 :            : {
     546                 :          0 :         u64 pat;
     547                 :            : 
     548                 :            :         /*
     549                 :            :          * Map WB on BDW to snooped on CHV.
     550                 :            :          *
     551                 :            :          * Only the snoop bit has meaning for CHV, the rest is
     552                 :            :          * ignored.
     553                 :            :          *
     554                 :            :          * The hardware will never snoop for certain types of accesses:
     555                 :            :          * - CPU GTT (GMADR->GGTT->no snoop->memory)
     556                 :            :          * - PPGTT page tables
     557                 :            :          * - some other special cycles
     558                 :            :          *
     559                 :            :          * As with BDW, we also need to consider the following for GT accesses:
     560                 :            :          * "For GGTT, there is NO pat_sel[2:0] from the entry,
     561                 :            :          * so RTL will always use the value corresponding to
     562                 :            :          * pat_sel = 000".
     563                 :            :          * Which means we must set the snoop bit in PAT entry 0
     564                 :            :          * in order to keep the global status page working.
     565                 :            :          */
     566                 :            : 
     567                 :          0 :         pat = GEN8_PPAT(0, CHV_PPAT_SNOOP) |
     568                 :            :               GEN8_PPAT(1, 0) |
     569                 :            :               GEN8_PPAT(2, 0) |
     570                 :            :               GEN8_PPAT(3, 0) |
     571                 :            :               GEN8_PPAT(4, CHV_PPAT_SNOOP) |
     572                 :            :               GEN8_PPAT(5, CHV_PPAT_SNOOP) |
     573                 :            :               GEN8_PPAT(6, CHV_PPAT_SNOOP) |
     574                 :            :               GEN8_PPAT(7, CHV_PPAT_SNOOP);
     575                 :            : 
     576                 :          0 :         intel_uncore_write(uncore, GEN8_PRIVATE_PAT_LO, lower_32_bits(pat));
     577                 :          0 :         intel_uncore_write(uncore, GEN8_PRIVATE_PAT_HI, upper_32_bits(pat));
     578                 :          0 : }
     579                 :            : 
     580                 :          0 : void setup_private_pat(struct intel_uncore *uncore)
     581                 :            : {
     582                 :          0 :         struct drm_i915_private *i915 = uncore->i915;
     583                 :            : 
     584                 :          0 :         GEM_BUG_ON(INTEL_GEN(i915) < 8);
     585                 :            : 
     586         [ #  # ]:          0 :         if (INTEL_GEN(i915) >= 12)
     587                 :          0 :                 tgl_setup_private_ppat(uncore);
     588         [ #  # ]:          0 :         else if (INTEL_GEN(i915) >= 10)
     589                 :          0 :                 cnl_setup_private_ppat(uncore);
     590   [ #  #  #  #  :          0 :         else if (IS_CHERRYVIEW(i915) || IS_GEN9_LP(i915))
                   #  # ]
     591                 :          0 :                 chv_setup_private_ppat(uncore);
     592                 :            :         else
     593                 :          0 :                 bdw_setup_private_ppat(uncore);
     594                 :          0 : }
     595                 :            : 
     596                 :            : #if IS_ENABLED(CONFIG_DRM_I915_SELFTEST)
     597                 :            : #include "selftests/mock_gtt.c"
     598                 :            : #endif

Generated by: LCOV version 1.14