[PATCH V2 1/2] powerpc/powernv: new function to access OPAL msglog

Subsystems: linux for powerpc (32-bit and 64-bit), the rest

STALE3822d

12 messages, 5 authors, 2016-02-18 · open the first message on its own page

[PATCH V2 1/2] powerpc/powernv: new function to access OPAL msglog

From: Andrew Donnellan <hidden>
Date: 2016-02-09 07:19:31

Currently, the OPAL msglog/console buffer is exposed as a sysfs file, with
the sysfs read handler responsible for retrieving the log from the OPAL
buffer. We'd like to be able to use it in xmon as well.

Refactor the OPAL msglog code to create a new function, opal_msglog_copy(),
that copies to an arbitrary buffer. Separate the initialisation code into
generic memcons init and sysfs file creation.

Signed-off-by: Andrew Donnellan <redacted>

---

Changes V1->V2:
- Incorporate comments from mpe
- Move the memcons pointer out of the bin_attribute struct
- Decouple memcons init from sysfs init
---
 arch/powerpc/include/asm/opal.h              |  3 +++
 arch/powerpc/platforms/powernv/opal-msglog.c | 29 ++++++++++++++++++----------
 arch/powerpc/platforms/powernv/opal.c        |  7 +++++--
 3 files changed, 27 insertions(+), 12 deletions(-)
diff --git a/arch/powerpc/include/asm/opal.h b/arch/powerpc/include/asm/opal.h
index 07a99e6..9d86c66 100644
--- a/arch/powerpc/include/asm/opal.h
+++ b/arch/powerpc/include/asm/opal.h
@@ -248,6 +248,7 @@ extern int opal_elog_init(void);
 extern void opal_platform_dump_init(void);
 extern void opal_sys_param_init(void);
 extern void opal_msglog_init(void);
+extern void opal_msglog_sysfs_init(void);
 extern int opal_async_comp_init(void);
 extern int opal_sensor_init(void);
 extern int opal_hmi_handler_init(void);
@@ -273,6 +274,8 @@ void opal_free_sg_list(struct opal_sg_list *sg);
 
 extern int opal_error_code(int rc);
 
+ssize_t opal_msglog_copy(char *to, loff_t pos, size_t count);
+
 #endif /* __ASSEMBLY__ */
 
 #endif /* _ASM_POWERPC_OPAL_H */
diff --git a/arch/powerpc/platforms/powernv/opal-msglog.c b/arch/powerpc/platforms/powernv/opal-msglog.c
index 44ed78a..59fa6e1 100644
--- a/arch/powerpc/platforms/powernv/opal-msglog.c
+++ b/arch/powerpc/platforms/powernv/opal-msglog.c
@@ -31,26 +31,25 @@ struct memcons {
 	__be32 in_cons;
 };
 
-static ssize_t opal_msglog_read(struct file *file, struct kobject *kobj,
-				struct bin_attribute *bin_attr, char *to,
-				loff_t pos, size_t count)
+static struct memcons *opal_memcons = NULL;
+
+ssize_t opal_msglog_copy(char *to, loff_t pos, size_t count)
 {
-	struct memcons *mc = bin_attr->private;
 	const char *conbuf;
 	ssize_t ret;
 	size_t first_read = 0;
 	uint32_t out_pos, avail;
 
-	if (!mc)
+	if (!opal_memcons)
 		return -ENODEV;
 
-	out_pos = be32_to_cpu(ACCESS_ONCE(mc->out_pos));
+	out_pos = be32_to_cpu(ACCESS_ONCE(opal_memcons->out_pos));
 
 	/* Now we've read out_pos, put a barrier in before reading the new
 	 * data it points to in conbuf. */
 	smp_rmb();
 
-	conbuf = phys_to_virt(be64_to_cpu(mc->obuf_phys));
+	conbuf = phys_to_virt(be64_to_cpu(opal_memcons->obuf_phys));
 
 	/* When the buffer has wrapped, read from the out_pos marker to the end
 	 * of the buffer, and then read the remaining data as in the un-wrapped
@@ -58,7 +57,7 @@ static ssize_t opal_msglog_read(struct file *file, struct kobject *kobj,
 	if (out_pos & MEMCONS_OUT_POS_WRAP) {
 
 		out_pos &= MEMCONS_OUT_POS_MASK;
-		avail = be32_to_cpu(mc->obuf_size) - out_pos;
+		avail = be32_to_cpu(opal_memcons->obuf_size) - out_pos;
 
 		ret = memory_read_from_buffer(to, count, &pos,
 				conbuf + out_pos, avail);
@@ -76,7 +75,7 @@ static ssize_t opal_msglog_read(struct file *file, struct kobject *kobj,
 	}
 
 	/* Sanity check. The firmware should not do this to us. */
-	if (out_pos > be32_to_cpu(mc->obuf_size)) {
+	if (out_pos > be32_to_cpu(opal_memcons->obuf_size)) {
 		pr_err("OPAL: memory console corruption. Aborting read.\n");
 		return -EINVAL;
 	}
@@ -91,6 +90,13 @@ out:
 	return ret;
 }
 
+static ssize_t opal_msglog_read(struct file *file, struct kobject *kobj,
+				struct bin_attribute *bin_attr, char *to,
+				loff_t pos, size_t count)
+{
+	return opal_msglog_copy(to, pos, count);
+}
+
 static struct bin_attribute opal_msglog_attr = {
 	.attr = {.name = "msglog", .mode = 0444},
 	.read = opal_msglog_read
@@ -117,8 +123,11 @@ void __init opal_msglog_init(void)
 		return;
 	}
 
-	opal_msglog_attr.private = mc;
+	opal_memcons = mc;
+}
 
+void __init opal_msglog_sysfs_init(void)
+{
 	if (sysfs_create_bin_file(opal_kobj, &opal_msglog_attr) != 0)
 		pr_warn("OPAL: sysfs file creation failed\n");
 }
diff --git a/arch/powerpc/platforms/powernv/opal.c b/arch/powerpc/platforms/powernv/opal.c
index 4e0da5a..0256d07 100644
--- a/arch/powerpc/platforms/powernv/opal.c
+++ b/arch/powerpc/platforms/powernv/opal.c
@@ -724,6 +724,9 @@ static int __init opal_init(void)
 		of_node_put(leds);
 	}
 
+	/* Initialise OPAL message log interface */
+	opal_msglog_init();
+
 	/* Create "opal" kobject under /sys/firmware */
 	rc = opal_sysfs_init();
 	if (rc == 0) {
@@ -739,8 +742,8 @@ static int __init opal_init(void)
 		opal_platform_dump_init();
 		/* Setup system parameters interface */
 		opal_sys_param_init();
-		/* Setup message log interface. */
-		opal_msglog_init();
+		/* Setup message log sysfs interface. */
+		opal_msglog_sysfs_init();
 	}
 
 	/* Initialize platform devices: IPMI backend, PRD & flash interface */
-- 
Andrew Donnellan              Software Engineer, OzLabs
andrew.donnellan@au1.ibm.com  Australia Development Lab, Canberra
+61 2 6201 8874 (work)        IBM Australia Limited

[PATCH V2 2/2] powerpc/xmon: add command to dump OPAL msglog

From: Andrew Donnellan <hidden>
Date: 2016-02-09 07:19:02

Add the 'do' command to dump the OPAL msglog in xmon.

Signed-off-by: Andrew Donnellan <redacted>
---
 arch/powerpc/xmon/xmon.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 60 insertions(+)
diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c
index 07a8508..48b75ae 100644
--- a/arch/powerpc/xmon/xmon.c
+++ b/arch/powerpc/xmon/xmon.c
@@ -47,6 +47,11 @@
 #include <asm/debug.h>
 #include <asm/hw_breakpoint.h>
 
+#ifdef CONFIG_PPC_POWERNV
+#include <asm/opal.h>
+#include <asm/firmware.h>
+#endif
+
 #ifdef CONFIG_PPC64
 #include <asm/hvcall.h>
 #include <asm/paca.h>
@@ -119,6 +124,11 @@ static void dump(void);
 static void prdump(unsigned long, long);
 static int ppc_inst_dump(unsigned long, long, int);
 static void dump_log_buf(void);
+
+#ifdef CONFIG_PPC_POWERNV
+static void dump_opal_msglog(void);
+#endif
+
 static void backtrace(struct pt_regs *);
 static void excprint(struct pt_regs *);
 static void prregs(struct pt_regs *);
@@ -202,6 +212,10 @@ Commands:\n\
   df	dump float values\n\
   dd	dump double values\n\
   dl    dump the kernel log buffer\n"
+#ifdef CONFIG_PPC_POWERNV
+  "\
+  do    dump the OPAL message log\n"
+#endif
 #ifdef CONFIG_PPC64
   "\
   dp[#]	dump paca for current cpu, or cpu #\n\
@@ -2253,6 +2267,12 @@ dump(void)
 		last_cmd = "di\n";
 	} else if (c == 'l') {
 		dump_log_buf();
+	} else if (c == 'o') {
+#ifdef CONFIG_PPC_POWERNV
+		dump_opal_msglog();
+#else
+		printf("Machine is not running OPAL firmware.\n");
+#endif
 	} else if (c == 'r') {
 		scanhex(&ndump);
 		if (ndump == 0)
@@ -2395,6 +2415,46 @@ dump_log_buf(void)
 	catch_memory_errors = 0;
 }
 
+#ifdef CONFIG_PPC_POWERNV
+void
+dump_opal_msglog(void)
+{
+	unsigned char buf[128];
+	ssize_t res;
+	loff_t pos = 0;
+
+	if (!firmware_has_feature(FW_FEATURE_OPAL)) {
+		printf("Machine is not running OPAL firmware.\n");
+		return;
+	}
+
+	if (setjmp(bus_error_jmp) != 0) {
+		printf("Error dumping OPAL msglog!\n");
+		return;
+	}
+
+	catch_memory_errors = 1;
+	sync();
+
+	xmon_start_pagination();
+	while ((res = opal_msglog_copy(buf, pos, sizeof(buf) - 1))) {
+		if (res < 0) {
+			printf("Error dumping OPAL msglog! Error: %zd\n", res);
+			break;
+		}
+		buf[res] = '\0';
+		printf("%s", buf);
+		pos += res;
+	}
+	xmon_end_pagination();
+
+	sync();
+	/* wait a little while to see if we get a machine check */
+	__delay(200);
+	catch_memory_errors = 0;
+}
+#endif
+
 /*
  * Memory operations - move, set, print differences
  */
-- 
Andrew Donnellan              Software Engineer, OzLabs
andrew.donnellan@au1.ibm.com  Australia Development Lab, Canberra
+61 2 6201 8874 (work)        IBM Australia Limited

Re: [PATCH V2 1/2] powerpc/powernv: new function to access OPAL msglog

From: Stewart Smith <hidden>
Date: 2016-02-11 06:33:09

Andrew Donnellan [off-list ref] writes:
Currently, the OPAL msglog/console buffer is exposed as a sysfs file, with
the sysfs read handler responsible for retrieving the log from the OPAL
buffer. We'd like to be able to use it in xmon as well.

Refactor the OPAL msglog code to create a new function, opal_msglog_copy(),
that copies to an arbitrary buffer. Separate the initialisation code into
generic memcons init and sysfs file creation.

Signed-off-by: Andrew Donnellan <redacted>
Acked-by: Stewart Smith <redacted>

-- 
Stewart Smith
OPAL Architect, IBM.

Re: [PATCH V2 1/2] powerpc/powernv: new function to access OPAL msglog

From: Joel Stanley <joel@jms.id.au>
Date: 2016-02-11 07:15:16

On Tue, Feb 9, 2016 at 5:47 PM, Andrew Donnellan
[off-list ref] wrote:
Currently, the OPAL msglog/console buffer is exposed as a sysfs file, with
the sysfs read handler responsible for retrieving the log from the OPAL
buffer. We'd like to be able to use it in xmon as well.

Refactor the OPAL msglog code to create a new function, opal_msglog_copy(),
that copies to an arbitrary buffer. Separate the initialisation code into
generic memcons init and sysfs file creation.

Signed-off-by: Andrew Donnellan <redacted>
Looks like you didn't break it much. Congratulations on being the new
memcons maintainer!

There's one issue with your error handling.
quoted hunk
diff --git a/arch/powerpc/platforms/powernv/opal.c b/arch/powerpc/platforms/powernv/opal.c
index 4e0da5a..0256d07 100644
--- a/arch/powerpc/platforms/powernv/opal.c
+++ b/arch/powerpc/platforms/powernv/opal.c
@@ -724,6 +724,9 @@ static int __init opal_init(void)
                of_node_put(leds);
        }

+       /* Initialise OPAL message log interface */
+       opal_msglog_init();
If this fails due to eg. the magic number being wrong.
quoted hunk
+
        /* Create "opal" kobject under /sys/firmware */
        rc = opal_sysfs_init();
        if (rc == 0) {
@@ -739,8 +742,8 @@ static int __init opal_init(void)
                opal_platform_dump_init();
                /* Setup system parameters interface */
                opal_sys_param_init();
-               /* Setup message log interface. */
-               opal_msglog_init();
+               /* Setup message log sysfs interface. */
+               opal_msglog_sysfs_init();
This will succeed, leaving you with a sysfs file attached to a broken driver.
        }

        /* Initialize platform devices: IPMI backend, PRD & flash interface */

Re: [PATCH V2 1/2] powerpc/powernv: new function to access OPAL msglog

From: Andrew Donnellan <hidden>
Date: 2016-02-11 07:32:41

On 11/02/16 18:14, Joel Stanley wrote:
Looks like you didn't break it much. Congratulations on being the new
memcons maintainer!
Argh, I forgot the golden rule of kernel development - if you touch it, 
you own it... :)
There's one issue with your error handling.
quoted
diff --git a/arch/powerpc/platforms/powernv/opal.c b/arch/powerpc/platforms/powernv/opal.c
index 4e0da5a..0256d07 100644
--- a/arch/powerpc/platforms/powernv/opal.c
+++ b/arch/powerpc/platforms/powernv/opal.c
@@ -724,6 +724,9 @@ static int __init opal_init(void)
                 of_node_put(leds);
         }

+       /* Initialise OPAL message log interface */
+       opal_msglog_init();
If this fails due to eg. the magic number being wrong.
quoted
+
         /* Create "opal" kobject under /sys/firmware */
         rc = opal_sysfs_init();
         if (rc == 0) {
@@ -739,8 +742,8 @@ static int __init opal_init(void)
                 opal_platform_dump_init();
                 /* Setup system parameters interface */
                 opal_sys_param_init();
-               /* Setup message log interface. */
-               opal_msglog_init();
+               /* Setup message log sysfs interface. */
+               opal_msglog_sysfs_init();
This will succeed, leaving you with a sysfs file attached to a broken driver.
V3 on its way...

-- 
Andrew Donnellan              Software Engineer, OzLabs
andrew.donnellan@au1.ibm.com  Australia Development Lab, Canberra
+61 2 6201 8874 (work)        IBM Australia Limited

[PATCH V3 2/2] powerpc/xmon: add command to dump OPAL msglog

From: Andrew Donnellan <hidden>
Date: 2016-02-11 07:37:41

Add the 'do' command to dump the OPAL msglog in xmon.

Signed-off-by: Andrew Donnellan <redacted>
---
 arch/powerpc/xmon/xmon.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 60 insertions(+)
diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c
index 07a8508..48b75ae 100644
--- a/arch/powerpc/xmon/xmon.c
+++ b/arch/powerpc/xmon/xmon.c
@@ -47,6 +47,11 @@
 #include <asm/debug.h>
 #include <asm/hw_breakpoint.h>
 
+#ifdef CONFIG_PPC_POWERNV
+#include <asm/opal.h>
+#include <asm/firmware.h>
+#endif
+
 #ifdef CONFIG_PPC64
 #include <asm/hvcall.h>
 #include <asm/paca.h>
@@ -119,6 +124,11 @@ static void dump(void);
 static void prdump(unsigned long, long);
 static int ppc_inst_dump(unsigned long, long, int);
 static void dump_log_buf(void);
+
+#ifdef CONFIG_PPC_POWERNV
+static void dump_opal_msglog(void);
+#endif
+
 static void backtrace(struct pt_regs *);
 static void excprint(struct pt_regs *);
 static void prregs(struct pt_regs *);
@@ -202,6 +212,10 @@ Commands:\n\
   df	dump float values\n\
   dd	dump double values\n\
   dl    dump the kernel log buffer\n"
+#ifdef CONFIG_PPC_POWERNV
+  "\
+  do    dump the OPAL message log\n"
+#endif
 #ifdef CONFIG_PPC64
   "\
   dp[#]	dump paca for current cpu, or cpu #\n\
@@ -2253,6 +2267,12 @@ dump(void)
 		last_cmd = "di\n";
 	} else if (c == 'l') {
 		dump_log_buf();
+	} else if (c == 'o') {
+#ifdef CONFIG_PPC_POWERNV
+		dump_opal_msglog();
+#else
+		printf("Machine is not running OPAL firmware.\n");
+#endif
 	} else if (c == 'r') {
 		scanhex(&ndump);
 		if (ndump == 0)
@@ -2395,6 +2415,46 @@ dump_log_buf(void)
 	catch_memory_errors = 0;
 }
 
+#ifdef CONFIG_PPC_POWERNV
+void
+dump_opal_msglog(void)
+{
+	unsigned char buf[128];
+	ssize_t res;
+	loff_t pos = 0;
+
+	if (!firmware_has_feature(FW_FEATURE_OPAL)) {
+		printf("Machine is not running OPAL firmware.\n");
+		return;
+	}
+
+	if (setjmp(bus_error_jmp) != 0) {
+		printf("Error dumping OPAL msglog!\n");
+		return;
+	}
+
+	catch_memory_errors = 1;
+	sync();
+
+	xmon_start_pagination();
+	while ((res = opal_msglog_copy(buf, pos, sizeof(buf) - 1))) {
+		if (res < 0) {
+			printf("Error dumping OPAL msglog! Error: %zd\n", res);
+			break;
+		}
+		buf[res] = '\0';
+		printf("%s", buf);
+		pos += res;
+	}
+	xmon_end_pagination();
+
+	sync();
+	/* wait a little while to see if we get a machine check */
+	__delay(200);
+	catch_memory_errors = 0;
+}
+#endif
+
 /*
  * Memory operations - move, set, print differences
  */
-- 
Andrew Donnellan              Software Engineer, OzLabs
andrew.donnellan@au1.ibm.com  Australia Development Lab, Canberra
+61 2 6201 8874 (work)        IBM Australia Limited

[PATCH V3 1/2] powerpc/powernv: new function to access OPAL msglog

From: Andrew Donnellan <hidden>
Date: 2016-02-11 07:38:06

Currently, the OPAL msglog/console buffer is exposed as a sysfs file, with
the sysfs read handler responsible for retrieving the log from the OPAL
buffer. We'd like to be able to use it in xmon as well.

Refactor the OPAL msglog code to create a new function, opal_msglog_copy(),
that copies to an arbitrary buffer. Separate the initialisation code into
generic memcons init and sysfs file creation.

Signed-off-by: Andrew Donnellan <redacted>

---

Changes V2->V3:
- incorporate comments from Joel Stanley
- opal_msglog_sysfs_init() now bails out if opal_memcons isn't set

Changes V1->V2:
- Incorporate comments from mpe
- Move the memcons pointer out of the bin_attribute struct
- Decouple memcons init from sysfs init
---
 arch/powerpc/include/asm/opal.h              |  3 +++
 arch/powerpc/platforms/powernv/opal-msglog.c | 34 ++++++++++++++++++++--------
 arch/powerpc/platforms/powernv/opal.c        |  7 ++++--
 3 files changed, 32 insertions(+), 12 deletions(-)
diff --git a/arch/powerpc/include/asm/opal.h b/arch/powerpc/include/asm/opal.h
index 07a99e6..9d86c66 100644
--- a/arch/powerpc/include/asm/opal.h
+++ b/arch/powerpc/include/asm/opal.h
@@ -248,6 +248,7 @@ extern int opal_elog_init(void);
 extern void opal_platform_dump_init(void);
 extern void opal_sys_param_init(void);
 extern void opal_msglog_init(void);
+extern void opal_msglog_sysfs_init(void);
 extern int opal_async_comp_init(void);
 extern int opal_sensor_init(void);
 extern int opal_hmi_handler_init(void);
@@ -273,6 +274,8 @@ void opal_free_sg_list(struct opal_sg_list *sg);
 
 extern int opal_error_code(int rc);
 
+ssize_t opal_msglog_copy(char *to, loff_t pos, size_t count);
+
 #endif /* __ASSEMBLY__ */
 
 #endif /* _ASM_POWERPC_OPAL_H */
diff --git a/arch/powerpc/platforms/powernv/opal-msglog.c b/arch/powerpc/platforms/powernv/opal-msglog.c
index 44ed78a..c7a8f72 100644
--- a/arch/powerpc/platforms/powernv/opal-msglog.c
+++ b/arch/powerpc/platforms/powernv/opal-msglog.c
@@ -31,26 +31,25 @@ struct memcons {
 	__be32 in_cons;
 };
 
-static ssize_t opal_msglog_read(struct file *file, struct kobject *kobj,
-				struct bin_attribute *bin_attr, char *to,
-				loff_t pos, size_t count)
+static struct memcons *opal_memcons = NULL;
+
+ssize_t opal_msglog_copy(char *to, loff_t pos, size_t count)
 {
-	struct memcons *mc = bin_attr->private;
 	const char *conbuf;
 	ssize_t ret;
 	size_t first_read = 0;
 	uint32_t out_pos, avail;
 
-	if (!mc)
+	if (!opal_memcons)
 		return -ENODEV;
 
-	out_pos = be32_to_cpu(ACCESS_ONCE(mc->out_pos));
+	out_pos = be32_to_cpu(ACCESS_ONCE(opal_memcons->out_pos));
 
 	/* Now we've read out_pos, put a barrier in before reading the new
 	 * data it points to in conbuf. */
 	smp_rmb();
 
-	conbuf = phys_to_virt(be64_to_cpu(mc->obuf_phys));
+	conbuf = phys_to_virt(be64_to_cpu(opal_memcons->obuf_phys));
 
 	/* When the buffer has wrapped, read from the out_pos marker to the end
 	 * of the buffer, and then read the remaining data as in the un-wrapped
@@ -58,7 +57,7 @@ static ssize_t opal_msglog_read(struct file *file, struct kobject *kobj,
 	if (out_pos & MEMCONS_OUT_POS_WRAP) {
 
 		out_pos &= MEMCONS_OUT_POS_MASK;
-		avail = be32_to_cpu(mc->obuf_size) - out_pos;
+		avail = be32_to_cpu(opal_memcons->obuf_size) - out_pos;
 
 		ret = memory_read_from_buffer(to, count, &pos,
 				conbuf + out_pos, avail);
@@ -76,7 +75,7 @@ static ssize_t opal_msglog_read(struct file *file, struct kobject *kobj,
 	}
 
 	/* Sanity check. The firmware should not do this to us. */
-	if (out_pos > be32_to_cpu(mc->obuf_size)) {
+	if (out_pos > be32_to_cpu(opal_memcons->obuf_size)) {
 		pr_err("OPAL: memory console corruption. Aborting read.\n");
 		return -EINVAL;
 	}
@@ -91,6 +90,13 @@ out:
 	return ret;
 }
 
+static ssize_t opal_msglog_read(struct file *file, struct kobject *kobj,
+				struct bin_attribute *bin_attr, char *to,
+				loff_t pos, size_t count)
+{
+	return opal_msglog_copy(to, pos, count);
+}
+
 static struct bin_attribute opal_msglog_attr = {
 	.attr = {.name = "msglog", .mode = 0444},
 	.read = opal_msglog_read
@@ -117,8 +123,16 @@ void __init opal_msglog_init(void)
 		return;
 	}
 
-	opal_msglog_attr.private = mc;
+	opal_memcons = mc;
+}
 
+void __init opal_msglog_sysfs_init(void)
+{
+	if (!opal_memcons) {
+		pr_warn("OPAL: message log initialisation failed, not creating sysfs entry\n");
+		return;
+	}
+	
 	if (sysfs_create_bin_file(opal_kobj, &opal_msglog_attr) != 0)
 		pr_warn("OPAL: sysfs file creation failed\n");
 }
diff --git a/arch/powerpc/platforms/powernv/opal.c b/arch/powerpc/platforms/powernv/opal.c
index 4e0da5a..0256d07 100644
--- a/arch/powerpc/platforms/powernv/opal.c
+++ b/arch/powerpc/platforms/powernv/opal.c
@@ -724,6 +724,9 @@ static int __init opal_init(void)
 		of_node_put(leds);
 	}
 
+	/* Initialise OPAL message log interface */
+	opal_msglog_init();
+
 	/* Create "opal" kobject under /sys/firmware */
 	rc = opal_sysfs_init();
 	if (rc == 0) {
@@ -739,8 +742,8 @@ static int __init opal_init(void)
 		opal_platform_dump_init();
 		/* Setup system parameters interface */
 		opal_sys_param_init();
-		/* Setup message log interface. */
-		opal_msglog_init();
+		/* Setup message log sysfs interface. */
+		opal_msglog_sysfs_init();
 	}
 
 	/* Initialize platform devices: IPMI backend, PRD & flash interface */
-- 
Andrew Donnellan              Software Engineer, OzLabs
andrew.donnellan@au1.ibm.com  Australia Development Lab, Canberra
+61 2 6201 8874 (work)        IBM Australia Limited

Re: [PATCH V2 2/2] powerpc/xmon: add command to dump OPAL msglog

From: Denis Kirjanov <hidden>
Date: 2016-02-11 14:15:42

On 2/9/16, Andrew Donnellan [off-list ref] wrote:
Add the 'do' command to dump the OPAL msglog in xmon.

Signed-off-by: Andrew Donnellan <redacted>
I think it would be better to create system-specific files under
 powerpc/xmon/ directory, in this case something like xmon_powernv.c.

There are some many macros there.

Current code already looks very ugly, look at the cell-specific spu* stuff
for example.
quoted hunk
---
 arch/powerpc/xmon/xmon.c | 60
++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 60 insertions(+)
diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c
index 07a8508..48b75ae 100644
--- a/arch/powerpc/xmon/xmon.c
+++ b/arch/powerpc/xmon/xmon.c
@@ -47,6 +47,11 @@
 #include <asm/debug.h>
 #include <asm/hw_breakpoint.h>

+#ifdef CONFIG_PPC_POWERNV
+#include <asm/opal.h>
+#include <asm/firmware.h>
+#endif
+
 #ifdef CONFIG_PPC64
 #include <asm/hvcall.h>
 #include <asm/paca.h>
@@ -119,6 +124,11 @@ static void dump(void);
 static void prdump(unsigned long, long);
 static int ppc_inst_dump(unsigned long, long, int);
 static void dump_log_buf(void);
+
+#ifdef CONFIG_PPC_POWERNV
+static void dump_opal_msglog(void);
+#endif
+
 static void backtrace(struct pt_regs *);
 static void excprint(struct pt_regs *);
 static void prregs(struct pt_regs *);
@@ -202,6 +212,10 @@ Commands:\n\
   df	dump float values\n\
   dd	dump double values\n\
   dl    dump the kernel log buffer\n"
+#ifdef CONFIG_PPC_POWERNV
+  "\
+  do    dump the OPAL message log\n"
+#endif
 #ifdef CONFIG_PPC64
   "\
   dp[#]	dump paca for current cpu, or cpu #\n\
@@ -2253,6 +2267,12 @@ dump(void)
 		last_cmd = "di\n";
 	} else if (c == 'l') {
 		dump_log_buf();
+	} else if (c == 'o') {
+#ifdef CONFIG_PPC_POWERNV
+		dump_opal_msglog();
+#else
+		printf("Machine is not running OPAL firmware.\n");
+#endif
 	} else if (c == 'r') {
 		scanhex(&ndump);
 		if (ndump == 0)
@@ -2395,6 +2415,46 @@ dump_log_buf(void)
 	catch_memory_errors = 0;
 }

+#ifdef CONFIG_PPC_POWERNV
+void
+dump_opal_msglog(void)
+{
+	unsigned char buf[128];
+	ssize_t res;
+	loff_t pos = 0;
+
+	if (!firmware_has_feature(FW_FEATURE_OPAL)) {
+		printf("Machine is not running OPAL firmware.\n");
+		return;
+	}
+
+	if (setjmp(bus_error_jmp) != 0) {
+		printf("Error dumping OPAL msglog!\n");
+		return;
+	}
+
+	catch_memory_errors = 1;
+	sync();
+
+	xmon_start_pagination();
+	while ((res = opal_msglog_copy(buf, pos, sizeof(buf) - 1))) {
+		if (res < 0) {
+			printf("Error dumping OPAL msglog! Error: %zd\n", res);
+			break;
+		}
+		buf[res] = '\0';
+		printf("%s", buf);
+		pos += res;
+	}
+	xmon_end_pagination();
+
+	sync();
+	/* wait a little while to see if we get a machine check */
+	__delay(200);
+	catch_memory_errors = 0;
+}
+#endif
+
 /*
  * Memory operations - move, set, print differences
  */
--
Andrew Donnellan              Software Engineer, OzLabs
andrew.donnellan@au1.ibm.com  Australia Development Lab, Canberra
+61 2 6201 8874 (work)        IBM Australia Limited

_______________________________________________
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev

Re: [PATCH V3 1/2] powerpc/powernv: new function to access OPAL msglog

From: Joel Stanley <joel@jms.id.au>
Date: 2016-02-11 22:30:33

On Thu, Feb 11, 2016 at 6:06 PM, Andrew Donnellan
[off-list ref] wrote:
Currently, the OPAL msglog/console buffer is exposed as a sysfs file, with
the sysfs read handler responsible for retrieving the log from the OPAL
buffer. We'd like to be able to use it in xmon as well.

Refactor the OPAL msglog code to create a new function, opal_msglog_copy(),
that copies to an arbitrary buffer. Separate the initialisation code into
generic memcons init and sysfs file creation.

Signed-off-by: Andrew Donnellan <redacted>
Reviewed-by: Joel Stanley <joel@jms.id.au>
quoted hunk
---

Changes V2->V3:
- incorporate comments from Joel Stanley
- opal_msglog_sysfs_init() now bails out if opal_memcons isn't set

Changes V1->V2:
- Incorporate comments from mpe
- Move the memcons pointer out of the bin_attribute struct
- Decouple memcons init from sysfs init
---
 arch/powerpc/include/asm/opal.h              |  3 +++
 arch/powerpc/platforms/powernv/opal-msglog.c | 34 ++++++++++++++++++++--------
 arch/powerpc/platforms/powernv/opal.c        |  7 ++++--
 3 files changed, 32 insertions(+), 12 deletions(-)
diff --git a/arch/powerpc/include/asm/opal.h b/arch/powerpc/include/asm/opal.h
index 07a99e6..9d86c66 100644
--- a/arch/powerpc/include/asm/opal.h
+++ b/arch/powerpc/include/asm/opal.h
@@ -248,6 +248,7 @@ extern int opal_elog_init(void);
 extern void opal_platform_dump_init(void);
 extern void opal_sys_param_init(void);
 extern void opal_msglog_init(void);
+extern void opal_msglog_sysfs_init(void);
 extern int opal_async_comp_init(void);
 extern int opal_sensor_init(void);
 extern int opal_hmi_handler_init(void);
@@ -273,6 +274,8 @@ void opal_free_sg_list(struct opal_sg_list *sg);

 extern int opal_error_code(int rc);

+ssize_t opal_msglog_copy(char *to, loff_t pos, size_t count);
+
 #endif /* __ASSEMBLY__ */

 #endif /* _ASM_POWERPC_OPAL_H */
diff --git a/arch/powerpc/platforms/powernv/opal-msglog.c b/arch/powerpc/platforms/powernv/opal-msglog.c
index 44ed78a..c7a8f72 100644
--- a/arch/powerpc/platforms/powernv/opal-msglog.c
+++ b/arch/powerpc/platforms/powernv/opal-msglog.c
@@ -31,26 +31,25 @@ struct memcons {
        __be32 in_cons;
 };

-static ssize_t opal_msglog_read(struct file *file, struct kobject *kobj,
-                               struct bin_attribute *bin_attr, char *to,
-                               loff_t pos, size_t count)
+static struct memcons *opal_memcons = NULL;
+
+ssize_t opal_msglog_copy(char *to, loff_t pos, size_t count)
 {
-       struct memcons *mc = bin_attr->private;
        const char *conbuf;
        ssize_t ret;
        size_t first_read = 0;
        uint32_t out_pos, avail;

-       if (!mc)
+       if (!opal_memcons)
                return -ENODEV;

-       out_pos = be32_to_cpu(ACCESS_ONCE(mc->out_pos));
+       out_pos = be32_to_cpu(ACCESS_ONCE(opal_memcons->out_pos));

        /* Now we've read out_pos, put a barrier in before reading the new
         * data it points to in conbuf. */
        smp_rmb();

-       conbuf = phys_to_virt(be64_to_cpu(mc->obuf_phys));
+       conbuf = phys_to_virt(be64_to_cpu(opal_memcons->obuf_phys));

        /* When the buffer has wrapped, read from the out_pos marker to the end
         * of the buffer, and then read the remaining data as in the un-wrapped
@@ -58,7 +57,7 @@ static ssize_t opal_msglog_read(struct file *file, struct kobject *kobj,
        if (out_pos & MEMCONS_OUT_POS_WRAP) {

                out_pos &= MEMCONS_OUT_POS_MASK;
-               avail = be32_to_cpu(mc->obuf_size) - out_pos;
+               avail = be32_to_cpu(opal_memcons->obuf_size) - out_pos;

                ret = memory_read_from_buffer(to, count, &pos,
                                conbuf + out_pos, avail);
@@ -76,7 +75,7 @@ static ssize_t opal_msglog_read(struct file *file, struct kobject *kobj,
        }

        /* Sanity check. The firmware should not do this to us. */
-       if (out_pos > be32_to_cpu(mc->obuf_size)) {
+       if (out_pos > be32_to_cpu(opal_memcons->obuf_size)) {
                pr_err("OPAL: memory console corruption. Aborting read.\n");
                return -EINVAL;
        }
@@ -91,6 +90,13 @@ out:
        return ret;
 }

+static ssize_t opal_msglog_read(struct file *file, struct kobject *kobj,
+                               struct bin_attribute *bin_attr, char *to,
+                               loff_t pos, size_t count)
+{
+       return opal_msglog_copy(to, pos, count);
+}
+
 static struct bin_attribute opal_msglog_attr = {
        .attr = {.name = "msglog", .mode = 0444},
        .read = opal_msglog_read
@@ -117,8 +123,16 @@ void __init opal_msglog_init(void)
                return;
        }

-       opal_msglog_attr.private = mc;
+       opal_memcons = mc;
+}

+void __init opal_msglog_sysfs_init(void)
+{
+       if (!opal_memcons) {
+               pr_warn("OPAL: message log initialisation failed, not creating sysfs entry\n");
+               return;
+       }
+
        if (sysfs_create_bin_file(opal_kobj, &opal_msglog_attr) != 0)
                pr_warn("OPAL: sysfs file creation failed\n");
 }
diff --git a/arch/powerpc/platforms/powernv/opal.c b/arch/powerpc/platforms/powernv/opal.c
index 4e0da5a..0256d07 100644
--- a/arch/powerpc/platforms/powernv/opal.c
+++ b/arch/powerpc/platforms/powernv/opal.c
@@ -724,6 +724,9 @@ static int __init opal_init(void)
                of_node_put(leds);
        }

+       /* Initialise OPAL message log interface */
+       opal_msglog_init();
+
        /* Create "opal" kobject under /sys/firmware */
        rc = opal_sysfs_init();
        if (rc == 0) {
@@ -739,8 +742,8 @@ static int __init opal_init(void)
                opal_platform_dump_init();
                /* Setup system parameters interface */
                opal_sys_param_init();
-               /* Setup message log interface. */
-               opal_msglog_init();
+               /* Setup message log sysfs interface. */
+               opal_msglog_sysfs_init();
        }

        /* Initialize platform devices: IPMI backend, PRD & flash interface */
--
Andrew Donnellan              Software Engineer, OzLabs
andrew.donnellan@au1.ibm.com  Australia Development Lab, Canberra
+61 2 6201 8874 (work)        IBM Australia Limited

Re: [V2,1/2] powerpc/powernv: new function to access OPAL msglog

From: Michael Ellerman <mpe@ellerman.id.au>
Date: 2016-02-17 12:41:26

On Tue, 2016-09-02 at 07:17:48 UTC, Andrew Donnellan wrote:
Currently, the OPAL msglog/console buffer is exposed as a sysfs file, with
the sysfs read handler responsible for retrieving the log from the OPAL
buffer. We'd like to be able to use it in xmon as well.

Refactor the OPAL msglog code to create a new function, opal_msglog_copy(),
that copies to an arbitrary buffer. Separate the initialisation code into
generic memcons init and sysfs file creation.

Signed-off-by: Andrew Donnellan <redacted>
Applied to powerpc next, thanks.

https://git.kernel.org/powerpc/c/9b4fffa14906fce7aabf1f032d


I see you've posted a v3 since I merged this, please send an incremental patch
with the changes.

cheers

Re: [V2,2/2] powerpc/xmon: add command to dump OPAL msglog

From: Michael Ellerman <mpe@ellerman.id.au>
Date: 2016-02-17 12:41:27

On Tue, 2016-09-02 at 07:17:49 UTC, Andrew Donnellan wrote:
Add the 'do' command to dump the OPAL msglog in xmon.

Signed-off-by: Andrew Donnellan <redacted>
Applied to powerpc next, thanks.

https://git.kernel.org/powerpc/c/fde93a0f774f510bfaabccd5ba

cheers

Re: [V2,1/2] powerpc/powernv: new function to access OPAL msglog

From: Andrew Donnellan <hidden>
Date: 2016-02-18 01:18:06

On 17/02/16 23:41, Michael Ellerman wrote:
I see you've posted a v3 since I merged this, please send an incremental patch
with the changes.
http://patchwork.ozlabs.org/patch/584416/

-- 
Andrew Donnellan              Software Engineer, OzLabs
andrew.donnellan@au1.ibm.com  Australia Development Lab, Canberra
+61 2 6201 8874 (work)        IBM Australia Limited
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help