diff options
-rw-r--r-- | arch/Kconfig | 4 | ||||
-rw-r--r-- | arch/arm/Kconfig | 1 | ||||
-rw-r--r-- | arch/arm/kernel/smp.c | 2 | ||||
-rw-r--r-- | arch/avr32/Kconfig | 1 | ||||
-rw-r--r-- | arch/blackfin/Kconfig | 1 | ||||
-rw-r--r-- | arch/cris/Kconfig | 1 | ||||
-rw-r--r-- | arch/mips/Kconfig | 1 | ||||
-rw-r--r-- | arch/powerpc/Kconfig | 1 | ||||
-rw-r--r-- | arch/s390/Kconfig | 1 | ||||
-rw-r--r-- | arch/sh/Kconfig | 1 | ||||
-rw-r--r-- | arch/sparc/Kconfig | 1 | ||||
-rw-r--r-- | arch/tile/Kconfig | 1 | ||||
-rw-r--r-- | arch/x86/Kconfig | 1 | ||||
-rw-r--r-- | arch/x86/kernel/apic/hw_nmi.c | 1 | ||||
-rw-r--r-- | include/linux/hardirq.h | 2 | ||||
-rw-r--r-- | include/linux/percpu.h | 3 | ||||
-rw-r--r-- | include/linux/printk.h | 12 | ||||
-rw-r--r-- | init/Kconfig | 5 | ||||
-rw-r--r-- | init/main.c | 1 | ||||
-rw-r--r-- | kernel/printk/Makefile | 1 | ||||
-rw-r--r-- | kernel/printk/internal.h | 44 | ||||
-rw-r--r-- | kernel/printk/nmi.c | 219 | ||||
-rw-r--r-- | kernel/printk/printk.c | 19 | ||||
-rw-r--r-- | lib/nmi_backtrace.c | 89 |
24 files changed, 306 insertions, 107 deletions
diff --git a/arch/Kconfig b/arch/Kconfig index 0f298f9123dc..8f84fd268dee 100644 --- a/arch/Kconfig +++ b/arch/Kconfig | |||
@@ -187,7 +187,11 @@ config HAVE_OPTPROBES | |||
187 | config HAVE_KPROBES_ON_FTRACE | 187 | config HAVE_KPROBES_ON_FTRACE |
188 | bool | 188 | bool |
189 | 189 | ||
190 | config HAVE_NMI | ||
191 | bool | ||
192 | |||
190 | config HAVE_NMI_WATCHDOG | 193 | config HAVE_NMI_WATCHDOG |
194 | depends on HAVE_NMI | ||
191 | bool | 195 | bool |
192 | # | 196 | # |
193 | # An arch should select this if it provides all these things: | 197 | # An arch should select this if it provides all these things: |
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 956d3575426c..90542db1220d 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig | |||
@@ -67,6 +67,7 @@ config ARM | |||
67 | select HAVE_KRETPROBES if (HAVE_KPROBES) | 67 | select HAVE_KRETPROBES if (HAVE_KPROBES) |
68 | select HAVE_MEMBLOCK | 68 | select HAVE_MEMBLOCK |
69 | select HAVE_MOD_ARCH_SPECIFIC | 69 | select HAVE_MOD_ARCH_SPECIFIC |
70 | select HAVE_NMI | ||
70 | select HAVE_OPROFILE if (HAVE_PERF_EVENTS) | 71 | select HAVE_OPROFILE if (HAVE_PERF_EVENTS) |
71 | select HAVE_OPTPROBES if !THUMB2_KERNEL | 72 | select HAVE_OPTPROBES if !THUMB2_KERNEL |
72 | select HAVE_PERF_EVENTS | 73 | select HAVE_PERF_EVENTS |
diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c index baee70267f29..df90bc59bfce 100644 --- a/arch/arm/kernel/smp.c +++ b/arch/arm/kernel/smp.c | |||
@@ -644,9 +644,11 @@ void handle_IPI(int ipinr, struct pt_regs *regs) | |||
644 | break; | 644 | break; |
645 | 645 | ||
646 | case IPI_CPU_BACKTRACE: | 646 | case IPI_CPU_BACKTRACE: |
647 | printk_nmi_enter(); | ||
647 | irq_enter(); | 648 | irq_enter(); |
648 | nmi_cpu_backtrace(regs); | 649 | nmi_cpu_backtrace(regs); |
649 | irq_exit(); | 650 | irq_exit(); |
651 | printk_nmi_exit(); | ||
650 | break; | 652 | break; |
651 | 653 | ||
652 | default: | 654 | default: |
diff --git a/arch/avr32/Kconfig b/arch/avr32/Kconfig index e43519a2ca89..7e75d45e20cd 100644 --- a/arch/avr32/Kconfig +++ b/arch/avr32/Kconfig | |||
@@ -18,6 +18,7 @@ config AVR32 | |||
18 | select GENERIC_CLOCKEVENTS | 18 | select GENERIC_CLOCKEVENTS |
19 | select HAVE_MOD_ARCH_SPECIFIC | 19 | select HAVE_MOD_ARCH_SPECIFIC |
20 | select MODULES_USE_ELF_RELA | 20 | select MODULES_USE_ELF_RELA |
21 | select HAVE_NMI | ||
21 | help | 22 | help |
22 | AVR32 is a high-performance 32-bit RISC microprocessor core, | 23 | AVR32 is a high-performance 32-bit RISC microprocessor core, |
23 | designed for cost-sensitive embedded applications, with particular | 24 | designed for cost-sensitive embedded applications, with particular |
diff --git a/arch/blackfin/Kconfig b/arch/blackfin/Kconfig index a63c12259e77..28c63fea786d 100644 --- a/arch/blackfin/Kconfig +++ b/arch/blackfin/Kconfig | |||
@@ -40,6 +40,7 @@ config BLACKFIN | |||
40 | select HAVE_MOD_ARCH_SPECIFIC | 40 | select HAVE_MOD_ARCH_SPECIFIC |
41 | select MODULES_USE_ELF_RELA | 41 | select MODULES_USE_ELF_RELA |
42 | select HAVE_DEBUG_STACKOVERFLOW | 42 | select HAVE_DEBUG_STACKOVERFLOW |
43 | select HAVE_NMI | ||
43 | 44 | ||
44 | config GENERIC_CSUM | 45 | config GENERIC_CSUM |
45 | def_bool y | 46 | def_bool y |
diff --git a/arch/cris/Kconfig b/arch/cris/Kconfig index 5c0ca8ae9293..deba2662b9f3 100644 --- a/arch/cris/Kconfig +++ b/arch/cris/Kconfig | |||
@@ -70,6 +70,7 @@ config CRIS | |||
70 | select GENERIC_CLOCKEVENTS if ETRAX_ARCH_V32 | 70 | select GENERIC_CLOCKEVENTS if ETRAX_ARCH_V32 |
71 | select GENERIC_SCHED_CLOCK if ETRAX_ARCH_V32 | 71 | select GENERIC_SCHED_CLOCK if ETRAX_ARCH_V32 |
72 | select HAVE_DEBUG_BUGVERBOSE if ETRAX_ARCH_V32 | 72 | select HAVE_DEBUG_BUGVERBOSE if ETRAX_ARCH_V32 |
73 | select HAVE_NMI | ||
73 | 74 | ||
74 | config HZ | 75 | config HZ |
75 | int | 76 | int |
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 5663f411c225..8040fb1845b4 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig | |||
@@ -48,6 +48,7 @@ config MIPS | |||
48 | select GENERIC_SCHED_CLOCK if !CAVIUM_OCTEON_SOC | 48 | select GENERIC_SCHED_CLOCK if !CAVIUM_OCTEON_SOC |
49 | select GENERIC_CMOS_UPDATE | 49 | select GENERIC_CMOS_UPDATE |
50 | select HAVE_MOD_ARCH_SPECIFIC | 50 | select HAVE_MOD_ARCH_SPECIFIC |
51 | select HAVE_NMI | ||
51 | select VIRT_TO_BUS | 52 | select VIRT_TO_BUS |
52 | select MODULES_USE_ELF_REL if MODULES | 53 | select MODULES_USE_ELF_REL if MODULES |
53 | select MODULES_USE_ELF_RELA if MODULES && 64BIT | 54 | select MODULES_USE_ELF_RELA if MODULES && 64BIT |
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index f0403b58ae8b..01f7464d9fea 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig | |||
@@ -155,6 +155,7 @@ config PPC | |||
155 | select NO_BOOTMEM | 155 | select NO_BOOTMEM |
156 | select HAVE_GENERIC_RCU_GUP | 156 | select HAVE_GENERIC_RCU_GUP |
157 | select HAVE_PERF_EVENTS_NMI if PPC64 | 157 | select HAVE_PERF_EVENTS_NMI if PPC64 |
158 | select HAVE_NMI if PERF_EVENTS | ||
158 | select EDAC_SUPPORT | 159 | select EDAC_SUPPORT |
159 | select EDAC_ATOMIC_SCRUB | 160 | select EDAC_ATOMIC_SCRUB |
160 | select ARCH_HAS_DMA_SET_COHERENT_MASK | 161 | select ARCH_HAS_DMA_SET_COHERENT_MASK |
diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig index e2c9aaaf64b2..1c3c43d9d1b5 100644 --- a/arch/s390/Kconfig +++ b/arch/s390/Kconfig | |||
@@ -166,6 +166,7 @@ config S390 | |||
166 | select TTY | 166 | select TTY |
167 | select VIRT_CPU_ACCOUNTING | 167 | select VIRT_CPU_ACCOUNTING |
168 | select VIRT_TO_BUS | 168 | select VIRT_TO_BUS |
169 | select HAVE_NMI | ||
169 | 170 | ||
170 | 171 | ||
171 | config SCHED_OMIT_FRAME_POINTER | 172 | config SCHED_OMIT_FRAME_POINTER |
diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig index cb93af8f8017..f6254341c065 100644 --- a/arch/sh/Kconfig +++ b/arch/sh/Kconfig | |||
@@ -44,6 +44,7 @@ config SUPERH | |||
44 | select OLD_SIGSUSPEND | 44 | select OLD_SIGSUSPEND |
45 | select OLD_SIGACTION | 45 | select OLD_SIGACTION |
46 | select HAVE_ARCH_AUDITSYSCALL | 46 | select HAVE_ARCH_AUDITSYSCALL |
47 | select HAVE_NMI | ||
47 | help | 48 | help |
48 | The SuperH is a RISC processor targeted for use in embedded systems | 49 | The SuperH is a RISC processor targeted for use in embedded systems |
49 | and consumer electronics; it was also used in the Sega Dreamcast | 50 | and consumer electronics; it was also used in the Sega Dreamcast |
diff --git a/arch/sparc/Kconfig b/arch/sparc/Kconfig index 27b3a0ad40a0..1012f7ffcdf5 100644 --- a/arch/sparc/Kconfig +++ b/arch/sparc/Kconfig | |||
@@ -79,6 +79,7 @@ config SPARC64 | |||
79 | select NO_BOOTMEM | 79 | select NO_BOOTMEM |
80 | select HAVE_ARCH_AUDITSYSCALL | 80 | select HAVE_ARCH_AUDITSYSCALL |
81 | select ARCH_SUPPORTS_ATOMIC_RMW | 81 | select ARCH_SUPPORTS_ATOMIC_RMW |
82 | select HAVE_NMI | ||
82 | 83 | ||
83 | config ARCH_DEFCONFIG | 84 | config ARCH_DEFCONFIG |
84 | string | 85 | string |
diff --git a/arch/tile/Kconfig b/arch/tile/Kconfig index 174746225577..76989b878f3c 100644 --- a/arch/tile/Kconfig +++ b/arch/tile/Kconfig | |||
@@ -30,6 +30,7 @@ config TILE | |||
30 | select HAVE_DEBUG_STACKOVERFLOW | 30 | select HAVE_DEBUG_STACKOVERFLOW |
31 | select ARCH_WANT_FRAME_POINTERS | 31 | select ARCH_WANT_FRAME_POINTERS |
32 | select HAVE_CONTEXT_TRACKING | 32 | select HAVE_CONTEXT_TRACKING |
33 | select HAVE_NMI if USE_PMC | ||
33 | select EDAC_SUPPORT | 34 | select EDAC_SUPPORT |
34 | select GENERIC_STRNCPY_FROM_USER | 35 | select GENERIC_STRNCPY_FROM_USER |
35 | select GENERIC_STRNLEN_USER | 36 | select GENERIC_STRNLEN_USER |
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 8ff5b3be95d4..0a7b885964ba 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig | |||
@@ -131,6 +131,7 @@ config X86 | |||
131 | select HAVE_MEMBLOCK | 131 | select HAVE_MEMBLOCK |
132 | select HAVE_MEMBLOCK_NODE_MAP | 132 | select HAVE_MEMBLOCK_NODE_MAP |
133 | select HAVE_MIXED_BREAKPOINTS_REGS | 133 | select HAVE_MIXED_BREAKPOINTS_REGS |
134 | select HAVE_NMI | ||
134 | select HAVE_OPROFILE | 135 | select HAVE_OPROFILE |
135 | select HAVE_OPTPROBES | 136 | select HAVE_OPTPROBES |
136 | select HAVE_PCSPKR_PLATFORM | 137 | select HAVE_PCSPKR_PLATFORM |
diff --git a/arch/x86/kernel/apic/hw_nmi.c b/arch/x86/kernel/apic/hw_nmi.c index 045e424fb368..7788ce643bf4 100644 --- a/arch/x86/kernel/apic/hw_nmi.c +++ b/arch/x86/kernel/apic/hw_nmi.c | |||
@@ -18,7 +18,6 @@ | |||
18 | #include <linux/nmi.h> | 18 | #include <linux/nmi.h> |
19 | #include <linux/module.h> | 19 | #include <linux/module.h> |
20 | #include <linux/delay.h> | 20 | #include <linux/delay.h> |
21 | #include <linux/seq_buf.h> | ||
22 | 21 | ||
23 | #ifdef CONFIG_HARDLOCKUP_DETECTOR | 22 | #ifdef CONFIG_HARDLOCKUP_DETECTOR |
24 | u64 hw_nmi_get_sample_period(int watchdog_thresh) | 23 | u64 hw_nmi_get_sample_period(int watchdog_thresh) |
diff --git a/include/linux/hardirq.h b/include/linux/hardirq.h index dfd59d6bc6f0..c683996110b1 100644 --- a/include/linux/hardirq.h +++ b/include/linux/hardirq.h | |||
@@ -61,6 +61,7 @@ extern void irq_exit(void); | |||
61 | 61 | ||
62 | #define nmi_enter() \ | 62 | #define nmi_enter() \ |
63 | do { \ | 63 | do { \ |
64 | printk_nmi_enter(); \ | ||
64 | lockdep_off(); \ | 65 | lockdep_off(); \ |
65 | ftrace_nmi_enter(); \ | 66 | ftrace_nmi_enter(); \ |
66 | BUG_ON(in_nmi()); \ | 67 | BUG_ON(in_nmi()); \ |
@@ -77,6 +78,7 @@ extern void irq_exit(void); | |||
77 | preempt_count_sub(NMI_OFFSET + HARDIRQ_OFFSET); \ | 78 | preempt_count_sub(NMI_OFFSET + HARDIRQ_OFFSET); \ |
78 | ftrace_nmi_exit(); \ | 79 | ftrace_nmi_exit(); \ |
79 | lockdep_on(); \ | 80 | lockdep_on(); \ |
81 | printk_nmi_exit(); \ | ||
80 | } while (0) | 82 | } while (0) |
81 | 83 | ||
82 | #endif /* LINUX_HARDIRQ_H */ | 84 | #endif /* LINUX_HARDIRQ_H */ |
diff --git a/include/linux/percpu.h b/include/linux/percpu.h index 4bc6dafb703e..56939d3f6e53 100644 --- a/include/linux/percpu.h +++ b/include/linux/percpu.h | |||
@@ -129,7 +129,4 @@ extern phys_addr_t per_cpu_ptr_to_phys(void *addr); | |||
129 | (typeof(type) __percpu *)__alloc_percpu(sizeof(type), \ | 129 | (typeof(type) __percpu *)__alloc_percpu(sizeof(type), \ |
130 | __alignof__(type)) | 130 | __alignof__(type)) |
131 | 131 | ||
132 | /* To avoid include hell, as printk can not declare this, we declare it here */ | ||
133 | DECLARE_PER_CPU(printk_func_t, printk_func); | ||
134 | |||
135 | #endif /* __LINUX_PERCPU_H */ | 132 | #endif /* __LINUX_PERCPU_H */ |
diff --git a/include/linux/printk.h b/include/linux/printk.h index 9ccbdf2c1453..51dd6b824fe2 100644 --- a/include/linux/printk.h +++ b/include/linux/printk.h | |||
@@ -122,7 +122,17 @@ static inline __printf(1, 2) __cold | |||
122 | void early_printk(const char *s, ...) { } | 122 | void early_printk(const char *s, ...) { } |
123 | #endif | 123 | #endif |
124 | 124 | ||
125 | typedef __printf(1, 0) int (*printk_func_t)(const char *fmt, va_list args); | 125 | #ifdef CONFIG_PRINTK_NMI |
126 | extern void printk_nmi_init(void); | ||
127 | extern void printk_nmi_enter(void); | ||
128 | extern void printk_nmi_exit(void); | ||
129 | extern void printk_nmi_flush(void); | ||
130 | #else | ||
131 | static inline void printk_nmi_init(void) { } | ||
132 | static inline void printk_nmi_enter(void) { } | ||
133 | static inline void printk_nmi_exit(void) { } | ||
134 | static inline void printk_nmi_flush(void) { } | ||
135 | #endif /* PRINTK_NMI */ | ||
126 | 136 | ||
127 | #ifdef CONFIG_PRINTK | 137 | #ifdef CONFIG_PRINTK |
128 | asmlinkage __printf(5, 0) | 138 | asmlinkage __printf(5, 0) |
diff --git a/init/Kconfig b/init/Kconfig index 79a91a2c0444..bccc1d607be5 100644 --- a/init/Kconfig +++ b/init/Kconfig | |||
@@ -1454,6 +1454,11 @@ config PRINTK | |||
1454 | very difficult to diagnose system problems, saying N here is | 1454 | very difficult to diagnose system problems, saying N here is |
1455 | strongly discouraged. | 1455 | strongly discouraged. |
1456 | 1456 | ||
1457 | config PRINTK_NMI | ||
1458 | def_bool y | ||
1459 | depends on PRINTK | ||
1460 | depends on HAVE_NMI | ||
1461 | |||
1457 | config BUG | 1462 | config BUG |
1458 | bool "BUG() support" if EXPERT | 1463 | bool "BUG() support" if EXPERT |
1459 | default y | 1464 | default y |
diff --git a/init/main.c b/init/main.c index 2075fafaad59..fa9b2bdde183 100644 --- a/init/main.c +++ b/init/main.c | |||
@@ -569,6 +569,7 @@ asmlinkage __visible void __init start_kernel(void) | |||
569 | timekeeping_init(); | 569 | timekeeping_init(); |
570 | time_init(); | 570 | time_init(); |
571 | sched_clock_postinit(); | 571 | sched_clock_postinit(); |
572 | printk_nmi_init(); | ||
572 | perf_event_init(); | 573 | perf_event_init(); |
573 | profile_init(); | 574 | profile_init(); |
574 | call_function_init(); | 575 | call_function_init(); |
diff --git a/kernel/printk/Makefile b/kernel/printk/Makefile index 85405bdcf2b3..abb0042a427b 100644 --- a/kernel/printk/Makefile +++ b/kernel/printk/Makefile | |||
@@ -1,2 +1,3 @@ | |||
1 | obj-y = printk.o | 1 | obj-y = printk.o |
2 | obj-$(CONFIG_PRINTK_NMI) += nmi.o | ||
2 | obj-$(CONFIG_A11Y_BRAILLE_CONSOLE) += braille.o | 3 | obj-$(CONFIG_A11Y_BRAILLE_CONSOLE) += braille.o |
diff --git a/kernel/printk/internal.h b/kernel/printk/internal.h new file mode 100644 index 000000000000..2de99faedfc1 --- /dev/null +++ b/kernel/printk/internal.h | |||
@@ -0,0 +1,44 @@ | |||
1 | /* | ||
2 | * internal.h - printk internal definitions | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or | ||
5 | * modify it under the terms of the GNU General Public License | ||
6 | * as published by the Free Software Foundation; either version 2 | ||
7 | * of the License, or (at your option) any later version. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License | ||
15 | * along with this program; if not, see <http://www.gnu.org/licenses/>. | ||
16 | */ | ||
17 | #include <linux/percpu.h> | ||
18 | |||
19 | typedef __printf(1, 0) int (*printk_func_t)(const char *fmt, va_list args); | ||
20 | |||
21 | int __printf(1, 0) vprintk_default(const char *fmt, va_list args); | ||
22 | |||
23 | #ifdef CONFIG_PRINTK_NMI | ||
24 | |||
25 | /* | ||
26 | * printk() could not take logbuf_lock in NMI context. Instead, | ||
27 | * it temporary stores the strings into a per-CPU buffer. | ||
28 | * The alternative implementation is chosen transparently | ||
29 | * via per-CPU variable. | ||
30 | */ | ||
31 | DECLARE_PER_CPU(printk_func_t, printk_func); | ||
32 | static inline __printf(1, 0) int vprintk_func(const char *fmt, va_list args) | ||
33 | { | ||
34 | return this_cpu_read(printk_func)(fmt, args); | ||
35 | } | ||
36 | |||
37 | #else /* CONFIG_PRINTK_NMI */ | ||
38 | |||
39 | static inline __printf(1, 0) int vprintk_func(const char *fmt, va_list args) | ||
40 | { | ||
41 | return vprintk_default(fmt, args); | ||
42 | } | ||
43 | |||
44 | #endif /* CONFIG_PRINTK_NMI */ | ||
diff --git a/kernel/printk/nmi.c b/kernel/printk/nmi.c new file mode 100644 index 000000000000..303cf0d15e57 --- /dev/null +++ b/kernel/printk/nmi.c | |||
@@ -0,0 +1,219 @@ | |||
1 | /* | ||
2 | * nmi.c - Safe printk in NMI context | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or | ||
5 | * modify it under the terms of the GNU General Public License | ||
6 | * as published by the Free Software Foundation; either version 2 | ||
7 | * of the License, or (at your option) any later version. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License | ||
15 | * along with this program; if not, see <http://www.gnu.org/licenses/>. | ||
16 | */ | ||
17 | |||
18 | #include <linux/preempt.h> | ||
19 | #include <linux/spinlock.h> | ||
20 | #include <linux/smp.h> | ||
21 | #include <linux/cpumask.h> | ||
22 | #include <linux/irq_work.h> | ||
23 | #include <linux/printk.h> | ||
24 | |||
25 | #include "internal.h" | ||
26 | |||
27 | /* | ||
28 | * printk() could not take logbuf_lock in NMI context. Instead, | ||
29 | * it uses an alternative implementation that temporary stores | ||
30 | * the strings into a per-CPU buffer. The content of the buffer | ||
31 | * is later flushed into the main ring buffer via IRQ work. | ||
32 | * | ||
33 | * The alternative implementation is chosen transparently | ||
34 | * via @printk_func per-CPU variable. | ||
35 | * | ||
36 | * The implementation allows to flush the strings also from another CPU. | ||
37 | * There are situations when we want to make sure that all buffers | ||
38 | * were handled or when IRQs are blocked. | ||
39 | */ | ||
40 | DEFINE_PER_CPU(printk_func_t, printk_func) = vprintk_default; | ||
41 | static int printk_nmi_irq_ready; | ||
42 | |||
43 | #define NMI_LOG_BUF_LEN (4096 - sizeof(atomic_t) - sizeof(struct irq_work)) | ||
44 | |||
45 | struct nmi_seq_buf { | ||
46 | atomic_t len; /* length of written data */ | ||
47 | struct irq_work work; /* IRQ work that flushes the buffer */ | ||
48 | unsigned char buffer[NMI_LOG_BUF_LEN]; | ||
49 | }; | ||
50 | static DEFINE_PER_CPU(struct nmi_seq_buf, nmi_print_seq); | ||
51 | |||
52 | /* | ||
53 | * Safe printk() for NMI context. It uses a per-CPU buffer to | ||
54 | * store the message. NMIs are not nested, so there is always only | ||
55 | * one writer running. But the buffer might get flushed from another | ||
56 | * CPU, so we need to be careful. | ||
57 | */ | ||
58 | static int vprintk_nmi(const char *fmt, va_list args) | ||
59 | { | ||
60 | struct nmi_seq_buf *s = this_cpu_ptr(&nmi_print_seq); | ||
61 | int add = 0; | ||
62 | size_t len; | ||
63 | |||
64 | again: | ||
65 | len = atomic_read(&s->len); | ||
66 | |||
67 | if (len >= sizeof(s->buffer)) | ||
68 | return 0; | ||
69 | |||
70 | /* | ||
71 | * Make sure that all old data have been read before the buffer was | ||
72 | * reseted. This is not needed when we just append data. | ||
73 | */ | ||
74 | if (!len) | ||
75 | smp_rmb(); | ||
76 | |||
77 | add = vsnprintf(s->buffer + len, sizeof(s->buffer) - len, fmt, args); | ||
78 | |||
79 | /* | ||
80 | * Do it once again if the buffer has been flushed in the meantime. | ||
81 | * Note that atomic_cmpxchg() is an implicit memory barrier that | ||
82 | * makes sure that the data were written before updating s->len. | ||
83 | */ | ||
84 | if (atomic_cmpxchg(&s->len, len, len + add) != len) | ||
85 | goto again; | ||
86 | |||
87 | /* Get flushed in a more safe context. */ | ||
88 | if (add && printk_nmi_irq_ready) { | ||
89 | /* Make sure that IRQ work is really initialized. */ | ||
90 | smp_rmb(); | ||
91 | irq_work_queue(&s->work); | ||
92 | } | ||
93 | |||
94 | return add; | ||
95 | } | ||
96 | |||
97 | /* | ||
98 | * printk one line from the temporary buffer from @start index until | ||
99 | * and including the @end index. | ||
100 | */ | ||
101 | static void print_nmi_seq_line(struct nmi_seq_buf *s, int start, int end) | ||
102 | { | ||
103 | const char *buf = s->buffer + start; | ||
104 | |||
105 | printk("%.*s", (end - start) + 1, buf); | ||
106 | } | ||
107 | |||
108 | /* | ||
109 | * Flush data from the associated per_CPU buffer. The function | ||
110 | * can be called either via IRQ work or independently. | ||
111 | */ | ||
112 | static void __printk_nmi_flush(struct irq_work *work) | ||
113 | { | ||
114 | static raw_spinlock_t read_lock = | ||
115 | __RAW_SPIN_LOCK_INITIALIZER(read_lock); | ||
116 | struct nmi_seq_buf *s = container_of(work, struct nmi_seq_buf, work); | ||
117 | unsigned long flags; | ||
118 | size_t len, size; | ||
119 | int i, last_i; | ||
120 | |||
121 | /* | ||
122 | * The lock has two functions. First, one reader has to flush all | ||
123 | * available message to make the lockless synchronization with | ||
124 | * writers easier. Second, we do not want to mix messages from | ||
125 | * different CPUs. This is especially important when printing | ||
126 | * a backtrace. | ||
127 | */ | ||
128 | raw_spin_lock_irqsave(&read_lock, flags); | ||
129 | |||
130 | i = 0; | ||
131 | more: | ||
132 | len = atomic_read(&s->len); | ||
133 | |||
134 | /* | ||
135 | * This is just a paranoid check that nobody has manipulated | ||
136 | * the buffer an unexpected way. If we printed something then | ||
137 | * @len must only increase. | ||
138 | */ | ||
139 | if (i && i >= len) | ||
140 | pr_err("printk_nmi_flush: internal error: i=%d >= len=%zu\n", | ||
141 | i, len); | ||
142 | |||
143 | if (!len) | ||
144 | goto out; /* Someone else has already flushed the buffer. */ | ||
145 | |||
146 | /* Make sure that data has been written up to the @len */ | ||
147 | smp_rmb(); | ||
148 | |||
149 | size = min(len, sizeof(s->buffer)); | ||
150 | last_i = i; | ||
151 | |||
152 | /* Print line by line. */ | ||
153 | for (; i < size; i++) { | ||
154 | if (s->buffer[i] == '\n') { | ||
155 | print_nmi_seq_line(s, last_i, i); | ||
156 | last_i = i + 1; | ||
157 | } | ||
158 | } | ||
159 | /* Check if there was a partial line. */ | ||
160 | if (last_i < size) { | ||
161 | print_nmi_seq_line(s, last_i, size - 1); | ||
162 | pr_cont("\n"); | ||
163 | } | ||
164 | |||
165 | /* | ||
166 | * Check that nothing has got added in the meantime and truncate | ||
167 | * the buffer. Note that atomic_cmpxchg() is an implicit memory | ||
168 | * barrier that makes sure that the data were copied before | ||
169 | * updating s->len. | ||
170 | */ | ||
171 | if (atomic_cmpxchg(&s->len, len, 0) != len) | ||
172 | goto more; | ||
173 | |||
174 | out: | ||
175 | raw_spin_unlock_irqrestore(&read_lock, flags); | ||
176 | } | ||
177 | |||
178 | /** | ||
179 | * printk_nmi_flush - flush all per-cpu nmi buffers. | ||
180 | * | ||
181 | * The buffers are flushed automatically via IRQ work. This function | ||
182 | * is useful only when someone wants to be sure that all buffers have | ||
183 | * been flushed at some point. | ||
184 | */ | ||
185 | void printk_nmi_flush(void) | ||
186 | { | ||
187 | int cpu; | ||
188 | |||
189 | for_each_possible_cpu(cpu) | ||
190 | __printk_nmi_flush(&per_cpu(nmi_print_seq, cpu).work); | ||
191 | } | ||
192 | |||
193 | void __init printk_nmi_init(void) | ||
194 | { | ||
195 | int cpu; | ||
196 | |||
197 | for_each_possible_cpu(cpu) { | ||
198 | struct nmi_seq_buf *s = &per_cpu(nmi_print_seq, cpu); | ||
199 | |||
200 | init_irq_work(&s->work, __printk_nmi_flush); | ||
201 | } | ||
202 | |||
203 | /* Make sure that IRQ works are initialized before enabling. */ | ||
204 | smp_wmb(); | ||
205 | printk_nmi_irq_ready = 1; | ||
206 | |||
207 | /* Flush pending messages that did not have scheduled IRQ works. */ | ||
208 | printk_nmi_flush(); | ||
209 | } | ||
210 | |||
211 | void printk_nmi_enter(void) | ||
212 | { | ||
213 | this_cpu_write(printk_func, vprintk_nmi); | ||
214 | } | ||
215 | |||
216 | void printk_nmi_exit(void) | ||
217 | { | ||
218 | this_cpu_write(printk_func, vprintk_default); | ||
219 | } | ||
diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c index bfbf284e4218..71eba0607034 100644 --- a/kernel/printk/printk.c +++ b/kernel/printk/printk.c | |||
@@ -55,6 +55,7 @@ | |||
55 | 55 | ||
56 | #include "console_cmdline.h" | 56 | #include "console_cmdline.h" |
57 | #include "braille.h" | 57 | #include "braille.h" |
58 | #include "internal.h" | ||
58 | 59 | ||
59 | int console_printk[4] = { | 60 | int console_printk[4] = { |
60 | CONSOLE_LOGLEVEL_DEFAULT, /* console_loglevel */ | 61 | CONSOLE_LOGLEVEL_DEFAULT, /* console_loglevel */ |
@@ -1807,14 +1808,6 @@ int vprintk_default(const char *fmt, va_list args) | |||
1807 | } | 1808 | } |
1808 | EXPORT_SYMBOL_GPL(vprintk_default); | 1809 | EXPORT_SYMBOL_GPL(vprintk_default); |
1809 | 1810 | ||
1810 | /* | ||
1811 | * This allows printk to be diverted to another function per cpu. | ||
1812 | * This is useful for calling printk functions from within NMI | ||
1813 | * without worrying about race conditions that can lock up the | ||
1814 | * box. | ||
1815 | */ | ||
1816 | DEFINE_PER_CPU(printk_func_t, printk_func) = vprintk_default; | ||
1817 | |||
1818 | /** | 1811 | /** |
1819 | * printk - print a kernel message | 1812 | * printk - print a kernel message |
1820 | * @fmt: format string | 1813 | * @fmt: format string |
@@ -1838,21 +1831,11 @@ DEFINE_PER_CPU(printk_func_t, printk_func) = vprintk_default; | |||
1838 | */ | 1831 | */ |
1839 | asmlinkage __visible int printk(const char *fmt, ...) | 1832 | asmlinkage __visible int printk(const char *fmt, ...) |
1840 | { | 1833 | { |
1841 | printk_func_t vprintk_func; | ||
1842 | va_list args; | 1834 | va_list args; |
1843 | int r; | 1835 | int r; |
1844 | 1836 | ||
1845 | va_start(args, fmt); | 1837 | va_start(args, fmt); |
1846 | |||
1847 | /* | ||
1848 | * If a caller overrides the per_cpu printk_func, then it needs | ||
1849 | * to disable preemption when calling printk(). Otherwise | ||
1850 | * the printk_func should be set to the default. No need to | ||
1851 | * disable preemption here. | ||
1852 | */ | ||
1853 | vprintk_func = this_cpu_read(printk_func); | ||
1854 | r = vprintk_func(fmt, args); | 1838 | r = vprintk_func(fmt, args); |
1855 | |||
1856 | va_end(args); | 1839 | va_end(args); |
1857 | 1840 | ||
1858 | return r; | 1841 | return r; |
diff --git a/lib/nmi_backtrace.c b/lib/nmi_backtrace.c index 6019c53c669e..26caf51cc238 100644 --- a/lib/nmi_backtrace.c +++ b/lib/nmi_backtrace.c | |||
@@ -16,33 +16,14 @@ | |||
16 | #include <linux/delay.h> | 16 | #include <linux/delay.h> |
17 | #include <linux/kprobes.h> | 17 | #include <linux/kprobes.h> |
18 | #include <linux/nmi.h> | 18 | #include <linux/nmi.h> |
19 | #include <linux/seq_buf.h> | ||
20 | 19 | ||
21 | #ifdef arch_trigger_all_cpu_backtrace | 20 | #ifdef arch_trigger_all_cpu_backtrace |
22 | /* For reliability, we're prepared to waste bits here. */ | 21 | /* For reliability, we're prepared to waste bits here. */ |
23 | static DECLARE_BITMAP(backtrace_mask, NR_CPUS) __read_mostly; | 22 | static DECLARE_BITMAP(backtrace_mask, NR_CPUS) __read_mostly; |
24 | static cpumask_t printtrace_mask; | ||
25 | |||
26 | #define NMI_BUF_SIZE 4096 | ||
27 | |||
28 | struct nmi_seq_buf { | ||
29 | unsigned char buffer[NMI_BUF_SIZE]; | ||
30 | struct seq_buf seq; | ||
31 | }; | ||
32 | |||
33 | /* Safe printing in NMI context */ | ||
34 | static DEFINE_PER_CPU(struct nmi_seq_buf, nmi_print_seq); | ||
35 | 23 | ||
36 | /* "in progress" flag of arch_trigger_all_cpu_backtrace */ | 24 | /* "in progress" flag of arch_trigger_all_cpu_backtrace */ |
37 | static unsigned long backtrace_flag; | 25 | static unsigned long backtrace_flag; |
38 | 26 | ||
39 | static void print_seq_line(struct nmi_seq_buf *s, int start, int end) | ||
40 | { | ||
41 | const char *buf = s->buffer + start; | ||
42 | |||
43 | printk("%.*s", (end - start) + 1, buf); | ||
44 | } | ||
45 | |||
46 | /* | 27 | /* |
47 | * When raise() is called it will be is passed a pointer to the | 28 | * When raise() is called it will be is passed a pointer to the |
48 | * backtrace_mask. Architectures that call nmi_cpu_backtrace() | 29 | * backtrace_mask. Architectures that call nmi_cpu_backtrace() |
@@ -52,8 +33,7 @@ static void print_seq_line(struct nmi_seq_buf *s, int start, int end) | |||
52 | void nmi_trigger_all_cpu_backtrace(bool include_self, | 33 | void nmi_trigger_all_cpu_backtrace(bool include_self, |
53 | void (*raise)(cpumask_t *mask)) | 34 | void (*raise)(cpumask_t *mask)) |
54 | { | 35 | { |
55 | struct nmi_seq_buf *s; | 36 | int i, this_cpu = get_cpu(); |
56 | int i, cpu, this_cpu = get_cpu(); | ||
57 | 37 | ||
58 | if (test_and_set_bit(0, &backtrace_flag)) { | 38 | if (test_and_set_bit(0, &backtrace_flag)) { |
59 | /* | 39 | /* |
@@ -68,17 +48,6 @@ void nmi_trigger_all_cpu_backtrace(bool include_self, | |||
68 | if (!include_self) | 48 | if (!include_self) |
69 | cpumask_clear_cpu(this_cpu, to_cpumask(backtrace_mask)); | 49 | cpumask_clear_cpu(this_cpu, to_cpumask(backtrace_mask)); |
70 | 50 | ||
71 | cpumask_copy(&printtrace_mask, to_cpumask(backtrace_mask)); | ||
72 | |||
73 | /* | ||
74 | * Set up per_cpu seq_buf buffers that the NMIs running on the other | ||
75 | * CPUs will write to. | ||
76 | */ | ||
77 | for_each_cpu(cpu, to_cpumask(backtrace_mask)) { | ||
78 | s = &per_cpu(nmi_print_seq, cpu); | ||
79 | seq_buf_init(&s->seq, s->buffer, NMI_BUF_SIZE); | ||
80 | } | ||
81 | |||
82 | if (!cpumask_empty(to_cpumask(backtrace_mask))) { | 51 | if (!cpumask_empty(to_cpumask(backtrace_mask))) { |
83 | pr_info("Sending NMI to %s CPUs:\n", | 52 | pr_info("Sending NMI to %s CPUs:\n", |
84 | (include_self ? "all" : "other")); | 53 | (include_self ? "all" : "other")); |
@@ -94,73 +63,25 @@ void nmi_trigger_all_cpu_backtrace(bool include_self, | |||
94 | } | 63 | } |
95 | 64 | ||
96 | /* | 65 | /* |
97 | * Now that all the NMIs have triggered, we can dump out their | 66 | * Force flush any remote buffers that might be stuck in IRQ context |
98 | * back traces safely to the console. | 67 | * and therefore could not run their irq_work. |
99 | */ | 68 | */ |
100 | for_each_cpu(cpu, &printtrace_mask) { | 69 | printk_nmi_flush(); |
101 | int len, last_i = 0; | ||
102 | 70 | ||
103 | s = &per_cpu(nmi_print_seq, cpu); | 71 | clear_bit_unlock(0, &backtrace_flag); |
104 | len = seq_buf_used(&s->seq); | ||
105 | if (!len) | ||
106 | continue; | ||
107 | |||
108 | /* Print line by line. */ | ||
109 | for (i = 0; i < len; i++) { | ||
110 | if (s->buffer[i] == '\n') { | ||
111 | print_seq_line(s, last_i, i); | ||
112 | last_i = i + 1; | ||
113 | } | ||
114 | } | ||
115 | /* Check if there was a partial line. */ | ||
116 | if (last_i < len) { | ||
117 | print_seq_line(s, last_i, len - 1); | ||
118 | pr_cont("\n"); | ||
119 | } | ||
120 | } | ||
121 | |||
122 | clear_bit(0, &backtrace_flag); | ||
123 | smp_mb__after_atomic(); | ||
124 | put_cpu(); | 72 | put_cpu(); |
125 | } | 73 | } |
126 | 74 | ||
127 | /* | ||
128 | * It is not safe to call printk() directly from NMI handlers. | ||
129 | * It may be fine if the NMI detected a lock up and we have no choice | ||
130 | * but to do so, but doing a NMI on all other CPUs to get a back trace | ||
131 | * can be done with a sysrq-l. We don't want that to lock up, which | ||
132 | * can happen if the NMI interrupts a printk in progress. | ||
133 | * | ||
134 | * Instead, we redirect the vprintk() to this nmi_vprintk() that writes | ||
135 | * the content into a per cpu seq_buf buffer. Then when the NMIs are | ||
136 | * all done, we can safely dump the contents of the seq_buf to a printk() | ||
137 | * from a non NMI context. | ||
138 | */ | ||
139 | static int nmi_vprintk(const char *fmt, va_list args) | ||
140 | { | ||
141 | struct nmi_seq_buf *s = this_cpu_ptr(&nmi_print_seq); | ||
142 | unsigned int len = seq_buf_used(&s->seq); | ||
143 | |||
144 | seq_buf_vprintf(&s->seq, fmt, args); | ||
145 | return seq_buf_used(&s->seq) - len; | ||
146 | } | ||
147 | |||
148 | bool nmi_cpu_backtrace(struct pt_regs *regs) | 75 | bool nmi_cpu_backtrace(struct pt_regs *regs) |
149 | { | 76 | { |
150 | int cpu = smp_processor_id(); | 77 | int cpu = smp_processor_id(); |
151 | 78 | ||
152 | if (cpumask_test_cpu(cpu, to_cpumask(backtrace_mask))) { | 79 | if (cpumask_test_cpu(cpu, to_cpumask(backtrace_mask))) { |
153 | printk_func_t printk_func_save = this_cpu_read(printk_func); | ||
154 | |||
155 | /* Replace printk to write into the NMI seq */ | ||
156 | this_cpu_write(printk_func, nmi_vprintk); | ||
157 | pr_warn("NMI backtrace for cpu %d\n", cpu); | 80 | pr_warn("NMI backtrace for cpu %d\n", cpu); |
158 | if (regs) | 81 | if (regs) |
159 | show_regs(regs); | 82 | show_regs(regs); |
160 | else | 83 | else |
161 | dump_stack(); | 84 | dump_stack(); |
162 | this_cpu_write(printk_func, printk_func_save); | ||
163 | |||
164 | cpumask_clear_cpu(cpu, to_cpumask(backtrace_mask)); | 85 | cpumask_clear_cpu(cpu, to_cpumask(backtrace_mask)); |
165 | return true; | 86 | return true; |
166 | } | 87 | } |