* [PATCH v2] rseq: fix hard lockup on granted time slice extension
@ 2026-08-06 11:34 Niels Pressel
2026-08-06 12:48 ` [tip: core/urgent] entry/rseq: Fix " tip-bot2 for Niels Pressel
0 siblings, 1 reply; 5+ messages in thread
From: Niels Pressel @ 2026-08-06 11:34 UTC (permalink / raw)
To: Peter Zijlstra, Thomas Gleixner, Andy Lutomirski,
Mathieu Desnoyers, Paul E . McKenney, Boqun Feng
Cc: linux-kernel, Niels Pressel
In __exit_to_user_mode_loop(), TSE eligibility is checked while
IRQs are enabled. Granting a TSE might involve rearming the
hrtimers. However, hrtimer_rearm_deferred_tif() is expected to be
called with IRQs disabled (see include/linux/hrtimer_rearm.h:17).
Calling the function with IRQs enabled can lead to a hard lockup
because __hrtimer_rearm_deferred() acquires a raw spinlock (without
disabling IRQs) that is also acquired in hard IRQ context within
hrtimer_run_queues().
Lockdep flags the issue when running the rseq selftests on the
7.2-rc5 release:
WARNING: ./include/linux/hrtimer_rearm.h:17 at irqentry_exit, CPU#1: slice_test
================================
WARNING: inconsistent lock state
7.2.0-rc5 #1 Tainted: G W
--------------------------------
inconsistent {IN-HARDIRQ-W} -> {HARDIRQ-ON-W} usage.
slice_test [HC0[0]:SC0[0]:HE1:SE1] takes:
ffff95b82ec5c698 (hrtimer_bases.lock){?.-.}-{2:2}, at: __hrtimer_rearm_deferred
{IN-HARDIRQ-W} state was registered at:
lock_acquire
_raw_spin_lock_irqsave
hrtimer_run_queues
update_process_times
tick_periodic
tick_handle_periodic
timer_interrupt
__handle_irq_event_percpu
handle_irq_event_percpu
handle_irq_event
handle_level_irq
__common_interrupt
common_interrupt
asm_common_interrupt
_raw_spin_unlock_irqrestore
__setup_irq
request_threaded_irq
hpet_time_init
x86_late_time_init
start_kernel
x86_64_start_reservations
x86_64_start_kernel
common_startup_64
Possible unsafe locking scenario:
CPU0
----
lock(hrtimer_bases.lock);
<Interrupt>
lock(hrtimer_bases.lock);
*** DEADLOCK ***
Call Trace:
<TASK>
dump_stack_lvl
print_usage_bug
mark_lock.part.0
__lock_acquire
lock_acquire
_raw_spin_lock
__hrtimer_rearm_deferred
irqentry_exit
asm_sysvec_apic_timer_interrupt
</TASK>
Originally, the issue was discovered because of intermittent lockups
when heavily using rseq TSEs.
Following the suggestion from Peter Zijlstra, fix this potential lockup
by reflowing __exit_to_user_mode_loop() to only enable IRQs after the
TSE check.
Fixes: 15dd3a948855 ("hrtimer: Push reprogramming timers into the interrupt return path")
Signed-off-by: Niels Pressel <npressel@ethz.ch>
---
Changes in v2:
- Move to enabling IRQS in __exit_to_user_mode_loop() after the rseq
TSE check
- Remove IRQ disable in __rseq_grant_slice_extension()
- Rebased on core/entry
- Link to v1: https://lore.kernel.org/all/20260802124423.51616-1-npressel@ethz.ch/
include/linux/rseq_entry.h | 8 ++++----
kernel/entry/common.c | 10 +++++-----
2 files changed, 9 insertions(+), 9 deletions(-)
diff --git a/include/linux/rseq_entry.h b/include/linux/rseq_entry.h
index ed9da6e41a2a..cb41b30c9cb9 100644
--- a/include/linux/rseq_entry.h
+++ b/include/linux/rseq_entry.h
@@ -127,6 +127,8 @@ do { \
static __always_inline bool __rseq_grant_slice_extension(bool work_pending)
{
+ lockdep_assert_irqs_disabled();
+
struct task_struct *curr = current;
struct rseq_slice_ctrl usr_ctrl;
union rseq_slice_state state;
@@ -219,10 +221,8 @@ static __always_inline bool __rseq_grant_slice_extension(bool work_pending)
*
* which would be inconsistent state.
*/
- scoped_guard(irq) {
- clear_tsk_need_resched(curr);
- clear_preempt_need_resched();
- }
+ clear_tsk_need_resched(curr);
+ clear_preempt_need_resched();
return true;
efault:
diff --git a/kernel/entry/common.c b/kernel/entry/common.c
index e3d381fd3d25..9cefb37f4dd4 100644
--- a/kernel/entry/common.c
+++ b/kernel/entry/common.c
@@ -47,13 +47,13 @@ static __always_inline unsigned long __exit_to_user_mode_loop(struct pt_regs *re
* items have been completed.
*/
while (ti_work & EXIT_TO_USER_MODE_WORK_LOOP) {
-
+ /* Check rseq slice extensions with IRQs disabled */
+ bool sched = (ti_work & (_TIF_NEED_RESCHED | _TIF_NEED_RESCHED_LAZY)) &&
+ !rseq_grant_slice_extension(ti_work, TIF_SLICE_EXT_DENY);
local_irq_enable();
- if (ti_work & (_TIF_NEED_RESCHED | _TIF_NEED_RESCHED_LAZY)) {
- if (!rseq_grant_slice_extension(ti_work, TIF_SLICE_EXT_DENY))
- schedule();
- }
+ if (sched)
+ schedule();
if (ti_work & _TIF_UPROBE)
uprobe_notify_resume(regs);
base-commit: 05c033db7e9ad3c34f6968ec568cb6ee01051c57
--
2.50.1 (Apple Git-155)
^ permalink raw reply related [flat|nested] 5+ messages in thread* [tip: core/urgent] entry/rseq: Fix hard lockup on granted time slice extension
2026-08-06 11:34 [PATCH v2] rseq: fix hard lockup on granted time slice extension Niels Pressel
@ 2026-08-06 12:48 ` tip-bot2 for Niels Pressel
2026-08-07 21:15 ` Thomas Gleixner
0 siblings, 1 reply; 5+ messages in thread
From: tip-bot2 for Niels Pressel @ 2026-08-06 12:48 UTC (permalink / raw)
To: linux-tip-commits
Cc: Niels Pressel, Peter Zijlstra (Intel), x86, linux-kernel
The following commit has been merged into the core/urgent branch of tip:
Commit-ID: f81845889e128d2e5f8f2f38eb7339cc74640f4f
Gitweb: https://git.kernel.org/tip/f81845889e128d2e5f8f2f38eb7339cc74640f4f
Author: Niels Pressel <npressel@ethz.ch>
AuthorDate: Thu, 06 Aug 2026 13:34:29 +02:00
Committer: Peter Zijlstra <peterz@infradead.org>
CommitterDate: Thu, 06 Aug 2026 14:42:22 +02:00
entry/rseq: Fix hard lockup on granted time slice extension
In __exit_to_user_mode_loop(), TSE eligibility is checked while
IRQs are enabled. Granting a TSE might involve rearming the
hrtimers. However, hrtimer_rearm_deferred_tif() is expected to be
called with IRQs disabled (see include/linux/hrtimer_rearm.h:17).
Calling the function with IRQs enabled can lead to a hard lockup
because __hrtimer_rearm_deferred() acquires a raw spinlock (without
disabling IRQs) that is also acquired in hard IRQ context within
hrtimer_run_queues().
Lockdep flags the issue when running the rseq selftests on the
7.2-rc5 release:
WARNING: ./include/linux/hrtimer_rearm.h:17 at irqentry_exit, CPU#1: slice_test
Originally, the issue was discovered because of intermittent lockups
when heavily using rseq TSEs.
Following the suggestion from Peter Zijlstra, fix this potential lockup
by reflowing __exit_to_user_mode_loop() to only enable IRQs after the
TSE check.
Fixes: 15dd3a948855 ("hrtimer: Push reprogramming timers into the interrupt return path")
Signed-off-by: Niels Pressel <npressel@ethz.ch>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Link: https://patch.msgid.link/20260806113429.38333-1-npressel@ethz.ch
---
include/linux/rseq_entry.h | 8 ++++----
kernel/entry/common.c | 10 +++++-----
2 files changed, 9 insertions(+), 9 deletions(-)
diff --git a/include/linux/rseq_entry.h b/include/linux/rseq_entry.h
index ed9da6e..772e72d 100644
--- a/include/linux/rseq_entry.h
+++ b/include/linux/rseq_entry.h
@@ -132,6 +132,8 @@ static __always_inline bool __rseq_grant_slice_extension(bool work_pending)
union rseq_slice_state state;
struct rseq __user *rseq;
+ lockdep_assert_irqs_disabled();
+
if (!rseq_slice_extension_enabled())
return false;
@@ -219,10 +221,8 @@ static __always_inline bool __rseq_grant_slice_extension(bool work_pending)
*
* which would be inconsistent state.
*/
- scoped_guard(irq) {
- clear_tsk_need_resched(curr);
- clear_preempt_need_resched();
- }
+ clear_tsk_need_resched(curr);
+ clear_preempt_need_resched();
return true;
efault:
diff --git a/kernel/entry/common.c b/kernel/entry/common.c
index e3d381f..e7dae46 100644
--- a/kernel/entry/common.c
+++ b/kernel/entry/common.c
@@ -47,13 +47,13 @@ static __always_inline unsigned long __exit_to_user_mode_loop(struct pt_regs *re
* items have been completed.
*/
while (ti_work & EXIT_TO_USER_MODE_WORK_LOOP) {
-
+ /* Check rseq slice extensions with IRQs disabled */
+ bool sched = (ti_work & (_TIF_NEED_RESCHED | _TIF_NEED_RESCHED_LAZY)) &&
+ !rseq_grant_slice_extension(ti_work, TIF_SLICE_EXT_DENY);
local_irq_enable();
- if (ti_work & (_TIF_NEED_RESCHED | _TIF_NEED_RESCHED_LAZY)) {
- if (!rseq_grant_slice_extension(ti_work, TIF_SLICE_EXT_DENY))
- schedule();
- }
+ if (sched)
+ schedule();
if (ti_work & _TIF_UPROBE)
uprobe_notify_resume(regs);
^ permalink raw reply related [flat|nested] 5+ messages in thread* Re: [tip: core/urgent] entry/rseq: Fix hard lockup on granted time slice extension
2026-08-06 12:48 ` [tip: core/urgent] entry/rseq: Fix " tip-bot2 for Niels Pressel
@ 2026-08-07 21:15 ` Thomas Gleixner
2026-08-08 8:36 ` Peter Zijlstra
0 siblings, 1 reply; 5+ messages in thread
From: Thomas Gleixner @ 2026-08-07 21:15 UTC (permalink / raw)
To: tip-bot2 for Niels Pressel, linux-tip-commits
Cc: Niels Pressel, Peter Zijlstra (Intel), x86, linux-kernel
On Thu, Aug 06 2026 at 12:48, tip-bot wrote:
> In __exit_to_user_mode_loop(), TSE eligibility is checked while
> IRQs are enabled. Granting a TSE might involve rearming the
> hrtimers. However, hrtimer_rearm_deferred_tif() is expected to be
> called with IRQs disabled (see include/linux/hrtimer_rearm.h:17).
Groan. Can people please use proper words and not random made up
acronyms. This is not a SMS service. And this file reference is
more than pointless.
> Following the suggestion from Peter Zijlstra, fix this potential lockup
> by reflowing __exit_to_user_mode_loop() to only enable IRQs after the
> TSE check.
Which is broken.
> @@ -132,6 +132,8 @@ static __always_inline bool __rseq_grant_slice_extension(bool work_pending)
> union rseq_slice_state state;
> struct rseq __user *rseq;
>
> + lockdep_assert_irqs_disabled();
> +
> if (!rseq_slice_extension_enabled())
> return false;
Care to look what the code there does?
rseq = curr->rseq.usrptr;
scoped_user_rw_access(rseq, efault) {
That's user access which requires interrupts to be enabled.
Niels' original patch was correct.
To answer Peter's question from the V1 submission:
>> Thomas, previously we would call hrtimer_rearm_deferred() before
>> re-enabling IRQs, but here it slipped past. And while disabling it will
>> cure the splat, I'm thinking it makes sense to reflow
>> __exit_to_user_mode_loop() to instead delay enabling IRQs.
Yes, but then we consolidated all the schedule() hrtimer interaction and
got a benefit when schedule() was invoked directly on the way
out. That's why we ended up moving into into the success path
of rseq_grant_slice_extension() because that obviously skips schedule().
That's why we have hrtimer_rearm_deferred_user_irq() in
__exit_to_user_mode_prepare() _before_ invoking exit_to_user_mode_loop()
to ensure that one of the TIF_NEED_RESCHED bits is set. If not and if
TIF_HRTIMER_REARM is set, then the rearming happens right there with
interrupts still disabled.
If one of the TIF_NEED_RESCHED bits is set, then enabling interrupts
right on top of the loop is safe because any interrupt/exception entry
needs to check the bit as well.
So the thing [wm]e f*cked up royally was to invoke
hrtimer_rearm_deferred_tif() with interrupts enabled and that needs to
be fixed.
Of course all of this can be figured out from the copious amount of
comments which got added to explain all of this magic.
Thanks,
tglx
^ permalink raw reply [flat|nested] 5+ messages in thread* Re: [tip: core/urgent] entry/rseq: Fix hard lockup on granted time slice extension
2026-08-07 21:15 ` Thomas Gleixner
@ 2026-08-08 8:36 ` Peter Zijlstra
2026-08-08 11:23 ` Thomas Gleixner
0 siblings, 1 reply; 5+ messages in thread
From: Peter Zijlstra @ 2026-08-08 8:36 UTC (permalink / raw)
To: Thomas Gleixner
Cc: tip-bot2 for Niels Pressel, linux-tip-commits, Niels Pressel, x86,
linux-kernel
On Fri, Aug 07, 2026 at 11:15:19PM +0200, Thomas Gleixner wrote:
> > @@ -132,6 +132,8 @@ static __always_inline bool __rseq_grant_slice_extension(bool work_pending)
> > union rseq_slice_state state;
> > struct rseq __user *rseq;
> >
> > + lockdep_assert_irqs_disabled();
> > +
> > if (!rseq_slice_extension_enabled())
> > return false;
>
> Care to look what the code there does?
>
> rseq = curr->rseq.usrptr;
> scoped_user_rw_access(rseq, efault) {
>
> That's user access which requires interrupts to be enabled.
Well, you can do user access with IRQs disabled just fine, you just get
more efault. But yes, this one really wants the fault handler to page in
stuff if it is so needed.. Moo :-(
> Niels' original patch was correct.
>
> To answer Peter's question from the V1 submission:
>
> >> Thomas, previously we would call hrtimer_rearm_deferred() before
> >> re-enabling IRQs, but here it slipped past. And while disabling it will
> >> cure the splat, I'm thinking it makes sense to reflow
> >> __exit_to_user_mode_loop() to instead delay enabling IRQs.
>
> Yes, but then we consolidated all the schedule() hrtimer interaction and
> got a benefit when schedule() was invoked directly on the way
> out. That's why we ended up moving into into the success path
> of rseq_grant_slice_extension() because that obviously skips schedule().
>
> That's why we have hrtimer_rearm_deferred_user_irq() in
> __exit_to_user_mode_prepare() _before_ invoking exit_to_user_mode_loop()
> to ensure that one of the TIF_NEED_RESCHED bits is set. If not and if
> TIF_HRTIMER_REARM is set, then the rearming happens right there with
> interrupts still disabled.
>
> If one of the TIF_NEED_RESCHED bits is set, then enabling interrupts
> right on top of the loop is safe because any interrupt/exception entry
> needs to check the bit as well.
>
> So the thing [wm]e f*cked up royally was to invoke
> hrtimer_rearm_deferred_tif() with interrupts enabled and that needs to
> be fixed.
>
> Of course all of this can be figured out from the copious amount of
> comments which got added to explain all of this magic.
Bah, its spread out over too damn many functions is what :/ Anyway, I
see you've not yet pulled the patch, let me go do that now.
^ permalink raw reply [flat|nested] 5+ messages in thread* Re: [tip: core/urgent] entry/rseq: Fix hard lockup on granted time slice extension
2026-08-08 8:36 ` Peter Zijlstra
@ 2026-08-08 11:23 ` Thomas Gleixner
0 siblings, 0 replies; 5+ messages in thread
From: Thomas Gleixner @ 2026-08-08 11:23 UTC (permalink / raw)
To: Peter Zijlstra
Cc: tip-bot2 for Niels Pressel, linux-tip-commits, Niels Pressel, x86,
linux-kernel
On Sat, Aug 08 2026 at 10:36, Peter Zijlstra wrote:
> On Fri, Aug 07, 2026 at 11:15:19PM +0200, Thomas Gleixner wrote:
>> rseq = curr->rseq.usrptr;
>> scoped_user_rw_access(rseq, efault) {
>>
>> That's user access which requires interrupts to be enabled.
>
> Well, you can do user access with IRQs disabled just fine, you just get
> more efault.
Sure, but then you need a manual fault handler, which requires that
interrupts are enabled :)
>> So the thing [wm]e f*cked up royally was to invoke
>> hrtimer_rearm_deferred_tif() with interrupts enabled and that needs to
>> be fixed.
>>
>> Of course all of this can be figured out from the copious amount of
>> comments which got added to explain all of this magic.
>
> Bah, its spread out over too damn many functions is what :/
That and comments are missing at crucial places :(
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2026-08-08 11:23 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-08-06 11:34 [PATCH v2] rseq: fix hard lockup on granted time slice extension Niels Pressel
2026-08-06 12:48 ` [tip: core/urgent] entry/rseq: Fix " tip-bot2 for Niels Pressel
2026-08-07 21:15 ` Thomas Gleixner
2026-08-08 8:36 ` Peter Zijlstra
2026-08-08 11:23 ` Thomas Gleixner
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox