diff options
author | Catalin Marinas <catalin.marinas@arm.com> | 2011-11-22 12:30:29 -0500 |
---|---|---|
committer | Catalin Marinas <catalin.marinas@arm.com> | 2011-12-08 05:30:39 -0500 |
commit | 1b6ba46b7efa31055eb993a6f2c6bbcb8b35b001 (patch) | |
tree | b04e3b1fd23ba81a643f64cba113551d127111a0 /arch/arm/kernel | |
parent | da02877987e6e173ebba137d4e1e155e1f1151cd (diff) |
ARM: LPAE: MMU setup for the 3-level page table format
This patch adds the MMU initialisation for the LPAE page table format.
The swapper_pg_dir size with LPAE is 5 rather than 4 pages. A new
proc-v7-3level.S file contains the TTB initialisation, context switch
and PTE setting code with the LPAE. The TTBRx split is based on the
PAGE_OFFSET with TTBR1 used for the kernel mappings. The 36-bit mappings
(supersections) and a few other memory types in mmu.c are conditionally
compiled.
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
Diffstat (limited to 'arch/arm/kernel')
-rw-r--r-- | arch/arm/kernel/head.S | 45 |
1 files changed, 43 insertions, 2 deletions
diff --git a/arch/arm/kernel/head.S b/arch/arm/kernel/head.S index 54eb94aff6cd..c8e797baaf55 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,6 +170,25 @@ __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 | /* |
@@ -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,6 +316,9 @@ __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 |
@@ -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 | ||