aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/kernel/head.S
diff options
context:
space:
mode:
authorRussell King <rmk+kernel@arm.linux.org.uk>2010-10-04 12:51:54 -0400
committerRussell King <rmk+kernel@arm.linux.org.uk>2010-10-08 05:07:34 -0400
commit786f1b73f7d5cad5c88dc75a96d53a74160aa7d7 (patch)
tree1a8004c1a1b74060f283d6b042fe3c1c495f22a8 /arch/arm/kernel/head.S
parent80924ac595f3ca32ec0a80cc1217c7019d3519ff (diff)
ARM: hotplug cpu: ensure that __enable_mmu is identity mapped
__enable_mmu is required to be executed in an identity mapped region to ensure that variances in CPUs do not cause a crash. We currently achieve this by assuming that it will be co-located with __create_page_tables. With hotplug CPU support, this assumption becomes invalid. Implement a better solution which ensures that it will be appropriately mapped no matter where it is placed. Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'arch/arm/kernel/head.S')
-rw-r--r--arch/arm/kernel/head.S33
1 files changed, 24 insertions, 9 deletions
diff --git a/arch/arm/kernel/head.S b/arch/arm/kernel/head.S
index aa6ab9d86461..17414e299482 100644
--- a/arch/arm/kernel/head.S
+++ b/arch/arm/kernel/head.S
@@ -201,6 +201,7 @@ __turn_mmu_on:
201 mov r3, r3 201 mov r3, r3
202 mov r3, r13 202 mov r3, r13
203 mov pc, r3 203 mov pc, r3
204__enable_mmu_end:
204ENDPROC(__turn_mmu_on) 205ENDPROC(__turn_mmu_on)
205 206
206 207
@@ -214,7 +215,7 @@ ENDPROC(__turn_mmu_on)
214 * r10 = procinfo 215 * r10 = procinfo
215 * 216 *
216 * Returns: 217 * Returns:
217 * r0, r3, r6, r7 corrupted 218 * r0, r3, r5-r7 corrupted
218 * r4 = physical page table address 219 * r4 = physical page table address
219 */ 220 */
220__create_page_tables: 221__create_page_tables:
@@ -236,20 +237,30 @@ __create_page_tables:
236 ldr r7, [r10, #PROCINFO_MM_MMUFLAGS] @ mm_mmuflags 237 ldr r7, [r10, #PROCINFO_MM_MMUFLAGS] @ mm_mmuflags
237 238
238 /* 239 /*
239 * Create identity mapping for first MB of kernel to 240 * Create identity mapping to cater for __enable_mmu.
240 * cater for the MMU enable. This identity mapping 241 * This identity mapping will be removed by paging_init().
241 * will be removed by paging_init(). We use our current program
242 * counter to determine corresponding section base address.
243 */ 242 */
244 mov r6, pc 243 adr r0, __enable_mmu_loc
245 mov r6, r6, lsr #20 @ start of kernel section 244 ldmia r0, {r3, r5, r6}
246 orr r3, r7, r6, lsl #20 @ flags + kernel base 245 sub r0, r0, r3 @ virt->phys offset
247 str r3, [r4, r6, lsl #2] @ identity mapping 246 add r5, r5, r0 @ phys __enable_mmu
247 add r6, r6, r0 @ phys __enable_mmu_end
248 mov r5, r5, lsr #20
249 mov r6, r6, lsr #20
250
2511: orr r3, r7, r5, lsl #20 @ flags + kernel base
252 str r3, [r4, r5, lsl #2] @ identity mapping
253 teq r5, r6
254 addne r5, r5, #1 @ next section
255 bne 1b
248 256
249 /* 257 /*
250 * Now setup the pagetables for our kernel direct 258 * Now setup the pagetables for our kernel direct
251 * mapped region. 259 * mapped region.
252 */ 260 */
261 mov r3, pc
262 mov r3, r3, lsr #20
263 orr r3, r7, r3, lsl #20
253 add r0, r4, #(KERNEL_START & 0xff000000) >> 18 264 add r0, r4, #(KERNEL_START & 0xff000000) >> 18
254 str r3, [r0, #(KERNEL_START & 0x00f00000) >> 18]! 265 str r3, [r0, #(KERNEL_START & 0x00f00000) >> 18]!
255 ldr r6, =(KERNEL_END - 1) 266 ldr r6, =(KERNEL_END - 1)
@@ -333,5 +344,9 @@ __create_page_tables:
333 mov pc, lr 344 mov pc, lr
334ENDPROC(__create_page_tables) 345ENDPROC(__create_page_tables)
335 .ltorg 346 .ltorg
347__enable_mmu_loc:
348 .long .
349 .long __enable_mmu
350 .long __enable_mmu_end
336 351
337#include "head-common.S" 352#include "head-common.S"