// SPDX-License-Identifier: GPL-2.0 // Copyright (c) 2020 Wenbo Zhang #include #include #include #include "cpufreq.h" #include "maps.bpf.h" __u32 freqs_mhz[MAX_CPU_NR] = {}; static struct hist zero; struct hist syswide = {}; struct { __uint(type, BPF_MAP_TYPE_HASH); __uint(max_entries, MAX_ENTRIES); __type(key, struct hkey); __type(value, struct hist); } hists SEC(".maps"); SEC("tp_btf/cpu_frequency") int BPF_PROG(cpu_frequency, unsigned int state, unsigned int cpu_id) { if (cpu_id >= MAX_CPU_NR) return 0; freqs_mhz[cpu_id] = state / 1000; return 0; } SEC("perf_event") int do_sample(struct bpf_perf_event_data *ctx) { u32 freq_mhz, pid = bpf_get_current_pid_tgid(); u64 slot, cpu = bpf_get_smp_processor_id(); struct hist *hist; struct hkey hkey; if (cpu >= MAX_CPU_NR) return 0; freq_mhz = freqs_mhz[cpu]; if (!freq_mhz) return 0; /* * The range of the linear histogram is 0 ~ 5000mhz, * and the step size is 200. */ slot = freq_mhz / HIST_STEP_SIZE; if (slot >= MAX_SLOTS) slot = MAX_SLOTS - 1; __sync_fetch_and_add(&syswide.slots[slot], 1); if (!pid) return 0; bpf_get_current_comm(&hkey.comm, sizeof(hkey.comm)); hist = bpf_map_lookup_or_try_init(&hists, &hkey, &zero); if (!hist) return 0; __sync_fetch_and_add(&hist->slots[slot], 1); return 0; } char LICENSE[] SEC("license") = "GPL";