97 lines · c
1// SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause)2//3// This file is provided under a dual BSD/GPLv2 license. When using or4// redistributing this file, you may do so under either license.5//6// Copyright(c) 2023 Intel Corporation7 8/* telemetry data queried from debug window */9 10#include <sound/sof/ipc4/header.h>11#include <sound/sof/xtensa.h>12#include "../ipc4-priv.h"13#include "../sof-priv.h"14#include "hda.h"15#include "telemetry.h"16 17void sof_ipc4_intel_dump_telemetry_state(struct snd_sof_dev *sdev, u32 flags)18{19 static const char invalid_slot_msg[] = "Core dump is not available due to";20 struct sof_ipc4_telemetry_slot_data *telemetry_data;21 struct sof_ipc_dsp_oops_xtensa *xoops;22 struct xtensa_arch_block *block;23 u32 slot_offset;24 char *level;25 26 level = (flags & SOF_DBG_DUMP_OPTIONAL) ? KERN_DEBUG : KERN_ERR;27 28 slot_offset = sof_ipc4_find_debug_slot_offset_by_type(sdev, SOF_IPC4_DEBUG_SLOT_TELEMETRY);29 if (!slot_offset)30 return;31 32 telemetry_data = kmalloc(sizeof(*telemetry_data), GFP_KERNEL);33 if (!telemetry_data)34 return;35 sof_mailbox_read(sdev, slot_offset, telemetry_data, sizeof(*telemetry_data));36 if (telemetry_data->separator != XTENSA_CORE_DUMP_SEPARATOR) {37 dev_err(sdev->dev, "%s invalid separator %#x\n", invalid_slot_msg,38 telemetry_data->separator);39 goto free_telemetry_data;40 }41 42 block = kmalloc(sizeof(*block), GFP_KERNEL);43 if (!block)44 goto free_telemetry_data;45 46 sof_mailbox_read(sdev, slot_offset + sizeof(*telemetry_data), block, sizeof(*block));47 if (block->soc != XTENSA_SOC_INTEL_ADSP) {48 dev_err(sdev->dev, "%s invalid SOC %d\n", invalid_slot_msg, block->soc);49 goto free_block;50 }51 52 if (telemetry_data->hdr.id[0] != COREDUMP_HDR_ID0 ||53 telemetry_data->hdr.id[1] != COREDUMP_HDR_ID1 ||54 telemetry_data->arch_hdr.id != COREDUMP_ARCH_HDR_ID) {55 dev_err(sdev->dev, "%s invalid coredump header %c%c, arch hdr %c\n",56 invalid_slot_msg, telemetry_data->hdr.id[0],57 telemetry_data->hdr.id[1],58 telemetry_data->arch_hdr.id);59 goto free_block;60 }61 62 switch (block->toolchain) {63 case XTENSA_TOOL_CHAIN_ZEPHYR:64 dev_printk(level, sdev->dev, "FW is built with Zephyr toolchain\n");65 break;66 case XTENSA_TOOL_CHAIN_XCC:67 dev_printk(level, sdev->dev, "FW is built with XCC toolchain\n");68 break;69 default:70 dev_printk(level, sdev->dev, "Unknown toolchain is used\n");71 break;72 }73 74 xoops = kzalloc(struct_size(xoops, ar, XTENSA_CORE_AR_REGS_COUNT), GFP_KERNEL);75 if (!xoops)76 goto free_block;77 78 xoops->exccause = block->exccause;79 xoops->excvaddr = block->excvaddr;80 xoops->epc1 = block->pc;81 xoops->ps = block->ps;82 xoops->sar = block->sar;83 84 xoops->plat_hdr.numaregs = XTENSA_CORE_AR_REGS_COUNT;85 memcpy((void *)xoops->ar, block->ar, XTENSA_CORE_AR_REGS_COUNT * sizeof(u32));86 87 sof_oops(sdev, level, xoops);88 sof_stack(sdev, level, xoops, NULL, 0);89 90 kfree(xoops);91free_block:92 kfree(block);93free_telemetry_data:94 kfree(telemetry_data);95}96EXPORT_SYMBOL_NS(sof_ipc4_intel_dump_telemetry_state, SND_SOC_SOF_INTEL_HDA_COMMON);97