This patch creates 'opalmsg' command which can be used to dump opal console log
in crash. Currently it uses hard-coded start address and size of opal console
log buffer.
As this command is specific to POWER, it is coded as such.
Here is the sample output of 'opalmsg' command:
crash> opalmsg
[ 65.219056911,5] SkiBoot skiboot-5.4.0-218-ge0225cc-mukesh-dirty-df9a248 starting...
[ 65.219065872,5] initial console log level: memory 7, driver 5
[ 65.219068917,6] CPU: P8 generation processor(max 8 threads/core)
[ 65.219071681,7] CPU: Boot CPU PIR is 0x0060 PVR is 0x004d0200
[ 65.219074685,7] CPU: Initial max PIR set to 0x1fff
[ 65.219602559,5] OPAL table: 0x300c7440 .. 0x300c78d0, branch table: 0x30002000
[ 65.219607955,5] FDT: Parsing fdt @0xff00000
[ 65.225380389,5] XSCOM: chip 0x8 at 0x3fc4000000000 [P8 DD2.0]
[ 65.225387919,6] XSTOP: XSCOM addr = 0x2010c82, FIR bit = 31
[ 491.377710151,7] PHB#0022: LINK: Link is up
[ 494.026291523,7] BT: seq 0x25 netfn 0x0a cmd 0x48: Message sent to host
[ 494.027636927,7] BT: seq 0x25 netfn 0x0a cmd 0x48: IPMI MSG done
Log for dump collected on non OPAL ppc machine:
crash> opalmsg
Dump was not captured on an OPAL based machine
crash> help
btop help opalmsg set vm
On Non POWER machine 'opalmsg' command won't be available as opalmsg is
specific to POWER.
crash> opalmsg
crash: command not found: opalmsg
crash> help opalmsg
NAME
opalmsg - dump opal console log buffer
SYNOPSIS
opalmsg
DESCRIPTION
The opalmsg command retrieves, formats and dumps the OPAL console ring
buffer to help understand the state of OPAL firmware when the dump was
taken
EXAMPLES
crash> opalmsg
[ 65.219056911,5] SkiBoot skiboot-5.4.0-218-ge0225cc-df9a248 starting...
[ 65.225387919,6] XSTOP: XSCOM addr = 0x2010c82, FIR bit = 31
[ 491.377710151,7] PHB#0022: LINK: Link is up
[ 494.026291523,7] BT: seq 0x25 netfn 0x0a cmd 0x48: Message sent to host
[ 494.027636927,7] BT: seq 0x25 netfn 0x0a cmd 0x48: IPMI MSG done
Signed-off-by: Ankit Kumar <ankit(a)linux.vnet.ibm.com>
---
defs.h | 2 ++
global_data.c | 3 ++
help.c | 25 ++++++++++++++++
memory.c | 91 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 121 insertions(+)
diff --git a/defs.h b/defs.h
index 68ed4d4..c81154a 100644
--- a/defs.h
+++ b/defs.h
@@ -4623,6 +4623,7 @@ void cmd_template(void); /* tools.c */
void cmd_alias(void); /* cmdline.c */
void cmd_repeat(void); /* cmdline.c */
void cmd_rd(void); /* memory.c */
+void cmd_opalmsg(void); /* memory.c */
void cmd_wr(void); /* memory.c */
void cmd_ptov(void); /* memory.c */
void cmd_vtop(void); /* memory.c */
@@ -5189,6 +5190,7 @@ extern char *help_ptob[];
extern char *help_ptov[];
extern char *help_quit[];
extern char *help_rd[];
+extern char *help_opalmsg[];
extern char *help_repeat[];
extern char *help_runq[];
extern char *help_ipcs[];
diff --git a/global_data.c b/global_data.c
index 998aaae..6bf3406 100644
--- a/global_data.c
+++ b/global_data.c
@@ -102,6 +102,9 @@ struct command_table_entry linux_command_table[] = {
{"q", cmd_quit, help_quit, MINIMAL},
{"tree", cmd_tree, help_tree, REFRESH_TASK_TABLE},
{"rd", cmd_rd, help_rd, MINIMAL},
+#if defined(PPC) || defined(PPC64)
+ {"opalmsg", cmd_opalmsg, help_opalmsg, 0},
+#endif
{"repeat", cmd_repeat, help_repeat, 0},
{"runq", cmd_runq, help_runq, REFRESH_TASK_TABLE},
{"search", cmd_search, help_search, 0},
diff --git a/help.c b/help.c
index 35cd941..75d771e 100644
--- a/help.c
+++ b/help.c
@@ -1717,6 +1717,30 @@ char *help_rd[] = {
NULL
};
+char *help_opalmsg[] = {
+"opalmsg",
+"dump opal console log buffer",
+"",
+" The opalmsg command retrieves, formats and dumps the OPAL console ring",
+" buffer to help understand the state of OPAL firmware when the dump was",
+" taken",
+"\nEXAMPLES",
+"crash> opalmsg",
+"[ 65.219056911,5] SkiBoot skiboot-5.4.0-218-ge0225cc-df9a248 starting...",
+"[ 65.219065872,5] initial console log level: memory 7, driver 5",
+"[ 65.219068917,6] CPU: P8 generation processor(max 8 threads/core)",
+"[ 65.219071681,7] CPU: Boot CPU PIR is 0x0060 PVR is 0x004d0200",
+"[ 65.219074685,7] CPU: Initial max PIR set to 0x1fff",
+"[ 65.219602559,5] OPAL table: 0x300c7440 .. 0x300c78d0, branch table:
0x30002000",
+"[ 65.219607955,5] FDT: Parsing fdt @0xff00000",
+"[ 65.225380389,5] XSCOM: chip 0x8 at 0x3fc4000000000 [P8 DD2.0]",
+"[ 65.225387919,6] XSTOP: XSCOM addr = 0x2010c82, FIR bit = 31",
+"[ 491.377710151,7] PHB#0022: LINK: Link is up",
+"[ 494.026291523,7] BT: seq 0x25 netfn 0x0a cmd 0x48: Message sent to host",
+"[ 494.027636927,7] BT: seq 0x25 netfn 0x0a cmd 0x48: IPMI MSG done",
+NULL
+};
+
char *help_wr[] = {
"wr",
"write memory",
@@ -3778,6 +3802,7 @@ char *help_alias[] = {
" builtin for foreach",
" builtin size *",
" builtin dmesg log",
+" builtin opalmsg opalmsg",
" builtin lsmod mod",
" builtin last ps -l",
" ",
diff --git a/memory.c b/memory.c
index 774d090..e7b8495 100644
--- a/memory.c
+++ b/memory.c
@@ -1419,6 +1419,97 @@ struct memloc { /* common holder of read memory
*/
uint64_t limit64;
};
+/*
+ * Definitions derived from OPAL. These need to track corresponding values in
+ *
https://github.com/open-power/skiboot/blob/master/include/mem-map.h
+ */
+#define SKIBOOT_CONSOLE_DUMP_START 0x31000000
+#define SKIBOOT_CONSOLE_DUMP_SIZE 0x40000
+#define SKIBOOT_BASE 0x30000000
+
+void
+cmd_opalmsg(void)
+{
+ int i, a;
+ size_t typesz, sz;
+ void *location;
+ char readtype[20];
+ char *addrtype;
+ struct memloc mem;
+ int displayed, per_line;
+ int lost;
+ ulong error_handle;
+ struct opal {
+ unsigned long long base;
+ unsigned long long entry;
+ } opal;
+ long count = SKIBOOT_CONSOLE_DUMP_SIZE;
+ ulonglong addr = SKIBOOT_CONSOLE_DUMP_START;
+
+ if (CRASHDEBUG(4))
+ fprintf(fp, "<addr: %llx count: %ld (%s)>\n",
+ addr, count, "PHYSADDR");
+
+ /*
+ * Are we on an OPAL platform?
+ * struct opal of BSS section and hence default value will be ZERO(0)
+ * opal_init() in the kernel initializes this structure based on
+ * the platform. Use it as a key to determine whether the dump
+ * was taken on an OPAL based system or not.
+ */
+ if (symbol_exists("opal")) {
+ get_symbol_data("opal", sizeof(struct opal), &opal);
+ if (opal.base != SKIBOOT_BASE) {
+ fprintf(fp, "Dump was not captured on an OPAL based machine");
+ return;
+ }
+ } else {
+ fprintf(fp, "Dump was not captured on an OPAL based machine");
+ return;
+ }
+
+ BZERO(&mem, sizeof(struct memloc));
+ lost = typesz = per_line = 0;
+ location = NULL;
+
+ /* ASCII */
+ typesz = SIZEOF_8BIT;
+ location = &mem.u8;
+ sprintf(readtype, "ascii");
+ per_line = 256;
+ displayed = 0;
+
+ error_handle = FAULT_ON_ERROR;
+
+ for (i = a = 0; i < count; i++) {
+ if (!readmem(addr, PHYSADDR, location, typesz,
+ readtype, error_handle)) {
+ addr += typesz;
+ lost += 1;
+ continue;
+ }
+
+ if (isprint(mem.u8)) {
+ if ((a % per_line) == 0) {
+ if (displayed && i)
+ fprintf(fp, "\n");
+ }
+ fprintf(fp, "%c", mem.u8);
+ displayed++;
+ a++;
+ } else {
+ if (count == ASCII_UNLIMITED)
+ return;
+ a = 0;
+ }
+
+ addr += typesz;
+ }
+
+ if (lost != count)
+ fprintf(fp, "\n");
+}
+
static void
display_memory(ulonglong addr, long count, ulong flag, int memtype, void *opt)
{
--
2.7.4