File Index
Files and directories
Sign in
FILE

xe_sriov_vf_ccs.c

File preview with syntax highlighting.

linux-6.19.14/drivers/gpu/drm/xe/xe_sriov_vf_ccs.c C
  1// SPDX-License-Identifier: MIT
  2/*
  3 * Copyright © 2025 Intel Corporation
  4 */
  5
  6#include "instructions/xe_mi_commands.h"
  7#include "instructions/xe_gpu_commands.h"
  8#include "xe_bb.h"
  9#include "xe_bo.h"
 10#include "xe_device.h"
 11#include "xe_exec_queue.h"
 12#include "xe_exec_queue_types.h"
 13#include "xe_gt_sriov_vf.h"
 14#include "xe_guc.h"
 15#include "xe_guc_submit.h"
 16#include "xe_lrc.h"
 17#include "xe_migrate.h"
 18#include "xe_pm.h"
 19#include "xe_sa.h"
 20#include "xe_sriov_printk.h"
 21#include "xe_sriov_vf.h"
 22#include "xe_sriov_vf_ccs.h"
 23#include "xe_sriov_vf_ccs_types.h"
 24
 25/**
 26 * DOC: VF save/restore of compression Meta Data
 27 *
 28 * VF KMD registers two special contexts/LRCAs.
 29 *
 30 * Save Context/LRCA: contain necessary cmds+page table to trigger Meta data /
 31 * compression control surface (Aka CCS) save in regular System memory in VM.
 32 *
 33 * Restore Context/LRCA: contain necessary cmds+page table to trigger Meta data /
 34 * compression control surface (Aka CCS) Restore from regular System memory in
 35 * VM to corresponding CCS pool.
 36 *
 37 * Below diagram explain steps needed for VF save/Restore of compression Meta Data::
 38 *
 39 *    CCS Save    CCS Restore          VF KMD                          Guc       BCS
 40 *     LRCA        LRCA
 41 *      |           |                     |                              |         |
 42 *      |           |                     |                              |         |
 43 *      |     Create Save LRCA            |                              |         |
 44 *     [ ]<----------------------------- [ ]                             |         |
 45 *      |           |                     |                              |         |
 46 *      |           |                     |                              |         |
 47 *      |           |                     |       Register save LRCA     |         |
 48 *      |           |                     |           with Guc           |         |
 49 *      |           |                    [ ]--------------------------->[ ]        |
 50 *      |           |                     |                              |         |
 51 *      |           | Create restore LRCA |                              |         |
 52 *      |          [ ]<------------------[ ]                             |         |
 53 *      |           |                     |                              |         |
 54 *      |           |                     |       Register restore LRCA  |         |
 55 *      |           |                     |           with Guc           |         |
 56 *      |           |                    [ ]--------------------------->[ ]        |
 57 *      |           |                     |                              |         |
 58 *      |           |                     |                              |         |
 59 *      |           |                    [ ]-------------------------    |         |
 60 *      |           |                    [ ]  Allocate main memory.  |   |         |
 61 *      |           |                    [ ]  Allocate CCS memory.   |   |         |
 62 *      |           |                    [ ]  Update Main memory &   |   |         |
 63 *     [ ]<------------------------------[ ]  CCS pages PPGTT + BB   |   |         |
 64 *      |          [ ]<------------------[ ]  cmds to save & restore.|   |         |
 65 *      |           |                    [ ]<------------------------    |         |
 66 *      |           |                     |                              |         |
 67 *      |           |                     |                              |         |
 68 *      |           |                     |                              |         |
 69 *      :           :                     :                              :         :
 70 *      ---------------------------- VF Paused -------------------------------------
 71 *      |           |                     |                              |         |
 72 *      |           |                     |                              |         |
 73 *      |           |                     |                              |Schedule |
 74 *      |           |                     |                              |CCS Save |
 75 *      |           |                     |                              | LRCA    |
 76 *      |           |                     |                             [ ]------>[ ]
 77 *      |           |                     |                              |         |
 78 *      |           |                     |                              |         |
 79 *      |           |                     |                              |CCS save |
 80 *      |           |                     |                              |completed|
 81 *      |           |                     |                             [ ]<------[ ]
 82 *      |           |                     |                              |         |
 83 *      :           :                     :                              :         :
 84 *      ---------------------------- VM Migrated -----------------------------------
 85 *      |           |                     |                              |         |
 86 *      |           |                     |                              |         |
 87 *      :           :                     :                              :         :
 88 *      ---------------------------- VF Resumed ------------------------------------
 89 *      |           |                     |                              |         |
 90 *      |           |                     |                              |         |
 91 *      |           |                    [ ]--------------               |         |
 92 *      |           |                    [ ] Fix up GGTT  |              |         |
 93 *      |           |                    [ ]<-------------               |         |
 94 *      |           |                     |                              |         |
 95 *      |           |                     |                              |         |
 96 *      |           |                     |  Notify VF_RESFIX_DONE       |         |
 97 *      |           |                    [ ]--------------------------->[ ]        |
 98 *      |           |                     |                              |         |
 99 *      |           |                     |                              |Schedule |
100 *      |           |                     |                              |CCS      |
101 *      |           |                     |                              |Restore  |
102 *      |           |                     |                              |LRCA     |
103 *      |           |                     |                             [ ]------>[ ]
104 *      |           |                     |                              |         |
105 *      |           |                     |                              |         |
106 *      |           |                     |                              |CCS      |
107 *      |           |                     |                              |restore  |
108 *      |           |                     |                              |completed|
109 *      |           |                     |                             [ ]<------[ ]
110 *      |           |                     |                              |         |
111 *      |           |                     |                              |         |
112 *      |           |                     |  VF_RESFIX_DONE complete     |         |
113 *      |           |                     |       notification           |         |
114 *      |           |                    [ ]<---------------------------[ ]        |
115 *      |           |                     |                              |         |
116 *      |           |                     |                              |         |
117 *      :           :                     :                              :         :
118 *      ------------------------- Continue VM restore ------------------------------
119 */
120
121static u64 get_ccs_bb_pool_size(struct xe_device *xe)
122{
123	u64 sys_mem_size, ccs_mem_size, ptes, bb_pool_size;
124	struct sysinfo si;
125
126	si_meminfo(&si);
127	sys_mem_size = si.totalram * si.mem_unit;
128	ccs_mem_size = div64_u64(sys_mem_size, NUM_BYTES_PER_CCS_BYTE(xe));
129	ptes = DIV_ROUND_UP_ULL(sys_mem_size + ccs_mem_size, XE_PAGE_SIZE);
130
131	/**
132	 * We need below BB size to hold PTE mappings and some DWs for copy
133	 * command. In reality, we need space for many copy commands. So, let
134	 * us allocate double the calculated size which is enough to holds GPU
135	 * instructions for the whole region.
136	 */
137	bb_pool_size = ptes * sizeof(u32);
138
139	return round_up(bb_pool_size * 2, SZ_1M);
140}
141
142static int alloc_bb_pool(struct xe_tile *tile, struct xe_sriov_vf_ccs_ctx *ctx)
143{
144	struct xe_device *xe = tile_to_xe(tile);
145	struct xe_sa_manager *sa_manager;
146	u64 bb_pool_size;
147	int offset, err;
148
149	bb_pool_size = get_ccs_bb_pool_size(xe);
150	xe_sriov_info(xe, "Allocating %s CCS BB pool size = %lldMB\n",
151		      ctx->ctx_id ? "Restore" : "Save", bb_pool_size / SZ_1M);
152
153	sa_manager = xe_sa_bo_manager_init(tile, bb_pool_size, SZ_16);
154
155	if (IS_ERR(sa_manager)) {
156		xe_sriov_err(xe, "Suballocator init failed with error: %pe\n",
157			     sa_manager);
158		err = PTR_ERR(sa_manager);
159		return err;
160	}
161
162	offset = 0;
163	xe_map_memset(xe, &sa_manager->bo->vmap, offset, MI_NOOP,
164		      bb_pool_size);
165
166	offset = bb_pool_size - sizeof(u32);
167	xe_map_wr(xe, &sa_manager->bo->vmap, offset, u32, MI_BATCH_BUFFER_END);
168
169	ctx->mem.ccs_bb_pool = sa_manager;
170
171	return 0;
172}
173
174static void ccs_rw_update_ring(struct xe_sriov_vf_ccs_ctx *ctx)
175{
176	u64 addr = xe_sa_manager_gpu_addr(ctx->mem.ccs_bb_pool);
177	struct xe_lrc *lrc = xe_exec_queue_lrc(ctx->mig_q);
178	u32 dw[10], i = 0;
179
180	/*
181	 * XXX: Save/restore fixes — for some reason, the GuC only accepts the
182	 * save/restore context if the LRC head pointer is zero. This is evident
183	 * from repeated VF migrations failing when the LRC head pointer is
184	 * non-zero.
185	 */
186	lrc->ring.tail = 0;
187	xe_lrc_set_ring_head(lrc, 0);
188
189	dw[i++] = MI_ARB_ON_OFF | MI_ARB_ENABLE;
190	dw[i++] = MI_BATCH_BUFFER_START | XE_INSTR_NUM_DW(3);
191	dw[i++] = lower_32_bits(addr);
192	dw[i++] = upper_32_bits(addr);
193	dw[i++] = MI_NOOP;
194	dw[i++] = MI_NOOP;
195
196	xe_lrc_write_ring(lrc, dw, i * sizeof(u32));
197	xe_lrc_set_ring_tail(lrc, lrc->ring.tail);
198}
199
200/**
201 * xe_sriov_vf_ccs_rebase - Rebase GGTT addresses for CCS save / restore
202 * @xe: the &xe_device.
203 */
204void xe_sriov_vf_ccs_rebase(struct xe_device *xe)
205{
206	enum xe_sriov_vf_ccs_rw_ctxs ctx_id;
207
208	if (!IS_VF_CCS_READY(xe))
209		return;
210
211	for_each_ccs_rw_ctx(ctx_id) {
212		struct xe_sriov_vf_ccs_ctx *ctx =
213			&xe->sriov.vf.ccs.contexts[ctx_id];
214
215		ccs_rw_update_ring(ctx);
216	}
217}
218
219static int register_save_restore_context(struct xe_sriov_vf_ccs_ctx *ctx)
220{
221	int ctx_type;
222
223	switch (ctx->ctx_id) {
224	case XE_SRIOV_VF_CCS_READ_CTX:
225		ctx_type = GUC_CONTEXT_COMPRESSION_SAVE;
226		break;
227	case XE_SRIOV_VF_CCS_WRITE_CTX:
228		ctx_type = GUC_CONTEXT_COMPRESSION_RESTORE;
229		break;
230	default:
231		return -EINVAL;
232	}
233
234	xe_guc_register_vf_exec_queue(ctx->mig_q, ctx_type);
235	return 0;
236}
237
238/**
239 * xe_sriov_vf_ccs_register_context - Register read/write contexts with guc.
240 * @xe: the &xe_device to register contexts on.
241 *
242 * This function registers read and write contexts with Guc. Re-registration
243 * is needed whenever resuming from pm runtime suspend.
244 *
245 * Return: 0 on success. Negative error code on failure.
246 */
247int xe_sriov_vf_ccs_register_context(struct xe_device *xe)
248{
249	enum xe_sriov_vf_ccs_rw_ctxs ctx_id;
250	struct xe_sriov_vf_ccs_ctx *ctx;
251	int err;
252
253	xe_assert(xe, IS_VF_CCS_READY(xe));
254
255	for_each_ccs_rw_ctx(ctx_id) {
256		ctx = &xe->sriov.vf.ccs.contexts[ctx_id];
257		err = register_save_restore_context(ctx);
258		if (err)
259			return err;
260	}
261
262	return err;
263}
264
265/*
266 * Whether GuC requires CCS copy BBs for VF migration.
267 * @xe: the &xe_device instance.
268 *
269 * Only selected platforms require VF KMD to maintain CCS copy BBs and linked LRCAs.
270 *
271 * Return: true if VF driver must participate in the CCS migration, false otherwise.
272 */
273static bool vf_migration_ccs_bb_needed(struct xe_device *xe)
274{
275	xe_assert(xe, IS_SRIOV_VF(xe));
276
277	return !IS_DGFX(xe) && xe_device_has_flat_ccs(xe);
278}
279
280/*
281 * Check for disable migration due to no CCS BBs support in GuC FW.
282 * @xe: the &xe_device instance.
283 *
284 * Performs late disable of VF migration feature in case GuC FW cannot support it.
285 *
286 * Returns: True if VF migration with CCS BBs is supported, false otherwise.
287 */
288static bool vf_migration_ccs_bb_support_check(struct xe_device *xe)
289{
290	struct xe_gt *gt = xe_root_mmio_gt(xe);
291	struct xe_uc_fw_version guc_version;
292
293	xe_gt_sriov_vf_guc_versions(gt, NULL, &guc_version);
294	if (MAKE_GUC_VER_STRUCT(guc_version) < MAKE_GUC_VER(1, 23, 0)) {
295		xe_sriov_vf_migration_disable(xe,
296					      "CCS migration requires GuC ABI >= 1.23 but only %u.%u found",
297					      guc_version.major, guc_version.minor);
298		return false;
299	}
300
301	return true;
302}
303
304static void xe_sriov_vf_ccs_fini(void *arg)
305{
306	struct xe_sriov_vf_ccs_ctx *ctx = arg;
307	struct xe_lrc *lrc = xe_exec_queue_lrc(ctx->mig_q);
308
309	/*
310	 * Make TAIL = HEAD in the ring so that no issues are seen if Guc
311	 * submits this context to HW on VF pause after unbinding device.
312	 */
313	xe_lrc_set_ring_tail(lrc, xe_lrc_ring_head(lrc));
314	xe_exec_queue_put(ctx->mig_q);
315}
316
317/**
318 * xe_sriov_vf_ccs_init - Setup LRCA for save & restore.
319 * @xe: the &xe_device to start recovery on
320 *
321 * This function shall be called only by VF. It initializes
322 * LRCA and suballocator needed for CCS save & restore.
323 *
324 * Return: 0 on success. Negative error code on failure.
325 */
326int xe_sriov_vf_ccs_init(struct xe_device *xe)
327{
328	struct xe_tile *tile = xe_device_get_root_tile(xe);
329	enum xe_sriov_vf_ccs_rw_ctxs ctx_id;
330	struct xe_sriov_vf_ccs_ctx *ctx;
331	struct xe_exec_queue *q;
332	u32 flags;
333	int err;
334
335	xe_assert(xe, IS_SRIOV_VF(xe));
336
337	if (!xe_sriov_vf_migration_supported(xe) ||
338	    !vf_migration_ccs_bb_needed(xe) ||
339	    !vf_migration_ccs_bb_support_check(xe))
340		return 0;
341
342	for_each_ccs_rw_ctx(ctx_id) {
343		ctx = &xe->sriov.vf.ccs.contexts[ctx_id];
344		ctx->ctx_id = ctx_id;
345
346		flags = EXEC_QUEUE_FLAG_KERNEL |
347			EXEC_QUEUE_FLAG_PERMANENT |
348			EXEC_QUEUE_FLAG_MIGRATE;
349		q = xe_exec_queue_create_bind(xe, tile, NULL, flags, 0);
350		if (IS_ERR(q)) {
351			err = PTR_ERR(q);
352			goto err_ret;
353		}
354		ctx->mig_q = q;
355
356		err = alloc_bb_pool(tile, ctx);
357		if (err)
358			goto err_free_queue;
359
360		ccs_rw_update_ring(ctx);
361
362		err = register_save_restore_context(ctx);
363		if (err)
364			goto err_free_queue;
365
366		err = devm_add_action_or_reset(xe->drm.dev,
367					       xe_sriov_vf_ccs_fini,
368					       ctx);
369		if (err)
370			goto err_ret;
371	}
372
373	xe->sriov.vf.ccs.initialized = 1;
374
375	return 0;
376
377err_free_queue:
378	xe_exec_queue_put(q);
379
380err_ret:
381	return err;
382}
383
384/**
385 * xe_sriov_vf_ccs_attach_bo - Insert CCS read write commands in the BO.
386 * @bo: the &buffer object to which batch buffer commands will be added.
387 *
388 * This function shall be called only by VF. It inserts the PTEs and copy
389 * command instructions in the BO by calling xe_migrate_ccs_rw_copy()
390 * function.
391 *
392 * Returns: 0 if successful, negative error code on failure.
393 */
394int xe_sriov_vf_ccs_attach_bo(struct xe_bo *bo)
395{
396	struct xe_device *xe = xe_bo_device(bo);
397	enum xe_sriov_vf_ccs_rw_ctxs ctx_id;
398	struct xe_sriov_vf_ccs_ctx *ctx;
399	struct xe_tile *tile;
400	struct xe_bb *bb;
401	int err = 0;
402
403	xe_assert(xe, IS_VF_CCS_READY(xe));
404
405	tile = xe_device_get_root_tile(xe);
406
407	for_each_ccs_rw_ctx(ctx_id) {
408		bb = bo->bb_ccs[ctx_id];
409		/* bb should be NULL here. Assert if not NULL */
410		xe_assert(xe, !bb);
411
412		ctx = &xe->sriov.vf.ccs.contexts[ctx_id];
413		err = xe_migrate_ccs_rw_copy(tile, ctx->mig_q, bo, ctx_id);
414	}
415	return err;
416}
417
418/**
419 * xe_sriov_vf_ccs_detach_bo - Remove CCS read write commands from the BO.
420 * @bo: the &buffer object from which batch buffer commands will be removed.
421 *
422 * This function shall be called only by VF. It removes the PTEs and copy
423 * command instructions from the BO. Make sure to update the BB with MI_NOOP
424 * before freeing.
425 *
426 * Returns: 0 if successful.
427 */
428int xe_sriov_vf_ccs_detach_bo(struct xe_bo *bo)
429{
430	struct xe_device *xe = xe_bo_device(bo);
431	enum xe_sriov_vf_ccs_rw_ctxs ctx_id;
432	struct xe_bb *bb;
433
434	xe_assert(xe, IS_VF_CCS_READY(xe));
435
436	if (!xe_bo_has_valid_ccs_bb(bo))
437		return 0;
438
439	for_each_ccs_rw_ctx(ctx_id) {
440		bb = bo->bb_ccs[ctx_id];
441		if (!bb)
442			continue;
443
444		memset(bb->cs, MI_NOOP, bb->len * sizeof(u32));
445		xe_bb_free(bb, NULL);
446		bo->bb_ccs[ctx_id] = NULL;
447	}
448	return 0;
449}
450
451/**
452 * xe_sriov_vf_ccs_print - Print VF CCS details.
453 * @xe: the &xe_device
454 * @p: the &drm_printer
455 *
456 * This function is for VF use only.
457 */
458void xe_sriov_vf_ccs_print(struct xe_device *xe, struct drm_printer *p)
459{
460	struct xe_sa_manager *bb_pool;
461	enum xe_sriov_vf_ccs_rw_ctxs ctx_id;
462
463	if (!IS_VF_CCS_READY(xe))
464		return;
465
466	xe_pm_runtime_get(xe);
467
468	for_each_ccs_rw_ctx(ctx_id) {
469		bb_pool = xe->sriov.vf.ccs.contexts[ctx_id].mem.ccs_bb_pool;
470		if (!bb_pool)
471			break;
472
473		drm_printf(p, "ccs %s bb suballoc info\n", ctx_id ? "write" : "read");
474		drm_printf(p, "-------------------------\n");
475		drm_suballoc_dump_debug_info(&bb_pool->base, p, xe_sa_manager_gpu_addr(bb_pool));
476		drm_puts(p, "\n");
477	}
478
479	xe_pm_runtime_put(xe);
480}
~/ Read-only file preview.