xref: /aosp_15_r20/external/bcc/libbpf-tools/hardirqs.bpf.c (revision 387f9dfdfa2baef462e92476d413c7bc2470293e)
1*387f9dfdSAndroid Build Coastguard Worker // SPDX-License-Identifier: GPL-2.0
2*387f9dfdSAndroid Build Coastguard Worker // Copyright (c) 2020 Wenbo Zhang
3*387f9dfdSAndroid Build Coastguard Worker #include <vmlinux.h>
4*387f9dfdSAndroid Build Coastguard Worker #include <bpf/bpf_core_read.h>
5*387f9dfdSAndroid Build Coastguard Worker #include <bpf/bpf_helpers.h>
6*387f9dfdSAndroid Build Coastguard Worker #include <bpf/bpf_tracing.h>
7*387f9dfdSAndroid Build Coastguard Worker #include "hardirqs.h"
8*387f9dfdSAndroid Build Coastguard Worker #include "bits.bpf.h"
9*387f9dfdSAndroid Build Coastguard Worker #include "maps.bpf.h"
10*387f9dfdSAndroid Build Coastguard Worker 
11*387f9dfdSAndroid Build Coastguard Worker #define MAX_ENTRIES	256
12*387f9dfdSAndroid Build Coastguard Worker 
13*387f9dfdSAndroid Build Coastguard Worker const volatile bool filter_cg = false;
14*387f9dfdSAndroid Build Coastguard Worker const volatile bool targ_dist = false;
15*387f9dfdSAndroid Build Coastguard Worker const volatile bool targ_ns = false;
16*387f9dfdSAndroid Build Coastguard Worker const volatile bool do_count = false;
17*387f9dfdSAndroid Build Coastguard Worker 
18*387f9dfdSAndroid Build Coastguard Worker struct {
19*387f9dfdSAndroid Build Coastguard Worker 	__uint(type, BPF_MAP_TYPE_CGROUP_ARRAY);
20*387f9dfdSAndroid Build Coastguard Worker 	__type(key, u32);
21*387f9dfdSAndroid Build Coastguard Worker 	__type(value, u32);
22*387f9dfdSAndroid Build Coastguard Worker 	__uint(max_entries, 1);
23*387f9dfdSAndroid Build Coastguard Worker } cgroup_map SEC(".maps");
24*387f9dfdSAndroid Build Coastguard Worker 
25*387f9dfdSAndroid Build Coastguard Worker struct {
26*387f9dfdSAndroid Build Coastguard Worker 	__uint(type, BPF_MAP_TYPE_PERCPU_ARRAY);
27*387f9dfdSAndroid Build Coastguard Worker 	__uint(max_entries, 1);
28*387f9dfdSAndroid Build Coastguard Worker 	__type(key, u32);
29*387f9dfdSAndroid Build Coastguard Worker 	__type(value, u64);
30*387f9dfdSAndroid Build Coastguard Worker } start SEC(".maps");
31*387f9dfdSAndroid Build Coastguard Worker 
32*387f9dfdSAndroid Build Coastguard Worker struct {
33*387f9dfdSAndroid Build Coastguard Worker 	__uint(type, BPF_MAP_TYPE_HASH);
34*387f9dfdSAndroid Build Coastguard Worker 	__uint(max_entries, MAX_ENTRIES);
35*387f9dfdSAndroid Build Coastguard Worker 	__type(key, struct irq_key);
36*387f9dfdSAndroid Build Coastguard Worker 	__type(value, struct info);
37*387f9dfdSAndroid Build Coastguard Worker } infos SEC(".maps");
38*387f9dfdSAndroid Build Coastguard Worker 
39*387f9dfdSAndroid Build Coastguard Worker static struct info zero;
40*387f9dfdSAndroid Build Coastguard Worker 
handle_entry(int irq,struct irqaction * action)41*387f9dfdSAndroid Build Coastguard Worker static int handle_entry(int irq, struct irqaction *action)
42*387f9dfdSAndroid Build Coastguard Worker {
43*387f9dfdSAndroid Build Coastguard Worker 	if (filter_cg && !bpf_current_task_under_cgroup(&cgroup_map, 0))
44*387f9dfdSAndroid Build Coastguard Worker 		return 0;
45*387f9dfdSAndroid Build Coastguard Worker 
46*387f9dfdSAndroid Build Coastguard Worker 	if (do_count) {
47*387f9dfdSAndroid Build Coastguard Worker 		struct irq_key key = {};
48*387f9dfdSAndroid Build Coastguard Worker 		struct info *info;
49*387f9dfdSAndroid Build Coastguard Worker 
50*387f9dfdSAndroid Build Coastguard Worker 		bpf_probe_read_kernel_str(&key.name, sizeof(key.name), BPF_CORE_READ(action, name));
51*387f9dfdSAndroid Build Coastguard Worker 		info = bpf_map_lookup_or_try_init(&infos, &key, &zero);
52*387f9dfdSAndroid Build Coastguard Worker 		if (!info)
53*387f9dfdSAndroid Build Coastguard Worker 			return 0;
54*387f9dfdSAndroid Build Coastguard Worker 		info->count += 1;
55*387f9dfdSAndroid Build Coastguard Worker 		return 0;
56*387f9dfdSAndroid Build Coastguard Worker 	} else {
57*387f9dfdSAndroid Build Coastguard Worker 		u64 ts = bpf_ktime_get_ns();
58*387f9dfdSAndroid Build Coastguard Worker 		u32 key = 0;
59*387f9dfdSAndroid Build Coastguard Worker 
60*387f9dfdSAndroid Build Coastguard Worker 		if (filter_cg && !bpf_current_task_under_cgroup(&cgroup_map, 0))
61*387f9dfdSAndroid Build Coastguard Worker 			return 0;
62*387f9dfdSAndroid Build Coastguard Worker 
63*387f9dfdSAndroid Build Coastguard Worker 		bpf_map_update_elem(&start, &key, &ts, BPF_ANY);
64*387f9dfdSAndroid Build Coastguard Worker 		return 0;
65*387f9dfdSAndroid Build Coastguard Worker 	}
66*387f9dfdSAndroid Build Coastguard Worker }
67*387f9dfdSAndroid Build Coastguard Worker 
handle_exit(int irq,struct irqaction * action)68*387f9dfdSAndroid Build Coastguard Worker static int handle_exit(int irq, struct irqaction *action)
69*387f9dfdSAndroid Build Coastguard Worker {
70*387f9dfdSAndroid Build Coastguard Worker 	struct irq_key ikey = {};
71*387f9dfdSAndroid Build Coastguard Worker 	struct info *info;
72*387f9dfdSAndroid Build Coastguard Worker 	u32 key = 0;
73*387f9dfdSAndroid Build Coastguard Worker 	u64 delta;
74*387f9dfdSAndroid Build Coastguard Worker 	u64 *tsp;
75*387f9dfdSAndroid Build Coastguard Worker 
76*387f9dfdSAndroid Build Coastguard Worker 	if (filter_cg && !bpf_current_task_under_cgroup(&cgroup_map, 0))
77*387f9dfdSAndroid Build Coastguard Worker 		return 0;
78*387f9dfdSAndroid Build Coastguard Worker 
79*387f9dfdSAndroid Build Coastguard Worker 	tsp = bpf_map_lookup_elem(&start, &key);
80*387f9dfdSAndroid Build Coastguard Worker 	if (!tsp)
81*387f9dfdSAndroid Build Coastguard Worker 		return 0;
82*387f9dfdSAndroid Build Coastguard Worker 
83*387f9dfdSAndroid Build Coastguard Worker 	delta = bpf_ktime_get_ns() - *tsp;
84*387f9dfdSAndroid Build Coastguard Worker 	if (!targ_ns)
85*387f9dfdSAndroid Build Coastguard Worker 		delta /= 1000U;
86*387f9dfdSAndroid Build Coastguard Worker 
87*387f9dfdSAndroid Build Coastguard Worker 	bpf_probe_read_kernel_str(&ikey.name, sizeof(ikey.name), BPF_CORE_READ(action, name));
88*387f9dfdSAndroid Build Coastguard Worker 	info = bpf_map_lookup_or_try_init(&infos, &ikey, &zero);
89*387f9dfdSAndroid Build Coastguard Worker 	if (!info)
90*387f9dfdSAndroid Build Coastguard Worker 		return 0;
91*387f9dfdSAndroid Build Coastguard Worker 
92*387f9dfdSAndroid Build Coastguard Worker 	if (!targ_dist) {
93*387f9dfdSAndroid Build Coastguard Worker 		info->count += delta;
94*387f9dfdSAndroid Build Coastguard Worker 	} else {
95*387f9dfdSAndroid Build Coastguard Worker 		u64 slot;
96*387f9dfdSAndroid Build Coastguard Worker 
97*387f9dfdSAndroid Build Coastguard Worker 		slot = log2(delta);
98*387f9dfdSAndroid Build Coastguard Worker 		if (slot >= MAX_SLOTS)
99*387f9dfdSAndroid Build Coastguard Worker 			slot = MAX_SLOTS - 1;
100*387f9dfdSAndroid Build Coastguard Worker 		info->slots[slot]++;
101*387f9dfdSAndroid Build Coastguard Worker 	}
102*387f9dfdSAndroid Build Coastguard Worker 
103*387f9dfdSAndroid Build Coastguard Worker 	return 0;
104*387f9dfdSAndroid Build Coastguard Worker }
105*387f9dfdSAndroid Build Coastguard Worker 
106*387f9dfdSAndroid Build Coastguard Worker SEC("tp_btf/irq_handler_entry")
BPF_PROG(irq_handler_entry_btf,int irq,struct irqaction * action)107*387f9dfdSAndroid Build Coastguard Worker int BPF_PROG(irq_handler_entry_btf, int irq, struct irqaction *action)
108*387f9dfdSAndroid Build Coastguard Worker {
109*387f9dfdSAndroid Build Coastguard Worker 	return handle_entry(irq, action);
110*387f9dfdSAndroid Build Coastguard Worker }
111*387f9dfdSAndroid Build Coastguard Worker 
112*387f9dfdSAndroid Build Coastguard Worker SEC("tp_btf/irq_handler_exit")
BPF_PROG(irq_handler_exit_btf,int irq,struct irqaction * action)113*387f9dfdSAndroid Build Coastguard Worker int BPF_PROG(irq_handler_exit_btf, int irq, struct irqaction *action)
114*387f9dfdSAndroid Build Coastguard Worker {
115*387f9dfdSAndroid Build Coastguard Worker 	return handle_exit(irq, action);
116*387f9dfdSAndroid Build Coastguard Worker }
117*387f9dfdSAndroid Build Coastguard Worker 
118*387f9dfdSAndroid Build Coastguard Worker SEC("raw_tp/irq_handler_entry")
BPF_PROG(irq_handler_entry,int irq,struct irqaction * action)119*387f9dfdSAndroid Build Coastguard Worker int BPF_PROG(irq_handler_entry, int irq, struct irqaction *action)
120*387f9dfdSAndroid Build Coastguard Worker {
121*387f9dfdSAndroid Build Coastguard Worker 	return handle_entry(irq, action);
122*387f9dfdSAndroid Build Coastguard Worker }
123*387f9dfdSAndroid Build Coastguard Worker 
124*387f9dfdSAndroid Build Coastguard Worker SEC("raw_tp/irq_handler_exit")
BPF_PROG(irq_handler_exit,int irq,struct irqaction * action)125*387f9dfdSAndroid Build Coastguard Worker int BPF_PROG(irq_handler_exit, int irq, struct irqaction *action)
126*387f9dfdSAndroid Build Coastguard Worker {
127*387f9dfdSAndroid Build Coastguard Worker 	return handle_exit(irq, action);
128*387f9dfdSAndroid Build Coastguard Worker }
129*387f9dfdSAndroid Build Coastguard Worker 
130*387f9dfdSAndroid Build Coastguard Worker char LICENSE[] SEC("license") = "GPL";
131