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.

Merge branch 'rework/nbcon-in-kdb' into for-linus

+176 -73
+1 -1
arch/um/kernel/kmsg_dump.c
··· 31 31 * expected to output the crash information. 32 32 */ 33 33 if (strcmp(con->name, "ttynull") != 0 && 34 - (console_srcu_read_flags(con) & CON_ENABLED)) { 34 + console_is_usable(con, console_srcu_read_flags(con), true)) { 35 35 break; 36 36 } 37 37 }
-1
drivers/tty/serial/kgdboc.c
··· 577 577 console_list_lock(); 578 578 for_each_console(con) { 579 579 if (con->write && con->read && 580 - (con->flags & (CON_BOOT | CON_ENABLED)) && 581 580 (!opt || !opt[0] || strcmp(con->name, opt) == 0)) 582 581 break; 583 582 }
+55
include/linux/console.h
··· 19 19 #include <linux/irq_work.h> 20 20 #include <linux/rculist.h> 21 21 #include <linux/rcuwait.h> 22 + #include <linux/smp.h> 22 23 #include <linux/types.h> 23 24 #include <linux/vesa.h> 24 25 ··· 603 602 extern void nbcon_cpu_emergency_enter(void); 604 603 extern void nbcon_cpu_emergency_exit(void); 605 604 extern bool nbcon_can_proceed(struct nbcon_write_context *wctxt); 605 + extern void nbcon_write_context_set_buf(struct nbcon_write_context *wctxt, 606 + char *buf, unsigned int len); 606 607 extern bool nbcon_enter_unsafe(struct nbcon_write_context *wctxt); 607 608 extern bool nbcon_exit_unsafe(struct nbcon_write_context *wctxt); 608 609 extern void nbcon_reacquire_nobuf(struct nbcon_write_context *wctxt); 610 + extern bool nbcon_kdb_try_acquire(struct console *con, 611 + struct nbcon_write_context *wctxt); 612 + extern void nbcon_kdb_release(struct nbcon_write_context *wctxt); 613 + 614 + /* 615 + * Check if the given console is currently capable and allowed to print 616 + * records. Note that this function does not consider the current context, 617 + * which can also play a role in deciding if @con can be used to print 618 + * records. 619 + */ 620 + static inline bool console_is_usable(struct console *con, short flags, bool use_atomic) 621 + { 622 + if (!(flags & CON_ENABLED)) 623 + return false; 624 + 625 + if ((flags & CON_SUSPENDED)) 626 + return false; 627 + 628 + if (flags & CON_NBCON) { 629 + /* The write_atomic() callback is optional. */ 630 + if (use_atomic && !con->write_atomic) 631 + return false; 632 + 633 + /* 634 + * For the !use_atomic case, @printk_kthreads_running is not 635 + * checked because the write_thread() callback is also used 636 + * via the legacy loop when the printer threads are not 637 + * available. 638 + */ 639 + } else { 640 + if (!con->write) 641 + return false; 642 + } 643 + 644 + /* 645 + * Console drivers may assume that per-cpu resources have been 646 + * allocated. So unless they're explicitly marked as being able to 647 + * cope (CON_ANYTIME) don't call them until this CPU is officially up. 648 + */ 649 + if (!cpu_online(raw_smp_processor_id()) && !(flags & CON_ANYTIME)) 650 + return false; 651 + 652 + return true; 653 + } 654 + 609 655 #else 610 656 static inline void nbcon_cpu_emergency_enter(void) { } 611 657 static inline void nbcon_cpu_emergency_exit(void) { } 612 658 static inline bool nbcon_can_proceed(struct nbcon_write_context *wctxt) { return false; } 659 + static inline void nbcon_write_context_set_buf(struct nbcon_write_context *wctxt, 660 + char *buf, unsigned int len) { } 613 661 static inline bool nbcon_enter_unsafe(struct nbcon_write_context *wctxt) { return false; } 614 662 static inline bool nbcon_exit_unsafe(struct nbcon_write_context *wctxt) { return false; } 615 663 static inline void nbcon_reacquire_nobuf(struct nbcon_write_context *wctxt) { } 664 + static inline bool nbcon_kdb_try_acquire(struct console *con, 665 + struct nbcon_write_context *wctxt) { return false; } 666 + static inline void nbcon_kdb_release(struct nbcon_write_context *wctxt) { } 667 + static inline bool console_is_usable(struct console *con, short flags, 668 + bool use_atomic) { return false; } 616 669 #endif 617 670 618 671 extern int console_set_on_cmdline;
+16
include/linux/kdb.h
··· 14 14 */ 15 15 16 16 #include <linux/list.h> 17 + #include <linux/smp.h> 17 18 18 19 /* Shifted versions of the command enable bits are be used if the command 19 20 * has no arguments (see kdb_check_flags). This allows commands, such as ··· 208 207 /* Dynamic kdb shell command registration */ 209 208 extern int kdb_register(kdbtab_t *cmd); 210 209 extern void kdb_unregister(kdbtab_t *cmd); 210 + 211 + /* Return true when KDB as locked for printing a message on this CPU. */ 212 + static inline 213 + bool kdb_printf_on_this_cpu(void) 214 + { 215 + /* 216 + * We can use raw_smp_processor_id() here because the task could 217 + * not get migrated when KDB has locked for printing on this CPU. 218 + */ 219 + return unlikely(READ_ONCE(kdb_printf_cpu) == raw_smp_processor_id()); 220 + } 221 + 211 222 #else /* ! CONFIG_KGDB_KDB */ 212 223 static inline __printf(1, 2) int kdb_printf(const char *fmt, ...) { return 0; } 213 224 static inline void kdb_init(int level) {} 214 225 static inline int kdb_register(kdbtab_t *cmd) { return 0; } 215 226 static inline void kdb_unregister(kdbtab_t *cmd) {} 227 + 228 + static inline bool kdb_printf_on_this_cpu(void) { return false; } 229 + 216 230 #endif /* CONFIG_KGDB_KDB */ 217 231 enum { 218 232 KDB_NOT_INITIALIZED,
+32 -15
kernel/debug/kdb/kdb_io.c
··· 589 589 */ 590 590 cookie = console_srcu_read_lock(); 591 591 for_each_console_srcu(c) { 592 - if (!(console_srcu_read_flags(c) & CON_ENABLED)) 592 + short flags = console_srcu_read_flags(c); 593 + 594 + if (!console_is_usable(c, flags, true)) 593 595 continue; 594 596 if (c == dbg_io_ops->cons) 595 597 continue; 596 - if (!c->write) 597 - continue; 598 - /* 599 - * Set oops_in_progress to encourage the console drivers to 600 - * disregard their internal spin locks: in the current calling 601 - * context the risk of deadlock is a bigger problem than risks 602 - * due to re-entering the console driver. We operate directly on 603 - * oops_in_progress rather than using bust_spinlocks() because 604 - * the calls bust_spinlocks() makes on exit are not appropriate 605 - * for this calling context. 606 - */ 607 - ++oops_in_progress; 608 - c->write(c, msg, msg_len); 609 - --oops_in_progress; 598 + 599 + if (flags & CON_NBCON) { 600 + struct nbcon_write_context wctxt = { }; 601 + 602 + /* 603 + * Do not continue if the console is NBCON and the context 604 + * can't be acquired. 605 + */ 606 + if (!nbcon_kdb_try_acquire(c, &wctxt)) 607 + continue; 608 + 609 + nbcon_write_context_set_buf(&wctxt, (char *)msg, msg_len); 610 + 611 + c->write_atomic(c, &wctxt); 612 + nbcon_kdb_release(&wctxt); 613 + } else { 614 + /* 615 + * Set oops_in_progress to encourage the console drivers to 616 + * disregard their internal spin locks: in the current calling 617 + * context the risk of deadlock is a bigger problem than risks 618 + * due to re-entering the console driver. We operate directly on 619 + * oops_in_progress rather than using bust_spinlocks() because 620 + * the calls bust_spinlocks() makes on exit are not appropriate 621 + * for this calling context. 622 + */ 623 + ++oops_in_progress; 624 + c->write(c, msg, msg_len); 625 + --oops_in_progress; 626 + } 610 627 touch_nmi_watchdog(); 611 628 } 612 629 console_srcu_read_unlock(cookie);
-45
kernel/printk/internal.h
··· 3 3 * internal.h - printk internal definitions 4 4 */ 5 5 #include <linux/console.h> 6 - #include <linux/percpu.h> 7 6 #include <linux/types.h> 8 7 9 8 #if defined(CONFIG_PRINTK) && defined(CONFIG_SYSCTL) ··· 111 112 void nbcon_kthread_stop(struct console *con); 112 113 void nbcon_kthreads_wake(void); 113 114 114 - /* 115 - * Check if the given console is currently capable and allowed to print 116 - * records. Note that this function does not consider the current context, 117 - * which can also play a role in deciding if @con can be used to print 118 - * records. 119 - */ 120 - static inline bool console_is_usable(struct console *con, short flags, bool use_atomic) 121 - { 122 - if (!(flags & CON_ENABLED)) 123 - return false; 124 - 125 - if ((flags & CON_SUSPENDED)) 126 - return false; 127 - 128 - if (flags & CON_NBCON) { 129 - /* The write_atomic() callback is optional. */ 130 - if (use_atomic && !con->write_atomic) 131 - return false; 132 - 133 - /* 134 - * For the !use_atomic case, @printk_kthreads_running is not 135 - * checked because the write_thread() callback is also used 136 - * via the legacy loop when the printer threads are not 137 - * available. 138 - */ 139 - } else { 140 - if (!con->write) 141 - return false; 142 - } 143 - 144 - /* 145 - * Console drivers may assume that per-cpu resources have been 146 - * allocated. So unless they're explicitly marked as being able to 147 - * cope (CON_ANYTIME) don't call them until this CPU is officially up. 148 - */ 149 - if (!cpu_online(raw_smp_processor_id()) && !(flags & CON_ANYTIME)) 150 - return false; 151 - 152 - return true; 153 - } 154 - 155 115 /** 156 116 * nbcon_kthread_wake - Wake up a console printing thread 157 117 * @con: Console to operate on ··· 161 203 int cookie, bool use_atomic) { return false; } 162 204 static inline void nbcon_kthread_wake(struct console *con) { } 163 205 static inline void nbcon_kthreads_wake(void) { } 164 - 165 - static inline bool console_is_usable(struct console *con, short flags, 166 - bool use_atomic) { return false; } 167 206 168 207 #endif /* CONFIG_PRINTK */ 169 208
+68 -3
kernel/printk/nbcon.c
··· 10 10 #include <linux/export.h> 11 11 #include <linux/init.h> 12 12 #include <linux/irqflags.h> 13 + #include <linux/kdb.h> 13 14 #include <linux/kthread.h> 14 15 #include <linux/minmax.h> 15 16 #include <linux/panic.h> ··· 253 252 * since all non-panic CPUs are stopped during panic(), it 254 253 * is safer to have them avoid gaining console ownership. 255 254 * 256 - * If this acquire is a reacquire (and an unsafe takeover 255 + * One exception is when kdb has locked for printing on this CPU. 256 + * 257 + * Second exception is a reacquire (and an unsafe takeover 257 258 * has not previously occurred) then it is allowed to attempt 258 259 * a direct acquire in panic. This gives console drivers an 259 260 * opportunity to perform any necessary cleanup if they were 260 261 * interrupted by the panic CPU while printing. 261 262 */ 262 263 if (panic_on_other_cpu() && 264 + !kdb_printf_on_this_cpu() && 263 265 (!is_reacquire || cur->unsafe_takeover)) { 264 266 return -EPERM; 265 267 } ··· 857 853 return nbcon_context_can_proceed(ctxt, &cur); 858 854 } 859 855 860 - static void nbcon_write_context_set_buf(struct nbcon_write_context *wctxt, 861 - char *buf, unsigned int len) 856 + void nbcon_write_context_set_buf(struct nbcon_write_context *wctxt, 857 + char *buf, unsigned int len) 862 858 { 863 859 struct nbcon_context *ctxt = &ACCESS_PRIVATE(wctxt, ctxt); 864 860 struct console *con = ctxt->console; ··· 1898 1894 console_srcu_read_unlock(cookie); 1899 1895 } 1900 1896 EXPORT_SYMBOL_GPL(nbcon_device_release); 1897 + 1898 + /** 1899 + * nbcon_kdb_try_acquire - Try to acquire nbcon console and enter unsafe 1900 + * section 1901 + * @con: The nbcon console to acquire 1902 + * @wctxt: The nbcon write context to be used on success 1903 + * 1904 + * Context: Under console_srcu_read_lock() for emitting a single kdb message 1905 + * using the given con->write_atomic() callback. Can be called 1906 + * only when the console is usable at the moment. 1907 + * 1908 + * Return: True if the console was acquired. False otherwise. 1909 + * 1910 + * kdb emits messages on consoles registered for printk() without 1911 + * storing them into the ring buffer. It has to acquire the console 1912 + * ownerhip so that it could call con->write_atomic() callback a safe way. 1913 + * 1914 + * This function acquires the nbcon console using priority NBCON_PRIO_EMERGENCY 1915 + * and marks it unsafe for handover/takeover. 1916 + */ 1917 + bool nbcon_kdb_try_acquire(struct console *con, 1918 + struct nbcon_write_context *wctxt) 1919 + { 1920 + struct nbcon_context *ctxt = &ACCESS_PRIVATE(wctxt, ctxt); 1921 + 1922 + memset(ctxt, 0, sizeof(*ctxt)); 1923 + ctxt->console = con; 1924 + ctxt->prio = NBCON_PRIO_EMERGENCY; 1925 + 1926 + if (!nbcon_context_try_acquire(ctxt, false)) 1927 + return false; 1928 + 1929 + if (!nbcon_context_enter_unsafe(ctxt)) 1930 + return false; 1931 + 1932 + return true; 1933 + } 1934 + 1935 + /** 1936 + * nbcon_kdb_release - Exit unsafe section and release the nbcon console 1937 + * 1938 + * @wctxt: The nbcon write context initialized by a successful 1939 + * nbcon_kdb_try_acquire() 1940 + */ 1941 + void nbcon_kdb_release(struct nbcon_write_context *wctxt) 1942 + { 1943 + struct nbcon_context *ctxt = &ACCESS_PRIVATE(wctxt, ctxt); 1944 + 1945 + if (!nbcon_context_exit_unsafe(ctxt)) 1946 + return; 1947 + 1948 + nbcon_context_release(ctxt); 1949 + 1950 + /* 1951 + * Flush any new printk() messages added when the console was blocked. 1952 + * Only the console used by the given write context was blocked. 1953 + * The console was locked only when the write_atomic() callback 1954 + * was usable. 1955 + */ 1956 + __nbcon_atomic_flush_pending_con(ctxt->console, prb_next_reserve_seq(prb), false); 1957 + }
+4 -8
kernel/printk/printk.c
··· 3331 3331 */ 3332 3332 cookie = console_srcu_read_lock(); 3333 3333 for_each_console_srcu(c) { 3334 - short flags = console_srcu_read_flags(c); 3335 - 3336 - if (flags & CON_SUSPENDED) 3334 + if (!console_is_usable(c, console_srcu_read_flags(c), true)) 3337 3335 continue; 3338 3336 3339 - if ((flags & CON_ENABLED) && c->unblank) { 3337 + if (c->unblank) { 3340 3338 found_unblank = true; 3341 3339 break; 3342 3340 } ··· 3371 3373 3372 3374 cookie = console_srcu_read_lock(); 3373 3375 for_each_console_srcu(c) { 3374 - short flags = console_srcu_read_flags(c); 3375 - 3376 - if (flags & CON_SUSPENDED) 3376 + if (!console_is_usable(c, console_srcu_read_flags(c), true)) 3377 3377 continue; 3378 3378 3379 - if ((flags & CON_ENABLED) && c->unblank) 3379 + if (c->unblank) 3380 3380 c->unblank(); 3381 3381 } 3382 3382 console_srcu_read_unlock(cookie);