xref: /aosp_15_r20/external/bcc/libbpf-tools/cpufreq.bpf.c (revision 387f9dfdfa2baef462e92476d413c7bc2470293e)
1*387f9dfdSAndroid Build Coastguard Worker // SPDX-License-Identifier: GPL-2.0
2*387f9dfdSAndroid Build Coastguard Worker // Copyright (c) 2020 Wenbo Zhang
3*387f9dfdSAndroid Build Coastguard Worker #include <vmlinux.h>
4*387f9dfdSAndroid Build Coastguard Worker #include <bpf/bpf_helpers.h>
5*387f9dfdSAndroid Build Coastguard Worker #include <bpf/bpf_tracing.h>
6*387f9dfdSAndroid Build Coastguard Worker #include "cpufreq.h"
7*387f9dfdSAndroid Build Coastguard Worker #include "maps.bpf.h"
8*387f9dfdSAndroid Build Coastguard Worker 
9*387f9dfdSAndroid Build Coastguard Worker __u32 freqs_mhz[MAX_CPU_NR] = {};
10*387f9dfdSAndroid Build Coastguard Worker static struct hist zero;
11*387f9dfdSAndroid Build Coastguard Worker struct hist syswide = {};
12*387f9dfdSAndroid Build Coastguard Worker bool filter_cg = false;
13*387f9dfdSAndroid Build Coastguard Worker 
14*387f9dfdSAndroid Build Coastguard Worker struct {
15*387f9dfdSAndroid Build Coastguard Worker 	__uint(type, BPF_MAP_TYPE_CGROUP_ARRAY);
16*387f9dfdSAndroid Build Coastguard Worker 	__type(key, u32);
17*387f9dfdSAndroid Build Coastguard Worker 	__type(value, u32);
18*387f9dfdSAndroid Build Coastguard Worker 	__uint(max_entries, 1);
19*387f9dfdSAndroid Build Coastguard Worker } cgroup_map SEC(".maps");
20*387f9dfdSAndroid Build Coastguard Worker 
21*387f9dfdSAndroid Build Coastguard Worker struct {
22*387f9dfdSAndroid Build Coastguard Worker 	__uint(type, BPF_MAP_TYPE_HASH);
23*387f9dfdSAndroid Build Coastguard Worker 	__uint(max_entries, MAX_ENTRIES);
24*387f9dfdSAndroid Build Coastguard Worker 	__type(key, struct hkey);
25*387f9dfdSAndroid Build Coastguard Worker 	__type(value, struct hist);
26*387f9dfdSAndroid Build Coastguard Worker } hists SEC(".maps");
27*387f9dfdSAndroid Build Coastguard Worker 
28*387f9dfdSAndroid Build Coastguard Worker #define clamp_umax(VAR, UMAX)						\
29*387f9dfdSAndroid Build Coastguard Worker 	asm volatile (							\
30*387f9dfdSAndroid Build Coastguard Worker 		"if %0 <= %[max] goto +1\n"				\
31*387f9dfdSAndroid Build Coastguard Worker 		"%0 = %[max]\n"						\
32*387f9dfdSAndroid Build Coastguard Worker 		: "+r"(VAR)						\
33*387f9dfdSAndroid Build Coastguard Worker 		: [max]"i"(UMAX)					\
34*387f9dfdSAndroid Build Coastguard Worker 	)
35*387f9dfdSAndroid Build Coastguard Worker 
36*387f9dfdSAndroid Build Coastguard Worker SEC("tp_btf/cpu_frequency")
BPF_PROG(cpu_frequency,unsigned int state,unsigned int cpu_id)37*387f9dfdSAndroid Build Coastguard Worker int BPF_PROG(cpu_frequency, unsigned int state, unsigned int cpu_id)
38*387f9dfdSAndroid Build Coastguard Worker {
39*387f9dfdSAndroid Build Coastguard Worker 	if (filter_cg && !bpf_current_task_under_cgroup(&cgroup_map, 0))
40*387f9dfdSAndroid Build Coastguard Worker 		return 0;
41*387f9dfdSAndroid Build Coastguard Worker 
42*387f9dfdSAndroid Build Coastguard Worker 	if (cpu_id >= MAX_CPU_NR)
43*387f9dfdSAndroid Build Coastguard Worker 		return 0;
44*387f9dfdSAndroid Build Coastguard Worker 
45*387f9dfdSAndroid Build Coastguard Worker 	clamp_umax(cpu_id, MAX_CPU_NR - 1);
46*387f9dfdSAndroid Build Coastguard Worker 	freqs_mhz[cpu_id] = state / 1000;
47*387f9dfdSAndroid Build Coastguard Worker 	return 0;
48*387f9dfdSAndroid Build Coastguard Worker }
49*387f9dfdSAndroid Build Coastguard Worker 
50*387f9dfdSAndroid Build Coastguard Worker SEC("perf_event")
do_sample(struct bpf_perf_event_data * ctx)51*387f9dfdSAndroid Build Coastguard Worker int do_sample(struct bpf_perf_event_data *ctx)
52*387f9dfdSAndroid Build Coastguard Worker {
53*387f9dfdSAndroid Build Coastguard Worker 	u32 freq_mhz, pid = bpf_get_current_pid_tgid();
54*387f9dfdSAndroid Build Coastguard Worker 	u64 slot, cpu = bpf_get_smp_processor_id();
55*387f9dfdSAndroid Build Coastguard Worker 	struct hist *hist;
56*387f9dfdSAndroid Build Coastguard Worker 	struct hkey hkey;
57*387f9dfdSAndroid Build Coastguard Worker 
58*387f9dfdSAndroid Build Coastguard Worker 	if (filter_cg && !bpf_current_task_under_cgroup(&cgroup_map, 0))
59*387f9dfdSAndroid Build Coastguard Worker 		return 0;
60*387f9dfdSAndroid Build Coastguard Worker 
61*387f9dfdSAndroid Build Coastguard Worker 	if (cpu >= MAX_CPU_NR)
62*387f9dfdSAndroid Build Coastguard Worker 		return 0;
63*387f9dfdSAndroid Build Coastguard Worker 	clamp_umax(cpu, MAX_CPU_NR - 1);
64*387f9dfdSAndroid Build Coastguard Worker 	freq_mhz = freqs_mhz[cpu];
65*387f9dfdSAndroid Build Coastguard Worker 	if (!freq_mhz)
66*387f9dfdSAndroid Build Coastguard Worker 		return 0;
67*387f9dfdSAndroid Build Coastguard Worker 	/*
68*387f9dfdSAndroid Build Coastguard Worker 	 * The range of the linear histogram is 0 ~ 5000mhz,
69*387f9dfdSAndroid Build Coastguard Worker 	 * and the step size is 200.
70*387f9dfdSAndroid Build Coastguard Worker 	 */
71*387f9dfdSAndroid Build Coastguard Worker 	slot = freq_mhz / HIST_STEP_SIZE;
72*387f9dfdSAndroid Build Coastguard Worker 	if (slot >= MAX_SLOTS)
73*387f9dfdSAndroid Build Coastguard Worker 		slot = MAX_SLOTS - 1;
74*387f9dfdSAndroid Build Coastguard Worker 	__sync_fetch_and_add(&syswide.slots[slot], 1);
75*387f9dfdSAndroid Build Coastguard Worker 	if (!pid)
76*387f9dfdSAndroid Build Coastguard Worker 		return 0;
77*387f9dfdSAndroid Build Coastguard Worker 	bpf_get_current_comm(&hkey.comm, sizeof(hkey.comm));
78*387f9dfdSAndroid Build Coastguard Worker 	hist = bpf_map_lookup_or_try_init(&hists, &hkey, &zero);
79*387f9dfdSAndroid Build Coastguard Worker 	if (!hist)
80*387f9dfdSAndroid Build Coastguard Worker 		return 0;
81*387f9dfdSAndroid Build Coastguard Worker 	__sync_fetch_and_add(&hist->slots[slot], 1);
82*387f9dfdSAndroid Build Coastguard Worker 	return 0;
83*387f9dfdSAndroid Build Coastguard Worker }
84*387f9dfdSAndroid Build Coastguard Worker 
85*387f9dfdSAndroid Build Coastguard Worker char LICENSE[] SEC("license") = "GPL";
86