1 /* drivers/cpufreq/cpufreq_times.c
2 *
3 * Copyright (C) 2018 Google, Inc.
4 *
5 * This software is licensed under the terms of the GNU General Public
6 * License version 2, as published by the Free Software Foundation, and
7 * may be copied, distributed, and modified under those terms.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 */
15
16 #include <linux/cpufreq.h>
17 #include <linux/cpufreq_times.h>
18 #include <linux/hashtable.h>
19 #include <linux/init.h>
20 #include <linux/jiffies.h>
21 #include <linux/proc_fs.h>
22 #include <linux/sched.h>
23 #include <linux/seq_file.h>
24 #include <linux/slab.h>
25 #include <linux/spinlock.h>
26 #include <linux/threads.h>
27
28 #define UID_HASH_BITS 10
29
30 static DECLARE_HASHTABLE(uid_hash_table, UID_HASH_BITS);
31
32 static DEFINE_SPINLOCK(task_time_in_state_lock); /* task->time_in_state */
33 static DEFINE_SPINLOCK(uid_lock); /* uid_hash_table */
34
35 struct concurrent_times {
36 atomic64_t active[NR_CPUS];
37 atomic64_t policy[NR_CPUS];
38 };
39
40 struct uid_entry {
41 uid_t uid;
42 unsigned int max_state;
43 struct hlist_node hash;
44 struct rcu_head rcu;
45 struct concurrent_times *concurrent_times;
46 u64 time_in_state[0];
47 };
48
49 /**
50 * struct cpu_freqs - per-cpu frequency information
51 * @offset: start of these freqs' stats in task time_in_state array
52 * @max_state: number of entries in freq_table
53 * @last_index: index in freq_table of last frequency switched to
54 * @freq_table: list of available frequencies
55 */
56 struct cpu_freqs {
57 unsigned int offset;
58 unsigned int max_state;
59 unsigned int last_index;
60 unsigned int freq_table[0];
61 };
62
63 static struct cpu_freqs *all_freqs[NR_CPUS];
64
65 static unsigned int next_offset;
66
67
68 /* Caller must hold rcu_read_lock() */
find_uid_entry_rcu(uid_t uid)69 static struct uid_entry *find_uid_entry_rcu(uid_t uid)
70 {
71 struct uid_entry *uid_entry;
72
73 hash_for_each_possible_rcu(uid_hash_table, uid_entry, hash, uid) {
74 if (uid_entry->uid == uid)
75 return uid_entry;
76 }
77 return NULL;
78 }
79
80 /* Caller must hold uid lock */
find_uid_entry_locked(uid_t uid)81 static struct uid_entry *find_uid_entry_locked(uid_t uid)
82 {
83 struct uid_entry *uid_entry;
84
85 hash_for_each_possible(uid_hash_table, uid_entry, hash, uid) {
86 if (uid_entry->uid == uid)
87 return uid_entry;
88 }
89 return NULL;
90 }
91
92 /* Caller must hold uid lock */
find_or_register_uid_locked(uid_t uid)93 static struct uid_entry *find_or_register_uid_locked(uid_t uid)
94 {
95 struct uid_entry *uid_entry, *temp;
96 struct concurrent_times *times;
97 unsigned int max_state = READ_ONCE(next_offset);
98 size_t alloc_size = sizeof(*uid_entry) + max_state *
99 sizeof(uid_entry->time_in_state[0]);
100
101 uid_entry = find_uid_entry_locked(uid);
102 if (uid_entry) {
103 if (uid_entry->max_state == max_state)
104 return uid_entry;
105 /* uid_entry->time_in_state is too small to track all freqs, so
106 * expand it.
107 */
108 temp = __krealloc(uid_entry, alloc_size, GFP_ATOMIC);
109 if (!temp)
110 return uid_entry;
111 temp->max_state = max_state;
112 memset(temp->time_in_state + uid_entry->max_state, 0,
113 (max_state - uid_entry->max_state) *
114 sizeof(uid_entry->time_in_state[0]));
115 if (temp != uid_entry) {
116 hlist_replace_rcu(&uid_entry->hash, &temp->hash);
117 kfree_rcu(uid_entry, rcu);
118 }
119 return temp;
120 }
121
122 uid_entry = kzalloc(alloc_size, GFP_ATOMIC);
123 if (!uid_entry)
124 return NULL;
125 times = kzalloc(sizeof(*times), GFP_ATOMIC);
126 if (!times) {
127 kfree(uid_entry);
128 return NULL;
129 }
130
131 uid_entry->uid = uid;
132 uid_entry->max_state = max_state;
133 uid_entry->concurrent_times = times;
134
135 hash_add_rcu(uid_hash_table, &uid_entry->hash, uid);
136
137 return uid_entry;
138 }
139
single_uid_time_in_state_show(struct seq_file * m,void * ptr)140 static int single_uid_time_in_state_show(struct seq_file *m, void *ptr)
141 {
142 struct uid_entry *uid_entry;
143 unsigned int i;
144 uid_t uid = from_kuid_munged(current_user_ns(), *(kuid_t *)m->private);
145
146 if (uid == overflowuid)
147 return -EINVAL;
148
149 rcu_read_lock();
150
151 uid_entry = find_uid_entry_rcu(uid);
152 if (!uid_entry) {
153 rcu_read_unlock();
154 return 0;
155 }
156
157 for (i = 0; i < uid_entry->max_state; ++i) {
158 u64 time = nsec_to_clock_t(uid_entry->time_in_state[i]);
159 seq_write(m, &time, sizeof(time));
160 }
161
162 rcu_read_unlock();
163
164 return 0;
165 }
166
uid_seq_start(struct seq_file * seq,loff_t * pos)167 static void *uid_seq_start(struct seq_file *seq, loff_t *pos)
168 {
169 if (*pos >= HASH_SIZE(uid_hash_table))
170 return NULL;
171
172 return &uid_hash_table[*pos];
173 }
174
uid_seq_next(struct seq_file * seq,void * v,loff_t * pos)175 static void *uid_seq_next(struct seq_file *seq, void *v, loff_t *pos)
176 {
177 do {
178 (*pos)++;
179
180 if (*pos >= HASH_SIZE(uid_hash_table))
181 return NULL;
182 } while (hlist_empty(&uid_hash_table[*pos]));
183
184 return &uid_hash_table[*pos];
185 }
186
uid_seq_stop(struct seq_file * seq,void * v)187 static void uid_seq_stop(struct seq_file *seq, void *v) { }
188
uid_time_in_state_seq_show(struct seq_file * m,void * v)189 static int uid_time_in_state_seq_show(struct seq_file *m, void *v)
190 {
191 struct uid_entry *uid_entry;
192 struct cpu_freqs *freqs, *last_freqs = NULL;
193 int i, cpu;
194
195 if (v == uid_hash_table) {
196 seq_puts(m, "uid:");
197 for_each_possible_cpu(cpu) {
198 freqs = all_freqs[cpu];
199 if (!freqs || freqs == last_freqs)
200 continue;
201 last_freqs = freqs;
202 for (i = 0; i < freqs->max_state; i++) {
203 seq_put_decimal_ull(m, " ",
204 freqs->freq_table[i]);
205 }
206 }
207 seq_putc(m, '\n');
208 }
209
210 rcu_read_lock();
211
212 hlist_for_each_entry_rcu(uid_entry, (struct hlist_head *)v, hash) {
213 if (uid_entry->max_state) {
214 seq_put_decimal_ull(m, "", uid_entry->uid);
215 seq_putc(m, ':');
216 }
217 for (i = 0; i < uid_entry->max_state; ++i) {
218 u64 time = nsec_to_clock_t(uid_entry->time_in_state[i]);
219 seq_put_decimal_ull(m, " ", time);
220 }
221 if (uid_entry->max_state)
222 seq_putc(m, '\n');
223 }
224
225 rcu_read_unlock();
226 return 0;
227 }
228
concurrent_time_seq_show(struct seq_file * m,void * v,atomic64_t * (* get_times)(struct concurrent_times *))229 static int concurrent_time_seq_show(struct seq_file *m, void *v,
230 atomic64_t *(*get_times)(struct concurrent_times *))
231 {
232 struct uid_entry *uid_entry;
233 int i, num_possible_cpus = num_possible_cpus();
234
235 rcu_read_lock();
236
237 hlist_for_each_entry_rcu(uid_entry, (struct hlist_head *)v, hash) {
238 atomic64_t *times = get_times(uid_entry->concurrent_times);
239
240 seq_put_decimal_ull(m, "", (u64)uid_entry->uid);
241 seq_putc(m, ':');
242
243 for (i = 0; i < num_possible_cpus; ++i) {
244 u64 time = nsec_to_clock_t(atomic64_read(×[i]));
245
246 seq_put_decimal_ull(m, " ", time);
247 }
248 seq_putc(m, '\n');
249 }
250
251 rcu_read_unlock();
252
253 return 0;
254 }
255
get_active_times(struct concurrent_times * times)256 static inline atomic64_t *get_active_times(struct concurrent_times *times)
257 {
258 return times->active;
259 }
260
concurrent_active_time_seq_show(struct seq_file * m,void * v)261 static int concurrent_active_time_seq_show(struct seq_file *m, void *v)
262 {
263 if (v == uid_hash_table) {
264 seq_put_decimal_ull(m, "cpus: ", num_possible_cpus());
265 seq_putc(m, '\n');
266 }
267
268 return concurrent_time_seq_show(m, v, get_active_times);
269 }
270
get_policy_times(struct concurrent_times * times)271 static inline atomic64_t *get_policy_times(struct concurrent_times *times)
272 {
273 return times->policy;
274 }
275
concurrent_policy_time_seq_show(struct seq_file * m,void * v)276 static int concurrent_policy_time_seq_show(struct seq_file *m, void *v)
277 {
278 int i;
279 struct cpu_freqs *freqs, *last_freqs = NULL;
280
281 if (v == uid_hash_table) {
282 int cnt = 0;
283
284 for_each_possible_cpu(i) {
285 freqs = all_freqs[i];
286 if (!freqs)
287 continue;
288 if (freqs != last_freqs) {
289 if (last_freqs) {
290 seq_put_decimal_ull(m, ": ", cnt);
291 seq_putc(m, ' ');
292 cnt = 0;
293 }
294 seq_put_decimal_ull(m, "policy", i);
295
296 last_freqs = freqs;
297 }
298 cnt++;
299 }
300 if (last_freqs) {
301 seq_put_decimal_ull(m, ": ", cnt);
302 seq_putc(m, '\n');
303 }
304 }
305
306 return concurrent_time_seq_show(m, v, get_policy_times);
307 }
308
cpufreq_task_times_init(struct task_struct * p)309 void cpufreq_task_times_init(struct task_struct *p)
310 {
311 unsigned long flags;
312
313 spin_lock_irqsave(&task_time_in_state_lock, flags);
314 p->time_in_state = NULL;
315 spin_unlock_irqrestore(&task_time_in_state_lock, flags);
316 p->max_state = 0;
317 }
318
cpufreq_task_times_alloc(struct task_struct * p)319 void cpufreq_task_times_alloc(struct task_struct *p)
320 {
321 void *temp;
322 unsigned long flags;
323 unsigned int max_state = READ_ONCE(next_offset);
324
325 /* We use one array to avoid multiple allocs per task */
326 temp = kcalloc(max_state, sizeof(p->time_in_state[0]), GFP_ATOMIC);
327 if (!temp)
328 return;
329
330 spin_lock_irqsave(&task_time_in_state_lock, flags);
331 p->time_in_state = temp;
332 spin_unlock_irqrestore(&task_time_in_state_lock, flags);
333 p->max_state = max_state;
334 }
335
336 /* Caller must hold task_time_in_state_lock */
cpufreq_task_times_realloc_locked(struct task_struct * p)337 static int cpufreq_task_times_realloc_locked(struct task_struct *p)
338 {
339 void *temp;
340 unsigned int max_state = READ_ONCE(next_offset);
341
342 temp = krealloc(p->time_in_state, max_state * sizeof(u64), GFP_ATOMIC);
343 if (!temp)
344 return -ENOMEM;
345 p->time_in_state = temp;
346 memset(p->time_in_state + p->max_state, 0,
347 (max_state - p->max_state) * sizeof(u64));
348 p->max_state = max_state;
349 return 0;
350 }
351
cpufreq_task_times_exit(struct task_struct * p)352 void cpufreq_task_times_exit(struct task_struct *p)
353 {
354 unsigned long flags;
355 void *temp;
356
357 if (!p->time_in_state)
358 return;
359
360 spin_lock_irqsave(&task_time_in_state_lock, flags);
361 temp = p->time_in_state;
362 p->time_in_state = NULL;
363 spin_unlock_irqrestore(&task_time_in_state_lock, flags);
364 kfree(temp);
365 }
366
proc_time_in_state_show(struct seq_file * m,struct pid_namespace * ns,struct pid * pid,struct task_struct * p)367 int proc_time_in_state_show(struct seq_file *m, struct pid_namespace *ns,
368 struct pid *pid, struct task_struct *p)
369 {
370 unsigned int cpu, i;
371 u64 cputime;
372 unsigned long flags;
373 struct cpu_freqs *freqs;
374 struct cpu_freqs *last_freqs = NULL;
375
376 spin_lock_irqsave(&task_time_in_state_lock, flags);
377 for_each_possible_cpu(cpu) {
378 freqs = all_freqs[cpu];
379 if (!freqs || freqs == last_freqs)
380 continue;
381 last_freqs = freqs;
382
383 seq_printf(m, "cpu%u\n", cpu);
384 for (i = 0; i < freqs->max_state; i++) {
385 cputime = 0;
386 if (freqs->offset + i < p->max_state &&
387 p->time_in_state)
388 cputime = p->time_in_state[freqs->offset + i];
389 seq_printf(m, "%u %lu\n", freqs->freq_table[i],
390 (unsigned long)nsec_to_clock_t(cputime));
391 }
392 }
393 spin_unlock_irqrestore(&task_time_in_state_lock, flags);
394 return 0;
395 }
396
cpufreq_acct_update_power(struct task_struct * p,u64 cputime)397 void cpufreq_acct_update_power(struct task_struct *p, u64 cputime)
398 {
399 unsigned long flags;
400 unsigned int state;
401 unsigned int active_cpu_cnt = 0;
402 unsigned int policy_cpu_cnt = 0;
403 unsigned int policy_first_cpu;
404 struct uid_entry *uid_entry;
405 struct cpu_freqs *freqs = all_freqs[task_cpu(p)];
406 struct cpufreq_policy *policy;
407 uid_t uid = from_kuid_munged(current_user_ns(), task_uid(p));
408 int cpu = 0;
409
410 if (!freqs || is_idle_task(p) || p->flags & PF_EXITING)
411 return;
412
413 state = freqs->offset + READ_ONCE(freqs->last_index);
414
415 spin_lock_irqsave(&task_time_in_state_lock, flags);
416 if ((state < p->max_state || !cpufreq_task_times_realloc_locked(p)) &&
417 p->time_in_state)
418 p->time_in_state[state] += cputime;
419 spin_unlock_irqrestore(&task_time_in_state_lock, flags);
420
421 spin_lock_irqsave(&uid_lock, flags);
422 uid_entry = find_or_register_uid_locked(uid);
423 if (uid_entry && state < uid_entry->max_state)
424 uid_entry->time_in_state[state] += cputime;
425 spin_unlock_irqrestore(&uid_lock, flags);
426
427 rcu_read_lock();
428 uid_entry = find_uid_entry_rcu(uid);
429 if (!uid_entry) {
430 rcu_read_unlock();
431 return;
432 }
433
434 for_each_possible_cpu(cpu)
435 if (!idle_cpu(cpu))
436 ++active_cpu_cnt;
437
438 atomic64_add(cputime,
439 &uid_entry->concurrent_times->active[active_cpu_cnt - 1]);
440
441 policy = cpufreq_cpu_get(task_cpu(p));
442 if (!policy) {
443 /*
444 * This CPU may have just come up and not have a cpufreq policy
445 * yet.
446 */
447 rcu_read_unlock();
448 return;
449 }
450
451 for_each_cpu(cpu, policy->related_cpus)
452 if (!idle_cpu(cpu))
453 ++policy_cpu_cnt;
454
455 policy_first_cpu = cpumask_first(policy->related_cpus);
456 cpufreq_cpu_put(policy);
457
458 atomic64_add(cputime,
459 &uid_entry->concurrent_times->policy[policy_first_cpu +
460 policy_cpu_cnt - 1]);
461 rcu_read_unlock();
462 }
463
cpufreq_times_get_index(struct cpu_freqs * freqs,unsigned int freq)464 static int cpufreq_times_get_index(struct cpu_freqs *freqs, unsigned int freq)
465 {
466 int index;
467 for (index = 0; index < freqs->max_state; ++index) {
468 if (freqs->freq_table[index] == freq)
469 return index;
470 }
471 return -1;
472 }
473
cpufreq_times_create_policy(struct cpufreq_policy * policy)474 void cpufreq_times_create_policy(struct cpufreq_policy *policy)
475 {
476 int cpu, index = 0;
477 unsigned int count = 0;
478 struct cpufreq_frequency_table *pos, *table;
479 struct cpu_freqs *freqs;
480 void *tmp;
481
482 if (all_freqs[policy->cpu])
483 return;
484
485 table = policy->freq_table;
486 if (!table)
487 return;
488
489 cpufreq_for_each_valid_entry(pos, table)
490 count++;
491
492 tmp = kzalloc(sizeof(*freqs) + sizeof(freqs->freq_table[0]) * count,
493 GFP_KERNEL);
494 if (!tmp)
495 return;
496
497 freqs = tmp;
498 freqs->max_state = count;
499
500 cpufreq_for_each_valid_entry(pos, table)
501 freqs->freq_table[index++] = pos->frequency;
502
503 index = cpufreq_times_get_index(freqs, policy->cur);
504 if (index >= 0)
505 WRITE_ONCE(freqs->last_index, index);
506
507 freqs->offset = next_offset;
508 WRITE_ONCE(next_offset, freqs->offset + count);
509 for_each_cpu(cpu, policy->related_cpus)
510 all_freqs[cpu] = freqs;
511 }
512
uid_entry_reclaim(struct rcu_head * rcu)513 static void uid_entry_reclaim(struct rcu_head *rcu)
514 {
515 struct uid_entry *uid_entry = container_of(rcu, struct uid_entry, rcu);
516
517 kfree(uid_entry->concurrent_times);
518 kfree(uid_entry);
519 }
520
cpufreq_task_times_remove_uids(uid_t uid_start,uid_t uid_end)521 void cpufreq_task_times_remove_uids(uid_t uid_start, uid_t uid_end)
522 {
523 struct uid_entry *uid_entry;
524 struct hlist_node *tmp;
525 unsigned long flags;
526
527 spin_lock_irqsave(&uid_lock, flags);
528
529 for (; uid_start <= uid_end; uid_start++) {
530 hash_for_each_possible_safe(uid_hash_table, uid_entry, tmp,
531 hash, uid_start) {
532 if (uid_start == uid_entry->uid) {
533 hash_del_rcu(&uid_entry->hash);
534 call_rcu(&uid_entry->rcu, uid_entry_reclaim);
535 }
536 }
537 }
538
539 spin_unlock_irqrestore(&uid_lock, flags);
540 }
541
cpufreq_times_record_transition(struct cpufreq_policy * policy,unsigned int new_freq)542 void cpufreq_times_record_transition(struct cpufreq_policy *policy,
543 unsigned int new_freq)
544 {
545 int index;
546 struct cpu_freqs *freqs = all_freqs[policy->cpu];
547 if (!freqs)
548 return;
549
550 index = cpufreq_times_get_index(freqs, new_freq);
551 if (index >= 0)
552 WRITE_ONCE(freqs->last_index, index);
553 }
554
555 static const struct seq_operations uid_time_in_state_seq_ops = {
556 .start = uid_seq_start,
557 .next = uid_seq_next,
558 .stop = uid_seq_stop,
559 .show = uid_time_in_state_seq_show,
560 };
561
uid_time_in_state_open(struct inode * inode,struct file * file)562 static int uid_time_in_state_open(struct inode *inode, struct file *file)
563 {
564 return seq_open(file, &uid_time_in_state_seq_ops);
565 }
566
single_uid_time_in_state_open(struct inode * inode,struct file * file)567 int single_uid_time_in_state_open(struct inode *inode, struct file *file)
568 {
569 return single_open(file, single_uid_time_in_state_show,
570 &(inode->i_uid));
571 }
572
573 static const struct file_operations uid_time_in_state_fops = {
574 .open = uid_time_in_state_open,
575 .read = seq_read,
576 .llseek = seq_lseek,
577 .release = seq_release,
578 };
579
580 static const struct seq_operations concurrent_active_time_seq_ops = {
581 .start = uid_seq_start,
582 .next = uid_seq_next,
583 .stop = uid_seq_stop,
584 .show = concurrent_active_time_seq_show,
585 };
586
concurrent_active_time_open(struct inode * inode,struct file * file)587 static int concurrent_active_time_open(struct inode *inode, struct file *file)
588 {
589 return seq_open(file, &concurrent_active_time_seq_ops);
590 }
591
592 static const struct file_operations concurrent_active_time_fops = {
593 .open = concurrent_active_time_open,
594 .read = seq_read,
595 .llseek = seq_lseek,
596 .release = seq_release,
597 };
598
599 static const struct seq_operations concurrent_policy_time_seq_ops = {
600 .start = uid_seq_start,
601 .next = uid_seq_next,
602 .stop = uid_seq_stop,
603 .show = concurrent_policy_time_seq_show,
604 };
605
concurrent_policy_time_open(struct inode * inode,struct file * file)606 static int concurrent_policy_time_open(struct inode *inode, struct file *file)
607 {
608 return seq_open(file, &concurrent_policy_time_seq_ops);
609 }
610
611 static const struct file_operations concurrent_policy_time_fops = {
612 .open = concurrent_policy_time_open,
613 .read = seq_read,
614 .llseek = seq_lseek,
615 .release = seq_release,
616 };
617
cpufreq_times_init(void)618 static int __init cpufreq_times_init(void)
619 {
620 proc_create_data("uid_time_in_state", 0444, NULL,
621 &uid_time_in_state_fops, NULL);
622
623 proc_create_data("uid_concurrent_active_time", 0444, NULL,
624 &concurrent_active_time_fops, NULL);
625
626 proc_create_data("uid_concurrent_policy_time", 0444, NULL,
627 &concurrent_policy_time_fops, NULL);
628
629 return 0;
630 }
631
632 early_initcall(cpufreq_times_init);
633