@@ -227,7 +227,9 @@
#define OPAL_SECVAR_ENQUEUE_UPDATE 178
#define OPAL_PHB_SET_OPTION 179
#define OPAL_PHB_GET_OPTION 180
-#define OPAL_LAST 180
+#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 */
new file mode 100644
@@ -0,0 +1,26 @@
+// SPDX-License-Identifier: Apache-2.0
+/* Copyright 2020 IBM Corp. */
+
+#ifndef __OPAL_DEBUG_H
+#define __OPAL_DEBUG_H
+
+struct opal_debug;
+
+struct opal_debug_ops {
+ const char *compat;
+ int (*read)(struct opal_debug *d, void *buf, uint64_t size);
+ int (*write)(struct opal_debug *d, void *buf, uint64_t size);
+};
+
+struct opal_debug {
+ const char *name;
+ void *private;
+ struct dt_node *node;
+ const struct opal_debug_ops *ops;
+};
+
+
+extern struct opal_debug *opal_debug_create(const char *name,
+ const struct opal_debug_ops *ops, void* private);
+
+#endif
new file mode 100644
@@ -0,0 +1,85 @@
+// SPDX-License-Identifier: Apache-2.0
+/* Copyright 2020 IBM Corp. */
+
+#define pr_fmt(fmt) "DEBUG: " fmt
+
+#include <cpu.h>
+#include <opal.h>
+#include <opal-debug.h>
+
+#define OPAL_DEBUG_MAX 100
+
+static struct dt_node *opal_debug_node;
+static int opal_debug_index;
+static struct opal_debug opal_debug_handlers[OPAL_DEBUG_MAX];
+
+extern struct opal_debug *opal_debug_create(const char *name,
+ const struct opal_debug_ops *ops, void* private)
+{
+ const char *compat = ops->compat ? ops->compat : "ibm,opal-debug";
+ struct opal_debug *d;
+
+ if (opal_debug_index == OPAL_DEBUG_MAX) {
+ prlog(PR_ERR, "Maximum number of handlers reached: %d\n",
+ OPAL_DEBUG_MAX);
+ return NULL;
+ }
+
+ d = &opal_debug_handlers[opal_debug_index];
+ d->name = name;
+ d->private = private;
+ d->ops = ops;
+
+ if (!opal_debug_node) {
+ opal_debug_node = dt_new_check(opal_node, "debug");
+ dt_add_property_cells(opal_debug_node, "#address-cells", 0);
+ dt_add_property_cells(opal_debug_node, "#size-cells", 0);
+ }
+
+ d->node = dt_new_addr(opal_debug_node, "debug", opal_debug_index);
+ dt_add_property_cells(d->node, "reg", opal_debug_index);
+ dt_add_property_string(d->node, "compatible", compat);
+ dt_add_property_string(d->node, "label", d->name);
+
+ opal_debug_index++;
+
+ return d;
+}
+
+static int64_t opal_debug_read(uint64_t id, uint64_t buf, uint64_t size)
+{
+ struct opal_debug *d;
+
+ if (id >= opal_debug_index)
+ return OPAL_PARAMETER;
+
+ d = &opal_debug_handlers[id];
+
+ if (!opal_addr_valid((void *)buf) || !size)
+ return OPAL_PARAMETER;
+
+ if (!d->ops->read)
+ return OPAL_INTERNAL_ERROR;
+
+ return d->ops->read(d, (void *)buf, size);
+}
+opal_call(OPAL_DEBUG_READ, opal_debug_read, 3);
+
+static int64_t opal_debug_write(uint64_t id, uint64_t buf, uint64_t size)
+{
+ struct opal_debug *d;
+
+ if (id >= opal_debug_index)
+ return OPAL_PARAMETER;
+
+ d = &opal_debug_handlers[id];
+
+ if (!opal_addr_valid((void *)buf) || !size)
+ return OPAL_PARAMETER;
+
+ if (!d->ops->write)
+ return OPAL_INTERNAL_ERROR;
+
+ return d->ops->write(d, (void *)buf, size);
+}
+opal_call(OPAL_DEBUG_WRITE, opal_debug_write, 3);
@@ -13,6 +13,7 @@ CORE_OBJS += timer.o i2c.o rtc.o flash.o sensor.o ipmi-opal.o
CORE_OBJS += flash-subpartition.o bitmap.o buddy.o pci-quirk.o powercap.o psr.o
CORE_OBJS += pci-dt-slot.o direct-controls.o cpufeatures.o
CORE_OBJS += flash-firmware-versions.o opal-dump.o
+CORE_OBJS += opal-debug.o
ifeq ($(SKIBOOT_GCOV),1)
CORE_OBJS += gcov-profiling.o
This is a very simplistic framework adding a read/write interface to opal drivers. Drivers should define a set of 'opal_debug' handlers, each with custom read/write operations. The device tree is then populated with nodes such as : debug@0 { ibm,chip-id = <0x00>; label = "xive-ivt"; compatible = "ibm,opal-debug"; reg = <0x00>; phandle = <0x805e>; }; which can be freely extended by the driver if needed. The Linux driver can choose to expose the contents of each 'opal_debug' handler through debugfs using the OPAL_DEBUG_READ call. It is relatively easy to implement a simple command interface with the OPAL_DEBUG_WRITE call, to set some values or reset some counters. Signed-off-by: Cédric Le Goater <clg@kaod.org> --- include/opal-api.h | 4 ++- include/opal-debug.h | 26 ++++++++++++++ core/opal-debug.c | 85 ++++++++++++++++++++++++++++++++++++++++++++ core/Makefile.inc | 1 + 4 files changed, 115 insertions(+), 1 deletion(-) create mode 100644 include/opal-debug.h create mode 100644 core/opal-debug.c