1 | // SPDX-License-Identifier: GPL-2.0 |
2 | #include <linux/kmsg_dump.h> |
3 | #include <linux/spinlock.h> |
4 | #include <linux/console.h> |
5 | #include <linux/string.h> |
6 | #include <shared/init.h> |
7 | #include <shared/kern.h> |
8 | #include <os.h> |
9 | |
10 | static void kmsg_dumper_stdout(struct kmsg_dumper *dumper, |
11 | enum kmsg_dump_reason reason) |
12 | { |
13 | static struct kmsg_dump_iter iter; |
14 | static DEFINE_SPINLOCK(lock); |
15 | static char line[1024]; |
16 | struct console *con; |
17 | unsigned long flags; |
18 | size_t len = 0; |
19 | int cookie; |
20 | |
21 | /* |
22 | * If no consoles are available to output crash information, dump |
23 | * the kmsg buffer to stdout. |
24 | */ |
25 | |
26 | cookie = console_srcu_read_lock(); |
27 | for_each_console_srcu(con) { |
28 | /* |
29 | * The ttynull console and disabled consoles are ignored |
30 | * since they cannot output. All other consoles are |
31 | * expected to output the crash information. |
32 | */ |
33 | if (strcmp(con->name, "ttynull" ) != 0 && |
34 | (console_srcu_read_flags(con) & CON_ENABLED)) { |
35 | break; |
36 | } |
37 | } |
38 | console_srcu_read_unlock(cookie); |
39 | if (con) |
40 | return; |
41 | |
42 | if (!spin_trylock_irqsave(&lock, flags)) |
43 | return; |
44 | |
45 | kmsg_dump_rewind(iter: &iter); |
46 | |
47 | printf("kmsg_dump:\n" ); |
48 | while (kmsg_dump_get_line(iter: &iter, syslog: true, line, size: sizeof(line), len: &len)) { |
49 | line[len] = '\0'; |
50 | printf("%s" , line); |
51 | } |
52 | |
53 | spin_unlock_irqrestore(lock: &lock, flags); |
54 | } |
55 | |
56 | static struct kmsg_dumper kmsg_dumper = { |
57 | .dump = kmsg_dumper_stdout |
58 | }; |
59 | |
60 | int __init kmsg_dumper_stdout_init(void) |
61 | { |
62 | return kmsg_dump_register(dumper: &kmsg_dumper); |
63 | } |
64 | |
65 | __uml_postsetup(kmsg_dumper_stdout_init); |
66 | |