aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2018-08-15 14:18:53 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2018-08-15 14:18:53 -0400
commitb125d903881901a53117dfe404c789850b4e98ed (patch)
tree95dd0bd0bf93c68c8b0ac354dda6ee2fa382dd4e
parent8c326850304d495deee6ff9a609173a340c5245b (diff)
parent9f68cb579115faa211ae067b4628cf11162783fb (diff)
Merge tag 'printk-for-4.19' of git://git.kernel.org/pub/scm/linux/kernel/git/pmladek/printk
Pull printk updates from Petr Mladek: - Different vendors have a different expectation about a console quietness. Make it configurable to reduce bike-shedding about the upstream default - Decide about the message visibility when the message is stored. It avoids races caused by a delayed console handling - Always store printk() messages into the per-CPU buffers again in NMI. The only exception is when flushing trace log in panic(). There the risk of loosing messages is worth an eventual reordering - Handle invalid %pO printf modifiers correctly - Better handle %p printf modifier tests before crng is initialized - Some clean up * tag 'printk-for-4.19' of git://git.kernel.org/pub/scm/linux/kernel/git/pmladek/printk: lib/vsprintf: Do not handle %pO[^F] as %px printk: Fix warning about unused suppress_message_printing printk/nmi: Prevent deadlock when accessing the main log buffer in NMI printk: Create helper function to queue deferred console handling printk: Split the code for storing a message into the log buffer printk: Clean up syslog_print_all() printk: Remove unnecessary kmalloc() from syslog during clear printk: Make CONSOLE_LOGLEVEL_QUIET configurable printk: make sure to print log on console. lib/test_printf.c: accept "ptrval" as valid result for plain 'p' tests
-rw-r--r--include/linux/printk.h10
-rw-r--r--kernel/printk/internal.h9
-rw-r--r--kernel/printk/printk.c181
-rw-r--r--kernel/printk/printk_safe.c58
-rw-r--r--kernel/trace/trace.c4
-rw-r--r--lib/Kconfig.debug11
-rw-r--r--lib/nmi_backtrace.c3
-rw-r--r--lib/test_printf.c24
-rw-r--r--lib/vsprintf.c1
9 files changed, 189 insertions, 112 deletions
diff --git a/include/linux/printk.h b/include/linux/printk.h
index 6d7e800affd8..cf3eccfe1543 100644
--- a/include/linux/printk.h
+++ b/include/linux/printk.h
@@ -50,15 +50,15 @@ static inline const char *printk_skip_headers(const char *buffer)
50/* We show everything that is MORE important than this.. */ 50/* We show everything that is MORE important than this.. */
51#define CONSOLE_LOGLEVEL_SILENT 0 /* Mum's the word */ 51#define CONSOLE_LOGLEVEL_SILENT 0 /* Mum's the word */
52#define CONSOLE_LOGLEVEL_MIN 1 /* Minimum loglevel we let people use */ 52#define CONSOLE_LOGLEVEL_MIN 1 /* Minimum loglevel we let people use */
53#define CONSOLE_LOGLEVEL_QUIET 4 /* Shhh ..., when booted with "quiet" */
54#define CONSOLE_LOGLEVEL_DEBUG 10 /* issue debug messages */ 53#define CONSOLE_LOGLEVEL_DEBUG 10 /* issue debug messages */
55#define CONSOLE_LOGLEVEL_MOTORMOUTH 15 /* You can't shut this one up */ 54#define CONSOLE_LOGLEVEL_MOTORMOUTH 15 /* You can't shut this one up */
56 55
57/* 56/*
58 * Default used to be hard-coded at 7, we're now allowing it to be set from 57 * Default used to be hard-coded at 7, quiet used to be hardcoded at 4,
59 * kernel config. 58 * we're now allowing both to be set from kernel config.
60 */ 59 */
61#define CONSOLE_LOGLEVEL_DEFAULT CONFIG_CONSOLE_LOGLEVEL_DEFAULT 60#define CONSOLE_LOGLEVEL_DEFAULT CONFIG_CONSOLE_LOGLEVEL_DEFAULT
61#define CONSOLE_LOGLEVEL_QUIET CONFIG_CONSOLE_LOGLEVEL_QUIET
62 62
63extern int console_printk[]; 63extern int console_printk[];
64 64
@@ -148,9 +148,13 @@ void early_printk(const char *s, ...) { }
148#ifdef CONFIG_PRINTK_NMI 148#ifdef CONFIG_PRINTK_NMI
149extern void printk_nmi_enter(void); 149extern void printk_nmi_enter(void);
150extern void printk_nmi_exit(void); 150extern void printk_nmi_exit(void);
151extern void printk_nmi_direct_enter(void);
152extern void printk_nmi_direct_exit(void);
151#else 153#else
152static inline void printk_nmi_enter(void) { } 154static inline void printk_nmi_enter(void) { }
153static inline void printk_nmi_exit(void) { } 155static inline void printk_nmi_exit(void) { }
156static inline void printk_nmi_direct_enter(void) { }
157static inline void printk_nmi_direct_exit(void) { }
154#endif /* PRINTK_NMI */ 158#endif /* PRINTK_NMI */
155 159
156#ifdef CONFIG_PRINTK 160#ifdef CONFIG_PRINTK
diff --git a/kernel/printk/internal.h b/kernel/printk/internal.h
index 2a7d04049af4..0f1898820cba 100644
--- a/kernel/printk/internal.h
+++ b/kernel/printk/internal.h
@@ -19,11 +19,16 @@
19#ifdef CONFIG_PRINTK 19#ifdef CONFIG_PRINTK
20 20
21#define PRINTK_SAFE_CONTEXT_MASK 0x3fffffff 21#define PRINTK_SAFE_CONTEXT_MASK 0x3fffffff
22#define PRINTK_NMI_DEFERRED_CONTEXT_MASK 0x40000000 22#define PRINTK_NMI_DIRECT_CONTEXT_MASK 0x40000000
23#define PRINTK_NMI_CONTEXT_MASK 0x80000000 23#define PRINTK_NMI_CONTEXT_MASK 0x80000000
24 24
25extern raw_spinlock_t logbuf_lock; 25extern raw_spinlock_t logbuf_lock;
26 26
27__printf(5, 0)
28int vprintk_store(int facility, int level,
29 const char *dict, size_t dictlen,
30 const char *fmt, va_list args);
31
27__printf(1, 0) int vprintk_default(const char *fmt, va_list args); 32__printf(1, 0) int vprintk_default(const char *fmt, va_list args);
28__printf(1, 0) int vprintk_deferred(const char *fmt, va_list args); 33__printf(1, 0) int vprintk_deferred(const char *fmt, va_list args);
29__printf(1, 0) int vprintk_func(const char *fmt, va_list args); 34__printf(1, 0) int vprintk_func(const char *fmt, va_list args);
@@ -54,6 +59,8 @@ void __printk_safe_exit(void);
54 local_irq_enable(); \ 59 local_irq_enable(); \
55 } while (0) 60 } while (0)
56 61
62void defer_console_output(void);
63
57#else 64#else
58 65
59__printf(1, 0) int vprintk_func(const char *fmt, va_list args) { return 0; } 66__printf(1, 0) int vprintk_func(const char *fmt, va_list args) { return 0; }
diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c
index 247808333ba4..9a63aeeaaf5d 100644
--- a/kernel/printk/printk.c
+++ b/kernel/printk/printk.c
@@ -349,7 +349,7 @@ static int console_msg_format = MSG_FORMAT_DEFAULT;
349 */ 349 */
350 350
351enum log_flags { 351enum log_flags {
352 LOG_NOCONS = 1, /* already flushed, do not print to console */ 352 LOG_NOCONS = 1, /* suppress print, do not print to console */
353 LOG_NEWLINE = 2, /* text ended with a newline */ 353 LOG_NEWLINE = 2, /* text ended with a newline */
354 LOG_PREFIX = 4, /* text started with a prefix */ 354 LOG_PREFIX = 4, /* text started with a prefix */
355 LOG_CONT = 8, /* text is a fragment of a continuation line */ 355 LOG_CONT = 8, /* text is a fragment of a continuation line */
@@ -1352,71 +1352,68 @@ static int syslog_print_all(char __user *buf, int size, bool clear)
1352{ 1352{
1353 char *text; 1353 char *text;
1354 int len = 0; 1354 int len = 0;
1355 u64 next_seq;
1356 u64 seq;
1357 u32 idx;
1355 1358
1356 text = kmalloc(LOG_LINE_MAX + PREFIX_MAX, GFP_KERNEL); 1359 text = kmalloc(LOG_LINE_MAX + PREFIX_MAX, GFP_KERNEL);
1357 if (!text) 1360 if (!text)
1358 return -ENOMEM; 1361 return -ENOMEM;
1359 1362
1360 logbuf_lock_irq(); 1363 logbuf_lock_irq();
1361 if (buf) { 1364 /*
1362 u64 next_seq; 1365 * Find first record that fits, including all following records,
1363 u64 seq; 1366 * into the user-provided buffer for this dump.
1364 u32 idx; 1367 */
1368 seq = clear_seq;
1369 idx = clear_idx;
1370 while (seq < log_next_seq) {
1371 struct printk_log *msg = log_from_idx(idx);
1365 1372
1366 /* 1373 len += msg_print_text(msg, true, NULL, 0);
1367 * Find first record that fits, including all following records, 1374 idx = log_next(idx);
1368 * into the user-provided buffer for this dump. 1375 seq++;
1369 */ 1376 }
1370 seq = clear_seq;
1371 idx = clear_idx;
1372 while (seq < log_next_seq) {
1373 struct printk_log *msg = log_from_idx(idx);
1374
1375 len += msg_print_text(msg, true, NULL, 0);
1376 idx = log_next(idx);
1377 seq++;
1378 }
1379 1377
1380 /* move first record forward until length fits into the buffer */ 1378 /* move first record forward until length fits into the buffer */
1381 seq = clear_seq; 1379 seq = clear_seq;
1382 idx = clear_idx; 1380 idx = clear_idx;
1383 while (len > size && seq < log_next_seq) { 1381 while (len > size && seq < log_next_seq) {
1384 struct printk_log *msg = log_from_idx(idx); 1382 struct printk_log *msg = log_from_idx(idx);
1385 1383
1386 len -= msg_print_text(msg, true, NULL, 0); 1384 len -= msg_print_text(msg, true, NULL, 0);
1387 idx = log_next(idx); 1385 idx = log_next(idx);
1388 seq++; 1386 seq++;
1389 } 1387 }
1390 1388
1391 /* last message fitting into this dump */ 1389 /* last message fitting into this dump */
1392 next_seq = log_next_seq; 1390 next_seq = log_next_seq;
1393 1391
1394 len = 0; 1392 len = 0;
1395 while (len >= 0 && seq < next_seq) { 1393 while (len >= 0 && seq < next_seq) {
1396 struct printk_log *msg = log_from_idx(idx); 1394 struct printk_log *msg = log_from_idx(idx);
1397 int textlen; 1395 int textlen;
1398 1396
1399 textlen = msg_print_text(msg, true, text, 1397 textlen = msg_print_text(msg, true, text,
1400 LOG_LINE_MAX + PREFIX_MAX); 1398 LOG_LINE_MAX + PREFIX_MAX);
1401 if (textlen < 0) { 1399 if (textlen < 0) {
1402 len = textlen; 1400 len = textlen;
1403 break; 1401 break;
1404 } 1402 }
1405 idx = log_next(idx); 1403 idx = log_next(idx);
1406 seq++; 1404 seq++;
1407 1405
1408 logbuf_unlock_irq(); 1406 logbuf_unlock_irq();
1409 if (copy_to_user(buf + len, text, textlen)) 1407 if (copy_to_user(buf + len, text, textlen))
1410 len = -EFAULT; 1408 len = -EFAULT;
1411 else 1409 else
1412 len += textlen; 1410 len += textlen;
1413 logbuf_lock_irq(); 1411 logbuf_lock_irq();
1414 1412
1415 if (seq < log_first_seq) { 1413 if (seq < log_first_seq) {
1416 /* messages are gone, move to next one */ 1414 /* messages are gone, move to next one */
1417 seq = log_first_seq; 1415 seq = log_first_seq;
1418 idx = log_first_idx; 1416 idx = log_first_idx;
1419 }
1420 } 1417 }
1421 } 1418 }
1422 1419
@@ -1430,6 +1427,14 @@ static int syslog_print_all(char __user *buf, int size, bool clear)
1430 return len; 1427 return len;
1431} 1428}
1432 1429
1430static void syslog_clear(void)
1431{
1432 logbuf_lock_irq();
1433 clear_seq = log_next_seq;
1434 clear_idx = log_next_idx;
1435 logbuf_unlock_irq();
1436}
1437
1433int do_syslog(int type, char __user *buf, int len, int source) 1438int do_syslog(int type, char __user *buf, int len, int source)
1434{ 1439{
1435 bool clear = false; 1440 bool clear = false;
@@ -1474,7 +1479,7 @@ int do_syslog(int type, char __user *buf, int len, int source)
1474 break; 1479 break;
1475 /* Clear ring buffer */ 1480 /* Clear ring buffer */
1476 case SYSLOG_ACTION_CLEAR: 1481 case SYSLOG_ACTION_CLEAR:
1477 syslog_print_all(NULL, 0, true); 1482 syslog_clear();
1478 break; 1483 break;
1479 /* Disable logging to console */ 1484 /* Disable logging to console */
1480 case SYSLOG_ACTION_CONSOLE_OFF: 1485 case SYSLOG_ACTION_CONSOLE_OFF:
@@ -1824,28 +1829,16 @@ static size_t log_output(int facility, int level, enum log_flags lflags, const c
1824 return log_store(facility, level, lflags, 0, dict, dictlen, text, text_len); 1829 return log_store(facility, level, lflags, 0, dict, dictlen, text, text_len);
1825} 1830}
1826 1831
1827asmlinkage int vprintk_emit(int facility, int level, 1832/* Must be called under logbuf_lock. */
1828 const char *dict, size_t dictlen, 1833int vprintk_store(int facility, int level,
1829 const char *fmt, va_list args) 1834 const char *dict, size_t dictlen,
1835 const char *fmt, va_list args)
1830{ 1836{
1831 static char textbuf[LOG_LINE_MAX]; 1837 static char textbuf[LOG_LINE_MAX];
1832 char *text = textbuf; 1838 char *text = textbuf;
1833 size_t text_len; 1839 size_t text_len;
1834 enum log_flags lflags = 0; 1840 enum log_flags lflags = 0;
1835 unsigned long flags;
1836 int printed_len;
1837 bool in_sched = false;
1838 1841
1839 if (level == LOGLEVEL_SCHED) {
1840 level = LOGLEVEL_DEFAULT;
1841 in_sched = true;
1842 }
1843
1844 boot_delay_msec(level);
1845 printk_delay();
1846
1847 /* This stops the holder of console_sem just where we want him */
1848 logbuf_lock_irqsave(flags);
1849 /* 1842 /*
1850 * The printf needs to come first; we need the syslog 1843 * The printf needs to come first; we need the syslog
1851 * prefix which might be passed-in as a parameter. 1844 * prefix which might be passed-in as a parameter.
@@ -1886,8 +1879,32 @@ asmlinkage int vprintk_emit(int facility, int level,
1886 if (dict) 1879 if (dict)
1887 lflags |= LOG_PREFIX|LOG_NEWLINE; 1880 lflags |= LOG_PREFIX|LOG_NEWLINE;
1888 1881
1889 printed_len = log_output(facility, level, lflags, dict, dictlen, text, text_len); 1882 if (suppress_message_printing(level))
1883 lflags |= LOG_NOCONS;
1884
1885 return log_output(facility, level, lflags,
1886 dict, dictlen, text, text_len);
1887}
1888
1889asmlinkage int vprintk_emit(int facility, int level,
1890 const char *dict, size_t dictlen,
1891 const char *fmt, va_list args)
1892{
1893 int printed_len;
1894 bool in_sched = false;
1895 unsigned long flags;
1896
1897 if (level == LOGLEVEL_SCHED) {
1898 level = LOGLEVEL_DEFAULT;
1899 in_sched = true;
1900 }
1890 1901
1902 boot_delay_msec(level);
1903 printk_delay();
1904
1905 /* This stops the holder of console_sem just where we want him */
1906 logbuf_lock_irqsave(flags);
1907 printed_len = vprintk_store(facility, level, dict, dictlen, fmt, args);
1891 logbuf_unlock_irqrestore(flags); 1908 logbuf_unlock_irqrestore(flags);
1892 1909
1893 /* If called from the scheduler, we can not call up(). */ 1910 /* If called from the scheduler, we can not call up(). */
@@ -2013,7 +2030,6 @@ static void call_console_drivers(const char *ext_text, size_t ext_len,
2013 const char *text, size_t len) {} 2030 const char *text, size_t len) {}
2014static size_t msg_print_text(const struct printk_log *msg, 2031static size_t msg_print_text(const struct printk_log *msg,
2015 bool syslog, char *buf, size_t size) { return 0; } 2032 bool syslog, char *buf, size_t size) { return 0; }
2016static bool suppress_message_printing(int level) { return false; }
2017 2033
2018#endif /* CONFIG_PRINTK */ 2034#endif /* CONFIG_PRINTK */
2019 2035
@@ -2349,11 +2365,10 @@ skip:
2349 break; 2365 break;
2350 2366
2351 msg = log_from_idx(console_idx); 2367 msg = log_from_idx(console_idx);
2352 if (suppress_message_printing(msg->level)) { 2368 if (msg->flags & LOG_NOCONS) {
2353 /* 2369 /*
2354 * Skip record we have buffered and already printed 2370 * Skip record if !ignore_loglevel, and
2355 * directly to the console when we received it, and 2371 * record has level above the console loglevel.
2356 * record that has level above the console loglevel.
2357 */ 2372 */
2358 console_idx = log_next(console_idx); 2373 console_idx = log_next(console_idx);
2359 console_seq++; 2374 console_seq++;
@@ -2878,16 +2893,20 @@ void wake_up_klogd(void)
2878 preempt_enable(); 2893 preempt_enable();
2879} 2894}
2880 2895
2881int vprintk_deferred(const char *fmt, va_list args) 2896void defer_console_output(void)
2882{ 2897{
2883 int r;
2884
2885 r = vprintk_emit(0, LOGLEVEL_SCHED, NULL, 0, fmt, args);
2886
2887 preempt_disable(); 2898 preempt_disable();
2888 __this_cpu_or(printk_pending, PRINTK_PENDING_OUTPUT); 2899 __this_cpu_or(printk_pending, PRINTK_PENDING_OUTPUT);
2889 irq_work_queue(this_cpu_ptr(&wake_up_klogd_work)); 2900 irq_work_queue(this_cpu_ptr(&wake_up_klogd_work));
2890 preempt_enable(); 2901 preempt_enable();
2902}
2903
2904int vprintk_deferred(const char *fmt, va_list args)
2905{
2906 int r;
2907
2908 r = vprintk_emit(0, LOGLEVEL_SCHED, NULL, 0, fmt, args);
2909 defer_console_output();
2891 2910
2892 return r; 2911 return r;
2893} 2912}
diff --git a/kernel/printk/printk_safe.c b/kernel/printk/printk_safe.c
index d7d091309054..a0a74c533e4b 100644
--- a/kernel/printk/printk_safe.c
+++ b/kernel/printk/printk_safe.c
@@ -308,24 +308,33 @@ static __printf(1, 0) int vprintk_nmi(const char *fmt, va_list args)
308 308
309void printk_nmi_enter(void) 309void printk_nmi_enter(void)
310{ 310{
311 /* 311 this_cpu_or(printk_context, PRINTK_NMI_CONTEXT_MASK);
312 * The size of the extra per-CPU buffer is limited. Use it only when
313 * the main one is locked. If this CPU is not in the safe context,
314 * the lock must be taken on another CPU and we could wait for it.
315 */
316 if ((this_cpu_read(printk_context) & PRINTK_SAFE_CONTEXT_MASK) &&
317 raw_spin_is_locked(&logbuf_lock)) {
318 this_cpu_or(printk_context, PRINTK_NMI_CONTEXT_MASK);
319 } else {
320 this_cpu_or(printk_context, PRINTK_NMI_DEFERRED_CONTEXT_MASK);
321 }
322} 312}
323 313
324void printk_nmi_exit(void) 314void printk_nmi_exit(void)
325{ 315{
326 this_cpu_and(printk_context, 316 this_cpu_and(printk_context, ~PRINTK_NMI_CONTEXT_MASK);
327 ~(PRINTK_NMI_CONTEXT_MASK | 317}
328 PRINTK_NMI_DEFERRED_CONTEXT_MASK)); 318
319/*
320 * Marks a code that might produce many messages in NMI context
321 * and the risk of losing them is more critical than eventual
322 * reordering.
323 *
324 * It has effect only when called in NMI context. Then printk()
325 * will try to store the messages into the main logbuf directly
326 * and use the per-CPU buffers only as a fallback when the lock
327 * is not available.
328 */
329void printk_nmi_direct_enter(void)
330{
331 if (this_cpu_read(printk_context) & PRINTK_NMI_CONTEXT_MASK)
332 this_cpu_or(printk_context, PRINTK_NMI_DIRECT_CONTEXT_MASK);
333}
334
335void printk_nmi_direct_exit(void)
336{
337 this_cpu_and(printk_context, ~PRINTK_NMI_DIRECT_CONTEXT_MASK);
329} 338}
330 339
331#else 340#else
@@ -363,6 +372,20 @@ void __printk_safe_exit(void)
363 372
364__printf(1, 0) int vprintk_func(const char *fmt, va_list args) 373__printf(1, 0) int vprintk_func(const char *fmt, va_list args)
365{ 374{
375 /*
376 * Try to use the main logbuf even in NMI. But avoid calling console
377 * drivers that might have their own locks.
378 */
379 if ((this_cpu_read(printk_context) & PRINTK_NMI_DIRECT_CONTEXT_MASK) &&
380 raw_spin_trylock(&logbuf_lock)) {
381 int len;
382
383 len = vprintk_store(0, LOGLEVEL_DEFAULT, NULL, 0, fmt, args);
384 raw_spin_unlock(&logbuf_lock);
385 defer_console_output();
386 return len;
387 }
388
366 /* Use extra buffer in NMI when logbuf_lock is taken or in safe mode. */ 389 /* Use extra buffer in NMI when logbuf_lock is taken or in safe mode. */
367 if (this_cpu_read(printk_context) & PRINTK_NMI_CONTEXT_MASK) 390 if (this_cpu_read(printk_context) & PRINTK_NMI_CONTEXT_MASK)
368 return vprintk_nmi(fmt, args); 391 return vprintk_nmi(fmt, args);
@@ -371,13 +394,6 @@ __printf(1, 0) int vprintk_func(const char *fmt, va_list args)
371 if (this_cpu_read(printk_context) & PRINTK_SAFE_CONTEXT_MASK) 394 if (this_cpu_read(printk_context) & PRINTK_SAFE_CONTEXT_MASK)
372 return vprintk_safe(fmt, args); 395 return vprintk_safe(fmt, args);
373 396
374 /*
375 * Use the main logbuf when logbuf_lock is available in NMI.
376 * But avoid calling console drivers that might have their own locks.
377 */
378 if (this_cpu_read(printk_context) & PRINTK_NMI_DEFERRED_CONTEXT_MASK)
379 return vprintk_deferred(fmt, args);
380
381 /* No obstacles. */ 397 /* No obstacles. */
382 return vprintk_default(fmt, args); 398 return vprintk_default(fmt, args);
383} 399}
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
index 823687997b01..176debd3481b 100644
--- a/kernel/trace/trace.c
+++ b/kernel/trace/trace.c
@@ -8288,6 +8288,7 @@ void ftrace_dump(enum ftrace_dump_mode oops_dump_mode)
8288 tracing_off(); 8288 tracing_off();
8289 8289
8290 local_irq_save(flags); 8290 local_irq_save(flags);
8291 printk_nmi_direct_enter();
8291 8292
8292 /* Simulate the iterator */ 8293 /* Simulate the iterator */
8293 trace_init_global_iter(&iter); 8294 trace_init_global_iter(&iter);
@@ -8367,7 +8368,8 @@ void ftrace_dump(enum ftrace_dump_mode oops_dump_mode)
8367 for_each_tracing_cpu(cpu) { 8368 for_each_tracing_cpu(cpu) {
8368 atomic_dec(&per_cpu_ptr(iter.trace_buffer->data, cpu)->disabled); 8369 atomic_dec(&per_cpu_ptr(iter.trace_buffer->data, cpu)->disabled);
8369 } 8370 }
8370 atomic_dec(&dump_running); 8371 atomic_dec(&dump_running);
8372 printk_nmi_direct_exit();
8371 local_irq_restore(flags); 8373 local_irq_restore(flags);
8372} 8374}
8373EXPORT_SYMBOL_GPL(ftrace_dump); 8375EXPORT_SYMBOL_GPL(ftrace_dump);
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
index 0b066b3c9284..ce5a45e46885 100644
--- a/lib/Kconfig.debug
+++ b/lib/Kconfig.debug
@@ -30,6 +30,17 @@ config CONSOLE_LOGLEVEL_DEFAULT
30 usage in the kernel. That is controlled by the MESSAGE_LOGLEVEL_DEFAULT 30 usage in the kernel. That is controlled by the MESSAGE_LOGLEVEL_DEFAULT
31 option. 31 option.
32 32
33config CONSOLE_LOGLEVEL_QUIET
34 int "quiet console loglevel (1-15)"
35 range 1 15
36 default "4"
37 help
38 loglevel to use when "quiet" is passed on the kernel commandline.
39
40 When "quiet" is passed on the kernel commandline this loglevel
41 will be used as the loglevel. IOW passing "quiet" will be the
42 equivalent of passing "loglevel=<CONSOLE_LOGLEVEL_QUIET>"
43
33config MESSAGE_LOGLEVEL_DEFAULT 44config MESSAGE_LOGLEVEL_DEFAULT
34 int "Default message log level (1-7)" 45 int "Default message log level (1-7)"
35 range 1 7 46 range 1 7
diff --git a/lib/nmi_backtrace.c b/lib/nmi_backtrace.c
index 61a6b5aab07e..15ca78e1c7d4 100644
--- a/lib/nmi_backtrace.c
+++ b/lib/nmi_backtrace.c
@@ -87,11 +87,9 @@ void nmi_trigger_cpumask_backtrace(const cpumask_t *mask,
87 87
88bool nmi_cpu_backtrace(struct pt_regs *regs) 88bool nmi_cpu_backtrace(struct pt_regs *regs)
89{ 89{
90 static arch_spinlock_t lock = __ARCH_SPIN_LOCK_UNLOCKED;
91 int cpu = smp_processor_id(); 90 int cpu = smp_processor_id();
92 91
93 if (cpumask_test_cpu(cpu, to_cpumask(backtrace_mask))) { 92 if (cpumask_test_cpu(cpu, to_cpumask(backtrace_mask))) {
94 arch_spin_lock(&lock);
95 if (regs && cpu_in_idle(instruction_pointer(regs))) { 93 if (regs && cpu_in_idle(instruction_pointer(regs))) {
96 pr_warn("NMI backtrace for cpu %d skipped: idling at %pS\n", 94 pr_warn("NMI backtrace for cpu %d skipped: idling at %pS\n",
97 cpu, (void *)instruction_pointer(regs)); 95 cpu, (void *)instruction_pointer(regs));
@@ -102,7 +100,6 @@ bool nmi_cpu_backtrace(struct pt_regs *regs)
102 else 100 else
103 dump_stack(); 101 dump_stack();
104 } 102 }
105 arch_spin_unlock(&lock);
106 cpumask_clear_cpu(cpu, to_cpumask(backtrace_mask)); 103 cpumask_clear_cpu(cpu, to_cpumask(backtrace_mask));
107 return true; 104 return true;
108 } 105 }
diff --git a/lib/test_printf.c b/lib/test_printf.c
index cea592f402ed..53527ea822b5 100644
--- a/lib/test_printf.c
+++ b/lib/test_printf.c
@@ -206,6 +206,7 @@ test_string(void)
206#define PTR_WIDTH 16 206#define PTR_WIDTH 16
207#define PTR ((void *)0xffff0123456789abUL) 207#define PTR ((void *)0xffff0123456789abUL)
208#define PTR_STR "ffff0123456789ab" 208#define PTR_STR "ffff0123456789ab"
209#define PTR_VAL_NO_CRNG "(____ptrval____)"
209#define ZEROS "00000000" /* hex 32 zero bits */ 210#define ZEROS "00000000" /* hex 32 zero bits */
210 211
211static int __init 212static int __init
@@ -216,7 +217,16 @@ plain_format(void)
216 217
217 nchars = snprintf(buf, PLAIN_BUF_SIZE, "%p", PTR); 218 nchars = snprintf(buf, PLAIN_BUF_SIZE, "%p", PTR);
218 219
219 if (nchars != PTR_WIDTH || strncmp(buf, ZEROS, strlen(ZEROS)) != 0) 220 if (nchars != PTR_WIDTH)
221 return -1;
222
223 if (strncmp(buf, PTR_VAL_NO_CRNG, PTR_WIDTH) == 0) {
224 pr_warn("crng possibly not yet initialized. plain 'p' buffer contains \"%s\"",
225 PTR_VAL_NO_CRNG);
226 return 0;
227 }
228
229 if (strncmp(buf, ZEROS, strlen(ZEROS)) != 0)
220 return -1; 230 return -1;
221 231
222 return 0; 232 return 0;
@@ -227,6 +237,7 @@ plain_format(void)
227#define PTR_WIDTH 8 237#define PTR_WIDTH 8
228#define PTR ((void *)0x456789ab) 238#define PTR ((void *)0x456789ab)
229#define PTR_STR "456789ab" 239#define PTR_STR "456789ab"
240#define PTR_VAL_NO_CRNG "(ptrval)"
230 241
231static int __init 242static int __init
232plain_format(void) 243plain_format(void)
@@ -245,7 +256,16 @@ plain_hash(void)
245 256
246 nchars = snprintf(buf, PLAIN_BUF_SIZE, "%p", PTR); 257 nchars = snprintf(buf, PLAIN_BUF_SIZE, "%p", PTR);
247 258
248 if (nchars != PTR_WIDTH || strncmp(buf, PTR_STR, PTR_WIDTH) == 0) 259 if (nchars != PTR_WIDTH)
260 return -1;
261
262 if (strncmp(buf, PTR_VAL_NO_CRNG, PTR_WIDTH) == 0) {
263 pr_warn("crng possibly not yet initialized. plain 'p' buffer contains \"%s\"",
264 PTR_VAL_NO_CRNG);
265 return 0;
266 }
267
268 if (strncmp(buf, PTR_STR, PTR_WIDTH) == 0)
249 return -1; 269 return -1;
250 270
251 return 0; 271 return 0;
diff --git a/lib/vsprintf.c b/lib/vsprintf.c
index a48aaa79d352..cda186230287 100644
--- a/lib/vsprintf.c
+++ b/lib/vsprintf.c
@@ -1942,6 +1942,7 @@ char *pointer(const char *fmt, char *buf, char *end, void *ptr,
1942 case 'F': 1942 case 'F':
1943 return device_node_string(buf, end, ptr, spec, fmt + 1); 1943 return device_node_string(buf, end, ptr, spec, fmt + 1);
1944 } 1944 }
1945 break;
1945 case 'x': 1946 case 'x':
1946 return pointer_string(buf, end, ptr, spec); 1947 return pointer_string(buf, end, ptr, spec);
1947 } 1948 }