Thread (6 messages) flat view 6 messages, 1 author, 4d ago
COOLING4d

[PATCH 4/5] powerpc/spufs: fix context state race in spu_acquire_saved()

From: Junrui Luo via B4 Relay <devnull+moonafterrain.outlook.com@kernel.org>
Date: 2026-08-12 05:48:29
Also in: b4-sent, lkml, stable
Subsystem: cell broadband engine architecture, linux for powerpc (32-bit and 64-bit), spu file system, the rest · Maintainers: Madhavan Srinivasan, Linus Torvalds

From: Junrui Luo <redacted>

spu_acquire_saved() returns with ctx->state_mutex held and the context
in SPU_STATE_SAVED.  It tests ctx->state once and, if the context is
still running, sets SPU_SCHED_WAS_ACTIVE and calls spu_deactivate().
That path reaches __spu_deactivate(ctx, 1, MAX_PRIO), which drops
state_mutex around spu_schedule() once spu_unschedule() has unbound the
context, so the test result is stale by the time the function returns.

A second thread reading any saved-state file of the same context can
take state_mutex in that window, observe SPU_STATE_SAVED and skip its
own deactivate.  SPU_SCHED_WAS_ACTIVE is a single bit in
ctx->sched_flags rather than a per-acquirer token, so that thread's
spu_release_saved() consumes the bit and calls spu_activate(), binding
the context back onto an SPU.  The first thread then returns from
spu_acquire_saved() with the context RUNNABLE, reads a save image the
SPU is concurrently writing, and trips the
BUG_ON(ctx->state != SPU_STATE_SAVED) in its own spu_release_saved(),
leaving state_mutex held.

Fix by retesting the state after spu_deactivate() returns, which also
re-sets SPU_SCHED_WAS_ACTIVE so the acquirer keeps its own reactivation
token.

Fixes: e65c2f6fcebb ("[POWERPC] spufs: decouple spu scheduler from spufs_spu_run (asynchronous scheduling)")
Reported-by: Yuhao Jiang <redacted>
Assisted-by: Claude:claude-opus-5
Cc: stable@vger.kernel.org
Signed-off-by: Junrui Luo <redacted>
---
Found by inspection; I have no Cell/PS3 hardware, so this is
compile-tested only.
---
 arch/powerpc/platforms/cell/spufs/context.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/arch/powerpc/platforms/cell/spufs/context.c b/arch/powerpc/platforms/cell/spufs/context.c
index 44377dfff1f8..2414ad9be0ae 100644
--- a/arch/powerpc/platforms/cell/spufs/context.c
+++ b/arch/powerpc/platforms/cell/spufs/context.c
@@ -107,7 +107,7 @@ void spu_forget(struct spu_context *ctx)
 	 * want this context to be rescheduled on release.
 	 */
 	mutex_lock(&ctx->state_mutex);
-	if (ctx->state != SPU_STATE_SAVED)
+	while (ctx->state != SPU_STATE_SAVED)
 		spu_deactivate(ctx);
 
 	mm = ctx->owner;
@@ -150,7 +150,7 @@ int spu_acquire_saved(struct spu_context *ctx)
 	if (ret)
 		return ret;
 
-	if (ctx->state != SPU_STATE_SAVED) {
+	while (ctx->state != SPU_STATE_SAVED) {
 		set_bit(SPU_SCHED_WAS_ACTIVE, &ctx->sched_flags);
 		spu_deactivate(ctx);
 	}
-- 
2.51.2


Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help