diff options
Diffstat (limited to 'arch/arm')
-rw-r--r-- | arch/arm/Kconfig | 2 | ||||
-rw-r--r-- | arch/arm/include/asm/assembler.h | 22 | ||||
-rw-r--r-- | arch/arm/kernel/entry-armv.S | 4 | ||||
-rw-r--r-- | arch/arm/kernel/head.S | 13 |
4 files changed, 32 insertions, 9 deletions
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index db524e75c4a2..290a4b57617f 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig | |||
@@ -1229,7 +1229,7 @@ config SMP | |||
1229 | config SMP_ON_UP | 1229 | config SMP_ON_UP |
1230 | bool "Allow booting SMP kernel on uniprocessor systems (EXPERIMENTAL)" | 1230 | bool "Allow booting SMP kernel on uniprocessor systems (EXPERIMENTAL)" |
1231 | depends on EXPERIMENTAL | 1231 | depends on EXPERIMENTAL |
1232 | depends on SMP && !XIP && !THUMB2_KERNEL | 1232 | depends on SMP && !XIP |
1233 | default y | 1233 | default y |
1234 | help | 1234 | help |
1235 | SMP kernels contain instructions which fail on non-SMP processors. | 1235 | SMP kernels contain instructions which fail on non-SMP processors. |
diff --git a/arch/arm/include/asm/assembler.h b/arch/arm/include/asm/assembler.h index 749bb6622404..72d3389e9c12 100644 --- a/arch/arm/include/asm/assembler.h +++ b/arch/arm/include/asm/assembler.h | |||
@@ -157,16 +157,24 @@ | |||
157 | #ifdef CONFIG_SMP | 157 | #ifdef CONFIG_SMP |
158 | #define ALT_SMP(instr...) \ | 158 | #define ALT_SMP(instr...) \ |
159 | 9998: instr | 159 | 9998: instr |
160 | /* | ||
161 | * Note: if you get assembler errors from ALT_UP() when building with | ||
162 | * CONFIG_THUMB2_KERNEL, you almost certainly need to use | ||
163 | * ALT_SMP( W(instr) ... ) | ||
164 | */ | ||
160 | #define ALT_UP(instr...) \ | 165 | #define ALT_UP(instr...) \ |
161 | .pushsection ".alt.smp.init", "a" ;\ | 166 | .pushsection ".alt.smp.init", "a" ;\ |
162 | .long 9998b ;\ | 167 | .long 9998b ;\ |
163 | instr ;\ | 168 | 9997: instr ;\ |
169 | .if . - 9997b != 4 ;\ | ||
170 | .error "ALT_UP() content must assemble to exactly 4 bytes";\ | ||
171 | .endif ;\ | ||
164 | .popsection | 172 | .popsection |
165 | #define ALT_UP_B(label) \ | 173 | #define ALT_UP_B(label) \ |
166 | .equ up_b_offset, label - 9998b ;\ | 174 | .equ up_b_offset, label - 9998b ;\ |
167 | .pushsection ".alt.smp.init", "a" ;\ | 175 | .pushsection ".alt.smp.init", "a" ;\ |
168 | .long 9998b ;\ | 176 | .long 9998b ;\ |
169 | b . + up_b_offset ;\ | 177 | W(b) . + up_b_offset ;\ |
170 | .popsection | 178 | .popsection |
171 | #else | 179 | #else |
172 | #define ALT_SMP(instr...) | 180 | #define ALT_SMP(instr...) |
@@ -177,16 +185,24 @@ | |||
177 | /* | 185 | /* |
178 | * SMP data memory barrier | 186 | * SMP data memory barrier |
179 | */ | 187 | */ |
180 | .macro smp_dmb | 188 | .macro smp_dmb mode |
181 | #ifdef CONFIG_SMP | 189 | #ifdef CONFIG_SMP |
182 | #if __LINUX_ARM_ARCH__ >= 7 | 190 | #if __LINUX_ARM_ARCH__ >= 7 |
191 | .ifeqs "\mode","arm" | ||
183 | ALT_SMP(dmb) | 192 | ALT_SMP(dmb) |
193 | .else | ||
194 | ALT_SMP(W(dmb)) | ||
195 | .endif | ||
184 | #elif __LINUX_ARM_ARCH__ == 6 | 196 | #elif __LINUX_ARM_ARCH__ == 6 |
185 | ALT_SMP(mcr p15, 0, r0, c7, c10, 5) @ dmb | 197 | ALT_SMP(mcr p15, 0, r0, c7, c10, 5) @ dmb |
186 | #else | 198 | #else |
187 | #error Incompatible SMP platform | 199 | #error Incompatible SMP platform |
188 | #endif | 200 | #endif |
201 | .ifeqs "\mode","arm" | ||
189 | ALT_UP(nop) | 202 | ALT_UP(nop) |
203 | .else | ||
204 | ALT_UP(W(nop)) | ||
205 | .endif | ||
190 | #endif | 206 | #endif |
191 | .endm | 207 | .endm |
192 | 208 | ||
diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S index 955cf5f539ed..7f22a11a5105 100644 --- a/arch/arm/kernel/entry-armv.S +++ b/arch/arm/kernel/entry-armv.S | |||
@@ -842,7 +842,7 @@ __kuser_helper_start: | |||
842 | */ | 842 | */ |
843 | 843 | ||
844 | __kuser_memory_barrier: @ 0xffff0fa0 | 844 | __kuser_memory_barrier: @ 0xffff0fa0 |
845 | smp_dmb | 845 | smp_dmb arm |
846 | usr_ret lr | 846 | usr_ret lr |
847 | 847 | ||
848 | .align 5 | 848 | .align 5 |
@@ -959,7 +959,7 @@ kuser_cmpxchg_fixup: | |||
959 | 959 | ||
960 | #else | 960 | #else |
961 | 961 | ||
962 | smp_dmb | 962 | smp_dmb arm |
963 | 1: ldrex r3, [r2] | 963 | 1: ldrex r3, [r2] |
964 | subs r3, r3, r0 | 964 | subs r3, r3, r0 |
965 | strexeq r3, r1, [r2] | 965 | strexeq r3, r1, [r2] |
diff --git a/arch/arm/kernel/head.S b/arch/arm/kernel/head.S index fd94e4e82fc9..359e54e83bd5 100644 --- a/arch/arm/kernel/head.S +++ b/arch/arm/kernel/head.S | |||
@@ -412,10 +412,17 @@ __fixup_smp_on_up: | |||
412 | add r4, r4, r3 | 412 | add r4, r4, r3 |
413 | add r5, r5, r3 | 413 | add r5, r5, r3 |
414 | 2: cmp r4, r5 | 414 | 2: cmp r4, r5 |
415 | movhs pc, lr | ||
415 | ldmia r4!, {r0, r6} | 416 | ldmia r4!, {r0, r6} |
416 | strlo r6, [r0, r3] | 417 | ARM( str r6, [r0, r3] ) |
417 | blo 2b | 418 | THUMB( add r0, r0, r3 ) |
418 | mov pc, lr | 419 | #ifdef __ARMEB__ |
420 | THUMB( mov r6, r6, ror #16 ) @ Convert word order for big-endian. | ||
421 | #endif | ||
422 | THUMB( strh r6, [r0], #2 ) @ For Thumb-2, store as two halfwords | ||
423 | THUMB( mov r6, r6, lsr #16 ) @ to be robust against misaligned r3. | ||
424 | THUMB( strh r6, [r0] ) | ||
425 | b 2b | ||
419 | ENDPROC(__fixup_smp) | 426 | ENDPROC(__fixup_smp) |
420 | 427 | ||
421 | 1: .word . | 428 | 1: .word . |