aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRussell Currey <ruscur@russell.cc>2015-11-27 01:23:07 -0500
committerMichael Ellerman <mpe@ellerman.id.au>2015-12-27 03:12:40 -0500
commitaffddff69c55eb68969448f35f59054a370bc7c1 (patch)
tree08ab6b332d22f7a58e4a6650729b05f073a2f18d
parent2fc251a8dda56b71ec491bee4c6897e3e12c0739 (diff)
powerpc/powernv: Add a kmsg_dumper that flushes console output on panic
On BMC machines, console output is controlled by the OPAL firmware and is only flushed when its pollers are called. When the kernel is in a panic state, it no longer calls these pollers and thus console output does not completely flush, causing some output from the panic to be lost. Output is only actually lost when the kernel is configured to not power off or reboot after panic (i.e. CONFIG_PANIC_TIMEOUT is set to 0) since OPAL flushes the console buffer as part of its power down routines. Before this patch, however, only partial output would be printed during the timeout wait. This patch adds a new kmsg_dumper which gets called at panic time to ensure panic output is not lost. It accomplishes this by calling OPAL_CONSOLE_FLUSH in the OPAL API, and if that is not available, the pollers are called enough times to (hopefully) completely flush the buffer. The flushing mechanism will only affect output printed at and before the kmsg_dump call in kernel/panic.c:panic(). As such, the "end Kernel panic" message may still be truncated as follows: >Call Trace: >[c000000f1f603b00] [c0000000008e9458] dump_stack+0x90/0xbc (unreliable) >[c000000f1f603b30] [c0000000008e7e78] panic+0xf8/0x2c4 >[c000000f1f603bc0] [c000000000be4860] mount_block_root+0x288/0x33c >[c000000f1f603c80] [c000000000be4d14] prepare_namespace+0x1f4/0x254 >[c000000f1f603d00] [c000000000be43e8] kernel_init_freeable+0x318/0x350 >[c000000f1f603dc0] [c00000000000bd74] kernel_init+0x24/0x130 >[c000000f1f603e30] [c0000000000095b0] ret_from_kernel_thread+0x5c/0xac >---[ end Kernel panic - not This functionality is implemented as a kmsg_dumper as it seems to be the most sensible way to introduce platform-specific functionality to the panic function. Signed-off-by: Russell Currey <ruscur@russell.cc> Reviewed-by: Andrew Donnellan <andrew.donnellan@au1.ibm.com> Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
-rw-r--r--arch/powerpc/include/asm/opal-api.h3
-rw-r--r--arch/powerpc/include/asm/opal.h3
-rw-r--r--arch/powerpc/platforms/powernv/Makefile1
-rw-r--r--arch/powerpc/platforms/powernv/opal-kmsg.c68
-rw-r--r--arch/powerpc/platforms/powernv/opal-wrappers.S1
-rw-r--r--arch/powerpc/platforms/powernv/opal.c3
6 files changed, 78 insertions, 1 deletions
diff --git a/arch/powerpc/include/asm/opal-api.h b/arch/powerpc/include/asm/opal-api.h
index 8374afed9d0a..f8faaaeeca1e 100644
--- a/arch/powerpc/include/asm/opal-api.h
+++ b/arch/powerpc/include/asm/opal-api.h
@@ -157,7 +157,8 @@
157#define OPAL_LEDS_GET_INDICATOR 114 157#define OPAL_LEDS_GET_INDICATOR 114
158#define OPAL_LEDS_SET_INDICATOR 115 158#define OPAL_LEDS_SET_INDICATOR 115
159#define OPAL_CEC_REBOOT2 116 159#define OPAL_CEC_REBOOT2 116
160#define OPAL_LAST 116 160#define OPAL_CONSOLE_FLUSH 117
161#define OPAL_LAST 117
161 162
162/* Device tree flags */ 163/* Device tree flags */
163 164
diff --git a/arch/powerpc/include/asm/opal.h b/arch/powerpc/include/asm/opal.h
index 800115910e43..a5fd407213b6 100644
--- a/arch/powerpc/include/asm/opal.h
+++ b/arch/powerpc/include/asm/opal.h
@@ -35,6 +35,7 @@ int64_t opal_console_read(int64_t term_number, __be64 *length,
35 uint8_t *buffer); 35 uint8_t *buffer);
36int64_t opal_console_write_buffer_space(int64_t term_number, 36int64_t opal_console_write_buffer_space(int64_t term_number,
37 __be64 *length); 37 __be64 *length);
38void opal_console_flush(void);
38int64_t opal_rtc_read(__be32 *year_month_day, 39int64_t opal_rtc_read(__be32 *year_month_day,
39 __be64 *hour_minute_second_millisecond); 40 __be64 *hour_minute_second_millisecond);
40int64_t opal_rtc_write(uint32_t year_month_day, 41int64_t opal_rtc_write(uint32_t year_month_day,
@@ -262,6 +263,8 @@ extern int opal_resync_timebase(void);
262 263
263extern void opal_lpc_init(void); 264extern void opal_lpc_init(void);
264 265
266extern void opal_kmsg_init(void);
267
265extern int opal_event_request(unsigned int opal_event_nr); 268extern int opal_event_request(unsigned int opal_event_nr);
266 269
267struct opal_sg_list *opal_vmalloc_to_sg_list(void *vmalloc_addr, 270struct opal_sg_list *opal_vmalloc_to_sg_list(void *vmalloc_addr,
diff --git a/arch/powerpc/platforms/powernv/Makefile b/arch/powerpc/platforms/powernv/Makefile
index ee774e8a4837..f1516b5ecec9 100644
--- a/arch/powerpc/platforms/powernv/Makefile
+++ b/arch/powerpc/platforms/powernv/Makefile
@@ -2,6 +2,7 @@ obj-y += setup.o opal-wrappers.o opal.o opal-async.o idle.o
2obj-y += opal-rtc.o opal-nvram.o opal-lpc.o opal-flash.o 2obj-y += opal-rtc.o opal-nvram.o opal-lpc.o opal-flash.o
3obj-y += rng.o opal-elog.o opal-dump.o opal-sysparam.o opal-sensor.o 3obj-y += rng.o opal-elog.o opal-dump.o opal-sysparam.o opal-sensor.o
4obj-y += opal-msglog.o opal-hmi.o opal-power.o opal-irqchip.o 4obj-y += opal-msglog.o opal-hmi.o opal-power.o opal-irqchip.o
5obj-y += opal-kmsg.o
5 6
6obj-$(CONFIG_SMP) += smp.o subcore.o subcore-asm.o 7obj-$(CONFIG_SMP) += smp.o subcore.o subcore-asm.o
7obj-$(CONFIG_PCI) += pci.o pci-p5ioc2.o pci-ioda.o npu-dma.o 8obj-$(CONFIG_PCI) += pci.o pci-p5ioc2.o pci-ioda.o npu-dma.o
diff --git a/arch/powerpc/platforms/powernv/opal-kmsg.c b/arch/powerpc/platforms/powernv/opal-kmsg.c
new file mode 100644
index 000000000000..bd3b2ee1ba1d
--- /dev/null
+++ b/arch/powerpc/platforms/powernv/opal-kmsg.c
@@ -0,0 +1,68 @@
1/*
2 * kmsg dumper that ensures the OPAL console fully flushes panic messages
3 *
4 * Author: Russell Currey <ruscur@russell.cc>
5 *
6 * Copyright 2015 IBM Corporation.
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation; either version 2 of the License, or (at your
11 * option) any later version.
12 */
13
14#include <linux/kmsg_dump.h>
15
16#include <asm/opal.h>
17#include <asm/opal-api.h>
18
19/*
20 * Console output is controlled by OPAL firmware. The kernel regularly calls
21 * OPAL_POLL_EVENTS, which flushes some console output. In a panic state,
22 * however, the kernel no longer calls OPAL_POLL_EVENTS and the panic message
23 * may not be completely printed. This function does not actually dump the
24 * message, it just ensures that OPAL completely flushes the console buffer.
25 */
26static void force_opal_console_flush(struct kmsg_dumper *dumper,
27 enum kmsg_dump_reason reason)
28{
29 int i;
30
31 /*
32 * Outside of a panic context the pollers will continue to run,
33 * so we don't need to do any special flushing.
34 */
35 if (reason != KMSG_DUMP_PANIC)
36 return;
37
38 if (opal_check_token(OPAL_CONSOLE_FLUSH)) {
39 opal_console_flush();
40 } else {
41 /*
42 * If OPAL_CONSOLE_FLUSH is not implemented in the firmware,
43 * the console can still be flushed by calling the polling
44 * function enough times to flush the buffer. We don't know
45 * how much output still needs to be flushed, but we can be
46 * generous since the kernel is in panic and doesn't need
47 * to do much else.
48 */
49 printk(KERN_NOTICE "opal: OPAL_CONSOLE_FLUSH missing.\n");
50 for (i = 0; i < 1024; i++) {
51 opal_poll_events(NULL);
52 }
53 }
54}
55
56static struct kmsg_dumper opal_kmsg_dumper = {
57 .dump = force_opal_console_flush
58};
59
60void __init opal_kmsg_init(void)
61{
62 int rc;
63
64 /* Add our dumper to the list */
65 rc = kmsg_dump_register(&opal_kmsg_dumper);
66 if (rc != 0)
67 pr_err("opal: kmsg_dump_register failed; returned %d\n", rc);
68}
diff --git a/arch/powerpc/platforms/powernv/opal-wrappers.S b/arch/powerpc/platforms/powernv/opal-wrappers.S
index b7a464fef7a7..e45b88a5d7e0 100644
--- a/arch/powerpc/platforms/powernv/opal-wrappers.S
+++ b/arch/powerpc/platforms/powernv/opal-wrappers.S
@@ -301,3 +301,4 @@ OPAL_CALL(opal_flash_erase, OPAL_FLASH_ERASE);
301OPAL_CALL(opal_prd_msg, OPAL_PRD_MSG); 301OPAL_CALL(opal_prd_msg, OPAL_PRD_MSG);
302OPAL_CALL(opal_leds_get_ind, OPAL_LEDS_GET_INDICATOR); 302OPAL_CALL(opal_leds_get_ind, OPAL_LEDS_GET_INDICATOR);
303OPAL_CALL(opal_leds_set_ind, OPAL_LEDS_SET_INDICATOR); 303OPAL_CALL(opal_leds_set_ind, OPAL_LEDS_SET_INDICATOR);
304OPAL_CALL(opal_console_flush, OPAL_CONSOLE_FLUSH);
diff --git a/arch/powerpc/platforms/powernv/opal.c b/arch/powerpc/platforms/powernv/opal.c
index aad0033d65d1..b349dd3e76ea 100644
--- a/arch/powerpc/platforms/powernv/opal.c
+++ b/arch/powerpc/platforms/powernv/opal.c
@@ -748,6 +748,9 @@ static int __init opal_init(void)
748 opal_pdev_init(opal_node, "ibm,opal-flash"); 748 opal_pdev_init(opal_node, "ibm,opal-flash");
749 opal_pdev_init(opal_node, "ibm,opal-prd"); 749 opal_pdev_init(opal_node, "ibm,opal-prd");
750 750
751 /* Initialise OPAL kmsg dumper for flushing console on panic */
752 opal_kmsg_init();
753
751 return 0; 754 return 0;
752} 755}
753machine_subsys_initcall(powernv, opal_init); 756machine_subsys_initcall(powernv, opal_init);