From mboxrd@z Thu Jan 1 00:00:00 1970 From: lauraa@codeaurora.org (Laura Abbott) Date: Tue, 20 May 2014 09:21:59 -0700 Subject: [PATCH 2/4] arm64: place initial page tables above the kernel In-Reply-To: <1400233839-15140-3-git-send-email-mark.rutland@arm.com> References: <1400233839-15140-1-git-send-email-mark.rutland@arm.com> <1400233839-15140-3-git-send-email-mark.rutland@arm.com> Message-ID: <537B8127.8000902@codeaurora.org> To: linux-arm-kernel@lists.infradead.org List-Id: linux-arm-kernel.lists.infradead.org On 5/16/2014 2:50 AM, Mark Rutland wrote: > Currently we place swapper_pg_dir and idmap_pg_dir below the kernel > image, between PHYS_OFFSET and (PHYS_OFFSET + TEXT_OFFSET). However, > bootloaders may use portions of this memory below the kernel and we do > not parse the memory reservation list until after the MMU has been > enabled. As such we may clobber some memory a bootloader wishes to have > preserved. > > To enable the use of all of this memory by bootloaders (when the > required memory reservations are communicated to the kernel) it is > necessary to move our initial page tables elsewhere. As we currently > have an effectively unbound requirement for memory at the end of the > kernel image for .bss, we can place the page tables here. > > This patch moves the initial page table to the end of the kernel image, > after the BSS. As they do not consist of any initialised data they will > be stripped from the kernel Image as with the BSS. The BSS clearing > routine is updated to stop at __bss_stop rather than _end so as to not > clobber the page tables, and memory reservations made redundant by the > new organisation are removed. > > Signed-off-by: Mark Rutland > --- > arch/arm64/include/asm/page.h | 9 +++++++++ > arch/arm64/kernel/head.S | 28 ++++++++-------------------- > arch/arm64/kernel/vmlinux.lds.S | 7 +++++++ > arch/arm64/mm/init.c | 12 ++++-------- > 4 files changed, 28 insertions(+), 28 deletions(-) > > diff --git a/arch/arm64/include/asm/page.h b/arch/arm64/include/asm/page.h > index 46bf666..a6331e6 100644 > --- a/arch/arm64/include/asm/page.h > +++ b/arch/arm64/include/asm/page.h > @@ -31,6 +31,15 @@ > /* We do define AT_SYSINFO_EHDR but don't use the gate mechanism */ > #define __HAVE_ARCH_GATE_AREA 1 > > +/* > + * The idmap and swapper page tables need some space reserved in the kernel > + * image. The idmap only requires a pgd and a next level table to (section) map > + * the kernel, while the swapper also maps the FDT and requires an additional > + * table to map an early UART. See __create_page_tables for more information. > + */ > +#define SWAPPER_DIR_SIZE (3 * PAGE_SIZE) > +#define IDMAP_DIR_SIZE (2 * PAGE_SIZE) > + > #ifndef __ASSEMBLY__ > > #ifdef CONFIG_ARM64_64K_PAGES > diff --git a/arch/arm64/kernel/head.S b/arch/arm64/kernel/head.S > index e8e9883..5dd8127 100644 > --- a/arch/arm64/kernel/head.S > +++ b/arch/arm64/kernel/head.S > @@ -35,29 +35,17 @@ > #include > #include > > -/* > - * swapper_pg_dir is the virtual address of the initial page table. We place > - * the page tables 3 * PAGE_SIZE below KERNEL_RAM_VADDR. The idmap_pg_dir has > - * 2 pages and is placed below swapper_pg_dir. > - */ > #define KERNEL_RAM_VADDR (PAGE_OFFSET + TEXT_OFFSET) > > #if (KERNEL_RAM_VADDR & 0xfffff) != 0x80000 > #error KERNEL_RAM_VADDR must start at 0xXXX80000 > #endif > > -#define SWAPPER_DIR_SIZE (3 * PAGE_SIZE) > -#define IDMAP_DIR_SIZE (2 * PAGE_SIZE) > - > - .globl swapper_pg_dir > - .equ swapper_pg_dir, KERNEL_RAM_VADDR - SWAPPER_DIR_SIZE > - > - .globl idmap_pg_dir > - .equ idmap_pg_dir, swapper_pg_dir - IDMAP_DIR_SIZE > - > - .macro pgtbl, ttb0, ttb1, phys > - add \ttb1, \phys, #TEXT_OFFSET - SWAPPER_DIR_SIZE > - sub \ttb0, \ttb1, #IDMAP_DIR_SIZE > + .macro pgtbl, ttb0, ttb1, virt_to_phys > + ldr \ttb1, =swapper_pg_dir > + ldr \ttb0, =idmap_pg_dir > + add \ttb1, \ttb1, \virt_to_phys > + add \ttb0, \ttb0, \virt_to_phys > .endm > > #ifdef CONFIG_ARM64_64K_PAGES > @@ -304,7 +292,7 @@ ENTRY(secondary_startup) > mov x23, x0 // x23=current cpu_table > cbz x23, __error_p // invalid processor (x23=0)? > > - pgtbl x25, x26, x24 // x25=TTBR0, x26=TTBR1 > + pgtbl x25, x26, x28 // x25=TTBR0, x26=TTBR1 > ldr x12, [x23, #CPU_INFO_SETUP] > add x12, x12, x28 // __virt_to_phys > blr x12 // initialise processor > @@ -418,7 +406,7 @@ ENDPROC(__calc_phys_offset) > * - pgd entry for fixed mappings (TTBR1) > */ > __create_page_tables: > - pgtbl x25, x26, x24 // idmap_pg_dir and swapper_pg_dir addresses > + pgtbl x25, x26, x28 // idmap_pg_dir and swapper_pg_dir addresses > mov x27, lr > > /* > @@ -507,7 +495,7 @@ ENDPROC(__create_page_tables) > __switch_data: > .quad __mmap_switched > .quad __bss_start // x6 > - .quad _end // x7 > + .quad __bss_stop // x7 > .quad processor_id // x4 > .quad __fdt_pointer // x5 > .quad memstart_addr // x6 > diff --git a/arch/arm64/kernel/vmlinux.lds.S b/arch/arm64/kernel/vmlinux.lds.S > index 4ba7a55..51258bc 100644 > --- a/arch/arm64/kernel/vmlinux.lds.S > +++ b/arch/arm64/kernel/vmlinux.lds.S > @@ -104,6 +104,13 @@ SECTIONS > _edata = .; > > BSS_SECTION(0, 0, 0) > + > + . = ALIGN(PAGE_SIZE); > + idmap_pg_dir = .; > + . += IDMAP_DIR_SIZE; > + swapper_pg_dir = .; > + . += SWAPPER_DIR_SIZE; > + > _end = .; > > STABS_DEBUG > diff --git a/arch/arm64/mm/init.c b/arch/arm64/mm/init.c > index 51d5352..cc3339d 100644 > --- a/arch/arm64/mm/init.c > +++ b/arch/arm64/mm/init.c > @@ -128,20 +128,16 @@ void __init arm64_memblock_init(void) > { > u64 *reserve_map, base, size; > > - /* Register the kernel text, kernel data and initrd with memblock */ > + /* > + * Register the kernel text, kernel data, initrd, and initial > + * pagetables with memblock. > + */ > memblock_reserve(__pa(_text), _end - _text); > #ifdef CONFIG_BLK_DEV_INITRD > if (initrd_start) > memblock_reserve(__virt_to_phys(initrd_start), initrd_end - initrd_start); > #endif > > - /* > - * Reserve the page tables. These are already in use, > - * and can only be in node 0. > - */ > - memblock_reserve(__pa(swapper_pg_dir), SWAPPER_DIR_SIZE); > - memblock_reserve(__pa(idmap_pg_dir), IDMAP_DIR_SIZE); > - > /* Reserve the dtb region */ > memblock_reserve(virt_to_phys(initial_boot_params), > be32_to_cpu(initial_boot_params->totalsize)); > Tested-by: Laura Abbott Both 4K and 64K pages -- Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation