1 // SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause)
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.
6 // Copyright(c) 2023 Intel Corporation
8 /* telemetry data queried from debug window */
10 #include <sound/sof/ipc4/header.h>
11 #include <sound/sof/xtensa.h>
12 #include "../ipc4-priv.h"
13 #include "../sof-priv.h"
15 #include "telemetry.h"
17 void sof_ipc4_intel_dump_telemetry_state(struct snd_sof_dev
*sdev
, u32 flags
)
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
;
26 level
= (flags
& SOF_DBG_DUMP_OPTIONAL
) ? KERN_DEBUG
: KERN_ERR
;
28 slot_offset
= sof_ipc4_find_debug_slot_offset_by_type(sdev
, SOF_IPC4_DEBUG_SLOT_TELEMETRY
);
32 telemetry_data
= kmalloc(sizeof(*telemetry_data
), GFP_KERNEL
);
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
;
42 block
= kmalloc(sizeof(*block
), GFP_KERNEL
);
44 goto free_telemetry_data
;
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
);
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
);
62 switch (block
->toolchain
) {
63 case XTENSA_TOOL_CHAIN_ZEPHYR
:
64 dev_printk(level
, sdev
->dev
, "FW is built with Zephyr toolchain\n");
66 case XTENSA_TOOL_CHAIN_XCC
:
67 dev_printk(level
, sdev
->dev
, "FW is built with XCC toolchain\n");
70 dev_printk(level
, sdev
->dev
, "Unknown toolchain is used\n");
74 xoops
= kzalloc(struct_size(xoops
, ar
, XTENSA_CORE_AR_REGS_COUNT
), GFP_KERNEL
);
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
;
84 xoops
->plat_hdr
.numaregs
= XTENSA_CORE_AR_REGS_COUNT
;
85 memcpy((void *)xoops
->ar
, block
->ar
, XTENSA_CORE_AR_REGS_COUNT
* sizeof(u32
));
87 sof_oops(sdev
, level
, xoops
);
88 sof_stack(sdev
, level
, xoops
, NULL
, 0);
94 kfree(telemetry_data
);
96 EXPORT_SYMBOL_NS(sof_ipc4_intel_dump_telemetry_state
, "SND_SOC_SOF_INTEL_HDA_COMMON");