topology.c 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * driver/base/topology.c - Populate sysfs with cpu topology information
  4. *
  5. * Written by: Zhang Yanmin, Intel Corporation
  6. *
  7. * Copyright (C) 2006, Intel Corp.
  8. *
  9. * All rights reserved.
  10. */
  11. #include <linux/mm.h>
  12. #include <linux/cpu.h>
  13. #include <linux/module.h>
  14. #include <linux/hardirq.h>
  15. #include <linux/topology.h>
  16. #define define_id_show_func(name, fmt) \
  17. static ssize_t name##_show(struct device *dev, \
  18. struct device_attribute *attr, char *buf) \
  19. { \
  20. return sysfs_emit(buf, fmt "\n", topology_##name(dev->id)); \
  21. }
  22. #define define_siblings_read_func(name, mask) \
  23. static ssize_t name##_read(struct file *file, struct kobject *kobj, \
  24. const struct bin_attribute *attr, char *buf, \
  25. loff_t off, size_t count) \
  26. { \
  27. struct device *dev = kobj_to_dev(kobj); \
  28. cpumask_var_t mask; \
  29. ssize_t n; \
  30. \
  31. if (!alloc_cpumask_var(&mask, GFP_KERNEL)) \
  32. return -ENOMEM; \
  33. \
  34. cpumask_copy(mask, topology_##mask(dev->id)); \
  35. n = cpumap_print_bitmask_to_buf(buf, mask, off, count); \
  36. free_cpumask_var(mask); \
  37. \
  38. return n; \
  39. } \
  40. \
  41. static ssize_t name##_list_read(struct file *file, struct kobject *kobj, \
  42. const struct bin_attribute *attr, char *buf, \
  43. loff_t off, size_t count) \
  44. { \
  45. struct device *dev = kobj_to_dev(kobj); \
  46. cpumask_var_t mask; \
  47. ssize_t n; \
  48. \
  49. if (!alloc_cpumask_var(&mask, GFP_KERNEL)) \
  50. return -ENOMEM; \
  51. \
  52. cpumask_copy(mask, topology_##mask(dev->id)); \
  53. n = cpumap_print_list_to_buf(buf, mask, off, count); \
  54. free_cpumask_var(mask); \
  55. \
  56. return n; \
  57. }
  58. define_id_show_func(physical_package_id, "%d");
  59. static DEVICE_ATTR_RO(physical_package_id);
  60. #ifdef TOPOLOGY_DIE_SYSFS
  61. define_id_show_func(die_id, "%d");
  62. static DEVICE_ATTR_RO(die_id);
  63. #endif
  64. #ifdef TOPOLOGY_CLUSTER_SYSFS
  65. define_id_show_func(cluster_id, "%d");
  66. static DEVICE_ATTR_RO(cluster_id);
  67. #endif
  68. define_id_show_func(core_id, "%d");
  69. static DEVICE_ATTR_RO(core_id);
  70. define_id_show_func(ppin, "0x%llx");
  71. static DEVICE_ATTR_ADMIN_RO(ppin);
  72. define_siblings_read_func(thread_siblings, sibling_cpumask);
  73. static const BIN_ATTR_RO(thread_siblings, CPUMAP_FILE_MAX_BYTES);
  74. static const BIN_ATTR_RO(thread_siblings_list, CPULIST_FILE_MAX_BYTES);
  75. define_siblings_read_func(core_cpus, sibling_cpumask);
  76. static const BIN_ATTR_RO(core_cpus, CPUMAP_FILE_MAX_BYTES);
  77. static const BIN_ATTR_RO(core_cpus_list, CPULIST_FILE_MAX_BYTES);
  78. define_siblings_read_func(core_siblings, core_cpumask);
  79. static const BIN_ATTR_RO(core_siblings, CPUMAP_FILE_MAX_BYTES);
  80. static const BIN_ATTR_RO(core_siblings_list, CPULIST_FILE_MAX_BYTES);
  81. #ifdef TOPOLOGY_CLUSTER_SYSFS
  82. define_siblings_read_func(cluster_cpus, cluster_cpumask);
  83. static const BIN_ATTR_RO(cluster_cpus, CPUMAP_FILE_MAX_BYTES);
  84. static const BIN_ATTR_RO(cluster_cpus_list, CPULIST_FILE_MAX_BYTES);
  85. #endif
  86. #ifdef TOPOLOGY_DIE_SYSFS
  87. define_siblings_read_func(die_cpus, die_cpumask);
  88. static const BIN_ATTR_RO(die_cpus, CPUMAP_FILE_MAX_BYTES);
  89. static const BIN_ATTR_RO(die_cpus_list, CPULIST_FILE_MAX_BYTES);
  90. #endif
  91. define_siblings_read_func(package_cpus, core_cpumask);
  92. static const BIN_ATTR_RO(package_cpus, CPUMAP_FILE_MAX_BYTES);
  93. static const BIN_ATTR_RO(package_cpus_list, CPULIST_FILE_MAX_BYTES);
  94. #ifdef TOPOLOGY_BOOK_SYSFS
  95. define_id_show_func(book_id, "%d");
  96. static DEVICE_ATTR_RO(book_id);
  97. define_siblings_read_func(book_siblings, book_cpumask);
  98. static const BIN_ATTR_RO(book_siblings, CPUMAP_FILE_MAX_BYTES);
  99. static const BIN_ATTR_RO(book_siblings_list, CPULIST_FILE_MAX_BYTES);
  100. #endif
  101. #ifdef TOPOLOGY_DRAWER_SYSFS
  102. define_id_show_func(drawer_id, "%d");
  103. static DEVICE_ATTR_RO(drawer_id);
  104. define_siblings_read_func(drawer_siblings, drawer_cpumask);
  105. static const BIN_ATTR_RO(drawer_siblings, CPUMAP_FILE_MAX_BYTES);
  106. static const BIN_ATTR_RO(drawer_siblings_list, CPULIST_FILE_MAX_BYTES);
  107. #endif
  108. static const struct bin_attribute *const bin_attrs[] = {
  109. &bin_attr_core_cpus,
  110. &bin_attr_core_cpus_list,
  111. &bin_attr_thread_siblings,
  112. &bin_attr_thread_siblings_list,
  113. &bin_attr_core_siblings,
  114. &bin_attr_core_siblings_list,
  115. #ifdef TOPOLOGY_CLUSTER_SYSFS
  116. &bin_attr_cluster_cpus,
  117. &bin_attr_cluster_cpus_list,
  118. #endif
  119. #ifdef TOPOLOGY_DIE_SYSFS
  120. &bin_attr_die_cpus,
  121. &bin_attr_die_cpus_list,
  122. #endif
  123. &bin_attr_package_cpus,
  124. &bin_attr_package_cpus_list,
  125. #ifdef TOPOLOGY_BOOK_SYSFS
  126. &bin_attr_book_siblings,
  127. &bin_attr_book_siblings_list,
  128. #endif
  129. #ifdef TOPOLOGY_DRAWER_SYSFS
  130. &bin_attr_drawer_siblings,
  131. &bin_attr_drawer_siblings_list,
  132. #endif
  133. NULL
  134. };
  135. static struct attribute *default_attrs[] = {
  136. &dev_attr_physical_package_id.attr,
  137. #ifdef TOPOLOGY_DIE_SYSFS
  138. &dev_attr_die_id.attr,
  139. #endif
  140. #ifdef TOPOLOGY_CLUSTER_SYSFS
  141. &dev_attr_cluster_id.attr,
  142. #endif
  143. &dev_attr_core_id.attr,
  144. #ifdef TOPOLOGY_BOOK_SYSFS
  145. &dev_attr_book_id.attr,
  146. #endif
  147. #ifdef TOPOLOGY_DRAWER_SYSFS
  148. &dev_attr_drawer_id.attr,
  149. #endif
  150. &dev_attr_ppin.attr,
  151. NULL
  152. };
  153. static umode_t topology_is_visible(struct kobject *kobj,
  154. struct attribute *attr, int unused)
  155. {
  156. if (attr == &dev_attr_ppin.attr && !topology_ppin(kobj_to_dev(kobj)->id))
  157. return 0;
  158. return attr->mode;
  159. }
  160. static const struct attribute_group topology_attr_group = {
  161. .attrs = default_attrs,
  162. .bin_attrs = bin_attrs,
  163. .is_visible = topology_is_visible,
  164. .name = "topology"
  165. };
  166. /* Add/Remove cpu_topology interface for CPU device */
  167. static int topology_add_dev(unsigned int cpu)
  168. {
  169. struct device *dev = get_cpu_device(cpu);
  170. return sysfs_create_group(&dev->kobj, &topology_attr_group);
  171. }
  172. static int topology_remove_dev(unsigned int cpu)
  173. {
  174. struct device *dev = get_cpu_device(cpu);
  175. sysfs_remove_group(&dev->kobj, &topology_attr_group);
  176. return 0;
  177. }
  178. static int __init topology_sysfs_init(void)
  179. {
  180. return cpuhp_setup_state(CPUHP_TOPOLOGY_PREPARE,
  181. "base/topology:prepare", topology_add_dev,
  182. topology_remove_dev);
  183. }
  184. device_initcall(topology_sysfs_init);
  185. DEFINE_PER_CPU(unsigned long, cpu_scale) = SCHED_CAPACITY_SCALE;
  186. EXPORT_PER_CPU_SYMBOL_GPL(cpu_scale);
  187. void topology_set_cpu_scale(unsigned int cpu, unsigned long capacity)
  188. {
  189. per_cpu(cpu_scale, cpu) = capacity;
  190. }
  191. static ssize_t cpu_capacity_show(struct device *dev,
  192. struct device_attribute *attr,
  193. char *buf)
  194. {
  195. struct cpu *cpu = container_of(dev, struct cpu, dev);
  196. return sysfs_emit(buf, "%lu\n", topology_get_cpu_scale(cpu->dev.id));
  197. }
  198. static DEVICE_ATTR_RO(cpu_capacity);
  199. static int cpu_capacity_sysctl_add(unsigned int cpu)
  200. {
  201. struct device *cpu_dev = get_cpu_device(cpu);
  202. if (!cpu_dev)
  203. return -ENOENT;
  204. device_create_file(cpu_dev, &dev_attr_cpu_capacity);
  205. return 0;
  206. }
  207. static int cpu_capacity_sysctl_remove(unsigned int cpu)
  208. {
  209. struct device *cpu_dev = get_cpu_device(cpu);
  210. if (!cpu_dev)
  211. return -ENOENT;
  212. device_remove_file(cpu_dev, &dev_attr_cpu_capacity);
  213. return 0;
  214. }
  215. static int register_cpu_capacity_sysctl(void)
  216. {
  217. cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "topology/cpu-capacity",
  218. cpu_capacity_sysctl_add, cpu_capacity_sysctl_remove);
  219. return 0;
  220. }
  221. subsys_initcall(register_cpu_capacity_sysctl);