Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge tag 'common/for-v5.4-rc1/cpu-topology' of git://git.kernel.org/pub/scm/linux/kernel/git/riscv/linux into for-next/cpu-topology

Pull in generic CPU topology changes from Paul Walmsley (RISC-V).

* tag 'common/for-v5.4-rc1/cpu-topology' of git://git.kernel.org/pub/scm/linux/kernel/git/riscv/linux:
MAINTAINERS: Add an entry for generic architecture topology
base: arch_topology: update Kconfig help description
RISC-V: Parse cpu topology during boot.
arm: Use common cpu_topology structure and functions.
cpu-topology: Move cpu topology code to common code.
dt-binding: cpu-topology: Move cpu-map to a common binding.
Documentation: DT: arm: add support for sockets defining package boundaries

+515 -487
+168 -90
Documentation/devicetree/bindings/arm/topology.txt Documentation/devicetree/bindings/cpu/cpu-topology.txt
··· 1 1 =========================================== 2 - ARM topology binding description 2 + CPU topology binding description 3 3 =========================================== 4 4 5 5 =========================================== 6 6 1 - Introduction 7 7 =========================================== 8 8 9 - In an ARM system, the hierarchy of CPUs is defined through three entities that 9 + In a SMP system, the hierarchy of CPUs is defined through three entities that 10 10 are used to describe the layout of physical CPUs in the system: 11 11 12 + - socket 12 13 - cluster 13 14 - core 14 15 - thread 15 - 16 - The cpu nodes (bindings defined in [1]) represent the devices that 17 - correspond to physical CPUs and are to be mapped to the hierarchy levels. 18 16 19 17 The bottom hierarchy level sits at core or thread level depending on whether 20 18 symmetric multi-threading (SMT) is supported or not. ··· 22 24 In systems where SMT is not supported "cpu" nodes represent all cores present 23 25 in the system and map to the hierarchy level "core" above. 24 26 25 - ARM topology bindings allow one to associate cpu nodes with hierarchical groups 27 + CPU topology bindings allow one to associate cpu nodes with hierarchical groups 26 28 corresponding to the system hierarchy; syntactically they are defined as device 27 29 tree nodes. 28 30 29 - The remainder of this document provides the topology bindings for ARM, based 30 - on the Devicetree Specification, available from: 31 + Currently, only ARM/RISC-V intend to use this cpu topology binding but it may be 32 + used for any other architecture as well. 31 33 32 - https://www.devicetree.org/specifications/ 34 + The cpu nodes, as per bindings defined in [4], represent the devices that 35 + correspond to physical CPUs and are to be mapped to the hierarchy levels. 33 36 34 - If not stated otherwise, whenever a reference to a cpu node phandle is made its 35 - value must point to a cpu node compliant with the cpu node bindings as 36 - documented in [1]. 37 37 A topology description containing phandles to cpu nodes that are not compliant 38 - with bindings standardized in [1] is therefore considered invalid. 38 + with bindings standardized in [4] is therefore considered invalid. 39 39 40 40 =========================================== 41 41 2 - cpu-map node 42 42 =========================================== 43 43 44 - The ARM CPU topology is defined within the cpu-map node, which is a direct 44 + The ARM/RISC-V CPU topology is defined within the cpu-map node, which is a direct 45 45 child of the cpus node and provides a container where the actual topology 46 46 nodes are listed. 47 47 48 48 - cpu-map node 49 49 50 - Usage: Optional - On ARM SMP systems provide CPUs topology to the OS. 51 - ARM uniprocessor systems do not require a topology 50 + Usage: Optional - On SMP systems provide CPUs topology to the OS. 51 + Uniprocessor systems do not require a topology 52 52 description and therefore should not define a 53 53 cpu-map node. 54 54 ··· 59 63 60 64 The cpu-map node's child nodes can be: 61 65 62 - - one or more cluster nodes 66 + - one or more cluster nodes or 67 + - one or more socket nodes in a multi-socket system 63 68 64 69 Any other configuration is considered invalid. 65 70 66 - The cpu-map node can only contain three types of child nodes: 71 + The cpu-map node can only contain 4 types of child nodes: 67 72 73 + - socket node 68 74 - cluster node 69 75 - core node 70 76 - thread node 71 77 72 78 whose bindings are described in paragraph 3. 73 79 74 - The nodes describing the CPU topology (cluster/core/thread) can only 75 - be defined within the cpu-map node and every core/thread in the system 76 - must be defined within the topology. Any other configuration is 80 + The nodes describing the CPU topology (socket/cluster/core/thread) can 81 + only be defined within the cpu-map node and every core/thread in the 82 + system must be defined within the topology. Any other configuration is 77 83 invalid and therefore must be ignored. 78 84 79 85 =========================================== ··· 83 85 =========================================== 84 86 85 87 cpu-map child nodes must follow a naming convention where the node name 86 - must be "clusterN", "coreN", "threadN" depending on the node type (ie 87 - cluster/core/thread) (where N = {0, 1, ...} is the node number; nodes which 88 - are siblings within a single common parent node must be given a unique and 88 + must be "socketN", "clusterN", "coreN", "threadN" depending on the node type 89 + (ie socket/cluster/core/thread) (where N = {0, 1, ...} is the node number; nodes 90 + which are siblings within a single common parent node must be given a unique and 89 91 sequential N value, starting from 0). 90 92 cpu-map child nodes which do not share a common parent node can have the same 91 93 name (ie same number N as other cpu-map child nodes at different device tree 92 94 levels) since name uniqueness will be guaranteed by the device tree hierarchy. 93 95 94 96 =========================================== 95 - 3 - cluster/core/thread node bindings 97 + 3 - socket/cluster/core/thread node bindings 96 98 =========================================== 97 99 98 - Bindings for cluster/cpu/thread nodes are defined as follows: 100 + Bindings for socket/cluster/cpu/thread nodes are defined as follows: 101 + 102 + - socket node 103 + 104 + Description: must be declared within a cpu-map node, one node 105 + per physical socket in the system. A system can 106 + contain single or multiple physical socket. 107 + The association of sockets and NUMA nodes is beyond 108 + the scope of this bindings, please refer [2] for 109 + NUMA bindings. 110 + 111 + This node is optional for a single socket system. 112 + 113 + The socket node name must be "socketN" as described in 2.1 above. 114 + A socket node can not be a leaf node. 115 + 116 + A socket node's child nodes must be one or more cluster nodes. 117 + 118 + Any other configuration is considered invalid. 99 119 100 120 - cluster node 101 121 102 122 Description: must be declared within a cpu-map node, one node 103 123 per cluster. A system can contain several layers of 104 - clustering and cluster nodes can be contained in parent 105 - cluster nodes. 124 + clustering within a single physical socket and cluster 125 + nodes can be contained in parent cluster nodes. 106 126 107 127 The cluster node name must be "clusterN" as described in 2.1 above. 108 128 A cluster node can not be a leaf node. ··· 180 164 4 - Example dts 181 165 =========================================== 182 166 183 - Example 1 (ARM 64-bit, 16-cpu system, two clusters of clusters): 167 + Example 1 (ARM 64-bit, 16-cpu system, two clusters of clusters in a single 168 + physical socket): 184 169 185 170 cpus { 186 171 #size-cells = <0>; 187 172 #address-cells = <2>; 188 173 189 174 cpu-map { 190 - cluster0 { 175 + socket0 { 191 176 cluster0 { 192 - core0 { 193 - thread0 { 194 - cpu = <&CPU0>; 177 + cluster0 { 178 + core0 { 179 + thread0 { 180 + cpu = <&CPU0>; 181 + }; 182 + thread1 { 183 + cpu = <&CPU1>; 184 + }; 195 185 }; 196 - thread1 { 197 - cpu = <&CPU1>; 186 + 187 + core1 { 188 + thread0 { 189 + cpu = <&CPU2>; 190 + }; 191 + thread1 { 192 + cpu = <&CPU3>; 193 + }; 198 194 }; 199 195 }; 200 196 201 - core1 { 202 - thread0 { 203 - cpu = <&CPU2>; 197 + cluster1 { 198 + core0 { 199 + thread0 { 200 + cpu = <&CPU4>; 201 + }; 202 + thread1 { 203 + cpu = <&CPU5>; 204 + }; 204 205 }; 205 - thread1 { 206 - cpu = <&CPU3>; 206 + 207 + core1 { 208 + thread0 { 209 + cpu = <&CPU6>; 210 + }; 211 + thread1 { 212 + cpu = <&CPU7>; 213 + }; 207 214 }; 208 215 }; 209 216 }; 210 217 211 218 cluster1 { 212 - core0 { 213 - thread0 { 214 - cpu = <&CPU4>; 219 + cluster0 { 220 + core0 { 221 + thread0 { 222 + cpu = <&CPU8>; 223 + }; 224 + thread1 { 225 + cpu = <&CPU9>; 226 + }; 215 227 }; 216 - thread1 { 217 - cpu = <&CPU5>; 228 + core1 { 229 + thread0 { 230 + cpu = <&CPU10>; 231 + }; 232 + thread1 { 233 + cpu = <&CPU11>; 234 + }; 218 235 }; 219 236 }; 220 237 221 - core1 { 222 - thread0 { 223 - cpu = <&CPU6>; 238 + cluster1 { 239 + core0 { 240 + thread0 { 241 + cpu = <&CPU12>; 242 + }; 243 + thread1 { 244 + cpu = <&CPU13>; 245 + }; 224 246 }; 225 - thread1 { 226 - cpu = <&CPU7>; 227 - }; 228 - }; 229 - }; 230 - }; 231 - 232 - cluster1 { 233 - cluster0 { 234 - core0 { 235 - thread0 { 236 - cpu = <&CPU8>; 237 - }; 238 - thread1 { 239 - cpu = <&CPU9>; 240 - }; 241 - }; 242 - core1 { 243 - thread0 { 244 - cpu = <&CPU10>; 245 - }; 246 - thread1 { 247 - cpu = <&CPU11>; 248 - }; 249 - }; 250 - }; 251 - 252 - cluster1 { 253 - core0 { 254 - thread0 { 255 - cpu = <&CPU12>; 256 - }; 257 - thread1 { 258 - cpu = <&CPU13>; 259 - }; 260 - }; 261 - core1 { 262 - thread0 { 263 - cpu = <&CPU14>; 264 - }; 265 - thread1 { 266 - cpu = <&CPU15>; 247 + core1 { 248 + thread0 { 249 + cpu = <&CPU14>; 250 + }; 251 + thread1 { 252 + cpu = <&CPU15>; 253 + }; 267 254 }; 268 255 }; 269 256 }; ··· 489 470 }; 490 471 }; 491 472 473 + Example 3: HiFive Unleashed (RISC-V 64 bit, 4 core system) 474 + 475 + { 476 + #address-cells = <2>; 477 + #size-cells = <2>; 478 + compatible = "sifive,fu540g", "sifive,fu500"; 479 + model = "sifive,hifive-unleashed-a00"; 480 + 481 + ... 482 + cpus { 483 + #address-cells = <1>; 484 + #size-cells = <0>; 485 + cpu-map { 486 + socket0 { 487 + cluster0 { 488 + core0 { 489 + cpu = <&CPU1>; 490 + }; 491 + core1 { 492 + cpu = <&CPU2>; 493 + }; 494 + core2 { 495 + cpu0 = <&CPU2>; 496 + }; 497 + core3 { 498 + cpu0 = <&CPU3>; 499 + }; 500 + }; 501 + }; 502 + }; 503 + 504 + CPU1: cpu@1 { 505 + device_type = "cpu"; 506 + compatible = "sifive,rocket0", "riscv"; 507 + reg = <0x1>; 508 + } 509 + 510 + CPU2: cpu@2 { 511 + device_type = "cpu"; 512 + compatible = "sifive,rocket0", "riscv"; 513 + reg = <0x2>; 514 + } 515 + CPU3: cpu@3 { 516 + device_type = "cpu"; 517 + compatible = "sifive,rocket0", "riscv"; 518 + reg = <0x3>; 519 + } 520 + CPU4: cpu@4 { 521 + device_type = "cpu"; 522 + compatible = "sifive,rocket0", "riscv"; 523 + reg = <0x4>; 524 + } 525 + } 526 + }; 492 527 =============================================================================== 493 528 [1] ARM Linux kernel documentation 494 529 Documentation/devicetree/bindings/arm/cpus.yaml 530 + [2] Devicetree NUMA binding description 531 + Documentation/devicetree/bindings/numa.txt 532 + [3] RISC-V Linux kernel documentation 533 + Documentation/devicetree/bindings/riscv/cpus.txt 534 + [4] https://www.devicetree.org/specifications/
+7
MAINTAINERS
··· 6724 6724 S: Maintained 6725 6725 F: drivers/media/radio/radio-gemtek* 6726 6726 6727 + GENERIC ARCHITECTURE TOPOLOGY 6728 + M: Sudeep Holla <sudeep.holla@arm.com> 6729 + L: linux-kernel@vger.kernel.org 6730 + S: Maintained 6731 + F: drivers/base/arch_topology.c 6732 + F: include/linux/arch_topology.h 6733 + 6727 6734 GENERIC GPIO I2C DRIVER 6728 6735 M: Wolfram Sang <wsa+renesas@sang-engineering.com> 6729 6736 S: Supported
-20
arch/arm/include/asm/topology.h
··· 5 5 #ifdef CONFIG_ARM_CPU_TOPOLOGY 6 6 7 7 #include <linux/cpumask.h> 8 - 9 - struct cputopo_arm { 10 - int thread_id; 11 - int core_id; 12 - int socket_id; 13 - cpumask_t thread_sibling; 14 - cpumask_t core_sibling; 15 - }; 16 - 17 - extern struct cputopo_arm cpu_topology[NR_CPUS]; 18 - 19 - #define topology_physical_package_id(cpu) (cpu_topology[cpu].socket_id) 20 - #define topology_core_id(cpu) (cpu_topology[cpu].core_id) 21 - #define topology_core_cpumask(cpu) (&cpu_topology[cpu].core_sibling) 22 - #define topology_sibling_cpumask(cpu) (&cpu_topology[cpu].thread_sibling) 23 - 24 - void init_cpu_topology(void); 25 - void store_cpu_topology(unsigned int cpuid); 26 - const struct cpumask *cpu_coregroup_mask(int cpu); 27 - 28 8 #include <linux/arch_topology.h> 29 9 30 10 /* Replace task scheduler's default frequency-invariant accounting */
+6 -54
arch/arm/kernel/topology.c
··· 177 177 static inline void update_cpu_capacity(unsigned int cpuid) {} 178 178 #endif 179 179 180 - /* 181 - * cpu topology table 182 - */ 183 - struct cputopo_arm cpu_topology[NR_CPUS]; 184 - EXPORT_SYMBOL_GPL(cpu_topology); 185 - 186 - const struct cpumask *cpu_coregroup_mask(int cpu) 187 - { 188 - return &cpu_topology[cpu].core_sibling; 189 - } 190 - 191 180 /* 192 181 * The current assumption is that we can power gate each core independently. 193 182 * This will be superseded by DT binding once available. ··· 186 197 return &cpu_topology[cpu].thread_sibling; 187 198 } 188 199 189 - static void update_siblings_masks(unsigned int cpuid) 190 - { 191 - struct cputopo_arm *cpu_topo, *cpuid_topo = &cpu_topology[cpuid]; 192 - int cpu; 193 - 194 - /* update core and thread sibling masks */ 195 - for_each_possible_cpu(cpu) { 196 - cpu_topo = &cpu_topology[cpu]; 197 - 198 - if (cpuid_topo->socket_id != cpu_topo->socket_id) 199 - continue; 200 - 201 - cpumask_set_cpu(cpuid, &cpu_topo->core_sibling); 202 - if (cpu != cpuid) 203 - cpumask_set_cpu(cpu, &cpuid_topo->core_sibling); 204 - 205 - if (cpuid_topo->core_id != cpu_topo->core_id) 206 - continue; 207 - 208 - cpumask_set_cpu(cpuid, &cpu_topo->thread_sibling); 209 - if (cpu != cpuid) 210 - cpumask_set_cpu(cpu, &cpuid_topo->thread_sibling); 211 - } 212 - smp_wmb(); 213 - } 214 - 215 200 /* 216 201 * store_cpu_topology is called at boot when only one cpu is running 217 202 * and with the mutex cpu_hotplug.lock locked, when several cpus have booted, ··· 193 230 */ 194 231 void store_cpu_topology(unsigned int cpuid) 195 232 { 196 - struct cputopo_arm *cpuid_topo = &cpu_topology[cpuid]; 233 + struct cpu_topology *cpuid_topo = &cpu_topology[cpuid]; 197 234 unsigned int mpidr; 198 235 199 236 /* If the cpu topology has been already set, just return */ ··· 213 250 /* core performance interdependency */ 214 251 cpuid_topo->thread_id = MPIDR_AFFINITY_LEVEL(mpidr, 0); 215 252 cpuid_topo->core_id = MPIDR_AFFINITY_LEVEL(mpidr, 1); 216 - cpuid_topo->socket_id = MPIDR_AFFINITY_LEVEL(mpidr, 2); 253 + cpuid_topo->package_id = MPIDR_AFFINITY_LEVEL(mpidr, 2); 217 254 } else { 218 255 /* largely independent cores */ 219 256 cpuid_topo->thread_id = -1; 220 257 cpuid_topo->core_id = MPIDR_AFFINITY_LEVEL(mpidr, 0); 221 - cpuid_topo->socket_id = MPIDR_AFFINITY_LEVEL(mpidr, 1); 258 + cpuid_topo->package_id = MPIDR_AFFINITY_LEVEL(mpidr, 1); 222 259 } 223 260 } else { 224 261 /* ··· 228 265 */ 229 266 cpuid_topo->thread_id = -1; 230 267 cpuid_topo->core_id = 0; 231 - cpuid_topo->socket_id = -1; 268 + cpuid_topo->package_id = -1; 232 269 } 233 270 234 271 update_siblings_masks(cpuid); ··· 238 275 pr_info("CPU%u: thread %d, cpu %d, socket %d, mpidr %x\n", 239 276 cpuid, cpu_topology[cpuid].thread_id, 240 277 cpu_topology[cpuid].core_id, 241 - cpu_topology[cpuid].socket_id, mpidr); 278 + cpu_topology[cpuid].package_id, mpidr); 242 279 } 243 280 244 281 static inline int cpu_corepower_flags(void) ··· 261 298 */ 262 299 void __init init_cpu_topology(void) 263 300 { 264 - unsigned int cpu; 265 - 266 - /* init core mask and capacity */ 267 - for_each_possible_cpu(cpu) { 268 - struct cputopo_arm *cpu_topo = &(cpu_topology[cpu]); 269 - 270 - cpu_topo->thread_id = -1; 271 - cpu_topo->core_id = -1; 272 - cpu_topo->socket_id = -1; 273 - cpumask_clear(&cpu_topo->core_sibling); 274 - cpumask_clear(&cpu_topo->thread_sibling); 275 - } 301 + reset_cpu_topology(); 276 302 smp_wmb(); 277 303 278 304 parse_dt_topology();
-23
arch/arm64/include/asm/topology.h
··· 4 4 5 5 #include <linux/cpumask.h> 6 6 7 - struct cpu_topology { 8 - int thread_id; 9 - int core_id; 10 - int package_id; 11 - int llc_id; 12 - cpumask_t thread_sibling; 13 - cpumask_t core_sibling; 14 - cpumask_t llc_sibling; 15 - }; 16 - 17 - extern struct cpu_topology cpu_topology[NR_CPUS]; 18 - 19 - #define topology_physical_package_id(cpu) (cpu_topology[cpu].package_id) 20 - #define topology_core_id(cpu) (cpu_topology[cpu].core_id) 21 - #define topology_core_cpumask(cpu) (&cpu_topology[cpu].core_sibling) 22 - #define topology_sibling_cpumask(cpu) (&cpu_topology[cpu].thread_sibling) 23 - #define topology_llc_cpumask(cpu) (&cpu_topology[cpu].llc_sibling) 24 - 25 - void init_cpu_topology(void); 26 - void store_cpu_topology(unsigned int cpuid); 27 - void remove_cpu_topology(unsigned int cpuid); 28 - const struct cpumask *cpu_coregroup_mask(int cpu); 29 - 30 7 #ifdef CONFIG_NUMA 31 8 32 9 struct pci_bus;
+4 -299
arch/arm64/kernel/topology.c
··· 14 14 #include <linux/acpi.h> 15 15 #include <linux/arch_topology.h> 16 16 #include <linux/cacheinfo.h> 17 - #include <linux/cpu.h> 18 - #include <linux/cpumask.h> 19 17 #include <linux/init.h> 20 18 #include <linux/percpu.h> 21 - #include <linux/node.h> 22 - #include <linux/nodemask.h> 23 - #include <linux/of.h> 24 - #include <linux/sched.h> 25 - #include <linux/sched/topology.h> 26 - #include <linux/slab.h> 27 - #include <linux/smp.h> 28 - #include <linux/string.h> 29 19 30 20 #include <asm/cpu.h> 31 21 #include <asm/cputype.h> 32 22 #include <asm/topology.h> 33 - 34 - static int __init get_cpu_for_node(struct device_node *node) 35 - { 36 - struct device_node *cpu_node; 37 - int cpu; 38 - 39 - cpu_node = of_parse_phandle(node, "cpu", 0); 40 - if (!cpu_node) 41 - return -1; 42 - 43 - cpu = of_cpu_node_to_id(cpu_node); 44 - if (cpu >= 0) 45 - topology_parse_cpu_capacity(cpu_node, cpu); 46 - else 47 - pr_crit("Unable to find CPU node for %pOF\n", cpu_node); 48 - 49 - of_node_put(cpu_node); 50 - return cpu; 51 - } 52 - 53 - static int __init parse_core(struct device_node *core, int package_id, 54 - int core_id) 55 - { 56 - char name[10]; 57 - bool leaf = true; 58 - int i = 0; 59 - int cpu; 60 - struct device_node *t; 61 - 62 - do { 63 - snprintf(name, sizeof(name), "thread%d", i); 64 - t = of_get_child_by_name(core, name); 65 - if (t) { 66 - leaf = false; 67 - cpu = get_cpu_for_node(t); 68 - if (cpu >= 0) { 69 - cpu_topology[cpu].package_id = package_id; 70 - cpu_topology[cpu].core_id = core_id; 71 - cpu_topology[cpu].thread_id = i; 72 - } else { 73 - pr_err("%pOF: Can't get CPU for thread\n", 74 - t); 75 - of_node_put(t); 76 - return -EINVAL; 77 - } 78 - of_node_put(t); 79 - } 80 - i++; 81 - } while (t); 82 - 83 - cpu = get_cpu_for_node(core); 84 - if (cpu >= 0) { 85 - if (!leaf) { 86 - pr_err("%pOF: Core has both threads and CPU\n", 87 - core); 88 - return -EINVAL; 89 - } 90 - 91 - cpu_topology[cpu].package_id = package_id; 92 - cpu_topology[cpu].core_id = core_id; 93 - } else if (leaf) { 94 - pr_err("%pOF: Can't get CPU for leaf core\n", core); 95 - return -EINVAL; 96 - } 97 - 98 - return 0; 99 - } 100 - 101 - static int __init parse_cluster(struct device_node *cluster, int depth) 102 - { 103 - char name[10]; 104 - bool leaf = true; 105 - bool has_cores = false; 106 - struct device_node *c; 107 - static int package_id __initdata; 108 - int core_id = 0; 109 - int i, ret; 110 - 111 - /* 112 - * First check for child clusters; we currently ignore any 113 - * information about the nesting of clusters and present the 114 - * scheduler with a flat list of them. 115 - */ 116 - i = 0; 117 - do { 118 - snprintf(name, sizeof(name), "cluster%d", i); 119 - c = of_get_child_by_name(cluster, name); 120 - if (c) { 121 - leaf = false; 122 - ret = parse_cluster(c, depth + 1); 123 - of_node_put(c); 124 - if (ret != 0) 125 - return ret; 126 - } 127 - i++; 128 - } while (c); 129 - 130 - /* Now check for cores */ 131 - i = 0; 132 - do { 133 - snprintf(name, sizeof(name), "core%d", i); 134 - c = of_get_child_by_name(cluster, name); 135 - if (c) { 136 - has_cores = true; 137 - 138 - if (depth == 0) { 139 - pr_err("%pOF: cpu-map children should be clusters\n", 140 - c); 141 - of_node_put(c); 142 - return -EINVAL; 143 - } 144 - 145 - if (leaf) { 146 - ret = parse_core(c, package_id, core_id++); 147 - } else { 148 - pr_err("%pOF: Non-leaf cluster with core %s\n", 149 - cluster, name); 150 - ret = -EINVAL; 151 - } 152 - 153 - of_node_put(c); 154 - if (ret != 0) 155 - return ret; 156 - } 157 - i++; 158 - } while (c); 159 - 160 - if (leaf && !has_cores) 161 - pr_warn("%pOF: empty cluster\n", cluster); 162 - 163 - if (leaf) 164 - package_id++; 165 - 166 - return 0; 167 - } 168 - 169 - static int __init parse_dt_topology(void) 170 - { 171 - struct device_node *cn, *map; 172 - int ret = 0; 173 - int cpu; 174 - 175 - cn = of_find_node_by_path("/cpus"); 176 - if (!cn) { 177 - pr_err("No CPU information found in DT\n"); 178 - return 0; 179 - } 180 - 181 - /* 182 - * When topology is provided cpu-map is essentially a root 183 - * cluster with restricted subnodes. 184 - */ 185 - map = of_get_child_by_name(cn, "cpu-map"); 186 - if (!map) 187 - goto out; 188 - 189 - ret = parse_cluster(map, 0); 190 - if (ret != 0) 191 - goto out_map; 192 - 193 - topology_normalize_cpu_scale(); 194 - 195 - /* 196 - * Check that all cores are in the topology; the SMP code will 197 - * only mark cores described in the DT as possible. 198 - */ 199 - for_each_possible_cpu(cpu) 200 - if (cpu_topology[cpu].package_id == -1) 201 - ret = -EINVAL; 202 - 203 - out_map: 204 - of_node_put(map); 205 - out: 206 - of_node_put(cn); 207 - return ret; 208 - } 209 - 210 - /* 211 - * cpu topology table 212 - */ 213 - struct cpu_topology cpu_topology[NR_CPUS]; 214 - EXPORT_SYMBOL_GPL(cpu_topology); 215 - 216 - const struct cpumask *cpu_coregroup_mask(int cpu) 217 - { 218 - const cpumask_t *core_mask = cpumask_of_node(cpu_to_node(cpu)); 219 - 220 - /* Find the smaller of NUMA, core or LLC siblings */ 221 - if (cpumask_subset(&cpu_topology[cpu].core_sibling, core_mask)) { 222 - /* not numa in package, lets use the package siblings */ 223 - core_mask = &cpu_topology[cpu].core_sibling; 224 - } 225 - if (cpu_topology[cpu].llc_id != -1) { 226 - if (cpumask_subset(&cpu_topology[cpu].llc_sibling, core_mask)) 227 - core_mask = &cpu_topology[cpu].llc_sibling; 228 - } 229 - 230 - return core_mask; 231 - } 232 - 233 - static void update_siblings_masks(unsigned int cpuid) 234 - { 235 - struct cpu_topology *cpu_topo, *cpuid_topo = &cpu_topology[cpuid]; 236 - int cpu; 237 - 238 - /* update core and thread sibling masks */ 239 - for_each_online_cpu(cpu) { 240 - cpu_topo = &cpu_topology[cpu]; 241 - 242 - if (cpuid_topo->llc_id == cpu_topo->llc_id) { 243 - cpumask_set_cpu(cpu, &cpuid_topo->llc_sibling); 244 - cpumask_set_cpu(cpuid, &cpu_topo->llc_sibling); 245 - } 246 - 247 - if (cpuid_topo->package_id != cpu_topo->package_id) 248 - continue; 249 - 250 - cpumask_set_cpu(cpuid, &cpu_topo->core_sibling); 251 - cpumask_set_cpu(cpu, &cpuid_topo->core_sibling); 252 - 253 - if (cpuid_topo->core_id != cpu_topo->core_id) 254 - continue; 255 - 256 - cpumask_set_cpu(cpuid, &cpu_topo->thread_sibling); 257 - cpumask_set_cpu(cpu, &cpuid_topo->thread_sibling); 258 - } 259 - } 260 23 261 24 void store_cpu_topology(unsigned int cpuid) 262 25 { ··· 59 296 update_siblings_masks(cpuid); 60 297 } 61 298 62 - static void clear_cpu_topology(int cpu) 63 - { 64 - struct cpu_topology *cpu_topo = &cpu_topology[cpu]; 65 - 66 - cpumask_clear(&cpu_topo->llc_sibling); 67 - cpumask_set_cpu(cpu, &cpu_topo->llc_sibling); 68 - 69 - cpumask_clear(&cpu_topo->core_sibling); 70 - cpumask_set_cpu(cpu, &cpu_topo->core_sibling); 71 - cpumask_clear(&cpu_topo->thread_sibling); 72 - cpumask_set_cpu(cpu, &cpu_topo->thread_sibling); 73 - } 74 - 75 - static void __init reset_cpu_topology(void) 76 - { 77 - unsigned int cpu; 78 - 79 - for_each_possible_cpu(cpu) { 80 - struct cpu_topology *cpu_topo = &cpu_topology[cpu]; 81 - 82 - cpu_topo->thread_id = -1; 83 - cpu_topo->core_id = 0; 84 - cpu_topo->package_id = -1; 85 - cpu_topo->llc_id = -1; 86 - 87 - clear_cpu_topology(cpu); 88 - } 89 - } 90 - 91 - void remove_cpu_topology(unsigned int cpu) 92 - { 93 - int sibling; 94 - 95 - for_each_cpu(sibling, topology_core_cpumask(cpu)) 96 - cpumask_clear_cpu(cpu, topology_core_cpumask(sibling)); 97 - for_each_cpu(sibling, topology_sibling_cpumask(cpu)) 98 - cpumask_clear_cpu(cpu, topology_sibling_cpumask(sibling)); 99 - for_each_cpu(sibling, topology_llc_cpumask(cpu)) 100 - cpumask_clear_cpu(cpu, topology_llc_cpumask(sibling)); 101 - 102 - clear_cpu_topology(cpu); 103 - } 104 - 105 299 #ifdef CONFIG_ACPI 106 300 static bool __init acpi_cpu_is_threaded(int cpu) 107 301 { ··· 78 358 * Propagate the topology information of the processor_topology_node tree to the 79 359 * cpu_topology array. 80 360 */ 81 - static int __init parse_acpi_topology(void) 361 + int __init parse_acpi_topology(void) 82 362 { 83 363 int cpu, topology_id; 364 + 365 + if (acpi_disabled) 366 + return 0; 84 367 85 368 for_each_possible_cpu(cpu) { 86 369 int i, cache_id; ··· 118 395 119 396 return 0; 120 397 } 121 - 122 - #else 123 - static inline int __init parse_acpi_topology(void) 124 - { 125 - return -EINVAL; 126 - } 127 398 #endif 128 399 129 - void __init init_cpu_topology(void) 130 - { 131 - reset_cpu_topology(); 132 400 133 - /* 134 - * Discard anything that was parsed if we hit an error so we 135 - * don't use partial information. 136 - */ 137 - if (!acpi_disabled && parse_acpi_topology()) 138 - reset_cpu_topology(); 139 - else if (of_have_populated_dt() && parse_dt_topology()) 140 - reset_cpu_topology(); 141 - }
+1
arch/riscv/Kconfig
··· 48 48 select PCI_MSI if PCI 49 49 select RISCV_TIMER 50 50 select GENERIC_IRQ_MULTI_HANDLER 51 + select GENERIC_ARCH_TOPOLOGY if SMP 51 52 select ARCH_HAS_PTE_SPECIAL 52 53 select ARCH_HAS_MMIOWB 53 54 select HAVE_EBPF_JIT if 64BIT
+3
arch/riscv/kernel/smpboot.c
··· 8 8 * Copyright (C) 2017 SiFive 9 9 */ 10 10 11 + #include <linux/arch_topology.h> 11 12 #include <linux/module.h> 12 13 #include <linux/init.h> 13 14 #include <linux/kernel.h> ··· 36 35 37 36 void __init smp_prepare_boot_cpu(void) 38 37 { 38 + init_cpu_topology(); 39 39 } 40 40 41 41 void __init smp_prepare_cpus(unsigned int max_cpus) ··· 140 138 141 139 trap_init(); 142 140 notify_cpu_starting(smp_processor_id()); 141 + update_siblings_masks(smp_processor_id()); 143 142 set_cpu_online(smp_processor_id(), 1); 144 143 /* 145 144 * Remote TLB flushes are ignored while the CPU is offline, so emit
+1 -1
drivers/base/Kconfig
··· 202 202 help 203 203 Enable support for architectures common topology code: e.g., parsing 204 204 CPU capacity information from DT, usage of such information for 205 - appropriate scaling, sysfs interface for changing capacity values at 205 + appropriate scaling, sysfs interface for reading capacity values at 206 206 runtime. 207 207 208 208 endmenu
+298
drivers/base/arch_topology.c
··· 15 15 #include <linux/string.h> 16 16 #include <linux/sched/topology.h> 17 17 #include <linux/cpuset.h> 18 + #include <linux/cpumask.h> 19 + #include <linux/init.h> 20 + #include <linux/percpu.h> 21 + #include <linux/sched.h> 22 + #include <linux/smp.h> 18 23 19 24 DEFINE_PER_CPU(unsigned long, freq_scale) = SCHED_CAPACITY_SCALE; 20 25 ··· 245 240 246 241 #else 247 242 core_initcall(free_raw_capacity); 243 + #endif 244 + 245 + #if defined(CONFIG_ARM64) || defined(CONFIG_RISCV) 246 + static int __init get_cpu_for_node(struct device_node *node) 247 + { 248 + struct device_node *cpu_node; 249 + int cpu; 250 + 251 + cpu_node = of_parse_phandle(node, "cpu", 0); 252 + if (!cpu_node) 253 + return -1; 254 + 255 + cpu = of_cpu_node_to_id(cpu_node); 256 + if (cpu >= 0) 257 + topology_parse_cpu_capacity(cpu_node, cpu); 258 + else 259 + pr_crit("Unable to find CPU node for %pOF\n", cpu_node); 260 + 261 + of_node_put(cpu_node); 262 + return cpu; 263 + } 264 + 265 + static int __init parse_core(struct device_node *core, int package_id, 266 + int core_id) 267 + { 268 + char name[10]; 269 + bool leaf = true; 270 + int i = 0; 271 + int cpu; 272 + struct device_node *t; 273 + 274 + do { 275 + snprintf(name, sizeof(name), "thread%d", i); 276 + t = of_get_child_by_name(core, name); 277 + if (t) { 278 + leaf = false; 279 + cpu = get_cpu_for_node(t); 280 + if (cpu >= 0) { 281 + cpu_topology[cpu].package_id = package_id; 282 + cpu_topology[cpu].core_id = core_id; 283 + cpu_topology[cpu].thread_id = i; 284 + } else { 285 + pr_err("%pOF: Can't get CPU for thread\n", 286 + t); 287 + of_node_put(t); 288 + return -EINVAL; 289 + } 290 + of_node_put(t); 291 + } 292 + i++; 293 + } while (t); 294 + 295 + cpu = get_cpu_for_node(core); 296 + if (cpu >= 0) { 297 + if (!leaf) { 298 + pr_err("%pOF: Core has both threads and CPU\n", 299 + core); 300 + return -EINVAL; 301 + } 302 + 303 + cpu_topology[cpu].package_id = package_id; 304 + cpu_topology[cpu].core_id = core_id; 305 + } else if (leaf) { 306 + pr_err("%pOF: Can't get CPU for leaf core\n", core); 307 + return -EINVAL; 308 + } 309 + 310 + return 0; 311 + } 312 + 313 + static int __init parse_cluster(struct device_node *cluster, int depth) 314 + { 315 + char name[10]; 316 + bool leaf = true; 317 + bool has_cores = false; 318 + struct device_node *c; 319 + static int package_id __initdata; 320 + int core_id = 0; 321 + int i, ret; 322 + 323 + /* 324 + * First check for child clusters; we currently ignore any 325 + * information about the nesting of clusters and present the 326 + * scheduler with a flat list of them. 327 + */ 328 + i = 0; 329 + do { 330 + snprintf(name, sizeof(name), "cluster%d", i); 331 + c = of_get_child_by_name(cluster, name); 332 + if (c) { 333 + leaf = false; 334 + ret = parse_cluster(c, depth + 1); 335 + of_node_put(c); 336 + if (ret != 0) 337 + return ret; 338 + } 339 + i++; 340 + } while (c); 341 + 342 + /* Now check for cores */ 343 + i = 0; 344 + do { 345 + snprintf(name, sizeof(name), "core%d", i); 346 + c = of_get_child_by_name(cluster, name); 347 + if (c) { 348 + has_cores = true; 349 + 350 + if (depth == 0) { 351 + pr_err("%pOF: cpu-map children should be clusters\n", 352 + c); 353 + of_node_put(c); 354 + return -EINVAL; 355 + } 356 + 357 + if (leaf) { 358 + ret = parse_core(c, package_id, core_id++); 359 + } else { 360 + pr_err("%pOF: Non-leaf cluster with core %s\n", 361 + cluster, name); 362 + ret = -EINVAL; 363 + } 364 + 365 + of_node_put(c); 366 + if (ret != 0) 367 + return ret; 368 + } 369 + i++; 370 + } while (c); 371 + 372 + if (leaf && !has_cores) 373 + pr_warn("%pOF: empty cluster\n", cluster); 374 + 375 + if (leaf) 376 + package_id++; 377 + 378 + return 0; 379 + } 380 + 381 + static int __init parse_dt_topology(void) 382 + { 383 + struct device_node *cn, *map; 384 + int ret = 0; 385 + int cpu; 386 + 387 + cn = of_find_node_by_path("/cpus"); 388 + if (!cn) { 389 + pr_err("No CPU information found in DT\n"); 390 + return 0; 391 + } 392 + 393 + /* 394 + * When topology is provided cpu-map is essentially a root 395 + * cluster with restricted subnodes. 396 + */ 397 + map = of_get_child_by_name(cn, "cpu-map"); 398 + if (!map) 399 + goto out; 400 + 401 + ret = parse_cluster(map, 0); 402 + if (ret != 0) 403 + goto out_map; 404 + 405 + topology_normalize_cpu_scale(); 406 + 407 + /* 408 + * Check that all cores are in the topology; the SMP code will 409 + * only mark cores described in the DT as possible. 410 + */ 411 + for_each_possible_cpu(cpu) 412 + if (cpu_topology[cpu].package_id == -1) 413 + ret = -EINVAL; 414 + 415 + out_map: 416 + of_node_put(map); 417 + out: 418 + of_node_put(cn); 419 + return ret; 420 + } 421 + #endif 422 + 423 + /* 424 + * cpu topology table 425 + */ 426 + struct cpu_topology cpu_topology[NR_CPUS]; 427 + EXPORT_SYMBOL_GPL(cpu_topology); 428 + 429 + const struct cpumask *cpu_coregroup_mask(int cpu) 430 + { 431 + const cpumask_t *core_mask = cpumask_of_node(cpu_to_node(cpu)); 432 + 433 + /* Find the smaller of NUMA, core or LLC siblings */ 434 + if (cpumask_subset(&cpu_topology[cpu].core_sibling, core_mask)) { 435 + /* not numa in package, lets use the package siblings */ 436 + core_mask = &cpu_topology[cpu].core_sibling; 437 + } 438 + if (cpu_topology[cpu].llc_id != -1) { 439 + if (cpumask_subset(&cpu_topology[cpu].llc_sibling, core_mask)) 440 + core_mask = &cpu_topology[cpu].llc_sibling; 441 + } 442 + 443 + return core_mask; 444 + } 445 + 446 + void update_siblings_masks(unsigned int cpuid) 447 + { 448 + struct cpu_topology *cpu_topo, *cpuid_topo = &cpu_topology[cpuid]; 449 + int cpu; 450 + 451 + /* update core and thread sibling masks */ 452 + for_each_online_cpu(cpu) { 453 + cpu_topo = &cpu_topology[cpu]; 454 + 455 + if (cpuid_topo->llc_id == cpu_topo->llc_id) { 456 + cpumask_set_cpu(cpu, &cpuid_topo->llc_sibling); 457 + cpumask_set_cpu(cpuid, &cpu_topo->llc_sibling); 458 + } 459 + 460 + if (cpuid_topo->package_id != cpu_topo->package_id) 461 + continue; 462 + 463 + cpumask_set_cpu(cpuid, &cpu_topo->core_sibling); 464 + cpumask_set_cpu(cpu, &cpuid_topo->core_sibling); 465 + 466 + if (cpuid_topo->core_id != cpu_topo->core_id) 467 + continue; 468 + 469 + cpumask_set_cpu(cpuid, &cpu_topo->thread_sibling); 470 + cpumask_set_cpu(cpu, &cpuid_topo->thread_sibling); 471 + } 472 + } 473 + 474 + static void clear_cpu_topology(int cpu) 475 + { 476 + struct cpu_topology *cpu_topo = &cpu_topology[cpu]; 477 + 478 + cpumask_clear(&cpu_topo->llc_sibling); 479 + cpumask_set_cpu(cpu, &cpu_topo->llc_sibling); 480 + 481 + cpumask_clear(&cpu_topo->core_sibling); 482 + cpumask_set_cpu(cpu, &cpu_topo->core_sibling); 483 + cpumask_clear(&cpu_topo->thread_sibling); 484 + cpumask_set_cpu(cpu, &cpu_topo->thread_sibling); 485 + } 486 + 487 + void __init reset_cpu_topology(void) 488 + { 489 + unsigned int cpu; 490 + 491 + for_each_possible_cpu(cpu) { 492 + struct cpu_topology *cpu_topo = &cpu_topology[cpu]; 493 + 494 + cpu_topo->thread_id = -1; 495 + cpu_topo->core_id = -1; 496 + cpu_topo->package_id = -1; 497 + cpu_topo->llc_id = -1; 498 + 499 + clear_cpu_topology(cpu); 500 + } 501 + } 502 + 503 + void remove_cpu_topology(unsigned int cpu) 504 + { 505 + int sibling; 506 + 507 + for_each_cpu(sibling, topology_core_cpumask(cpu)) 508 + cpumask_clear_cpu(cpu, topology_core_cpumask(sibling)); 509 + for_each_cpu(sibling, topology_sibling_cpumask(cpu)) 510 + cpumask_clear_cpu(cpu, topology_sibling_cpumask(sibling)); 511 + for_each_cpu(sibling, topology_llc_cpumask(cpu)) 512 + cpumask_clear_cpu(cpu, topology_llc_cpumask(sibling)); 513 + 514 + clear_cpu_topology(cpu); 515 + } 516 + 517 + __weak int __init parse_acpi_topology(void) 518 + { 519 + return 0; 520 + } 521 + 522 + #if defined(CONFIG_ARM64) || defined(CONFIG_RISCV) 523 + void __init init_cpu_topology(void) 524 + { 525 + reset_cpu_topology(); 526 + 527 + /* 528 + * Discard anything that was parsed if we hit an error so we 529 + * don't use partial information. 530 + */ 531 + if (parse_acpi_topology()) 532 + reset_cpu_topology(); 533 + else if (of_have_populated_dt() && parse_dt_topology()) 534 + reset_cpu_topology(); 535 + } 248 536 #endif
+26
include/linux/arch_topology.h
··· 33 33 return per_cpu(freq_scale, cpu); 34 34 } 35 35 36 + struct cpu_topology { 37 + int thread_id; 38 + int core_id; 39 + int package_id; 40 + int llc_id; 41 + cpumask_t thread_sibling; 42 + cpumask_t core_sibling; 43 + cpumask_t llc_sibling; 44 + }; 45 + 46 + #ifdef CONFIG_GENERIC_ARCH_TOPOLOGY 47 + extern struct cpu_topology cpu_topology[NR_CPUS]; 48 + 49 + #define topology_physical_package_id(cpu) (cpu_topology[cpu].package_id) 50 + #define topology_core_id(cpu) (cpu_topology[cpu].core_id) 51 + #define topology_core_cpumask(cpu) (&cpu_topology[cpu].core_sibling) 52 + #define topology_sibling_cpumask(cpu) (&cpu_topology[cpu].thread_sibling) 53 + #define topology_llc_cpumask(cpu) (&cpu_topology[cpu].llc_sibling) 54 + void init_cpu_topology(void); 55 + void store_cpu_topology(unsigned int cpuid); 56 + const struct cpumask *cpu_coregroup_mask(int cpu); 57 + void update_siblings_masks(unsigned int cpu); 58 + void remove_cpu_topology(unsigned int cpuid); 59 + void reset_cpu_topology(void); 60 + #endif 61 + 36 62 #endif /* _LINUX_ARCH_TOPOLOGY_H_ */
+1
include/linux/topology.h
··· 27 27 #ifndef _LINUX_TOPOLOGY_H 28 28 #define _LINUX_TOPOLOGY_H 29 29 30 + #include <linux/arch_topology.h> 30 31 #include <linux/cpumask.h> 31 32 #include <linux/bitops.h> 32 33 #include <linux/mmzone.h>