1 // SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
2 // Copyright (c) 2021 Facebook
3 #include <linux/bpf.h>
4 #include <linux/perf_event.h>
5 #include <bpf/bpf_helpers.h>
6 #include <bpf/bpf_tracing.h>
7 #include "bperf_u.h"
8
9 struct {
10 __uint(type, BPF_MAP_TYPE_PERCPU_ARRAY);
11 __uint(key_size, sizeof(__u32));
12 __uint(value_size, sizeof(struct bpf_perf_event_value));
13 __uint(max_entries, 1);
14 } diff_readings SEC(".maps");
15
16 struct {
17 __uint(type, BPF_MAP_TYPE_PERCPU_ARRAY);
18 __uint(key_size, sizeof(__u32));
19 __uint(value_size, sizeof(struct bpf_perf_event_value));
20 __uint(max_entries, 1);
21 } accum_readings SEC(".maps");
22
23 struct {
24 __uint(type, BPF_MAP_TYPE_HASH);
25 __uint(key_size, sizeof(__u32));
26 __uint(value_size, sizeof(__u32));
27 } filter SEC(".maps");
28
29 enum bperf_filter_type type = 0;
30 int enabled = 0;
31
32 SEC("fexit/XXX")
BPF_PROG(fexit_XXX)33 int BPF_PROG(fexit_XXX)
34 {
35 struct bpf_perf_event_value *diff_val, *accum_val;
36 __u32 filter_key, zero = 0;
37 __u32 *accum_key;
38
39 if (!enabled)
40 return 0;
41
42 switch (type) {
43 case BPERF_FILTER_GLOBAL:
44 accum_key = &zero;
45 goto do_add;
46 case BPERF_FILTER_CPU:
47 filter_key = bpf_get_smp_processor_id();
48 break;
49 case BPERF_FILTER_PID:
50 filter_key = bpf_get_current_pid_tgid() & 0xffffffff;
51 break;
52 case BPERF_FILTER_TGID:
53 filter_key = bpf_get_current_pid_tgid() >> 32;
54 break;
55 default:
56 return 0;
57 }
58
59 accum_key = bpf_map_lookup_elem(&filter, &filter_key);
60 if (!accum_key)
61 return 0;
62
63 do_add:
64 diff_val = bpf_map_lookup_elem(&diff_readings, &zero);
65 if (!diff_val)
66 return 0;
67
68 accum_val = bpf_map_lookup_elem(&accum_readings, accum_key);
69 if (!accum_val)
70 return 0;
71
72 accum_val->counter += diff_val->counter;
73 accum_val->enabled += diff_val->enabled;
74 accum_val->running += diff_val->running;
75
76 return 0;
77 }
78
79 char LICENSE[] SEC("license") = "Dual BSD/GPL";
80