Skip to content
Merged
17 changes: 17 additions & 0 deletions include/sound/sof/ipc4/header.h
Original file line numberDiff line numberDiff line change
Expand Up@@ -508,6 +508,23 @@ struct sof_ipc4_notify_resource_data {
uint32_t data[6];
} __packed __aligned(4);

#define SOF_IPC4_DEBUG_DESCRIPTOR_SIZE 12 /* 3 x u32 */
Comment thread
RanderWang marked this conversation as resolved.

/*
* The debug memory window is divided into 16 slots, and the
* first slot is used as a recorder for the other 15 slots.
*/
#define SOF_IPC4_MAX_DEBUG_SLOTS 15
#define SOF_IPC4_DEBUG_SLOT_SIZE 0x1000

/* debug log slot types */
#define SOF_IPC4_DEBUG_SLOT_UNUSED 0x00000000
#define SOF_IPC4_DEBUG_SLOT_CRITICAL_LOG 0x54524300 /* byte 0: core ID */
#define SOF_IPC4_DEBUG_SLOT_DEBUG_LOG 0x474f4c00 /* byte 0: core ID */
#define SOF_IPC4_DEBUG_SLOT_GDB_STUB 0x42444700
#define SOF_IPC4_DEBUG_SLOT_TELEMETRY 0x4c455400
#define SOF_IPC4_DEBUG_SLOT_BROKEN 0x44414544

/** @}*/

#endif
2 changes: 1 addition & 1 deletion sound/soc/sof/Makefile
Original file line numberDiff line numberDiff line change
Expand Up@@ -10,7 +10,7 @@ snd-sof-objs += ipc3.o ipc3-loader.o ipc3-topology.o ipc3-control.o ipc3-pcm.o\
endif
ifneq ($(CONFIG_SND_SOC_SOF_INTEL_IPC4),)
snd-sof-objs += ipc4.o ipc4-loader.o ipc4-topology.o ipc4-control.o ipc4-pcm.o\
ipc4-mtrace.o
ipc4-mtrace.o ipc4-telemetry.o
Comment thread
plbossart marked this conversation as resolved.
endif

# SOF client support
Expand Down
3 changes: 2 additions & 1 deletion sound/soc/sof/intel/Makefile
Original file line numberDiff line numberDiff line change
Expand Up@@ -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
Comment thread
btian1 marked this conversation as resolved.

snd-sof-intel-hda-mlink-objs := hda-mlink.o

Expand Down
14 changes: 14 additions & 0 deletions sound/soc/sof/intel/hda.c
Original file line numberDiff line numberDiff line change
Expand Up@@ -31,6 +31,7 @@
#include "../sof-pci-dev.h"
#include "../ops.h"
#include "hda.h"
#include "telemetry.h"
Comment thread
RanderWang marked this conversation as resolved.

#define CREATE_TRACE_POINTS
#include <trace/events/sof_intel.h>
Expand DownExpand Up@@ -720,6 +721,19 @@ void hda_dsp_dump(struct snd_sof_dev *sdev, u32 flags)
}
}

void hda_ipc4_dsp_dump(struct snd_sof_dev *sdev, u32 flags)
Comment thread
plbossart marked this conversation as resolved.
{
char *level = (flags & SOF_DBG_DUMP_OPTIONAL) ? KERN_DEBUG : KERN_ERR;

/* print ROM/FW status */
hda_dsp_get_state(sdev, level);

if (flags & SOF_DBG_DUMP_REGS)
sof_ipc4_intel_dump_telemetry_state(sdev, flags);
else
hda_dsp_dump_ext_rom_status(sdev, level, flags);
}

static bool hda_check_ipc_irq(struct snd_sof_dev *sdev)
{
const struct sof_intel_dsp_desc *chip;
Expand Down
1 change: 1 addition & 0 deletions sound/soc/sof/intel/hda.h
Original file line numberDiff line numberDiff line change
Expand Up@@ -600,6 +600,7 @@ int hda_dsp_shutdown_dma_flush(struct snd_sof_dev *sdev);
int hda_dsp_shutdown(struct snd_sof_dev *sdev);
int hda_dsp_set_hw_params_upon_resume(struct snd_sof_dev *sdev);
void hda_dsp_dump(struct snd_sof_dev *sdev, u32 flags);
void hda_ipc4_dsp_dump(struct snd_sof_dev *sdev, u32 flags);
void hda_ipc_dump(struct snd_sof_dev *sdev);
void hda_ipc_irq_dump(struct snd_sof_dev *sdev);
void hda_dsp_d0i3_work(struct work_struct *work);
Expand Down
3 changes: 3 additions & 0 deletions sound/soc/sof/intel/mtl.c
Original file line numberDiff line numberDiff line change
Expand Up@@ -18,6 +18,7 @@
#include "hda-ipc.h"
#include "../sof-audio.h"
#include "mtl.h"
#include "telemetry.h"
Comment thread
RanderWang marked this conversation as resolved.
Comment thread
RanderWang marked this conversation as resolved.

static const struct snd_sof_debugfs_map mtl_dsp_debugfs[] = {
{"hda", HDA_DSP_HDA_BAR, 0, 0x4000, SOF_DEBUGFS_ACCESS_ALWAYS},
Expand DownExpand Up@@ -320,6 +321,8 @@ void mtl_dsp_dump(struct snd_sof_dev *sdev, u32 flags)
romdbgsts = snd_sof_dsp_read(sdev, HDA_DSP_BAR, MTL_DSP_REG_HFFLGPXQWY + 0x8 * 3);
dev_printk(level, sdev->dev, "ROM feature bit%s enabled\n",
romdbgsts & BIT(24) ? "" : " not");

sof_ipc4_intel_dump_telemetry_state(sdev, flags);
}

static bool mtl_dsp_primary_core_is_enabled(struct snd_sof_dev *sdev)
Expand Down
95 changes: 95 additions & 0 deletions sound/soc/sof/intel/telemetry.c
Original file line numberDiff line numberDiff line change
@@ -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";
Comment thread
RanderWang marked this conversation as resolved.
struct sof_ipc4_telemetry_slot_data *telemetry_data;
struct sof_ipc_dsp_oops_xtensa *xoops;
struct xtensa_arch_block *block;
u32 slot_offset;
Comment thread
RanderWang marked this conversation as resolved.
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));
Comment thread
RanderWang marked this conversation as resolved.
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;
}
Comment thread
RanderWang marked this conversation as resolved.

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) {
Comment thread
RanderWang marked this conversation as resolved.
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;
}
Comment thread
RanderWang marked this conversation as resolved.

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:
Comment thread
plbossart marked this conversation as resolved.
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);
Comment thread
RanderWang marked this conversation as resolved.
free_block:
kfree(block);
free_telemetry_data:
kfree(telemetry_data);
}
35 changes: 35 additions & 0 deletions sound/soc/sof/intel/telemetry.h
Original file line numberDiff line numberDiff line change
@@ -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 {
Comment thread
kv2019i marked this conversation as resolved.
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;
Comment thread
kv2019i marked this conversation as resolved.
u32 lend;
u32 lcount;
} __packed;
Comment thread
plbossart marked this conversation as resolved.

void sof_ipc4_intel_dump_telemetry_state(struct snd_sof_dev *sdev, u32 flags);

#endif /* _SOF_INTEL_TELEMETRY_H */
1 change: 1 addition & 0 deletions sound/soc/sof/intel/tgl.c
Original file line numberDiff line numberDiff line change
Expand Up@@ -102,6 +102,7 @@ int sof_tgl_ops_init(struct snd_sof_dev *sdev)

/* debug */
sof_tgl_ops.ipc_dump = cnl_ipc4_dump;
sof_tgl_ops.dbg_dump = hda_ipc4_dsp_dump;

sof_tgl_ops.set_power_state = hda_dsp_set_power_state_ipc4;
}
Expand Down
34 changes: 11 additions & 23 deletions sound/soc/sof/ipc4-mtrace.c
Original file line numberDiff line numberDiff line change
Expand Up@@ -41,24 +41,12 @@
* The two pointers are offsets within the buffer.
*/

#define SOF_MTRACE_DESCRIPTOR_SIZE 12 /* 3 x u32 */

#define FW_EPOCH_DELTA 11644473600LL

#define INVALID_SLOT_OFFSET 0xffffffff
#define MAX_ALLOWED_LIBRARIES 16
#define MAX_MTRACE_SLOTS 15

#define SOF_MTRACE_PAGE_SIZE 0x1000
#define SOF_MTRACE_SLOT_SIZE SOF_MTRACE_PAGE_SIZE

/* debug log slot types */
#define SOF_MTRACE_SLOT_UNUSED 0x00000000
#define SOF_MTRACE_SLOT_CRITICAL_LOG 0x54524300 /* byte 0: core ID */
#define SOF_MTRACE_SLOT_DEBUG_LOG 0x474f4c00 /* byte 0: core ID */
#define SOF_MTRACE_SLOT_GDB_STUB 0x42444700
#define SOF_MTRACE_SLOT_TELEMETRY 0x4c455400
#define SOF_MTRACE_SLOT_BROKEN 0x44414544
Comment thread
RanderWang marked this conversation as resolved.

#define SOF_IPC4_INVALID_SLOT_OFFSET 0xffffffff

/* for debug and critical types */
#define SOF_MTRACE_SLOT_CORE_MASK GENMASK(7, 0)
#define SOF_MTRACE_SLOT_TYPE_MASK GENMASK(31, 8)
Expand DownExpand Up@@ -140,7 +128,7 @@ static int sof_ipc4_mtrace_dfs_open(struct inode *inode, struct file *file)
if (unlikely(ret))
goto out;

core_data->log_buffer = kmalloc(SOF_MTRACE_SLOT_SIZE, GFP_KERNEL);
core_data->log_buffer = kmalloc(SOF_IPC4_DEBUG_SLOT_SIZE, GFP_KERNEL);
if (!core_data->log_buffer) {
debugfs_file_put(file->f_path.dentry);
ret = -ENOMEM;
Expand DownExpand Up@@ -212,13 +200,13 @@ static ssize_t sof_ipc4_mtrace_dfs_read(struct file *file, char __user *buffer,
return 0;
}

if (core_data->slot_offset == INVALID_SLOT_OFFSET)
if (core_data->slot_offset == SOF_IPC4_INVALID_SLOT_OFFSET)
return 0;

/* The log data buffer starts after the two pointer in the slot */
log_buffer_offset = core_data->slot_offset + (sizeof(u32) * 2);
/* The log data size excludes the pointers */
log_buffer_size = SOF_MTRACE_SLOT_SIZE - (sizeof(u32) * 2);
log_buffer_size = SOF_IPC4_DEBUG_SLOT_SIZE - (sizeof(u32) * 2);

read_ptr = core_data->host_read_ptr;
write_ptr = core_data->dsp_write_ptr;
Expand DownExpand Up@@ -510,13 +498,13 @@ static void sof_mtrace_find_core_slots(struct snd_sof_dev *sdev)
u32 slot_desc_type_offset, type, core;
int i;

for (i = 0; i < MAX_MTRACE_SLOTS; i++) {
for (i = 0; i < SOF_IPC4_MAX_DEBUG_SLOTS; i++) {
/* The type is the second u32 in the slot descriptor */
slot_desc_type_offset = sdev->debug_box.offset;
slot_desc_type_offset += SOF_MTRACE_DESCRIPTOR_SIZE * i + sizeof(u32);
slot_desc_type_offset += SOF_IPC4_DEBUG_DESCRIPTOR_SIZE * i + sizeof(u32);
sof_mailbox_read(sdev, slot_desc_type_offset, &type, sizeof(type));

if ((type & SOF_MTRACE_SLOT_TYPE_MASK) == SOF_MTRACE_SLOT_DEBUG_LOG) {
if ((type & SOF_MTRACE_SLOT_TYPE_MASK) == SOF_IPC4_DEBUG_SLOT_DEBUG_LOG) {
core = type & SOF_MTRACE_SLOT_CORE_MASK;

if (core >= sdev->num_cores) {
Expand All@@ -533,7 +521,7 @@ static void sof_mtrace_find_core_slots(struct snd_sof_dev *sdev)
* debug_box + SOF_MTRACE_SLOT_SIZE offset
*/
core_data->slot_offset = sdev->debug_box.offset;
core_data->slot_offset += SOF_MTRACE_SLOT_SIZE * (i + 1);
core_data->slot_offset += SOF_IPC4_DEBUG_SLOT_SIZE * (i + 1);
dev_dbg(sdev->dev, "slot%d is used for core%u\n", i, core);
if (core_data->delayed_pos_update) {
sof_ipc4_mtrace_update_pos(sdev, core);
Expand DownExpand Up@@ -633,7 +621,7 @@ int sof_ipc4_mtrace_update_pos(struct snd_sof_dev *sdev, int core)

core_data = &priv->cores[core];

if (core_data->slot_offset == INVALID_SLOT_OFFSET) {
if (core_data->slot_offset == SOF_IPC4_INVALID_SLOT_OFFSET) {
core_data->delayed_pos_update = true;
return 0;
}
Expand Down
3 changes: 3 additions & 0 deletions sound/soc/sof/ipc4-priv.h
Original file line numberDiff line numberDiff line change
Expand Up@@ -120,4 +120,7 @@ void sof_ipc4_update_cpc_from_manifest(struct snd_sof_dev *sdev,
struct sof_ipc4_fw_module *fw_module,
struct sof_ipc4_base_module_cfg *basecfg);

size_t sof_ipc4_find_debug_slot_offset_by_type(struct snd_sof_dev *sdev,
u32 slot_type);

#endif
Loading