From patchwork Thu Dec 21 08:20:12 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Leo Yan X-Patchwork-Id: 122516 Delivered-To: patch@linaro.org Received: by 10.140.22.227 with SMTP id 90csp580459qgn; Thu, 21 Dec 2017 00:21:05 -0800 (PST) X-Google-Smtp-Source: ACJfBouxOHXpT6pybEdQAgTNq4TbhOVMzBfrC9WhpdKTcEE/iH0+vCnRncIRQS+e24qNlXxIXdK/ X-Received: by 10.84.217.14 with SMTP id o14mr9991180pli.169.1513844464762; Thu, 21 Dec 2017 00:21:04 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1513844464; cv=none; d=google.com; s=arc-20160816; b=T7GjDlFMb6LPNgnrvte3plCHhhqV5GObQFN3dUis3LuVJ2OyU3VJxtUoSm6ygtVOtF EvLKETahfephwyrL7WyQsBdgEKbEGK2I1kKwnz4B4q0lLwiTcsyLPdUgDRnwiOGwKvWZ KNjO2zx+R5ugFVze8fDoFFjQ0TvNyXfqHa+WxEQPfM7J44TcBp/xBCpbaSJtDa9W92Jf Vh0QHep/4sPYgqxV9RW2E46ZLdVZBGgfF+F/PgZg1KGVo0Ur/E1YMyjXyKSlQzTB5b2N PmvznmKWl7y8RqnqZoNtQMXljCSOa3klYU+MqAe+ZreDBsGtEuK2PV5e2UcnYLVXtlyS ioPA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:message-id:date :subject:cc:to:from:dkim-signature:arc-authentication-results; bh=9JYwaGUC0An/axs8tCXKpUNaJOc1/MZD9kXVLyjpgqA=; b=XKEN+cXz/w4nsQb+rzvXXCTBHZKpr0pTyJn/LKMo+YluHIsUbrwYr733yZdSUqU0Nw 8OVdb/VZssA9TMNvQKuLFFlLhldAeNsAJC51YwcewEilY6T2w4FvlpZLtJw2rCiNFoB0 aHtRW9Rt6nKrGCkjGdtGjyYa8M8tTQLF3dNgpSuADFjXR6hBPiPtWQaxwsalnZAUco7y kxnp+7KCdj/7qzhR64uRBBy3m59WOCDAnUciBJcfuKyr9hXS38FLSjBFq37G+tqK9YRk 6gjCg8U3uViCkFY70W1eyd70RYAC/0Zt43a7PMrK2wNn/Yzn35Q8UbwKJKiNjSYG5y75 mSvw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=hSCIzdtB; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id 8si14568944pfo.144.2017.12.21.00.21.04; Thu, 21 Dec 2017 00:21:04 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=hSCIzdtB; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751842AbdLUIVB (ORCPT + 28 others); Thu, 21 Dec 2017 03:21:01 -0500 Received: from mail-pl0-f65.google.com ([209.85.160.65]:44571 "EHLO mail-pl0-f65.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751685AbdLUIUx (ORCPT ); Thu, 21 Dec 2017 03:20:53 -0500 Received: by mail-pl0-f65.google.com with SMTP id n13so10586560plp.11 for ; Thu, 21 Dec 2017 00:20:53 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=9JYwaGUC0An/axs8tCXKpUNaJOc1/MZD9kXVLyjpgqA=; b=hSCIzdtBO5d5Vj++O8/dGOwC+Ym2KnFrRBn8JmNnVjFBFSz9TjHSOdMyhhtlZCehW/ wgYINh4TG4M1cqJjU7fBrZn4LZBCW7KVf6yYK351pDSds9m7QNXb+XBo+MJvilGjGH3i lR9zW81CO20ezPL8kyQkTcQcuyTVOxSBw/6BA= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=9JYwaGUC0An/axs8tCXKpUNaJOc1/MZD9kXVLyjpgqA=; b=Wyf/GEYG+lRf93DuSmY4L25IKMSXYxJTd94HQ3Z4BygnxnLZtjOmOkPMn101LUo0fC 6fyRND6WmgH2ziG5g+1hTfqNgFXvs2xzIppuMUBPPuTVRNBH8VLm0J8tW32aSh4Sk8yh ZdG1HBmR3cm+DGuiY66KZSSOlX0deNgHn6/Ael1JKM3pzb4xNEWWfoWMo4sZZZfwd4XR 7ZSoQOCvJoPkpD/0HAIoYboZ+7bQzFNn/80kG/fTeCJ/VEnht3ZN0Y6qkntVkmtZOoFE qeuJylC4r+zJ8ctvcMsUJyi0C1MRxUHcuxulnFA+chQyJkVatgRvggy8TE0+R+xnWdIm X5Tw== X-Gm-Message-State: AKGB3mL9BQG8oxlmMJD7DrylH6+U7ZpSy8lJByJkn/+WwLPNcH0teFbe cq0oKR91guLaIAahlRdlNezgAw== X-Received: by 10.84.218.193 with SMTP id g1mr9779075plm.63.1513844452764; Thu, 21 Dec 2017 00:20:52 -0800 (PST) Received: from localhost.localdomain (li159-223.members.linode.com. [173.230.149.223]) by smtp.gmail.com with ESMTPSA id r86sm43699720pfk.114.2017.12.21.00.20.48 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Thu, 21 Dec 2017 00:20:51 -0800 (PST) From: Leo Yan To: Jonathan Corbet , Mathieu Poirier , Greg Kroah-Hartman , Will Deacon , linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, coresight@lists.linaro.org Cc: Leo Yan Subject: [PATCH v3 3/6] coresight: Support panic kdump functionality Date: Thu, 21 Dec 2017 16:20:12 +0800 Message-Id: <1513844415-11427-4-git-send-email-leo.yan@linaro.org> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1513844415-11427-1-git-send-email-leo.yan@linaro.org> References: <1513844415-11427-1-git-send-email-leo.yan@linaro.org> Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org 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 save DDR content and uses "crash" tool to extract coresight dumping 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_kdump_add|coresight_kdump_del} as helper functions so any coresight device can add itself into dump list or delete as needed. This driver provides helper function coresight_kdump_update() to update the dump buffer base address and buffer size. This function can be used by coresight driver, e.g. it can be used to save ETM meta data info at runtime and these info can be prepared pre panic happening. When kernel panic happens, the notifier iterates dump list and calls callback function to dump device specific info. The panic dump is mainly used to dump trace data so we can get to know the execution flow before the panic happens. Signed-off-by: Leo Yan --- drivers/hwtracing/coresight/Kconfig | 9 ++ drivers/hwtracing/coresight/Makefile | 1 + .../hwtracing/coresight/coresight-panic-kdump.c | 154 +++++++++++++++++++++ drivers/hwtracing/coresight/coresight-priv.h | 13 ++ include/linux/coresight.h | 7 + 5 files changed, 184 insertions(+) create mode 100644 drivers/hwtracing/coresight/coresight-panic-kdump.c -- 2.7.4 diff --git a/drivers/hwtracing/coresight/Kconfig b/drivers/hwtracing/coresight/Kconfig index ef9cb3c..4812529 100644 --- a/drivers/hwtracing/coresight/Kconfig +++ b/drivers/hwtracing/coresight/Kconfig @@ -103,4 +103,13 @@ config CORESIGHT_CPU_DEBUG properly, please refer Documentation/trace/coresight-cpu-debug.txt for detailed description and the example for usage. +config CORESIGHT_PANIC_KDUMP + bool "CoreSight Panic Kdump driver" + depends on ARM || ARM64 + help + This driver provides panic kdump 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 61db9dd..946fe19 100644 --- a/drivers/hwtracing/coresight/Makefile +++ b/drivers/hwtracing/coresight/Makefile @@ -18,3 +18,4 @@ obj-$(CONFIG_CORESIGHT_SOURCE_ETM4X) += coresight-etm4x.o \ obj-$(CONFIG_CORESIGHT_DYNAMIC_REPLICATOR) += coresight-dynamic-replicator.o obj-$(CONFIG_CORESIGHT_STM) += coresight-stm.o obj-$(CONFIG_CORESIGHT_CPU_DEBUG) += coresight-cpu-debug.o +obj-$(CONFIG_CORESIGHT_PANIC_KDUMP) += coresight-panic-kdump.o diff --git a/drivers/hwtracing/coresight/coresight-panic-kdump.c b/drivers/hwtracing/coresight/coresight-panic-kdump.c new file mode 100644 index 0000000..c21d20b --- /dev/null +++ b/drivers/hwtracing/coresight/coresight-panic-kdump.c @@ -0,0 +1,154 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (c) 2017 Linaro Limited. +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "coresight-priv.h" + +typedef void (*coresight_cb_t)(void *data); + +/** + * struct coresight_kdump_node - Node information for dump + * @cpu: The cpu this node is affined to. + * @csdev: Handler for coresight device. + * @buf: Pointer for dump buffer. + * @buf_size: Length of dump buffer. + * @list: Hook to the list. + */ +struct coresight_kdump_node { + int cpu; + struct coresight_device *csdev; + char *buf; + unsigned int buf_size; + struct list_head list; +}; + +static DEFINE_SPINLOCK(coresight_kdump_lock); +static LIST_HEAD(coresight_kdump_list); +static struct notifier_block coresight_kdump_nb; + +int coresight_kdump_update(struct coresight_device *csdev, char *buf, + unsigned int buf_size) +{ + struct coresight_kdump_node *node = csdev->dump_node; + + if (!node) { + dev_err(&csdev->dev, "Failed to update dump node.\n"); + return -EINVAL; + } + + node->buf = buf; + node->buf_size = buf_size; + return 0; +} + +int coresight_kdump_add(struct coresight_device *csdev, int cpu) +{ + struct coresight_kdump_node *node; + unsigned long flags; + + node = kzalloc(sizeof(*node), GFP_KERNEL); + if (!node) + return -ENOMEM; + + csdev->dump_node = (void *)node; + node->cpu = cpu; + node->csdev = csdev; + + spin_lock_irqsave(&coresight_kdump_lock, flags); + list_add_tail(&node->list, &coresight_kdump_list); + spin_unlock_irqrestore(&coresight_kdump_lock, flags); + return 0; +} + +void coresight_kdump_del(struct coresight_device *csdev) +{ + struct coresight_kdump_node *node, *next; + unsigned long flags; + + spin_lock_irqsave(&coresight_kdump_lock, flags); + list_for_each_entry_safe(node, next, &coresight_kdump_list, list) { + if (node->csdev == csdev) { + list_del(&node->list); + kfree(node); + break; + } + } + spin_unlock_irqrestore(&coresight_kdump_lock, flags); +} + +static coresight_cb_t +coresight_kdump_get_cb(struct coresight_device *csdev) +{ + coresight_cb_t cb = NULL; + + switch (csdev->type) { + case CORESIGHT_DEV_TYPE_SINK: + case CORESIGHT_DEV_TYPE_LINKSINK: + cb = sink_ops(csdev)->panic_cb; + break; + case CORESIGHT_DEV_TYPE_SOURCE: + cb = source_ops(csdev)->panic_cb; + break; + case CORESIGHT_DEV_TYPE_LINK: + cb = link_ops(csdev)->panic_cb; + break; + default: + dev_info(&csdev->dev, "Unsupport panic dump\n"); + break; + } + + return cb; +} + +/** + * coresight_kdump_notify - Invoke panic dump callbacks, this is + * the main function to fulfill the panic dump. It distinguishs + * to two types: one is pre panic dump which the callback function + * handler is NULL and coresight drivers can use function + * coresight_kdump_update() to directly update dump buffer base + * address and buffer size, for this case this function does nothing + * and directly bail out; another case is for post panic dump so + * invoke callback on alive CPU. + * + * Returns: 0 on success. + */ +static int coresight_kdump_notify(struct notifier_block *nb, + unsigned long mode, void *_unused) +{ + struct coresight_kdump_node *node; + struct coresight_device *csdev; + coresight_cb_t cb; + unsigned long flags; + + spin_lock_irqsave(&coresight_kdump_lock, flags); + + list_for_each_entry(node, &coresight_kdump_list, list) { + csdev = node->csdev; + cb = coresight_kdump_get_cb(csdev); + if (cb) + cb(csdev); + } + + spin_unlock_irqrestore(&coresight_kdump_lock, flags); + return 0; +} + +static int __init coresight_kdump_init(void) +{ + int ret; + + coresight_kdump_nb.notifier_call = coresight_kdump_notify; + ret = atomic_notifier_chain_register(&panic_notifier_list, + &coresight_kdump_nb); + return ret; +} +late_initcall(coresight_kdump_init); diff --git a/drivers/hwtracing/coresight/coresight-priv.h b/drivers/hwtracing/coresight/coresight-priv.h index f1d0e21d..937750e 100644 --- a/drivers/hwtracing/coresight/coresight-priv.h +++ b/drivers/hwtracing/coresight/coresight-priv.h @@ -151,4 +151,17 @@ 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_KDUMP +extern int coresight_kdump_add(struct coresight_device *csdev, int cpu); +extern void coresight_kdump_del(struct coresight_device *csdev); +extern int coresight_kdump_update(struct coresight_device *csdev, + char *buf, unsigned int buf_size); +#else +static inline int +coresight_kdump_add(struct coresight_device *csdev, int cpu) { return 0; } +static inline void coresight_kdump_del(struct coresight_device *csdev) {} +static inline int coresight_kdump_update(struct coresight_device *csdev, + char *buf, unsigned int buf_size) { return 0; } +#endif + #endif diff --git a/include/linux/coresight.h b/include/linux/coresight.h index d950dad..43e40fa 100644 --- a/include/linux/coresight.h +++ b/include/linux/coresight.h @@ -171,6 +171,7 @@ struct coresight_device { bool orphan; bool enable; /* true only if configured as part of a path */ bool activated; /* true only if a sink is part of a path */ + void *dump_node; }; #define to_coresight_device(d) container_of(d, struct coresight_device, dev) @@ -189,6 +190,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: hook function for panic notifier. */ struct coresight_ops_sink { int (*enable)(struct coresight_device *csdev, u32 mode); @@ -205,6 +207,7 @@ struct coresight_ops_sink { void (*update_buffer)(struct coresight_device *csdev, struct perf_output_handle *handle, void *sink_config); + void (*panic_cb)(void *data); }; /** @@ -212,10 +215,12 @@ struct coresight_ops_sink { * Operations available for links. * @enable: enables flow between iport and oport. * @disable: disables flow between iport and oport. + * @panic_cb: hook function for panic notifier. */ struct coresight_ops_link { int (*enable)(struct coresight_device *csdev, int iport, int oport); void (*disable)(struct coresight_device *csdev, int iport, int oport); + void (*panic_cb)(void *data); }; /** @@ -227,6 +232,7 @@ struct coresight_ops_link { * to the HW. * @enable: enables tracing for a source. * @disable: disables tracing for a source. + * @panic_cb: hook function for panic notifier. */ struct coresight_ops_source { int (*cpu_id)(struct coresight_device *csdev); @@ -235,6 +241,7 @@ struct coresight_ops_source { struct perf_event *event, u32 mode); void (*disable)(struct coresight_device *csdev, struct perf_event *event); + void (*panic_cb)(void *data); }; struct coresight_ops {