From: Rander Wang rander.wang@intel.com
Core dump includes hardware platform information, cpu registers and exception call stack. FW saves core dump to telemetry slot in shared memory window for host in the event of FW exception. This patch creates exception node in debugfs for user to dump telemetry data.
Signed-off-by: Rander Wang rander.wang@intel.com Reviewed-by: Péter Ujfalusi peter.ujfalusi@linux.intel.com Reviewed-by: Kai Vehmanen kai.vehmanen@linux.intel.com Reviewed-by: Pierre-Louis Bossart pierre-louis.bossart@linux.intel.com Reviewed-by: Guennadi Liakhovetski guennadi.liakhovetski@linux.intel.com Signed-off-by: Peter Ujfalusi peter.ujfalusi@linux.intel.com --- sound/soc/sof/Makefile | 2 +- sound/soc/sof/ipc4-telemetry.c | 95 ++++++++++++++++++++++++++++++++++ sound/soc/sof/ipc4-telemetry.h | 73 ++++++++++++++++++++++++++ 3 files changed, 169 insertions(+), 1 deletion(-) create mode 100644 sound/soc/sof/ipc4-telemetry.c create mode 100644 sound/soc/sof/ipc4-telemetry.h
diff --git a/sound/soc/sof/Makefile b/sound/soc/sof/Makefile index 744d40bd8c8b..42dc48e53964 100644 --- a/sound/soc/sof/Makefile +++ b/sound/soc/sof/Makefile @@ -10,7 +10,7 @@ snd-sof-objs += ipc3.o ipc3-loader.o ipc3-topology.o ipc3-control.o ipc3-pcm.o\ endif ifneq ($(CONFIG_SND_SOC_SOF_INTEL_IPC4),) snd-sof-objs += ipc4.o ipc4-loader.o ipc4-topology.o ipc4-control.o ipc4-pcm.o\ - ipc4-mtrace.o + ipc4-mtrace.o ipc4-telemetry.o endif
# SOF client support diff --git a/sound/soc/sof/ipc4-telemetry.c b/sound/soc/sof/ipc4-telemetry.c new file mode 100644 index 000000000000..ec4ae9674364 --- /dev/null +++ b/sound/soc/sof/ipc4-telemetry.c @@ -0,0 +1,95 @@ +// SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) +// +// This file is provided under a dual BSD/GPLv2 license. When using or +// redistributing this file, you may do so under either license. +// +// Copyright(c) 2018-2023 Intel Corporation. All rights reserved. +// + +#include <linux/debugfs.h> +#include <linux/io.h> +#include <linux/pm_runtime.h> +#include <sound/sof/debug.h> +#include <sound/sof/ipc4/header.h> +#include "sof-priv.h" +#include "ops.h" +#include "ipc4-telemetry.h" +#include "ipc4-priv.h" + +static void __iomem *sof_ipc4_query_exception_address(struct snd_sof_dev *sdev) +{ + u32 type = SOF_IPC4_DEBUG_SLOT_TELEMETRY; + size_t telemetry_slot_offset; + u32 offset; + + telemetry_slot_offset = sof_ipc4_find_debug_slot_offset_by_type(sdev, type); + if (!telemetry_slot_offset) + return NULL; + + /* skip the first separator magic number */ + offset = telemetry_slot_offset + sizeof(u32); + + return sdev->bar[sdev->mailbox_bar] + offset; +} + +static ssize_t sof_telemetry_entry_read(struct file *file, char __user *buffer, + size_t count, loff_t *ppos) +{ + struct snd_sof_dfsentry *dfse = file->private_data; + struct snd_sof_dev *sdev = dfse->sdev; + void __iomem *io_addr; + loff_t pos = *ppos; + size_t size_ret; + u8 *buf; + + if (pos < 0) + return -EINVAL; + /* skip the first separator magic number */ + if (pos >= SOF_IPC4_DEBUG_SLOT_SIZE - 4 || !count) + return 0; + if (count > SOF_IPC4_DEBUG_SLOT_SIZE - 4 - pos) + count = SOF_IPC4_DEBUG_SLOT_SIZE - 4 - pos; + + io_addr = sof_ipc4_query_exception_address(sdev); + if (!io_addr) + return -EFAULT; + + buf = kzalloc(SOF_IPC4_DEBUG_SLOT_SIZE - 4, GFP_KERNEL); + if (!buf) + return -ENOMEM; + + memcpy_fromio(buf, io_addr, SOF_IPC4_DEBUG_SLOT_SIZE - 4); + size_ret = copy_to_user(buffer, buf + pos, count); + if (size_ret) { + kfree(buf); + return -EFAULT; + } + + *ppos = pos + count; + kfree(buf); + + return count; +} + +static const struct file_operations sof_telemetry_fops = { + .open = simple_open, + .read = sof_telemetry_entry_read, +}; + +void sof_ipc4_create_exception_debugfs_node(struct snd_sof_dev *sdev) +{ + struct snd_sof_dfsentry *dfse; + + dfse = devm_kzalloc(sdev->dev, sizeof(*dfse), GFP_KERNEL); + if (!dfse) + return; + + dfse->type = SOF_DFSENTRY_TYPE_IOMEM; + dfse->size = SOF_IPC4_DEBUG_SLOT_SIZE - 4; + dfse->access_type = SOF_DEBUGFS_ACCESS_ALWAYS; + dfse->sdev = sdev; + + list_add(&dfse->list, &sdev->dfsentry_list); + + debugfs_create_file("exception", 0444, sdev->debugfs_root, dfse, &sof_telemetry_fops); +} diff --git a/sound/soc/sof/ipc4-telemetry.h b/sound/soc/sof/ipc4-telemetry.h new file mode 100644 index 000000000000..ab3599e3d87d --- /dev/null +++ b/sound/soc/sof/ipc4-telemetry.h @@ -0,0 +1,73 @@ +/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) */ +/* + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * Copyright(c) 2023 Intel Corporation. All rights reserved. + */ + +#ifndef __SOUND_SOC_SOF_IPC4_TELEMETRY_H +#define __SOUND_SOC_SOF_IPC4_TELEMETRY_H + +/* Target code */ +enum sof_ipc4_coredump_tgt_code { + COREDUMP_TGT_UNKNOWN = 0, + COREDUMP_TGT_X86, + COREDUMP_TGT_X86_64, + COREDUMP_TGT_ARM_CORTEX_M, + COREDUMP_TGT_RISC_V, + COREDUMP_TGT_XTENSA, +}; + +#define COREDUMP_ARCH_HDR_ID 'A' +#define COREDUMP_HDR_ID0 'Z' +#define COREDUMP_HDR_ID1 'E' + +#define XTENSA_BLOCK_HDR_VER 2 +#define XTENSA_CORE_DUMP_SEPARATOR 0x0DEC0DEB +#define XTENSA_CORE_AR_REGS_COUNT 16 +#define XTENSA_SOC_INTEL_ADSP 3 +#define XTENSA_TOOL_CHAIN_ZEPHYR 1 +#define XTENSA_TOOL_CHAIN_XCC 2 + +/* Coredump header */ +struct sof_ipc4_coredump_hdr { + /* 'Z', 'E' as identifier of file */ + char id[2]; + + /* Identify the version of the header */ + u16 hdr_version; + + /* Indicate which target (e.g. architecture or SoC) */ + u16 tgt_code; + + /* Size of uintptr_t in power of 2. (e.g. 5 for 32-bit, 6 for 64-bit) */ + u8 ptr_size_bits; + + u8 flag; + + /* Reason for the fatal error */ + u32 reason; +} __packed; + +/* Architecture-specific block header */ +struct sof_ipc4_coredump_arch_hdr { + /* COREDUMP_ARCH_HDR_ID to indicate this is a architecture-specific block */ + char id; + + /* Identify the version of this block */ + u16 hdr_version; + + /* Number of bytes following the header */ + u16 num_bytes; +} __packed; + +struct sof_ipc4_telemetry_slot_data { + u32 separator; + struct sof_ipc4_coredump_hdr hdr; + struct sof_ipc4_coredump_arch_hdr arch_hdr; + u32 arch_data[]; +} __packed; + +void sof_ipc4_create_exception_debugfs_node(struct snd_sof_dev *sdev); +#endif