diff options
Diffstat (limited to 'kernel/printk/printk.c')
-rw-r--r-- | kernel/printk/printk.c | 26 |
1 files changed, 25 insertions, 1 deletions
diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c index 2ce8826f1053..0c9f02506169 100644 --- a/kernel/printk/printk.c +++ b/kernel/printk/printk.c | |||
@@ -48,6 +48,7 @@ | |||
48 | #include <linux/uio.h> | 48 | #include <linux/uio.h> |
49 | 49 | ||
50 | #include <asm/uaccess.h> | 50 | #include <asm/uaccess.h> |
51 | #include <asm-generic/sections.h> | ||
51 | 52 | ||
52 | #define CREATE_TRACE_POINTS | 53 | #define CREATE_TRACE_POINTS |
53 | #include <trace/events/printk.h> | 54 | #include <trace/events/printk.h> |
@@ -2658,13 +2659,36 @@ int unregister_console(struct console *console) | |||
2658 | } | 2659 | } |
2659 | EXPORT_SYMBOL(unregister_console); | 2660 | EXPORT_SYMBOL(unregister_console); |
2660 | 2661 | ||
2662 | /* | ||
2663 | * Some boot consoles access data that is in the init section and which will | ||
2664 | * be discarded after the initcalls have been run. To make sure that no code | ||
2665 | * will access this data, unregister the boot consoles in a late initcall. | ||
2666 | * | ||
2667 | * If for some reason, such as deferred probe or the driver being a loadable | ||
2668 | * module, the real console hasn't registered yet at this point, there will | ||
2669 | * be a brief interval in which no messages are logged to the console, which | ||
2670 | * makes it difficult to diagnose problems that occur during this time. | ||
2671 | * | ||
2672 | * To mitigate this problem somewhat, only unregister consoles whose memory | ||
2673 | * intersects with the init section. Note that code exists elsewhere to get | ||
2674 | * rid of the boot console as soon as the proper console shows up, so there | ||
2675 | * won't be side-effects from postponing the removal. | ||
2676 | */ | ||
2661 | static int __init printk_late_init(void) | 2677 | static int __init printk_late_init(void) |
2662 | { | 2678 | { |
2663 | struct console *con; | 2679 | struct console *con; |
2664 | 2680 | ||
2665 | for_each_console(con) { | 2681 | for_each_console(con) { |
2666 | if (!keep_bootcon && con->flags & CON_BOOT) { | 2682 | if (!keep_bootcon && con->flags & CON_BOOT) { |
2667 | unregister_console(con); | 2683 | /* |
2684 | * Make sure to unregister boot consoles whose data | ||
2685 | * resides in the init section before the init section | ||
2686 | * is discarded. Boot consoles whose data will stick | ||
2687 | * around will automatically be unregistered when the | ||
2688 | * proper console replaces them. | ||
2689 | */ | ||
2690 | if (init_section_intersects(con, sizeof(*con))) | ||
2691 | unregister_console(con); | ||
2668 | } | 2692 | } |
2669 | } | 2693 | } |
2670 | hotcpu_notifier(console_cpu_notify, 0); | 2694 | hotcpu_notifier(console_cpu_notify, 0); |