[PATCH v1 1/4] coresight: support panic dump functionality
Mathieu Poirier
mathieu.poirier at linaro.org
Thu Jun 8 11:13:01 PDT 2017
On 3 June 2017 at 08:42, Leo Yan <leo.yan at linaro.org> wrote:
> After kernel panic happens, coresight has many useful info can be used
> for analysis. For example, the trace info from ETB RAM can be used to
> check the CPU execution flows before crash. So we can save the tracing
> data from sink devices, and rely on kdump to extract them from vmcore
> file.
>
> This patch is to add a simple framework to support panic dump
> functionality; it registers panic notifier, and provide the general APIs
> {coresight_add_panic_cb|coresight_del_panic_cb} as helper functions so
> any coresight device can add itself into dump list or delete as needed;
> usually these two functions can be used when a session is started or
> when it ends. When kernel panic happened, the panic notifier iterates
> dump list and calls every node for the device callback function to dump
> device specific info. Generally all the panic dump specific stuff are
> related to the sinks devices, so this initial version code it only
> supports sink devices.
>
> Signed-off-by: Leo Yan <leo.yan at linaro.org>
Hi Leo,
> ---
> drivers/hwtracing/coresight/Kconfig | 10 ++
> drivers/hwtracing/coresight/Makefile | 1 +
> drivers/hwtracing/coresight/coresight-panic-dump.c | 130 +++++++++++++++++++++
> drivers/hwtracing/coresight/coresight-priv.h | 10 ++
> include/linux/coresight.h | 2 +
> 5 files changed, 153 insertions(+)
> create mode 100644 drivers/hwtracing/coresight/coresight-panic-dump.c
>
> diff --git a/drivers/hwtracing/coresight/Kconfig b/drivers/hwtracing/coresight/Kconfig
> index 8d55d6d..8890023 100644
> --- a/drivers/hwtracing/coresight/Kconfig
> +++ b/drivers/hwtracing/coresight/Kconfig
> @@ -103,4 +103,14 @@ config CORESIGHT_CPU_DEBUG
> properly, please refer Documentation/trace/coresight-cpu-debug.txt
> for detailed description and the example for usage.
>
> +config CORESIGHT_PANIC_DUMP
> + bool "CoreSight Panic Dump driver"
> + depends on ARM || ARM64
> + depends on CORESIGHT_LINKS_AND_SINKS
> + help
> + This driver provides panic dump functionality for coresight
> + devices; when kernel panic happens, we can use callback functions
> + to save trace data to memory. Finally can rely on kdump to extract
> + out these trace data from kernel dump file.
This driver provides panic dump functionality for CoreSight
devices. When a kernel panic happen a device supplied callback function
is used to save trace data to memory. From there we rely on kdump to extract
the trace data from kernel dump file.
> +
> endif
> diff --git a/drivers/hwtracing/coresight/Makefile b/drivers/hwtracing/coresight/Makefile
> index 433d590..0ac3216 100644
> --- a/drivers/hwtracing/coresight/Makefile
> +++ b/drivers/hwtracing/coresight/Makefile
> @@ -17,3 +17,4 @@ obj-$(CONFIG_CORESIGHT_SOURCE_ETM4X) += coresight-etm4x.o \
> obj-$(CONFIG_CORESIGHT_QCOM_REPLICATOR) += coresight-replicator-qcom.o
> obj-$(CONFIG_CORESIGHT_STM) += coresight-stm.o
> obj-$(CONFIG_CORESIGHT_CPU_DEBUG) += coresight-cpu-debug.o
> +obj-$(CONFIG_CORESIGHT_PANIC_DUMP) += coresight-panic-dump.o
> diff --git a/drivers/hwtracing/coresight/coresight-panic-dump.c b/drivers/hwtracing/coresight/coresight-panic-dump.c
> new file mode 100644
> index 0000000..23869ff
> --- /dev/null
> +++ b/drivers/hwtracing/coresight/coresight-panic-dump.c
> @@ -0,0 +1,130 @@
> +/*
> + * Copyright(C) 2017 Linaro Limited. All rights reserved.
> + * Author: Leo Yan <leo.yan at linaro.org>
> + *
> + * This program is free software; you can redistribute it and/or modify it
> + * under the terms of the GNU General Public License version 2 as published by
> + * the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful, but WITHOUT
> + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
> + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
> + * more details.
> + *
> + * You should have received a copy of the GNU General Public License along with
> + * this program. If not, see <http://www.gnu.org/licenses/>.
> + */
> +
> +#include <linux/coresight.h>
> +#include <linux/coresight-pmu.h>
> +#include <linux/cpumask.h>
> +#include <linux/device.h>
> +#include <linux/list.h>
> +#include <linux/mm.h>
> +#include <linux/init.h>
Alphabetical order if possible.
> +#include <linux/perf_event.h>
> +#include <linux/slab.h>
> +#include <linux/types.h>
> +#include <linux/workqueue.h>
> +
> +static DEFINE_MUTEX(coresight_panic_lock);
> +static struct list_head coresight_panic_list;
> +static struct notifier_block coresight_panic_nb;
> +
> +struct coresight_panic_node {
> + char *name;
There is no need for another copy of the device name as it is already
available in csdev->dev.
> + struct coresight_device *csdev;
> + struct list_head list;
> +};
> +
> +static int coresight_panic_notify(struct notifier_block *nb,
> + unsigned long mode, void *_unused)
> +{
> + int ret = 0, err;
> + struct coresight_panic_node *node;
> + struct coresight_device *csdev;
> + u32 type;
> +
> + mutex_lock(&coresight_panic_lock);
> +
> + list_for_each_entry(node, &coresight_panic_list, list) {
> + csdev = node->csdev;
> + type = csdev->type;
> +
> + dev_info(&csdev->dev, "invoke panic dump...\n");
> +
> + switch (type) {
> + case CORESIGHT_DEV_TYPE_SINK:
> + case CORESIGHT_DEV_TYPE_LINKSINK:
> + err = sink_ops(csdev)->panic_cb(csdev);
> + if (err)
> + ret = err;
> + break;
> + default:
> + dev_err(&csdev->dev,
> + "Unsupported type for panic dump\n");
> + break;
> + }
> + }
> +
> + mutex_unlock(&coresight_panic_lock);
> + return ret;
> +}
This should be called in coresight_register() if a csdev has a panic
callback. I'm backing Suzuki's suggestion of executing the callbacks
only if a device has been enabled. That way the only thing CS devices
have to do is provide a panic_cb function.
> +
> +int coresight_add_panic_cb(struct coresight_device *csdev)
> +{
> + struct coresight_panic_node *node;
> +
> + node = kzalloc(sizeof(struct coresight_panic_node), GFP_KERNEL);
The trend in the kernel is so use "sizeof(*node)"
> + if (!node)
> + return -ENOMEM;
> +
> + node->name = kstrndup(dev_name(&csdev->dev), 16, GFP_KERNEL);
> + if (!node->name) {
> + kfree(node);
> + return -ENOMEM;
> + }
> + node->csdev = csdev;
> +
> + mutex_lock(&coresight_panic_lock);
> + list_add_tail(&node->list, &coresight_panic_list);
> + mutex_unlock(&coresight_panic_lock);
> +
> + return 0;
> +}
Same as above.
> +
> +void coresight_del_panic_cb(struct coresight_device *csdev)
> +{
> + struct coresight_panic_node *node;
> +
> + mutex_lock(&coresight_panic_lock);
> +
> + list_for_each_entry(node, &coresight_panic_list, list) {
> + if (node->csdev == csdev) {
> + list_del(&node->list);
> + kfree(node->name);
> + kfree(node);
> + mutex_unlock(&coresight_panic_lock);
> + return;
> + }
> + }
> +
> + dev_err(&csdev->dev, "Failed to find panic node.\n");
> + mutex_unlock(&coresight_panic_lock);
> +}
> +
> +static int __init coresight_panic_init(void)
> +{
This function should go in function coresight_init().
> + int ret;
> +
> + INIT_LIST_HEAD(&coresight_panic_list);
> +
> + coresight_panic_nb.notifier_call = coresight_panic_notify;
> + ret = atomic_notifier_chain_register(&panic_notifier_list,
> + &coresight_panic_nb);
> + if (ret)
> + return ret;
> +
> + return 0;
> +}
> +subsys_initcall(coresight_panic_init);
> diff --git a/drivers/hwtracing/coresight/coresight-priv.h b/drivers/hwtracing/coresight/coresight-priv.h
> index 5f662d8..e6ed3e9 100644
> --- a/drivers/hwtracing/coresight/coresight-priv.h
> +++ b/drivers/hwtracing/coresight/coresight-priv.h
> @@ -122,4 +122,14 @@ static inline int etm_readl_cp14(u32 off, unsigned int *val) { return 0; }
> static inline int etm_writel_cp14(u32 off, u32 val) { return 0; }
> #endif
>
> +#ifdef CONFIG_CORESIGHT_PANIC_DUMP
> +extern int coresight_add_panic_cb(struct coresight_device *csdev);
> +extern void coresight_del_panic_cb(struct coresight_device *csdev);
> +#else
> +static inline int coresight_add_panic_cb(struct coresight_device *csdev)
> +{ return 0; }
> +static inline void coresight_del_panic_cb(struct coresight_device *csdev)
> +{ return; }
> +#endif
> +
> #endif
> diff --git a/include/linux/coresight.h b/include/linux/coresight.h
> index d950dad..31fcaeb 100644
> --- a/include/linux/coresight.h
> +++ b/include/linux/coresight.h
> @@ -189,6 +189,7 @@ struct coresight_device {
> * @set_buffer: initialises buffer mechanic before a trace session.
> * @reset_buffer: finalises buffer mechanic after a trace session.
> * @update_buffer: update buffer pointers after a trace session.
> + * @panic_cb: hooks callback function for panic notifier.
"hook function for panic notifier"
Thanks,
Mathieu
> */
> struct coresight_ops_sink {
> int (*enable)(struct coresight_device *csdev, u32 mode);
> @@ -205,6 +206,7 @@ struct coresight_ops_sink {
> void (*update_buffer)(struct coresight_device *csdev,
> struct perf_output_handle *handle,
> void *sink_config);
> + int (*panic_cb)(struct coresight_device *csdev);
> };
>
> /**
> --
> 2.7.4
>
More information about the linux-arm-kernel
mailing list