diff options
author | Arnd Bergmann <arnd@arndb.de> | 2011-10-20 10:07:27 -0400 |
---|---|---|
committer | Arnd Bergmann <arnd@arndb.de> | 2011-10-20 10:07:27 -0400 |
commit | 97c24c1aa403e0d4ef7c1958db8459e488862b46 (patch) | |
tree | 15214db3c82fffcdbad1d0ef109c9c7558982ebb /arch | |
parent | f350b86121c7a004a5f866333fa1d23fe30263a6 (diff) | |
parent | 4a139b64703115e41e1a4e16ebf7eb93d0a0e349 (diff) |
Merge branches 'cross-platform/debug_ll' and 'cross-platform/cpu-mapping' into next/cross-platform
Diffstat (limited to 'arch')
26 files changed, 312 insertions, 23 deletions
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 3269576dbfa8..c208fd97c180 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig | |||
@@ -1393,6 +1393,31 @@ config SMP_ON_UP | |||
1393 | 1393 | ||
1394 | If you don't know what to do here, say Y. | 1394 | If you don't know what to do here, say Y. |
1395 | 1395 | ||
1396 | config ARM_CPU_TOPOLOGY | ||
1397 | bool "Support cpu topology definition" | ||
1398 | depends on SMP && CPU_V7 | ||
1399 | default y | ||
1400 | help | ||
1401 | Support ARM cpu topology definition. The MPIDR register defines | ||
1402 | affinity between processors which is then used to describe the cpu | ||
1403 | topology of an ARM System. | ||
1404 | |||
1405 | config SCHED_MC | ||
1406 | bool "Multi-core scheduler support" | ||
1407 | depends on ARM_CPU_TOPOLOGY | ||
1408 | help | ||
1409 | Multi-core scheduler support improves the CPU scheduler's decision | ||
1410 | making when dealing with multi-core CPU chips at a cost of slightly | ||
1411 | increased overhead in some places. If unsure say N here. | ||
1412 | |||
1413 | config SCHED_SMT | ||
1414 | bool "SMT scheduler support" | ||
1415 | depends on ARM_CPU_TOPOLOGY | ||
1416 | help | ||
1417 | Improves the CPU scheduler's decision making when dealing with | ||
1418 | MultiThreading at a cost of slightly increased overhead in some | ||
1419 | places. If unsure say N here. | ||
1420 | |||
1396 | config HAVE_ARM_SCU | 1421 | config HAVE_ARM_SCU |
1397 | bool | 1422 | bool |
1398 | help | 1423 | help |
diff --git a/arch/arm/common/gic.c b/arch/arm/common/gic.c index 3227ca952a12..666b278e56d7 100644 --- a/arch/arm/common/gic.c +++ b/arch/arm/common/gic.c | |||
@@ -180,7 +180,7 @@ static int gic_set_affinity(struct irq_data *d, const struct cpumask *mask_val, | |||
180 | return -EINVAL; | 180 | return -EINVAL; |
181 | 181 | ||
182 | mask = 0xff << shift; | 182 | mask = 0xff << shift; |
183 | bit = 1 << (cpu + shift); | 183 | bit = 1 << (cpu_logical_map(cpu) + shift); |
184 | 184 | ||
185 | spin_lock(&irq_controller_lock); | 185 | spin_lock(&irq_controller_lock); |
186 | val = readl_relaxed(reg) & ~mask; | 186 | val = readl_relaxed(reg) & ~mask; |
@@ -259,9 +259,15 @@ static void __init gic_dist_init(struct gic_chip_data *gic, | |||
259 | unsigned int irq_start) | 259 | unsigned int irq_start) |
260 | { | 260 | { |
261 | unsigned int gic_irqs, irq_limit, i; | 261 | unsigned int gic_irqs, irq_limit, i; |
262 | u32 cpumask; | ||
262 | void __iomem *base = gic->dist_base; | 263 | void __iomem *base = gic->dist_base; |
263 | u32 cpumask = 1 << smp_processor_id(); | 264 | u32 cpu = 0; |
264 | 265 | ||
266 | #ifdef CONFIG_SMP | ||
267 | cpu = cpu_logical_map(smp_processor_id()); | ||
268 | #endif | ||
269 | |||
270 | cpumask = 1 << cpu; | ||
265 | cpumask |= cpumask << 8; | 271 | cpumask |= cpumask << 8; |
266 | cpumask |= cpumask << 16; | 272 | cpumask |= cpumask << 16; |
267 | 273 | ||
@@ -382,7 +388,12 @@ void __cpuinit gic_enable_ppi(unsigned int irq) | |||
382 | #ifdef CONFIG_SMP | 388 | #ifdef CONFIG_SMP |
383 | void gic_raise_softirq(const struct cpumask *mask, unsigned int irq) | 389 | void gic_raise_softirq(const struct cpumask *mask, unsigned int irq) |
384 | { | 390 | { |
385 | unsigned long map = *cpus_addr(*mask); | 391 | int cpu; |
392 | unsigned long map = 0; | ||
393 | |||
394 | /* Convert our logical CPU mask into a physical one. */ | ||
395 | for_each_cpu(cpu, mask) | ||
396 | map |= 1 << cpu_logical_map(cpu); | ||
386 | 397 | ||
387 | /* | 398 | /* |
388 | * Ensure that stores to Normal memory are visible to the | 399 | * Ensure that stores to Normal memory are visible to the |
diff --git a/arch/arm/include/asm/cputype.h b/arch/arm/include/asm/cputype.h index cd4458f64171..cb47d28cbe1f 100644 --- a/arch/arm/include/asm/cputype.h +++ b/arch/arm/include/asm/cputype.h | |||
@@ -8,6 +8,7 @@ | |||
8 | #define CPUID_CACHETYPE 1 | 8 | #define CPUID_CACHETYPE 1 |
9 | #define CPUID_TCM 2 | 9 | #define CPUID_TCM 2 |
10 | #define CPUID_TLBTYPE 3 | 10 | #define CPUID_TLBTYPE 3 |
11 | #define CPUID_MPIDR 5 | ||
11 | 12 | ||
12 | #define CPUID_EXT_PFR0 "c1, 0" | 13 | #define CPUID_EXT_PFR0 "c1, 0" |
13 | #define CPUID_EXT_PFR1 "c1, 1" | 14 | #define CPUID_EXT_PFR1 "c1, 1" |
@@ -70,6 +71,11 @@ static inline unsigned int __attribute_const__ read_cpuid_tcmstatus(void) | |||
70 | return read_cpuid(CPUID_TCM); | 71 | return read_cpuid(CPUID_TCM); |
71 | } | 72 | } |
72 | 73 | ||
74 | static inline unsigned int __attribute_const__ read_cpuid_mpidr(void) | ||
75 | { | ||
76 | return read_cpuid(CPUID_MPIDR); | ||
77 | } | ||
78 | |||
73 | /* | 79 | /* |
74 | * Intel's XScale3 core supports some v6 features (supersections, L2) | 80 | * Intel's XScale3 core supports some v6 features (supersections, L2) |
75 | * but advertises itself as v5 as it does not support the v6 ISA. For | 81 | * but advertises itself as v5 as it does not support the v6 ISA. For |
diff --git a/arch/arm/include/asm/exception.h b/arch/arm/include/asm/exception.h new file mode 100644 index 000000000000..5abaf5bbd985 --- /dev/null +++ b/arch/arm/include/asm/exception.h | |||
@@ -0,0 +1,19 @@ | |||
1 | /* | ||
2 | * Annotations for marking C functions as exception handlers. | ||
3 | * | ||
4 | * These should only be used for C functions that are called from the low | ||
5 | * level exception entry code and not any intervening C code. | ||
6 | */ | ||
7 | #ifndef __ASM_ARM_EXCEPTION_H | ||
8 | #define __ASM_ARM_EXCEPTION_H | ||
9 | |||
10 | #include <linux/ftrace.h> | ||
11 | |||
12 | #define __exception __attribute__((section(".exception.text"))) | ||
13 | #ifdef CONFIG_FUNCTION_GRAPH_TRACER | ||
14 | #define __exception_irq_entry __irq_entry | ||
15 | #else | ||
16 | #define __exception_irq_entry __exception | ||
17 | #endif | ||
18 | |||
19 | #endif /* __ASM_ARM_EXCEPTION_H */ | ||
diff --git a/arch/arm/include/asm/localtimer.h b/arch/arm/include/asm/localtimer.h index 080d74f8128d..3306f281333c 100644 --- a/arch/arm/include/asm/localtimer.h +++ b/arch/arm/include/asm/localtimer.h | |||
@@ -22,6 +22,10 @@ void percpu_timer_setup(void); | |||
22 | */ | 22 | */ |
23 | asmlinkage void do_local_timer(struct pt_regs *); | 23 | asmlinkage void do_local_timer(struct pt_regs *); |
24 | 24 | ||
25 | /* | ||
26 | * Called from C code | ||
27 | */ | ||
28 | void handle_local_timer(struct pt_regs *); | ||
25 | 29 | ||
26 | #ifdef CONFIG_LOCAL_TIMERS | 30 | #ifdef CONFIG_LOCAL_TIMERS |
27 | 31 | ||
diff --git a/arch/arm/include/asm/smp.h b/arch/arm/include/asm/smp.h index e42d96a45d3e..0a17b62538c2 100644 --- a/arch/arm/include/asm/smp.h +++ b/arch/arm/include/asm/smp.h | |||
@@ -33,6 +33,11 @@ extern void show_ipi_list(struct seq_file *, int); | |||
33 | asmlinkage void do_IPI(int ipinr, struct pt_regs *regs); | 33 | asmlinkage void do_IPI(int ipinr, struct pt_regs *regs); |
34 | 34 | ||
35 | /* | 35 | /* |
36 | * Called from C code, this handles an IPI. | ||
37 | */ | ||
38 | void handle_IPI(int ipinr, struct pt_regs *regs); | ||
39 | |||
40 | /* | ||
36 | * Setup the set of possible CPUs (via set_cpu_possible) | 41 | * Setup the set of possible CPUs (via set_cpu_possible) |
37 | */ | 42 | */ |
38 | extern void smp_init_cpus(void); | 43 | extern void smp_init_cpus(void); |
@@ -66,6 +71,12 @@ extern void platform_secondary_init(unsigned int cpu); | |||
66 | extern void platform_smp_prepare_cpus(unsigned int); | 71 | extern void platform_smp_prepare_cpus(unsigned int); |
67 | 72 | ||
68 | /* | 73 | /* |
74 | * Logical CPU mapping. | ||
75 | */ | ||
76 | extern int __cpu_logical_map[NR_CPUS]; | ||
77 | #define cpu_logical_map(cpu) __cpu_logical_map[cpu] | ||
78 | |||
79 | /* | ||
69 | * Initial data for bringing up a secondary CPU. | 80 | * Initial data for bringing up a secondary CPU. |
70 | */ | 81 | */ |
71 | struct secondary_data { | 82 | struct secondary_data { |
diff --git a/arch/arm/include/asm/system.h b/arch/arm/include/asm/system.h index 832888d0c20c..ed6b0499a106 100644 --- a/arch/arm/include/asm/system.h +++ b/arch/arm/include/asm/system.h | |||
@@ -62,13 +62,6 @@ | |||
62 | 62 | ||
63 | #include <asm/outercache.h> | 63 | #include <asm/outercache.h> |
64 | 64 | ||
65 | #define __exception __attribute__((section(".exception.text"))) | ||
66 | #ifdef CONFIG_FUNCTION_GRAPH_TRACER | ||
67 | #define __exception_irq_entry __irq_entry | ||
68 | #else | ||
69 | #define __exception_irq_entry __exception | ||
70 | #endif | ||
71 | |||
72 | struct thread_info; | 65 | struct thread_info; |
73 | struct task_struct; | 66 | struct task_struct; |
74 | 67 | ||
diff --git a/arch/arm/include/asm/topology.h b/arch/arm/include/asm/topology.h index accbd7cad9b5..a7e457ed27c3 100644 --- a/arch/arm/include/asm/topology.h +++ b/arch/arm/include/asm/topology.h | |||
@@ -1,6 +1,39 @@ | |||
1 | #ifndef _ASM_ARM_TOPOLOGY_H | 1 | #ifndef _ASM_ARM_TOPOLOGY_H |
2 | #define _ASM_ARM_TOPOLOGY_H | 2 | #define _ASM_ARM_TOPOLOGY_H |
3 | 3 | ||
4 | #ifdef CONFIG_ARM_CPU_TOPOLOGY | ||
5 | |||
6 | #include <linux/cpumask.h> | ||
7 | |||
8 | struct cputopo_arm { | ||
9 | int thread_id; | ||
10 | int core_id; | ||
11 | int socket_id; | ||
12 | cpumask_t thread_sibling; | ||
13 | cpumask_t core_sibling; | ||
14 | }; | ||
15 | |||
16 | extern struct cputopo_arm cpu_topology[NR_CPUS]; | ||
17 | |||
18 | #define topology_physical_package_id(cpu) (cpu_topology[cpu].socket_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].socket_id != -1) | ||
24 | #define smt_capable() (cpu_topology[0].thread_id != -1) | ||
25 | |||
26 | void init_cpu_topology(void); | ||
27 | void store_cpu_topology(unsigned int cpuid); | ||
28 | const struct cpumask *cpu_coregroup_mask(unsigned int cpu); | ||
29 | |||
30 | #else | ||
31 | |||
32 | static inline void init_cpu_topology(void) { } | ||
33 | static inline void store_cpu_topology(unsigned int cpuid) { } | ||
34 | |||
35 | #endif | ||
36 | |||
4 | #include <asm-generic/topology.h> | 37 | #include <asm-generic/topology.h> |
5 | 38 | ||
6 | #endif /* _ASM_ARM_TOPOLOGY_H */ | 39 | #endif /* _ASM_ARM_TOPOLOGY_H */ |
diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile index f7887dc53c1f..c687bceba7da 100644 --- a/arch/arm/kernel/Makefile +++ b/arch/arm/kernel/Makefile | |||
@@ -66,6 +66,7 @@ obj-$(CONFIG_IWMMXT) += iwmmxt.o | |||
66 | obj-$(CONFIG_CPU_HAS_PMU) += pmu.o | 66 | obj-$(CONFIG_CPU_HAS_PMU) += pmu.o |
67 | obj-$(CONFIG_HW_PERF_EVENTS) += perf_event.o | 67 | obj-$(CONFIG_HW_PERF_EVENTS) += perf_event.o |
68 | AFLAGS_iwmmxt.o := -Wa,-mcpu=iwmmxt | 68 | AFLAGS_iwmmxt.o := -Wa,-mcpu=iwmmxt |
69 | obj-$(CONFIG_ARM_CPU_TOPOLOGY) += topology.o | ||
69 | 70 | ||
70 | ifneq ($(CONFIG_ARCH_EBSA110),y) | 71 | ifneq ($(CONFIG_ARCH_EBSA110),y) |
71 | obj-y += io.o | 72 | obj-y += io.o |
diff --git a/arch/arm/kernel/irq.c b/arch/arm/kernel/irq.c index de3dcab8610b..53919b230e8b 100644 --- a/arch/arm/kernel/irq.c +++ b/arch/arm/kernel/irq.c | |||
@@ -35,8 +35,8 @@ | |||
35 | #include <linux/list.h> | 35 | #include <linux/list.h> |
36 | #include <linux/kallsyms.h> | 36 | #include <linux/kallsyms.h> |
37 | #include <linux/proc_fs.h> | 37 | #include <linux/proc_fs.h> |
38 | #include <linux/ftrace.h> | ||
39 | 38 | ||
39 | #include <asm/exception.h> | ||
40 | #include <asm/system.h> | 40 | #include <asm/system.h> |
41 | #include <asm/mach/arch.h> | 41 | #include <asm/mach/arch.h> |
42 | #include <asm/mach/irq.h> | 42 | #include <asm/mach/irq.h> |
diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c index d88ff0230e82..35417d0fb8ab 100644 --- a/arch/arm/kernel/smp.c +++ b/arch/arm/kernel/smp.c | |||
@@ -16,7 +16,6 @@ | |||
16 | #include <linux/cache.h> | 16 | #include <linux/cache.h> |
17 | #include <linux/profile.h> | 17 | #include <linux/profile.h> |
18 | #include <linux/errno.h> | 18 | #include <linux/errno.h> |
19 | #include <linux/ftrace.h> | ||
20 | #include <linux/mm.h> | 19 | #include <linux/mm.h> |
21 | #include <linux/err.h> | 20 | #include <linux/err.h> |
22 | #include <linux/cpu.h> | 21 | #include <linux/cpu.h> |
@@ -31,6 +30,8 @@ | |||
31 | #include <asm/cacheflush.h> | 30 | #include <asm/cacheflush.h> |
32 | #include <asm/cpu.h> | 31 | #include <asm/cpu.h> |
33 | #include <asm/cputype.h> | 32 | #include <asm/cputype.h> |
33 | #include <asm/exception.h> | ||
34 | #include <asm/topology.h> | ||
34 | #include <asm/mmu_context.h> | 35 | #include <asm/mmu_context.h> |
35 | #include <asm/pgtable.h> | 36 | #include <asm/pgtable.h> |
36 | #include <asm/pgalloc.h> | 37 | #include <asm/pgalloc.h> |
@@ -39,6 +40,7 @@ | |||
39 | #include <asm/tlbflush.h> | 40 | #include <asm/tlbflush.h> |
40 | #include <asm/ptrace.h> | 41 | #include <asm/ptrace.h> |
41 | #include <asm/localtimer.h> | 42 | #include <asm/localtimer.h> |
43 | #include <asm/smp_plat.h> | ||
42 | 44 | ||
43 | /* | 45 | /* |
44 | * as from 2.5, kernels no longer have an init_tasks structure | 46 | * as from 2.5, kernels no longer have an init_tasks structure |
@@ -259,6 +261,20 @@ void __ref cpu_die(void) | |||
259 | } | 261 | } |
260 | #endif /* CONFIG_HOTPLUG_CPU */ | 262 | #endif /* CONFIG_HOTPLUG_CPU */ |
261 | 263 | ||
264 | int __cpu_logical_map[NR_CPUS]; | ||
265 | |||
266 | void __init smp_setup_processor_id(void) | ||
267 | { | ||
268 | int i; | ||
269 | u32 cpu = is_smp() ? read_cpuid_mpidr() & 0xff : 0; | ||
270 | |||
271 | cpu_logical_map(0) = cpu; | ||
272 | for (i = 1; i < NR_CPUS; ++i) | ||
273 | cpu_logical_map(i) = i == cpu ? 0 : i; | ||
274 | |||
275 | printk(KERN_INFO "Booting Linux on physical CPU %d\n", cpu); | ||
276 | } | ||
277 | |||
262 | /* | 278 | /* |
263 | * Called by both boot and secondaries to move global data into | 279 | * Called by both boot and secondaries to move global data into |
264 | * per-processor storage. | 280 | * per-processor storage. |
@@ -268,6 +284,8 @@ static void __cpuinit smp_store_cpu_info(unsigned int cpuid) | |||
268 | struct cpuinfo_arm *cpu_info = &per_cpu(cpu_data, cpuid); | 284 | struct cpuinfo_arm *cpu_info = &per_cpu(cpu_data, cpuid); |
269 | 285 | ||
270 | cpu_info->loops_per_jiffy = loops_per_jiffy; | 286 | cpu_info->loops_per_jiffy = loops_per_jiffy; |
287 | |||
288 | store_cpu_topology(cpuid); | ||
271 | } | 289 | } |
272 | 290 | ||
273 | /* | 291 | /* |
@@ -358,6 +376,8 @@ void __init smp_prepare_cpus(unsigned int max_cpus) | |||
358 | { | 376 | { |
359 | unsigned int ncores = num_possible_cpus(); | 377 | unsigned int ncores = num_possible_cpus(); |
360 | 378 | ||
379 | init_cpu_topology(); | ||
380 | |||
361 | smp_store_cpu_info(smp_processor_id()); | 381 | smp_store_cpu_info(smp_processor_id()); |
362 | 382 | ||
363 | /* | 383 | /* |
@@ -460,6 +480,11 @@ static void ipi_timer(void) | |||
460 | #ifdef CONFIG_LOCAL_TIMERS | 480 | #ifdef CONFIG_LOCAL_TIMERS |
461 | asmlinkage void __exception_irq_entry do_local_timer(struct pt_regs *regs) | 481 | asmlinkage void __exception_irq_entry do_local_timer(struct pt_regs *regs) |
462 | { | 482 | { |
483 | handle_local_timer(regs); | ||
484 | } | ||
485 | |||
486 | void handle_local_timer(struct pt_regs *regs) | ||
487 | { | ||
463 | struct pt_regs *old_regs = set_irq_regs(regs); | 488 | struct pt_regs *old_regs = set_irq_regs(regs); |
464 | int cpu = smp_processor_id(); | 489 | int cpu = smp_processor_id(); |
465 | 490 | ||
@@ -567,6 +592,11 @@ static void ipi_cpu_stop(unsigned int cpu) | |||
567 | */ | 592 | */ |
568 | asmlinkage void __exception_irq_entry do_IPI(int ipinr, struct pt_regs *regs) | 593 | asmlinkage void __exception_irq_entry do_IPI(int ipinr, struct pt_regs *regs) |
569 | { | 594 | { |
595 | handle_IPI(ipinr, regs); | ||
596 | } | ||
597 | |||
598 | void handle_IPI(int ipinr, struct pt_regs *regs) | ||
599 | { | ||
570 | unsigned int cpu = smp_processor_id(); | 600 | unsigned int cpu = smp_processor_id(); |
571 | struct pt_regs *old_regs = set_irq_regs(regs); | 601 | struct pt_regs *old_regs = set_irq_regs(regs); |
572 | 602 | ||
diff --git a/arch/arm/kernel/smp_scu.c b/arch/arm/kernel/smp_scu.c index 79ed5e7f204a..5b6d536cbfe3 100644 --- a/arch/arm/kernel/smp_scu.c +++ b/arch/arm/kernel/smp_scu.c | |||
@@ -33,7 +33,7 @@ unsigned int __init scu_get_core_count(void __iomem *scu_base) | |||
33 | /* | 33 | /* |
34 | * Enable the SCU | 34 | * Enable the SCU |
35 | */ | 35 | */ |
36 | void __init scu_enable(void __iomem *scu_base) | 36 | void scu_enable(void __iomem *scu_base) |
37 | { | 37 | { |
38 | u32 scu_ctrl; | 38 | u32 scu_ctrl; |
39 | 39 | ||
diff --git a/arch/arm/kernel/topology.c b/arch/arm/kernel/topology.c new file mode 100644 index 000000000000..1040c00405d0 --- /dev/null +++ b/arch/arm/kernel/topology.c | |||
@@ -0,0 +1,148 @@ | |||
1 | /* | ||
2 | * arch/arm/kernel/topology.c | ||
3 | * | ||
4 | * Copyright (C) 2011 Linaro Limited. | ||
5 | * Written by: Vincent Guittot | ||
6 | * | ||
7 | * based on 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/cputype.h> | ||
23 | #include <asm/topology.h> | ||
24 | |||
25 | #define MPIDR_SMP_BITMASK (0x3 << 30) | ||
26 | #define MPIDR_SMP_VALUE (0x2 << 30) | ||
27 | |||
28 | #define MPIDR_MT_BITMASK (0x1 << 24) | ||
29 | |||
30 | /* | ||
31 | * These masks reflect the current use of the affinity levels. | ||
32 | * The affinity level can be up to 16 bits according to ARM ARM | ||
33 | */ | ||
34 | |||
35 | #define MPIDR_LEVEL0_MASK 0x3 | ||
36 | #define MPIDR_LEVEL0_SHIFT 0 | ||
37 | |||
38 | #define MPIDR_LEVEL1_MASK 0xF | ||
39 | #define MPIDR_LEVEL1_SHIFT 8 | ||
40 | |||
41 | #define MPIDR_LEVEL2_MASK 0xFF | ||
42 | #define MPIDR_LEVEL2_SHIFT 16 | ||
43 | |||
44 | struct cputopo_arm cpu_topology[NR_CPUS]; | ||
45 | |||
46 | const struct cpumask *cpu_coregroup_mask(unsigned int cpu) | ||
47 | { | ||
48 | return &cpu_topology[cpu].core_sibling; | ||
49 | } | ||
50 | |||
51 | /* | ||
52 | * store_cpu_topology is called at boot when only one cpu is running | ||
53 | * and with the mutex cpu_hotplug.lock locked, when several cpus have booted, | ||
54 | * which prevents simultaneous write access to cpu_topology array | ||
55 | */ | ||
56 | void store_cpu_topology(unsigned int cpuid) | ||
57 | { | ||
58 | struct cputopo_arm *cpuid_topo = &cpu_topology[cpuid]; | ||
59 | unsigned int mpidr; | ||
60 | unsigned int cpu; | ||
61 | |||
62 | /* If the cpu topology has been already set, just return */ | ||
63 | if (cpuid_topo->core_id != -1) | ||
64 | return; | ||
65 | |||
66 | mpidr = read_cpuid_mpidr(); | ||
67 | |||
68 | /* create cpu topology mapping */ | ||
69 | if ((mpidr & MPIDR_SMP_BITMASK) == MPIDR_SMP_VALUE) { | ||
70 | /* | ||
71 | * This is a multiprocessor system | ||
72 | * multiprocessor format & multiprocessor mode field are set | ||
73 | */ | ||
74 | |||
75 | if (mpidr & MPIDR_MT_BITMASK) { | ||
76 | /* core performance interdependency */ | ||
77 | cpuid_topo->thread_id = (mpidr >> MPIDR_LEVEL0_SHIFT) | ||
78 | & MPIDR_LEVEL0_MASK; | ||
79 | cpuid_topo->core_id = (mpidr >> MPIDR_LEVEL1_SHIFT) | ||
80 | & MPIDR_LEVEL1_MASK; | ||
81 | cpuid_topo->socket_id = (mpidr >> MPIDR_LEVEL2_SHIFT) | ||
82 | & MPIDR_LEVEL2_MASK; | ||
83 | } else { | ||
84 | /* largely independent cores */ | ||
85 | cpuid_topo->thread_id = -1; | ||
86 | cpuid_topo->core_id = (mpidr >> MPIDR_LEVEL0_SHIFT) | ||
87 | & MPIDR_LEVEL0_MASK; | ||
88 | cpuid_topo->socket_id = (mpidr >> MPIDR_LEVEL1_SHIFT) | ||
89 | & MPIDR_LEVEL1_MASK; | ||
90 | } | ||
91 | } else { | ||
92 | /* | ||
93 | * This is an uniprocessor system | ||
94 | * we are in multiprocessor format but uniprocessor system | ||
95 | * or in the old uniprocessor format | ||
96 | */ | ||
97 | cpuid_topo->thread_id = -1; | ||
98 | cpuid_topo->core_id = 0; | ||
99 | cpuid_topo->socket_id = -1; | ||
100 | } | ||
101 | |||
102 | /* update core and thread sibling masks */ | ||
103 | for_each_possible_cpu(cpu) { | ||
104 | struct cputopo_arm *cpu_topo = &cpu_topology[cpu]; | ||
105 | |||
106 | if (cpuid_topo->socket_id == cpu_topo->socket_id) { | ||
107 | cpumask_set_cpu(cpuid, &cpu_topo->core_sibling); | ||
108 | if (cpu != cpuid) | ||
109 | cpumask_set_cpu(cpu, | ||
110 | &cpuid_topo->core_sibling); | ||
111 | |||
112 | if (cpuid_topo->core_id == cpu_topo->core_id) { | ||
113 | cpumask_set_cpu(cpuid, | ||
114 | &cpu_topo->thread_sibling); | ||
115 | if (cpu != cpuid) | ||
116 | cpumask_set_cpu(cpu, | ||
117 | &cpuid_topo->thread_sibling); | ||
118 | } | ||
119 | } | ||
120 | } | ||
121 | smp_wmb(); | ||
122 | |||
123 | printk(KERN_INFO "CPU%u: thread %d, cpu %d, socket %d, mpidr %x\n", | ||
124 | cpuid, cpu_topology[cpuid].thread_id, | ||
125 | cpu_topology[cpuid].core_id, | ||
126 | cpu_topology[cpuid].socket_id, mpidr); | ||
127 | } | ||
128 | |||
129 | /* | ||
130 | * init_cpu_topology is called at boot when only one cpu is running | ||
131 | * which prevent simultaneous write access to cpu_topology array | ||
132 | */ | ||
133 | void init_cpu_topology(void) | ||
134 | { | ||
135 | unsigned int cpu; | ||
136 | |||
137 | /* init core mask */ | ||
138 | for_each_possible_cpu(cpu) { | ||
139 | struct cputopo_arm *cpu_topo = &(cpu_topology[cpu]); | ||
140 | |||
141 | cpu_topo->thread_id = -1; | ||
142 | cpu_topo->core_id = -1; | ||
143 | cpu_topo->socket_id = -1; | ||
144 | cpumask_clear(&cpu_topo->core_sibling); | ||
145 | cpumask_clear(&cpu_topo->thread_sibling); | ||
146 | } | ||
147 | smp_wmb(); | ||
148 | } | ||
diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c index bc9f9da782cb..210382555af1 100644 --- a/arch/arm/kernel/traps.c +++ b/arch/arm/kernel/traps.c | |||
@@ -27,6 +27,7 @@ | |||
27 | 27 | ||
28 | #include <linux/atomic.h> | 28 | #include <linux/atomic.h> |
29 | #include <asm/cacheflush.h> | 29 | #include <asm/cacheflush.h> |
30 | #include <asm/exception.h> | ||
30 | #include <asm/system.h> | 31 | #include <asm/system.h> |
31 | #include <asm/unistd.h> | 32 | #include <asm/unistd.h> |
32 | #include <asm/traps.h> | 33 | #include <asm/traps.h> |
diff --git a/arch/arm/mach-exynos4/hotplug.c b/arch/arm/mach-exynos4/hotplug.c index 7490789784c9..da70e7e39937 100644 --- a/arch/arm/mach-exynos4/hotplug.c +++ b/arch/arm/mach-exynos4/hotplug.c | |||
@@ -75,7 +75,7 @@ static inline void platform_do_lowpower(unsigned int cpu, int *spurious) | |||
75 | : | 75 | : |
76 | : "memory", "cc"); | 76 | : "memory", "cc"); |
77 | 77 | ||
78 | if (pen_release == cpu) { | 78 | if (pen_release == cpu_logical_map(cpu)) { |
79 | /* | 79 | /* |
80 | * OK, proper wakeup, we're done | 80 | * OK, proper wakeup, we're done |
81 | */ | 81 | */ |
diff --git a/arch/arm/mach-exynos4/platsmp.c b/arch/arm/mach-exynos4/platsmp.c index 7c2282c6ba81..073381469c9d 100644 --- a/arch/arm/mach-exynos4/platsmp.c +++ b/arch/arm/mach-exynos4/platsmp.c | |||
@@ -126,7 +126,7 @@ int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle) | |||
126 | * Note that "pen_release" is the hardware CPU ID, whereas | 126 | * Note that "pen_release" is the hardware CPU ID, whereas |
127 | * "cpu" is Linux's internal ID. | 127 | * "cpu" is Linux's internal ID. |
128 | */ | 128 | */ |
129 | write_pen_release(cpu); | 129 | write_pen_release(cpu_logical_map(cpu)); |
130 | 130 | ||
131 | if (!(__raw_readl(S5P_ARM_CORE1_STATUS) & S5P_CORE_LOCAL_PWR_EN)) { | 131 | if (!(__raw_readl(S5P_ARM_CORE1_STATUS) & S5P_CORE_LOCAL_PWR_EN)) { |
132 | __raw_writel(S5P_CORE_LOCAL_PWR_EN, | 132 | __raw_writel(S5P_CORE_LOCAL_PWR_EN, |
diff --git a/arch/arm/mach-msm/hotplug.c b/arch/arm/mach-msm/hotplug.c index 5a31f70dfb8e..41c252de0215 100644 --- a/arch/arm/mach-msm/hotplug.c +++ b/arch/arm/mach-msm/hotplug.c | |||
@@ -37,7 +37,7 @@ static inline void platform_do_lowpower(unsigned int cpu) | |||
37 | : | 37 | : |
38 | : "memory", "cc"); | 38 | : "memory", "cc"); |
39 | 39 | ||
40 | if (pen_release == cpu) { | 40 | if (pen_release == cpu_logical_map(cpu)) { |
41 | /* | 41 | /* |
42 | * OK, proper wakeup, we're done | 42 | * OK, proper wakeup, we're done |
43 | */ | 43 | */ |
diff --git a/arch/arm/mach-msm/platsmp.c b/arch/arm/mach-msm/platsmp.c index 1a1af9e56250..e3375ee7841e 100644 --- a/arch/arm/mach-msm/platsmp.c +++ b/arch/arm/mach-msm/platsmp.c | |||
@@ -117,7 +117,7 @@ int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle) | |||
117 | * Note that "pen_release" is the hardware CPU ID, whereas | 117 | * Note that "pen_release" is the hardware CPU ID, whereas |
118 | * "cpu" is Linux's internal ID. | 118 | * "cpu" is Linux's internal ID. |
119 | */ | 119 | */ |
120 | pen_release = cpu; | 120 | pen_release = cpu_logical_map(cpu); |
121 | __cpuc_flush_dcache_area((void *)&pen_release, sizeof(pen_release)); | 121 | __cpuc_flush_dcache_area((void *)&pen_release, sizeof(pen_release)); |
122 | outer_clean_range(__pa(&pen_release), __pa(&pen_release + 1)); | 122 | outer_clean_range(__pa(&pen_release), __pa(&pen_release + 1)); |
123 | 123 | ||
diff --git a/arch/arm/mach-pxa/irq.c b/arch/arm/mach-pxa/irq.c index b09e848eb6c6..ca6075717824 100644 --- a/arch/arm/mach-pxa/irq.c +++ b/arch/arm/mach-pxa/irq.c | |||
@@ -19,6 +19,8 @@ | |||
19 | #include <linux/io.h> | 19 | #include <linux/io.h> |
20 | #include <linux/irq.h> | 20 | #include <linux/irq.h> |
21 | 21 | ||
22 | #include <asm/exception.h> | ||
23 | |||
22 | #include <mach/hardware.h> | 24 | #include <mach/hardware.h> |
23 | #include <mach/irqs.h> | 25 | #include <mach/irqs.h> |
24 | #include <mach/gpio.h> | 26 | #include <mach/gpio.h> |
diff --git a/arch/arm/mach-realview/hotplug.c b/arch/arm/mach-realview/hotplug.c index a87523d095e6..ac1aed2a8da4 100644 --- a/arch/arm/mach-realview/hotplug.c +++ b/arch/arm/mach-realview/hotplug.c | |||
@@ -69,7 +69,7 @@ static inline void platform_do_lowpower(unsigned int cpu, int *spurious) | |||
69 | : | 69 | : |
70 | : "memory", "cc"); | 70 | : "memory", "cc"); |
71 | 71 | ||
72 | if (pen_release == cpu) { | 72 | if (pen_release == cpu_logical_map(cpu)) { |
73 | /* | 73 | /* |
74 | * OK, proper wakeup, we're done | 74 | * OK, proper wakeup, we're done |
75 | */ | 75 | */ |
diff --git a/arch/arm/mach-shmobile/smp-sh73a0.c b/arch/arm/mach-shmobile/smp-sh73a0.c index 3ffdbc92ba82..be1ade76ccc8 100644 --- a/arch/arm/mach-shmobile/smp-sh73a0.c +++ b/arch/arm/mach-shmobile/smp-sh73a0.c | |||
@@ -74,6 +74,8 @@ void __cpuinit sh73a0_secondary_init(unsigned int cpu) | |||
74 | 74 | ||
75 | int __cpuinit sh73a0_boot_secondary(unsigned int cpu) | 75 | int __cpuinit sh73a0_boot_secondary(unsigned int cpu) |
76 | { | 76 | { |
77 | cpu = cpu_logical_map(cpu); | ||
78 | |||
77 | /* enable cache coherency */ | 79 | /* enable cache coherency */ |
78 | modify_scu_cpu_psr(0, 3 << (cpu * 8)); | 80 | modify_scu_cpu_psr(0, 3 << (cpu * 8)); |
79 | 81 | ||
@@ -87,6 +89,8 @@ int __cpuinit sh73a0_boot_secondary(unsigned int cpu) | |||
87 | 89 | ||
88 | void __init sh73a0_smp_prepare_cpus(void) | 90 | void __init sh73a0_smp_prepare_cpus(void) |
89 | { | 91 | { |
92 | int cpu = cpu_logical_map(0); | ||
93 | |||
90 | scu_enable(scu_base_addr()); | 94 | scu_enable(scu_base_addr()); |
91 | 95 | ||
92 | /* Map the reset vector (in headsmp.S) */ | 96 | /* Map the reset vector (in headsmp.S) */ |
@@ -94,5 +98,5 @@ void __init sh73a0_smp_prepare_cpus(void) | |||
94 | __raw_writel(__pa(shmobile_secondary_vector), __io(SBAR)); | 98 | __raw_writel(__pa(shmobile_secondary_vector), __io(SBAR)); |
95 | 99 | ||
96 | /* enable cache coherency on CPU0 */ | 100 | /* enable cache coherency on CPU0 */ |
97 | modify_scu_cpu_psr(0, 3 << (0 * 8)); | 101 | modify_scu_cpu_psr(0, 3 << (cpu * 8)); |
98 | } | 102 | } |
diff --git a/arch/arm/mach-ux500/hotplug.c b/arch/arm/mach-ux500/hotplug.c index dd8037ebccf8..572015e57cd9 100644 --- a/arch/arm/mach-ux500/hotplug.c +++ b/arch/arm/mach-ux500/hotplug.c | |||
@@ -24,7 +24,7 @@ static inline void platform_do_lowpower(unsigned int cpu) | |||
24 | for (;;) { | 24 | for (;;) { |
25 | __asm__ __volatile__("dsb\n\t" "wfi\n\t" | 25 | __asm__ __volatile__("dsb\n\t" "wfi\n\t" |
26 | : : : "memory"); | 26 | : : : "memory"); |
27 | if (pen_release == cpu) { | 27 | if (pen_release == cpu_logical_map(cpu)) { |
28 | /* | 28 | /* |
29 | * OK, proper wakeup, we're done | 29 | * OK, proper wakeup, we're done |
30 | */ | 30 | */ |
diff --git a/arch/arm/mach-ux500/platsmp.c b/arch/arm/mach-ux500/platsmp.c index a33df5f4c27a..27e5281cd55d 100644 --- a/arch/arm/mach-ux500/platsmp.c +++ b/arch/arm/mach-ux500/platsmp.c | |||
@@ -96,7 +96,7 @@ int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle) | |||
96 | * the holding pen - release it, then wait for it to flag | 96 | * the holding pen - release it, then wait for it to flag |
97 | * that it has been released by resetting pen_release. | 97 | * that it has been released by resetting pen_release. |
98 | */ | 98 | */ |
99 | write_pen_release(cpu); | 99 | write_pen_release(cpu_logical_map(cpu)); |
100 | 100 | ||
101 | gic_raise_softirq(cpumask_of(cpu), 1); | 101 | gic_raise_softirq(cpumask_of(cpu), 1); |
102 | 102 | ||
diff --git a/arch/arm/mach-vexpress/hotplug.c b/arch/arm/mach-vexpress/hotplug.c index ea4cbfb90a66..2866ed8c4b05 100644 --- a/arch/arm/mach-vexpress/hotplug.c +++ b/arch/arm/mach-vexpress/hotplug.c | |||
@@ -70,7 +70,7 @@ static inline void platform_do_lowpower(unsigned int cpu, int *spurious) | |||
70 | : | 70 | : |
71 | : "memory", "cc"); | 71 | : "memory", "cc"); |
72 | 72 | ||
73 | if (pen_release == cpu) { | 73 | if (pen_release == cpu_logical_map(cpu)) { |
74 | /* | 74 | /* |
75 | * OK, proper wakeup, we're done | 75 | * OK, proper wakeup, we're done |
76 | */ | 76 | */ |
diff --git a/arch/arm/mm/fault.c b/arch/arm/mm/fault.c index 3b5ea68acbb8..aa33949fef60 100644 --- a/arch/arm/mm/fault.c +++ b/arch/arm/mm/fault.c | |||
@@ -20,6 +20,7 @@ | |||
20 | #include <linux/highmem.h> | 20 | #include <linux/highmem.h> |
21 | #include <linux/perf_event.h> | 21 | #include <linux/perf_event.h> |
22 | 22 | ||
23 | #include <asm/exception.h> | ||
23 | #include <asm/system.h> | 24 | #include <asm/system.h> |
24 | #include <asm/pgtable.h> | 25 | #include <asm/pgtable.h> |
25 | #include <asm/tlbflush.h> | 26 | #include <asm/tlbflush.h> |
diff --git a/arch/arm/plat-versatile/platsmp.c b/arch/arm/plat-versatile/platsmp.c index 51ecfea09b27..92f18d372b69 100644 --- a/arch/arm/plat-versatile/platsmp.c +++ b/arch/arm/plat-versatile/platsmp.c | |||
@@ -77,7 +77,7 @@ int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle) | |||
77 | * since we haven't sent them a soft interrupt, they shouldn't | 77 | * since we haven't sent them a soft interrupt, they shouldn't |
78 | * be there. | 78 | * be there. |
79 | */ | 79 | */ |
80 | write_pen_release(cpu); | 80 | write_pen_release(cpu_logical_map(cpu)); |
81 | 81 | ||
82 | /* | 82 | /* |
83 | * Send the secondary CPU a soft interrupt, thereby causing | 83 | * Send the secondary CPU a soft interrupt, thereby causing |