Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ASoC: SOF: ipc4/Intel: Support for firmware exception

Merge series from Peter Ujfalusi <peter.ujfalusi@linux.intel.com>:

When a firmware crashes it creats a panic information into a telemetry
slot. The panic format is defined by Zephyr, includes stack and
additional information to help to identify the reason for the crash.
Part of the firmware exception handling the firmware also sends an
EXCEPTION_CAUGHT notification.

This series implements the kernel side handling of the exception: print
information into the kernel log export the whole telemetry slot to user
space for tools extract additional information from the panic dump.

+389 -23
+17
include/sound/sof/ipc4/header.h
··· 515 515 uint32_t data[6]; 516 516 } __packed __aligned(4); 517 517 518 + #define SOF_IPC4_DEBUG_DESCRIPTOR_SIZE 12 /* 3 x u32 */ 519 + 520 + /* 521 + * The debug memory window is divided into 16 slots, and the 522 + * first slot is used as a recorder for the other 15 slots. 523 + */ 524 + #define SOF_IPC4_MAX_DEBUG_SLOTS 15 525 + #define SOF_IPC4_DEBUG_SLOT_SIZE 0x1000 526 + 527 + /* debug log slot types */ 528 + #define SOF_IPC4_DEBUG_SLOT_UNUSED 0x00000000 529 + #define SOF_IPC4_DEBUG_SLOT_CRITICAL_LOG 0x54524300 /* byte 0: core ID */ 530 + #define SOF_IPC4_DEBUG_SLOT_DEBUG_LOG 0x474f4c00 /* byte 0: core ID */ 531 + #define SOF_IPC4_DEBUG_SLOT_GDB_STUB 0x42444700 532 + #define SOF_IPC4_DEBUG_SLOT_TELEMETRY 0x4c455400 533 + #define SOF_IPC4_DEBUG_SLOT_BROKEN 0x44414544 534 + 518 535 /** @}*/ 519 536 520 537 #endif
+1 -1
sound/soc/sof/Makefile
··· 10 10 endif 11 11 ifneq ($(CONFIG_SND_SOC_SOF_IPC4),) 12 12 snd-sof-objs += ipc4.o ipc4-loader.o ipc4-topology.o ipc4-control.o ipc4-pcm.o\ 13 - ipc4-mtrace.o 13 + ipc4-mtrace.o ipc4-telemetry.o 14 14 endif 15 15 16 16 # SOF client support
+2 -1
sound/soc/sof/intel/Makefile
··· 7 7 hda-dsp.o hda-ipc.o hda-ctrl.o hda-pcm.o \ 8 8 hda-dai.o hda-dai-ops.o hda-bus.o \ 9 9 skl.o hda-loader-skl.o \ 10 - apl.o cnl.o tgl.o icl.o mtl.o lnl.o hda-common-ops.o 10 + apl.o cnl.o tgl.o icl.o mtl.o lnl.o hda-common-ops.o \ 11 + telemetry.o 11 12 12 13 snd-sof-intel-hda-mlink-objs := hda-mlink.o 13 14
+14
sound/soc/sof/intel/hda.c
··· 31 31 #include "../sof-pci-dev.h" 32 32 #include "../ops.h" 33 33 #include "hda.h" 34 + #include "telemetry.h" 34 35 35 36 #define CREATE_TRACE_POINTS 36 37 #include <trace/events/sof_intel.h> ··· 730 729 } else { 731 730 hda_dsp_dump_ext_rom_status(sdev, level, flags); 732 731 } 732 + } 733 + 734 + void hda_ipc4_dsp_dump(struct snd_sof_dev *sdev, u32 flags) 735 + { 736 + char *level = (flags & SOF_DBG_DUMP_OPTIONAL) ? KERN_DEBUG : KERN_ERR; 737 + 738 + /* print ROM/FW status */ 739 + hda_dsp_get_state(sdev, level); 740 + 741 + if (flags & SOF_DBG_DUMP_REGS) 742 + sof_ipc4_intel_dump_telemetry_state(sdev, flags); 743 + else 744 + hda_dsp_dump_ext_rom_status(sdev, level, flags); 733 745 } 734 746 735 747 static bool hda_check_ipc_irq(struct snd_sof_dev *sdev)
+1
sound/soc/sof/intel/hda.h
··· 603 603 int hda_dsp_shutdown(struct snd_sof_dev *sdev); 604 604 int hda_dsp_set_hw_params_upon_resume(struct snd_sof_dev *sdev); 605 605 void hda_dsp_dump(struct snd_sof_dev *sdev, u32 flags); 606 + void hda_ipc4_dsp_dump(struct snd_sof_dev *sdev, u32 flags); 606 607 void hda_ipc_dump(struct snd_sof_dev *sdev); 607 608 void hda_ipc_irq_dump(struct snd_sof_dev *sdev); 608 609 void hda_dsp_d0i3_work(struct work_struct *work);
+3
sound/soc/sof/intel/mtl.c
··· 18 18 #include "hda-ipc.h" 19 19 #include "../sof-audio.h" 20 20 #include "mtl.h" 21 + #include "telemetry.h" 21 22 22 23 static const struct snd_sof_debugfs_map mtl_dsp_debugfs[] = { 23 24 {"hda", HDA_DSP_HDA_BAR, 0, 0x4000, SOF_DEBUGFS_ACCESS_ALWAYS}, ··· 321 320 romdbgsts = snd_sof_dsp_read(sdev, HDA_DSP_BAR, MTL_DSP_REG_HFFLGPXQWY + 0x8 * 3); 322 321 dev_printk(level, sdev->dev, "ROM feature bit%s enabled\n", 323 322 romdbgsts & BIT(24) ? "" : " not"); 323 + 324 + sof_ipc4_intel_dump_telemetry_state(sdev, flags); 324 325 } 325 326 326 327 static bool mtl_dsp_primary_core_is_enabled(struct snd_sof_dev *sdev)
+95
sound/soc/sof/intel/telemetry.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 or 4 + // redistributing this file, you may do so under either license. 5 + // 6 + // Copyright(c) 2023 Intel Corporation. All rights reserved. 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 + }
+35
sound/soc/sof/intel/telemetry.h
··· 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. All rights reserved. 7 + * 8 + * telemetry data in debug windows 9 + */ 10 + 11 + #ifndef _SOF_INTEL_TELEMETRY_H 12 + #define _SOF_INTEL_TELEMETRY_H 13 + 14 + #include "../ipc4-telemetry.h" 15 + 16 + struct xtensa_arch_block { 17 + u8 soc; /* should be equal to XTENSA_SOC_INTEL_ADSP */ 18 + u16 version; 19 + u8 toolchain; /* ZEPHYR or XCC */ 20 + 21 + u32 pc; 22 + u32 exccause; 23 + u32 excvaddr; 24 + u32 sar; 25 + u32 ps; 26 + u32 scompare1; 27 + u32 ar[XTENSA_CORE_AR_REGS_COUNT]; 28 + u32 lbeg; 29 + u32 lend; 30 + u32 lcount; 31 + } __packed; 32 + 33 + void sof_ipc4_intel_dump_telemetry_state(struct snd_sof_dev *sdev, u32 flags); 34 + 35 + #endif /* _SOF_INTEL_TELEMETRY_H */
+1
sound/soc/sof/intel/tgl.c
··· 102 102 103 103 /* debug */ 104 104 sof_tgl_ops.ipc_dump = cnl_ipc4_dump; 105 + sof_tgl_ops.dbg_dump = hda_ipc4_dsp_dump; 105 106 106 107 sof_tgl_ops.set_power_state = hda_dsp_set_power_state_ipc4; 107 108 }
+9 -21
sound/soc/sof/ipc4-mtrace.c
··· 41 41 * The two pointers are offsets within the buffer. 42 42 */ 43 43 44 - #define SOF_MTRACE_DESCRIPTOR_SIZE 12 /* 3 x u32 */ 45 - 46 44 #define FW_EPOCH_DELTA 11644473600LL 47 45 48 - #define INVALID_SLOT_OFFSET 0xffffffff 49 46 #define MAX_ALLOWED_LIBRARIES 16 50 - #define MAX_MTRACE_SLOTS 15 51 47 52 - #define SOF_MTRACE_PAGE_SIZE 0x1000 53 - #define SOF_MTRACE_SLOT_SIZE SOF_MTRACE_PAGE_SIZE 48 + #define SOF_IPC4_INVALID_SLOT_OFFSET 0xffffffff 54 49 55 - /* debug log slot types */ 56 - #define SOF_MTRACE_SLOT_UNUSED 0x00000000 57 - #define SOF_MTRACE_SLOT_CRITICAL_LOG 0x54524300 /* byte 0: core ID */ 58 - #define SOF_MTRACE_SLOT_DEBUG_LOG 0x474f4c00 /* byte 0: core ID */ 59 - #define SOF_MTRACE_SLOT_GDB_STUB 0x42444700 60 - #define SOF_MTRACE_SLOT_TELEMETRY 0x4c455400 61 - #define SOF_MTRACE_SLOT_BROKEN 0x44414544 62 50 /* for debug and critical types */ 63 51 #define SOF_MTRACE_SLOT_CORE_MASK GENMASK(7, 0) 64 52 #define SOF_MTRACE_SLOT_TYPE_MASK GENMASK(31, 8) ··· 128 140 if (unlikely(ret)) 129 141 goto out; 130 142 131 - core_data->log_buffer = kmalloc(SOF_MTRACE_SLOT_SIZE, GFP_KERNEL); 143 + core_data->log_buffer = kmalloc(SOF_IPC4_DEBUG_SLOT_SIZE, GFP_KERNEL); 132 144 if (!core_data->log_buffer) { 133 145 debugfs_file_put(file->f_path.dentry); 134 146 ret = -ENOMEM; ··· 200 212 return 0; 201 213 } 202 214 203 - if (core_data->slot_offset == INVALID_SLOT_OFFSET) 215 + if (core_data->slot_offset == SOF_IPC4_INVALID_SLOT_OFFSET) 204 216 return 0; 205 217 206 218 /* The log data buffer starts after the two pointer in the slot */ 207 219 log_buffer_offset = core_data->slot_offset + (sizeof(u32) * 2); 208 220 /* The log data size excludes the pointers */ 209 - log_buffer_size = SOF_MTRACE_SLOT_SIZE - (sizeof(u32) * 2); 221 + log_buffer_size = SOF_IPC4_DEBUG_SLOT_SIZE - (sizeof(u32) * 2); 210 222 211 223 read_ptr = core_data->host_read_ptr; 212 224 write_ptr = core_data->dsp_write_ptr; ··· 498 510 u32 slot_desc_type_offset, type, core; 499 511 int i; 500 512 501 - for (i = 0; i < MAX_MTRACE_SLOTS; i++) { 513 + for (i = 0; i < SOF_IPC4_MAX_DEBUG_SLOTS; i++) { 502 514 /* The type is the second u32 in the slot descriptor */ 503 515 slot_desc_type_offset = sdev->debug_box.offset; 504 - slot_desc_type_offset += SOF_MTRACE_DESCRIPTOR_SIZE * i + sizeof(u32); 516 + slot_desc_type_offset += SOF_IPC4_DEBUG_DESCRIPTOR_SIZE * i + sizeof(u32); 505 517 sof_mailbox_read(sdev, slot_desc_type_offset, &type, sizeof(type)); 506 518 507 - if ((type & SOF_MTRACE_SLOT_TYPE_MASK) == SOF_MTRACE_SLOT_DEBUG_LOG) { 519 + if ((type & SOF_MTRACE_SLOT_TYPE_MASK) == SOF_IPC4_DEBUG_SLOT_DEBUG_LOG) { 508 520 core = type & SOF_MTRACE_SLOT_CORE_MASK; 509 521 510 522 if (core >= sdev->num_cores) { ··· 521 533 * debug_box + SOF_MTRACE_SLOT_SIZE offset 522 534 */ 523 535 core_data->slot_offset = sdev->debug_box.offset; 524 - core_data->slot_offset += SOF_MTRACE_SLOT_SIZE * (i + 1); 536 + core_data->slot_offset += SOF_IPC4_DEBUG_SLOT_SIZE * (i + 1); 525 537 dev_dbg(sdev->dev, "slot%d is used for core%u\n", i, core); 526 538 if (core_data->delayed_pos_update) { 527 539 sof_ipc4_mtrace_update_pos(sdev, core); ··· 621 633 622 634 core_data = &priv->cores[core]; 623 635 624 - if (core_data->slot_offset == INVALID_SLOT_OFFSET) { 636 + if (core_data->slot_offset == SOF_IPC4_INVALID_SLOT_OFFSET) { 625 637 core_data->delayed_pos_update = true; 626 638 return 0; 627 639 }
+3
sound/soc/sof/ipc4-priv.h
··· 120 120 struct sof_ipc4_fw_module *fw_module, 121 121 struct sof_ipc4_base_module_cfg *basecfg); 122 122 123 + size_t sof_ipc4_find_debug_slot_offset_by_type(struct snd_sof_dev *sdev, 124 + u32 slot_type); 125 + 123 126 #endif
+95
sound/soc/sof/ipc4-telemetry.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 or 4 + // redistributing this file, you may do so under either license. 5 + // 6 + // Copyright(c) 2018-2023 Intel Corporation. All rights reserved. 7 + // 8 + 9 + #include <linux/debugfs.h> 10 + #include <linux/io.h> 11 + #include <linux/pm_runtime.h> 12 + #include <sound/sof/debug.h> 13 + #include <sound/sof/ipc4/header.h> 14 + #include "sof-priv.h" 15 + #include "ops.h" 16 + #include "ipc4-telemetry.h" 17 + #include "ipc4-priv.h" 18 + 19 + static void __iomem *sof_ipc4_query_exception_address(struct snd_sof_dev *sdev) 20 + { 21 + u32 type = SOF_IPC4_DEBUG_SLOT_TELEMETRY; 22 + size_t telemetry_slot_offset; 23 + u32 offset; 24 + 25 + telemetry_slot_offset = sof_ipc4_find_debug_slot_offset_by_type(sdev, type); 26 + if (!telemetry_slot_offset) 27 + return NULL; 28 + 29 + /* skip the first separator magic number */ 30 + offset = telemetry_slot_offset + sizeof(u32); 31 + 32 + return sdev->bar[sdev->mailbox_bar] + offset; 33 + } 34 + 35 + static ssize_t sof_telemetry_entry_read(struct file *file, char __user *buffer, 36 + size_t count, loff_t *ppos) 37 + { 38 + struct snd_sof_dfsentry *dfse = file->private_data; 39 + struct snd_sof_dev *sdev = dfse->sdev; 40 + void __iomem *io_addr; 41 + loff_t pos = *ppos; 42 + size_t size_ret; 43 + u8 *buf; 44 + 45 + if (pos < 0) 46 + return -EINVAL; 47 + /* skip the first separator magic number */ 48 + if (pos >= SOF_IPC4_DEBUG_SLOT_SIZE - 4 || !count) 49 + return 0; 50 + if (count > SOF_IPC4_DEBUG_SLOT_SIZE - 4 - pos) 51 + count = SOF_IPC4_DEBUG_SLOT_SIZE - 4 - pos; 52 + 53 + io_addr = sof_ipc4_query_exception_address(sdev); 54 + if (!io_addr) 55 + return -EFAULT; 56 + 57 + buf = kzalloc(SOF_IPC4_DEBUG_SLOT_SIZE - 4, GFP_KERNEL); 58 + if (!buf) 59 + return -ENOMEM; 60 + 61 + memcpy_fromio(buf, io_addr, SOF_IPC4_DEBUG_SLOT_SIZE - 4); 62 + size_ret = copy_to_user(buffer, buf + pos, count); 63 + if (size_ret) { 64 + kfree(buf); 65 + return -EFAULT; 66 + } 67 + 68 + *ppos = pos + count; 69 + kfree(buf); 70 + 71 + return count; 72 + } 73 + 74 + static const struct file_operations sof_telemetry_fops = { 75 + .open = simple_open, 76 + .read = sof_telemetry_entry_read, 77 + }; 78 + 79 + void sof_ipc4_create_exception_debugfs_node(struct snd_sof_dev *sdev) 80 + { 81 + struct snd_sof_dfsentry *dfse; 82 + 83 + dfse = devm_kzalloc(sdev->dev, sizeof(*dfse), GFP_KERNEL); 84 + if (!dfse) 85 + return; 86 + 87 + dfse->type = SOF_DFSENTRY_TYPE_IOMEM; 88 + dfse->size = SOF_IPC4_DEBUG_SLOT_SIZE - 4; 89 + dfse->access_type = SOF_DEBUGFS_ACCESS_ALWAYS; 90 + dfse->sdev = sdev; 91 + 92 + list_add(&dfse->list, &sdev->dfsentry_list); 93 + 94 + debugfs_create_file("exception", 0444, sdev->debugfs_root, dfse, &sof_telemetry_fops); 95 + }
+73
sound/soc/sof/ipc4-telemetry.h
··· 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. All rights reserved. 7 + */ 8 + 9 + #ifndef __SOUND_SOC_SOF_IPC4_TELEMETRY_H 10 + #define __SOUND_SOC_SOF_IPC4_TELEMETRY_H 11 + 12 + /* Target code */ 13 + enum sof_ipc4_coredump_tgt_code { 14 + COREDUMP_TGT_UNKNOWN = 0, 15 + COREDUMP_TGT_X86, 16 + COREDUMP_TGT_X86_64, 17 + COREDUMP_TGT_ARM_CORTEX_M, 18 + COREDUMP_TGT_RISC_V, 19 + COREDUMP_TGT_XTENSA, 20 + }; 21 + 22 + #define COREDUMP_ARCH_HDR_ID 'A' 23 + #define COREDUMP_HDR_ID0 'Z' 24 + #define COREDUMP_HDR_ID1 'E' 25 + 26 + #define XTENSA_BLOCK_HDR_VER 2 27 + #define XTENSA_CORE_DUMP_SEPARATOR 0x0DEC0DEB 28 + #define XTENSA_CORE_AR_REGS_COUNT 16 29 + #define XTENSA_SOC_INTEL_ADSP 3 30 + #define XTENSA_TOOL_CHAIN_ZEPHYR 1 31 + #define XTENSA_TOOL_CHAIN_XCC 2 32 + 33 + /* Coredump header */ 34 + struct sof_ipc4_coredump_hdr { 35 + /* 'Z', 'E' as identifier of file */ 36 + char id[2]; 37 + 38 + /* Identify the version of the header */ 39 + u16 hdr_version; 40 + 41 + /* Indicate which target (e.g. architecture or SoC) */ 42 + u16 tgt_code; 43 + 44 + /* Size of uintptr_t in power of 2. (e.g. 5 for 32-bit, 6 for 64-bit) */ 45 + u8 ptr_size_bits; 46 + 47 + u8 flag; 48 + 49 + /* Reason for the fatal error */ 50 + u32 reason; 51 + } __packed; 52 + 53 + /* Architecture-specific block header */ 54 + struct sof_ipc4_coredump_arch_hdr { 55 + /* COREDUMP_ARCH_HDR_ID to indicate this is a architecture-specific block */ 56 + char id; 57 + 58 + /* Identify the version of this block */ 59 + u16 hdr_version; 60 + 61 + /* Number of bytes following the header */ 62 + u16 num_bytes; 63 + } __packed; 64 + 65 + struct sof_ipc4_telemetry_slot_data { 66 + u32 separator; 67 + struct sof_ipc4_coredump_hdr hdr; 68 + struct sof_ipc4_coredump_arch_hdr arch_hdr; 69 + u32 arch_data[]; 70 + } __packed; 71 + 72 + void sof_ipc4_create_exception_debugfs_node(struct snd_sof_dev *sdev); 73 + #endif
+29
sound/soc/sof/ipc4.c
··· 15 15 #include "sof-audio.h" 16 16 #include "ipc4-fw-reg.h" 17 17 #include "ipc4-priv.h" 18 + #include "ipc4-telemetry.h" 18 19 #include "ops.h" 19 20 20 21 static const struct sof_ipc4_fw_status { ··· 548 547 return 0; 549 548 } 550 549 550 + size_t sof_ipc4_find_debug_slot_offset_by_type(struct snd_sof_dev *sdev, 551 + u32 slot_type) 552 + { 553 + size_t slot_desc_type_offset; 554 + u32 type; 555 + int i; 556 + 557 + /* The type is the second u32 in the slot descriptor */ 558 + slot_desc_type_offset = sdev->debug_box.offset + sizeof(u32); 559 + for (i = 0; i < SOF_IPC4_MAX_DEBUG_SLOTS; i++) { 560 + sof_mailbox_read(sdev, slot_desc_type_offset, &type, sizeof(type)); 561 + 562 + if (type == slot_type) 563 + return sdev->debug_box.offset + (i + 1) * SOF_IPC4_DEBUG_SLOT_SIZE; 564 + 565 + slot_desc_type_offset += SOF_IPC4_DEBUG_DESCRIPTOR_SIZE; 566 + } 567 + 568 + dev_dbg(sdev->dev, "Slot type %#x is not available in debug window\n", slot_type); 569 + return 0; 570 + } 571 + EXPORT_SYMBOL(sof_ipc4_find_debug_slot_offset_by_type); 572 + 551 573 static int ipc4_fw_ready(struct snd_sof_dev *sdev, struct sof_ipc4_msg *ipc4_msg) 552 574 { 553 575 int inbox_offset, inbox_size, outbox_offset, outbox_size; ··· 598 574 599 575 sdev->debug_box.offset = snd_sof_dsp_get_window_offset(sdev, 600 576 SOF_IPC4_DEBUG_WINDOW_IDX); 577 + 578 + sof_ipc4_create_exception_debugfs_node(sdev); 601 579 602 580 dev_dbg(sdev->dev, "mailbox upstream 0x%x - size 0x%x\n", 603 581 inbox_offset, inbox_size); ··· 644 618 break; 645 619 case SOF_IPC4_NOTIFY_LOG_BUFFER_STATUS: 646 620 sof_ipc4_mtrace_update_pos(sdev, SOF_IPC4_LOG_CORE_GET(ipc4_msg->primary)); 621 + break; 622 + case SOF_IPC4_NOTIFY_EXCEPTION_CAUGHT: 623 + snd_sof_dsp_panic(sdev, 0, true); 647 624 break; 648 625 default: 649 626 dev_dbg(sdev->dev, "Unhandled DSP message: %#x|%#x\n",
+11
sound/soc/sof/xtensa/core.c
··· 132 132 buf, sizeof(buf), false); 133 133 dev_printk(level, sdev->dev, "0x%08x: %s\n", stack_ptr + i * 4, buf); 134 134 } 135 + 136 + if (!xoops->plat_hdr.numaregs) 137 + return; 138 + 139 + dev_printk(level, sdev->dev, "AR registers:\n"); 140 + /* the number of ar registers is a multiple of 4 */ 141 + for (i = 0; i < xoops->plat_hdr.numaregs; i += 4) { 142 + hex_dump_to_buffer(xoops->ar + i, 16, 16, 4, 143 + buf, sizeof(buf), false); 144 + dev_printk(level, sdev->dev, "%#x: %s\n", i * 4, buf); 145 + } 135 146 } 136 147 137 148 const struct dsp_arch_ops sof_xtensa_arch_ops = {