Skip to content

Commit 56441f9

Browse files
mbrost05Thomas Hellström
authored andcommitted
drm/xe/vf: Fix VF CCS attach/detach race with in-flight BO moves
xe_bo_move() attaches VF CCS read/write batch buffers (BBs) to a BO after it transitions NULL/SYSTEM -> TT, and detaches them after it transitions TT -> SYSTEM. Both operations were done synchronously on the CPU immediately after building the move's copy/clear fence, without waiting for that fence to signal. This creates two races with VF migration: - Attach happens too late relative to the copy job it is meant to protect. If the copy job is submitted before the CCS BBs are attached, a VF migration event that pauses execution mid-copy can observe partially copied CCS metadata without the attach state needed to correctly save/restore it. - Detach happens too early relative to the copy job that moves data out of TT. The CCS BBs are torn down right after the copy fence is obtained, while the actual blit may still be in flight. A VF migration event that pauses execution mid-copy can then race the save/restore path against the still-running blit, and the CCS BBs it would need to make sense of the paused state have already been removed. Fix both races: - Move the attach call to before the copy/clear job is submitted, so the CCS BBs are already registered by the time the copy runs. On attach failure, unwind and bail out of the move. xe_migrate_ccs_rw_copy() now takes the destination resource explicitly, since bo->ttm.resource is not updated to the new resource until after the move commits. - Detach only after explicitly waiting for the copy fence to signal, instead of tearing down the CCS BBs immediately after obtaining it. While here, also fix xe_sriov_vf_ccs_attach_bo() to properly unwind and propagate errors: the per-context loop previously never broke out on error, silently discarding earlier failures. Unwind by clearing each attached context directly via xe_migrate_ccs_rw_copy_clear() instead of reusing xe_sriov_vf_ccs_detach_bo(), which requires both contexts to be attached before it will clean up either one. Fixes: 864690c ("drm/xe/vf: Attach and detach CCS copy commands with BO") Cc: Michal Wajdeczko <michal.wajdeczko@intel.com> Cc: Matthew Auld <matthew.auld@intel.com> Cc: Michał Winiarski <michal.winiarski@intel.com> Cc: Satyanarayana K V P <satyanarayana.k.v.p@intel.com> Assisted-by: GitHub_Copilot:claude-sonnet-5 Signed-off-by: Matthew Brost <matthew.brost@intel.com> Acked-by: Satyanarayana K V P <satyanarayana.k.v.p@intel.com> Reviewed-by: Matthew Auld <matthew.auld@intel.com> Link: https://patch.msgid.link/20260714062440.3421225-1-matthew.brost@intel.com (cherry picked from commit d45ad0a) Signed-off-by: Thomas Hellström <thomas.hellstrom@linux.intel.com>
1 parent c473761 commit 56441f9

5 files changed

Lines changed: 48 additions & 15 deletions

File tree

drivers/gpu/drm/xe/xe_bo.c

Lines changed: 23 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1102,6 +1102,21 @@ static int xe_bo_move(struct ttm_buffer_object *ttm_bo, bool evict,
11021102
xe_pm_runtime_get_noresume(xe);
11031103
}
11041104

1105+
/*
1106+
* Attach CCS BBs before submitting the copy job below so a VF
1107+
* migration racing the copy sees valid, up to date attach state.
1108+
*/
1109+
if (IS_VF_CCS_READY(xe) &&
1110+
((move_lacks_source && new_mem->mem_type == XE_PL_TT) ||
1111+
(old_mem_type == XE_PL_SYSTEM && new_mem->mem_type == XE_PL_TT)) &&
1112+
handle_system_ccs) {
1113+
ret = xe_sriov_vf_ccs_attach_bo(bo, new_mem);
1114+
if (ret) {
1115+
xe_pm_runtime_put(xe);
1116+
goto out;
1117+
}
1118+
}
1119+
11051120
if (move_lacks_source) {
11061121
u32 flags = 0;
11071122

@@ -1139,22 +1154,19 @@ static int xe_bo_move(struct ttm_buffer_object *ttm_bo, bool evict,
11391154
ttm_bo_move_null(ttm_bo, new_mem);
11401155
}
11411156

1142-
dma_fence_put(fence);
1143-
xe_pm_runtime_put(xe);
1144-
11451157
/*
1146-
* CCS meta data is migrated from TT -> SMEM. So, let us detach the
1147-
* BBs from BO as it is no longer needed.
1158+
* Detach must wait for the copy above to complete: a VF migration
1159+
* racing an in-flight copy must still see valid CCS BBs, so don't
1160+
* tear them down until the copy fence has signaled.
11481161
*/
11491162
if (IS_VF_CCS_READY(xe) && old_mem_type == XE_PL_TT &&
1150-
new_mem->mem_type == XE_PL_SYSTEM)
1163+
new_mem->mem_type == XE_PL_SYSTEM) {
1164+
dma_fence_wait(fence, false);
11511165
xe_sriov_vf_ccs_detach_bo(bo);
1166+
}
11521167

1153-
if (IS_VF_CCS_READY(xe) &&
1154-
((move_lacks_source && new_mem->mem_type == XE_PL_TT) ||
1155-
(old_mem_type == XE_PL_SYSTEM && new_mem->mem_type == XE_PL_TT)) &&
1156-
handle_system_ccs)
1157-
ret = xe_sriov_vf_ccs_attach_bo(bo);
1168+
dma_fence_put(fence);
1169+
xe_pm_runtime_put(xe);
11581170

11591171
out:
11601172
if ((!ttm_bo->resource || ttm_bo->resource->mem_type == XE_PL_SYSTEM) &&

drivers/gpu/drm/xe/xe_migrate.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1166,6 +1166,8 @@ static int emit_flush_invalidate(u32 *dw, int i, u32 flags)
11661166
* @tile: Tile whose migration context to be used.
11671167
* @q : Execution to be used along with migration context.
11681168
* @src_bo: The buffer object @src is currently bound to.
1169+
* @new_mem: The (not yet committed) destination resource @src_bo is being
1170+
* moved into; src_bo->ttm.resource is still the old resource.
11691171
* @read_write : Creates BB commands for CCS read/write.
11701172
*
11711173
* Creates batch buffer instructions to copy CCS metadata from CCS pool to
@@ -1177,12 +1179,13 @@ static int emit_flush_invalidate(u32 *dw, int i, u32 flags)
11771179
*/
11781180
int xe_migrate_ccs_rw_copy(struct xe_tile *tile, struct xe_exec_queue *q,
11791181
struct xe_bo *src_bo,
1182+
struct ttm_resource *new_mem,
11801183
enum xe_sriov_vf_ccs_rw_ctxs read_write)
11811184

11821185
{
11831186
bool src_is_pltt = read_write == XE_SRIOV_VF_CCS_READ_CTX;
11841187
bool dst_is_pltt = read_write == XE_SRIOV_VF_CCS_WRITE_CTX;
1185-
struct ttm_resource *src = src_bo->ttm.resource;
1188+
struct ttm_resource *src = new_mem;
11861189
struct xe_migrate *m = tile->migrate;
11871190
struct xe_gt *gt = tile->primary_gt;
11881191
u32 batch_size, batch_size_allocated;

drivers/gpu/drm/xe/xe_migrate.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,7 @@ struct dma_fence *xe_migrate_resolve(struct xe_migrate *m,
138138

139139
int xe_migrate_ccs_rw_copy(struct xe_tile *tile, struct xe_exec_queue *q,
140140
struct xe_bo *src_bo,
141+
struct ttm_resource *new_mem,
141142
enum xe_sriov_vf_ccs_rw_ctxs read_write);
142143

143144
void xe_migrate_ccs_rw_copy_clear(struct xe_bo *src_bo,

drivers/gpu/drm/xe/xe_sriov_vf_ccs.c

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -404,14 +404,16 @@ void xe_sriov_vf_ccs_rw_update_bb_addr(struct xe_sriov_vf_ccs_ctx *ctx)
404404
/**
405405
* xe_sriov_vf_ccs_attach_bo - Insert CCS read write commands in the BO.
406406
* @bo: the &buffer object to which batch buffer commands will be added.
407+
* @new_mem: the (not yet committed) destination resource @bo is being moved
408+
* into; bo->ttm.resource is still the old resource at this point.
407409
*
408410
* This function shall be called only by VF. It inserts the PTEs and copy
409411
* command instructions in the BO by calling xe_migrate_ccs_rw_copy()
410412
* function.
411413
*
412414
* Returns: 0 if successful, negative error code on failure.
413415
*/
414-
int xe_sriov_vf_ccs_attach_bo(struct xe_bo *bo)
416+
int xe_sriov_vf_ccs_attach_bo(struct xe_bo *bo, struct ttm_resource *new_mem)
415417
{
416418
struct xe_device *xe = xe_bo_device(bo);
417419
enum xe_sriov_vf_ccs_rw_ctxs ctx_id;
@@ -430,7 +432,21 @@ int xe_sriov_vf_ccs_attach_bo(struct xe_bo *bo)
430432
xe_assert(xe, !bb);
431433

432434
ctx = &xe->sriov.vf.ccs.contexts[ctx_id];
433-
err = xe_migrate_ccs_rw_copy(tile, ctx->mig_q, bo, ctx_id);
435+
err = xe_migrate_ccs_rw_copy(tile, ctx->mig_q, bo, new_mem, ctx_id);
436+
if (err)
437+
goto err_unwind;
438+
}
439+
return 0;
440+
441+
err_unwind:
442+
/*
443+
* Clean up any contexts already attached. Can't reuse
444+
* xe_sriov_vf_ccs_detach_bo() here as it requires both contexts
445+
* attached before cleaning up either one.
446+
*/
447+
for_each_ccs_rw_ctx(ctx_id) {
448+
if (bo->bb_ccs[ctx_id])
449+
xe_migrate_ccs_rw_copy_clear(bo, ctx_id);
434450
}
435451
return err;
436452
}

drivers/gpu/drm/xe/xe_sriov_vf_ccs.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,12 @@
1111
#include "xe_sriov_vf_ccs_types.h"
1212

1313
struct drm_printer;
14+
struct ttm_resource;
1415
struct xe_device;
1516
struct xe_bo;
1617

1718
int xe_sriov_vf_ccs_init(struct xe_device *xe);
18-
int xe_sriov_vf_ccs_attach_bo(struct xe_bo *bo);
19+
int xe_sriov_vf_ccs_attach_bo(struct xe_bo *bo, struct ttm_resource *new_mem);
1920
int xe_sriov_vf_ccs_detach_bo(struct xe_bo *bo);
2021
int xe_sriov_vf_ccs_register_context(struct xe_device *xe);
2122
void xe_sriov_vf_ccs_rebase(struct xe_device *xe);

0 commit comments

Comments
 (0)