sched/tune: Add support for negative boost values
[firefly-linux-kernel-4.4.55.git] / kernel / sched / tune.c
1 #include <linux/cgroup.h>
2 #include <linux/err.h>
3 #include <linux/kernel.h>
4 #include <linux/percpu.h>
5 #include <linux/printk.h>
6 #include <linux/rcupdate.h>
7 #include <linux/slab.h>
8
9 #include <trace/events/sched.h>
10
11 #include "sched.h"
12 #include "tune.h"
13
14 unsigned int sysctl_sched_cfs_boost __read_mostly;
15
16 extern struct target_nrg schedtune_target_nrg;
17
18 /* Performance Boost region (B) threshold params */
19 static int perf_boost_idx;
20
21 /* Performance Constraint region (C) threshold params */
22 static int perf_constrain_idx;
23
24 /**
25  * Performance-Energy (P-E) Space thresholds constants
26  */
27 struct threshold_params {
28         int nrg_gain;
29         int cap_gain;
30 };
31
32 /*
33  * System specific P-E space thresholds constants
34  */
35 static struct threshold_params
36 threshold_gains[] = {
37         { 0, 4 }, /* >=  0% */
38         { 0, 4 }, /* >= 10% */
39         { 1, 4 }, /* >= 20% */
40         { 2, 4 }, /* >= 30% */
41         { 3, 4 }, /* >= 40% */
42         { 4, 3 }, /* >= 50% */
43         { 4, 2 }, /* >= 60% */
44         { 4, 1 }, /* >= 70% */
45         { 4, 0 }, /* >= 80% */
46         { 4, 0 }  /* >= 90% */
47 };
48
49 static int
50 __schedtune_accept_deltas(int nrg_delta, int cap_delta,
51                           int perf_boost_idx, int perf_constrain_idx)
52 {
53         int payoff = -INT_MAX;
54
55         /* Performance Boost (B) region */
56         if (nrg_delta > 0 && cap_delta > 0) {
57                 /*
58                  * Evaluate "Performance Boost" vs "Energy Increase"
59                  * payoff criteria:
60                  *    cap_delta / nrg_delta < cap_gain / nrg_gain
61                  * which is:
62                  *    nrg_delta * cap_gain > cap_delta * nrg_gain
63                  */
64                 payoff  = nrg_delta * threshold_gains[perf_boost_idx].cap_gain;
65                 payoff -= cap_delta * threshold_gains[perf_boost_idx].nrg_gain;
66
67                 trace_sched_tune_filter(
68                                 nrg_delta, cap_delta,
69                                 threshold_gains[perf_boost_idx].nrg_gain,
70                                 threshold_gains[perf_boost_idx].cap_gain,
71                                 payoff, 8);
72
73                 return payoff;
74         }
75
76         /* Performance Constraint (C) region */
77         if (nrg_delta < 0 && cap_delta < 0) {
78                 /*
79                  * Evaluate "Performance Boost" vs "Energy Increase"
80                  * payoff criteria:
81                  *    cap_delta / nrg_delta > cap_gain / nrg_gain
82                  * which is:
83                  *    cap_delta * nrg_gain > nrg_delta * cap_gain
84                  */
85                 payoff  = cap_delta * threshold_gains[perf_constrain_idx].nrg_gain;
86                 payoff -= nrg_delta * threshold_gains[perf_constrain_idx].cap_gain;
87
88                 trace_sched_tune_filter(
89                                 nrg_delta, cap_delta,
90                                 threshold_gains[perf_constrain_idx].nrg_gain,
91                                 threshold_gains[perf_constrain_idx].cap_gain,
92                                 payoff, 6);
93
94                 return payoff;
95         }
96
97         /* Default: reject schedule candidate */
98         return payoff;
99 }
100
101 #ifdef CONFIG_CGROUP_SCHEDTUNE
102
103 /*
104  * EAS scheduler tunables for task groups.
105  */
106
107 /* SchdTune tunables for a group of tasks */
108 struct schedtune {
109         /* SchedTune CGroup subsystem */
110         struct cgroup_subsys_state css;
111
112         /* Boost group allocated ID */
113         int idx;
114
115         /* Boost value for tasks on that SchedTune CGroup */
116         int boost;
117
118         /* Performance Boost (B) region threshold params */
119         int perf_boost_idx;
120
121         /* Performance Constraint (C) region threshold params */
122         int perf_constrain_idx;
123 };
124
125 static inline struct schedtune *css_st(struct cgroup_subsys_state *css)
126 {
127         return css ? container_of(css, struct schedtune, css) : NULL;
128 }
129
130 static inline struct schedtune *task_schedtune(struct task_struct *tsk)
131 {
132         return css_st(task_css(tsk, schedtune_cgrp_id));
133 }
134
135 static inline struct schedtune *parent_st(struct schedtune *st)
136 {
137         return css_st(st->css.parent);
138 }
139
140 /*
141  * SchedTune root control group
142  * The root control group is used to defined a system-wide boosting tuning,
143  * which is applied to all tasks in the system.
144  * Task specific boost tuning could be specified by creating and
145  * configuring a child control group under the root one.
146  * By default, system-wide boosting is disabled, i.e. no boosting is applied
147  * to tasks which are not into a child control group.
148  */
149 static struct schedtune
150 root_schedtune = {
151         .boost  = 0,
152         .perf_boost_idx = 0,
153         .perf_constrain_idx = 0,
154 };
155
156 int
157 schedtune_accept_deltas(int nrg_delta, int cap_delta,
158                         struct task_struct *task)
159 {
160         struct schedtune *ct;
161         int perf_boost_idx;
162         int perf_constrain_idx;
163
164         /* Optimal (O) region */
165         if (nrg_delta < 0 && cap_delta > 0) {
166                 trace_sched_tune_filter(nrg_delta, cap_delta, 0, 0, 1, 0);
167                 return INT_MAX;
168         }
169
170         /* Suboptimal (S) region */
171         if (nrg_delta > 0 && cap_delta < 0) {
172                 trace_sched_tune_filter(nrg_delta, cap_delta, 0, 0, -1, 5);
173                 return -INT_MAX;
174         }
175
176         /* Get task specific perf Boost/Constraints indexes */
177         rcu_read_lock();
178         ct = task_schedtune(task);
179         perf_boost_idx = ct->perf_boost_idx;
180         perf_constrain_idx = ct->perf_constrain_idx;
181         rcu_read_unlock();
182
183         return __schedtune_accept_deltas(nrg_delta, cap_delta,
184                         perf_boost_idx, perf_constrain_idx);
185 }
186
187 /*
188  * Maximum number of boost groups to support
189  * When per-task boosting is used we still allow only limited number of
190  * boost groups for two main reasons:
191  * 1. on a real system we usually have only few classes of workloads which
192  *    make sense to boost with different values (e.g. background vs foreground
193  *    tasks, interactive vs low-priority tasks)
194  * 2. a limited number allows for a simpler and more memory/time efficient
195  *    implementation especially for the computation of the per-CPU boost
196  *    value
197  */
198 #define BOOSTGROUPS_COUNT 4
199
200 /* Array of configured boostgroups */
201 static struct schedtune *allocated_group[BOOSTGROUPS_COUNT] = {
202         &root_schedtune,
203         NULL,
204 };
205
206 /* SchedTune boost groups
207  * Keep track of all the boost groups which impact on CPU, for example when a
208  * CPU has two RUNNABLE tasks belonging to two different boost groups and thus
209  * likely with different boost values.
210  * Since on each system we expect only a limited number of boost groups, here
211  * we use a simple array to keep track of the metrics required to compute the
212  * maximum per-CPU boosting value.
213  */
214 struct boost_groups {
215         /* Maximum boost value for all RUNNABLE tasks on a CPU */
216         bool idle;
217         int boost_max;
218         struct {
219                 /* The boost for tasks on that boost group */
220                 int boost;
221                 /* Count of RUNNABLE tasks on that boost group */
222                 unsigned tasks;
223         } group[BOOSTGROUPS_COUNT];
224 };
225
226 /* Boost groups affecting each CPU in the system */
227 DEFINE_PER_CPU(struct boost_groups, cpu_boost_groups);
228
229 static void
230 schedtune_cpu_update(int cpu)
231 {
232         struct boost_groups *bg;
233         int boost_max;
234         int idx;
235
236         bg = &per_cpu(cpu_boost_groups, cpu);
237
238         /* The root boost group is always active */
239         boost_max = bg->group[0].boost;
240         for (idx = 1; idx < BOOSTGROUPS_COUNT; ++idx) {
241                 /*
242                  * A boost group affects a CPU only if it has
243                  * RUNNABLE tasks on that CPU
244                  */
245                 if (bg->group[idx].tasks == 0)
246                         continue;
247
248                 boost_max = max(boost_max, bg->group[idx].boost);
249         }
250         /* Ensures boost_max is non-negative when all cgroup boost values
251          * are neagtive. Avoids under-accounting of cpu capacity which may cause
252          * task stacking and frequency spikes.*/
253         boost_max = max(boost_max, 0);
254         bg->boost_max = boost_max;
255 }
256
257 static int
258 schedtune_boostgroup_update(int idx, int boost)
259 {
260         struct boost_groups *bg;
261         int cur_boost_max;
262         int old_boost;
263         int cpu;
264
265         /* Update per CPU boost groups */
266         for_each_possible_cpu(cpu) {
267                 bg = &per_cpu(cpu_boost_groups, cpu);
268
269                 /*
270                  * Keep track of current boost values to compute the per CPU
271                  * maximum only when it has been affected by the new value of
272                  * the updated boost group
273                  */
274                 cur_boost_max = bg->boost_max;
275                 old_boost = bg->group[idx].boost;
276
277                 /* Update the boost value of this boost group */
278                 bg->group[idx].boost = boost;
279
280                 /* Check if this update increase current max */
281                 if (boost > cur_boost_max && bg->group[idx].tasks) {
282                         bg->boost_max = boost;
283                         trace_sched_tune_boostgroup_update(cpu, 1, bg->boost_max);
284                         continue;
285                 }
286
287                 /* Check if this update has decreased current max */
288                 if (cur_boost_max == old_boost && old_boost > boost) {
289                         schedtune_cpu_update(cpu);
290                         trace_sched_tune_boostgroup_update(cpu, -1, bg->boost_max);
291                         continue;
292                 }
293
294                 trace_sched_tune_boostgroup_update(cpu, 0, bg->boost_max);
295         }
296
297         return 0;
298 }
299
300 static inline void
301 schedtune_tasks_update(struct task_struct *p, int cpu, int idx, int task_count)
302 {
303         struct boost_groups *bg;
304         int tasks;
305
306         bg = &per_cpu(cpu_boost_groups, cpu);
307
308         /* Update boosted tasks count while avoiding to make it negative */
309         if (task_count < 0 && bg->group[idx].tasks <= -task_count)
310                 bg->group[idx].tasks = 0;
311         else
312                 bg->group[idx].tasks += task_count;
313
314         /* Boost group activation or deactivation on that RQ */
315         tasks = bg->group[idx].tasks;
316         if (tasks == 1 || tasks == 0)
317                 schedtune_cpu_update(cpu);
318
319         trace_sched_tune_tasks_update(p, cpu, tasks, idx,
320                         bg->group[idx].boost, bg->boost_max);
321
322 }
323
324 /*
325  * NOTE: This function must be called while holding the lock on the CPU RQ
326  */
327 void schedtune_enqueue_task(struct task_struct *p, int cpu)
328 {
329         struct schedtune *st;
330         int idx;
331
332         /*
333          * When a task is marked PF_EXITING by do_exit() it's going to be
334          * dequeued and enqueued multiple times in the exit path.
335          * Thus we avoid any further update, since we do not want to change
336          * CPU boosting while the task is exiting.
337          */
338         if (p->flags & PF_EXITING)
339                 return;
340
341         /* Get task boost group */
342         rcu_read_lock();
343         st = task_schedtune(p);
344         idx = st->idx;
345         rcu_read_unlock();
346
347         schedtune_tasks_update(p, cpu, idx, 1);
348 }
349
350 /*
351  * NOTE: This function must be called while holding the lock on the CPU RQ
352  */
353 void schedtune_dequeue_task(struct task_struct *p, int cpu)
354 {
355         struct schedtune *st;
356         int idx;
357
358         /*
359          * When a task is marked PF_EXITING by do_exit() it's going to be
360          * dequeued and enqueued multiple times in the exit path.
361          * Thus we avoid any further update, since we do not want to change
362          * CPU boosting while the task is exiting.
363          * The last dequeue will be done by cgroup exit() callback.
364          */
365         if (p->flags & PF_EXITING)
366                 return;
367
368         /* Get task boost group */
369         rcu_read_lock();
370         st = task_schedtune(p);
371         idx = st->idx;
372         rcu_read_unlock();
373
374         schedtune_tasks_update(p, cpu, idx, -1);
375 }
376
377 int schedtune_cpu_boost(int cpu)
378 {
379         struct boost_groups *bg;
380
381         bg = &per_cpu(cpu_boost_groups, cpu);
382         return bg->boost_max;
383 }
384
385 int schedtune_task_boost(struct task_struct *p)
386 {
387         struct schedtune *st;
388         int task_boost;
389
390         /* Get task boost value */
391         rcu_read_lock();
392         st = task_schedtune(p);
393         task_boost = st->boost;
394         rcu_read_unlock();
395
396         return task_boost;
397 }
398
399 static s64
400 boost_read(struct cgroup_subsys_state *css, struct cftype *cft)
401 {
402         struct schedtune *st = css_st(css);
403
404         return st->boost;
405 }
406
407 static int
408 boost_write(struct cgroup_subsys_state *css, struct cftype *cft,
409             s64 boost)
410 {
411         struct schedtune *st = css_st(css);
412         unsigned threshold_idx;
413         int boost_pct;
414
415         if (boost < -100 || boost > 100)
416                 return -EINVAL;
417
418         st->boost = boost;
419         if (css == &root_schedtune.css)
420                 sysctl_sched_cfs_boost = boost;
421
422         /* Update CPU boost */
423         schedtune_boostgroup_update(st->idx, st->boost);
424
425         trace_sched_tune_config(st->boost);
426
427         return 0;
428 }
429
430 static struct cftype files[] = {
431         {
432                 .name = "boost",
433                 .read_s64 = boost_read,
434                 .write_s64 = boost_write,
435         },
436         { }     /* terminate */
437 };
438
439 static int
440 schedtune_boostgroup_init(struct schedtune *st)
441 {
442         struct boost_groups *bg;
443         int cpu;
444
445         /* Keep track of allocated boost groups */
446         allocated_group[st->idx] = st;
447
448         /* Initialize the per CPU boost groups */
449         for_each_possible_cpu(cpu) {
450                 bg = &per_cpu(cpu_boost_groups, cpu);
451                 bg->group[st->idx].boost = 0;
452                 bg->group[st->idx].tasks = 0;
453         }
454
455         return 0;
456 }
457
458 static int
459 schedtune_init(void)
460 {
461         struct boost_groups *bg;
462         int cpu;
463
464         /* Initialize the per CPU boost groups */
465         for_each_possible_cpu(cpu) {
466                 bg = &per_cpu(cpu_boost_groups, cpu);
467                 memset(bg, 0, sizeof(struct boost_groups));
468         }
469
470         pr_info("  schedtune configured to support %d boost groups\n",
471                 BOOSTGROUPS_COUNT);
472         return 0;
473 }
474
475 static struct cgroup_subsys_state *
476 schedtune_css_alloc(struct cgroup_subsys_state *parent_css)
477 {
478         struct schedtune *st;
479         int idx;
480
481         if (!parent_css) {
482                 schedtune_init();
483                 return &root_schedtune.css;
484         }
485
486         /* Allow only single level hierachies */
487         if (parent_css != &root_schedtune.css) {
488                 pr_err("Nested SchedTune boosting groups not allowed\n");
489                 return ERR_PTR(-ENOMEM);
490         }
491
492         /* Allow only a limited number of boosting groups */
493         for (idx = 1; idx < BOOSTGROUPS_COUNT; ++idx)
494                 if (!allocated_group[idx])
495                         break;
496         if (idx == BOOSTGROUPS_COUNT) {
497                 pr_err("Trying to create more than %d SchedTune boosting groups\n",
498                        BOOSTGROUPS_COUNT);
499                 return ERR_PTR(-ENOSPC);
500         }
501
502         st = kzalloc(sizeof(*st), GFP_KERNEL);
503         if (!st)
504                 goto out;
505
506         /* Initialize per CPUs boost group support */
507         st->idx = idx;
508         if (schedtune_boostgroup_init(st))
509                 goto release;
510
511         return &st->css;
512
513 release:
514         kfree(st);
515 out:
516         return ERR_PTR(-ENOMEM);
517 }
518
519 static void
520 schedtune_boostgroup_release(struct schedtune *st)
521 {
522         /* Reset this boost group */
523         schedtune_boostgroup_update(st->idx, 0);
524
525         /* Keep track of allocated boost groups */
526         allocated_group[st->idx] = NULL;
527 }
528
529 static void
530 schedtune_css_free(struct cgroup_subsys_state *css)
531 {
532         struct schedtune *st = css_st(css);
533
534         schedtune_boostgroup_release(st);
535         kfree(st);
536 }
537
538 struct cgroup_subsys schedtune_cgrp_subsys = {
539         .css_alloc      = schedtune_css_alloc,
540         .css_free       = schedtune_css_free,
541         .legacy_cftypes = files,
542         .early_init     = 1,
543 };
544
545 #else /* CONFIG_CGROUP_SCHEDTUNE */
546
547 int
548 schedtune_accept_deltas(int nrg_delta, int cap_delta,
549                         struct task_struct *task)
550 {
551         /* Optimal (O) region */
552         if (nrg_delta < 0 && cap_delta > 0) {
553                 trace_sched_tune_filter(nrg_delta, cap_delta, 0, 0, 1, 0);
554                 return INT_MAX;
555         }
556
557         /* Suboptimal (S) region */
558         if (nrg_delta > 0 && cap_delta < 0) {
559                 trace_sched_tune_filter(nrg_delta, cap_delta, 0, 0, -1, 5);
560                 return -INT_MAX;
561         }
562
563         return __schedtune_accept_deltas(nrg_delta, cap_delta,
564                         perf_boost_idx, perf_constrain_idx);
565 }
566
567 #endif /* CONFIG_CGROUP_SCHEDTUNE */
568
569 int
570 sysctl_sched_cfs_boost_handler(struct ctl_table *table, int write,
571                                void __user *buffer, size_t *lenp,
572                                loff_t *ppos)
573 {
574         int ret = proc_dointvec_minmax(table, write, buffer, lenp, ppos);
575
576         if (ret || !write)
577                 return ret;
578
579         /* Performance Boost (B) region threshold params */
580         perf_boost_idx  = sysctl_sched_cfs_boost;
581         perf_boost_idx /= 10;
582
583         /* Performance Constraint (C) region threshold params */
584         perf_constrain_idx  = 100 - sysctl_sched_cfs_boost;
585         perf_constrain_idx /= 10;
586
587         return 0;
588 }
589
590 #ifdef CONFIG_SCHED_DEBUG
591 static void
592 schedtune_test_nrg(unsigned long delta_pwr)
593 {
594         unsigned long test_delta_pwr;
595         unsigned long test_norm_pwr;
596         int idx;
597
598         /*
599          * Check normalization constants using some constant system
600          * energy values
601          */
602         pr_info("schedtune: verify normalization constants...\n");
603         for (idx = 0; idx < 6; ++idx) {
604                 test_delta_pwr = delta_pwr >> idx;
605
606                 /* Normalize on max energy for target platform */
607                 test_norm_pwr = reciprocal_divide(
608                                         test_delta_pwr << SCHED_LOAD_SHIFT,
609                                         schedtune_target_nrg.rdiv);
610
611                 pr_info("schedtune: max_pwr/2^%d: %4lu => norm_pwr: %5lu\n",
612                         idx, test_delta_pwr, test_norm_pwr);
613         }
614 }
615 #else
616 #define schedtune_test_nrg(delta_pwr)
617 #endif
618
619 /*
620  * Compute the min/max power consumption of a cluster and all its CPUs
621  */
622 static void
623 schedtune_add_cluster_nrg(
624                 struct sched_domain *sd,
625                 struct sched_group *sg,
626                 struct target_nrg *ste)
627 {
628         struct sched_domain *sd2;
629         struct sched_group *sg2;
630
631         struct cpumask *cluster_cpus;
632         char str[32];
633
634         unsigned long min_pwr;
635         unsigned long max_pwr;
636         int cpu;
637
638         /* Get Cluster energy using EM data for the first CPU */
639         cluster_cpus = sched_group_cpus(sg);
640         snprintf(str, 32, "CLUSTER[%*pbl]",
641                  cpumask_pr_args(cluster_cpus));
642
643         min_pwr = sg->sge->idle_states[sg->sge->nr_idle_states - 1].power;
644         max_pwr = sg->sge->cap_states[sg->sge->nr_cap_states - 1].power;
645         pr_info("schedtune: %-17s min_pwr: %5lu max_pwr: %5lu\n",
646                 str, min_pwr, max_pwr);
647
648         /*
649          * Keep track of this cluster's energy in the computation of the
650          * overall system energy
651          */
652         ste->min_power += min_pwr;
653         ste->max_power += max_pwr;
654
655         /* Get CPU energy using EM data for each CPU in the group */
656         for_each_cpu(cpu, cluster_cpus) {
657                 /* Get a SD view for the specific CPU */
658                 for_each_domain(cpu, sd2) {
659                         /* Get the CPU group */
660                         sg2 = sd2->groups;
661                         min_pwr = sg2->sge->idle_states[sg2->sge->nr_idle_states - 1].power;
662                         max_pwr = sg2->sge->cap_states[sg2->sge->nr_cap_states - 1].power;
663
664                         ste->min_power += min_pwr;
665                         ste->max_power += max_pwr;
666
667                         snprintf(str, 32, "CPU[%d]", cpu);
668                         pr_info("schedtune: %-17s min_pwr: %5lu max_pwr: %5lu\n",
669                                 str, min_pwr, max_pwr);
670
671                         /*
672                          * Assume we have EM data only at the CPU and
673                          * the upper CLUSTER level
674                          */
675                         BUG_ON(!cpumask_equal(
676                                 sched_group_cpus(sg),
677                                 sched_group_cpus(sd2->parent->groups)
678                                 ));
679                         break;
680                 }
681         }
682 }
683
684 /*
685  * Initialize the constants required to compute normalized energy.
686  * The values of these constants depends on the EM data for the specific
687  * target system and topology.
688  * Thus, this function is expected to be called by the code
689  * that bind the EM to the topology information.
690  */
691 static int
692 schedtune_init_late(void)
693 {
694         struct target_nrg *ste = &schedtune_target_nrg;
695         unsigned long delta_pwr = 0;
696         struct sched_domain *sd;
697         struct sched_group *sg;
698
699         pr_info("schedtune: init normalization constants...\n");
700         ste->max_power = 0;
701         ste->min_power = 0;
702
703         rcu_read_lock();
704
705         /*
706          * When EAS is in use, we always have a pointer to the highest SD
707          * which provides EM data.
708          */
709         sd = rcu_dereference(per_cpu(sd_ea, cpumask_first(cpu_online_mask)));
710         if (!sd) {
711                 pr_info("schedtune: no energy model data\n");
712                 goto nodata;
713         }
714
715         sg = sd->groups;
716         do {
717                 schedtune_add_cluster_nrg(sd, sg, ste);
718         } while (sg = sg->next, sg != sd->groups);
719
720         rcu_read_unlock();
721
722         pr_info("schedtune: %-17s min_pwr: %5lu max_pwr: %5lu\n",
723                 "SYSTEM", ste->min_power, ste->max_power);
724
725         /* Compute normalization constants */
726         delta_pwr = ste->max_power - ste->min_power;
727         ste->rdiv = reciprocal_value(delta_pwr);
728         pr_info("schedtune: using normalization constants mul: %u sh1: %u sh2: %u\n",
729                 ste->rdiv.m, ste->rdiv.sh1, ste->rdiv.sh2);
730
731         schedtune_test_nrg(delta_pwr);
732         return 0;
733
734 nodata:
735         rcu_read_unlock();
736         return -EINVAL;
737 }
738 late_initcall(schedtune_init_late);