1 1.4 riastrad /* $NetBSD: intel_ppgtt.c,v 1.4 2021/12/19 12:07:47 riastradh Exp $ */ 2 1.1 riastrad 3 1.1 riastrad // SPDX-License-Identifier: MIT 4 1.1 riastrad /* 5 1.1 riastrad * Copyright 2020 Intel Corporation 6 1.1 riastrad */ 7 1.1 riastrad 8 1.1 riastrad #include <sys/cdefs.h> 9 1.4 riastrad __KERNEL_RCSID(0, "$NetBSD: intel_ppgtt.c,v 1.4 2021/12/19 12:07:47 riastradh Exp $"); 10 1.1 riastrad 11 1.1 riastrad #include <linux/slab.h> 12 1.1 riastrad 13 1.1 riastrad #include "i915_trace.h" 14 1.1 riastrad #include "intel_gtt.h" 15 1.1 riastrad #include "gen6_ppgtt.h" 16 1.1 riastrad #include "gen8_ppgtt.h" 17 1.1 riastrad 18 1.1 riastrad struct i915_page_table *alloc_pt(struct i915_address_space *vm) 19 1.1 riastrad { 20 1.1 riastrad struct i915_page_table *pt; 21 1.1 riastrad 22 1.1 riastrad pt = kmalloc(sizeof(*pt), I915_GFP_ALLOW_FAIL); 23 1.1 riastrad if (unlikely(!pt)) 24 1.1 riastrad return ERR_PTR(-ENOMEM); 25 1.1 riastrad 26 1.1 riastrad if (unlikely(setup_page_dma(vm, &pt->base))) { 27 1.1 riastrad kfree(pt); 28 1.1 riastrad return ERR_PTR(-ENOMEM); 29 1.1 riastrad } 30 1.1 riastrad 31 1.1 riastrad atomic_set(&pt->used, 0); 32 1.1 riastrad return pt; 33 1.1 riastrad } 34 1.1 riastrad 35 1.1 riastrad struct i915_page_directory *__alloc_pd(size_t sz) 36 1.1 riastrad { 37 1.1 riastrad struct i915_page_directory *pd; 38 1.1 riastrad 39 1.1 riastrad pd = kzalloc(sz, I915_GFP_ALLOW_FAIL); 40 1.1 riastrad if (unlikely(!pd)) 41 1.1 riastrad return NULL; 42 1.1 riastrad 43 1.1 riastrad spin_lock_init(&pd->lock); 44 1.1 riastrad return pd; 45 1.1 riastrad } 46 1.1 riastrad 47 1.1 riastrad struct i915_page_directory *alloc_pd(struct i915_address_space *vm) 48 1.1 riastrad { 49 1.1 riastrad struct i915_page_directory *pd; 50 1.1 riastrad 51 1.1 riastrad pd = __alloc_pd(sizeof(*pd)); 52 1.1 riastrad if (unlikely(!pd)) 53 1.1 riastrad return ERR_PTR(-ENOMEM); 54 1.1 riastrad 55 1.1 riastrad if (unlikely(setup_page_dma(vm, px_base(pd)))) { 56 1.4 riastrad spin_lock_destroy(&pd->lock); 57 1.1 riastrad kfree(pd); 58 1.1 riastrad return ERR_PTR(-ENOMEM); 59 1.1 riastrad } 60 1.1 riastrad 61 1.1 riastrad return pd; 62 1.1 riastrad } 63 1.1 riastrad 64 1.1 riastrad void free_pd(struct i915_address_space *vm, struct i915_page_dma *pd) 65 1.1 riastrad { 66 1.1 riastrad cleanup_page_dma(vm, pd); 67 1.1 riastrad kfree(pd); 68 1.1 riastrad } 69 1.1 riastrad 70 1.1 riastrad static inline void 71 1.1 riastrad write_dma_entry(struct i915_page_dma * const pdma, 72 1.1 riastrad const unsigned short idx, 73 1.1 riastrad const u64 encoded_entry) 74 1.1 riastrad { 75 1.1 riastrad u64 * const vaddr = kmap_atomic(pdma->page); 76 1.1 riastrad 77 1.1 riastrad vaddr[idx] = encoded_entry; 78 1.1 riastrad kunmap_atomic(vaddr); 79 1.1 riastrad } 80 1.1 riastrad 81 1.1 riastrad void 82 1.1 riastrad __set_pd_entry(struct i915_page_directory * const pd, 83 1.1 riastrad const unsigned short idx, 84 1.1 riastrad struct i915_page_dma * const to, 85 1.1 riastrad u64 (*encode)(const dma_addr_t, const enum i915_cache_level)) 86 1.1 riastrad { 87 1.1 riastrad /* Each thread pre-pins the pd, and we may have a thread per pde. */ 88 1.1 riastrad GEM_BUG_ON(atomic_read(px_used(pd)) > NALLOC * ARRAY_SIZE(pd->entry)); 89 1.1 riastrad 90 1.1 riastrad atomic_inc(px_used(pd)); 91 1.1 riastrad pd->entry[idx] = to; 92 1.3 riastrad #ifdef __NetBSD__ 93 1.3 riastrad write_dma_entry(px_base(pd), idx, encode(to->map->dm_segs[0].ds_addr, I915_CACHE_LLC)); 94 1.3 riastrad #else 95 1.1 riastrad write_dma_entry(px_base(pd), idx, encode(to->daddr, I915_CACHE_LLC)); 96 1.3 riastrad #endif 97 1.1 riastrad } 98 1.1 riastrad 99 1.1 riastrad void 100 1.1 riastrad clear_pd_entry(struct i915_page_directory * const pd, 101 1.1 riastrad const unsigned short idx, 102 1.1 riastrad const struct i915_page_scratch * const scratch) 103 1.1 riastrad { 104 1.1 riastrad GEM_BUG_ON(atomic_read(px_used(pd)) == 0); 105 1.1 riastrad 106 1.1 riastrad write_dma_entry(px_base(pd), idx, scratch->encode); 107 1.1 riastrad pd->entry[idx] = NULL; 108 1.1 riastrad atomic_dec(px_used(pd)); 109 1.1 riastrad } 110 1.1 riastrad 111 1.1 riastrad bool 112 1.1 riastrad release_pd_entry(struct i915_page_directory * const pd, 113 1.1 riastrad const unsigned short idx, 114 1.1 riastrad struct i915_page_table * const pt, 115 1.1 riastrad const struct i915_page_scratch * const scratch) 116 1.1 riastrad { 117 1.1 riastrad bool free = false; 118 1.1 riastrad 119 1.1 riastrad if (atomic_add_unless(&pt->used, -1, 1)) 120 1.1 riastrad return false; 121 1.1 riastrad 122 1.1 riastrad spin_lock(&pd->lock); 123 1.1 riastrad if (atomic_dec_and_test(&pt->used)) { 124 1.1 riastrad clear_pd_entry(pd, idx, scratch); 125 1.1 riastrad free = true; 126 1.1 riastrad } 127 1.1 riastrad spin_unlock(&pd->lock); 128 1.1 riastrad 129 1.1 riastrad return free; 130 1.1 riastrad } 131 1.1 riastrad 132 1.1 riastrad int i915_ppgtt_init_hw(struct intel_gt *gt) 133 1.1 riastrad { 134 1.1 riastrad struct drm_i915_private *i915 = gt->i915; 135 1.1 riastrad 136 1.1 riastrad gtt_write_workarounds(gt); 137 1.1 riastrad 138 1.1 riastrad if (IS_GEN(i915, 6)) 139 1.1 riastrad gen6_ppgtt_enable(gt); 140 1.1 riastrad else if (IS_GEN(i915, 7)) 141 1.1 riastrad gen7_ppgtt_enable(gt); 142 1.1 riastrad 143 1.1 riastrad return 0; 144 1.1 riastrad } 145 1.1 riastrad 146 1.1 riastrad static struct i915_ppgtt * 147 1.1 riastrad __ppgtt_create(struct intel_gt *gt) 148 1.1 riastrad { 149 1.1 riastrad if (INTEL_GEN(gt->i915) < 8) 150 1.1 riastrad return gen6_ppgtt_create(gt); 151 1.1 riastrad else 152 1.1 riastrad return gen8_ppgtt_create(gt); 153 1.1 riastrad } 154 1.1 riastrad 155 1.1 riastrad struct i915_ppgtt *i915_ppgtt_create(struct intel_gt *gt) 156 1.1 riastrad { 157 1.1 riastrad struct i915_ppgtt *ppgtt; 158 1.1 riastrad 159 1.1 riastrad ppgtt = __ppgtt_create(gt); 160 1.1 riastrad if (IS_ERR(ppgtt)) 161 1.1 riastrad return ppgtt; 162 1.1 riastrad 163 1.1 riastrad trace_i915_ppgtt_create(&ppgtt->vm); 164 1.1 riastrad 165 1.1 riastrad return ppgtt; 166 1.1 riastrad } 167 1.1 riastrad 168 1.1 riastrad static int ppgtt_bind_vma(struct i915_vma *vma, 169 1.1 riastrad enum i915_cache_level cache_level, 170 1.1 riastrad u32 flags) 171 1.1 riastrad { 172 1.1 riastrad u32 pte_flags; 173 1.1 riastrad int err; 174 1.1 riastrad 175 1.1 riastrad if (flags & I915_VMA_ALLOC) { 176 1.1 riastrad err = vma->vm->allocate_va_range(vma->vm, 177 1.1 riastrad vma->node.start, vma->size); 178 1.1 riastrad if (err) 179 1.1 riastrad return err; 180 1.1 riastrad 181 1.1 riastrad set_bit(I915_VMA_ALLOC_BIT, __i915_vma_flags(vma)); 182 1.1 riastrad } 183 1.1 riastrad 184 1.1 riastrad /* Applicable to VLV, and gen8+ */ 185 1.1 riastrad pte_flags = 0; 186 1.1 riastrad if (i915_gem_object_is_readonly(vma->obj)) 187 1.1 riastrad pte_flags |= PTE_READ_ONLY; 188 1.1 riastrad 189 1.1 riastrad GEM_BUG_ON(!test_bit(I915_VMA_ALLOC_BIT, __i915_vma_flags(vma))); 190 1.1 riastrad vma->vm->insert_entries(vma->vm, vma, cache_level, pte_flags); 191 1.1 riastrad wmb(); 192 1.1 riastrad 193 1.1 riastrad return 0; 194 1.1 riastrad } 195 1.1 riastrad 196 1.1 riastrad static void ppgtt_unbind_vma(struct i915_vma *vma) 197 1.1 riastrad { 198 1.1 riastrad if (test_and_clear_bit(I915_VMA_ALLOC_BIT, __i915_vma_flags(vma))) 199 1.1 riastrad vma->vm->clear_range(vma->vm, vma->node.start, vma->size); 200 1.1 riastrad } 201 1.1 riastrad 202 1.1 riastrad int ppgtt_set_pages(struct i915_vma *vma) 203 1.1 riastrad { 204 1.1 riastrad GEM_BUG_ON(vma->pages); 205 1.1 riastrad 206 1.1 riastrad vma->pages = vma->obj->mm.pages; 207 1.1 riastrad 208 1.1 riastrad vma->page_sizes = vma->obj->mm.page_sizes; 209 1.1 riastrad 210 1.1 riastrad return 0; 211 1.1 riastrad } 212 1.1 riastrad 213 1.1 riastrad void ppgtt_init(struct i915_ppgtt *ppgtt, struct intel_gt *gt) 214 1.1 riastrad { 215 1.1 riastrad struct drm_i915_private *i915 = gt->i915; 216 1.1 riastrad 217 1.1 riastrad ppgtt->vm.gt = gt; 218 1.1 riastrad ppgtt->vm.i915 = i915; 219 1.3 riastrad #ifdef __NetBSD__ 220 1.3 riastrad ppgtt->vm.dmat = i915->drm.dmat; 221 1.3 riastrad #else 222 1.1 riastrad ppgtt->vm.dma = &i915->drm.pdev->dev; 223 1.3 riastrad #endif 224 1.1 riastrad ppgtt->vm.total = BIT_ULL(INTEL_INFO(i915)->ppgtt_size); 225 1.1 riastrad 226 1.1 riastrad i915_address_space_init(&ppgtt->vm, VM_CLASS_PPGTT); 227 1.1 riastrad 228 1.1 riastrad ppgtt->vm.vma_ops.bind_vma = ppgtt_bind_vma; 229 1.1 riastrad ppgtt->vm.vma_ops.unbind_vma = ppgtt_unbind_vma; 230 1.1 riastrad ppgtt->vm.vma_ops.set_pages = ppgtt_set_pages; 231 1.1 riastrad ppgtt->vm.vma_ops.clear_pages = clear_pages; 232 1.1 riastrad } 233