[Skiboot] [PATCH linux 1/4] powerpc/powernv: Add support for OPAL_DEBUG_READ/WRITE

Cédric Le Goater clg at kaod.org
Fri Nov 6 03:15:39 AEDT 2020


Signed-off-by: Cédric Le Goater <clg at kaod.org>
---
 arch/powerpc/include/asm/opal-api.h         |   4 +-
 arch/powerpc/include/asm/opal.h             |   5 +
 arch/powerpc/platforms/powernv/opal-call.c  |   2 +
 arch/powerpc/platforms/powernv/opal-debug.c | 109 ++++++++++++++++++++
 arch/powerpc/platforms/powernv/Makefile     |   1 +
 5 files changed, 120 insertions(+), 1 deletion(-)
 create mode 100644 arch/powerpc/platforms/powernv/opal-debug.c

diff --git a/arch/powerpc/include/asm/opal-api.h b/arch/powerpc/include/asm/opal-api.h
index 1dffa3cb16ba..1a4ac8d1d944 100644
--- a/arch/powerpc/include/asm/opal-api.h
+++ b/arch/powerpc/include/asm/opal-api.h
@@ -214,7 +214,9 @@
 #define OPAL_SECVAR_GET				176
 #define OPAL_SECVAR_GET_NEXT			177
 #define OPAL_SECVAR_ENQUEUE_UPDATE		178
-#define OPAL_LAST				178
+#define OPAL_DEBUG_READ				181
+#define OPAL_DEBUG_WRITE			182
+#define OPAL_LAST				182
 
 #define QUIESCE_HOLD			1 /* Spin all calls at entry */
 #define QUIESCE_REJECT			2 /* Fail all calls with OPAL_BUSY */
diff --git a/arch/powerpc/include/asm/opal.h b/arch/powerpc/include/asm/opal.h
index 9986ac34b8e2..c42400107a44 100644
--- a/arch/powerpc/include/asm/opal.h
+++ b/arch/powerpc/include/asm/opal.h
@@ -311,6 +311,8 @@ s64 opal_mpipl_query_tag(enum opal_mpipl_tags tag, u64 *addr);
 
 s64 opal_signal_system_reset(s32 cpu);
 s64 opal_quiesce(u64 shutdown_type, s32 cpu);
+int64_t opal_debug_read(uint64_t id, uint64_t buf, uint64_t size);
+int64_t opal_debug_write(uint64_t id, uint64_t buf, uint64_t size);
 
 /* Internal functions */
 extern int early_init_dt_scan_opal(unsigned long node, const char *uname,
@@ -400,6 +402,9 @@ void opal_powercap_init(void);
 void opal_psr_init(void);
 void opal_sensor_groups_init(void);
 
+struct dentry;
+int opal_debug_create(struct device_node *node, struct dentry *debug_dir);
+
 #endif /* __ASSEMBLY__ */
 
 #endif /* _ASM_POWERPC_OPAL_H */
diff --git a/arch/powerpc/platforms/powernv/opal-call.c b/arch/powerpc/platforms/powernv/opal-call.c
index 5cd0f52d258f..c7e109220956 100644
--- a/arch/powerpc/platforms/powernv/opal-call.c
+++ b/arch/powerpc/platforms/powernv/opal-call.c
@@ -293,3 +293,5 @@ OPAL_CALL(opal_mpipl_query_tag,			OPAL_MPIPL_QUERY_TAG);
 OPAL_CALL(opal_secvar_get,			OPAL_SECVAR_GET);
 OPAL_CALL(opal_secvar_get_next,			OPAL_SECVAR_GET_NEXT);
 OPAL_CALL(opal_secvar_enqueue_update,		OPAL_SECVAR_ENQUEUE_UPDATE);
+OPAL_CALL(opal_debug_read,			OPAL_DEBUG_READ);
+OPAL_CALL(opal_debug_write,			OPAL_DEBUG_WRITE);
diff --git a/arch/powerpc/platforms/powernv/opal-debug.c b/arch/powerpc/platforms/powernv/opal-debug.c
new file mode 100644
index 000000000000..ce52517f0cb4
--- /dev/null
+++ b/arch/powerpc/platforms/powernv/opal-debug.c
@@ -0,0 +1,109 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * PowerNV OPAL debugfs interface
+ *
+ * Copyright 2020 IBM Corp.
+ */
+
+#define pr_fmt(fmt)     "opal-debug: " fmt
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_platform.h>
+
+#include <asm/errno.h>
+#include <asm/opal.h>
+#include <asm/debugfs.h>
+
+/*
+ * The snprintf implementation in OPAL does not return the number of
+ * bytes that would have been written if the buffer was large enough.
+ * Allocate a page to cover most cases.
+ */
+static int opal_debug_show(struct seq_file *m, void *p)
+{
+	u64 id = (u64) m->private;
+	int size = PAGE_SIZE;
+	char *buf;
+	int rc;
+
+	buf = kzalloc(size, GFP_KERNEL); /* TODO: make it global */
+	if (!buf)
+		return -ENOMEM;
+
+	rc = opal_debug_read(id, __pa(buf), size);
+	if (rc < 0) {
+		rc = opal_error_code(rc);
+	} else {
+		seq_puts(m, buf);
+		rc = 0;
+	}
+
+	kfree(buf);
+	return rc;
+}
+
+static int opal_debug_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, opal_debug_show, inode->i_private);
+}
+
+static ssize_t opal_debug_do_write(struct file *file, const char __user *user_buf,
+				   size_t count, loff_t *ppos)
+{
+	u64 id = (u64) file_inode(file)->i_private;
+	char buf[64] = { 0 }; /* Does it need a tunable ? */
+	const char *data;
+	size_t size;
+	int rc;
+
+	size = min(sizeof(buf) - 1, count);
+	if (copy_from_user(buf, user_buf, size))
+		return -EFAULT;
+	data = strim(buf);
+
+	rc = opal_debug_write(id, __pa(data), strlen(data) + 1);
+	if (rc < 0)
+		return opal_error_code(rc);
+
+	return count;
+}
+
+const struct file_operations opal_debug_ops = {
+	.open		= opal_debug_open,
+	.write		= opal_debug_do_write,
+	.read		= seq_read,
+	.llseek		= no_llseek,
+	.release	= single_release,
+};
+
+int opal_debug_create(struct device_node *node, struct dentry *debug_dir)
+{
+	u32 reg;
+	const char *name;
+	const char *label;
+	u32 chip_id;
+
+	if (of_property_read_u32(node, "reg", &reg)) {
+		pr_warn("'reg' property not found\n");
+		return -ENODEV;
+	}
+
+	if (of_property_read_string(node, "label", &label))
+		label = node->name;
+
+	if (!of_property_read_u32(node, "ibm,chip-id", &chip_id))
+		name = kasprintf(GFP_KERNEL, "%s-%x", label, chip_id);
+	else
+		name = kasprintf(GFP_KERNEL, "%s", label);
+
+	debugfs_create_file(name, 0400, debug_dir, (void *) (u64) reg,
+			    &opal_debug_ops);
+	kfree(name);
+	return 0;
+}
diff --git a/arch/powerpc/platforms/powernv/Makefile b/arch/powerpc/platforms/powernv/Makefile
index 2eb6ae150d1f..9cfd3942e0e8 100644
--- a/arch/powerpc/platforms/powernv/Makefile
+++ b/arch/powerpc/platforms/powernv/Makefile
@@ -5,6 +5,7 @@ obj-y			+= rng.o opal-elog.o opal-dump.o opal-sysparam.o opal-sensor.o
 obj-y			+= opal-msglog.o opal-hmi.o opal-power.o opal-irqchip.o
 obj-y			+= opal-kmsg.o opal-powercap.o opal-psr.o opal-sensor-groups.o
 obj-y			+= ultravisor.o
+obj-y			+= opal-debug.o
 
 obj-$(CONFIG_SMP)	+= smp.o subcore.o subcore-asm.o
 obj-$(CONFIG_FA_DUMP)	+= opal-fadump.o
-- 
2.26.2



More information about the Skiboot mailing list