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 or 4 // redistributing this file, you may do so under either license. 5 // 6 // Copyright(c) 2023 Intel Corporation 7 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 17 void 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); 91 free_block: 92 kfree(block); 93 free_telemetry_data: 94 kfree(telemetry_data); 95 } 96 EXPORT_SYMBOL_NS(sof_ipc4_intel_dump_telemetry_state, SND_SOC_SOF_INTEL_HDA_COMMON); 97