aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm64
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm64')
-rw-r--r--arch/arm64/Kconfig16
-rw-r--r--arch/arm64/include/asm/topology.h39
-rw-r--r--arch/arm64/kernel/Makefile2
-rw-r--r--arch/arm64/kernel/smp.c11
-rw-r--r--arch/arm64/kernel/topology.c95
5 files changed, 162 insertions, 1 deletions
diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index c2056ca04ae2..140cd1a9dc0c 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -165,6 +165,22 @@ config SMP
165 165
166 If you don't know what to do here, say N. 166 If you don't know what to do here, say N.
167 167
168config SCHED_MC
169 bool "Multi-core scheduler support"
170 depends on SMP
171 help
172 Multi-core scheduler support improves the CPU scheduler's decision
173 making when dealing with multi-core CPU chips at a cost of slightly
174 increased overhead in some places. If unsure say N here.
175
176config SCHED_SMT
177 bool "SMT scheduler support"
178 depends on SMP
179 help
180 Improves the CPU scheduler's decision making when dealing with
181 MultiThreading at a cost of slightly increased overhead in some
182 places. If unsure say N here.
183
168config NR_CPUS 184config NR_CPUS
169 int "Maximum number of CPUs (2-32)" 185 int "Maximum number of CPUs (2-32)"
170 range 2 32 186 range 2 32
diff --git a/arch/arm64/include/asm/topology.h b/arch/arm64/include/asm/topology.h
new file mode 100644
index 000000000000..0172e6d76bf3
--- /dev/null
+++ b/arch/arm64/include/asm/topology.h
@@ -0,0 +1,39 @@
1#ifndef __ASM_TOPOLOGY_H
2#define __ASM_TOPOLOGY_H
3
4#ifdef CONFIG_SMP
5
6#include <linux/cpumask.h>
7
8struct cpu_topology {
9 int thread_id;
10 int core_id;
11 int cluster_id;
12 cpumask_t thread_sibling;
13 cpumask_t core_sibling;
14};
15
16extern struct cpu_topology cpu_topology[NR_CPUS];
17
18#define topology_physical_package_id(cpu) (cpu_topology[cpu].cluster_id)
19#define topology_core_id(cpu) (cpu_topology[cpu].core_id)
20#define topology_core_cpumask(cpu) (&cpu_topology[cpu].core_sibling)
21#define topology_thread_cpumask(cpu) (&cpu_topology[cpu].thread_sibling)
22
23#define mc_capable() (cpu_topology[0].cluster_id != -1)
24#define smt_capable() (cpu_topology[0].thread_id != -1)
25
26void init_cpu_topology(void);
27void store_cpu_topology(unsigned int cpuid);
28const struct cpumask *cpu_coregroup_mask(int cpu);
29
30#else
31
32static inline void init_cpu_topology(void) { }
33static inline void store_cpu_topology(unsigned int cpuid) { }
34
35#endif
36
37#include <asm-generic/topology.h>
38
39#endif /* _ASM_ARM_TOPOLOGY_H */
diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile
index e52bcdc6f097..cfee8273fccb 100644
--- a/arch/arm64/kernel/Makefile
+++ b/arch/arm64/kernel/Makefile
@@ -14,7 +14,7 @@ arm64-obj-y := cputable.o debug-monitors.o entry.o irq.o fpsimd.o \
14arm64-obj-$(CONFIG_COMPAT) += sys32.o kuser32.o signal32.o \ 14arm64-obj-$(CONFIG_COMPAT) += sys32.o kuser32.o signal32.o \
15 sys_compat.o 15 sys_compat.o
16arm64-obj-$(CONFIG_MODULES) += arm64ksyms.o module.o 16arm64-obj-$(CONFIG_MODULES) += arm64ksyms.o module.o
17arm64-obj-$(CONFIG_SMP) += smp.o smp_spin_table.o 17arm64-obj-$(CONFIG_SMP) += smp.o smp_spin_table.o topology.o
18arm64-obj-$(CONFIG_HW_PERF_EVENTS) += perf_event.o 18arm64-obj-$(CONFIG_HW_PERF_EVENTS) += perf_event.o
19arm64-obj-$(CONFIG_HAVE_HW_BREAKPOINT)+= hw_breakpoint.o 19arm64-obj-$(CONFIG_HAVE_HW_BREAKPOINT)+= hw_breakpoint.o
20arm64-obj-$(CONFIG_EARLY_PRINTK) += early_printk.o 20arm64-obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
diff --git a/arch/arm64/kernel/smp.c b/arch/arm64/kernel/smp.c
index 5070dc3b65d2..f0a141dd5655 100644
--- a/arch/arm64/kernel/smp.c
+++ b/arch/arm64/kernel/smp.c
@@ -114,6 +114,11 @@ int __cpu_up(unsigned int cpu, struct task_struct *idle)
114 return ret; 114 return ret;
115} 115}
116 116
117static void smp_store_cpu_info(unsigned int cpuid)
118{
119 store_cpu_topology(cpuid);
120}
121
117/* 122/*
118 * This is the secondary CPU boot entry. We're using this CPUs 123 * This is the secondary CPU boot entry. We're using this CPUs
119 * idle thread stack, but a set of temporary page tables. 124 * idle thread stack, but a set of temporary page tables.
@@ -152,6 +157,8 @@ asmlinkage void secondary_start_kernel(void)
152 */ 157 */
153 notify_cpu_starting(cpu); 158 notify_cpu_starting(cpu);
154 159
160 smp_store_cpu_info(cpu);
161
155 /* 162 /*
156 * OK, now it's safe to let the boot CPU continue. Wait for 163 * OK, now it's safe to let the boot CPU continue. Wait for
157 * the CPU migration code to notice that the CPU is online 164 * the CPU migration code to notice that the CPU is online
@@ -391,6 +398,10 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
391 int err; 398 int err;
392 unsigned int cpu, ncores = num_possible_cpus(); 399 unsigned int cpu, ncores = num_possible_cpus();
393 400
401 init_cpu_topology();
402
403 smp_store_cpu_info(smp_processor_id());
404
394 /* 405 /*
395 * are we trying to boot more cores than exist? 406 * are we trying to boot more cores than exist?
396 */ 407 */
diff --git a/arch/arm64/kernel/topology.c b/arch/arm64/kernel/topology.c
new file mode 100644
index 000000000000..3e06b0be4ec8
--- /dev/null
+++ b/arch/arm64/kernel/topology.c
@@ -0,0 +1,95 @@
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 */
27struct cpu_topology cpu_topology[NR_CPUS];
28EXPORT_SYMBOL_GPL(cpu_topology);
29
30const struct cpumask *cpu_coregroup_mask(int cpu)
31{
32 return &cpu_topology[cpu].core_sibling;
33}
34
35static 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
72void 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 */
81void __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}