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