itmt.c 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212
  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. #include <linux/sched.h>
  23. #include <linux/cpumask.h>
  24. #include <linux/cpuset.h>
  25. #include <linux/mutex.h>
  26. #include <linux/sysctl.h>
  27. #include <linux/nodemask.h>
  28. static DEFINE_MUTEX(itmt_update_mutex);
  29. DEFINE_PER_CPU_READ_MOSTLY(int, sched_core_priority);
  30. /* Boolean to track if system has ITMT capabilities */
  31. static bool __read_mostly sched_itmt_capable;
  32. /*
  33. * Boolean to control whether we want to move processes to cpu capable
  34. * of higher turbo frequency for cpus supporting Intel Turbo Boost Max
  35. * Technology 3.0.
  36. *
  37. * It can be set via /proc/sys/kernel/sched_itmt_enabled
  38. */
  39. unsigned int __read_mostly sysctl_sched_itmt_enabled;
  40. static int sched_itmt_update_handler(struct ctl_table *table, int write,
  41. void __user *buffer, size_t *lenp,
  42. loff_t *ppos)
  43. {
  44. unsigned int old_sysctl;
  45. int ret;
  46. mutex_lock(&itmt_update_mutex);
  47. if (!sched_itmt_capable) {
  48. mutex_unlock(&itmt_update_mutex);
  49. return -EINVAL;
  50. }
  51. old_sysctl = sysctl_sched_itmt_enabled;
  52. ret = proc_dointvec_minmax(table, write, buffer, lenp, ppos);
  53. if (!ret && write && old_sysctl != sysctl_sched_itmt_enabled) {
  54. x86_topology_update = true;
  55. rebuild_sched_domains();
  56. }
  57. mutex_unlock(&itmt_update_mutex);
  58. return ret;
  59. }
  60. static unsigned int zero;
  61. static unsigned int one = 1;
  62. static struct ctl_table itmt_kern_table[] = {
  63. {
  64. .procname = "sched_itmt_enabled",
  65. .data = &sysctl_sched_itmt_enabled,
  66. .maxlen = sizeof(unsigned int),
  67. .mode = 0644,
  68. .proc_handler = sched_itmt_update_handler,
  69. .extra1 = &zero,
  70. .extra2 = &one,
  71. },
  72. {}
  73. };
  74. static struct ctl_table itmt_root_table[] = {
  75. {
  76. .procname = "kernel",
  77. .mode = 0555,
  78. .child = itmt_kern_table,
  79. },
  80. {}
  81. };
  82. static struct ctl_table_header *itmt_sysctl_header;
  83. /**
  84. * sched_set_itmt_support() - Indicate platform supports ITMT
  85. *
  86. * This function is used by the OS to indicate to scheduler that the platform
  87. * is capable of supporting the ITMT feature.
  88. *
  89. * The current scheme has the pstate driver detects if the system
  90. * is ITMT capable and call sched_set_itmt_support.
  91. *
  92. * This must be done only after sched_set_itmt_core_prio
  93. * has been called to set the cpus' priorities.
  94. * It must not be called with cpu hot plug lock
  95. * held as we need to acquire the lock to rebuild sched domains
  96. * later.
  97. *
  98. * Return: 0 on success
  99. */
  100. int sched_set_itmt_support(void)
  101. {
  102. mutex_lock(&itmt_update_mutex);
  103. if (sched_itmt_capable) {
  104. mutex_unlock(&itmt_update_mutex);
  105. return 0;
  106. }
  107. itmt_sysctl_header = register_sysctl_table(itmt_root_table);
  108. if (!itmt_sysctl_header) {
  109. mutex_unlock(&itmt_update_mutex);
  110. return -ENOMEM;
  111. }
  112. sched_itmt_capable = true;
  113. sysctl_sched_itmt_enabled = 1;
  114. x86_topology_update = true;
  115. rebuild_sched_domains();
  116. mutex_unlock(&itmt_update_mutex);
  117. return 0;
  118. }
  119. /**
  120. * sched_clear_itmt_support() - Revoke platform's support of ITMT
  121. *
  122. * This function is used by the OS to indicate that it has
  123. * revoked the platform's support of ITMT feature.
  124. *
  125. * It must not be called with cpu hot plug lock
  126. * held as we need to acquire the lock to rebuild sched domains
  127. * later.
  128. */
  129. void sched_clear_itmt_support(void)
  130. {
  131. mutex_lock(&itmt_update_mutex);
  132. if (!sched_itmt_capable) {
  133. mutex_unlock(&itmt_update_mutex);
  134. return;
  135. }
  136. sched_itmt_capable = false;
  137. if (itmt_sysctl_header) {
  138. unregister_sysctl_table(itmt_sysctl_header);
  139. itmt_sysctl_header = NULL;
  140. }
  141. if (sysctl_sched_itmt_enabled) {
  142. /* disable sched_itmt if we are no longer ITMT capable */
  143. sysctl_sched_itmt_enabled = 0;
  144. x86_topology_update = true;
  145. rebuild_sched_domains();
  146. }
  147. mutex_unlock(&itmt_update_mutex);
  148. }
  149. int arch_asym_cpu_priority(int cpu)
  150. {
  151. return per_cpu(sched_core_priority, cpu);
  152. }
  153. /**
  154. * sched_set_itmt_core_prio() - Set CPU priority based on ITMT
  155. * @prio: Priority of cpu core
  156. * @core_cpu: The cpu number associated with the core
  157. *
  158. * The pstate driver will find out the max boost frequency
  159. * and call this function to set a priority proportional
  160. * to the max boost frequency. CPU with higher boost
  161. * frequency will receive higher priority.
  162. *
  163. * No need to rebuild sched domain after updating
  164. * the CPU priorities. The sched domains have no
  165. * dependency on CPU priorities.
  166. */
  167. void sched_set_itmt_core_prio(int prio, int core_cpu)
  168. {
  169. int cpu, i = 1;
  170. for_each_cpu(cpu, topology_sibling_cpumask(core_cpu)) {
  171. int smt_prio;
  172. /*
  173. * Ensure that the siblings are moved to the end
  174. * of the priority chain and only used when
  175. * all other high priority cpus are out of capacity.
  176. */
  177. smt_prio = prio * smp_num_siblings / i;
  178. per_cpu(sched_core_priority, cpu) = smt_prio;
  179. i++;
  180. }
  181. }