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 |
