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 *