aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/include
diff options
context:
space:
mode:
authorDave Martin <dave.martin@linaro.org>2010-12-01 09:39:23 -0500
committerRussell King <rmk+kernel@arm.linux.org.uk>2010-12-20 10:09:12 -0500
commited3768a8d9dc2d345d4f27eb44ee1e4825056c08 (patch)
tree7ca8b45e83fa1eac70b285898e41332b28fe1626 /arch/arm/include
parent86e62b93368cffca9111996e3ed9e5b7bf6f0af3 (diff)
ARM: 6516/1: Allow SMP_ON_UP to work with Thumb-2 kernels.
* __fixup_smp_on_up has been modified with support for the THUMB2_KERNEL case. For THUMB2_KERNEL only, fixups are split into halfwords in case of misalignment, since we can't rely on unaligned accesses working before turning the MMU on. No attempt is made to optimise the aligned case, since the number of fixups is typically small, and it seems best to keep the code as simple as possible. * Add a rotate in the fixup_smp code in order to support CPU_BIG_ENDIAN, as suggested by Nicolas Pitre. * Add an assembly-time sanity-check to ALT_UP() to ensure that the content really is the right size (4 bytes). (No check is done for ALT_SMP(). Possibly, this could be fixed by splitting the two uses ot ALT_SMP() (ALT_SMP...SMP_UP versus ALT_SMP...SMP_UP_B) into two macros. In the first case, ALT_SMP needs to expand to >= 4 bytes, not == 4.) * smp_mpidr.h (which implements ALT_SMP()/ALT_UP() manually due to macro limitations) has not been modified: the affected instruction (mov) has no 16-bit encoding, so the correct instruction size is satisfied in this case. * A "mode" parameter has been added to smp_dmb: smp_dmb arm @ assumes 4-byte instructions (for ARM code, e.g. kuser) smp_dmb @ uses W() to ensure 4-byte instructions for ALT_SMP() This avoids assembly failures due to use of W() inside smp_dmb, when assembling pure-ARM code in the vectors page. There might be a better way to achieve this. * Kconfig: make SMP_ON_UP depend on (!THUMB2_KERNEL || !BIG_ENDIAN) i.e., THUMB2_KERNEL is now supported, but only if !BIG_ENDIAN (The fixup code for Thumb-2 currently assumes little-endian order.) Tested using a single generic realview kernel on: ARM RealView PB-A8 (CONFIG_THUMB2_KERNEL={n,y}) ARM RealView PBX-A9 (SMP) Signed-off-by: Dave Martin <dave.martin@linaro.org> Acked-by: Nicolas Pitre <nicolas.pitre@linaro.org> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'arch/arm/include')
-rw-r--r--arch/arm/include/asm/assembler.h22
1 files changed, 19 insertions, 3 deletions
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...) \
1599998: instr 1599998: 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 ;\ 1689997: 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