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