Skip to content

Commit 7d91de7

Browse files
committed
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/pmladek/printk
Pull printk updates from Petr Mladek: - Add Petr Mladek, Sergey Senozhatsky as printk maintainers, and Steven Rostedt as the printk reviewer. This idea came up after the discussion about printk issues at Kernel Summit. It was formulated and discussed at lkml[1]. - Extend a lock-less NMI per-cpu buffers idea to handle recursive printk() calls by Sergey Senozhatsky[2]. It is the first step in sanitizing printk as discussed at Kernel Summit. The change allows to see messages that would normally get ignored or would cause a deadlock. Also it allows to enable lockdep in printk(). This already paid off. The testing in linux-next helped to discover two old problems that were hidden before[3][4]. - Remove unused parameter by Sergey Senozhatsky. Clean up after a past change. [1] http://lkml.kernel.org/r/1481798878-31898-1-git-send-email-pmladek@suse.com [2] http://lkml.kernel.org/r/20161227141611.940-1-sergey.senozhatsky@gmail.com [3] http://lkml.kernel.org/r/20170215044332.30449-1-sergey.senozhatsky@gmail.com [4] http://lkml.kernel.org/r/20170217015932.11898-1-sergey.senozhatsky@gmail.com * 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/pmladek/printk: printk: drop call_console_drivers() unused param printk: convert the rest to printk-safe printk: remove zap_locks() function printk: use printk_safe buffers in printk printk: report lost messages in printk safe/nmi contexts printk: always use deferred printk when flush printk_safe lines printk: introduce per-cpu safe_print seq buffer printk: rename nmi.c and exported api printk: use vprintk_func in vprintk() MAINTAINERS: Add printk maintainers
2 parents 6ef192f + d9c2352 commit 7d91de7

File tree

11 files changed

+347
-255
lines changed

11 files changed

+347
-255
lines changed

MAINTAINERS

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9997,6 +9997,14 @@ S: Supported
99979997
F: Documentation/preempt-locking.txt
99989998
F: include/linux/preempt.h
99999999

10000+
PRINTK
10001+
M: Petr Mladek <pmladek@suse.com>
10002+
M: Sergey Senozhatsky <sergey.senozhatsky@gmail.com>
10003+
R: Steven Rostedt <rostedt@goodmis.org>
10004+
S: Maintained
10005+
F: kernel/printk/
10006+
F: include/linux/printk.h
10007+
1000010008
PRISM54 WIRELESS DRIVER
1000110009
M: "Luis R. Rodriguez" <mcgrof@gmail.com>
1000210010
L: linux-wireless@vger.kernel.org

include/linux/printk.h

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -147,17 +147,11 @@ void early_printk(const char *s, ...) { }
147147
#endif
148148

149149
#ifdef CONFIG_PRINTK_NMI
150-
extern void printk_nmi_init(void);
151150
extern void printk_nmi_enter(void);
152151
extern void printk_nmi_exit(void);
153-
extern void printk_nmi_flush(void);
154-
extern void printk_nmi_flush_on_panic(void);
155152
#else
156-
static inline void printk_nmi_init(void) { }
157153
static inline void printk_nmi_enter(void) { }
158154
static inline void printk_nmi_exit(void) { }
159-
static inline void printk_nmi_flush(void) { }
160-
static inline void printk_nmi_flush_on_panic(void) { }
161155
#endif /* PRINTK_NMI */
162156

163157
#ifdef CONFIG_PRINTK
@@ -209,6 +203,9 @@ void __init setup_log_buf(int early);
209203
__printf(1, 2) void dump_stack_set_arch_desc(const char *fmt, ...);
210204
void dump_stack_print_info(const char *log_lvl);
211205
void show_regs_print_info(const char *log_lvl);
206+
extern void printk_safe_init(void);
207+
extern void printk_safe_flush(void);
208+
extern void printk_safe_flush_on_panic(void);
212209
#else
213210
static inline __printf(1, 0)
214211
int vprintk(const char *s, va_list args)
@@ -268,6 +265,18 @@ static inline void dump_stack_print_info(const char *log_lvl)
268265
static inline void show_regs_print_info(const char *log_lvl)
269266
{
270267
}
268+
269+
static inline void printk_safe_init(void)
270+
{
271+
}
272+
273+
static inline void printk_safe_flush(void)
274+
{
275+
}
276+
277+
static inline void printk_safe_flush_on_panic(void)
278+
{
279+
}
271280
#endif
272281

273282
extern asmlinkage void dump_stack(void) __cold;

init/Kconfig

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -861,17 +861,19 @@ config LOG_CPU_MAX_BUF_SHIFT
861861
13 => 8 KB for each CPU
862862
12 => 4 KB for each CPU
863863

864-
config NMI_LOG_BUF_SHIFT
865-
int "Temporary per-CPU NMI log buffer size (12 => 4KB, 13 => 8KB)"
864+
config PRINTK_SAFE_LOG_BUF_SHIFT
865+
int "Temporary per-CPU printk log buffer size (12 => 4KB, 13 => 8KB)"
866866
range 10 21
867867
default 13
868-
depends on PRINTK_NMI
868+
depends on PRINTK
869869
help
870-
Select the size of a per-CPU buffer where NMI messages are temporary
871-
stored. They are copied to the main log buffer in a safe context
872-
to avoid a deadlock. The value defines the size as a power of 2.
870+
Select the size of an alternate printk per-CPU buffer where messages
871+
printed from usafe contexts are temporary stored. One example would
872+
be NMI messages, another one - printk recursion. The messages are
873+
copied to the main log buffer in a safe context to avoid a deadlock.
874+
The value defines the size as a power of 2.
873875

874-
NMI messages are rare and limited. The largest one is when
876+
Those messages are rare and limited. The largest one is when
875877
a backtrace is printed. It usually fits into 4KB. Select
876878
8KB if you want to be on the safe side.
877879

init/main.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -581,7 +581,7 @@ asmlinkage __visible void __init start_kernel(void)
581581
timekeeping_init();
582582
time_init();
583583
sched_clock_postinit();
584-
printk_nmi_init();
584+
printk_safe_init();
585585
perf_event_init();
586586
profile_init();
587587
call_function_init();

kernel/kexec_core.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -916,7 +916,7 @@ void crash_kexec(struct pt_regs *regs)
916916
old_cpu = atomic_cmpxchg(&panic_cpu, PANIC_CPU_INVALID, this_cpu);
917917
if (old_cpu == PANIC_CPU_INVALID) {
918918
/* This is the 1st CPU which comes here, so go ahead. */
919-
printk_nmi_flush_on_panic();
919+
printk_safe_flush_on_panic();
920920
__crash_kexec(regs);
921921

922922
/*

kernel/panic.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -188,7 +188,7 @@ void panic(const char *fmt, ...)
188188
* Bypass the panic_cpu check and call __crash_kexec directly.
189189
*/
190190
if (!_crash_kexec_post_notifiers) {
191-
printk_nmi_flush_on_panic();
191+
printk_safe_flush_on_panic();
192192
__crash_kexec(NULL);
193193

194194
/*
@@ -213,7 +213,7 @@ void panic(const char *fmt, ...)
213213
atomic_notifier_call_chain(&panic_notifier_list, 0, buf);
214214

215215
/* Call flush even twice. It tries harder with a single online CPU */
216-
printk_nmi_flush_on_panic();
216+
printk_safe_flush_on_panic();
217217
kmsg_dump(KMSG_DUMP_PANIC);
218218

219219
/*

kernel/printk/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
obj-y = printk.o
2-
obj-$(CONFIG_PRINTK_NMI) += nmi.o
2+
obj-$(CONFIG_PRINTK) += printk_safe.o
33
obj-$(CONFIG_A11Y_BRAILLE_CONSOLE) += braille.o

kernel/printk/internal.h

Lines changed: 46 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -16,42 +16,55 @@
1616
*/
1717
#include <linux/percpu.h>
1818

19-
typedef __printf(1, 0) int (*printk_func_t)(const char *fmt, va_list args);
19+
#ifdef CONFIG_PRINTK
2020

21-
int __printf(1, 0) vprintk_default(const char *fmt, va_list args);
22-
23-
#ifdef CONFIG_PRINTK_NMI
21+
#define PRINTK_SAFE_CONTEXT_MASK 0x7fffffff
22+
#define PRINTK_NMI_CONTEXT_MASK 0x80000000
2423

2524
extern raw_spinlock_t logbuf_lock;
2625

26+
__printf(1, 0) int vprintk_default(const char *fmt, va_list args);
27+
__printf(1, 0) int vprintk_func(const char *fmt, va_list args);
28+
void __printk_safe_enter(void);
29+
void __printk_safe_exit(void);
30+
31+
#define printk_safe_enter_irqsave(flags) \
32+
do { \
33+
local_irq_save(flags); \
34+
__printk_safe_enter(); \
35+
} while (0)
36+
37+
#define printk_safe_exit_irqrestore(flags) \
38+
do { \
39+
__printk_safe_exit(); \
40+
local_irq_restore(flags); \
41+
} while (0)
42+
43+
#define printk_safe_enter_irq() \
44+
do { \
45+
local_irq_disable(); \
46+
__printk_safe_enter(); \
47+
} while (0)
48+
49+
#define printk_safe_exit_irq() \
50+
do { \
51+
__printk_safe_exit(); \
52+
local_irq_enable(); \
53+
} while (0)
54+
55+
#else
56+
57+
__printf(1, 0) int vprintk_func(const char *fmt, va_list args) { return 0; }
58+
2759
/*
28-
* printk() could not take logbuf_lock in NMI context. Instead,
29-
* it temporary stores the strings into a per-CPU buffer.
30-
* The alternative implementation is chosen transparently
31-
* via per-CPU variable.
60+
* In !PRINTK builds we still export logbuf_lock spin_lock, console_sem
61+
* semaphore and some of console functions (console_unlock()/etc.), so
62+
* printk-safe must preserve the existing local IRQ guarantees.
3263
*/
33-
DECLARE_PER_CPU(printk_func_t, printk_func);
34-
static inline __printf(1, 0) int vprintk_func(const char *fmt, va_list args)
35-
{
36-
return this_cpu_read(printk_func)(fmt, args);
37-
}
38-
39-
extern atomic_t nmi_message_lost;
40-
static inline int get_nmi_message_lost(void)
41-
{
42-
return atomic_xchg(&nmi_message_lost, 0);
43-
}
44-
45-
#else /* CONFIG_PRINTK_NMI */
46-
47-
static inline __printf(1, 0) int vprintk_func(const char *fmt, va_list args)
48-
{
49-
return vprintk_default(fmt, args);
50-
}
51-
52-
static inline int get_nmi_message_lost(void)
53-
{
54-
return 0;
55-
}
56-
57-
#endif /* CONFIG_PRINTK_NMI */
64+
#define printk_safe_enter_irqsave(flags) local_irq_save(flags)
65+
#define printk_safe_exit_irqrestore(flags) local_irq_restore(flags)
66+
67+
#define printk_safe_enter_irq() local_irq_disable()
68+
#define printk_safe_exit_irq() local_irq_enable()
69+
70+
#endif /* CONFIG_PRINTK */

0 commit comments

Comments
 (0)