[PATCH v2 08/20] ARM: LPAE: MMU setup for the 3-level page table format
Russell King - ARM Linux
linux at arm.linux.org.uk
Mon Nov 22 08:10:10 EST 2010
On Fri, Nov 12, 2010 at 06:00:28PM +0000, Catalin Marinas wrote:
> 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. The
> __v7_setup function configures the TTBRx split based on the PAGE_OFFSET
> and sets the corresponding TTB control and MAIRx bits (similar to
> PRRR/NMRR for TEX remapping). The 36-bit mappings (supersections) and
> a few other memory types in mmu.c are conditionally compiled.
>
> Signed-off-by: Catalin Marinas <catalin.marinas at arm.com>
> ---
> arch/arm/kernel/head.S | 96 +++++++++++++++++++++++++++++++------------
> arch/arm/mm/mmu.c | 32 ++++++++++++++-
> arch/arm/mm/proc-macros.S | 5 +-
> arch/arm/mm/proc-v7.S | 99 ++++++++++++++++++++++++++++++++++++++++----
> 4 files changed, 193 insertions(+), 39 deletions(-)
>
> diff --git a/arch/arm/kernel/head.S b/arch/arm/kernel/head.S
> index dd6b369..fd8a29e 100644
> --- a/arch/arm/kernel/head.S
> +++ b/arch/arm/kernel/head.S
> @@ -21,6 +21,7 @@
> #include <asm/memory.h>
> #include <asm/thread_info.h>
> #include <asm/system.h>
> +#include <asm/pgtable.h>
>
> #ifdef CONFIG_DEBUG_LL
> #include <mach/debug-macro.S>
> @@ -45,11 +46,20 @@
> #error KERNEL_RAM_VADDR must start at 0xXXXX8000
> #endif
>
> +#ifdef CONFIG_ARM_LPAE
> + /* LPAE requires an additional page for the PGD */
> +#define PG_DIR_SIZE 0x5000
> +#define PTE_WORDS 3
> +#else
> +#define PG_DIR_SIZE 0x4000
> +#define PTE_WORDS 2
PTE is not the right prefix here - we don't deal with the lowest level
of page tables, which in Linux is called PTE. I think you mean PMD_WORDS
instead.
> +#endif
> +
> .globl swapper_pg_dir
> - .equ swapper_pg_dir, KERNEL_RAM_VADDR - 0x4000
> + .equ swapper_pg_dir, KERNEL_RAM_VADDR - PG_DIR_SIZE
>
> .macro pgtbl, rd
> - ldr \rd, =(KERNEL_RAM_PADDR - 0x4000)
> + ldr \rd, =(KERNEL_RAM_PADDR - PG_DIR_SIZE)
> .endm
>
> #ifdef CONFIG_XIP_KERNEL
> @@ -129,11 +139,11 @@ __create_page_tables:
> pgtbl r4 @ page table address
>
> /*
> - * Clear the 16K level 1 swapper page table
> + * Clear the swapper page table
> */
> mov r0, r4
> mov r3, #0
> - add r6, r0, #0x4000
> + add r6, r0, #PG_DIR_SIZE
> 1: str r3, [r0], #4
> str r3, [r0], #4
> str r3, [r0], #4
> @@ -141,6 +151,23 @@ __create_page_tables:
> teq r0, r6
> bne 1b
>
> +#ifdef CONFIG_ARM_LPAE
> + /*
> + * Build the PGD table (first level) to point to the PMD table. A PGD
> + * entry is 64-bit wide and the top 32 bits are 0.
> + */
> + mov r0, r4
> + add r3, r4, #0x1000 @ first PMD table address
> + orr r3, r3, #3 @ PGD block type
> + mov r6, #4 @ PTRS_PER_PGD
> +1: str r3, [r0], #8 @ set PGD entry
> + add r3, r3, #0x1000 @ next PMD table
> + subs r6, r6, #1
> + bne 1b
> +
> + add r4, r4, #0x1000 @ point to the PMD tables
> +#endif
> +
> ldr r7, [r10, #PROCINFO_MM_MMUFLAGS] @ mm_mmuflags
>
> /*
> @@ -152,30 +179,30 @@ __create_page_tables:
> sub r0, r0, r3 @ virt->phys offset
> add r5, r5, r0 @ phys __enable_mmu
> add r6, r6, r0 @ phys __enable_mmu_end
> - mov r5, r5, lsr #20
> - mov r6, r6, lsr #20
> + mov r5, r5, lsr #SECTION_SHIFT
> + mov r6, r6, lsr #SECTION_SHIFT
>
> -1: orr r3, r7, r5, lsl #20 @ flags + kernel base
> - str r3, [r4, r5, lsl #2] @ identity mapping
> - teq r5, r6
> - addne r5, r5, #1 @ next section
> - bne 1b
> +1: orr r3, r7, r5, lsl #SECTION_SHIFT @ flags + kernel base
> + str r3, [r4, r5, lsl #PTE_WORDS] @ identity mapping
> + cmp r5, r6
> + addlo r5, r5, #SECTION_SHIFT >> 20 @ next section
> + blo 1b
>
> /*
> * Now setup the pagetables for our kernel direct
> * mapped region.
> */
> mov r3, pc
> - mov r3, r3, lsr #20
> - orr r3, r7, r3, lsl #20
> + mov r3, r3, lsr #SECTION_SHIFT
> + orr r3, r7, r3, lsl #SECTION_SHIFT
> add r0, r4, #(KERNEL_START & 0xff000000) >> 18
> - str r3, [r0, #(KERNEL_START & 0x00f00000) >> 18]!
> + str r3, [r0, #(KERNEL_START & 0x00e00000) >> 18]!
> ldr r6, =(KERNEL_END - 1)
> - add r0, r0, #4
> + add r0, r0, #1 << PTE_WORDS
> add r6, r4, r6, lsr #18
Are you sure these shifts by 18 places are correct? They're actually
(val >> SECTION_SHIFT) << 2, so maybe they should be (SECTION_SHIFT -
PMD_WORDS) ?
More information about the linux-arm-kernel
mailing list