xref: /openbmc/linux/arch/arm64/kernel/topology.c (revision 84d517f3)
1 /*
2  * arch/arm64/kernel/topology.c
3  *
4  * Copyright (C) 2011,2013,2014 Linaro Limited.
5  *
6  * Based on the arm32 version written by Vincent Guittot in turn based on
7  * arch/sh/kernel/topology.c
8  *
9  * This file is subject to the terms and conditions of the GNU General Public
10  * License.  See the file "COPYING" in the main directory of this archive
11  * for more details.
12  */
13 
14 #include <linux/cpu.h>
15 #include <linux/cpumask.h>
16 #include <linux/init.h>
17 #include <linux/percpu.h>
18 #include <linux/node.h>
19 #include <linux/nodemask.h>
20 #include <linux/sched.h>
21 
22 #include <asm/topology.h>
23 
24 /*
25  * cpu topology table
26  */
27 struct cpu_topology cpu_topology[NR_CPUS];
28 EXPORT_SYMBOL_GPL(cpu_topology);
29 
30 const struct cpumask *cpu_coregroup_mask(int cpu)
31 {
32 	return &cpu_topology[cpu].core_sibling;
33 }
34 
35 static void update_siblings_masks(unsigned int cpuid)
36 {
37 	struct cpu_topology *cpu_topo, *cpuid_topo = &cpu_topology[cpuid];
38 	int cpu;
39 
40 	if (cpuid_topo->cluster_id == -1) {
41 		/*
42 		 * DT does not contain topology information for this cpu
43 		 * reset it to default behaviour
44 		 */
45 		pr_debug("CPU%u: No topology information configured\n", cpuid);
46 		cpuid_topo->core_id = 0;
47 		cpumask_set_cpu(cpuid, &cpuid_topo->core_sibling);
48 		cpumask_set_cpu(cpuid, &cpuid_topo->thread_sibling);
49 		return;
50 	}
51 
52 	/* update core and thread sibling masks */
53 	for_each_possible_cpu(cpu) {
54 		cpu_topo = &cpu_topology[cpu];
55 
56 		if (cpuid_topo->cluster_id != cpu_topo->cluster_id)
57 			continue;
58 
59 		cpumask_set_cpu(cpuid, &cpu_topo->core_sibling);
60 		if (cpu != cpuid)
61 			cpumask_set_cpu(cpu, &cpuid_topo->core_sibling);
62 
63 		if (cpuid_topo->core_id != cpu_topo->core_id)
64 			continue;
65 
66 		cpumask_set_cpu(cpuid, &cpu_topo->thread_sibling);
67 		if (cpu != cpuid)
68 			cpumask_set_cpu(cpu, &cpuid_topo->thread_sibling);
69 	}
70 }
71 
72 void store_cpu_topology(unsigned int cpuid)
73 {
74 	update_siblings_masks(cpuid);
75 }
76 
77 /*
78  * init_cpu_topology is called at boot when only one cpu is running
79  * which prevent simultaneous write access to cpu_topology array
80  */
81 void __init init_cpu_topology(void)
82 {
83 	unsigned int cpu;
84 
85 	/* init core mask and power*/
86 	for_each_possible_cpu(cpu) {
87 		struct cpu_topology *cpu_topo = &cpu_topology[cpu];
88 
89 		cpu_topo->thread_id = -1;
90 		cpu_topo->core_id =  -1;
91 		cpu_topo->cluster_id = -1;
92 		cpumask_clear(&cpu_topo->core_sibling);
93 		cpumask_clear(&cpu_topo->thread_sibling);
94 	}
95 }
96