xref: /aosp_15_r20/external/bcc/tools/kvmexit.py (revision 387f9dfdfa2baef462e92476d413c7bc2470293e)
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