From: Rander Wang rander.wang@intel.com
Telemetry data is decoded based on intel xtensa design and printed in kernel log by sof debug framework.
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/intel/Makefile | 3 +- sound/soc/sof/intel/telemetry.c | 95 +++++++++++++++++++++++++++++++++ sound/soc/sof/intel/telemetry.h | 35 ++++++++++++ 3 files changed, 132 insertions(+), 1 deletion(-) create mode 100644 sound/soc/sof/intel/telemetry.c create mode 100644 sound/soc/sof/intel/telemetry.h
diff --git a/sound/soc/sof/intel/Makefile b/sound/soc/sof/intel/Makefile index 030574dbc998..6489d0660d58 100644 --- a/sound/soc/sof/intel/Makefile +++ b/sound/soc/sof/intel/Makefile @@ -7,7 +7,8 @@ snd-sof-intel-hda-common-objs := hda.o hda-loader.o hda-stream.o hda-trace.o \ hda-dsp.o hda-ipc.o hda-ctrl.o hda-pcm.o \ hda-dai.o hda-dai-ops.o hda-bus.o \ skl.o hda-loader-skl.o \ - apl.o cnl.o tgl.o icl.o mtl.o lnl.o hda-common-ops.o + apl.o cnl.o tgl.o icl.o mtl.o lnl.o hda-common-ops.o \ + telemetry.o
snd-sof-intel-hda-mlink-objs := hda-mlink.o
diff --git a/sound/soc/sof/intel/telemetry.c b/sound/soc/sof/intel/telemetry.c new file mode 100644 index 000000000000..1a3b5c28a6f0 --- /dev/null +++ b/sound/soc/sof/intel/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) 2023 Intel Corporation. All rights reserved. + +/* telemetry data queried from debug window */ + +#include <sound/sof/ipc4/header.h> +#include <sound/sof/xtensa.h> +#include "../ipc4-priv.h" +#include "../sof-priv.h" +#include "hda.h" +#include "telemetry.h" + +void sof_ipc4_intel_dump_telemetry_state(struct snd_sof_dev *sdev, u32 flags) +{ + static const char invalid_slot_msg[] = "Core dump is not available due to"; + struct sof_ipc4_telemetry_slot_data *telemetry_data; + struct sof_ipc_dsp_oops_xtensa *xoops; + struct xtensa_arch_block *block; + u32 slot_offset; + char *level; + + level = (flags & SOF_DBG_DUMP_OPTIONAL) ? KERN_DEBUG : KERN_ERR; + + slot_offset = sof_ipc4_find_debug_slot_offset_by_type(sdev, SOF_IPC4_DEBUG_SLOT_TELEMETRY); + if (!slot_offset) + return; + + telemetry_data = kmalloc(sizeof(*telemetry_data), GFP_KERNEL); + if (!telemetry_data) + return; + sof_mailbox_read(sdev, slot_offset, telemetry_data, sizeof(*telemetry_data)); + if (telemetry_data->separator != XTENSA_CORE_DUMP_SEPARATOR) { + dev_err(sdev->dev, "%s invalid separator %#x\n", invalid_slot_msg, + telemetry_data->separator); + goto free_telemetry_data; + } + + block = kmalloc(sizeof(*block), GFP_KERNEL); + if (!block) + goto free_telemetry_data; + + sof_mailbox_read(sdev, slot_offset + sizeof(*telemetry_data), block, sizeof(*block)); + if (block->soc != XTENSA_SOC_INTEL_ADSP) { + dev_err(sdev->dev, "%s invalid SOC %d\n", invalid_slot_msg, block->soc); + goto free_block; + } + + if (telemetry_data->hdr.id[0] != COREDUMP_HDR_ID0 || + telemetry_data->hdr.id[1] != COREDUMP_HDR_ID1 || + telemetry_data->arch_hdr.id != COREDUMP_ARCH_HDR_ID) { + dev_err(sdev->dev, "%s invalid coredump header %c%c, arch hdr %c\n", + invalid_slot_msg, telemetry_data->hdr.id[0], + telemetry_data->hdr.id[1], + telemetry_data->arch_hdr.id); + goto free_block; + } + + switch (block->toolchain) { + case XTENSA_TOOL_CHAIN_ZEPHYR: + dev_printk(level, sdev->dev, "FW is built with Zephyr toolchain\n"); + break; + case XTENSA_TOOL_CHAIN_XCC: + dev_printk(level, sdev->dev, "FW is built with XCC toolchain\n"); + break; + default: + dev_printk(level, sdev->dev, "Unknown toolchain is used\n"); + break; + } + + xoops = kzalloc(struct_size(xoops, ar, XTENSA_CORE_AR_REGS_COUNT), GFP_KERNEL); + if (!xoops) + goto free_block; + + xoops->exccause = block->exccause; + xoops->excvaddr = block->excvaddr; + xoops->epc1 = block->pc; + xoops->ps = block->ps; + xoops->sar = block->sar; + + xoops->plat_hdr.numaregs = XTENSA_CORE_AR_REGS_COUNT; + memcpy((void *)xoops->ar, block->ar, XTENSA_CORE_AR_REGS_COUNT * sizeof(u32)); + + sof_oops(sdev, level, xoops); + sof_stack(sdev, level, xoops, NULL, 0); + + kfree(xoops); +free_block: + kfree(block); +free_telemetry_data: + kfree(telemetry_data); +} diff --git a/sound/soc/sof/intel/telemetry.h b/sound/soc/sof/intel/telemetry.h new file mode 100644 index 000000000000..3c2b23c75f5d --- /dev/null +++ b/sound/soc/sof/intel/telemetry.h @@ -0,0 +1,35 @@ +/* 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. + * + * telemetry data in debug windows + */ + +#ifndef _SOF_INTEL_TELEMETRY_H +#define _SOF_INTEL_TELEMETRY_H + +#include "../ipc4-telemetry.h" + +struct xtensa_arch_block { + u8 soc; /* should be equal to XTENSA_SOC_INTEL_ADSP */ + u16 version; + u8 toolchain; /* ZEPHYR or XCC */ + + u32 pc; + u32 exccause; + u32 excvaddr; + u32 sar; + u32 ps; + u32 scompare1; + u32 ar[XTENSA_CORE_AR_REGS_COUNT]; + u32 lbeg; + u32 lend; + u32 lcount; +} __packed; + +void sof_ipc4_intel_dump_telemetry_state(struct snd_sof_dev *sdev, u32 flags); + +#endif /* _SOF_INTEL_TELEMETRY_H */