This patch set is to explore Coresight tracing data for postmortem debugging. When kernel panic happens, the Coresight panic kdump can help to save on-chip tracing data and tracer metadata into DRAM, later relies on kdump and crash/perf tools to recovery tracing data for "offline" analysis.
Comparing the patch series v4 and previous series, this patch series has heavily refactored the implementation after investigated Intel PT for kdump support. Intel PT calls one function for emergency stopping trace when kernel panic occurs, in the function it reuses perf operation to dump trace data into ring buffer, later crash tool extracts trace data from perf ring buffer.
This patch series takes Intel PT as an example to use the same way to stop ETM trace with perf mode. So far the related work is primarily to focus on to support Coresight kdump with perf mode and we can add support SysFS mode if later there have more clear requirement.
Comparing to previous series, this patch series also simplifies the handling for tracer metadata. The old series introduced extra data structure and two double link lists to maintain CoreSignt kdump components; in the old implementation, one list was used to track tracer metadata and another list was used to trace dump buffers, later these two lists can be used to retrieve metadata and trace data buffer from vmcore file. In this patch series it directly relies on CoreSight driver global variables to retrieve related info, e.g. for perf mode we can rely on per CPU pointer 'ctx_handle' to get perf ring buffer related info and 'csdev_src' is for per CPU tracer device structure for metadata.
The crash extension program now has been enhanced to parse the data structures in the kernel and use them to extract metadata and dump trace data [1]; the crash extension program is updated to build with OpenCSD decoder so this can simplize the decoding process, rather than before needs to use perf to help decoding trace data.
This patch series has been verified on 96boards DB410c with below steps, the 'long_loop' is a pretty simple program to only execute big number loops so can generate big amount number of branch instructions.
Enable trace on the target board:
$ perf record -e cs_etm/@825000.etf/ --per-thread ./long_loop & $ sleep 3 $ echo c > /proc/sysrq-trigger
Use crash tool for post analysis:
$ crash vmcore vmlinux crash> extend arm_cs_dump.so crash> arm_cs_dump -o out
[1] https://git.linaro.org/people/leo.yan/crash.git/log/?h=arm_cs_dump_etm_perf
Changes from v4: * Support for CoreSight ETM with perf mode; * Add API for crash stop; * Simplized implementation with removing kdump dedicated data structures and functions;
Changes from v3: * Following Mathieu suggestion, reworked the panic kdump framework, used kdump array to maintain source and sink device handlers; * According to Mathieu suggestion, optimized panic notifier to firstly dump panic CPU tracing data and then dump other CPUs tracing data; * Refined doc to reflect these implementation changes; * Changed ETMv4 driver to add source device handler at probe phase; * Refactored crash extension program to reflect kernel changes.
Changes from v2: * Add the two patches for documentation. * Following Mathieu suggestion, reworked the panic kdump framework, removed the useless flag "PRE_PANIC". * According to comment, changed to add and delete kdump node operations in sink enable/disable functions; * According to Mathieu suggestion, handle kdump node addition/deletion/updating separately for sysFS interface and perf method.
Changes from v1: * Add support to dump ETMv4 meta data. * Wrote 'crash' extension csdump.so so rely on it to generate 'perf' format compatible file. * Refactored panic dump driver to support pre & post panic dump.
Changes from RFC: * Follow Mathieu's suggestion, use general framework to support dump functionality. * Changed to use perf to analyse trace data.
Leo Yan (6): doc: Add Coresight documentation directory doc: Add documentation for Coresight panic kdump coresight: etm4x: Save ID values in config structure coresight: tmc: Update latest value for page index and offset coresight: etm-perf: Add interface to stop etm trace arm64: smp: Stop CoreSight trace for kdump
.../trace/{ => coresight}/coresight-cpu-debug.txt | 0 .../trace/coresight/coresight-panic-kdump.txt | 99 ++++++++++++++++++++++ Documentation/trace/{ => coresight}/coresight.txt | 0 MAINTAINERS | 5 +- arch/arm64/kernel/smp.c | 5 ++ drivers/hwtracing/coresight/Kconfig | 10 +++ drivers/hwtracing/coresight/coresight-etm-perf.c | 10 +++ drivers/hwtracing/coresight/coresight-etm4x.c | 7 ++ drivers/hwtracing/coresight/coresight-etm4x.h | 8 ++ drivers/hwtracing/coresight/coresight-tmc-etf.c | 8 ++ include/linux/coresight.h | 6 ++ 11 files changed, 156 insertions(+), 2 deletions(-) rename Documentation/trace/{ => coresight}/coresight-cpu-debug.txt (100%) create mode 100644 Documentation/trace/coresight/coresight-panic-kdump.txt rename Documentation/trace/{ => coresight}/coresight.txt (100%)
For easy management and friendly adding more Coresight documentation, this commit creates a new directory: Documentation/trace/coresight.
This commit also moves Coresight related docs into the new directory and updates MAINTAINERS file to reflect docs movement.
Signed-off-by: Leo Yan leo.yan@linaro.org --- Documentation/trace/{ => coresight}/coresight-cpu-debug.txt | 0 Documentation/trace/{ => coresight}/coresight.txt | 0 MAINTAINERS | 4 ++-- 3 files changed, 2 insertions(+), 2 deletions(-) rename Documentation/trace/{ => coresight}/coresight-cpu-debug.txt (100%) rename Documentation/trace/{ => coresight}/coresight.txt (100%)
diff --git a/Documentation/trace/coresight-cpu-debug.txt b/Documentation/trace/coresight/coresight-cpu-debug.txt similarity index 100% rename from Documentation/trace/coresight-cpu-debug.txt rename to Documentation/trace/coresight/coresight-cpu-debug.txt diff --git a/Documentation/trace/coresight.txt b/Documentation/trace/coresight/coresight.txt similarity index 100% rename from Documentation/trace/coresight.txt rename to Documentation/trace/coresight/coresight.txt diff --git a/MAINTAINERS b/MAINTAINERS index a5b256b..815cb90 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1369,8 +1369,8 @@ M: Mathieu Poirier mathieu.poirier@linaro.org L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) S: Maintained F: drivers/hwtracing/coresight/* -F: Documentation/trace/coresight.txt -F: Documentation/trace/coresight-cpu-debug.txt +F: Documentation/trace/coresight/coresight.txt +F: Documentation/trace/coresight/coresight-cpu-debug.txt F: Documentation/devicetree/bindings/arm/coresight.txt F: Documentation/devicetree/bindings/arm/coresight-cpu-debug.txt F: Documentation/ABI/testing/sysfs-bus-coresight-devices-*
Add detailed documentation for Coresight panic kdump, which contains the idea for why need Coresight panic kdump and introduce the implementation of Coresight panic kdump framework; the last section gives an example for how to use it.
Suggested-by: Mathieu Poirier mathieu.poirier@linaro.org Signed-off-by: Leo Yan leo.yan@linaro.org --- .../trace/coresight/coresight-panic-kdump.txt | 99 ++++++++++++++++++++++ MAINTAINERS | 1 + 2 files changed, 100 insertions(+) create mode 100644 Documentation/trace/coresight/coresight-panic-kdump.txt
diff --git a/Documentation/trace/coresight/coresight-panic-kdump.txt b/Documentation/trace/coresight/coresight-panic-kdump.txt new file mode 100644 index 0000000..3fca77c --- /dev/null +++ b/Documentation/trace/coresight/coresight-panic-kdump.txt @@ -0,0 +1,99 @@ + Coresight Panic Kdump + ===================== + + Author: Leo Yan leo.yan@linaro.org + Date: September 11th, 2018 + +Introduction +------------ + +Coresight trace data is useful for postmortem debugging, the trace data can be +from different tracers: it can be from Embedded Trace Macrocell (ETM) or Program +Flow Trace Macrocell (PTM), which are mainly for program flow related trace; it +also can be from System Trace Macrocell (STM) for system level debugging info +generated by software. + +Coresight has different sinks for trace data to be routed, e.g. Embedded Trace +Buffer (ETB) is one kind of sink which provides on-chip storage of trace data, +usually uses SRAM as the buffer with several KBs size; if the SoC designs to +support 'Local ETF' (ARM DDI 0461B, chapter 1.2.7), every CPU has one local ETB +buffer so the per CPU trace data can avoid being overwritten by each other. +Trace Memory Controller (TMC) is another kind sink designed as a successor to +the CoreSight ETB to capture trace into DRAM. + +After Linux kernel panic has occurred, the trace data keeps the last execution +flow before issue occurs; thus we could consider the trace data is useful for +postmortem debugging, especially after saving trace data into DRAM and rely on +kdump to preserve them into vmcore file; at the end, we can retrieve trace data +from vmcore file and "offline" to analyze the execution flow. + + +Implementation +-------------- + +To support Coresight kdump functionality, when Coresight device acts as a PMU +device and works with perf framework, perf provides a ring buffer for storing +trace data and the ring buffer is accessed by user space with mmap() for high +efficiency data transferring; when the panic happens, Coresight kdump callback +function reuses the Coresight PMU event stop function to stop tracer and flush +trace data from hardware buffer (e.g. ETB RAM) to perf ring buffer, thus we can +save the trace data around the panic happening as possible. The perf ring +buffer is kept in DRAM and finally they can be stored into vmcore file by the +dump-capture kernel of kdump. + +When wrote this doc, the purpose is to keep Coresight kdump as simple as +possible in kernel and leave the complexity in crash tool to extract related +info. To delivery the correct tracer configuration info for decoder, ETM +driver saves related configuration info in the driver data structure and config +data structure when enable the hardware component. In the crash tool, by +accessing global symbol "csdev_src", it can get to know the handles for device +and driver data structures; thus it can extract tracer configurations from them. + +The perf ring buffer can be retrieved by accessing global symbol "ctx_handle" +which points to per CPU structure 'perf_output_handle', this variable can be +used to read ring buffer handler from 'perf_output_handle->rb' item. The ring +buffer handler points to ring buffer structure which contains buffer related +management information; at the end we can easily dump trace data from crash tool +according to information provided by the ring buffer structure. + + +Usage +----- + +Before use CoreSight kdump functionality, we need to build Linux kernel with +enabling 'CONFIG_CORESIGHT_KDUMP' configuration. + +After system booting up, firstly need to prepare dump-capture kernel, this can +refer to document [1] chapter 'Load the Dump-capture Kernel' for detailed steps. +For enabling the Coresight tracer with perf tool, please refer to document [2] +chapter 'How to use the tracer modules' for detailed steps. + +After kernel panic occurs, Coresight kdump callback function will be invoked +for every CPU to save trace data and kdump launches the dump-capture kernel, we +can utilize the dump-capture kernel to save kernel dump file, this can refer +to document [1] chapter 'Write Out the Dump File'. Thus all Coresight trace +data will be stored into kernel dump file. + +After get kernel dump file, we can use 'crash' tool + extension program +arm_cs_dump.so to extract trace data and decode trace data with OpenCSD [3]. + +Below is an example for post analysis for etmv4 tracer with crash extension +program; in the output folder, if every CPU has own perf ring buffer, the +extension program generates trace data file cstrace.X.bin for each CPU X. If +all CPUs share the same one ring buffer, it only generates file cstrace.0.bin. + + $ ./crash vmcore vmlinux + crash> extend arm_cs_dump.so + crash> arm_cs_dump -o etm_out + + $ ls etm_out + etm_out/ + ├── cstrace.0.bin + └── cstrace.0.log + +Finally the decoding info is displayed on the screen and also is saved into log +file cstrace.X.log (X is CPU number). + +[1] Documentation/kdump/kdump.txt +[2] Documentation/trace/coresight/coresight.txt +[3] https://github.com/Linaro/OpenCSD diff --git a/MAINTAINERS b/MAINTAINERS index 815cb90..031bdfd 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1371,6 +1371,7 @@ S: Maintained F: drivers/hwtracing/coresight/* F: Documentation/trace/coresight/coresight.txt F: Documentation/trace/coresight/coresight-cpu-debug.txt +F: Documentation/trace/coresight/coresight-panic-kdump.txt F: Documentation/devicetree/bindings/arm/coresight.txt F: Documentation/devicetree/bindings/arm/coresight-cpu-debug.txt F: Documentation/ABI/testing/sysfs-bus-coresight-devices-*
ETMv4 hardware information and configuration needs to be saved as metadata and the metadata finally can be used by kdump for tracing data decoding.
This patch saves ETMv4 metadata for registers TRCIDR{0, 1, 2, 8}. The decoder needs to use another two extra configuration and control registers TRCCONFIGR and TRCTRACEIDR, which are dynamically configured and their values are recorded during tracer enabling phase; their value are separately saved in 'etmv4_config::cfg' and 'etmv4_drvdata::trcid' so we don't need to add new fields for them.
Signed-off-by: Leo Yan leo.yan@linaro.org --- drivers/hwtracing/coresight/coresight-etm4x.c | 7 +++++++ drivers/hwtracing/coresight/coresight-etm4x.h | 8 ++++++++ 2 files changed, 15 insertions(+)
diff --git a/drivers/hwtracing/coresight/coresight-etm4x.c b/drivers/hwtracing/coresight/coresight-etm4x.c index b7379e9..e84fbb0 100644 --- a/drivers/hwtracing/coresight/coresight-etm4x.c +++ b/drivers/hwtracing/coresight/coresight-etm4x.c @@ -282,6 +282,7 @@ static int etm4_enable(struct coresight_device *csdev, int ret; u32 val; struct etmv4_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent); + struct etmv4_config *config = &drvdata->config;
val = local_cmpxchg(&drvdata->mode, CS_MODE_DISABLED, mode);
@@ -300,6 +301,12 @@ static int etm4_enable(struct coresight_device *csdev, ret = -EINVAL; }
+ /* Save idr registers for kdump */ + config->idr0 = readl_relaxed(drvdata->base + TRCIDR0); + config->idr1 = readl_relaxed(drvdata->base + TRCIDR1); + config->idr2 = readl_relaxed(drvdata->base + TRCIDR2); + config->idr8 = readl_relaxed(drvdata->base + TRCIDR8); + /* The tracer didn't start */ if (ret) local_set(&drvdata->mode, CS_MODE_DISABLED); diff --git a/drivers/hwtracing/coresight/coresight-etm4x.h b/drivers/hwtracing/coresight/coresight-etm4x.h index 52786e9..3fa08cc 100644 --- a/drivers/hwtracing/coresight/coresight-etm4x.h +++ b/drivers/hwtracing/coresight/coresight-etm4x.h @@ -237,6 +237,10 @@ * @vmid_mask0: VM ID comparator mask for comparator 0-3. * @vmid_mask1: VM ID comparator mask for comparator 4-7. * @ext_inp: External input selection. + * @idr0: Value of ID Register 0. + * @idr1: Value of ID Register 1. + * @idr2: Value of ID Register 2. + * @idr8: Value of ID Register 8. */ struct etmv4_config { u32 mode; @@ -279,6 +283,10 @@ struct etmv4_config { u32 vmid_mask0; u32 vmid_mask1; u32 ext_inp; + u32 idr0; + u32 idr1; + u32 idr2; + u32 idr8; };
/**
At every time the driver begins to write ring buffer, it will update the page index 'buf->cur' and offset value 'buf->offset'; but after update the ring buffer these two values will not be set. So these two values are mainly indicated the start point to fill ring buffer, but we have no chance to know where is the last writing point. This results in the post-mortem analysis tool (e.g. crash extension program) to read incomplete trace data from the dump.
This patch is to update CoreSight private structure to track the latest buffer state in 'buf->cur' and 'buf->offset', at the end this can delivery correct info of ring buffer for offline tool.
Signed-off-by: Leo Yan leo.yan@linaro.org --- drivers/hwtracing/coresight/coresight-tmc-etf.c | 8 ++++++++ 1 file changed, 8 insertions(+)
diff --git a/drivers/hwtracing/coresight/coresight-tmc-etf.c b/drivers/hwtracing/coresight/coresight-tmc-etf.c index 6265370..4ea1cd5 100644 --- a/drivers/hwtracing/coresight/coresight-tmc-etf.c +++ b/drivers/hwtracing/coresight/coresight-tmc-etf.c @@ -487,6 +487,14 @@ static unsigned long tmc_update_etf_buffer(struct coresight_device *csdev, to_read = to_read + barrier_sz; }
+ /* + * Though tmc_set_etf_buffer() will update the page index and offset + * for next data transferring, here update them to serve kernel panic + * emergency thus kdump can know the buffer last writing point. + */ + buf->cur = cur; + buf->offset = offset; + CS_LOCK(drvdata->base);
return to_read;
Since commit 24cc12b17679 ("perf/x86/intel/pt: Add interface to stop Intel PT logging") has been merged, Intel PT supports to stop the trace when kernel panic occurs and then this can be used for kdump for offline analysis.
This patch takes Intel PT as an example and do the exactly same thing; the patch adds a Kernel config to enable or disable panic dump functionality for building; it provides coresight_emergency_stop() which can be invoked when kernel panic occurs and call it for each CPU to stop the corresponding ETM. So far it supports to stop trace for ETM perf mode, later we can extend support for ETM and STM SysFS mode if have new requirements for this.
If the perf works as 'per-thread' mode, all CPUs share a single one ring buffer so this patch stop all CPUs ETM separately but it flushes trace data into the same ring buffer; at the time when wrote this patch, Arm ETM perf mode doesn't support global trace mode, after global trace mode has been supported, the change in this patch should can support to flush trace data into per CPU ring buffers.
Signed-off-by: Leo Yan leo.yan@linaro.org --- drivers/hwtracing/coresight/Kconfig | 10 ++++++++++ drivers/hwtracing/coresight/coresight-etm-perf.c | 10 ++++++++++ include/linux/coresight.h | 6 ++++++ 3 files changed, 26 insertions(+)
diff --git a/drivers/hwtracing/coresight/Kconfig b/drivers/hwtracing/coresight/Kconfig index ad34380..a3198ef 100644 --- a/drivers/hwtracing/coresight/Kconfig +++ b/drivers/hwtracing/coresight/Kconfig @@ -114,4 +114,14 @@ config CORESIGHT_CPU_DEBUG properly, please refer Documentation/trace/coresight-cpu-debug.txt for detailed description and the example for usage.
+config CORESIGHT_KDUMP + bool "CoreSight Kdump Support" + depends on ARM || ARM64 + depends on KEXEC_CORE + help + This enables kdump functionality for CoreSight devices. When kernel + panic happens Coresight supplies function to exectue emergency + stopping and dump trace data to memory. From then on, kdump can be + used to extract the trace data from kernel dump file. + endif diff --git a/drivers/hwtracing/coresight/coresight-etm-perf.c b/drivers/hwtracing/coresight/coresight-etm-perf.c index abe8249..0c8b2c4 100644 --- a/drivers/hwtracing/coresight/coresight-etm-perf.c +++ b/drivers/hwtracing/coresight/coresight-etm-perf.c @@ -454,6 +454,16 @@ static void etm_addr_filters_sync(struct perf_event *event) filters->nr_filters = i; }
+#ifdef CONFIG_CORESIGHT_KDUMP +void coresight_emergency_stop(void) +{ + struct perf_output_handle *handle = this_cpu_ptr(&ctx_handle); + + if (handle->event) + etm_event_stop(handle->event, PERF_EF_UPDATE); +} +#endif + int etm_perf_symlink(struct coresight_device *csdev, bool link) { char entry[sizeof("cpu9999999")]; diff --git a/include/linux/coresight.h b/include/linux/coresight.h index 5353582..68c2aa3 100644 --- a/include/linux/coresight.h +++ b/include/linux/coresight.h @@ -268,6 +268,12 @@ static inline int coresight_timeout(void __iomem *addr, u32 offset, int position, int value) { return 1; } #endif
+#ifdef CONFIG_CORESIGHT_KDUMP +extern void coresight_emergency_stop(void); +#else +static inline void coresight_emergency_stop(void) {} +#endif + #ifdef CONFIG_OF extern int of_coresight_get_cpu(const struct device_node *node); extern struct coresight_platform_data *
This patch invokes function coresight_emergency_stop() to stop Arm CoreSight before kdump is started. This feature is needed to stop CoreSight tracers and dump trace data from sink to buffer, the buffer can be either the aux buffer in perf mode or small size buffer within driver data structure for SysFS mode.
The related buffer can be saved in the vmcore file by kdump, users can retrieve the trace data from buffer in the vmcore and use it for post mortem analysis and reverse the program flow before panic.
Signed-off-by: Leo Yan leo.yan@linaro.org --- arch/arm64/kernel/smp.c | 5 +++++ 1 file changed, 5 insertions(+)
diff --git a/arch/arm64/kernel/smp.c b/arch/arm64/kernel/smp.c index 25fcd22..823d49a 100644 --- a/arch/arm64/kernel/smp.c +++ b/arch/arm64/kernel/smp.c @@ -41,6 +41,7 @@ #include <linux/of.h> #include <linux/irq_work.h> #include <linux/kexec.h> +#include <linux/coresight.h>
#include <asm/alternative.h> #include <asm/atomic.h> @@ -830,6 +831,8 @@ static void ipi_cpu_crash_stop(unsigned int cpu, struct pt_regs *regs) #ifdef CONFIG_KEXEC_CORE crash_save_cpu(regs, cpu);
+ coresight_emergency_stop(); + atomic_dec(&waiting_for_crash_ipi);
local_irq_disable(); @@ -973,6 +976,8 @@ void crash_smp_send_stop(void)
cpus_stopped = 1;
+ coresight_emergency_stop(); + if (num_online_cpus() == 1) { sdei_mask_local_cpu(); return;