xref: /aosp_15_r20/external/bcc/tools/old/hardirqs.py (revision 387f9dfdfa2baef462e92476d413c7bc2470293e)
1*387f9dfdSAndroid Build Coastguard Worker#!/usr/bin/python
2*387f9dfdSAndroid Build Coastguard Worker# @lint-avoid-python-3-compatibility-imports
3*387f9dfdSAndroid Build Coastguard Worker#
4*387f9dfdSAndroid Build Coastguard Worker# hardirqs  Summarize hard IRQ (interrupt) event time.
5*387f9dfdSAndroid Build Coastguard Worker#           For Linux, uses BCC, eBPF.
6*387f9dfdSAndroid Build Coastguard Worker#
7*387f9dfdSAndroid Build Coastguard Worker# USAGE: hardirqs [-h] [-T] [-N] [-C] [-d] [interval] [outputs]
8*387f9dfdSAndroid Build Coastguard Worker#
9*387f9dfdSAndroid Build Coastguard Worker# Thanks Amer Ather for help understanding irq behavior.
10*387f9dfdSAndroid Build Coastguard Worker#
11*387f9dfdSAndroid Build Coastguard Worker# Copyright (c) 2015 Brendan Gregg.
12*387f9dfdSAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the "License")
13*387f9dfdSAndroid Build Coastguard Worker#
14*387f9dfdSAndroid Build Coastguard Worker# 19-Oct-2015   Brendan Gregg   Created this.
15*387f9dfdSAndroid Build Coastguard Worker
16*387f9dfdSAndroid Build Coastguard Workerfrom __future__ import print_function
17*387f9dfdSAndroid Build Coastguard Workerfrom bcc import BPF
18*387f9dfdSAndroid Build Coastguard Workerfrom time import sleep, strftime
19*387f9dfdSAndroid Build Coastguard Workerimport argparse
20*387f9dfdSAndroid Build Coastguard Worker
21*387f9dfdSAndroid Build Coastguard Worker# arguments
22*387f9dfdSAndroid Build Coastguard Workerexamples = """examples:
23*387f9dfdSAndroid Build Coastguard Worker    ./hardirqs            # sum hard irq event time
24*387f9dfdSAndroid Build Coastguard Worker    ./hardirqs -d         # show hard irq event time as histograms
25*387f9dfdSAndroid Build Coastguard Worker    ./hardirqs 1 10       # print 1 second summaries, 10 times
26*387f9dfdSAndroid Build Coastguard Worker    ./hardirqs -NT 1      # 1s summaries, nanoseconds, and timestamps
27*387f9dfdSAndroid Build Coastguard Worker"""
28*387f9dfdSAndroid Build Coastguard Workerparser = argparse.ArgumentParser(
29*387f9dfdSAndroid Build Coastguard Worker    description="Summarize hard irq event time as histograms",
30*387f9dfdSAndroid Build Coastguard Worker    formatter_class=argparse.RawDescriptionHelpFormatter,
31*387f9dfdSAndroid Build Coastguard Worker    epilog=examples)
32*387f9dfdSAndroid Build Coastguard Workerparser.add_argument("-T", "--timestamp", action="store_true",
33*387f9dfdSAndroid Build Coastguard Worker    help="include timestamp on output")
34*387f9dfdSAndroid Build Coastguard Workerparser.add_argument("-N", "--nanoseconds", action="store_true",
35*387f9dfdSAndroid Build Coastguard Worker    help="output in nanoseconds")
36*387f9dfdSAndroid Build Coastguard Workerparser.add_argument("-C", "--count", action="store_true",
37*387f9dfdSAndroid Build Coastguard Worker    help="show event counts instead of timing")
38*387f9dfdSAndroid Build Coastguard Workerparser.add_argument("-d", "--dist", action="store_true",
39*387f9dfdSAndroid Build Coastguard Worker    help="show distributions as histograms")
40*387f9dfdSAndroid Build Coastguard Workerparser.add_argument("interval", nargs="?", default=99999999,
41*387f9dfdSAndroid Build Coastguard Worker    help="output interval, in seconds")
42*387f9dfdSAndroid Build Coastguard Workerparser.add_argument("outputs", nargs="?", default=99999999,
43*387f9dfdSAndroid Build Coastguard Worker    help="number of outputs")
44*387f9dfdSAndroid Build Coastguard Workerparser.add_argument("--ebpf", action="store_true",
45*387f9dfdSAndroid Build Coastguard Worker    help=argparse.SUPPRESS)
46*387f9dfdSAndroid Build Coastguard Workerargs = parser.parse_args()
47*387f9dfdSAndroid Build Coastguard Workercountdown = int(args.outputs)
48*387f9dfdSAndroid Build Coastguard Workerif args.count and (args.dist or args.nanoseconds):
49*387f9dfdSAndroid Build Coastguard Worker    print("The --count option can't be used with time-based options")
50*387f9dfdSAndroid Build Coastguard Worker    exit()
51*387f9dfdSAndroid Build Coastguard Workerif args.count:
52*387f9dfdSAndroid Build Coastguard Worker    factor = 1
53*387f9dfdSAndroid Build Coastguard Worker    label = "count"
54*387f9dfdSAndroid Build Coastguard Workerelif args.nanoseconds:
55*387f9dfdSAndroid Build Coastguard Worker    factor = 1
56*387f9dfdSAndroid Build Coastguard Worker    label = "nsecs"
57*387f9dfdSAndroid Build Coastguard Workerelse:
58*387f9dfdSAndroid Build Coastguard Worker    factor = 1000
59*387f9dfdSAndroid Build Coastguard Worker    label = "usecs"
60*387f9dfdSAndroid Build Coastguard Workerdebug = 0
61*387f9dfdSAndroid Build Coastguard Worker
62*387f9dfdSAndroid Build Coastguard Worker# define BPF program
63*387f9dfdSAndroid Build Coastguard Workerbpf_text = """
64*387f9dfdSAndroid Build Coastguard Worker#include <uapi/linux/ptrace.h>
65*387f9dfdSAndroid Build Coastguard Worker#include <linux/irq.h>
66*387f9dfdSAndroid Build Coastguard Worker#include <linux/irqdesc.h>
67*387f9dfdSAndroid Build Coastguard Worker#include <linux/interrupt.h>
68*387f9dfdSAndroid Build Coastguard Worker
69*387f9dfdSAndroid Build Coastguard Workertypedef struct irq_key {
70*387f9dfdSAndroid Build Coastguard Worker    char name[32];
71*387f9dfdSAndroid Build Coastguard Worker    u64 slot;
72*387f9dfdSAndroid Build Coastguard Worker} irq_key_t;
73*387f9dfdSAndroid Build Coastguard WorkerBPF_HASH(start, u32);
74*387f9dfdSAndroid Build Coastguard WorkerBPF_HASH(irqdesc, u32, struct irq_desc *);
75*387f9dfdSAndroid Build Coastguard WorkerBPF_HISTOGRAM(dist, irq_key_t);
76*387f9dfdSAndroid Build Coastguard Worker
77*387f9dfdSAndroid Build Coastguard Worker// count IRQ
78*387f9dfdSAndroid Build Coastguard Workerint count_only(struct pt_regs *ctx, struct irq_desc *desc)
79*387f9dfdSAndroid Build Coastguard Worker{
80*387f9dfdSAndroid Build Coastguard Worker    u32 pid = bpf_get_current_pid_tgid();
81*387f9dfdSAndroid Build Coastguard Worker
82*387f9dfdSAndroid Build Coastguard Worker    struct irqaction *action = desc->action;
83*387f9dfdSAndroid Build Coastguard Worker    char *name = (char *)action->name;
84*387f9dfdSAndroid Build Coastguard Worker
85*387f9dfdSAndroid Build Coastguard Worker    irq_key_t key = {.slot = 0 /* ignore */};
86*387f9dfdSAndroid Build Coastguard Worker    bpf_probe_read_kernel(&key.name, sizeof(key.name), name);
87*387f9dfdSAndroid Build Coastguard Worker    dist.increment(key);
88*387f9dfdSAndroid Build Coastguard Worker
89*387f9dfdSAndroid Build Coastguard Worker    return 0;
90*387f9dfdSAndroid Build Coastguard Worker}
91*387f9dfdSAndroid Build Coastguard Worker
92*387f9dfdSAndroid Build Coastguard Worker// time IRQ
93*387f9dfdSAndroid Build Coastguard Workerint trace_start(struct pt_regs *ctx, struct irq_desc *desc)
94*387f9dfdSAndroid Build Coastguard Worker{
95*387f9dfdSAndroid Build Coastguard Worker    u32 pid = bpf_get_current_pid_tgid();
96*387f9dfdSAndroid Build Coastguard Worker    u64 ts = bpf_ktime_get_ns();
97*387f9dfdSAndroid Build Coastguard Worker    start.update(&pid, &ts);
98*387f9dfdSAndroid Build Coastguard Worker    irqdesc.update(&pid, &desc);
99*387f9dfdSAndroid Build Coastguard Worker    return 0;
100*387f9dfdSAndroid Build Coastguard Worker}
101*387f9dfdSAndroid Build Coastguard Worker
102*387f9dfdSAndroid Build Coastguard Workerint trace_completion(struct pt_regs *ctx)
103*387f9dfdSAndroid Build Coastguard Worker{
104*387f9dfdSAndroid Build Coastguard Worker    u64 *tsp, delta;
105*387f9dfdSAndroid Build Coastguard Worker    struct irq_desc **descp;
106*387f9dfdSAndroid Build Coastguard Worker    u32 pid = bpf_get_current_pid_tgid();
107*387f9dfdSAndroid Build Coastguard Worker
108*387f9dfdSAndroid Build Coastguard Worker    // fetch timestamp and calculate delta
109*387f9dfdSAndroid Build Coastguard Worker    tsp = start.lookup(&pid);
110*387f9dfdSAndroid Build Coastguard Worker    descp = irqdesc.lookup(&pid);
111*387f9dfdSAndroid Build Coastguard Worker    if (tsp == 0 || descp == 0) {
112*387f9dfdSAndroid Build Coastguard Worker        return 0;   // missed start
113*387f9dfdSAndroid Build Coastguard Worker    }
114*387f9dfdSAndroid Build Coastguard Worker    struct irq_desc *desc = *descp;
115*387f9dfdSAndroid Build Coastguard Worker    struct irqaction *action = desc->action;
116*387f9dfdSAndroid Build Coastguard Worker    char *name = (char *)action->name;
117*387f9dfdSAndroid Build Coastguard Worker    delta = bpf_ktime_get_ns() - *tsp;
118*387f9dfdSAndroid Build Coastguard Worker
119*387f9dfdSAndroid Build Coastguard Worker    // store as sum or histogram
120*387f9dfdSAndroid Build Coastguard Worker    STORE
121*387f9dfdSAndroid Build Coastguard Worker
122*387f9dfdSAndroid Build Coastguard Worker    start.delete(&pid);
123*387f9dfdSAndroid Build Coastguard Worker    irqdesc.delete(&pid);
124*387f9dfdSAndroid Build Coastguard Worker    return 0;
125*387f9dfdSAndroid Build Coastguard Worker}
126*387f9dfdSAndroid Build Coastguard Worker"""
127*387f9dfdSAndroid Build Coastguard Worker
128*387f9dfdSAndroid Build Coastguard Worker# code substitutions
129*387f9dfdSAndroid Build Coastguard Workerif args.dist:
130*387f9dfdSAndroid Build Coastguard Worker    bpf_text = bpf_text.replace('STORE',
131*387f9dfdSAndroid Build Coastguard Worker        'irq_key_t key = {.slot = bpf_log2l(delta / %d)};' % factor +
132*387f9dfdSAndroid Build Coastguard Worker        'bpf_probe_read_kernel(&key.name, sizeof(key.name), name);' +
133*387f9dfdSAndroid Build Coastguard Worker        'dist.increment(key);')
134*387f9dfdSAndroid Build Coastguard Workerelse:
135*387f9dfdSAndroid Build Coastguard Worker    bpf_text = bpf_text.replace('STORE',
136*387f9dfdSAndroid Build Coastguard Worker        'irq_key_t key = {.slot = 0 /* ignore */};' +
137*387f9dfdSAndroid Build Coastguard Worker        'bpf_probe_read_kernel(&key.name, sizeof(key.name), name);' +
138*387f9dfdSAndroid Build Coastguard Worker        'dist.increment(key, delta);')
139*387f9dfdSAndroid Build Coastguard Workerif debug or args.ebpf:
140*387f9dfdSAndroid Build Coastguard Worker    print(bpf_text)
141*387f9dfdSAndroid Build Coastguard Worker    if args.ebpf:
142*387f9dfdSAndroid Build Coastguard Worker        exit()
143*387f9dfdSAndroid Build Coastguard Worker
144*387f9dfdSAndroid Build Coastguard Worker# load BPF program
145*387f9dfdSAndroid Build Coastguard Workerb = BPF(text=bpf_text)
146*387f9dfdSAndroid Build Coastguard Worker
147*387f9dfdSAndroid Build Coastguard Worker# these should really use irq:irq_handler_entry/exit tracepoints:
148*387f9dfdSAndroid Build Coastguard Workerif args.count:
149*387f9dfdSAndroid Build Coastguard Worker    b.attach_kprobe(event="handle_irq_event_percpu", fn_name="count_only")
150*387f9dfdSAndroid Build Coastguard Worker    print("Tracing hard irq events... Hit Ctrl-C to end.")
151*387f9dfdSAndroid Build Coastguard Workerelse:
152*387f9dfdSAndroid Build Coastguard Worker    b.attach_kprobe(event="handle_irq_event_percpu", fn_name="trace_start")
153*387f9dfdSAndroid Build Coastguard Worker    b.attach_kretprobe(event="handle_irq_event_percpu",
154*387f9dfdSAndroid Build Coastguard Worker        fn_name="trace_completion")
155*387f9dfdSAndroid Build Coastguard Worker    print("Tracing hard irq event time... Hit Ctrl-C to end.")
156*387f9dfdSAndroid Build Coastguard Worker
157*387f9dfdSAndroid Build Coastguard Worker# output
158*387f9dfdSAndroid Build Coastguard Workerexiting = 0 if args.interval else 1
159*387f9dfdSAndroid Build Coastguard Workerdist = b.get_table("dist")
160*387f9dfdSAndroid Build Coastguard Workerwhile (1):
161*387f9dfdSAndroid Build Coastguard Worker    try:
162*387f9dfdSAndroid Build Coastguard Worker        sleep(int(args.interval))
163*387f9dfdSAndroid Build Coastguard Worker    except KeyboardInterrupt:
164*387f9dfdSAndroid Build Coastguard Worker        exiting = 1
165*387f9dfdSAndroid Build Coastguard Worker
166*387f9dfdSAndroid Build Coastguard Worker    print()
167*387f9dfdSAndroid Build Coastguard Worker    if args.timestamp:
168*387f9dfdSAndroid Build Coastguard Worker        print("%-8s\n" % strftime("%H:%M:%S"), end="")
169*387f9dfdSAndroid Build Coastguard Worker
170*387f9dfdSAndroid Build Coastguard Worker    if args.dist:
171*387f9dfdSAndroid Build Coastguard Worker        dist.print_log2_hist(label, "hardirq")
172*387f9dfdSAndroid Build Coastguard Worker    else:
173*387f9dfdSAndroid Build Coastguard Worker        print("%-26s %11s" % ("HARDIRQ", "TOTAL_" + label))
174*387f9dfdSAndroid Build Coastguard Worker        for k, v in sorted(dist.items(), key=lambda dist: dist[1].value):
175*387f9dfdSAndroid Build Coastguard Worker            print("%-26s %11d" % (k.name.decode('utf-8', 'replace'), v.value / factor))
176*387f9dfdSAndroid Build Coastguard Worker    dist.clear()
177*387f9dfdSAndroid Build Coastguard Worker
178*387f9dfdSAndroid Build Coastguard Worker    countdown -= 1
179*387f9dfdSAndroid Build Coastguard Worker    if exiting or countdown == 0:
180*387f9dfdSAndroid Build Coastguard Worker        exit()
181