diff options
Diffstat (limited to 'arch/arm/kernel/head.S')
-rw-r--r-- | arch/arm/kernel/head.S | 65 |
1 files changed, 55 insertions, 10 deletions
diff --git a/arch/arm/kernel/head.S b/arch/arm/kernel/head.S index 08c82fd844a8..14e277d2ff91 100644 --- a/arch/arm/kernel/head.S +++ b/arch/arm/kernel/head.S | |||
@@ -39,8 +39,14 @@ | |||
39 | #error KERNEL_RAM_VADDR must start at 0xXXXX8000 | 39 | #error KERNEL_RAM_VADDR must start at 0xXXXX8000 |
40 | #endif | 40 | #endif |
41 | 41 | ||
42 | #ifdef CONFIG_ARM_LPAE | ||
43 | /* LPAE requires an additional page for the PGD */ | ||
44 | #define PG_DIR_SIZE 0x5000 | ||
45 | #define PMD_ORDER 3 | ||
46 | #else | ||
42 | #define PG_DIR_SIZE 0x4000 | 47 | #define PG_DIR_SIZE 0x4000 |
43 | #define PMD_ORDER 2 | 48 | #define PMD_ORDER 2 |
49 | #endif | ||
44 | 50 | ||
45 | .globl swapper_pg_dir | 51 | .globl swapper_pg_dir |
46 | .equ swapper_pg_dir, KERNEL_RAM_VADDR - PG_DIR_SIZE | 52 | .equ swapper_pg_dir, KERNEL_RAM_VADDR - PG_DIR_SIZE |
@@ -164,17 +170,36 @@ __create_page_tables: | |||
164 | teq r0, r6 | 170 | teq r0, r6 |
165 | bne 1b | 171 | bne 1b |
166 | 172 | ||
173 | #ifdef CONFIG_ARM_LPAE | ||
174 | /* | ||
175 | * Build the PGD table (first level) to point to the PMD table. A PGD | ||
176 | * entry is 64-bit wide. | ||
177 | */ | ||
178 | mov r0, r4 | ||
179 | add r3, r4, #0x1000 @ first PMD table address | ||
180 | orr r3, r3, #3 @ PGD block type | ||
181 | mov r6, #4 @ PTRS_PER_PGD | ||
182 | mov r7, #1 << (55 - 32) @ L_PGD_SWAPPER | ||
183 | 1: str r3, [r0], #4 @ set bottom PGD entry bits | ||
184 | str r7, [r0], #4 @ set top PGD entry bits | ||
185 | add r3, r3, #0x1000 @ next PMD table | ||
186 | subs r6, r6, #1 | ||
187 | bne 1b | ||
188 | |||
189 | add r4, r4, #0x1000 @ point to the PMD tables | ||
190 | #endif | ||
191 | |||
167 | ldr r7, [r10, #PROCINFO_MM_MMUFLAGS] @ mm_mmuflags | 192 | ldr r7, [r10, #PROCINFO_MM_MMUFLAGS] @ mm_mmuflags |
168 | 193 | ||
169 | /* | 194 | /* |
170 | * Create identity mapping to cater for __enable_mmu. | 195 | * Create identity mapping to cater for __enable_mmu. |
171 | * This identity mapping will be removed by paging_init(). | 196 | * This identity mapping will be removed by paging_init(). |
172 | */ | 197 | */ |
173 | adr r0, __enable_mmu_loc | 198 | adr r0, __turn_mmu_on_loc |
174 | ldmia r0, {r3, r5, r6} | 199 | ldmia r0, {r3, r5, r6} |
175 | sub r0, r0, r3 @ virt->phys offset | 200 | sub r0, r0, r3 @ virt->phys offset |
176 | add r5, r5, r0 @ phys __enable_mmu | 201 | add r5, r5, r0 @ phys __turn_mmu_on |
177 | add r6, r6, r0 @ phys __enable_mmu_end | 202 | add r6, r6, r0 @ phys __turn_mmu_on_end |
178 | mov r5, r5, lsr #SECTION_SHIFT | 203 | mov r5, r5, lsr #SECTION_SHIFT |
179 | mov r6, r6, lsr #SECTION_SHIFT | 204 | mov r6, r6, lsr #SECTION_SHIFT |
180 | 205 | ||
@@ -219,8 +244,8 @@ __create_page_tables: | |||
219 | #endif | 244 | #endif |
220 | 245 | ||
221 | /* | 246 | /* |
222 | * Then map boot params address in r2 or | 247 | * Then map boot params address in r2 or the first 1MB (2MB with LPAE) |
223 | * the first 1MB of ram if boot params address is not specified. | 248 | * of ram if boot params address is not specified. |
224 | */ | 249 | */ |
225 | mov r0, r2, lsr #SECTION_SHIFT | 250 | mov r0, r2, lsr #SECTION_SHIFT |
226 | movs r0, r0, lsl #SECTION_SHIFT | 251 | movs r0, r0, lsl #SECTION_SHIFT |
@@ -251,7 +276,15 @@ __create_page_tables: | |||
251 | mov r3, r7, lsr #SECTION_SHIFT | 276 | mov r3, r7, lsr #SECTION_SHIFT |
252 | ldr r7, [r10, #PROCINFO_IO_MMUFLAGS] @ io_mmuflags | 277 | ldr r7, [r10, #PROCINFO_IO_MMUFLAGS] @ io_mmuflags |
253 | orr r3, r7, r3, lsl #SECTION_SHIFT | 278 | orr r3, r7, r3, lsl #SECTION_SHIFT |
279 | #ifdef CONFIG_ARM_LPAE | ||
280 | mov r7, #1 << (54 - 32) @ XN | ||
281 | #else | ||
282 | orr r3, r3, #PMD_SECT_XN | ||
283 | #endif | ||
254 | 1: str r3, [r0], #4 | 284 | 1: str r3, [r0], #4 |
285 | #ifdef CONFIG_ARM_LPAE | ||
286 | str r7, [r0], #4 | ||
287 | #endif | ||
255 | add r3, r3, #1 << SECTION_SHIFT | 288 | add r3, r3, #1 << SECTION_SHIFT |
256 | cmp r0, r6 | 289 | cmp r0, r6 |
257 | blo 1b | 290 | blo 1b |
@@ -283,14 +316,17 @@ __create_page_tables: | |||
283 | str r3, [r0] | 316 | str r3, [r0] |
284 | #endif | 317 | #endif |
285 | #endif | 318 | #endif |
319 | #ifdef CONFIG_ARM_LPAE | ||
320 | sub r4, r4, #0x1000 @ point to the PGD table | ||
321 | #endif | ||
286 | mov pc, lr | 322 | mov pc, lr |
287 | ENDPROC(__create_page_tables) | 323 | ENDPROC(__create_page_tables) |
288 | .ltorg | 324 | .ltorg |
289 | .align | 325 | .align |
290 | __enable_mmu_loc: | 326 | __turn_mmu_on_loc: |
291 | .long . | 327 | .long . |
292 | .long __enable_mmu | 328 | .long __turn_mmu_on |
293 | .long __enable_mmu_end | 329 | .long __turn_mmu_on_end |
294 | 330 | ||
295 | #if defined(CONFIG_SMP) | 331 | #if defined(CONFIG_SMP) |
296 | __CPUINIT | 332 | __CPUINIT |
@@ -374,12 +410,17 @@ __enable_mmu: | |||
374 | #ifdef CONFIG_CPU_ICACHE_DISABLE | 410 | #ifdef CONFIG_CPU_ICACHE_DISABLE |
375 | bic r0, r0, #CR_I | 411 | bic r0, r0, #CR_I |
376 | #endif | 412 | #endif |
413 | #ifdef CONFIG_ARM_LPAE | ||
414 | mov r5, #0 | ||
415 | mcrr p15, 0, r4, r5, c2 @ load TTBR0 | ||
416 | #else | ||
377 | mov r5, #(domain_val(DOMAIN_USER, DOMAIN_MANAGER) | \ | 417 | mov r5, #(domain_val(DOMAIN_USER, DOMAIN_MANAGER) | \ |
378 | domain_val(DOMAIN_KERNEL, DOMAIN_MANAGER) | \ | 418 | domain_val(DOMAIN_KERNEL, DOMAIN_MANAGER) | \ |
379 | domain_val(DOMAIN_TABLE, DOMAIN_MANAGER) | \ | 419 | domain_val(DOMAIN_TABLE, DOMAIN_MANAGER) | \ |
380 | domain_val(DOMAIN_IO, DOMAIN_CLIENT)) | 420 | domain_val(DOMAIN_IO, DOMAIN_CLIENT)) |
381 | mcr p15, 0, r5, c3, c0, 0 @ load domain access register | 421 | mcr p15, 0, r5, c3, c0, 0 @ load domain access register |
382 | mcr p15, 0, r4, c2, c0, 0 @ load page table pointer | 422 | mcr p15, 0, r4, c2, c0, 0 @ load page table pointer |
423 | #endif | ||
383 | b __turn_mmu_on | 424 | b __turn_mmu_on |
384 | ENDPROC(__enable_mmu) | 425 | ENDPROC(__enable_mmu) |
385 | 426 | ||
@@ -398,15 +439,19 @@ ENDPROC(__enable_mmu) | |||
398 | * other registers depend on the function called upon completion | 439 | * other registers depend on the function called upon completion |
399 | */ | 440 | */ |
400 | .align 5 | 441 | .align 5 |
401 | __turn_mmu_on: | 442 | .pushsection .idmap.text, "ax" |
443 | ENTRY(__turn_mmu_on) | ||
402 | mov r0, r0 | 444 | mov r0, r0 |
445 | instr_sync | ||
403 | mcr p15, 0, r0, c1, c0, 0 @ write control reg | 446 | mcr p15, 0, r0, c1, c0, 0 @ write control reg |
404 | mrc p15, 0, r3, c0, c0, 0 @ read id reg | 447 | mrc p15, 0, r3, c0, c0, 0 @ read id reg |
448 | instr_sync | ||
405 | mov r3, r3 | 449 | mov r3, r3 |
406 | mov r3, r13 | 450 | mov r3, r13 |
407 | mov pc, r3 | 451 | mov pc, r3 |
408 | __enable_mmu_end: | 452 | __turn_mmu_on_end: |
409 | ENDPROC(__turn_mmu_on) | 453 | ENDPROC(__turn_mmu_on) |
454 | .popsection | ||
410 | 455 | ||
411 | 456 | ||
412 | #ifdef CONFIG_SMP_ON_UP | 457 | #ifdef CONFIG_SMP_ON_UP |