aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/printk
diff options
context:
space:
mode:
authorPetr Mladek <pmladek@suse.com>2016-05-20 20:00:33 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2016-05-20 20:58:30 -0400
commit42a0bb3f71383b457a7db362f1c69e7afb96732b (patch)
treec63f12bed74fee20662fbcc8cc985d53a0d20def /kernel/printk
parent2eeed7e98d6a1341b1574893a95ce5b8379140f2 (diff)
printk/nmi: generic solution for safe printk in NMI
printk() takes some locks and could not be used a safe way in NMI context. The chance of a deadlock is real especially when printing stacks from all CPUs. This particular problem has been addressed on x86 by the commit a9edc8809328 ("x86/nmi: Perform a safe NMI stack trace on all CPUs"). The patchset brings two big advantages. First, it makes the NMI backtraces safe on all architectures for free. Second, it makes all NMI messages almost safe on all architectures (the temporary buffer is limited. We still should keep the number of messages in NMI context at minimum). Note that there already are several messages printed in NMI context: WARN_ON(in_nmi()), BUG_ON(in_nmi()), anything being printed out from MCE handlers. These are not easy to avoid. This patch reuses most of the code and makes it generic. It is useful for all messages and architectures that support NMI. The alternative printk_func is set when entering and is reseted when leaving NMI context. It queues IRQ work to copy the messages into the main ring buffer in a safe context. __printk_nmi_flush() copies all available messages and reset the buffer. Then we could use a simple cmpxchg operations to get synchronized with writers. There is also used a spinlock to get synchronized with other flushers. We do not longer use seq_buf because it depends on external lock. It would be hard to make all supported operations safe for a lockless use. It would be confusing and error prone to make only some operations safe. The code is put into separate printk/nmi.c as suggested by Steven Rostedt. It needs a per-CPU buffer and is compiled only on architectures that call nmi_enter(). This is achieved by the new HAVE_NMI Kconfig flag. The are MN10300 and Xtensa architectures. We need to clean up NMI handling there first. Let's do it separately. The patch is heavily based on the draft from Peter Zijlstra, see https://lkml.org/lkml/2015/6/10/327 [arnd@arndb.de: printk-nmi: use %zu format string for size_t] [akpm@linux-foundation.org: min_t->min - all types are size_t here] Signed-off-by: Petr Mladek <pmladek@suse.com> Suggested-by: Peter Zijlstra <peterz@infradead.org> Suggested-by: Steven Rostedt <rostedt@goodmis.org> Cc: Jan Kara <jack@suse.cz> Acked-by: Russell King <rmk+kernel@arm.linux.org.uk> [arm part] Cc: Daniel Thompson <daniel.thompson@linaro.org> Cc: Jiri Kosina <jkosina@suse.com> Cc: Ingo Molnar <mingo@redhat.com> Cc: Thomas Gleixner <tglx@linutronix.de> Cc: Ralf Baechle <ralf@linux-mips.org> Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org> Cc: Martin Schwidefsky <schwidefsky@de.ibm.com> Cc: David Miller <davem@davemloft.net> Cc: Daniel Thompson <daniel.thompson@linaro.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'kernel/printk')
-rw-r--r--kernel/printk/Makefile1
-rw-r--r--kernel/printk/internal.h44
-rw-r--r--kernel/printk/nmi.c219
-rw-r--r--kernel/printk/printk.c19
4 files changed, 265 insertions, 18 deletions
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 @@
1obj-y = printk.o 1obj-y = printk.o
2obj-$(CONFIG_PRINTK_NMI) += nmi.o
2obj-$(CONFIG_A11Y_BRAILLE_CONSOLE) += braille.o 3obj-$(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
19typedef __printf(1, 0) int (*printk_func_t)(const char *fmt, va_list args);
20
21int __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 */
31DECLARE_PER_CPU(printk_func_t, printk_func);
32static 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
39static 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 */
40DEFINE_PER_CPU(printk_func_t, printk_func) = vprintk_default;
41static int printk_nmi_irq_ready;
42
43#define NMI_LOG_BUF_LEN (4096 - sizeof(atomic_t) - sizeof(struct irq_work))
44
45struct 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};
50static 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 */
58static 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
64again:
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 */
101static 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 */
112static 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;
131more:
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
174out:
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 */
185void 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
193void __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
211void printk_nmi_enter(void)
212{
213 this_cpu_write(printk_func, vprintk_nmi);
214}
215
216void 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
59int console_printk[4] = { 60int 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}
1808EXPORT_SYMBOL_GPL(vprintk_default); 1809EXPORT_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 */
1816DEFINE_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 */
1839asmlinkage __visible int printk(const char *fmt, ...) 1832asmlinkage __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;