itmt.c 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * itmt.c: Support Intel Turbo Boost Max Technology 3.0
  4. *
  5. * (C) Copyright 2016 Intel Corporation
  6. * Author: Tim Chen <tim.c.chen@linux.intel.com>
  7. *
  8. * On platforms supporting Intel Turbo Boost Max Technology 3.0, (ITMT),
  9. * the maximum turbo frequencies of some cores in a CPU package may be
  10. * higher than for the other cores in the same package. In that case,
  11. * better performance can be achieved by making the scheduler prefer
  12. * to run tasks on the CPUs with higher max turbo frequencies.
  13. *
  14. * This file provides functions and data structures for enabling the
  15. * scheduler to favor scheduling on cores can be boosted to a higher
  16. * frequency under ITMT.
  17. */
  18. #include <linux/sched.h>
  19. #include <linux/cpumask.h>
  20. #include <linux/cpuset.h>
  21. #include <linux/mutex.h>
  22. #include <linux/sysctl.h>
  23. #include <linux/nodemask.h>
  24. static DEFINE_MUTEX(itmt_update_mutex);
  25. DEFINE_PER_CPU_READ_MOSTLY(int, sched_core_priority);
  26. /* Boolean to track if system has ITMT capabilities */
  27. static bool __read_mostly sched_itmt_capable;
  28. /*
  29. * Boolean to control whether we want to move processes to cpu capable
  30. * of higher turbo frequency for cpus supporting Intel Turbo Boost Max
  31. * Technology 3.0.
  32. *
  33. * It can be set via /proc/sys/kernel/sched_itmt_enabled
  34. */
  35. unsigned int __read_mostly sysctl_sched_itmt_enabled;
  36. static int sched_itmt_update_handler(const struct ctl_table *table, int write,
  37. void *buffer, size_t *lenp, loff_t *ppos)
  38. {
  39. unsigned int old_sysctl;
  40. int ret;
  41. mutex_lock(&itmt_update_mutex);
  42. if (!sched_itmt_capable) {
  43. mutex_unlock(&itmt_update_mutex);
  44. return -EINVAL;
  45. }
  46. old_sysctl = sysctl_sched_itmt_enabled;
  47. ret = proc_dointvec_minmax(table, write, buffer, lenp, ppos);
  48. if (!ret && write && old_sysctl != sysctl_sched_itmt_enabled) {
  49. x86_topology_update = true;
  50. rebuild_sched_domains();
  51. }
  52. mutex_unlock(&itmt_update_mutex);
  53. return ret;
  54. }
  55. static struct ctl_table itmt_kern_table[] = {
  56. {
  57. .procname = "sched_itmt_enabled",
  58. .data = &sysctl_sched_itmt_enabled,
  59. .maxlen = sizeof(unsigned int),
  60. .mode = 0644,
  61. .proc_handler = sched_itmt_update_handler,
  62. .extra1 = SYSCTL_ZERO,
  63. .extra2 = SYSCTL_ONE,
  64. },
  65. };
  66. static struct ctl_table_header *itmt_sysctl_header;
  67. /**
  68. * sched_set_itmt_support() - Indicate platform supports ITMT
  69. *
  70. * This function is used by the OS to indicate to scheduler that the platform
  71. * is capable of supporting the ITMT feature.
  72. *
  73. * The current scheme has the pstate driver detects if the system
  74. * is ITMT capable and call sched_set_itmt_support.
  75. *
  76. * This must be done only after sched_set_itmt_core_prio
  77. * has been called to set the cpus' priorities.
  78. * It must not be called with cpu hot plug lock
  79. * held as we need to acquire the lock to rebuild sched domains
  80. * later.
  81. *
  82. * Return: 0 on success
  83. */
  84. int sched_set_itmt_support(void)
  85. {
  86. mutex_lock(&itmt_update_mutex);
  87. if (sched_itmt_capable) {
  88. mutex_unlock(&itmt_update_mutex);
  89. return 0;
  90. }
  91. itmt_sysctl_header = register_sysctl("kernel", itmt_kern_table);
  92. if (!itmt_sysctl_header) {
  93. mutex_unlock(&itmt_update_mutex);
  94. return -ENOMEM;
  95. }
  96. sched_itmt_capable = true;
  97. sysctl_sched_itmt_enabled = 1;
  98. x86_topology_update = true;
  99. rebuild_sched_domains();
  100. mutex_unlock(&itmt_update_mutex);
  101. return 0;
  102. }
  103. /**
  104. * sched_clear_itmt_support() - Revoke platform's support of ITMT
  105. *
  106. * This function is used by the OS to indicate that it has
  107. * revoked the platform's support of ITMT feature.
  108. *
  109. * It must not be called with cpu hot plug lock
  110. * held as we need to acquire the lock to rebuild sched domains
  111. * later.
  112. */
  113. void sched_clear_itmt_support(void)
  114. {
  115. mutex_lock(&itmt_update_mutex);
  116. if (!sched_itmt_capable) {
  117. mutex_unlock(&itmt_update_mutex);
  118. return;
  119. }
  120. sched_itmt_capable = false;
  121. if (itmt_sysctl_header) {
  122. unregister_sysctl_table(itmt_sysctl_header);
  123. itmt_sysctl_header = NULL;
  124. }
  125. if (sysctl_sched_itmt_enabled) {
  126. /* disable sched_itmt if we are no longer ITMT capable */
  127. sysctl_sched_itmt_enabled = 0;
  128. x86_topology_update = true;
  129. rebuild_sched_domains();
  130. }
  131. mutex_unlock(&itmt_update_mutex);
  132. }
  133. int arch_asym_cpu_priority(int cpu)
  134. {
  135. return per_cpu(sched_core_priority, cpu);
  136. }
  137. /**
  138. * sched_set_itmt_core_prio() - Set CPU priority based on ITMT
  139. * @prio: Priority of @cpu
  140. * @cpu: The CPU number
  141. *
  142. * The pstate driver will find out the max boost frequency
  143. * and call this function to set a priority proportional
  144. * to the max boost frequency. CPUs with higher boost
  145. * frequency will receive higher priority.
  146. *
  147. * No need to rebuild sched domain after updating
  148. * the CPU priorities. The sched domains have no
  149. * dependency on CPU priorities.
  150. */
  151. void sched_set_itmt_core_prio(int prio, int cpu)
  152. {
  153. per_cpu(sched_core_priority, cpu) = prio;
  154. }