diff --git a/tools/README.md b/tools/README.md index 1925c918..d8ced3f6 100644 --- a/tools/README.md +++ b/tools/README.md @@ -34,6 +34,8 @@ * sof-process-state.sh
Shows the current state of a given process +* eBPF (directory) +
Enhanced Berkeley Packet Filter (eBPF) scripts for kernel tracing Topologies ---------- diff --git a/tools/eBPF/README.md b/tools/eBPF/README.md new file mode 100644 index 00000000..dd74c3fc --- /dev/null +++ b/tools/eBPF/README.md @@ -0,0 +1,28 @@ +# Enhanced Berkeley Packet Filter (eBPF) scripts + +bpftrace must be installed to be able to use eBPF scripts: + +``` +sudo apt install bpftrace +sudo dnf install bpftrace +sudo pacman -S bpftrace +sudo emerge -a bpftrace +... +``` + +**Note**: the distro provided bpftrace might be old, in that case the tool can be downloaded from [https://github.com/bpftrace/bpftrace/releases](URL) + +## ipc4-msg-trace.bt + +The script will tap onto the entry of sof_ipc4_log_header() to log IPC messages. +It will start logging the sent messages (including payloads) and received notification with exception of 0x1b060000 - trace update. + +### To use the script: + +``` +sudo ./tools/sof-ipc4-msg-trace.bt +or +sudo bpftrace tools/sof-ipc4-msg-trace.bt +``` + +To stop the logging, just terminate the script with CTRL+C diff --git a/tools/eBPF/ipc4-msg-trace.bt b/tools/eBPF/ipc4-msg-trace.bt new file mode 100755 index 00000000..79e22f1f --- /dev/null +++ b/tools/eBPF/ipc4-msg-trace.bt @@ -0,0 +1,76 @@ +#!/usr/bin/bpftrace + +struct sof_ipc4_msg { + union { + unsigned long header_u64; + struct { + unsigned int primary; + unsigned int extension; + }; + }; + + unsigned long data_size; + void *data_ptr; +}; + +BEGIN +{ + printf("SOF IPC4 tx message logging. Ctrl-C to end.\n\n"); +} + +/* + * Log the sent IPC4 messages, ignoring the 0x1b060000 notification + * from firmware (trace update) + * The message payload is printed as 32bit words, arranged by 4 words/line + * In case the payload lenght is not aligned to 32bit words, the remaining 1-3 + * bytes are printed as bytes (unlikely, just for safety) + */ +kprobe:sof_ipc4_log_header { + $msg = (struct sof_ipc4_msg *)arg2; + + if ($msg->primary != 0x1b060000 && arg3 == 1 && $msg->data_size != 0) { + printf("%s : 0x%x|0x%x [data size:: %llu]\n", str(arg1), + $msg->primary, $msg->extension, $msg->data_size); + if (!strcontains(str(arg1), "done")) { + $count = (int64) $msg->data_size; + $ptr = (uint32*) $msg->data_ptr; + $line = 0; + + printf("Message payload:\n"); + while ($line < 500) { + printf("%08x:", $line * 16); + $word = 0; + while ($word < 4) { + if ($count >= 4) { + printf(" %08x", *$ptr); + $count -= 4; + } else { + printf("%rh", buf($ptr, $count)); + $count = 0; + } + if ($count == 0) { + break; + } + $word++; + $ptr++; + } + + printf("\n"); + + if ($count == 0) { + break; + } + $line++; + } + } else { + printf("\n"); + } + } else if ($msg->primary != 0x1b060000) { + printf("%s : 0x%x|0x%x\n", str(arg1), $msg->primary, + $msg->extension); + if (strcontains(str(arg1), "done")) { + printf("\n"); + } + } +} +