Skip to content

Commit be940b8

Browse files
author
Jyri Sarha
committed
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 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 not matter if the tool 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 look something like this: CPU 2: FATAL EXCEPTION CPU 2 EXCCAUSE 63 (zephyr exception) PC 0xa003048b VADDR 0xa0031020 PS 0x60220 (INTLEVEL:0 EXCM: 0 UM:1 RING:0 WOE:1 OWB:2 CALLINC:2) A0 0xa006c2b8 SP 0xa00dd160 A2 0x4 A3 0xa00dd170 A4 0xa00dd150 A5 0x4 A6 0x6 A7 0x4 A8 0xa006c109 A9 0xa00dd0f0 A10 0xa00a697d A11 0xa00dd170 A12 0xa00dd150 A13 0x4 A14 0x401a6b24 A15 0x401a6b24 LBEG 0xa0044323 LEND 0xa0044330 LCOUNT 0xa006de66 SAR 0x4 THREADPTR (nil) BT 0xa0030488:0xa00dd160 CORRUPTED Signed-off-by: Jyri Sarha <jyri.sarha@linux.intel.com> src/audio/host-zephyr.c: HACK assert(0) at the begin of host_get_copy_bytes_normal()
1 parent ba001a4 commit be940b8

File tree

2 files changed

+100
-0
lines changed

2 files changed

+100
-0
lines changed

src/audio/host-zephyr.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -432,6 +432,7 @@ static uint32_t host_get_copy_bytes_normal(struct host_data *hd, struct comp_dev
432432
uint32_t dma_copy_bytes;
433433
int ret;
434434

435+
assert(0);
435436
/* get data sizes from DMA */
436437
ret = host_get_status(dev, hd, &dma_stat);
437438
if (ret < 0) {

src/debug/debug_stream/debug_stream_text_msg.c

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,13 @@
88
#include <soc.h>
99
#include <adsp_debug_window.h>
1010
#include <sof/common.h>
11+
#include <zephyr/logging/log.h>
12+
#include <zephyr/arch/exception.h>
1113

1214
#include <user/debug_stream_text_msg.h>
1315

16+
LOG_MODULE_REGISTER(debug_stream_text_msg);
17+
1418
void ds_msg(const char *format, ...)
1519
{
1620
va_list args;
@@ -33,3 +37,98 @@ void ds_msg(const char *format, ...)
3337
sizeof(buf.msg.hdr.data[0]));
3438
debug_stream_slot_send_record(&buf.msg.hdr);
3539
}
40+
41+
#if defined(CONFIG_EXCEPTION_DUMP_HOOK)
42+
/* The debug stream debug window slot is 4k, and when it is split
43+
* between the cores and the header/other overhead is removed, with 5
44+
* cores the size is 768 bytes. The dump record must be smaller than
45+
* that to get through to the host side.
46+
*
47+
* Also, because of the limited circular buffer size, we should only
48+
* send one exception record. Exceptions often happen in bursts in a
49+
* SOF system, and sending more than one record makes the host-side
50+
* decoder lose track of things.
51+
*/
52+
static struct {
53+
struct debug_stream_text_msg msg;
54+
char text[640];
55+
} __packed ds_buf[CONFIG_MP_MAX_NUM_CPUS];
56+
static int reports_sent_cpu[CONFIG_MP_MAX_NUM_CPUS];
57+
static size_t ds_pos[CONFIG_MP_MAX_NUM_CPUS];
58+
59+
static void ds_exception_drain(bool flush)
60+
{
61+
unsigned int cpu = arch_proc_id();
62+
63+
if (flush) {
64+
ds_pos[cpu] = 0;
65+
reports_sent_cpu[cpu] = 0;
66+
return;
67+
}
68+
69+
if (ds_pos[cpu] == 0)
70+
return;
71+
72+
if (reports_sent_cpu[cpu] > 0)
73+
return;
74+
75+
ds_buf[cpu].msg.hdr.id = DEBUG_STREAM_RECORD_ID_TEXT_MSG;
76+
ds_buf[cpu].msg.hdr.size_words =
77+
SOF_DIV_ROUND_UP(sizeof(ds_buf[cpu].msg) + ds_pos[cpu],
78+
sizeof(ds_buf[cpu].msg.hdr.data[0]));
79+
/* Make sure the possible up to 3 extra bytes at end of msg are '\0' */
80+
memset(ds_buf[cpu].text + ds_pos[cpu], 0,
81+
ds_buf[cpu].msg.hdr.size_words * sizeof(ds_buf[cpu].msg.hdr.data[0]) - ds_pos[cpu]);
82+
debug_stream_slot_send_record(&ds_buf[cpu].msg.hdr);
83+
reports_sent_cpu[cpu] = 1;
84+
ds_pos[cpu] = 0;
85+
}
86+
87+
static void ds_exception_dump(const char *format, va_list args)
88+
{
89+
ssize_t len;
90+
size_t avail;
91+
size_t written;
92+
unsigned int cpu = arch_proc_id();
93+
94+
if (reports_sent_cpu[cpu] > 0)
95+
return;
96+
97+
avail = sizeof(ds_buf[cpu].text) - ds_pos[cpu];
98+
if (avail == 0) {
99+
ds_exception_drain(false);
100+
return;
101+
}
102+
103+
if (format[0] == '\0')
104+
return;
105+
106+
len = vsnprintf(ds_buf[cpu].text + ds_pos[cpu], avail, format, args);
107+
if (len < 0) {
108+
ds_pos[cpu] = 0;
109+
return;
110+
}
111+
112+
if (len == 0)
113+
return;
114+
115+
if ((size_t)len >= avail)
116+
written = avail - 1;
117+
else
118+
written = (size_t)len;
119+
120+
ds_pos[cpu] += written;
121+
122+
if (ds_pos[cpu] >= sizeof(ds_buf[cpu].text))
123+
ds_exception_drain(false);
124+
}
125+
126+
static int init_exception_dump_hook(void)
127+
{
128+
set_exception_dump_hook(ds_exception_dump, ds_exception_drain);
129+
LOG_INF("exception_dump_hook set");
130+
return 0;
131+
}
132+
133+
SYS_INIT(init_exception_dump_hook, APPLICATION, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT);
134+
#endif

0 commit comments

Comments
 (0)