1*387f9dfdSAndroid Build Coastguard Worker#!/usr/bin/env python 2*387f9dfdSAndroid Build Coastguard Worker# 3*387f9dfdSAndroid Build Coastguard Worker# kvmexit.py 4*387f9dfdSAndroid Build Coastguard Worker# 5*387f9dfdSAndroid Build Coastguard Worker# Display the exit_reason and its statistics of each vm exit 6*387f9dfdSAndroid Build Coastguard Worker# for all vcpus of all virtual machines. For example: 7*387f9dfdSAndroid Build Coastguard Worker# $./kvmexit.py 8*387f9dfdSAndroid Build Coastguard Worker# PID TID KVM_EXIT_REASON COUNT 9*387f9dfdSAndroid Build Coastguard Worker# 1273551 1273568 EXIT_REASON_MSR_WRITE 6 10*387f9dfdSAndroid Build Coastguard Worker# 1274253 1274261 EXIT_REASON_EXTERNAL_INTERRUPT 1 11*387f9dfdSAndroid Build Coastguard Worker# 1274253 1274261 EXIT_REASON_HLT 12 12*387f9dfdSAndroid Build Coastguard Worker# ... 13*387f9dfdSAndroid Build Coastguard Worker# 14*387f9dfdSAndroid Build Coastguard Worker# Besides, we also allow users to specify one pid, tid(s), or one 15*387f9dfdSAndroid Build Coastguard Worker# pid and its vcpu. See kvmexit_example.txt for more examples. 16*387f9dfdSAndroid Build Coastguard Worker# 17*387f9dfdSAndroid Build Coastguard Worker# @PID: each vitual machine's pid in the user space. 18*387f9dfdSAndroid Build Coastguard Worker# @TID: the user space's thread of each vcpu of that virtual machine. 19*387f9dfdSAndroid Build Coastguard Worker# @KVM_EXIT_REASON: the reason why the vm exits. 20*387f9dfdSAndroid Build Coastguard Worker# @COUNT: the counts of the @KVM_EXIT_REASONS. 21*387f9dfdSAndroid Build Coastguard Worker# 22*387f9dfdSAndroid Build Coastguard Worker# REQUIRES: Linux 4.7+ (BPF_PROG_TYPE_TRACEPOINT support) 23*387f9dfdSAndroid Build Coastguard Worker# 24*387f9dfdSAndroid Build Coastguard Worker# Copyright (c) 2021 ByteDance Inc. All rights reserved. 25*387f9dfdSAndroid Build Coastguard Worker# 26*387f9dfdSAndroid Build Coastguard Worker# Author(s): 27*387f9dfdSAndroid Build Coastguard Worker# Fei Li <[email protected]> 28*387f9dfdSAndroid Build Coastguard Worker 29*387f9dfdSAndroid Build Coastguard Worker 30*387f9dfdSAndroid Build Coastguard Workerfrom __future__ import print_function 31*387f9dfdSAndroid Build Coastguard Workerfrom time import sleep 32*387f9dfdSAndroid Build Coastguard Workerfrom bcc import BPF 33*387f9dfdSAndroid Build Coastguard Workerimport argparse 34*387f9dfdSAndroid Build Coastguard Workerimport multiprocessing 35*387f9dfdSAndroid Build Coastguard Workerimport os 36*387f9dfdSAndroid Build Coastguard Workerimport subprocess 37*387f9dfdSAndroid Build Coastguard Worker 38*387f9dfdSAndroid Build Coastguard Worker# 39*387f9dfdSAndroid Build Coastguard Worker# Process Arguments 40*387f9dfdSAndroid Build Coastguard Worker# 41*387f9dfdSAndroid Build Coastguard Workerdef valid_args_list(args): 42*387f9dfdSAndroid Build Coastguard Worker args_list = args.split(",") 43*387f9dfdSAndroid Build Coastguard Worker for arg in args_list: 44*387f9dfdSAndroid Build Coastguard Worker try: 45*387f9dfdSAndroid Build Coastguard Worker int(arg) 46*387f9dfdSAndroid Build Coastguard Worker except: 47*387f9dfdSAndroid Build Coastguard Worker raise argparse.ArgumentTypeError("must be valid integer") 48*387f9dfdSAndroid Build Coastguard Worker return args_list 49*387f9dfdSAndroid Build Coastguard Worker 50*387f9dfdSAndroid Build Coastguard Worker# arguments 51*387f9dfdSAndroid Build Coastguard Workerexamples = """examples: 52*387f9dfdSAndroid Build Coastguard Worker ./kvmexit # Display kvm_exit_reason and its statistics in real-time until Ctrl-C 53*387f9dfdSAndroid Build Coastguard Worker ./kvmexit 5 # Display in real-time after sleeping 5s 54*387f9dfdSAndroid Build Coastguard Worker ./kvmexit -p 3195281 # Collpase all tids for pid 3195281 with exit reasons sorted in descending order 55*387f9dfdSAndroid Build Coastguard Worker ./kvmexit -p 3195281 20 # Collpase all tids for pid 3195281 with exit reasons sorted in descending order, and display after sleeping 20s 56*387f9dfdSAndroid Build Coastguard Worker ./kvmexit -p 3195281 -v 0 # Display only vcpu0 for pid 3195281, descending sort by default 57*387f9dfdSAndroid Build Coastguard Worker ./kvmexit -p 3195281 -a # Display all tids for pid 3195281 58*387f9dfdSAndroid Build Coastguard Worker ./kvmexit -t 395490 # Display only for tid 395490 with exit reasons sorted in descending order 59*387f9dfdSAndroid Build Coastguard Worker ./kvmexit -t 395490 20 # Display only for tid 395490 with exit reasons sorted in descending order after sleeping 20s 60*387f9dfdSAndroid Build Coastguard Worker ./kvmexit -T '395490,395491' # Display for a union like {395490, 395491} 61*387f9dfdSAndroid Build Coastguard Worker""" 62*387f9dfdSAndroid Build Coastguard Workerparser = argparse.ArgumentParser( 63*387f9dfdSAndroid Build Coastguard Worker description="Display kvm_exit_reason and its statistics at a timed interval", 64*387f9dfdSAndroid Build Coastguard Worker formatter_class=argparse.RawDescriptionHelpFormatter, 65*387f9dfdSAndroid Build Coastguard Worker epilog=examples) 66*387f9dfdSAndroid Build Coastguard Workerparser.add_argument("duration", nargs="?", default=99999999, type=int, help="show delta for next several seconds") 67*387f9dfdSAndroid Build Coastguard Workerparser.add_argument("-p", "--pid", type=int, help="trace this PID only") 68*387f9dfdSAndroid Build Coastguard Workerexgroup = parser.add_mutually_exclusive_group() 69*387f9dfdSAndroid Build Coastguard Workerexgroup.add_argument("-t", "--tid", type=int, help="trace this TID only") 70*387f9dfdSAndroid Build Coastguard Workerexgroup.add_argument("-T", "--tids", type=valid_args_list, help="trace a comma separated series of tids with no space in between") 71*387f9dfdSAndroid Build Coastguard Workerexgroup.add_argument("-v", "--vcpu", type=int, help="trace this vcpu only") 72*387f9dfdSAndroid Build Coastguard Workerexgroup.add_argument("-a", "--alltids", action="store_true", help="trace all tids for this pid") 73*387f9dfdSAndroid Build Coastguard Workerargs = parser.parse_args() 74*387f9dfdSAndroid Build Coastguard Workerduration = int(args.duration) 75*387f9dfdSAndroid Build Coastguard Worker 76*387f9dfdSAndroid Build Coastguard Worker# 77*387f9dfdSAndroid Build Coastguard Worker# Setup BPF 78*387f9dfdSAndroid Build Coastguard Worker# 79*387f9dfdSAndroid Build Coastguard Worker 80*387f9dfdSAndroid Build Coastguard Worker# load BPF program 81*387f9dfdSAndroid Build Coastguard Workerbpf_text = """ 82*387f9dfdSAndroid Build Coastguard Worker#include <linux/delay.h> 83*387f9dfdSAndroid Build Coastguard Worker 84*387f9dfdSAndroid Build Coastguard Worker#define REASON_NUM 69 85*387f9dfdSAndroid Build Coastguard Worker#define TGID_NUM 1024 86*387f9dfdSAndroid Build Coastguard Worker 87*387f9dfdSAndroid Build Coastguard Workerstruct exit_count { 88*387f9dfdSAndroid Build Coastguard Worker u64 exit_ct[REASON_NUM]; 89*387f9dfdSAndroid Build Coastguard Worker}; 90*387f9dfdSAndroid Build Coastguard WorkerBPF_PERCPU_ARRAY(init_value, struct exit_count, 1); 91*387f9dfdSAndroid Build Coastguard WorkerBPF_TABLE("percpu_hash", u64, struct exit_count, pcpu_kvm_stat, TGID_NUM); 92*387f9dfdSAndroid Build Coastguard Worker 93*387f9dfdSAndroid Build Coastguard Workerstruct cache_info { 94*387f9dfdSAndroid Build Coastguard Worker u64 cache_pid_tgid; 95*387f9dfdSAndroid Build Coastguard Worker struct exit_count cache_exit_ct; 96*387f9dfdSAndroid Build Coastguard Worker}; 97*387f9dfdSAndroid Build Coastguard WorkerBPF_PERCPU_ARRAY(pcpu_cache, struct cache_info, 1); 98*387f9dfdSAndroid Build Coastguard Worker 99*387f9dfdSAndroid Build Coastguard WorkerTRACEPOINT_PROBE(kvm, kvm_exit) { 100*387f9dfdSAndroid Build Coastguard Worker int cache_miss = 0; 101*387f9dfdSAndroid Build Coastguard Worker int zero = 0; 102*387f9dfdSAndroid Build Coastguard Worker u32 er = args->exit_reason; 103*387f9dfdSAndroid Build Coastguard Worker if (er >= REASON_NUM) { 104*387f9dfdSAndroid Build Coastguard Worker return 0; 105*387f9dfdSAndroid Build Coastguard Worker } 106*387f9dfdSAndroid Build Coastguard Worker 107*387f9dfdSAndroid Build Coastguard Worker u64 cur_pid_tgid = bpf_get_current_pid_tgid(); 108*387f9dfdSAndroid Build Coastguard Worker u32 tgid = cur_pid_tgid >> 32; 109*387f9dfdSAndroid Build Coastguard Worker u32 pid = cur_pid_tgid; 110*387f9dfdSAndroid Build Coastguard Worker 111*387f9dfdSAndroid Build Coastguard Worker if (THREAD_FILTER) 112*387f9dfdSAndroid Build Coastguard Worker return 0; 113*387f9dfdSAndroid Build Coastguard Worker 114*387f9dfdSAndroid Build Coastguard Worker struct exit_count *tmp_info = NULL, *initial = NULL; 115*387f9dfdSAndroid Build Coastguard Worker struct cache_info *cache_p; 116*387f9dfdSAndroid Build Coastguard Worker cache_p = pcpu_cache.lookup(&zero); 117*387f9dfdSAndroid Build Coastguard Worker if (cache_p == NULL) { 118*387f9dfdSAndroid Build Coastguard Worker return 0; 119*387f9dfdSAndroid Build Coastguard Worker } 120*387f9dfdSAndroid Build Coastguard Worker 121*387f9dfdSAndroid Build Coastguard Worker if (cache_p->cache_pid_tgid == cur_pid_tgid) { 122*387f9dfdSAndroid Build Coastguard Worker //a. If the cur_pid_tgid hit this physical cpu consecutively, save it to pcpu_cache 123*387f9dfdSAndroid Build Coastguard Worker tmp_info = &cache_p->cache_exit_ct; 124*387f9dfdSAndroid Build Coastguard Worker } else { 125*387f9dfdSAndroid Build Coastguard Worker //b. If another pid_tgid matches this pcpu for the last hit, OR it is the first time to hit this physical cpu. 126*387f9dfdSAndroid Build Coastguard Worker cache_miss = 1; 127*387f9dfdSAndroid Build Coastguard Worker 128*387f9dfdSAndroid Build Coastguard Worker // b.a Try to load the last cache struct if exists. 129*387f9dfdSAndroid Build Coastguard Worker tmp_info = pcpu_kvm_stat.lookup(&cur_pid_tgid); 130*387f9dfdSAndroid Build Coastguard Worker 131*387f9dfdSAndroid Build Coastguard Worker // b.b If it is the first time for the cur_pid_tgid to hit this pcpu, employ a 132*387f9dfdSAndroid Build Coastguard Worker // per_cpu array to initialize pcpu_kvm_stat's exit_count with each exit reason's count is zero 133*387f9dfdSAndroid Build Coastguard Worker if (tmp_info == NULL) { 134*387f9dfdSAndroid Build Coastguard Worker initial = init_value.lookup(&zero); 135*387f9dfdSAndroid Build Coastguard Worker if (initial == NULL) { 136*387f9dfdSAndroid Build Coastguard Worker return 0; 137*387f9dfdSAndroid Build Coastguard Worker } 138*387f9dfdSAndroid Build Coastguard Worker 139*387f9dfdSAndroid Build Coastguard Worker pcpu_kvm_stat.update(&cur_pid_tgid, initial); 140*387f9dfdSAndroid Build Coastguard Worker tmp_info = pcpu_kvm_stat.lookup(&cur_pid_tgid); 141*387f9dfdSAndroid Build Coastguard Worker // To pass the verifier 142*387f9dfdSAndroid Build Coastguard Worker if (tmp_info == NULL) { 143*387f9dfdSAndroid Build Coastguard Worker return 0; 144*387f9dfdSAndroid Build Coastguard Worker } 145*387f9dfdSAndroid Build Coastguard Worker } 146*387f9dfdSAndroid Build Coastguard Worker } 147*387f9dfdSAndroid Build Coastguard Worker 148*387f9dfdSAndroid Build Coastguard Worker if (er < REASON_NUM) { 149*387f9dfdSAndroid Build Coastguard Worker tmp_info->exit_ct[er]++; 150*387f9dfdSAndroid Build Coastguard Worker if (cache_miss == 1) { 151*387f9dfdSAndroid Build Coastguard Worker if (cache_p->cache_pid_tgid != 0) { 152*387f9dfdSAndroid Build Coastguard Worker // b.*.a Let's save the last hit cache_info into kvm_stat. 153*387f9dfdSAndroid Build Coastguard Worker pcpu_kvm_stat.update(&cache_p->cache_pid_tgid, &cache_p->cache_exit_ct); 154*387f9dfdSAndroid Build Coastguard Worker } 155*387f9dfdSAndroid Build Coastguard Worker // b.* As the cur_pid_tgid meets current pcpu_cache_array for the first time, save it. 156*387f9dfdSAndroid Build Coastguard Worker cache_p->cache_pid_tgid = cur_pid_tgid; 157*387f9dfdSAndroid Build Coastguard Worker bpf_probe_read(&cache_p->cache_exit_ct, sizeof(*tmp_info), tmp_info); 158*387f9dfdSAndroid Build Coastguard Worker } 159*387f9dfdSAndroid Build Coastguard Worker return 0; 160*387f9dfdSAndroid Build Coastguard Worker } 161*387f9dfdSAndroid Build Coastguard Worker 162*387f9dfdSAndroid Build Coastguard Worker return 0; 163*387f9dfdSAndroid Build Coastguard Worker} 164*387f9dfdSAndroid Build Coastguard Worker""" 165*387f9dfdSAndroid Build Coastguard Worker 166*387f9dfdSAndroid Build Coastguard Worker# format output 167*387f9dfdSAndroid Build Coastguard Workerexit_reasons = ( 168*387f9dfdSAndroid Build Coastguard Worker "EXCEPTION_NMI", 169*387f9dfdSAndroid Build Coastguard Worker "EXTERNAL_INTERRUPT", 170*387f9dfdSAndroid Build Coastguard Worker "TRIPLE_FAULT", 171*387f9dfdSAndroid Build Coastguard Worker "INIT_SIGNAL", 172*387f9dfdSAndroid Build Coastguard Worker "N/A", 173*387f9dfdSAndroid Build Coastguard Worker "N/A", 174*387f9dfdSAndroid Build Coastguard Worker "N/A", 175*387f9dfdSAndroid Build Coastguard Worker "INTERRUPT_WINDOW", 176*387f9dfdSAndroid Build Coastguard Worker "NMI_WINDOW", 177*387f9dfdSAndroid Build Coastguard Worker "TASK_SWITCH", 178*387f9dfdSAndroid Build Coastguard Worker "CPUID", 179*387f9dfdSAndroid Build Coastguard Worker "N/A", 180*387f9dfdSAndroid Build Coastguard Worker "HLT", 181*387f9dfdSAndroid Build Coastguard Worker "INVD", 182*387f9dfdSAndroid Build Coastguard Worker "INVLPG", 183*387f9dfdSAndroid Build Coastguard Worker "RDPMC", 184*387f9dfdSAndroid Build Coastguard Worker "RDTSC", 185*387f9dfdSAndroid Build Coastguard Worker "N/A", 186*387f9dfdSAndroid Build Coastguard Worker "VMCALL", 187*387f9dfdSAndroid Build Coastguard Worker "VMCLEAR", 188*387f9dfdSAndroid Build Coastguard Worker "VMLAUNCH", 189*387f9dfdSAndroid Build Coastguard Worker "VMPTRLD", 190*387f9dfdSAndroid Build Coastguard Worker "VMPTRST", 191*387f9dfdSAndroid Build Coastguard Worker "VMREAD", 192*387f9dfdSAndroid Build Coastguard Worker "VMRESUME", 193*387f9dfdSAndroid Build Coastguard Worker "VMWRITE", 194*387f9dfdSAndroid Build Coastguard Worker "VMOFF", 195*387f9dfdSAndroid Build Coastguard Worker "VMON", 196*387f9dfdSAndroid Build Coastguard Worker "CR_ACCESS", 197*387f9dfdSAndroid Build Coastguard Worker "DR_ACCESS", 198*387f9dfdSAndroid Build Coastguard Worker "IO_INSTRUCTION", 199*387f9dfdSAndroid Build Coastguard Worker "MSR_READ", 200*387f9dfdSAndroid Build Coastguard Worker "MSR_WRITE", 201*387f9dfdSAndroid Build Coastguard Worker "INVALID_STATE", 202*387f9dfdSAndroid Build Coastguard Worker "MSR_LOAD_FAIL", 203*387f9dfdSAndroid Build Coastguard Worker "N/A", 204*387f9dfdSAndroid Build Coastguard Worker "MWAIT_INSTRUCTION", 205*387f9dfdSAndroid Build Coastguard Worker "MONITOR_TRAP_FLAG", 206*387f9dfdSAndroid Build Coastguard Worker "N/A", 207*387f9dfdSAndroid Build Coastguard Worker "MONITOR_INSTRUCTION", 208*387f9dfdSAndroid Build Coastguard Worker "PAUSE_INSTRUCTION", 209*387f9dfdSAndroid Build Coastguard Worker "MCE_DURING_VMENTRY", 210*387f9dfdSAndroid Build Coastguard Worker "N/A", 211*387f9dfdSAndroid Build Coastguard Worker "TPR_BELOW_THRESHOLD", 212*387f9dfdSAndroid Build Coastguard Worker "APIC_ACCESS", 213*387f9dfdSAndroid Build Coastguard Worker "EOI_INDUCED", 214*387f9dfdSAndroid Build Coastguard Worker "GDTR_IDTR", 215*387f9dfdSAndroid Build Coastguard Worker "LDTR_TR", 216*387f9dfdSAndroid Build Coastguard Worker "EPT_VIOLATION", 217*387f9dfdSAndroid Build Coastguard Worker "EPT_MISCONFIG", 218*387f9dfdSAndroid Build Coastguard Worker "INVEPT", 219*387f9dfdSAndroid Build Coastguard Worker "RDTSCP", 220*387f9dfdSAndroid Build Coastguard Worker "PREEMPTION_TIMER", 221*387f9dfdSAndroid Build Coastguard Worker "INVVPID", 222*387f9dfdSAndroid Build Coastguard Worker "WBINVD", 223*387f9dfdSAndroid Build Coastguard Worker "XSETBV", 224*387f9dfdSAndroid Build Coastguard Worker "APIC_WRITE", 225*387f9dfdSAndroid Build Coastguard Worker "RDRAND", 226*387f9dfdSAndroid Build Coastguard Worker "INVPCID", 227*387f9dfdSAndroid Build Coastguard Worker "VMFUNC", 228*387f9dfdSAndroid Build Coastguard Worker "ENCLS", 229*387f9dfdSAndroid Build Coastguard Worker "RDSEED", 230*387f9dfdSAndroid Build Coastguard Worker "PML_FULL", 231*387f9dfdSAndroid Build Coastguard Worker "XSAVES", 232*387f9dfdSAndroid Build Coastguard Worker "XRSTORS", 233*387f9dfdSAndroid Build Coastguard Worker "N/A", 234*387f9dfdSAndroid Build Coastguard Worker "N/A", 235*387f9dfdSAndroid Build Coastguard Worker "UMWAIT", 236*387f9dfdSAndroid Build Coastguard Worker "TPAUSE" 237*387f9dfdSAndroid Build Coastguard Worker) 238*387f9dfdSAndroid Build Coastguard Worker 239*387f9dfdSAndroid Build Coastguard Worker# 240*387f9dfdSAndroid Build Coastguard Worker# Do some checks 241*387f9dfdSAndroid Build Coastguard Worker# 242*387f9dfdSAndroid Build Coastguard Workertry: 243*387f9dfdSAndroid Build Coastguard Worker # Currently, only adapte on intel architecture 244*387f9dfdSAndroid Build Coastguard Worker cmd = "cat /proc/cpuinfo | grep vendor_id | head -n 1" 245*387f9dfdSAndroid Build Coastguard Worker arch_info = subprocess.check_output(cmd, shell=True).strip() 246*387f9dfdSAndroid Build Coastguard Worker if b"Intel" in arch_info: 247*387f9dfdSAndroid Build Coastguard Worker pass 248*387f9dfdSAndroid Build Coastguard Worker else: 249*387f9dfdSAndroid Build Coastguard Worker raise Exception("Currently we only support Intel architecture, please do expansion if needs more.") 250*387f9dfdSAndroid Build Coastguard Worker 251*387f9dfdSAndroid Build Coastguard Worker # Check if kvm module is loaded 252*387f9dfdSAndroid Build Coastguard Worker if os.access("/dev/kvm", os.R_OK | os.W_OK): 253*387f9dfdSAndroid Build Coastguard Worker pass 254*387f9dfdSAndroid Build Coastguard Worker else: 255*387f9dfdSAndroid Build Coastguard Worker raise Exception("Please insmod kvm module to use kvmexit tool.") 256*387f9dfdSAndroid Build Coastguard Workerexcept Exception as e: 257*387f9dfdSAndroid Build Coastguard Worker raise Exception("Failed to do precondition check, due to: %s." % e) 258*387f9dfdSAndroid Build Coastguard Worker 259*387f9dfdSAndroid Build Coastguard Workerdef find_tid(tgt_dir, tgt_vcpu): 260*387f9dfdSAndroid Build Coastguard Worker for tid in os.listdir(tgt_dir): 261*387f9dfdSAndroid Build Coastguard Worker path = tgt_dir + "/" + tid + "/comm" 262*387f9dfdSAndroid Build Coastguard Worker fp = open(path, "r") 263*387f9dfdSAndroid Build Coastguard Worker comm = fp.read() 264*387f9dfdSAndroid Build Coastguard Worker if (comm.find(tgt_vcpu) != -1): 265*387f9dfdSAndroid Build Coastguard Worker return tid 266*387f9dfdSAndroid Build Coastguard Worker return -1 267*387f9dfdSAndroid Build Coastguard Worker 268*387f9dfdSAndroid Build Coastguard Worker# set process/thread filter 269*387f9dfdSAndroid Build Coastguard Workerthread_context = "" 270*387f9dfdSAndroid Build Coastguard Workerheader_format = "" 271*387f9dfdSAndroid Build Coastguard Workerneed_collapse = not args.alltids 272*387f9dfdSAndroid Build Coastguard Workerif args.tid is not None: 273*387f9dfdSAndroid Build Coastguard Worker thread_context = "TID %s" % args.tid 274*387f9dfdSAndroid Build Coastguard Worker thread_filter = 'pid != %s' % args.tid 275*387f9dfdSAndroid Build Coastguard Workerelif args.tids is not None: 276*387f9dfdSAndroid Build Coastguard Worker thread_context = "TIDS %s" % args.tids 277*387f9dfdSAndroid Build Coastguard Worker thread_filter = "pid != " + " && pid != ".join(args.tids) 278*387f9dfdSAndroid Build Coastguard Worker header_format = "TIDS " 279*387f9dfdSAndroid Build Coastguard Workerelif args.pid is not None: 280*387f9dfdSAndroid Build Coastguard Worker thread_context = "PID %s" % args.pid 281*387f9dfdSAndroid Build Coastguard Worker thread_filter = 'tgid != %s' % args.pid 282*387f9dfdSAndroid Build Coastguard Worker if args.vcpu is not None: 283*387f9dfdSAndroid Build Coastguard Worker thread_context = "PID %s VCPU %s" % (args.pid, args.vcpu) 284*387f9dfdSAndroid Build Coastguard Worker # transfer vcpu to tid 285*387f9dfdSAndroid Build Coastguard Worker tgt_dir = '/proc/' + str(args.pid) + '/task' 286*387f9dfdSAndroid Build Coastguard Worker tgt_vcpu = "CPU " + str(args.vcpu) 287*387f9dfdSAndroid Build Coastguard Worker args.tid = find_tid(tgt_dir, tgt_vcpu) 288*387f9dfdSAndroid Build Coastguard Worker if args.tid == -1: 289*387f9dfdSAndroid Build Coastguard Worker raise Exception("There's no v%s for PID %d." % (tgt_vcpu, args.pid)) 290*387f9dfdSAndroid Build Coastguard Worker thread_filter = 'pid != %s' % args.tid 291*387f9dfdSAndroid Build Coastguard Worker elif args.alltids: 292*387f9dfdSAndroid Build Coastguard Worker thread_context = "PID %s and its all threads" % args.pid 293*387f9dfdSAndroid Build Coastguard Worker header_format = "TID " 294*387f9dfdSAndroid Build Coastguard Workerelse: 295*387f9dfdSAndroid Build Coastguard Worker thread_context = "all threads" 296*387f9dfdSAndroid Build Coastguard Worker thread_filter = '0' 297*387f9dfdSAndroid Build Coastguard Worker header_format = "PID TID " 298*387f9dfdSAndroid Build Coastguard Workerbpf_text = bpf_text.replace('THREAD_FILTER', thread_filter) 299*387f9dfdSAndroid Build Coastguard Workerb = BPF(text=bpf_text) 300*387f9dfdSAndroid Build Coastguard Worker 301*387f9dfdSAndroid Build Coastguard Worker 302*387f9dfdSAndroid Build Coastguard Worker# header 303*387f9dfdSAndroid Build Coastguard Workerprint("Display kvm exit reasons and statistics for %s" % thread_context, end="") 304*387f9dfdSAndroid Build Coastguard Workerif duration < 99999999: 305*387f9dfdSAndroid Build Coastguard Worker print(" after sleeping %d secs." % duration) 306*387f9dfdSAndroid Build Coastguard Workerelse: 307*387f9dfdSAndroid Build Coastguard Worker print("... Hit Ctrl-C to end.") 308*387f9dfdSAndroid Build Coastguard Worker 309*387f9dfdSAndroid Build Coastguard Workertry: 310*387f9dfdSAndroid Build Coastguard Worker sleep(duration) 311*387f9dfdSAndroid Build Coastguard Workerexcept KeyboardInterrupt: 312*387f9dfdSAndroid Build Coastguard Worker print() 313*387f9dfdSAndroid Build Coastguard Worker 314*387f9dfdSAndroid Build Coastguard Worker 315*387f9dfdSAndroid Build Coastguard Worker# Currently, sort multiple tids in descending order is not supported. 316*387f9dfdSAndroid Build Coastguard Workerif (args.pid or args.tid): 317*387f9dfdSAndroid Build Coastguard Worker ct_reason = [] 318*387f9dfdSAndroid Build Coastguard Worker if args.pid: 319*387f9dfdSAndroid Build Coastguard Worker tgid_exit = [0 for i in range(len(exit_reasons))] 320*387f9dfdSAndroid Build Coastguard Worker 321*387f9dfdSAndroid Build Coastguard Worker# output 322*387f9dfdSAndroid Build Coastguard Workerprint("%s%-35s %s" % (header_format, "KVM_EXIT_REASON", "COUNT")) 323*387f9dfdSAndroid Build Coastguard Worker 324*387f9dfdSAndroid Build Coastguard Workerpcpu_kvm_stat = b["pcpu_kvm_stat"] 325*387f9dfdSAndroid Build Coastguard Workerpcpu_cache = b["pcpu_cache"] 326*387f9dfdSAndroid Build Coastguard Workerfor k, v in pcpu_kvm_stat.items(): 327*387f9dfdSAndroid Build Coastguard Worker tgid = k.value >> 32 328*387f9dfdSAndroid Build Coastguard Worker pid = k.value & 0xffffffff 329*387f9dfdSAndroid Build Coastguard Worker for i in range(0, len(exit_reasons)): 330*387f9dfdSAndroid Build Coastguard Worker sum1 = 0 331*387f9dfdSAndroid Build Coastguard Worker for inner_cpu in range(0, multiprocessing.cpu_count()): 332*387f9dfdSAndroid Build Coastguard Worker cachePIDTGID = pcpu_cache[0][inner_cpu].cache_pid_tgid 333*387f9dfdSAndroid Build Coastguard Worker # Take priority to check if it is in cache 334*387f9dfdSAndroid Build Coastguard Worker if cachePIDTGID == k.value: 335*387f9dfdSAndroid Build Coastguard Worker sum1 += pcpu_cache[0][inner_cpu].cache_exit_ct.exit_ct[i] 336*387f9dfdSAndroid Build Coastguard Worker # If not in cache, find from kvm_stat 337*387f9dfdSAndroid Build Coastguard Worker else: 338*387f9dfdSAndroid Build Coastguard Worker sum1 += v[inner_cpu].exit_ct[i] 339*387f9dfdSAndroid Build Coastguard Worker if sum1 == 0: 340*387f9dfdSAndroid Build Coastguard Worker continue 341*387f9dfdSAndroid Build Coastguard Worker 342*387f9dfdSAndroid Build Coastguard Worker if (args.pid and args.pid == tgid and need_collapse): 343*387f9dfdSAndroid Build Coastguard Worker tgid_exit[i] += sum1 344*387f9dfdSAndroid Build Coastguard Worker elif (args.tid and args.tid == pid): 345*387f9dfdSAndroid Build Coastguard Worker ct_reason.append((sum1, i)) 346*387f9dfdSAndroid Build Coastguard Worker elif not need_collapse or args.tids: 347*387f9dfdSAndroid Build Coastguard Worker print("%-8u %-35s %-8u" % (pid, exit_reasons[i], sum1)) 348*387f9dfdSAndroid Build Coastguard Worker else: 349*387f9dfdSAndroid Build Coastguard Worker print("%-8u %-8u %-35s %-8u" % (tgid, pid, exit_reasons[i], sum1)) 350*387f9dfdSAndroid Build Coastguard Worker 351*387f9dfdSAndroid Build Coastguard Worker # Display only for the target tid in descending sort 352*387f9dfdSAndroid Build Coastguard Worker if (args.tid and args.tid == pid): 353*387f9dfdSAndroid Build Coastguard Worker ct_reason.sort(reverse=True) 354*387f9dfdSAndroid Build Coastguard Worker for i in range(0, len(ct_reason)): 355*387f9dfdSAndroid Build Coastguard Worker if ct_reason[i][0] == 0: 356*387f9dfdSAndroid Build Coastguard Worker continue 357*387f9dfdSAndroid Build Coastguard Worker print("%-35s %-8u" % (exit_reasons[ct_reason[i][1]], ct_reason[i][0])) 358*387f9dfdSAndroid Build Coastguard Worker break 359*387f9dfdSAndroid Build Coastguard Worker 360*387f9dfdSAndroid Build Coastguard Worker 361*387f9dfdSAndroid Build Coastguard Worker# Aggregate all tids' counts for this args.pid in descending sort 362*387f9dfdSAndroid Build Coastguard Workerif args.pid and need_collapse: 363*387f9dfdSAndroid Build Coastguard Worker for i in range(0, len(exit_reasons)): 364*387f9dfdSAndroid Build Coastguard Worker ct_reason.append((tgid_exit[i], i)) 365*387f9dfdSAndroid Build Coastguard Worker ct_reason.sort(reverse=True) 366*387f9dfdSAndroid Build Coastguard Worker for i in range(0, len(ct_reason)): 367*387f9dfdSAndroid Build Coastguard Worker if ct_reason[i][0] == 0: 368*387f9dfdSAndroid Build Coastguard Worker continue 369*387f9dfdSAndroid Build Coastguard Worker print("%-35s %-8u" % (exit_reasons[ct_reason[i][1]], ct_reason[i][0])) 370