[PATCH RFC] arm64: suspend: Fix context tracking during system suspend

"syzbot" <[email protected]> Wed, 29 Jul 2026 18:27:27 +0000 (UTC)
Newsgroups dev.linux.lists.syzbot
Message-ID <[email protected]>
Commit 19235e472798 ("cpuidle, arm64: Fix the ARM64 cpuidle logic") added
unconditional calls to ct_cpuidle_enter() and ct_cpuidle_exit() in
cpu_suspend() to keep RCU active longer before entering CPUIDLE. However,
cpu_suspend() is a dual-purpose function used both for CPUIDLE (called from
the idle task) and for system suspend (called synchronously by the task
initiating the suspend).

When cpu_suspend() is invoked during system suspend by a non-idle task,
ct_cpuidle_enter() triggers a warning in ct_kernel_exit() because it
expects to be called only from the idle task:

WARNING: kernel/context_tracking.c:120 at ct_kernel_exit+0x1b4/0x1f4
Call trace:
 ct_kernel_exit+0x1b4/0x1f4
 ct_idle_enter+0x24/0x38
 ct_cpuidle_enter include/linux/cpuidle.h:134 [inline]
 cpu_suspend+0x264/0x474
 psci_system_suspend_enter+0x4c/0x80
 suspend_enter kernel/power/suspend.c:468 [inline]
 suspend_devices_and_enter+0x88c/0xd0c

Furthermore, ct_cpuidle_enter() incorrectly tells lockdep that interrupts
are enabled, which is true for CPUIDLE but wrong for system suspend where
interrupts are strictly disabled.

Fix this by conditionally calling ct_cpuidle_enter() and ct_cpuidle_exit()
only if the current task is the idle task. This preserves the required RCU
context tracking behavior for CPUIDLE without violating context tracking
assumptions during system suspend.

Fixes: 19235e472798 ("cpuidle, arm64: Fix the ARM64 cpuidle logic")
Assisted-by: Gemini:gemini-3.5-flash Gemini:gemini-3.1-pro-preview syzbot
Reported-by: [email protected]
Closes: https://syzkaller.appspot.com/bug?extid=79883955da3a62652a80
Link: https://syzkaller.appspot.com/ai_job?id=a12b1304-974c-4342-8eb2-8cae11276afb
To: "Catalin Marinas" <[email protected]>
To: <[email protected]>
To: "Will Deacon" <[email protected]>
To: "Peter Zijlstra" <[email protected]>
Cc: <[email protected]>

---
diff --git a/arch/arm64/kernel/suspend.c b/arch/arm64/kernel/suspend.c
index eaaff9432..c6b6b1cac 100644
--- a/arch/arm64/kernel/suspend.c
+++ b/arch/arm64/kernel/suspend.c
@@ -5,6 +5,7 @@
 #include <linux/uaccess.h>
 #include <linux/pgtable.h>
 #include <linux/cpuidle.h>
+#include <linux/sched.h>
 #include <asm/alternative.h>
 #include <asm/cacheflush.h>
 #include <asm/cpufeature.h>
@@ -99,6 +100,7 @@ int cpu_suspend(unsigned long arg, int (*fn)(unsigned long))
 	int ret = 0;
 	unsigned long flags;
 	struct sleep_stack_data state;
+	bool idle = is_idle_task(current);
 	struct arm_cpuidle_irq_context context;
 
 	/*
@@ -137,7 +139,8 @@ int cpu_suspend(unsigned long arg, int (*fn)(unsigned long))
 	 */
 	arm_cpuidle_save_irq_context(&context);
 
-	ct_cpuidle_enter();
+	if (idle)
+		ct_cpuidle_enter();
 
 	if (__cpu_suspend_enter(&state)) {
 		/* Call the suspend finisher */
@@ -153,9 +156,11 @@ int cpu_suspend(unsigned long arg, int (*fn)(unsigned long))
 		if (!ret)
 			ret = -EOPNOTSUPP;
 
-		ct_cpuidle_exit();
+		if (idle)
+			ct_cpuidle_exit();
 	} else {
-		ct_cpuidle_exit();
+		if (idle)
+			ct_cpuidle_exit();
 		__cpu_suspend_exit();
 	}
 


base-commit: f5098b6bae761e346ebcd9da7f95622c04733cff
-- 
This is an AI-generated patch subject to moderation.
Reply with '#syz upstream' to Sign-off the patch as a human author
and send it to the upstream kernel mailing lists.
Reply with '#syz reject' to reject it ('#syz unreject' to undo).

See https://goo.gle/syzbot-ai-patches for information about AI-generated patches.
You can comment on the patch as usual, syzbot will try to address
the comments and send a new version of the patch if necessary.
syzbot engineers can be reached at [email protected].