xref: /openbmc/linux/arch/x86/kernel/itmt.c (revision 5e76b2ab)
1 /*
2  * itmt.c: Support Intel Turbo Boost Max Technology 3.0
3  *
4  * (C) Copyright 2016 Intel Corporation
5  * Author: Tim Chen <tim.c.chen@linux.intel.com>
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; version 2
10  * of the License.
11  *
12  * On platforms supporting Intel Turbo Boost Max Technology 3.0, (ITMT),
13  * the maximum turbo frequencies of some cores in a CPU package may be
14  * higher than for the other cores in the same package.  In that case,
15  * better performance can be achieved by making the scheduler prefer
16  * to run tasks on the CPUs with higher max turbo frequencies.
17  *
18  * This file provides functions and data structures for enabling the
19  * scheduler to favor scheduling on cores can be boosted to a higher
20  * frequency under ITMT.
21  */
22 
23 #include <linux/sched.h>
24 #include <linux/cpumask.h>
25 #include <linux/cpuset.h>
26 #include <asm/mutex.h>
27 #include <linux/sched.h>
28 #include <linux/sysctl.h>
29 #include <linux/nodemask.h>
30 
31 static DEFINE_MUTEX(itmt_update_mutex);
32 DEFINE_PER_CPU_READ_MOSTLY(int, sched_core_priority);
33 
34 /* Boolean to track if system has ITMT capabilities */
35 static bool __read_mostly sched_itmt_capable;
36 
37 /**
38  * sched_set_itmt_support() - Indicate platform supports ITMT
39  *
40  * This function is used by the OS to indicate to scheduler that the platform
41  * is capable of supporting the ITMT feature.
42  *
43  * The current scheme has the pstate driver detects if the system
44  * is ITMT capable and call sched_set_itmt_support.
45  *
46  * This must be done only after sched_set_itmt_core_prio
47  * has been called to set the cpus' priorities.
48  */
49 void sched_set_itmt_support(void)
50 {
51 	mutex_lock(&itmt_update_mutex);
52 
53 	sched_itmt_capable = true;
54 
55 	mutex_unlock(&itmt_update_mutex);
56 }
57 
58 /**
59  * sched_clear_itmt_support() - Revoke platform's support of ITMT
60  *
61  * This function is used by the OS to indicate that it has
62  * revoked the platform's support of ITMT feature.
63  *
64  */
65 void sched_clear_itmt_support(void)
66 {
67 	mutex_lock(&itmt_update_mutex);
68 
69 	sched_itmt_capable = false;
70 
71 	mutex_unlock(&itmt_update_mutex);
72 }
73 
74 int arch_asym_cpu_priority(int cpu)
75 {
76 	return per_cpu(sched_core_priority, cpu);
77 }
78 
79 /**
80  * sched_set_itmt_core_prio() - Set CPU priority based on ITMT
81  * @prio:	Priority of cpu core
82  * @core_cpu:	The cpu number associated with the core
83  *
84  * The pstate driver will find out the max boost frequency
85  * and call this function to set a priority proportional
86  * to the max boost frequency. CPU with higher boost
87  * frequency will receive higher priority.
88  *
89  * No need to rebuild sched domain after updating
90  * the CPU priorities. The sched domains have no
91  * dependency on CPU priorities.
92  */
93 void sched_set_itmt_core_prio(int prio, int core_cpu)
94 {
95 	int cpu, i = 1;
96 
97 	for_each_cpu(cpu, topology_sibling_cpumask(core_cpu)) {
98 		int smt_prio;
99 
100 		/*
101 		 * Ensure that the siblings are moved to the end
102 		 * of the priority chain and only used when
103 		 * all other high priority cpus are out of capacity.
104 		 */
105 		smt_prio = prio * smp_num_siblings / i;
106 		per_cpu(sched_core_priority, cpu) = smt_prio;
107 		i++;
108 	}
109 }
110