diff options
Diffstat (limited to 'arch/arm/kernel')
-rw-r--r-- | arch/arm/kernel/entry-armv.S | 11 | ||||
-rw-r--r-- | arch/arm/kernel/head.S | 50 | ||||
-rw-r--r-- | arch/arm/kernel/setup.c | 4 | ||||
-rw-r--r-- | arch/arm/kernel/vmlinux.lds.S | 11 |
4 files changed, 69 insertions, 7 deletions
diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S index bb8e93a76407..c09e3573c5de 100644 --- a/arch/arm/kernel/entry-armv.S +++ b/arch/arm/kernel/entry-armv.S @@ -46,7 +46,8 @@ * this macro assumes that irqstat (r6) and base (r5) are * preserved from get_irqnr_and_base above */ - test_for_ipi r0, r6, r5, lr + ALT_SMP(test_for_ipi r0, r6, r5, lr) + ALT_UP_B(9997f) movne r0, sp adrne lr, BSYM(1b) bne do_IPI @@ -57,6 +58,7 @@ adrne lr, BSYM(1b) bne do_local_timer #endif +9997: #endif .endm @@ -965,11 +967,8 @@ kuser_cmpxchg_fixup: beq 1b rsbs r0, r3, #0 /* beware -- each __kuser slot must be 8 instructions max */ -#ifdef CONFIG_SMP - b __kuser_memory_barrier -#else - usr_ret lr -#endif + ALT_SMP(b __kuser_memory_barrier) + ALT_UP(usr_ret lr) #endif diff --git a/arch/arm/kernel/head.S b/arch/arm/kernel/head.S index eb62bf947212..b44d21e1e344 100644 --- a/arch/arm/kernel/head.S +++ b/arch/arm/kernel/head.S @@ -86,6 +86,9 @@ ENTRY(stext) movs r8, r5 @ invalid machine (r5=0)? beq __error_a @ yes, error 'a' bl __vet_atags +#ifdef CONFIG_SMP_ON_UP + bl __fixup_smp +#endif bl __create_page_tables /* @@ -333,4 +336,51 @@ __create_page_tables: ENDPROC(__create_page_tables) .ltorg +#ifdef CONFIG_SMP_ON_UP +__fixup_smp: + mov r7, #0x00070000 + orr r6, r7, #0xff000000 @ mask 0xff070000 + orr r7, r7, #0x41000000 @ val 0x41070000 + and r0, r9, r6 + teq r0, r7 @ ARM CPU and ARMv6/v7? + bne __fixup_smp_on_up @ no, assume UP + + orr r6, r6, #0x0000ff00 + orr r6, r6, #0x000000f0 @ mask 0xff07fff0 + orr r7, r7, #0x0000b000 + orr r7, r7, #0x00000020 @ val 0x4107b020 + and r0, r9, r6 + teq r0, r7 @ ARM 11MPCore? + moveq pc, lr @ yes, assume SMP + + mrc p15, 0, r0, c0, c0, 5 @ read MPIDR + tst r0, #1 << 31 + movne pc, lr @ bit 31 => SMP + +__fixup_smp_on_up: + adr r0, 1f + ldmia r0, {r3, r6, r7} + sub r3, r0, r3 + add r6, r6, r3 + add r7, r7, r3 +2: cmp r6, r7 + ldmia r6!, {r0, r4} + strlo r4, [r0, r3] + blo 2b + mov pc, lr +ENDPROC(__fixup_smp) + +1: .word . + .word __smpalt_begin + .word __smpalt_end + + .pushsection .data + .globl smp_on_up +smp_on_up: + ALT_SMP(.long 1) + ALT_UP(.long 0) + .popsection + +#endif + #include "head-common.S" diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c index d5231ae7355a..5a82c39ca85e 100644 --- a/arch/arm/kernel/setup.c +++ b/arch/arm/kernel/setup.c @@ -36,6 +36,7 @@ #include <asm/procinfo.h> #include <asm/sections.h> #include <asm/setup.h> +#include <asm/smp_plat.h> #include <asm/mach-types.h> #include <asm/cacheflush.h> #include <asm/cachetype.h> @@ -825,7 +826,8 @@ void __init setup_arch(char **cmdline_p) request_standard_resources(&meminfo, mdesc); #ifdef CONFIG_SMP - smp_init_cpus(); + if (is_smp()) + smp_init_cpus(); #endif reserve_crashkernel(); diff --git a/arch/arm/kernel/vmlinux.lds.S b/arch/arm/kernel/vmlinux.lds.S index b16c07914b55..fd5750b8ac84 100644 --- a/arch/arm/kernel/vmlinux.lds.S +++ b/arch/arm/kernel/vmlinux.lds.S @@ -40,6 +40,11 @@ SECTIONS __tagtable_begin = .; *(.taglist.init) __tagtable_end = .; +#ifdef CONFIG_SMP_ON_UP + __smpalt_begin = .; + *(.alt.smp.init) + __smpalt_end = .; +#endif INIT_SETUP(16) @@ -237,6 +242,12 @@ SECTIONS /* Default discards */ DISCARDS + +#ifndef CONFIG_SMP_ON_UP + /DISCARD/ : { + *(.alt.smp.init) + } +#endif } /* |