diff --git a/drivers/char/tpm/tpm_tis.c b/drivers/char/tpm/tpm_tis.c index 5d778ea926f3f..513e0d1c349a6 100644 --- a/drivers/char/tpm/tpm_tis.c +++ b/drivers/char/tpm/tpm_tis.c @@ -53,7 +53,7 @@ static inline struct tpm_tis_tcg_phy *to_tpm_tis_tcg_phy(struct tpm_tis_data *da #ifdef CONFIG_PREEMPT_RT /* * Flushes previous write operations to chip so that a subsequent - * ioread*()s won't stall a cpu. + * ioread*()s won't stall a CPU. */ static inline void tpm_tis_flush(void __iomem *iobase) { diff --git a/include/linux/console.h b/include/linux/console.h index ae4bbec59eea8..1e9d5bc8fa76e 100644 --- a/include/linux/console.h +++ b/include/linux/console.h @@ -490,21 +490,21 @@ static inline bool console_is_registered(const struct console *con) hlist_for_each_entry(con, &console_list, node) #ifdef CONFIG_PRINTK +extern enum cons_prio cons_atomic_enter(enum cons_prio prio); +extern void cons_atomic_exit(enum cons_prio prio, enum cons_prio prev_prio); extern bool console_can_proceed(struct cons_write_context *wctxt); extern bool console_enter_unsafe(struct cons_write_context *wctxt); extern bool console_exit_unsafe(struct cons_write_context *wctxt); extern bool console_try_acquire(struct cons_write_context *wctxt); extern bool console_release(struct cons_write_context *wctxt); -extern enum cons_prio cons_atomic_enter(enum cons_prio prio); -extern void cons_atomic_exit(enum cons_prio prio, enum cons_prio prev_prio); #else +static inline enum cons_prio cons_atomic_enter(enum cons_prio prio) { return CONS_PRIO_NONE; } +static inline void cons_atomic_exit(enum cons_prio prio, enum cons_prio prev_prio) { } static inline bool console_can_proceed(struct cons_write_context *wctxt) { return false; } static inline bool console_enter_unsafe(struct cons_write_context *wctxt) { return false; } static inline bool console_exit_unsafe(struct cons_write_context *wctxt) { return false; } static inline bool console_try_acquire(struct cons_write_context *wctxt) { return false; } static inline bool console_release(struct cons_write_context *wctxt) { return false; } -static inline enum cons_prio cons_atomic_enter(enum cons_prio prio) { return CONS_PRIO_NONE; } -static inline void cons_atomic_exit(enum cons_prio prio, enum cons_prio prev_prio) { } #endif extern int console_set_on_cmdline; diff --git a/kernel/locking/rtmutex.c b/kernel/locking/rtmutex.c index 728f434de2bbf..c1bc2cb1522cb 100644 --- a/kernel/locking/rtmutex.c +++ b/kernel/locking/rtmutex.c @@ -23,6 +23,7 @@ #include #include #include +#include #include @@ -1700,6 +1701,12 @@ static __always_inline int __rt_mutex_lock(struct rt_mutex_base *lock, if (likely(rt_mutex_cmpxchg_acquire(lock, NULL, current))) return 0; + /* + * If we are going to sleep and we have plugged IO queued, make sure to + * submit it to avoid deadlocks. + */ + blk_flush_plug(current->plug, true); + return rt_mutex_slowlock(lock, NULL, state); } #endif /* RT_MUTEX_BUILD_MUTEX */ diff --git a/kernel/locking/rwbase_rt.c b/kernel/locking/rwbase_rt.c index c201aadb93017..96042dca2fd97 100644 --- a/kernel/locking/rwbase_rt.c +++ b/kernel/locking/rwbase_rt.c @@ -72,15 +72,6 @@ static int __sched __rwbase_read_lock(struct rwbase_rt *rwb, int ret; raw_spin_lock_irq(&rtm->wait_lock); - /* - * Allow readers, as long as the writer has not completely - * acquired the semaphore for write. - */ - if (atomic_read(&rwb->readers) != WRITER_BIAS) { - atomic_inc(&rwb->readers); - raw_spin_unlock_irq(&rtm->wait_lock); - return 0; - } /* * Call into the slow lock path with the rtmutex->wait_lock @@ -143,6 +134,14 @@ static __always_inline int rwbase_read_lock(struct rwbase_rt *rwb, if (rwbase_read_trylock(rwb)) return 0; + if (state != TASK_RTLOCK_WAIT) { + /* + * If we are going to sleep and we have plugged IO queued, + * make sure to submit it to avoid deadlocks. + */ + blk_flush_plug(current->plug, true); + } + return __rwbase_read_lock(rwb, state); } diff --git a/kernel/locking/ww_rt_mutex.c b/kernel/locking/ww_rt_mutex.c index d1473c624105c..472e3622abf09 100644 --- a/kernel/locking/ww_rt_mutex.c +++ b/kernel/locking/ww_rt_mutex.c @@ -67,6 +67,11 @@ __ww_rt_mutex_lock(struct ww_mutex *lock, struct ww_acquire_ctx *ww_ctx, ww_mutex_set_context_fastpath(lock, ww_ctx); return 0; } + /* + * If we are going to sleep and we have plugged IO queued, make sure to + * submit it to avoid deadlocks. + */ + blk_flush_plug(current->plug, true); ret = rt_mutex_slowlock(&rtm->rtmutex, ww_ctx, state); diff --git a/kernel/printk/internal.h b/kernel/printk/internal.h index fb363b495ce92..6631fd70542f9 100644 --- a/kernel/printk/internal.h +++ b/kernel/printk/internal.h @@ -58,6 +58,16 @@ __printf(1, 0) int vprintk_deferred(const char *fmt, va_list args); bool printk_percpu_data_ready(void); +/* + * The printk_safe_enter()/_exit() macros mark code blocks using locks that + * would lead to deadlock if an interrupting context were to call printk() + * while the interrupted context was within such code blocks. + * + * When a CPU is in such a code block, an interrupting context calling + * printk() will only log the new message to the lockless ringbuffer and + * then trigger console printing using irqwork. + */ + #define printk_safe_enter_irqsave(flags) \ do { \ __printk_safe_enter(&flags); \ diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c index f733204f33ee5..e2466366d4f84 100644 --- a/kernel/printk/printk.c +++ b/kernel/printk/printk.c @@ -318,10 +318,6 @@ static int __down_trylock_console_sem(unsigned long ip) int lock_failed; unsigned long flags; - /* Semaphores are not NMI-safe. */ - if (in_nmi()) - return 1; - /* * Here and in __up_console_sem() we need to be in safe mode, * because spindump/WARN/etc from under console ->lock will @@ -3150,6 +3146,10 @@ void console_unblank(void) * In that case, attempt a trylock as best-effort. */ if (oops_in_progress) { + /* Semaphores are not NMI-safe. */ + if (in_nmi()) + return; + if (down_trylock_console_sem() != 0) return; } else @@ -3210,8 +3210,12 @@ void console_flush_on_panic(enum con_flush_mode mode) * that messages are flushed out. As this can be called from any * context and we don't want to get preempted while flushing, * ensure may_schedule is cleared. + * + * Since semaphores are not NMI-safe, the console lock must be + * ignored if the panic is in NMI context. */ - console_trylock(); + if (!in_nmi()) + console_trylock(); console_may_schedule = 0; if (mode == CONSOLE_REPLAY_ALL) { @@ -3226,7 +3230,8 @@ void console_flush_on_panic(enum con_flush_mode mode) } console_srcu_read_unlock(cookie); } - console_unlock(); + if (!in_nmi()) + console_unlock(); } /* diff --git a/kernel/printk/printk_safe.c b/kernel/printk/printk_safe.c index 9cd33cddef9fc..5c1470bd60bcb 100644 --- a/kernel/printk/printk_safe.c +++ b/kernel/printk/printk_safe.c @@ -24,6 +24,7 @@ static DEFINE_PER_CPU(struct printk_context, printk_context) = { /* Can be preempted by NMI. */ void __printk_safe_enter(unsigned long *flags) { + WARN_ON_ONCE(in_nmi()); local_lock_irqsave(&printk_context.cpu, *flags); this_cpu_inc(printk_context.recursion); } @@ -31,6 +32,7 @@ void __printk_safe_enter(unsigned long *flags) /* Can be preempted by NMI. */ void __printk_safe_exit(unsigned long *flags) { + WARN_ON_ONCE(in_nmi()); this_cpu_dec(printk_context.recursion); local_unlock_irqrestore(&printk_context.cpu, *flags); } diff --git a/localversion-rt b/localversion-rt index ad3da1bcab7e8..0efe7ba1930e1 100644 --- a/localversion-rt +++ b/localversion-rt @@ -1 +1 @@ --rt4 +-rt5