Re: [PATCH v3 9/9] selftests/verification: add tlob selftests
From: Gabriele Monaco <gmonaco@redhat.com>
Date: 2026-06-22 09:26:49
Also in:
lkml
On Mon, 2026-06-08 at 00:13 +0800, wen.yang@linux.dev wrote:
From: Wen Yang <redacted>
+grep -qE "^p ${UPROBE_TARGET}:0x[0-9a-f]+ 0x[0-9a-f]+ threshold=[0-
9]+$" "$TLOB_MONITOR"
+grep -q "threshold=5000000000" "$TLOB_MONITOR"
+
+! echo "p ${UPROBE_TARGET}:${busy_offset} ${stop_offset}
threshold=9999000" > "$TLOB_MONITOR" 2>/dev/null
+
+echo "-${UPROBE_TARGET}:${busy_offset}" > "$TLOB_MONITOR"
+! grep -q "^p .*:0x${busy_offset#0x} " "$TLOB_MONITOR"...
+! grep -q "error_env_tlob" /sys/kernel/tracing/trace
There is a widespread misconception under selftests that ! cmd with set -e fails if the command succeeds, so you can use it to expect a program failure. That isn't the case though [1], errexit (what set -e does), skips commands starting with ! where the result isn't checked. Essentially if you want to say exit if the command succeeds, you can do: cmd && exit 1 # explicit ! cmd || exit 1 # explicit or still exploiting errexit cmd && false ! cmd || false I'm going to fix it in existing selftests using the last variant, but keep this in mind in your selftests as well. (Variants with ! are preferred because they also return 0 if cmd fails, as you'd expect, I personally prefer to use false instead of explicit exit, but that's up to you). Thanks, Gabriele [1] - https://www.shellcheck.net/wiki/SC2251
quoted hunk ↗ jump to hunk
+echo 0 > monitors/tlob/enable +echo 0 > /sys/kernel/tracing/events/rv/error_env_tlob/enable +echo > /sys/kernel/tracing/trace diff --git a/tools/testing/selftests/verification/test.d/tlob/uprobe_violation.t c b/tools/testing/selftests/verification/test.d/tlob/uprobe_violation.t c new file mode 100644 index 000000000000..d210d9c3a92d--- /dev/null +++b/tools/testing/selftests/verification/test.d/tlob/uprobe_violation.t c@@ -0,0 +1,67 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0-or-later +# description: Test tlob monitor budget violation (error_env_tloband detail_env_tlob fire with correct fields) +# requires: tlob:monitor + +RV_BINDIR="${RV_BINDIR:-$(realpath "$(dirname "${1:-$0}")")}" +UPROBE_TARGET="${RV_BINDIR}/tlob_target" +TLOB_SYM="${RV_BINDIR}/tlob_sym" +[ -x "$UPROBE_TARGET" ] || exit_unsupported +[ -x "$TLOB_SYM" ] || exit_unsupported +TLOB_MONITOR=monitors/tlob/monitor + +busy_offset=$("$TLOB_SYM" sym_offset "$UPROBE_TARGET" tlob_busy_work 2>/dev/null) +stop_offset=$("$TLOB_SYM" sym_offset "$UPROBE_TARGET" tlob_busy_work_done 2>/dev/null) +[ -n "$busy_offset" ] || exit_unsupported +[ -n "$stop_offset" ] || exit_unsupported + +"$UPROBE_TARGET" 30000 & +busy_pid=$! +sleep 0.05 + +echo 1 > /sys/kernel/tracing/events/rv/error_env_tlob/enable +echo 1 > /sys/kernel/tracing/events/rv/detail_env_tlob/enable +echo 1 > /sys/kernel/tracing/tracing_on +echo 1 > monitors/tlob/enable +echo > /sys/kernel/tracing/trace + +# 10 µs budget - fires almost immediately; task is busy-spinning on- CPU. +echo "p ${UPROBE_TARGET}:${busy_offset} ${stop_offset} threshold=10000" > "$TLOB_MONITOR" + +# wait up to 2 s for detail_env_tlob +found=0; i=0 +while [ "$i" -lt 20 ]; do + sleep 0.1 + grep -q "detail_env_tlob" /sys/kernel/tracing/trace && { found=1; break; } + i=$((i+1)) +done + +echo "-${UPROBE_TARGET}:${busy_offset}" > "$TLOB_MONITOR" 2>/dev/null +kill "$busy_pid" 2>/dev/null || true; wait "$busy_pid" 2>/dev/null || true +echo 0 > /sys/kernel/tracing/events/rv/error_env_tlob/enable +echo 0 > /sys/kernel/tracing/events/rv/detail_env_tlob/enable +echo 0 > monitors/tlob/enable + +[ "$found" = "1" ] + +# error_env_tlob must carry the clk_elapsed environment field. +# The event label is "budget_exceeded" when detected by the hrtimer callback, +# or the triggering sched event name when detected by the constraint path on a +# preemption that races with the timer (common on PREEMPT_RT / VM). Both are +# valid detections; check the env field instead of the label. +grep "error_env_tlob" /sys/kernel/tracing/trace | head -n 1 | grep - q "clk_elapsed=" + +# detail_env_tlob must have all five fields with the correct threshold +line=$(grep "detail_env_tlob" /sys/kernel/tracing/trace | head -n 1) +echo "$line" | grep -q "pid=" +echo "$line" | grep -q "threshold_ns=10000" +echo "$line" | grep -q "running_ns=" +echo "$line" | grep -q "waiting_ns=" +echo "$line" | grep -q "sleeping_ns=" + +# Busy-spin keeps the task on-CPU: running_ns must exceed sleeping_ns. +running=$(echo "$line" | sed 's/.*running_ns=\([0-9]*\).*/\1/') +sleeping=$(echo "$line" | sed 's/.*sleeping_ns=\([0-9]*\).*/\1/') +[ "$running" -gt "$sleeping" ] + +echo > /sys/kernel/tracing/trace