[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", ®)) {
+ 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