Ensure correct handling of closed VMAs on multi-gt platforms to prevent Use-After-Free. Currently, when GT0 goes idle, closed VMAs that are exclusively added to GT0's closed_vma link (gt->closed_vma) and subsequently freed by i915_vma_parked(), which assumes the entire GPU is idle. However, on platforms with multiple GTs, such as MTL, GT1 may remain active while GT0 is idle. This causes GT0 to mistakenly consider the closed VMAs in its closed_vma list as unnecessary, potentially leading to Use-After-Free issues if a job for GT1 attempts to access a freed VMA.
Although we do take a wakeref for GT0 but it happens later, after evaluating VMAs. To mitigate this, it is necessary to hold a GT0 wakeref early. Cc: Joonas Lahtinen <[email protected]> Cc: Rodrigo Vivi <[email protected]> Cc: Tvrtko Ursulin <[email protected]> Cc: Thomas Hellström <[email protected]> Cc: Chris Wilson <[email protected]> Cc: Andi Shyti <[email protected]> Cc: Andrzej Hajda <[email protected]> Signed-off-by: Nirmoy Das <[email protected]> --- drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c index 5fb459ea4294..adcf8837dfe6 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c @@ -2692,6 +2692,7 @@ static int eb_select_engine(struct i915_execbuffer *eb) { struct intel_context *ce, *child; + struct intel_gt *gt; unsigned int idx; int err; @@ -2715,10 +2716,16 @@ eb_select_engine(struct i915_execbuffer *eb) } } eb->num_batches = ce->parallel.number_children + 1; + gt = ce->engine->gt; for_each_child(ce, child) intel_context_get(child); intel_gt_pm_get(ce->engine->gt); + /* Keep GT0 active on MTL so that i915_vma_parked() doesn't + * free VMAs while execbuf ioctl is validating VMAs. + */ + if (gt != to_gt(gt->i915)) + intel_gt_pm_get(to_gt(ce->engine->gt->i915)); if (!test_bit(CONTEXT_ALLOC_BIT, &ce->flags)) { err = intel_context_alloc_state(ce); @@ -2757,6 +2764,9 @@ eb_select_engine(struct i915_execbuffer *eb) return err; err: + if (ce->engine->gt != to_gt(ce->engine->gt->i915)) + intel_gt_pm_get(to_gt(ce->engine->gt->i915)); + intel_gt_pm_put(ce->engine->gt); for_each_child(ce, child) intel_context_put(child); @@ -2770,6 +2780,8 @@ eb_put_engine(struct i915_execbuffer *eb) struct intel_context *child; i915_vm_put(eb->context->vm); + if (eb->gt != to_gt(eb->gt->i915)) + intel_gt_pm_put(to_gt(eb->gt->i915)); intel_gt_pm_put(eb->gt); for_each_child(eb->context, child) intel_context_put(child); -- 2.39.0
