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