diff mbox series

[1/4] core: Add debugfs framework

Message ID 20201105161542.670165-2-clg@kaod.org
State Superseded
Headers show
Series OPAL debugfs calls | expand

Checks

Context Check Description
snowpatch_ozlabs/apply_patch success Successfully applied on branch master (89a32b4930be829f37e6967354a759e38048d01f)
snowpatch_ozlabs/snowpatch_job_snowpatch-skiboot success Test snowpatch/job/snowpatch-skiboot on branch master
snowpatch_ozlabs/snowpatch_job_snowpatch-skiboot-dco success Signed-off-by present

Commit Message

Cédric Le Goater Nov. 5, 2020, 4:15 p.m. UTC
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 | 27 ++++++++++++
 core/opal-debug.c    | 97 ++++++++++++++++++++++++++++++++++++++++++++
 core/Makefile.inc    |  1 +
 4 files changed, 128 insertions(+), 1 deletion(-)
 create mode 100644 include/opal-debug.h
 create mode 100644 core/opal-debug.c

Comments

Frederic Barrat Nov. 24, 2020, 9:56 a.m. UTC | #1
On 05/11/2020 17:15, Cédric Le Goater wrote:
> 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 | 27 ++++++++++++
>   core/opal-debug.c    | 97 ++++++++++++++++++++++++++++++++++++++++++++
>   core/Makefile.inc    |  1 +
>   4 files changed, 128 insertions(+), 1 deletion(-)
>   create mode 100644 include/opal-debug.h
>   create mode 100644 core/opal-debug.c
> 
> diff --git a/include/opal-api.h b/include/opal-api.h
> index e90cab1e9f65..03c414946651 100644
> --- a/include/opal-api.h
> +++ b/include/opal-api.h
> @@ -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 */
> diff --git a/include/opal-debug.h b/include/opal-debug.h
> new file mode 100644
> index 000000000000..fc8e3980f8a6
> --- /dev/null
> +++ b/include/opal-debug.h
> @@ -0,0 +1,27 @@
> +// 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 {
> +	struct list_node link;
> +	uint64_t id;
> +	struct dt_node *node;
> +	const char *name;
> +	void *private;
> +	const struct opal_debug_ops *ops;
> +};
> +
> +struct opal_debug *opal_debug_create(const char *name, struct dt_node *node,
> +			     void* private, const struct opal_debug_ops *ops);
> +
> +#endif
> diff --git a/core/opal-debug.c b/core/opal-debug.c
> new file mode 100644
> index 000000000000..a9ed2552e908
> --- /dev/null
> +++ b/core/opal-debug.c
> @@ -0,0 +1,97 @@
> +// 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>
> +
> +static LIST_HEAD(opal_debug_handlers);
> +static uint64_t opal_debug_index;
> +
> +/* This would need some locking */
> +struct opal_debug *opal_debug_create(const char *name, struct dt_node *node,
> +				     void* private, const struct opal_debug_ops *ops)
> +{
> +	const char *compat = ops->compat ? ops->compat : "ibm,opal-debug";
> +	struct opal_debug *d;
> +
> +	d = zalloc(sizeof(*d));
> +	if (!d) {
> +		prlog(PR_ERR, "Failed to allocate debug handler!\n");
> +		return NULL;
> +	}
> +
> +	d->id = opal_debug_index;
> +	d->name = name;


Duplicating the name would be safer and avoid making assumptions on the 
caller.

  Fred


> +	d->private = private;
> +	d->ops = ops;
> +
> +	d->node = dt_new_addr(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);
> +
> +	list_add_tail(&opal_debug_handlers, &d->link);
> +
> +	opal_debug_index++;
> +
> +	return d;
> +}
> +
> +static struct opal_debug *opal_debug_find(uint64_t id)
> +{
> +	struct opal_debug *d;
> +
> +	list_for_each(&opal_debug_handlers, d, link) {
> +		if (d->id == id)
> +			return d;
> +	}
> +	return NULL;
> +}
> +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;
> +
> +	if (!opal_addr_valid((void *)buf) || !size)
> +		return OPAL_PARAMETER;
> +
> +	d = opal_debug_find(id);
> +	if (!d) {
> +		prlog(PR_ERR, "No debug handler %lld!\n", id);
> +		return OPAL_INTERNAL_ERROR;
> +	}
> +
> +	if (!d->ops->read)
> +		return OPAL_UNSUPPORTED;
> +
> +	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;
> +
> +	if (!opal_addr_valid((void *)buf) || !size)
> +		return OPAL_PARAMETER;
> +
> +	d = opal_debug_find(id);
> +	if (!d) {
> +		prlog(PR_ERR, "No debug handler %lld!\n", id);
> +		return OPAL_INTERNAL_ERROR;
> +	}
> +
> +	if (!d->ops->write)
> +		return OPAL_UNSUPPORTED;
> +
> +	return d->ops->write(d, (void *)buf, size);
> +}
> +opal_call(OPAL_DEBUG_WRITE, opal_debug_write, 3);
> diff --git a/core/Makefile.inc b/core/Makefile.inc
> index 829800e5b27f..ed7003ed7a7a 100644
> --- a/core/Makefile.inc
> +++ b/core/Makefile.inc
> @@ -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
>
diff mbox series

Patch

diff --git a/include/opal-api.h b/include/opal-api.h
index e90cab1e9f65..03c414946651 100644
--- a/include/opal-api.h
+++ b/include/opal-api.h
@@ -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 */
diff --git a/include/opal-debug.h b/include/opal-debug.h
new file mode 100644
index 000000000000..fc8e3980f8a6
--- /dev/null
+++ b/include/opal-debug.h
@@ -0,0 +1,27 @@ 
+// 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 {
+	struct list_node link;
+	uint64_t id;
+	struct dt_node *node;
+	const char *name;
+	void *private;
+	const struct opal_debug_ops *ops;
+};
+
+struct opal_debug *opal_debug_create(const char *name, struct dt_node *node,
+			     void* private, const struct opal_debug_ops *ops);
+
+#endif
diff --git a/core/opal-debug.c b/core/opal-debug.c
new file mode 100644
index 000000000000..a9ed2552e908
--- /dev/null
+++ b/core/opal-debug.c
@@ -0,0 +1,97 @@ 
+// 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>
+
+static LIST_HEAD(opal_debug_handlers);
+static uint64_t opal_debug_index;
+
+/* This would need some locking */
+struct opal_debug *opal_debug_create(const char *name, struct dt_node *node,
+				     void* private, const struct opal_debug_ops *ops)
+{
+	const char *compat = ops->compat ? ops->compat : "ibm,opal-debug";
+	struct opal_debug *d;
+
+	d = zalloc(sizeof(*d));
+	if (!d) {
+		prlog(PR_ERR, "Failed to allocate debug handler!\n");
+		return NULL;
+	}
+
+	d->id = opal_debug_index;
+	d->name = name;
+	d->private = private;
+	d->ops = ops;
+
+	d->node = dt_new_addr(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);
+
+	list_add_tail(&opal_debug_handlers, &d->link);
+
+	opal_debug_index++;
+
+	return d;
+}
+
+static struct opal_debug *opal_debug_find(uint64_t id)
+{
+	struct opal_debug *d;
+
+	list_for_each(&opal_debug_handlers, d, link) {
+		if (d->id == id)
+			return d;
+	}
+	return NULL;
+}
+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;
+
+	if (!opal_addr_valid((void *)buf) || !size)
+		return OPAL_PARAMETER;
+
+	d = opal_debug_find(id);
+	if (!d) {
+		prlog(PR_ERR, "No debug handler %lld!\n", id);
+		return OPAL_INTERNAL_ERROR;
+	}
+
+	if (!d->ops->read)
+		return OPAL_UNSUPPORTED;
+
+	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;
+
+	if (!opal_addr_valid((void *)buf) || !size)
+		return OPAL_PARAMETER;
+
+	d = opal_debug_find(id);
+	if (!d) {
+		prlog(PR_ERR, "No debug handler %lld!\n", id);
+		return OPAL_INTERNAL_ERROR;
+	}
+
+	if (!d->ops->write)
+		return OPAL_UNSUPPORTED;
+
+	return d->ops->write(d, (void *)buf, size);
+}
+opal_call(OPAL_DEBUG_WRITE, opal_debug_write, 3);
diff --git a/core/Makefile.inc b/core/Makefile.inc
index 829800e5b27f..ed7003ed7a7a 100644
--- a/core/Makefile.inc
+++ b/core/Makefile.inc
@@ -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