Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions include/sound/sof/ipc4/header.h
Original file line number Diff line number Diff 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 */

/*
* 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 number Diff line number Diff 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
endif

# SOF client support
Expand Down
3 changes: 2 additions & 1 deletion sound/soc/sof/intel/Makefile
Original file line number Diff line number Diff 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

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 number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
#include "../sof-pci-dev.h"
#include "../ops.h"
#include "hda.h"
#include "telemetry.h"

#define CREATE_TRACE_POINTS
#include <trace/events/sof_intel.h>
Expand Down Expand 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)
{
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 number Diff line number Diff 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 number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#include "hda-ipc.h"
#include "../sof-audio.h"
#include "mtl.h"
#include "telemetry.h"

static const struct snd_sof_debugfs_map mtl_dsp_debugfs[] = {
{"hda", HDA_DSP_HDA_BAR, 0, 0x4000, SOF_DEBUGFS_ACCESS_ALWAYS},
Expand Down Expand 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 number Diff line number Diff 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";
struct sof_ipc4_telemetry_slot_data *telemetry_data;
struct sof_ipc_dsp_oops_xtensa *xoops;
struct xtensa_arch_block *block;
u32 slot_offset;
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));
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;
}

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) {
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;
}

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:
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);
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 number Diff line number Diff 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 {
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;
u32 lend;
u32 lcount;
} __packed;

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 number Diff line number Diff 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 number Diff line number Diff 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

#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 Down Expand 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 Down Expand 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 Down Expand 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 Down Expand 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 number Diff line number Diff 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