Loading arch/um/kernel/kmsg_dump.c +1 −1 Original line number Diff line number Diff line Loading @@ -31,7 +31,7 @@ static void kmsg_dumper_stdout(struct kmsg_dumper *dumper, * expected to output the crash information. */ if (strcmp(con->name, "ttynull") != 0 && (console_srcu_read_flags(con) & CON_ENABLED)) { console_is_usable(con, console_srcu_read_flags(con), true)) { break; } } Loading drivers/tty/serial/kgdboc.c +0 −1 Original line number Diff line number Diff line Loading @@ -577,7 +577,6 @@ static int __init kgdboc_earlycon_init(char *opt) console_list_lock(); for_each_console(con) { if (con->write && con->read && (con->flags & (CON_BOOT | CON_ENABLED)) && (!opt || !opt[0] || strcmp(con->name, opt) == 0)) break; } Loading include/linux/console.h +55 −0 Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ #include <linux/irq_work.h> #include <linux/rculist.h> #include <linux/rcuwait.h> #include <linux/smp.h> #include <linux/types.h> #include <linux/vesa.h> Loading Loading @@ -602,16 +603,70 @@ static inline bool console_is_registered(const struct console *con) extern void nbcon_cpu_emergency_enter(void); extern void nbcon_cpu_emergency_exit(void); extern bool nbcon_can_proceed(struct nbcon_write_context *wctxt); extern void nbcon_write_context_set_buf(struct nbcon_write_context *wctxt, char *buf, unsigned int len); extern bool nbcon_enter_unsafe(struct nbcon_write_context *wctxt); extern bool nbcon_exit_unsafe(struct nbcon_write_context *wctxt); extern void nbcon_reacquire_nobuf(struct nbcon_write_context *wctxt); extern bool nbcon_kdb_try_acquire(struct console *con, struct nbcon_write_context *wctxt); extern void nbcon_kdb_release(struct nbcon_write_context *wctxt); /* * Check if the given console is currently capable and allowed to print * records. Note that this function does not consider the current context, * which can also play a role in deciding if @con can be used to print * records. */ static inline bool console_is_usable(struct console *con, short flags, bool use_atomic) { if (!(flags & CON_ENABLED)) return false; if ((flags & CON_SUSPENDED)) return false; if (flags & CON_NBCON) { /* The write_atomic() callback is optional. */ if (use_atomic && !con->write_atomic) return false; /* * For the !use_atomic case, @printk_kthreads_running is not * checked because the write_thread() callback is also used * via the legacy loop when the printer threads are not * available. */ } else { if (!con->write) return false; } /* * Console drivers may assume that per-cpu resources have been * allocated. So unless they're explicitly marked as being able to * cope (CON_ANYTIME) don't call them until this CPU is officially up. */ if (!cpu_online(raw_smp_processor_id()) && !(flags & CON_ANYTIME)) return false; return true; } #else static inline void nbcon_cpu_emergency_enter(void) { } static inline void nbcon_cpu_emergency_exit(void) { } static inline bool nbcon_can_proceed(struct nbcon_write_context *wctxt) { return false; } static inline void nbcon_write_context_set_buf(struct nbcon_write_context *wctxt, char *buf, unsigned int len) { } static inline bool nbcon_enter_unsafe(struct nbcon_write_context *wctxt) { return false; } static inline bool nbcon_exit_unsafe(struct nbcon_write_context *wctxt) { return false; } static inline void nbcon_reacquire_nobuf(struct nbcon_write_context *wctxt) { } static inline bool nbcon_kdb_try_acquire(struct console *con, struct nbcon_write_context *wctxt) { return false; } static inline void nbcon_kdb_release(struct nbcon_write_context *wctxt) { } static inline bool console_is_usable(struct console *con, short flags, bool use_atomic) { return false; } #endif extern int console_set_on_cmdline; Loading include/linux/kdb.h +16 −0 Original line number Diff line number Diff line Loading @@ -14,6 +14,7 @@ */ #include <linux/list.h> #include <linux/smp.h> /* Shifted versions of the command enable bits are be used if the command * has no arguments (see kdb_check_flags). This allows commands, such as Loading Loading @@ -207,11 +208,26 @@ static inline const char *kdb_walk_kallsyms(loff_t *pos) /* Dynamic kdb shell command registration */ extern int kdb_register(kdbtab_t *cmd); extern void kdb_unregister(kdbtab_t *cmd); /* Return true when KDB as locked for printing a message on this CPU. */ static inline bool kdb_printf_on_this_cpu(void) { /* * We can use raw_smp_processor_id() here because the task could * not get migrated when KDB has locked for printing on this CPU. */ return unlikely(READ_ONCE(kdb_printf_cpu) == raw_smp_processor_id()); } #else /* ! CONFIG_KGDB_KDB */ static inline __printf(1, 2) int kdb_printf(const char *fmt, ...) { return 0; } static inline void kdb_init(int level) {} static inline int kdb_register(kdbtab_t *cmd) { return 0; } static inline void kdb_unregister(kdbtab_t *cmd) {} static inline bool kdb_printf_on_this_cpu(void) { return false; } #endif /* CONFIG_KGDB_KDB */ enum { KDB_NOT_INITIALIZED, Loading kernel/debug/kdb/kdb_io.c +32 −15 Original line number Diff line number Diff line Loading @@ -589,12 +589,28 @@ static void kdb_msg_write(const char *msg, int msg_len) */ cookie = console_srcu_read_lock(); for_each_console_srcu(c) { if (!(console_srcu_read_flags(c) & CON_ENABLED)) short flags = console_srcu_read_flags(c); if (!console_is_usable(c, flags, true)) continue; if (c == dbg_io_ops->cons) continue; if (!c->write) if (flags & CON_NBCON) { struct nbcon_write_context wctxt = { }; /* * Do not continue if the console is NBCON and the context * can't be acquired. */ if (!nbcon_kdb_try_acquire(c, &wctxt)) continue; nbcon_write_context_set_buf(&wctxt, (char *)msg, msg_len); c->write_atomic(c, &wctxt); nbcon_kdb_release(&wctxt); } else { /* * Set oops_in_progress to encourage the console drivers to * disregard their internal spin locks: in the current calling Loading @@ -607,6 +623,7 @@ static void kdb_msg_write(const char *msg, int msg_len) ++oops_in_progress; c->write(c, msg, msg_len); --oops_in_progress; } touch_nmi_watchdog(); } console_srcu_read_unlock(cookie); Loading Loading
arch/um/kernel/kmsg_dump.c +1 −1 Original line number Diff line number Diff line Loading @@ -31,7 +31,7 @@ static void kmsg_dumper_stdout(struct kmsg_dumper *dumper, * expected to output the crash information. */ if (strcmp(con->name, "ttynull") != 0 && (console_srcu_read_flags(con) & CON_ENABLED)) { console_is_usable(con, console_srcu_read_flags(con), true)) { break; } } Loading
drivers/tty/serial/kgdboc.c +0 −1 Original line number Diff line number Diff line Loading @@ -577,7 +577,6 @@ static int __init kgdboc_earlycon_init(char *opt) console_list_lock(); for_each_console(con) { if (con->write && con->read && (con->flags & (CON_BOOT | CON_ENABLED)) && (!opt || !opt[0] || strcmp(con->name, opt) == 0)) break; } Loading
include/linux/console.h +55 −0 Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ #include <linux/irq_work.h> #include <linux/rculist.h> #include <linux/rcuwait.h> #include <linux/smp.h> #include <linux/types.h> #include <linux/vesa.h> Loading Loading @@ -602,16 +603,70 @@ static inline bool console_is_registered(const struct console *con) extern void nbcon_cpu_emergency_enter(void); extern void nbcon_cpu_emergency_exit(void); extern bool nbcon_can_proceed(struct nbcon_write_context *wctxt); extern void nbcon_write_context_set_buf(struct nbcon_write_context *wctxt, char *buf, unsigned int len); extern bool nbcon_enter_unsafe(struct nbcon_write_context *wctxt); extern bool nbcon_exit_unsafe(struct nbcon_write_context *wctxt); extern void nbcon_reacquire_nobuf(struct nbcon_write_context *wctxt); extern bool nbcon_kdb_try_acquire(struct console *con, struct nbcon_write_context *wctxt); extern void nbcon_kdb_release(struct nbcon_write_context *wctxt); /* * Check if the given console is currently capable and allowed to print * records. Note that this function does not consider the current context, * which can also play a role in deciding if @con can be used to print * records. */ static inline bool console_is_usable(struct console *con, short flags, bool use_atomic) { if (!(flags & CON_ENABLED)) return false; if ((flags & CON_SUSPENDED)) return false; if (flags & CON_NBCON) { /* The write_atomic() callback is optional. */ if (use_atomic && !con->write_atomic) return false; /* * For the !use_atomic case, @printk_kthreads_running is not * checked because the write_thread() callback is also used * via the legacy loop when the printer threads are not * available. */ } else { if (!con->write) return false; } /* * Console drivers may assume that per-cpu resources have been * allocated. So unless they're explicitly marked as being able to * cope (CON_ANYTIME) don't call them until this CPU is officially up. */ if (!cpu_online(raw_smp_processor_id()) && !(flags & CON_ANYTIME)) return false; return true; } #else static inline void nbcon_cpu_emergency_enter(void) { } static inline void nbcon_cpu_emergency_exit(void) { } static inline bool nbcon_can_proceed(struct nbcon_write_context *wctxt) { return false; } static inline void nbcon_write_context_set_buf(struct nbcon_write_context *wctxt, char *buf, unsigned int len) { } static inline bool nbcon_enter_unsafe(struct nbcon_write_context *wctxt) { return false; } static inline bool nbcon_exit_unsafe(struct nbcon_write_context *wctxt) { return false; } static inline void nbcon_reacquire_nobuf(struct nbcon_write_context *wctxt) { } static inline bool nbcon_kdb_try_acquire(struct console *con, struct nbcon_write_context *wctxt) { return false; } static inline void nbcon_kdb_release(struct nbcon_write_context *wctxt) { } static inline bool console_is_usable(struct console *con, short flags, bool use_atomic) { return false; } #endif extern int console_set_on_cmdline; Loading
include/linux/kdb.h +16 −0 Original line number Diff line number Diff line Loading @@ -14,6 +14,7 @@ */ #include <linux/list.h> #include <linux/smp.h> /* Shifted versions of the command enable bits are be used if the command * has no arguments (see kdb_check_flags). This allows commands, such as Loading Loading @@ -207,11 +208,26 @@ static inline const char *kdb_walk_kallsyms(loff_t *pos) /* Dynamic kdb shell command registration */ extern int kdb_register(kdbtab_t *cmd); extern void kdb_unregister(kdbtab_t *cmd); /* Return true when KDB as locked for printing a message on this CPU. */ static inline bool kdb_printf_on_this_cpu(void) { /* * We can use raw_smp_processor_id() here because the task could * not get migrated when KDB has locked for printing on this CPU. */ return unlikely(READ_ONCE(kdb_printf_cpu) == raw_smp_processor_id()); } #else /* ! CONFIG_KGDB_KDB */ static inline __printf(1, 2) int kdb_printf(const char *fmt, ...) { return 0; } static inline void kdb_init(int level) {} static inline int kdb_register(kdbtab_t *cmd) { return 0; } static inline void kdb_unregister(kdbtab_t *cmd) {} static inline bool kdb_printf_on_this_cpu(void) { return false; } #endif /* CONFIG_KGDB_KDB */ enum { KDB_NOT_INITIALIZED, Loading
kernel/debug/kdb/kdb_io.c +32 −15 Original line number Diff line number Diff line Loading @@ -589,12 +589,28 @@ static void kdb_msg_write(const char *msg, int msg_len) */ cookie = console_srcu_read_lock(); for_each_console_srcu(c) { if (!(console_srcu_read_flags(c) & CON_ENABLED)) short flags = console_srcu_read_flags(c); if (!console_is_usable(c, flags, true)) continue; if (c == dbg_io_ops->cons) continue; if (!c->write) if (flags & CON_NBCON) { struct nbcon_write_context wctxt = { }; /* * Do not continue if the console is NBCON and the context * can't be acquired. */ if (!nbcon_kdb_try_acquire(c, &wctxt)) continue; nbcon_write_context_set_buf(&wctxt, (char *)msg, msg_len); c->write_atomic(c, &wctxt); nbcon_kdb_release(&wctxt); } else { /* * Set oops_in_progress to encourage the console drivers to * disregard their internal spin locks: in the current calling Loading @@ -607,6 +623,7 @@ static void kdb_msg_write(const char *msg, int msg_len) ++oops_in_progress; c->write(c, msg, msg_len); --oops_in_progress; } touch_nmi_watchdog(); } console_srcu_read_unlock(cookie); Loading