• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
13 struct {
14 	__uint(type, BPF_MAP_TYPE_HASH);
15 	__uint(max_entries, MAX_ENTRIES);
16 	__type(key, struct hkey);
17 	__type(value, struct hist);
18 } hists SEC(".maps");
19 
20 #define clamp_umax(VAR, UMAX)						\
21 	asm volatile (							\
22 		"if %0 <= %[max] goto +1\n"				\
23 		"%0 = %[max]\n"						\
24 		: "+r"(VAR)						\
25 		: [max]"i"(UMAX)					\
26 	)
27 
28 SEC("tp_btf/cpu_frequency")
BPF_PROG(cpu_frequency,unsigned int state,unsigned int cpu_id)29 int BPF_PROG(cpu_frequency, unsigned int state, unsigned int cpu_id)
30 {
31 	if (cpu_id >= MAX_CPU_NR)
32 		return 0;
33 
34 	clamp_umax(cpu_id, MAX_CPU_NR - 1);
35 	freqs_mhz[cpu_id] = state / 1000;
36 	return 0;
37 }
38 
39 SEC("perf_event")
do_sample(struct bpf_perf_event_data * ctx)40 int do_sample(struct bpf_perf_event_data *ctx)
41 {
42 	u32 freq_mhz, pid = bpf_get_current_pid_tgid();
43 	u64 slot, cpu = bpf_get_smp_processor_id();
44 	struct hist *hist;
45 	struct hkey hkey;
46 
47 	if (cpu >= MAX_CPU_NR)
48 		return 0;
49 	clamp_umax(cpu, MAX_CPU_NR - 1);
50 	freq_mhz = freqs_mhz[cpu];
51 	if (!freq_mhz)
52 		return 0;
53 	/*
54 	 * The range of the linear histogram is 0 ~ 5000mhz,
55 	 * and the step size is 200.
56 	 */
57 	slot = freq_mhz / HIST_STEP_SIZE;
58 	if (slot >= MAX_SLOTS)
59 		slot = MAX_SLOTS - 1;
60 	__sync_fetch_and_add(&syswide.slots[slot], 1);
61 	if (!pid)
62 		return 0;
63 	bpf_get_current_comm(&hkey.comm, sizeof(hkey.comm));
64 	hist = bpf_map_lookup_or_try_init(&hists, &hkey, &zero);
65 	if (!hist)
66 		return 0;
67 	__sync_fetch_and_add(&hist->slots[slot], 1);
68 	return 0;
69 }
70 
71 char LICENSE[] SEC("license") = "GPL";
72