162306a36Sopenharmony_ci// SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
262306a36Sopenharmony_ci// Copyright (c) 2021 Facebook
362306a36Sopenharmony_ci#include "vmlinux.h"
462306a36Sopenharmony_ci#include <bpf/bpf_helpers.h>
562306a36Sopenharmony_ci#include <bpf/bpf_tracing.h>
662306a36Sopenharmony_ci#include "bperf_u.h"
762306a36Sopenharmony_ci
862306a36Sopenharmony_cistruct {
962306a36Sopenharmony_ci	__uint(type, BPF_MAP_TYPE_PERCPU_ARRAY);
1062306a36Sopenharmony_ci	__uint(key_size, sizeof(__u32));
1162306a36Sopenharmony_ci	__uint(value_size, sizeof(struct bpf_perf_event_value));
1262306a36Sopenharmony_ci	__uint(max_entries, 1);
1362306a36Sopenharmony_ci} diff_readings SEC(".maps");
1462306a36Sopenharmony_ci
1562306a36Sopenharmony_cistruct {
1662306a36Sopenharmony_ci	__uint(type, BPF_MAP_TYPE_PERCPU_ARRAY);
1762306a36Sopenharmony_ci	__uint(key_size, sizeof(__u32));
1862306a36Sopenharmony_ci	__uint(value_size, sizeof(struct bpf_perf_event_value));
1962306a36Sopenharmony_ci	__uint(max_entries, 1);
2062306a36Sopenharmony_ci} accum_readings SEC(".maps");
2162306a36Sopenharmony_ci
2262306a36Sopenharmony_cistruct {
2362306a36Sopenharmony_ci	__uint(type, BPF_MAP_TYPE_HASH);
2462306a36Sopenharmony_ci	__uint(key_size, sizeof(__u32));
2562306a36Sopenharmony_ci	__uint(value_size, sizeof(__u32));
2662306a36Sopenharmony_ci} filter SEC(".maps");
2762306a36Sopenharmony_ci
2862306a36Sopenharmony_cienum bperf_filter_type type = 0;
2962306a36Sopenharmony_ciint enabled = 0;
3062306a36Sopenharmony_ci
3162306a36Sopenharmony_ciSEC("fexit/XXX")
3262306a36Sopenharmony_ciint BPF_PROG(fexit_XXX)
3362306a36Sopenharmony_ci{
3462306a36Sopenharmony_ci	struct bpf_perf_event_value *diff_val, *accum_val;
3562306a36Sopenharmony_ci	__u32 filter_key, zero = 0;
3662306a36Sopenharmony_ci	__u32 *accum_key;
3762306a36Sopenharmony_ci
3862306a36Sopenharmony_ci	if (!enabled)
3962306a36Sopenharmony_ci		return 0;
4062306a36Sopenharmony_ci
4162306a36Sopenharmony_ci	switch (type) {
4262306a36Sopenharmony_ci	case BPERF_FILTER_GLOBAL:
4362306a36Sopenharmony_ci		accum_key = &zero;
4462306a36Sopenharmony_ci		goto do_add;
4562306a36Sopenharmony_ci	case BPERF_FILTER_CPU:
4662306a36Sopenharmony_ci		filter_key = bpf_get_smp_processor_id();
4762306a36Sopenharmony_ci		break;
4862306a36Sopenharmony_ci	case BPERF_FILTER_PID:
4962306a36Sopenharmony_ci		filter_key = bpf_get_current_pid_tgid() & 0xffffffff;
5062306a36Sopenharmony_ci		break;
5162306a36Sopenharmony_ci	case BPERF_FILTER_TGID:
5262306a36Sopenharmony_ci		filter_key = bpf_get_current_pid_tgid() >> 32;
5362306a36Sopenharmony_ci		break;
5462306a36Sopenharmony_ci	default:
5562306a36Sopenharmony_ci		return 0;
5662306a36Sopenharmony_ci	}
5762306a36Sopenharmony_ci
5862306a36Sopenharmony_ci	accum_key = bpf_map_lookup_elem(&filter, &filter_key);
5962306a36Sopenharmony_ci	if (!accum_key)
6062306a36Sopenharmony_ci		return 0;
6162306a36Sopenharmony_ci
6262306a36Sopenharmony_cido_add:
6362306a36Sopenharmony_ci	diff_val = bpf_map_lookup_elem(&diff_readings, &zero);
6462306a36Sopenharmony_ci	if (!diff_val)
6562306a36Sopenharmony_ci		return 0;
6662306a36Sopenharmony_ci
6762306a36Sopenharmony_ci	accum_val = bpf_map_lookup_elem(&accum_readings, accum_key);
6862306a36Sopenharmony_ci	if (!accum_val)
6962306a36Sopenharmony_ci		return 0;
7062306a36Sopenharmony_ci
7162306a36Sopenharmony_ci	accum_val->counter += diff_val->counter;
7262306a36Sopenharmony_ci	accum_val->enabled += diff_val->enabled;
7362306a36Sopenharmony_ci	accum_val->running += diff_val->running;
7462306a36Sopenharmony_ci
7562306a36Sopenharmony_ci	return 0;
7662306a36Sopenharmony_ci}
7762306a36Sopenharmony_ci
7862306a36Sopenharmony_cichar LICENSE[] SEC("license") = "Dual BSD/GPL";
79