From ba001a4d8e98114ba1a091fcdd6037cf6597f1b6 Mon Sep 17 00:00:00 2001 From: Jyri Sarha Date: Mon, 2 Feb 2026 16:17:01 +0200 Subject: [PATCH 1/4] debug: debug_stream_slot: Use spinlock instead of mutex for ISR Use spinlock instead of mutex to allow ISR context usage. Signed-off-by: Jyri Sarha --- src/debug/debug_stream/debug_stream_slot.c | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/src/debug/debug_stream/debug_stream_slot.c b/src/debug/debug_stream/debug_stream_slot.c index 388b7852e6ed..a55c1c1e116d 100644 --- a/src/debug/debug_stream/debug_stream_slot.c +++ b/src/debug/debug_stream/debug_stream_slot.c @@ -10,11 +10,12 @@ #include #include #include +#include LOG_MODULE_REGISTER(debug_stream_slot); struct cpu_mutex { - struct k_mutex m; + struct k_spinlock l; } __aligned(CONFIG_DCACHE_LINE_SIZE); /* CPU specific mutexes for each circular buffer */ @@ -66,6 +67,7 @@ int debug_stream_slot_send_record(struct debug_stream_record *rec) debug_stream_get_circular_buffer(&desc, arch_proc_id()); uint32_t record_size = rec->size_words; uint32_t record_start, buf_remain; + k_spinlock_key_t key; LOG_DBG("Sending record %u id %u len %u", rec->seqno, rec->id, rec->size_words); @@ -77,7 +79,7 @@ int debug_stream_slot_send_record(struct debug_stream_record *rec) desc.buf_words, desc.core_id, desc.buf_words, desc.offset); return -ENOMEM; } - k_mutex_lock(&cpu_mutex[arch_proc_id()].m, K_FOREVER); + key = k_spin_lock(&cpu_mutex[arch_proc_id()].l); rec->seqno = buf->next_seqno++; rec->size_words = record_size + 1; /* +1 for size at the end of record */ @@ -105,7 +107,7 @@ int debug_stream_slot_send_record(struct debug_stream_record *rec) buf->data[buf->w_ptr] = record_size + 1; buf->w_ptr = (buf->w_ptr + 1) % desc.buf_words; - k_mutex_unlock(&cpu_mutex[arch_proc_id()].m); + k_spin_unlock(&cpu_mutex[arch_proc_id()].l, key); LOG_DBG("Record %u id %u len %u sent", rec->seqno, rec->id, record_size); return 0; @@ -159,14 +161,6 @@ static int debug_stream_slot_init(void) buf->next_seqno = 0; buf->w_ptr = 0; - k_mutex_init(&cpu_mutex[i].m); - /* The core specific mutexes are now .bss which is uncached so the - * following line is commented out. However, since the mutexes are - * core specific there should be nothing preventing from having them - * in cached memory. - * - * sys_cache_data_flush_range(&cpu_mutex[i], sizeof(cpu_mutex[i])); - */ } LOG_INF("Debug stream slot initialized"); From 128e258e4fe9f70665e9cf491688aa85698b86b8 Mon Sep 17 00:00:00 2001 From: Jyri Sarha Date: Mon, 2 Feb 2026 23:06:19 +0200 Subject: [PATCH 2/4] debug_stream: text_msg: Set exception dump hooks if available Set exception dump hooks if CONFIG_EXCEPTION_DUMP_HOOK=y. This enables sending a simple text report of fatal exceptions. To get this working one needs these config options: CONFIG_EXCEPTION_DUMP_HOOK=y CONFIG_EXCEPTION_DUMP_HOOK_ONLY=y CONFIG_SOF_DEBUG_STREAM_SLOT=y CONFIG_SOF_DEBUG_STREAM_TEXT_MSG=y CONFIG_SOF_DEBUG_STREAM_SLOT_NUMBER=2 CONFIG_SOF_TELEMETRY=n CONFIG_SOF_TELEMETRY_PERFORMANCE_MEASUREMENTS=n CONFIG_SOF_TELEMETRY_IO_PERFORMANCE_MEASUREMENTS=n If system hangs and an the exception is reported successfully the report can be seen with debug_stream.py (which should be installed in the same directory with cavstool.py). It does matter if the too was not running at the time. The report should be available there in the debug slot window for debug_stream.py to decode as long as system remains up. The report should looks something like this: CPU 2: CPU 2 EXCCAUSE 13 (load/store PIF data error) PC 0xa06b24ba VADDR 0xa0031020 PS 0x60820 (INTLEVEL:0 EXCM: 0 UM:1 RING:0 WOE:1 OWB:8 CALLINC:2) A0 0xa06b10dd SP 0xa00f8b00 A2 0xa A3 0xa01a9354 A4 0xa01a922c A5 0x3c1 A6 0xa01a7ee4 A7 0xa01a7ec4 A8 0xa006e572 A9 0xa00f8ab0 A10 0x4018d8b0 A11 0xa A12 0x14 A13 0x1 A14 0xa A15 (nil) LBEG 0xa0044323 LEND 0xa0044330 LCOUNT 0xa006de66 SAR 0x5 THREADPTR (nil) BT 0xa06b24b7:0xa00f8b00 CORRUPTED Signed-off-by: Jyri Sarha --- .../debug_stream/debug_stream_text_msg.c | 60 +++++++++++++++++++ 1 file changed, 60 insertions(+) diff --git a/src/debug/debug_stream/debug_stream_text_msg.c b/src/debug/debug_stream/debug_stream_text_msg.c index 8933df03e6bb..bf68ff685328 100644 --- a/src/debug/debug_stream/debug_stream_text_msg.c +++ b/src/debug/debug_stream/debug_stream_text_msg.c @@ -8,9 +8,13 @@ #include #include #include +#include +#include #include +LOG_MODULE_REGISTER(debug_stream_text_msg); + void ds_msg(const char *format, ...) { va_list args; @@ -33,3 +37,59 @@ void ds_msg(const char *format, ...) sizeof(buf.msg.hdr.data[0])); debug_stream_slot_send_record(&buf.msg.hdr); } + +#if defined(CONFIG_EXCEPTION_DUMP_HOOK) +static struct { + struct debug_stream_text_msg msg; + char text[512]; +} __packed ds_buf; +static int reports_sent_cpu[CONFIG_MP_MAX_NUM_CPUS]; +static size_t ds_pos; + +static void ds_exception_drain(bool flush) +{ + if (flush) { + ds_pos = 0; + return; + } + + if (reports_sent_cpu[arch_proc_id()]++ > 0) + return; + + ds_buf.msg.hdr.id = DEBUG_STREAM_RECORD_ID_TEXT_MSG; + ds_buf.msg.hdr.size_words = SOF_DIV_ROUND_UP(sizeof(ds_buf.msg) + ds_pos, + sizeof(ds_buf.msg.hdr.data[0])); + /* Make sure the possible upto 3 extra bytes at end of msg are '\0' */ + memset(ds_buf.text + ds_pos, 0, ds_buf.msg.hdr.size_words * + sizeof(ds_buf.msg.hdr.data[0]) - ds_pos); + debug_stream_slot_send_record(&ds_buf.msg.hdr); + ds_pos = 0; +} + +static void ds_exception_dump(const char *format, va_list args) +{ + ssize_t len; + + if (reports_sent_cpu[arch_proc_id()] > 0) + return; + + len = vsnprintf(ds_buf.text + ds_pos, sizeof(ds_buf.text) - ds_pos, format, args); + if (len < 0) { + ds_pos = 0; + return; + } + ds_pos += MIN(len, sizeof(ds_buf.text) - ds_pos); + + if (ds_pos >= sizeof(ds_buf.text)) + ds_exception_drain(false); +} + +static int init_exception_dump_hook(void) +{ + set_exception_dump_hook(ds_exception_dump, ds_exception_drain); + LOG_INF("exception_dump_hook set"); + return 0; +} + +SYS_INIT(init_exception_dump_hook, APPLICATION, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT); +#endif From ba77abbc4b362d1f3ea140a0e44d30cda7e1a4d7 Mon Sep 17 00:00:00 2001 From: Jyri Sarha Date: Wed, 11 Feb 2026 00:17:41 +0200 Subject: [PATCH 3/4] debug_stream: text_msg: exception: Skip useless " ** " prefix Skip useless " ** " prefix from exception dumps to save byte is in the debug_stream buffer. Signed-off-by: Jyri Sarha --- src/debug/debug_stream/debug_stream_text_msg.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/debug/debug_stream/debug_stream_text_msg.c b/src/debug/debug_stream/debug_stream_text_msg.c index bf68ff685328..92ba0d333999 100644 --- a/src/debug/debug_stream/debug_stream_text_msg.c +++ b/src/debug/debug_stream/debug_stream_text_msg.c @@ -73,6 +73,11 @@ static void ds_exception_dump(const char *format, va_list args) if (reports_sent_cpu[arch_proc_id()] > 0) return; + /* Skip useless " ** " prefix to save bytes */ + if (strlen(format) >= 4 && + format[0] == ' ' && format[1] == '*' && format[2] == '*' && format[3] == ' ') + format += 4; + len = vsnprintf(ds_buf.text + ds_pos, sizeof(ds_buf.text) - ds_pos, format, args); if (len < 0) { ds_pos = 0; From 1e537a21f717212cc64c37d9e3498c1aadaba8f5 Mon Sep 17 00:00:00 2001 From: Jyri Sarha Date: Mon, 9 Feb 2026 22:05:14 +0200 Subject: [PATCH 4/4] src/audio/host-zephyr.c: HACK assert(0) at the begin of host_get_copy_bytes_normal() --- src/audio/host-zephyr.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/audio/host-zephyr.c b/src/audio/host-zephyr.c index 1fc69002a51d..0070b083053f 100644 --- a/src/audio/host-zephyr.c +++ b/src/audio/host-zephyr.c @@ -432,6 +432,7 @@ static uint32_t host_get_copy_bytes_normal(struct host_data *hd, struct comp_dev uint32_t dma_copy_bytes; int ret; + assert(0); /* get data sizes from DMA */ ret = host_get_status(dev, hd, &dma_stat); if (ret < 0) {