56df78dee9
Add a couple of test to the kselftest for the pKVM hypervisor tracing infrastructure. Bug: 357781595 Change-Id: I7e96a312fbaba3314bd1599d072a6042cc577ff2 Signed-off-by: Vincent Donnefort <vdonnefort@google.com>
332 lines
5.8 KiB
Bash
Executable File
332 lines
5.8 KiB
Bash
Executable File
#!/bin/sh -e
|
|
# SPDX-License-Identifier: GPL-2.0-only
|
|
|
|
# hyp-trace-test - Tracefs for pKVM hypervisor test
|
|
#
|
|
# Copyright (C) 2024 - Google LLC
|
|
# Author: Vincent Donnefort <vdonnefort@google.com>
|
|
#
|
|
|
|
log_and_die()
|
|
{
|
|
echo "$1"
|
|
|
|
exit 1
|
|
}
|
|
|
|
host_clock()
|
|
{
|
|
# BOOTTIME clock
|
|
awk '/now/ { printf "%.6f\n", $3 / 1000000000 }' /proc/timer_list
|
|
}
|
|
|
|
page_size()
|
|
{
|
|
echo "$(awk '/KernelPageSize/ {print $2; exit}' /proc/self/smaps) * 1024" | bc
|
|
}
|
|
|
|
goto_hyp_trace()
|
|
{
|
|
if [ -d "/sys/kernel/debug/tracing/hypervisor" ]; then
|
|
cd /sys/kernel/debug/tracing/hypervisor
|
|
return
|
|
fi
|
|
|
|
if [ -d "/sys/kernel/tracing/hypervisor" ]; then
|
|
cd /sys/kernel/tracing/hypervisor
|
|
return
|
|
fi
|
|
|
|
echo "ERROR: hyp tracing folder not found!"
|
|
|
|
exit 1
|
|
}
|
|
|
|
reset_hyp_trace()
|
|
{
|
|
echo 0 > tracing_on
|
|
echo 0 > trace
|
|
for event in events/hypervisor/*; do
|
|
echo 0 > $event/enable
|
|
done
|
|
}
|
|
|
|
setup_hyp_trace()
|
|
{
|
|
reset_hyp_trace
|
|
|
|
echo 16 > buffer_size_kb
|
|
echo 1 > events/hypervisor/selftest/enable
|
|
echo 1 > tracing_on
|
|
}
|
|
|
|
stop_hyp_trace()
|
|
{
|
|
echo 0 > tracing_on
|
|
}
|
|
|
|
hyp_trace_loaded()
|
|
{
|
|
grep -q "(loaded)" buffer_size_kb
|
|
}
|
|
|
|
write_events()
|
|
{
|
|
local num="$1"
|
|
local func="$2"
|
|
|
|
for i in $(seq 1 $num); do
|
|
echo 1 > selftest_event
|
|
[ -z "$func" -o $i -eq $num ] || eval $func
|
|
done
|
|
}
|
|
|
|
consuming_read()
|
|
{
|
|
local output=$1
|
|
|
|
cat trace_pipe > $output &
|
|
|
|
echo $!
|
|
}
|
|
|
|
run_test_consuming()
|
|
{
|
|
local nr_events=$1
|
|
local func=$2
|
|
local tmp="$(mktemp)"
|
|
local start_ts=0
|
|
local end_ts=0
|
|
local pid=0
|
|
|
|
echo "Output trace file: $tmp"
|
|
|
|
setup_hyp_trace
|
|
pid=$(consuming_read $tmp)
|
|
|
|
start_ts=$(host_clock)
|
|
write_events $nr_events $func
|
|
stop_hyp_trace
|
|
end_ts=$(host_clock)
|
|
|
|
kill $pid
|
|
validate_test $tmp $nr_events $start_ts $end_ts
|
|
|
|
rm $tmp
|
|
}
|
|
|
|
validate_test()
|
|
{
|
|
local output=$1
|
|
local expected_events=$2
|
|
local start_ts=$3
|
|
local end_ts=$4
|
|
local prev_ts=$3
|
|
local ts=0
|
|
local num_events=0
|
|
|
|
IFS=$'\n'
|
|
for line in $(cat $output); do
|
|
echo "$line" | grep -q -E "^# " && continue
|
|
ts=$(echo "$line" | awk '{print $2}' | cut -d ':' -f1)
|
|
if [ $(echo "$ts<$prev_ts" | bc) -eq 1 ]; then
|
|
log_and_die "Error event @$ts < $prev_ts"
|
|
fi
|
|
prev_ts=$ts
|
|
num_events=$((num_events + 1))
|
|
done
|
|
|
|
if [ $(echo "$ts>$end_ts" | bc) -eq 1 ]; then
|
|
log_and_die "Error event @$ts > $end_ts"
|
|
fi
|
|
|
|
if [ $num_events -ne $expected_events ]; then
|
|
log_and_die "Expected $expected_events events, got $num_events"
|
|
fi
|
|
}
|
|
|
|
test_ts()
|
|
{
|
|
echo "Test Timestamps..."
|
|
|
|
run_test_consuming 1000
|
|
|
|
echo "done."
|
|
}
|
|
|
|
test_extended_ts()
|
|
{
|
|
echo "Test Extended Timestamps..."
|
|
|
|
run_test_consuming 1000 "sleep 0.1"
|
|
|
|
echo "done."
|
|
}
|
|
|
|
assert_loaded()
|
|
{
|
|
hyp_trace_loaded || log_and_die "Expected loaded buffer"
|
|
}
|
|
|
|
assert_unloaded()
|
|
{
|
|
! hyp_trace_loaded || log_and_die "Expected unloaded buffer"
|
|
}
|
|
|
|
test_unloading()
|
|
{
|
|
local tmp="$(mktemp)"
|
|
|
|
echo "Test unloading..."
|
|
|
|
setup_hyp_trace
|
|
assert_loaded
|
|
|
|
echo 0 > tracing_on
|
|
assert_unloaded
|
|
|
|
pid=$(consuming_read $tmp)
|
|
sleep 1
|
|
assert_loaded
|
|
kill $pid
|
|
assert_unloaded
|
|
|
|
echo 1 > tracing_on
|
|
write_events 1
|
|
echo 0 > trace
|
|
assert_loaded
|
|
echo 0 > tracing_on
|
|
assert_unloaded
|
|
|
|
echo "done."
|
|
}
|
|
|
|
test_reset()
|
|
{
|
|
local tmp="$(mktemp)"
|
|
|
|
echo "Test Reset..."
|
|
|
|
setup_hyp_trace
|
|
write_events 1000
|
|
echo 0 > trace
|
|
clock_before=$(host_clock)
|
|
write_events 5
|
|
|
|
pid=$(consuming_read $tmp)
|
|
sleep 1
|
|
stop_hyp_trace
|
|
kill $pid
|
|
|
|
validate_test $tmp 5 $clock_before $(host_clock)
|
|
|
|
rm $tmp
|
|
|
|
echo "done."
|
|
}
|
|
|
|
test_big_bpacking()
|
|
{
|
|
local hyp_buffer_page_size=48
|
|
local page_size=$(page_size)
|
|
local min_buf_size=$(echo "$page_size * $page_size / ($hyp_buffer_page_size * $(nproc))" | bc)
|
|
|
|
min_buf_size=$(echo "$min_buf_size * 2 / 1024" | bc)
|
|
|
|
echo "Test loading $min_buf_size kB buffer..."
|
|
|
|
reset_hyp_trace
|
|
echo $min_buf_size > buffer_size_kb
|
|
echo 1 > tracing_on
|
|
|
|
stop_hyp_trace
|
|
|
|
echo "done."
|
|
}
|
|
|
|
validate_event()
|
|
{
|
|
local line="$1"
|
|
local expect_event="$2"
|
|
local expect_arg="$3"
|
|
local event="$(echo "$line" | awk '{print $3}')"
|
|
local arg="$(echo "$line" | awk '{print $4}')"
|
|
|
|
[ $event == $expect_event ] || log_and_die "Expected event '$expect_event', got: '$event'"
|
|
[ $arg == $expect_arg ] || log_and_die "Expected arg '$expect_arg', got: '$arg'"
|
|
}
|
|
|
|
setup_hyp_ftrace()
|
|
{
|
|
reset_hyp_trace
|
|
echo 1 > events/hypervisor/func/enable
|
|
echo 1 > events/hypervisor/func_ret/enable
|
|
}
|
|
|
|
run_test_ftrace()
|
|
{
|
|
local output="$2"
|
|
|
|
setup_hyp_ftrace
|
|
|
|
echo 1 > tracing_on
|
|
write_events 1
|
|
echo 0 > tracing_on
|
|
|
|
pid=$(consuming_read $tmp)
|
|
sleep 1
|
|
kill $pid
|
|
|
|
}
|
|
|
|
test_ftrace_nofilter()
|
|
{
|
|
local func="__kvm_nvhe_handle___pkvm_selftest_event"
|
|
local tmp="$(mktemp)"
|
|
|
|
echo "Test ftrace..."
|
|
|
|
echo "*" > set_ftrace_filter
|
|
|
|
run_test_ftrace $tmp
|
|
|
|
grep -qE "func *$func" $tmp || \
|
|
log_and_die "Couldn't find 'func' event with arg '$func'"
|
|
grep -q "func_ret $func" $tmp || \
|
|
log_and_die "Couldn't find 'func_ret' event with arg '$func'"
|
|
|
|
rm $tmp
|
|
}
|
|
|
|
test_ftrace_filter()
|
|
{
|
|
local func="__kvm_nvhe_handle___pkvm_selftest_event"
|
|
local tmp="$(mktemp)"
|
|
|
|
echo "Test ftrace filtering..."
|
|
|
|
echo "$func" > set_ftrace_filter
|
|
|
|
[ "$(cat set_ftrace_filter)" == "$func" ] || \
|
|
log_and_die "Failed to set set_ftrace_filter"
|
|
|
|
run_test_ftrace $tmp
|
|
|
|
validate_event "$(awk 'NR==1 {print}' $tmp)" "func" "$func"
|
|
validate_event "$(awk 'NR==2 {print}' $tmp)" "func_ret" "$func"
|
|
|
|
rm $tmp
|
|
}
|
|
|
|
goto_hyp_trace
|
|
|
|
test_reset
|
|
test_unloading
|
|
test_big_bpacking
|
|
test_ts
|
|
test_extended_ts
|
|
test_ftrace_nofilter
|
|
test_ftrace_filter
|
|
|
|
exit 0
|