[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20260125164016.331257-4-qq570070308@gmail.com>
Date: Mon, 26 Jan 2026 00:40:10 +0800
From: Xie Yuanbin <qq570070308@...il.com>
To: linux@...linux.org.uk,
johannes@...solutions.net,
masahiroy@...nel.org,
jgross@...e.com,
nsc@...nel.org,
kees@...nel.org,
tglx@...nel.org,
mingo@...nel.org,
frederic@...nel.org,
paulmck@...nel.org,
peterz@...radead.org,
mathieu.desnoyers@...icios.com,
luto@...nel.org,
edumazet@...gle.com
Cc: linux-arm-kernel@...ts.infradead.org,
linux-kernel@...r.kernel.org,
Xie Yuanbin <qq570070308@...il.com>
Subject: [PATCH 3/9] ARM: entry: fix wrong lockdep hardirqs state
When CONFIG_PROVE_LOCKING=y, CONFIG_TRACE_IRQFLAGS=y, CONFIG_NO_HZ_FULL=y,
and nohz_full is correctly enabled, if a user program returns to user mode
on the nohz_full CPUs, the following WARNING will be triggered:
```log
[ 4.763050] ------------[ cut here ]------------
[ 4.763244] WARNING: kernel/context_tracking.c:450 at __ct_user_enter+0x180/0x184, CPU#0: bash/1
[ 4.764815] Modules linked in:
[ 4.765386] CPU: 0 UID: 0 PID: 1 Comm: bash Not tainted 6.19.0-rc6-next-20260123 #1 VOLUNTARY
[ 4.765761] Hardware name: Generic DT based system
[ 4.766105] Call trace:
[ 4.766151] unwind_backtrace from show_stack+0x10/0x14
[ 4.766686] show_stack from dump_stack_lvl+0x68/0x80
[ 4.766919] dump_stack_lvl from __warn+0xf0/0x270
[ 4.767140] __warn from warn_slowpath_fmt+0xc0/0x194
[ 4.767542] warn_slowpath_fmt from __ct_user_enter+0x180/0x184
[ 4.767792] __ct_user_enter from user_enter_callable+0x64/0x6c
[ 4.768105] user_enter_callable from no_work_pending+0x8/0x4c
[ 4.768415] Exception stack(0xf0849fb0 to 0xf0849ff8)
[ 4.768816] 9fa0: 00000000 00000000 00000000 00000000
[ 4.769060] 9fc0: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
[ 4.769335] 9fe0: 00000000 beaf2ef0 00000000 b6f10dec 00000010 00000000
[ 4.769669] irq event stamp: 211021
[ 4.770932] hardirqs last enabled at (211021): [<c0300114>] no_work_pending+0x4/0x4c
[ 4.771687] hardirqs last disabled at (211020): [<c032a064>] do_work_pending+0x48/0xa4
[ 4.772290] softirqs last enabled at (210994): [<c0371354>] handle_softirqs+0x434/0x4dc
[ 4.772902] softirqs last disabled at (210987): [<c0371654>] __irq_exit_rcu+0xd0/0x204
[ 4.773359] ---[ end trace 0000000000000000 ]---
```
In ret_to_user() and ret_fast_syscall(), disable_irq_notrace() is called,
which skips trace_hardirqs_off(). On the other hand,
asm_trace_hardirqs_on() is called prematurely before user_enter(). This
causes lockdep's hardirqs to be recorded as enabled when user_enter() is
called, even if interrupts are disabled.
1. Do not skip the tracing when enabling/disabling interrupts before
returning to user mode, just like what other architectures do.
2. Call asm_trace_hardirqs_on() after user_enter().
Fixes: b04db8e19fc2 ("rcu: Use lockdep to assert IRQs are disabled/enabled")
Signed-off-by: Xie Yuanbin <qq570070308@...il.com>
---
arch/arm/kernel/entry-common.S | 14 ++++++--------
arch/arm/kernel/signal.c | 7 +------
2 files changed, 7 insertions(+), 14 deletions(-)
diff --git a/arch/arm/kernel/entry-common.S b/arch/arm/kernel/entry-common.S
index f579770fab71..0e462bbede2f 100644
--- a/arch/arm/kernel/entry-common.S
+++ b/arch/arm/kernel/entry-common.S
@@ -71,7 +71,7 @@ __ret_fast_syscall:
mov r0, sp @ 'regs'
bl do_rseq_syscall
#endif
- disable_irq_notrace @ disable interrupts
+ disable_irq save = 0 @ disable interrupts
ldr r1, [tsk, #TI_FLAGS] @ re-check for syscall tracing
movs r1, r1, lsl #16
beq no_work_pending
@@ -97,30 +97,28 @@ ENDPROC(ret_fast_syscall)
/*
* "slow" syscall return path. "why" tells us if this was a real syscall.
- * IRQs may be enabled here, so always disable them. Note that we use the
- * "notrace" version to avoid calling into the tracing code unnecessarily.
- * do_work_pending() will update this state if necessary.
+ * IRQs may be enabled here, so always disable them.
*/
ENTRY(ret_to_user)
ret_slow_syscall:
#if IS_ENABLED(CONFIG_DEBUG_RSEQ)
/* do_rseq_syscall needs interrupts enabled. */
- enable_irq_notrace @ enable interrupts
+ enable_irq save = 0 @ enable interrupts
mov r0, sp @ 'regs'
bl do_rseq_syscall
#endif
- disable_irq_notrace @ disable interrupts
+ disable_irq save = 0 @ disable interrupts
ENTRY(ret_to_user_from_irq)
ldr r1, [tsk, #TI_FLAGS]
movs r1, r1, lsl #16
bne slow_work_pending
no_work_pending:
- asm_trace_hardirqs_on save = 0
-
#ifdef CONFIG_CONTEXT_TRACKING_USER
bl user_enter_callable
#endif
+ asm_trace_hardirqs_on save = 0
+
#ifdef CONFIG_KSTACK_ERASE
bl stackleak_erase_on_task_stack
#endif
diff --git a/arch/arm/kernel/signal.c b/arch/arm/kernel/signal.c
index 79a6730fa0eb..93e0a7637c81 100644
--- a/arch/arm/kernel/signal.c
+++ b/arch/arm/kernel/signal.c
@@ -601,12 +601,7 @@ static int do_signal(struct pt_regs *regs, int syscall)
asmlinkage int
do_work_pending(struct pt_regs *regs, unsigned int thread_flags, int syscall)
{
- /*
- * The assembly code enters us with IRQs off, but it hasn't
- * informed the tracing code of that for efficiency reasons.
- * Update the trace code with the current status.
- */
- trace_hardirqs_off();
+ /* The assembly code enters us with IRQs off. */
do {
if (likely(thread_flags & _TIF_NEED_RESCHED)) {
schedule();
--
2.51.0
Powered by blists - more mailing lists