From: John Ogness Date: Mon, 11 Dec 2023 09:34:16 +0000 Subject: [PATCH 45/48] printk: Avoid false positive lockdep report for legacy printing Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.10/older/patches-6.10.2-rt14.tar.xz Legacy console printing from printk() caller context may invoke the console driver from atomic context. This leads to a lockdep splat because the console driver will acquire a sleeping lock and the caller may already hold a spinning lock. This is noticed by lockdep on !PREEMPT_RT configurations because it will lead to a problem on PREEMPT_RT. However, on PREEMPT_RT the printing path from atomic context is always avoided and the console driver is always invoked from a dedicated thread. Thus the lockdep splat on !PREEMPT_RT is a false positive. For !PREEMPT_RT override the lock-context before invoking the console driver to avoid the false positive. Do not override the lock-context for PREEMPT_RT in order to allow lockdep to catch any real locking context issues related to the write callback usage. Signed-off-by: John Ogness Signed-off-by: Sebastian Andrzej Siewior --- kernel/printk/printk.c | 31 ++++++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) --- a/kernel/printk/printk.c +++ b/kernel/printk/printk.c @@ -2981,6 +2981,33 @@ bool printk_get_next_message(struct prin } /* + * Legacy console printing from printk() caller context does not respect + * raw_spinlock/spinlock nesting. For !PREEMPT_RT the lockdep warning is a + * false positive. For PREEMPT_RT the false positive condition does not + * occur. + * + * This map is used to establish LD_WAIT_SLEEP context for the console write + * callbacks when legacy printing to avoid false positive lockdep complaints, + * thus allowing lockdep to continue to function for real issues. + */ +#ifdef CONFIG_PREEMPT_RT +static inline void printk_legacy_lock_map_acquire_try(void) { } +static inline void printk_legacy_lock_map_release(void) { } +#else +static DEFINE_WAIT_OVERRIDE_MAP(printk_legacy_map, LD_WAIT_SLEEP); + +static inline void printk_legacy_lock_map_acquire_try(void) +{ + lock_map_acquire_try(&printk_legacy_map); +} + +static inline void printk_legacy_lock_map_release(void) +{ + lock_map_release(&printk_legacy_map); +} +#endif /* CONFIG_PREEMPT_RT */ + +/* * Used as the printk buffers for non-panic, serialized console printing. * This is for legacy (!CON_NBCON) as well as all boot (CON_BOOT) consoles. * Its usage requires the console_lock held. @@ -3035,7 +3062,7 @@ static bool console_emit_next_record(str /* * With forced threading this function is either in a thread * or panic context. So there is no need for concern about - * printk reentrance or handovers. + * printk reentrance, handovers, or lockdep complaints. */ con->write(con, outbuf, pmsg.outbuf_len); @@ -3057,7 +3084,9 @@ static bool console_emit_next_record(str /* Do not trace print latency. */ stop_critical_timings(); + printk_legacy_lock_map_acquire_try(); con->write(con, outbuf, pmsg.outbuf_len); + printk_legacy_lock_map_release(); start_critical_timings();