1#!/bin/bash 2# perf kvm tests 3# SPDX-License-Identifier: GPL-2.0 4 5set -e 6 7err=0 8perfdata=$(mktemp /tmp/__perf_kvm_test.perf.data.XXXXX) 9qemu_pid_file=$(mktemp /tmp/__perf_kvm_test.qemu.pid.XXXXX) 10 11cleanup() { 12 rm -f "${perfdata}" 13 if [ -f "${qemu_pid_file}" ]; then 14 if [ -s "${qemu_pid_file}" ]; then 15 qemu_pid=$(cat "${qemu_pid_file}") 16 if [ -n "${qemu_pid}" ]; then 17 kill "${qemu_pid}" 2>/dev/null || true 18 fi 19 fi 20 rm -f "${qemu_pid_file}" 21 fi 22 trap - EXIT TERM INT 23} 24 25trap_cleanup() { 26 echo "Unexpected signal in ${FUNCNAME[1]}" 27 cleanup 28 exit 1 29} 30trap trap_cleanup EXIT TERM INT 31 32skip() { 33 echo "Skip: $1" 34 cleanup 35 exit 2 36} 37 38test_kvm_stat() { 39 echo "Testing perf kvm stat" 40 41 echo "Recording kvm events for pid ${qemu_pid}..." 42 if ! perf kvm stat record -p "${qemu_pid}" -o "${perfdata}" sleep 1; then 43 echo "Failed to record kvm events" 44 err=1 45 return 46 fi 47 48 echo "Reporting kvm events..." 49 if ! perf kvm -i "${perfdata}" stat report 2>&1 | grep -q "VM-EXIT"; then 50 echo "Failed to find VM-EXIT in report" 51 perf kvm -i "${perfdata}" stat report 2>&1 52 err=1 53 return 54 fi 55 56 echo "perf kvm stat test [Success]" 57} 58 59test_kvm_record_report() { 60 echo "Testing perf kvm record/report" 61 62 echo "Recording kvm profile for pid ${qemu_pid}..." 63 # Use --host to avoid needing guest symbols/mounts for this simple test 64 # We just want to verify the command runs and produces data 65 # We run in background and kill it because 'perf kvm record' appends options 66 # after the command, which breaks 'sleep' (e.g. it gets '-e cycles'). 67 perf kvm --host record -p "${qemu_pid}" -o "${perfdata}" & 68 rec_pid=$! 69 sleep 1 70 kill -INT "${rec_pid}" 71 wait "${rec_pid}" || true 72 73 echo "Reporting kvm profile..." 74 # Check for some standard output from report 75 if ! perf kvm -i "${perfdata}" report --stdio 2>&1 | grep -q "Event count"; then 76 echo "Failed to report kvm profile" 77 perf kvm -i "${perfdata}" report --stdio 2>&1 78 err=1 79 return 80 fi 81 82 echo "perf kvm record/report test [Success]" 83} 84 85test_kvm_buildid_list() { 86 echo "Testing perf kvm buildid-list" 87 88 # We reuse the perf.data from the previous record test 89 if ! perf kvm --host -i "${perfdata}" buildid-list 2>&1 | grep -q "."; then 90 echo "Failed to list buildids" 91 perf kvm --host -i "${perfdata}" buildid-list 2>&1 92 err=1 93 return 94 fi 95 96 echo "perf kvm buildid-list test [Success]" 97} 98 99setup_qemu() { 100 # Find qemu 101 if [ "$(uname -m)" = "x86_64" ]; then 102 qemu="qemu-system-x86_64" 103 elif [ "$(uname -m)" = "aarch64" ]; then 104 qemu="qemu-system-aarch64" 105 elif [ "$(uname -m)" = "s390x" ]; then 106 qemu="qemu-system-s390x" 107 elif [ "$(uname -m)" = "ppc64le" ]; then 108 qemu="qemu-system-ppc64" 109 else 110 qemu="qemu-system-$(uname -m)" 111 fi 112 113 if ! which -s "$qemu"; then 114 skip "$qemu not found" 115 fi 116 117 if [ ! -r /dev/kvm ] || [ ! -w /dev/kvm ]; then 118 skip "/dev/kvm not accessible" 119 fi 120 121 if ! perf kvm stat record -a sleep 0.01 >/dev/null 2>&1; then 122 skip "No permission to record kvm events" 123 fi 124 125 echo "Starting $qemu..." 126 # Start qemu in background, detached, with pidfile 127 # We use -display none -daemonize and a monitor to keep it alive/controllable if needed 128 # We don't need a real kernel, just KVM active. 129 if ! $qemu -enable-kvm -display none -daemonize -pidfile "${qemu_pid_file}" -monitor none; then 130 echo "Failed to start qemu" 131 err=1 132 return 133 fi 134 135 # Wait a bit for qemu to start 136 sleep 1 137 qemu_pid=$(cat "${qemu_pid_file}") 138 139 if ! kill -0 "${qemu_pid}" 2>/dev/null; then 140 echo "Qemu process failed to stay alive" 141 err=1 142 return 143 fi 144} 145 146setup_qemu 147if [ $err -eq 0 ]; then 148 test_kvm_stat 149 test_kvm_record_report 150 test_kvm_buildid_list 151fi 152 153cleanup 154exit $err 155