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..a1dacb7d --- /dev/null +++ b/tools/eBPF/README.md @@ -0,0 +1,26 @@ +# 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 +... +``` + +## 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..f23638ad --- /dev/null +++ b/tools/eBPF/ipc4-msg-trace.bt @@ -0,0 +1,63 @@ +#!/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 bytes, arranged by 16 bytes/line + */ +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 = (uint8*) $msg->data_ptr; + $line = 0; + + printf("Message payload:\n"); + while ($line < 500) { + if ($count <= 16) { + printf("%rh\n", buf($ptr, $count)); + break; + } + + printf("%rh\n", buf($ptr, 16)); + $count -= 16; + if ($count == 0) { + break; + } + $ptr += 16; + $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"); + } + } +} +