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");
+ }
+ }
+}
+