Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

timekeeping: Add a lockdep override in tick_freeze()

tick_freeze() acquires a raw spinlock (tick_freeze_lock). Later in the
callchain (timekeeping_suspend() -> mc146818_avoid_UIP()) the RTC driver
acquires a spinlock which becomes a sleeping lock on PREEMPT_RT. Lockdep
complains about this lock nesting.

Add a lockdep override for this special case and a comment explaining
why it is okay.

Reported-by: Borislav Petkov <bp@alien8.de>
Reported-by: Chris Bainbridge <chris.bainbridge@gmail.com>
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Acked-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Link: https://lore.kernel.org/all/20250404133429.pnAzf-eF@linutronix.de
Closes: https://lore.kernel.org/all/20250330113202.GAZ-krsjAnurOlTcp-@fat_crate.local/
Closes: https://lore.kernel.org/all/CAP-bSRZ0CWyZZsMtx046YV8L28LhY0fson2g4EqcwRAVN1Jk+Q@mail.gmail.com/

authored by

Sebastian Andrzej Siewior and committed by
Thomas Gleixner
92e250c6 2424e146

+22
+22
kernel/time/tick-common.c
··· 509 509 510 510 #ifdef CONFIG_SUSPEND 511 511 static DEFINE_RAW_SPINLOCK(tick_freeze_lock); 512 + static DEFINE_WAIT_OVERRIDE_MAP(tick_freeze_map, LD_WAIT_SLEEP); 512 513 static unsigned int tick_freeze_depth; 513 514 514 515 /** ··· 529 528 if (tick_freeze_depth == num_online_cpus()) { 530 529 trace_suspend_resume(TPS("timekeeping_freeze"), 531 530 smp_processor_id(), true); 531 + /* 532 + * All other CPUs have their interrupts disabled and are 533 + * suspended to idle. Other tasks have been frozen so there 534 + * is no scheduling happening. This means that there is no 535 + * concurrency in the system at this point. Therefore it is 536 + * okay to acquire a sleeping lock on PREEMPT_RT, such as a 537 + * spinlock, because the lock cannot be held by other CPUs 538 + * or threads and acquiring it cannot block. 539 + * 540 + * Inform lockdep about the situation. 541 + */ 542 + lock_map_acquire_try(&tick_freeze_map); 532 543 system_state = SYSTEM_SUSPEND; 533 544 sched_clock_suspend(); 534 545 timekeeping_suspend(); 546 + lock_map_release(&tick_freeze_map); 535 547 } else { 536 548 tick_suspend_local(); 537 549 } ··· 566 552 raw_spin_lock(&tick_freeze_lock); 567 553 568 554 if (tick_freeze_depth == num_online_cpus()) { 555 + /* 556 + * Similar to tick_freeze(). On resumption the first CPU may 557 + * acquire uncontended sleeping locks while other CPUs block on 558 + * tick_freeze_lock. 559 + */ 560 + lock_map_acquire_try(&tick_freeze_map); 569 561 timekeeping_resume(); 570 562 sched_clock_resume(); 563 + lock_map_release(&tick_freeze_map); 564 + 571 565 system_state = SYSTEM_RUNNING; 572 566 trace_suspend_resume(TPS("timekeeping_freeze"), 573 567 smp_processor_id(), false);