Re: [PATCH] timekeeping: Register default clocksource before taking tk_core.lock

From: Breno Leitao

Date: Tue Jun 16 2026 - 04:44:42 EST


On Tue, Jun 16, 2026 at 12:09:14PM +0500, Mikhail Gavrilov wrote:
> Commit f24df84cbe05 ("time/jiffies: Register jiffies clocksource before
> usage") moved the jiffies clocksource registration into
> clocksource_default_clock(), so that it is registered lazily on the first
> call. __clocksource_register() acquires clocksource_mutex, but the first
> caller is timekeeping_init(), which invokes clocksource_default_clock()
> while holding tk_core.lock, a raw spinlock.
>
> Acquiring a sleeping mutex while holding a raw spinlock is invalid, and
> lockdep reports it on every boot when CONFIG_PROVE_RAW_LOCK_NESTING is
> enabled:
>
> =============================
> [ BUG: Invalid wait context ]
> -----------------------------
> swapper/0/0 is trying to lock:
> ... (clocksource_mutex){....}-{4:4}, at: __clocksource_register_scale
> other info that might help us debug this:
> context-{5:5}
> 1 lock held by swapper/0/0:
> #0: ... (&tkd->lock){....}-{2:2}, at: timekeeping_init+0x1d5/0x320
> stack backtrace:
> dump_stack_lvl+0x84/0xd0
> __lock_acquire.cold+0x39/0x63
> lock_acquire.part.0+0xc7/0x280
> __mutex_lock+0x1b2/0x2440
> __clocksource_register_scale.cold+0x289/0x609
> clocksource_default_clock+0x31/0x50
> timekeeping_init+0x1e3/0x320
> start_kernel+0x243/0x3f0
> x86_64_start_reservations+0x24/0x30
> x86_64_start_kernel+0x134/0x140
> common_startup_64+0x13e/0x151
>
>
I am seeing a similar issue, although from a different code path.

=============================
[ BUG: Invalid wait context ]
7.1.0-next-20260615upstream-14023-g8d6dbbbe3ba6 #32 Not tainted
-----------------------------
swapper/0/0 is trying to lock:
ffff800084e4bd80 (clocksource_mutex){....}-{4:4}, at: __clocksource_register_scale+0x5c4/0xa48
other info that might help us debug this:
context-{5:5}
1 lock held by swapper/0/0:
#0: ffff80008ca99930 (&tkd->lock){....}-{2:2}, at: timekeeping_init+0x158/0x290
stack backtrace:
CPU: 0 UID: 0 PID: 0 Comm: swapper/0 Not tainted 7.1.0-next-20260615upstream-14023-g8d6dbbbe3ba6 #32 PREEMPT(full)
Hardware name: linux,dummy-virt (DT)
Call trace:
show_stack+0x24/0x38 (C)
__dump_stack+0x28/0x38
dump_stack_lvl+0x94/0xe0
dump_stack+0x18/0x24
__lock_acquire+0xba4/0x3520
lock_acquire+0x150/0x390
__mutex_lock+0xe4/0x1240
mutex_lock_nested+0x30/0x48
__clocksource_register_scale+0x5c4/0xa48
clocksource_default_clock+0x40/0x68
timekeeping_init+0x164/0x290
start_kernel+0x2b0/0x4b8
__primary_switched+0x8c/0xa0


> On PREEMPT_RT this is a genuine sleeping-while-atomic bug. On !RT
> clocksource_mutex is uncontended at this point, so the boot survives, but
> the locking rule is violated either way.
>
> The default clocksource only has to be registered before
> tk_setup_internals() consumes its mult/shift/maxadj. Neither
> clocksource_default_clock(), the ->enable() callback, nor the registration
> itself need tk_core.lock, so fetch and enable the clock before acquiring
> the lock. This preserves the "register before usage" ordering while
> keeping clocksource_mutex out of the raw spinlock section.
>
> clocksource_default_clock() has a second caller,
> clocksource_done_booting(), which invokes it with clocksource_mutex
> already held. That path avoids a recursive lock only because
> timekeeping_init() has already run and set cs_jiffies_registered, so the
> registration is skipped there. This change does not alter that; it only
> fixes the invalid wait context in timekeeping_init().
>
> Fixes: f24df84cbe05 ("time/jiffies: Register jiffies clocksource before usage")
> Signed-off-by: Mikhail Gavrilov <mikhail.v.gavrilov@xxxxxxxxx>

Reviwed-by: Breno Leitao <leitao@xxxxxxxxxx>