diff options
author | Russell King <rmk+kernel@arm.linux.org.uk> | 2010-10-04 12:51:54 -0400 |
---|---|---|
committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2010-10-08 05:07:34 -0400 |
commit | 786f1b73f7d5cad5c88dc75a96d53a74160aa7d7 (patch) | |
tree | 1a8004c1a1b74060f283d6b042fe3c1c495f22a8 /arch/arm/kernel/head.S | |
parent | 80924ac595f3ca32ec0a80cc1217c7019d3519ff (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.S | 33 |
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: | ||
204 | ENDPROC(__turn_mmu_on) | 205 | ENDPROC(__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 | |||
251 | 1: 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 |
334 | ENDPROC(__create_page_tables) | 345 | ENDPROC(__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" |