1*387f9dfdSAndroid Build Coastguard Worker // SPDX-License-Identifier: GPL-2.0
2*387f9dfdSAndroid Build Coastguard Worker // Copyright (c) 2020 Anton Protopopov
3*387f9dfdSAndroid Build Coastguard Worker //
4*387f9dfdSAndroid Build Coastguard Worker // Based on syscount(8) from BCC by Sasha Goldshtein
5*387f9dfdSAndroid Build Coastguard Worker #include <vmlinux.h>
6*387f9dfdSAndroid Build Coastguard Worker #include <bpf/bpf_helpers.h>
7*387f9dfdSAndroid Build Coastguard Worker #include <bpf/bpf_tracing.h>
8*387f9dfdSAndroid Build Coastguard Worker #include <bpf/bpf_core_read.h>
9*387f9dfdSAndroid Build Coastguard Worker #include "syscount.h"
10*387f9dfdSAndroid Build Coastguard Worker #include "maps.bpf.h"
11*387f9dfdSAndroid Build Coastguard Worker
12*387f9dfdSAndroid Build Coastguard Worker const volatile bool filter_cg = false;
13*387f9dfdSAndroid Build Coastguard Worker const volatile bool count_by_process = false;
14*387f9dfdSAndroid Build Coastguard Worker const volatile bool measure_latency = false;
15*387f9dfdSAndroid Build Coastguard Worker const volatile bool filter_failed = false;
16*387f9dfdSAndroid Build Coastguard Worker const volatile int filter_errno = false;
17*387f9dfdSAndroid Build Coastguard Worker const volatile pid_t filter_pid = 0;
18*387f9dfdSAndroid Build Coastguard Worker
19*387f9dfdSAndroid Build Coastguard Worker struct {
20*387f9dfdSAndroid Build Coastguard Worker __uint(type, BPF_MAP_TYPE_CGROUP_ARRAY);
21*387f9dfdSAndroid Build Coastguard Worker __type(key, u32);
22*387f9dfdSAndroid Build Coastguard Worker __type(value, u32);
23*387f9dfdSAndroid Build Coastguard Worker __uint(max_entries, 1);
24*387f9dfdSAndroid Build Coastguard Worker } cgroup_map SEC(".maps");
25*387f9dfdSAndroid Build Coastguard Worker
26*387f9dfdSAndroid Build Coastguard Worker struct {
27*387f9dfdSAndroid Build Coastguard Worker __uint(type, BPF_MAP_TYPE_HASH);
28*387f9dfdSAndroid Build Coastguard Worker __uint(max_entries, MAX_ENTRIES);
29*387f9dfdSAndroid Build Coastguard Worker __type(key, u32);
30*387f9dfdSAndroid Build Coastguard Worker __type(value, u64);
31*387f9dfdSAndroid Build Coastguard Worker } start SEC(".maps");
32*387f9dfdSAndroid Build Coastguard Worker
33*387f9dfdSAndroid Build Coastguard Worker struct {
34*387f9dfdSAndroid Build Coastguard Worker __uint(type, BPF_MAP_TYPE_HASH);
35*387f9dfdSAndroid Build Coastguard Worker __uint(max_entries, MAX_ENTRIES);
36*387f9dfdSAndroid Build Coastguard Worker __type(key, u32);
37*387f9dfdSAndroid Build Coastguard Worker __type(value, struct data_t);
38*387f9dfdSAndroid Build Coastguard Worker } data SEC(".maps");
39*387f9dfdSAndroid Build Coastguard Worker
40*387f9dfdSAndroid Build Coastguard Worker static __always_inline
save_proc_name(struct data_t * val)41*387f9dfdSAndroid Build Coastguard Worker void save_proc_name(struct data_t *val)
42*387f9dfdSAndroid Build Coastguard Worker {
43*387f9dfdSAndroid Build Coastguard Worker struct task_struct *current = (void *)bpf_get_current_task();
44*387f9dfdSAndroid Build Coastguard Worker
45*387f9dfdSAndroid Build Coastguard Worker /* We should save the process name every time because it can be
46*387f9dfdSAndroid Build Coastguard Worker * changed (e.g., by exec). This can be optimized later by managing
47*387f9dfdSAndroid Build Coastguard Worker * this field with the help of tp/sched/sched_process_exec and
48*387f9dfdSAndroid Build Coastguard Worker * raw_tp/task_rename. */
49*387f9dfdSAndroid Build Coastguard Worker BPF_CORE_READ_STR_INTO(&val->comm, current, group_leader, comm);
50*387f9dfdSAndroid Build Coastguard Worker }
51*387f9dfdSAndroid Build Coastguard Worker
52*387f9dfdSAndroid Build Coastguard Worker SEC("tracepoint/raw_syscalls/sys_enter")
sys_enter(struct trace_event_raw_sys_enter * args)53*387f9dfdSAndroid Build Coastguard Worker int sys_enter(struct trace_event_raw_sys_enter *args)
54*387f9dfdSAndroid Build Coastguard Worker {
55*387f9dfdSAndroid Build Coastguard Worker u64 id = bpf_get_current_pid_tgid();
56*387f9dfdSAndroid Build Coastguard Worker pid_t pid = id >> 32;
57*387f9dfdSAndroid Build Coastguard Worker u32 tid = id;
58*387f9dfdSAndroid Build Coastguard Worker u64 ts;
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 if (filter_pid && pid != filter_pid)
64*387f9dfdSAndroid Build Coastguard Worker return 0;
65*387f9dfdSAndroid Build Coastguard Worker
66*387f9dfdSAndroid Build Coastguard Worker ts = bpf_ktime_get_ns();
67*387f9dfdSAndroid Build Coastguard Worker bpf_map_update_elem(&start, &tid, &ts, 0);
68*387f9dfdSAndroid Build Coastguard Worker return 0;
69*387f9dfdSAndroid Build Coastguard Worker }
70*387f9dfdSAndroid Build Coastguard Worker
71*387f9dfdSAndroid Build Coastguard Worker SEC("tracepoint/raw_syscalls/sys_exit")
sys_exit(struct trace_event_raw_sys_exit * args)72*387f9dfdSAndroid Build Coastguard Worker int sys_exit(struct trace_event_raw_sys_exit *args)
73*387f9dfdSAndroid Build Coastguard Worker {
74*387f9dfdSAndroid Build Coastguard Worker if (filter_cg && !bpf_current_task_under_cgroup(&cgroup_map, 0))
75*387f9dfdSAndroid Build Coastguard Worker return 0;
76*387f9dfdSAndroid Build Coastguard Worker
77*387f9dfdSAndroid Build Coastguard Worker u64 id = bpf_get_current_pid_tgid();
78*387f9dfdSAndroid Build Coastguard Worker static const struct data_t zero;
79*387f9dfdSAndroid Build Coastguard Worker pid_t pid = id >> 32;
80*387f9dfdSAndroid Build Coastguard Worker struct data_t *val;
81*387f9dfdSAndroid Build Coastguard Worker u64 *start_ts, lat = 0;
82*387f9dfdSAndroid Build Coastguard Worker u32 tid = id;
83*387f9dfdSAndroid Build Coastguard Worker u32 key;
84*387f9dfdSAndroid Build Coastguard Worker
85*387f9dfdSAndroid Build Coastguard Worker /* this happens when there is an interrupt */
86*387f9dfdSAndroid Build Coastguard Worker if (args->id == -1)
87*387f9dfdSAndroid Build Coastguard Worker return 0;
88*387f9dfdSAndroid Build Coastguard Worker
89*387f9dfdSAndroid Build Coastguard Worker if (filter_pid && pid != filter_pid)
90*387f9dfdSAndroid Build Coastguard Worker return 0;
91*387f9dfdSAndroid Build Coastguard Worker if (filter_failed && args->ret >= 0)
92*387f9dfdSAndroid Build Coastguard Worker return 0;
93*387f9dfdSAndroid Build Coastguard Worker if (filter_errno && args->ret != -filter_errno)
94*387f9dfdSAndroid Build Coastguard Worker return 0;
95*387f9dfdSAndroid Build Coastguard Worker
96*387f9dfdSAndroid Build Coastguard Worker if (measure_latency) {
97*387f9dfdSAndroid Build Coastguard Worker start_ts = bpf_map_lookup_elem(&start, &tid);
98*387f9dfdSAndroid Build Coastguard Worker if (!start_ts)
99*387f9dfdSAndroid Build Coastguard Worker return 0;
100*387f9dfdSAndroid Build Coastguard Worker lat = bpf_ktime_get_ns() - *start_ts;
101*387f9dfdSAndroid Build Coastguard Worker }
102*387f9dfdSAndroid Build Coastguard Worker
103*387f9dfdSAndroid Build Coastguard Worker key = (count_by_process) ? pid : args->id;
104*387f9dfdSAndroid Build Coastguard Worker val = bpf_map_lookup_or_try_init(&data, &key, &zero);
105*387f9dfdSAndroid Build Coastguard Worker if (val) {
106*387f9dfdSAndroid Build Coastguard Worker __sync_fetch_and_add(&val->count, 1);
107*387f9dfdSAndroid Build Coastguard Worker if (count_by_process)
108*387f9dfdSAndroid Build Coastguard Worker save_proc_name(val);
109*387f9dfdSAndroid Build Coastguard Worker if (measure_latency)
110*387f9dfdSAndroid Build Coastguard Worker __sync_fetch_and_add(&val->total_ns, lat);
111*387f9dfdSAndroid Build Coastguard Worker }
112*387f9dfdSAndroid Build Coastguard Worker return 0;
113*387f9dfdSAndroid Build Coastguard Worker }
114*387f9dfdSAndroid Build Coastguard Worker
115*387f9dfdSAndroid Build Coastguard Worker char LICENSE[] SEC("license") = "GPL";
116