blob: 618ebd4f0117e94d964078d7920828a7beeeb65d [file] [log] [blame]
Joel Fernandesc5c05162018-10-16 13:26:56 -07001/*
2 * time_in_state eBPF program
3 *
4 * Copyright (C) 2018 Google
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License version
8 * 2 as published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 */
16
Joel Fernandes (Google)4134dbb2019-02-12 12:47:25 -050017#include <bpf_helpers.h>
Joel Fernandesc5c05162018-10-16 13:26:56 -070018
Maciej Żenczykowski162826e2019-04-17 18:03:17 -070019typedef struct {
Joel Fernandesc5c05162018-10-16 13:26:56 -070020 uint32_t uid;
21 uint32_t freq;
Maciej Żenczykowski162826e2019-04-17 18:03:17 -070022} time_key;
Joel Fernandesc5c05162018-10-16 13:26:56 -070023
Maciej Żenczykowski162826e2019-04-17 18:03:17 -070024DEFINE_BPF_MAP(uid_times_map, PERCPU_HASH, time_key, uint64_t, 10240)
25DEFINE_BPF_MAP(cpu_last_update_map, PERCPU_ARRAY, uint32_t, uint64_t, 1)
Joel Fernandesc5c05162018-10-16 13:26:56 -070026
Maciej Żenczykowski162826e2019-04-17 18:03:17 -070027/* Assume max of 1024 CPUs */
28DEFINE_BPF_MAP(cpu_freq_map, ARRAY, uint32_t, uint32_t, 1024)
Joel Fernandesc5c05162018-10-16 13:26:56 -070029
30struct switch_args {
31 unsigned long long ignore;
32 char prev_comm[16];
33 int prev_pid;
34 int prev_prio;
35 long long prev_state;
36 char next_comm[16];
37 int next_pid;
38 int next_prio;
39};
40
41SEC("tracepoint/sched/sched_switch")
42int tp_sched_switch(struct switch_args* args) {
43 uint32_t zero = 0;
Maciej Żenczykowski162826e2019-04-17 18:03:17 -070044 uint64_t* last = bpf_cpu_last_update_map_lookup_elem(&zero);
Joel Fernandesc5c05162018-10-16 13:26:56 -070045 if (!last) return 0;
46 uint64_t old_last = *last;
47 uint64_t time = bpf_ktime_get_ns();
48 *last = time;
49 uint32_t cpu = bpf_get_smp_processor_id();
Maciej Żenczykowski162826e2019-04-17 18:03:17 -070050 uint32_t* freq = bpf_cpu_freq_map_lookup_elem(&cpu);
Joel Fernandesc5c05162018-10-16 13:26:56 -070051 if (args->prev_pid && old_last && freq && *freq) {
52 uint32_t uid = bpf_get_current_uid_gid();
Maciej Żenczykowski162826e2019-04-17 18:03:17 -070053 time_key key = {.uid = uid, .freq = *freq};
54 uint64_t* tot_time = bpf_uid_times_map_lookup_elem(&key);
Joel Fernandesc5c05162018-10-16 13:26:56 -070055 uint64_t delta = time - old_last;
56 if (!tot_time)
Maciej Żenczykowski162826e2019-04-17 18:03:17 -070057 bpf_uid_times_map_update_elem(&key, &delta, BPF_ANY);
Joel Fernandesc5c05162018-10-16 13:26:56 -070058 else
59 *tot_time += delta;
60 }
61 return 0;
62}
63
64struct cpufreq_args {
65 unsigned long long ignore;
66 unsigned int state;
67 unsigned int cpu_id;
68};
69
70SEC("tracepoint/power/cpu_frequency")
71int tp_cpufreq(struct cpufreq_args* args) {
Maciej Żenczykowski162826e2019-04-17 18:03:17 -070072 uint32_t cpu = args->cpu_id;
Joel Fernandesc5c05162018-10-16 13:26:56 -070073 unsigned int new = args->state;
Maciej Żenczykowski162826e2019-04-17 18:03:17 -070074 bpf_cpu_freq_map_update_elem(&cpu, &new, BPF_ANY);
Joel Fernandesc5c05162018-10-16 13:26:56 -070075 return 0;
76}
77
78char _license[] SEC("license") = "GPL";