1#!/bin/sh -e 2# SPDX-License-Identifier: GPL-2.0-only 3 4# hyp-trace-test - Tracefs for pKVM hypervisor test 5# 6# Copyright (C) 2024 - Google LLC 7# Author: Vincent Donnefort <vdonnefort@google.com> 8# 9 10log_and_die() 11{ 12 echo "$1" 13 14 exit 1 15} 16 17host_clock() 18{ 19 # BOOTTIME clock 20 awk '/now/ { printf "%.6f\n", $3 / 1000000000 }' /proc/timer_list 21} 22 23page_size() 24{ 25 echo "$(awk '/KernelPageSize/ {print $2; exit}' /proc/self/smaps) * 1024" | bc 26} 27 28goto_hyp_trace() 29{ 30 if [ -d "/sys/kernel/debug/tracing/hypervisor" ]; then 31 cd /sys/kernel/debug/tracing/hypervisor 32 return 33 fi 34 35 if [ -d "/sys/kernel/tracing/hypervisor" ]; then 36 cd /sys/kernel/tracing/hypervisor 37 return 38 fi 39 40 echo "ERROR: hyp tracing folder not found!" 41 42 exit 1 43} 44 45reset_hyp_trace() 46{ 47 echo 0 > tracing_on 48 echo 0 > trace 49 for event in events/hypervisor/*; do 50 echo 0 > $event/enable 51 done 52} 53 54setup_hyp_trace() 55{ 56 reset_hyp_trace 57 58 echo 16 > buffer_size_kb 59 echo 1 > events/hypervisor/selftest/enable 60 echo 1 > tracing_on 61} 62 63stop_hyp_trace() 64{ 65 echo 0 > tracing_on 66} 67 68hyp_trace_loaded() 69{ 70 grep -q "(loaded)" buffer_size_kb 71} 72 73write_events() 74{ 75 local num="$1" 76 local func="$2" 77 78 for i in $(seq 1 $num); do 79 echo 1 > selftest_event 80 [ -z "$func" -o $i -eq $num ] || eval $func 81 done 82} 83 84consuming_read() 85{ 86 local output=$1 87 88 cat trace_pipe > $output & 89 90 echo $! 91} 92 93run_test_consuming() 94{ 95 local nr_events=$1 96 local func=$2 97 local tmp="$(mktemp)" 98 local start_ts=0 99 local end_ts=0 100 local pid=0 101 102 echo "Output trace file: $tmp" 103 104 setup_hyp_trace 105 pid=$(consuming_read $tmp) 106 107 start_ts=$(host_clock) 108 write_events $nr_events $func 109 stop_hyp_trace 110 end_ts=$(host_clock) 111 112 kill $pid 113 validate_test $tmp $nr_events $start_ts $end_ts 114 115 rm $tmp 116} 117 118validate_test() 119{ 120 local output=$1 121 local expected_events=$2 122 local start_ts=$3 123 local end_ts=$4 124 local prev_ts=$3 125 local ts=0 126 local num_events=0 127 128 IFS=$'\n' 129 for line in $(cat $output); do 130 echo "$line" | grep -q -E "^# " && continue 131 ts=$(echo "$line" | awk '{print $2}' | cut -d ':' -f1) 132 if [ $(echo "$ts<$prev_ts" | bc) -eq 1 ]; then 133 log_and_die "Error event @$ts < $prev_ts" 134 fi 135 prev_ts=$ts 136 num_events=$((num_events + 1)) 137 done 138 139 if [ $(echo "$ts>$end_ts" | bc) -eq 1 ]; then 140 log_and_die "Error event @$ts > $end_ts" 141 fi 142 143 if [ $num_events -ne $expected_events ]; then 144 log_and_die "Expected $expected_events events, got $num_events" 145 fi 146} 147 148test_ts() 149{ 150 echo "Test Timestamps..." 151 152 run_test_consuming 1000 153 154 echo "done." 155} 156 157test_extended_ts() 158{ 159 echo "Test Extended Timestamps..." 160 161 run_test_consuming 1000 "sleep 0.1" 162 163 echo "done." 164} 165 166assert_loaded() 167{ 168 hyp_trace_loaded || log_and_die "Expected loaded buffer" 169} 170 171assert_unloaded() 172{ 173 ! hyp_trace_loaded || log_and_die "Expected unloaded buffer" 174} 175 176test_unloading() 177{ 178 local tmp="$(mktemp)" 179 180 echo "Test unloading..." 181 182 setup_hyp_trace 183 assert_loaded 184 185 echo 0 > tracing_on 186 assert_unloaded 187 188 pid=$(consuming_read $tmp) 189 sleep 1 190 assert_loaded 191 kill $pid 192 assert_unloaded 193 194 echo 1 > tracing_on 195 write_events 1 196 echo 0 > trace 197 assert_loaded 198 echo 0 > tracing_on 199 assert_unloaded 200 201 echo "done." 202} 203 204test_reset() 205{ 206 local tmp="$(mktemp)" 207 208 echo "Test Reset..." 209 210 setup_hyp_trace 211 write_events 1000 212 echo 0 > trace 213 clock_before=$(host_clock) 214 write_events 5 215 216 pid=$(consuming_read $tmp) 217 sleep 1 218 stop_hyp_trace 219 kill $pid 220 221 validate_test $tmp 5 $clock_before $(host_clock) 222 223 rm $tmp 224 225 echo "done." 226} 227 228test_big_bpacking() 229{ 230 local hyp_buffer_page_size=48 231 local page_size=$(page_size) 232 local min_buf_size=$(echo "$page_size * $page_size / ($hyp_buffer_page_size * $(nproc))" | bc) 233 234 min_buf_size=$(echo "$min_buf_size * 2 / 1024" | bc) 235 236 echo "Test loading $min_buf_size kB buffer..." 237 238 reset_hyp_trace 239 echo $min_buf_size > buffer_size_kb 240 echo 1 > tracing_on 241 242 stop_hyp_trace 243 244 echo "done." 245} 246 247validate_event() 248{ 249 local line="$1" 250 local expect_event="$2" 251 local expect_arg="$3" 252 local event="$(echo "$line" | awk '{print $3}')" 253 local arg="$(echo "$line" | awk '{print $4}')" 254 255 [ $event == $expect_event ] || log_and_die "Expected event '$expect_event', got: '$event'" 256 [ $arg == $expect_arg ] || log_and_die "Expected arg '$expect_arg', got: '$arg'" 257} 258 259setup_hyp_ftrace() 260{ 261 reset_hyp_trace 262 echo 1 > events/hypervisor/func/enable 263 echo 1 > events/hypervisor/func_ret/enable 264} 265 266run_test_ftrace() 267{ 268 local output="$2" 269 270 setup_hyp_ftrace 271 272 echo 1 > tracing_on 273 write_events 1 274 echo 0 > tracing_on 275 276 pid=$(consuming_read $tmp) 277 sleep 1 278 kill $pid 279 280} 281 282test_ftrace_nofilter() 283{ 284 local func="__kvm_nvhe_handle___pkvm_selftest_event" 285 local tmp="$(mktemp)" 286 287 echo "Test ftrace..." 288 289 echo "*" > set_ftrace_filter 290 291 run_test_ftrace $tmp 292 293 grep -qE "func *$func" $tmp || \ 294 log_and_die "Couldn't find 'func' event with arg '$func'" 295 grep -q "func_ret $func" $tmp || \ 296 log_and_die "Couldn't find 'func_ret' event with arg '$func'" 297 298 rm $tmp 299} 300 301test_ftrace_filter() 302{ 303 local func="__kvm_nvhe_handle___pkvm_selftest_event" 304 local tmp="$(mktemp)" 305 306 echo "Test ftrace filtering..." 307 308 echo "$func" > set_ftrace_filter 309 310 [ "$(cat set_ftrace_filter)" == "$func" ] || \ 311 log_and_die "Failed to set set_ftrace_filter" 312 313 run_test_ftrace $tmp 314 315 validate_event "$(awk 'NR==1 {print}' $tmp)" "func" "$func" 316 validate_event "$(awk 'NR==2 {print}' $tmp)" "func_ret" "$func" 317 318 rm $tmp 319} 320 321goto_hyp_trace 322 323test_reset 324test_unloading 325test_big_bpacking 326test_ts 327test_extended_ts 328test_ftrace_nofilter 329test_ftrace_filter 330 331exit 0 332