xref: /linux/drivers/gpu/drm/xe/xe_lmtt.c (revision 3c2fe27971c3c9cc27de6e369385f6428db6c0b5)
1 // SPDX-License-Identifier: MIT
2 /*
3  * Copyright © 2023 Intel Corporation
4  */
5 
6 #include <linux/align.h>
7 
8 #include <drm/drm_managed.h>
9 
10 #include "regs/xe_gt_regs.h"
11 
12 #include "xe_assert.h"
13 #include "xe_bo.h"
14 #include "xe_lmtt.h"
15 #include "xe_map.h"
16 #include "xe_mmio.h"
17 #include "xe_res_cursor.h"
18 #include "xe_sriov.h"
19 #include "xe_sriov_printk.h"
20 
21 /**
22  * DOC: Local Memory Translation Table
23  *
24  * The Local Memory Translation Table (LMTT) provides additional abstraction
25  * when Virtual Function (VF) is accessing device Local Memory (VRAM).
26  *
27  * The Root LMTT Page Directory contains one entry for each VF. Entries are
28  * indexed by the function number (1-based, index 0 is unused).
29  *
30  * See `Two-Level LMTT Structure`_ and `Multi-Level LMTT Structure`_.
31  */
32 
33 #define lmtt_assert(lmtt, condition)	xe_tile_assert(lmtt_to_tile(lmtt), condition)
34 #define lmtt_debug(lmtt, msg...)	xe_sriov_dbg_verbose(lmtt_to_xe(lmtt), "LMTT: " msg)
35 
xe_has_multi_level_lmtt(struct xe_device * xe)36 static bool xe_has_multi_level_lmtt(struct xe_device *xe)
37 {
38 	return GRAPHICS_VERx100(xe) >= 1260;
39 }
40 
lmtt_to_tile(struct xe_lmtt * lmtt)41 static struct xe_tile *lmtt_to_tile(struct xe_lmtt *lmtt)
42 {
43 	return container_of(lmtt, struct xe_tile, sriov.pf.lmtt);
44 }
45 
lmtt_to_xe(struct xe_lmtt * lmtt)46 static struct xe_device *lmtt_to_xe(struct xe_lmtt *lmtt)
47 {
48 	return tile_to_xe(lmtt_to_tile(lmtt));
49 }
50 
lmtt_page_size(struct xe_lmtt * lmtt)51 static u64 lmtt_page_size(struct xe_lmtt *lmtt)
52 {
53 	return BIT_ULL(lmtt->ops->lmtt_pte_shift(0));
54 }
55 
lmtt_pt_alloc(struct xe_lmtt * lmtt,unsigned int level)56 static struct xe_lmtt_pt *lmtt_pt_alloc(struct xe_lmtt *lmtt, unsigned int level)
57 {
58 	unsigned int num_entries = level ? lmtt->ops->lmtt_pte_num(level) : 0;
59 	struct xe_lmtt_pt *pt;
60 	struct xe_bo *bo;
61 	int err;
62 
63 	pt = kzalloc(struct_size(pt, entries, num_entries), GFP_KERNEL);
64 	if (!pt) {
65 		err = -ENOMEM;
66 		goto out;
67 	}
68 
69 	bo = xe_bo_create_pin_map(lmtt_to_xe(lmtt), lmtt_to_tile(lmtt), NULL,
70 				  PAGE_ALIGN(lmtt->ops->lmtt_pte_size(level) *
71 					     lmtt->ops->lmtt_pte_num(level)),
72 				  ttm_bo_type_kernel,
73 				  XE_BO_FLAG_VRAM_IF_DGFX(lmtt_to_tile(lmtt)) |
74 				  XE_BO_FLAG_NEEDS_64K);
75 	if (IS_ERR(bo)) {
76 		err = PTR_ERR(bo);
77 		goto out_free_pt;
78 	}
79 
80 	lmtt_assert(lmtt, xe_bo_is_vram(bo));
81 	lmtt_debug(lmtt, "level=%u addr=%#llx\n", level, (u64)xe_bo_main_addr(bo, XE_PAGE_SIZE));
82 
83 	xe_map_memset(lmtt_to_xe(lmtt), &bo->vmap, 0, 0, bo->size);
84 
85 	pt->level = level;
86 	pt->bo = bo;
87 	return pt;
88 
89 out_free_pt:
90 	kfree(pt);
91 out:
92 	return ERR_PTR(err);
93 }
94 
lmtt_pt_free(struct xe_lmtt_pt * pt)95 static void lmtt_pt_free(struct xe_lmtt_pt *pt)
96 {
97 	lmtt_debug(&pt->bo->tile->sriov.pf.lmtt, "level=%u addr=%llx\n",
98 		   pt->level, (u64)xe_bo_main_addr(pt->bo, XE_PAGE_SIZE));
99 
100 	xe_bo_unpin_map_no_vm(pt->bo);
101 	kfree(pt);
102 }
103 
lmtt_init_pd(struct xe_lmtt * lmtt)104 static int lmtt_init_pd(struct xe_lmtt *lmtt)
105 {
106 	struct xe_lmtt_pt *pd;
107 
108 	lmtt_assert(lmtt, !lmtt->pd);
109 	lmtt_assert(lmtt, lmtt->ops->lmtt_root_pd_level());
110 
111 	pd = lmtt_pt_alloc(lmtt, lmtt->ops->lmtt_root_pd_level());
112 	if (IS_ERR(pd))
113 		return PTR_ERR(pd);
114 
115 	lmtt->pd = pd;
116 	return 0;
117 }
118 
lmtt_fini_pd(struct xe_lmtt * lmtt)119 static void lmtt_fini_pd(struct xe_lmtt *lmtt)
120 {
121 	struct xe_lmtt_pt *pd = lmtt->pd;
122 	unsigned int num_entries = lmtt->ops->lmtt_pte_num(pd->level);
123 	unsigned int n = 0;
124 
125 	/* make sure we don't leak */
126 	for (n = 0; n < num_entries; n++)
127 		lmtt_assert(lmtt, !pd->entries[n]);
128 
129 	lmtt->pd = NULL;
130 	lmtt_pt_free(pd);
131 }
132 
fini_lmtt(struct drm_device * drm,void * arg)133 static void fini_lmtt(struct drm_device *drm, void *arg)
134 {
135 	struct xe_lmtt *lmtt = arg;
136 
137 	lmtt_assert(lmtt, !(!!lmtt->ops ^ !!lmtt->pd));
138 
139 	if (!lmtt->pd)
140 		return;
141 
142 	lmtt_fini_pd(lmtt);
143 	lmtt->ops = NULL;
144 }
145 
146 /**
147  * xe_lmtt_init - LMTT software initialization.
148  * @lmtt: the &xe_lmtt to initialize
149  *
150  * The LMTT initialization requires two steps.
151  *
152  * The xe_lmtt_init() checks if LMTT is required on current device and selects
153  * and initialize proper variant of the LMTT Root Directory. Currently supported
154  * variants are `Two-Level LMTT Structure`_ and `Multi-Level LMTT Structure`_.
155  *
156  * In next step xe_lmtt_init_hw() will register this directory on the hardware.
157  *
158  * Notes:
159  * The LMTT allocations are managed and will be implicitly released on driver unload.
160  * This function shall be called only once and only when running as a PF driver.
161  * Any LMTT initialization failure should block VFs enabling.
162  *
163  * Return: 0 on success or a negative error code on failure.
164  */
xe_lmtt_init(struct xe_lmtt * lmtt)165 int xe_lmtt_init(struct xe_lmtt *lmtt)
166 {
167 	struct xe_device *xe = lmtt_to_xe(lmtt);
168 	int err;
169 
170 	lmtt_assert(lmtt, IS_SRIOV_PF(xe));
171 	lmtt_assert(lmtt, !lmtt->ops);
172 
173 	if (!xe_device_has_lmtt(xe))
174 		return 0;
175 
176 	if (xe_has_multi_level_lmtt(xe))
177 		lmtt->ops = &lmtt_ml_ops;
178 	else
179 		lmtt->ops = &lmtt_2l_ops;
180 
181 	err = lmtt_init_pd(lmtt);
182 	if (unlikely(err))
183 		goto fail;
184 
185 	return drmm_add_action_or_reset(&xe->drm, fini_lmtt, lmtt);
186 
187 fail:
188 	lmtt->ops = NULL;
189 	return err;
190 }
191 
lmtt_setup_dir_ptr(struct xe_lmtt * lmtt)192 static void lmtt_setup_dir_ptr(struct xe_lmtt *lmtt)
193 {
194 	struct xe_tile *tile = lmtt_to_tile(lmtt);
195 	struct xe_device *xe = tile_to_xe(tile);
196 	dma_addr_t offset = xe_bo_main_addr(lmtt->pd->bo, XE_PAGE_SIZE);
197 
198 	lmtt_debug(lmtt, "DIR offset %pad\n", &offset);
199 	lmtt_assert(lmtt, xe_bo_is_vram(lmtt->pd->bo));
200 	lmtt_assert(lmtt, IS_ALIGNED(offset, SZ_64K));
201 
202 	xe_mmio_write32(&tile->mmio,
203 			GRAPHICS_VER(xe) >= 20 ? XE2_LMEM_CFG : LMEM_CFG,
204 			LMEM_EN | REG_FIELD_PREP(LMTT_DIR_PTR, offset / SZ_64K));
205 }
206 
207 /**
208  * xe_lmtt_init_hw - Perform LMTT hardware initialization.
209  * @lmtt: the &xe_lmtt to initialize
210  *
211  * This function is a second step of the LMTT initialization.
212  * This function registers LMTT Root Directory prepared in xe_lmtt_init().
213  *
214  * This function shall be called after every hardware reset.
215  * This function shall be called only when running as a PF driver.
216  */
xe_lmtt_init_hw(struct xe_lmtt * lmtt)217 void xe_lmtt_init_hw(struct xe_lmtt *lmtt)
218 {
219 	if (!lmtt->pd)
220 		return;
221 
222 	lmtt_setup_dir_ptr(lmtt);
223 }
224 
lmtt_write_pte(struct xe_lmtt * lmtt,struct xe_lmtt_pt * pt,u64 pte,unsigned int idx)225 static void lmtt_write_pte(struct xe_lmtt *lmtt, struct xe_lmtt_pt *pt,
226 			   u64 pte, unsigned int idx)
227 {
228 	unsigned int level = pt->level;
229 
230 	lmtt_assert(lmtt, idx <= lmtt->ops->lmtt_pte_num(level));
231 	lmtt_debug(lmtt, "WRITE level=%u index=%u pte=%#llx\n", level, idx, pte);
232 
233 	switch (lmtt->ops->lmtt_pte_size(level)) {
234 	case sizeof(u32):
235 		lmtt_assert(lmtt, !overflows_type(pte, u32));
236 		lmtt_assert(lmtt, !pte || !iosys_map_rd(&pt->bo->vmap, idx * sizeof(u32), u32));
237 
238 		xe_map_wr(lmtt_to_xe(lmtt), &pt->bo->vmap, idx * sizeof(u32), u32, pte);
239 		break;
240 	case sizeof(u64):
241 		lmtt_assert(lmtt, !pte || !iosys_map_rd(&pt->bo->vmap, idx * sizeof(u64), u64));
242 
243 		xe_map_wr(lmtt_to_xe(lmtt), &pt->bo->vmap, idx * sizeof(u64), u64, pte);
244 		break;
245 	default:
246 		lmtt_assert(lmtt, !!!"invalid pte size");
247 	}
248 }
249 
lmtt_destroy_pt(struct xe_lmtt * lmtt,struct xe_lmtt_pt * pd)250 static void lmtt_destroy_pt(struct xe_lmtt *lmtt, struct xe_lmtt_pt *pd)
251 {
252 	unsigned int num_entries = pd->level ? lmtt->ops->lmtt_pte_num(pd->level) : 0;
253 	struct xe_lmtt_pt *pt;
254 	unsigned int i;
255 
256 	for (i = 0; i < num_entries; i++) {
257 		pt = pd->entries[i];
258 		pd->entries[i] = NULL;
259 		if (!pt)
260 			continue;
261 
262 		lmtt_destroy_pt(lmtt, pt);
263 	}
264 
265 	lmtt_pt_free(pd);
266 }
267 
lmtt_drop_pages(struct xe_lmtt * lmtt,unsigned int vfid)268 static void lmtt_drop_pages(struct xe_lmtt *lmtt, unsigned int vfid)
269 {
270 	struct xe_lmtt_pt *pd = lmtt->pd;
271 	struct xe_lmtt_pt *pt;
272 
273 	pt = pd->entries[vfid];
274 	pd->entries[vfid] = NULL;
275 	if (!pt)
276 		return;
277 
278 	lmtt_write_pte(lmtt, pd, LMTT_PTE_INVALID, vfid);
279 
280 	lmtt_assert(lmtt, pd->level > 0);
281 	lmtt_assert(lmtt, pt->level == pd->level - 1);
282 	lmtt_destroy_pt(lmtt, pt);
283 }
284 
__lmtt_alloc_range(struct xe_lmtt * lmtt,struct xe_lmtt_pt * pd,u64 start,u64 end)285 static int __lmtt_alloc_range(struct xe_lmtt *lmtt, struct xe_lmtt_pt *pd,
286 			      u64 start, u64 end)
287 {
288 	u64 pte_addr_shift = BIT_ULL(lmtt->ops->lmtt_pte_shift(pd->level));
289 	u64 offset;
290 	int err;
291 
292 	lmtt_assert(lmtt, pd->level > 0);
293 
294 	offset = start;
295 	while (offset < end) {
296 		struct xe_lmtt_pt *pt;
297 		u64 next, pde, pt_addr;
298 		unsigned int idx;
299 
300 		pt = lmtt_pt_alloc(lmtt, pd->level - 1);
301 		if (IS_ERR(pt))
302 			return PTR_ERR(pt);
303 
304 		pt_addr = xe_bo_main_addr(pt->bo, XE_PAGE_SIZE);
305 
306 		idx = lmtt->ops->lmtt_pte_index(offset, pd->level);
307 		pde = lmtt->ops->lmtt_pte_encode(pt_addr, pd->level);
308 
309 		lmtt_write_pte(lmtt, pd, pde, idx);
310 
311 		pd->entries[idx] = pt;
312 
313 		next = min(end, round_up(offset + 1, pte_addr_shift));
314 
315 		if (pt->level != 0) {
316 			err = __lmtt_alloc_range(lmtt, pt, offset, next);
317 			if (err)
318 				return err;
319 		}
320 
321 		offset = next;
322 	}
323 
324 	return 0;
325 }
326 
lmtt_alloc_range(struct xe_lmtt * lmtt,unsigned int vfid,u64 start,u64 end)327 static int lmtt_alloc_range(struct xe_lmtt *lmtt, unsigned int vfid, u64 start, u64 end)
328 {
329 	struct xe_lmtt_pt *pd = lmtt->pd;
330 	struct xe_lmtt_pt *pt;
331 	u64 pt_addr;
332 	u64 pde;
333 	int err;
334 
335 	lmtt_assert(lmtt, pd->level > 0);
336 	lmtt_assert(lmtt, vfid <= lmtt->ops->lmtt_pte_num(pd->level));
337 	lmtt_assert(lmtt, IS_ALIGNED(start, lmtt_page_size(lmtt)));
338 	lmtt_assert(lmtt, IS_ALIGNED(end, lmtt_page_size(lmtt)));
339 
340 	if (pd->entries[vfid])
341 		return -ENOTEMPTY;
342 
343 	pt = lmtt_pt_alloc(lmtt, pd->level - 1);
344 	if (IS_ERR(pt))
345 		return PTR_ERR(pt);
346 
347 	pt_addr = xe_bo_main_addr(pt->bo, XE_PAGE_SIZE);
348 
349 	pde = lmtt->ops->lmtt_pte_encode(pt_addr, pd->level);
350 
351 	lmtt_write_pte(lmtt, pd, pde, vfid);
352 
353 	pd->entries[vfid] = pt;
354 
355 	if (pt->level != 0) {
356 		err = __lmtt_alloc_range(lmtt, pt, start, end);
357 		if (err)
358 			goto out_free_pt;
359 	}
360 
361 	return 0;
362 
363 out_free_pt:
364 	lmtt_pt_free(pt);
365 	return err;
366 }
367 
lmtt_leaf_pt(struct xe_lmtt * lmtt,unsigned int vfid,u64 addr)368 static struct xe_lmtt_pt *lmtt_leaf_pt(struct xe_lmtt *lmtt, unsigned int vfid, u64 addr)
369 {
370 	struct xe_lmtt_pt *pd = lmtt->pd;
371 	struct xe_lmtt_pt *pt;
372 
373 	lmtt_assert(lmtt, vfid <= lmtt->ops->lmtt_pte_num(pd->level));
374 	pt = pd->entries[vfid];
375 
376 	while (pt->level) {
377 		lmtt_assert(lmtt, lmtt->ops->lmtt_pte_index(addr, pt->level) <=
378 			    lmtt->ops->lmtt_pte_num(pt->level));
379 
380 		pt = pt->entries[lmtt->ops->lmtt_pte_index(addr, pt->level)];
381 
382 		addr >>= lmtt->ops->lmtt_pte_shift(pt->level);
383 	}
384 
385 	lmtt_assert(lmtt, lmtt->ops->lmtt_pte_index(addr, pt->level) <=
386 		    lmtt->ops->lmtt_pte_num(pt->level));
387 	lmtt_assert(lmtt, pt->level != pd->level);
388 	lmtt_assert(lmtt, pt->level == 0);
389 	return pt;
390 }
391 
lmtt_insert_bo(struct xe_lmtt * lmtt,unsigned int vfid,struct xe_bo * bo,u64 start)392 static void lmtt_insert_bo(struct xe_lmtt *lmtt, unsigned int vfid, struct xe_bo *bo, u64 start)
393 {
394 	u64 page_size = lmtt_page_size(lmtt);
395 	struct xe_res_cursor cur;
396 	struct xe_lmtt_pt *pt;
397 	u64 addr, vram_offset;
398 
399 	lmtt_assert(lmtt, IS_ALIGNED(start, page_size));
400 	lmtt_assert(lmtt, IS_ALIGNED(bo->size, page_size));
401 	lmtt_assert(lmtt, xe_bo_is_vram(bo));
402 
403 	vram_offset = vram_region_gpu_offset(bo->ttm.resource);
404 	xe_res_first(bo->ttm.resource, 0, bo->size, &cur);
405 	while (cur.remaining) {
406 		addr = xe_res_dma(&cur);
407 		addr += vram_offset; /* XXX */
408 
409 		pt = lmtt_leaf_pt(lmtt, vfid, start);
410 
411 		lmtt_write_pte(lmtt, pt, lmtt->ops->lmtt_pte_encode(addr, 0),
412 					 lmtt->ops->lmtt_pte_index(start, 0));
413 
414 		xe_res_next(&cur, page_size);
415 		start += page_size;
416 	}
417 }
418 
419 /**
420  * xe_lmtt_prepare_pages - Create VF's LMTT Page Tables.
421  * @lmtt: the &xe_lmtt to update
422  * @vfid: the VF identifier (1-based)
423  * @range: top range of LMEM offset to be supported
424  *
425  * This function creates empty LMTT page tables for given VF to support
426  * up to maximum #range LMEM offset. The LMTT page tables created by this
427  * function must be released using xe_lmtt_drop_pages() function.
428  *
429  * Notes:
430  * This function shall be called only after successful LMTT initialization.
431  * See xe_lmtt_init().
432  *
433  * Return: 0 on success or a negative error code on failure.
434  */
xe_lmtt_prepare_pages(struct xe_lmtt * lmtt,unsigned int vfid,u64 range)435 int xe_lmtt_prepare_pages(struct xe_lmtt *lmtt, unsigned int vfid, u64 range)
436 {
437 	lmtt_assert(lmtt, lmtt->pd);
438 	lmtt_assert(lmtt, vfid);
439 
440 	return lmtt_alloc_range(lmtt, vfid, 0, range);
441 }
442 
443 /**
444  * xe_lmtt_populate_pages - Update VF's LMTT Page Table Entries.
445  * @lmtt: the &xe_lmtt to update
446  * @vfid: the VF identifier (1-based)
447  * @bo: the buffer object with LMEM allocation to be mapped
448  * @offset: the offset at which #bo should be mapped
449  *
450  * This function updates VF's LMTT entries to use given buffer object as a backstore.
451  *
452  * Notes:
453  * This function shall be called only after successful preparation of the
454  * VF's LMTT Page Tables. See xe_lmtt_prepare().
455  *
456  * Return: 0 on success or a negative error code on failure.
457  */
xe_lmtt_populate_pages(struct xe_lmtt * lmtt,unsigned int vfid,struct xe_bo * bo,u64 offset)458 int xe_lmtt_populate_pages(struct xe_lmtt *lmtt, unsigned int vfid, struct xe_bo *bo, u64 offset)
459 {
460 	lmtt_assert(lmtt, lmtt->pd);
461 	lmtt_assert(lmtt, vfid);
462 
463 	lmtt_insert_bo(lmtt, vfid, bo, offset);
464 	return 0;
465 }
466 
467 /**
468  * xe_lmtt_drop_pages - Remove VF's LMTT Pages.
469  * @lmtt: the &xe_lmtt to update
470  * @vfid: the VF identifier (1-based)
471  *
472  * This function removes all LMTT Page Tables prepared by xe_lmtt_prepare_pages().
473  *
474  * This function shall be called only after successful LMTT initialization.
475  * See xe_lmtt_init().
476  */
xe_lmtt_drop_pages(struct xe_lmtt * lmtt,unsigned int vfid)477 void xe_lmtt_drop_pages(struct xe_lmtt *lmtt, unsigned int vfid)
478 {
479 	lmtt_assert(lmtt, lmtt->pd);
480 	lmtt_assert(lmtt, vfid);
481 
482 	lmtt_drop_pages(lmtt, vfid);
483 }
484 
485 /**
486  * xe_lmtt_estimate_pt_size - Estimate size of LMTT PT allocations.
487  * @lmtt: the &xe_lmtt
488  * @size: the size of the LMEM to be mapped over LMTT (including any offset)
489  *
490  * This function shall be called only by PF.
491  *
492  * Return: size of the PT allocation(s) needed to support given LMEM size.
493  */
xe_lmtt_estimate_pt_size(struct xe_lmtt * lmtt,u64 size)494 u64 xe_lmtt_estimate_pt_size(struct xe_lmtt *lmtt, u64 size)
495 {
496 	unsigned int level = 0;
497 	u64 pt_size;
498 
499 	lmtt_assert(lmtt, IS_SRIOV_PF(lmtt_to_xe(lmtt)));
500 	lmtt_assert(lmtt, xe_device_has_lmtt(lmtt_to_xe(lmtt)));
501 	lmtt_assert(lmtt, lmtt->ops);
502 
503 	pt_size = PAGE_ALIGN(lmtt->ops->lmtt_pte_size(level) *
504 			     lmtt->ops->lmtt_pte_num(level));
505 
506 	while (++level < lmtt->ops->lmtt_root_pd_level()) {
507 		pt_size *= lmtt->ops->lmtt_pte_index(size, level) + 1;
508 		pt_size += PAGE_ALIGN(lmtt->ops->lmtt_pte_size(level) *
509 				      lmtt->ops->lmtt_pte_num(level));
510 	}
511 
512 	return pt_size;
513 }
514 
515 #if IS_BUILTIN(CONFIG_DRM_XE_KUNIT_TEST)
516 #include "tests/xe_lmtt_test.c"
517 #endif
518