From 0ceac9e094b065fe3fec19669740f338d3480498 Mon Sep 17 00:00:00 2001 From: Mark Salter Date: Mon, 8 Sep 2014 13:01:08 -0400 Subject: efi/arm64: Fix fdt-related memory reservation Commit 86c8b27a01cf: "arm64: ignore DT memreserve entries when booting in UEFI mode prevents early_init_fdt_scan_reserved_mem() from being called for arm64 kernels booting via UEFI. This was done because the kernel will use the UEFI memory map to determine reserved memory regions. That approach has problems in that early_init_fdt_scan_reserved_mem() also reserves the FDT itself and any node-specific reserved memory. By chance of some kernel configs, the FDT may be overwritten before it can be unflattened and the kernel will fail to boot. More subtle problems will result if the FDT has node specific reserved memory which is not really reserved. This patch has the UEFI stub remove the memory reserve map entries from the FDT as it does with the memory nodes. This allows early_init_fdt_scan_reserved_mem() to be called unconditionally so that the other needed reservations are made. Signed-off-by: Mark Salter Acked-by: Ard Biesheuvel Acked-by: Mark Rutland Signed-off-by: Matt Fleming --- arch/arm64/mm/init.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'arch/arm64') diff --git a/arch/arm64/mm/init.c b/arch/arm64/mm/init.c index 5472c2401876..a83061f37e43 100644 --- a/arch/arm64/mm/init.c +++ b/arch/arm64/mm/init.c @@ -149,8 +149,7 @@ void __init arm64_memblock_init(void) memblock_reserve(__virt_to_phys(initrd_start), initrd_end - initrd_start); #endif - if (!efi_enabled(EFI_MEMMAP)) - early_init_fdt_scan_reserved_mem(); + early_init_fdt_scan_reserved_mem(); /* 4GB maximum for 32-bit only capable devices */ if (IS_ENABLED(CONFIG_ZONE_DMA)) -- cgit v1.2.3-58-ga151 From 562c85cadb065e33ec9f651b8d41cdfd3054a5d0 Mon Sep 17 00:00:00 2001 From: Yalin Wang Date: Fri, 26 Sep 2014 03:30:59 +0100 Subject: ARM: 8168/1: extend __init_end to a page align address This patch changes the __init_end address to a page align address, so that free_initmem() can free the whole .init section, because if the end address is not page aligned, it will round down to a page align address, then the tail unligned page will not be freed. Signed-off-by: wang Acked-by: Catalin Marinas Signed-off-by: Russell King --- arch/arm/kernel/vmlinux.lds.S | 2 +- arch/arm64/kernel/vmlinux.lds.S | 2 +- include/asm-generic/vmlinux.lds.h | 2 ++ 3 files changed, 4 insertions(+), 2 deletions(-) (limited to 'arch/arm64') diff --git a/arch/arm/kernel/vmlinux.lds.S b/arch/arm/kernel/vmlinux.lds.S index 6f57cb94367f..8e95aa47457a 100644 --- a/arch/arm/kernel/vmlinux.lds.S +++ b/arch/arm/kernel/vmlinux.lds.S @@ -219,8 +219,8 @@ SECTIONS __data_loc = ALIGN(4); /* location in binary */ . = PAGE_OFFSET + TEXT_OFFSET; #else - __init_end = .; . = ALIGN(THREAD_SIZE); + __init_end = .; __data_loc = .; #endif diff --git a/arch/arm64/kernel/vmlinux.lds.S b/arch/arm64/kernel/vmlinux.lds.S index 97f0c0429dfa..edf8715ba39b 100644 --- a/arch/arm64/kernel/vmlinux.lds.S +++ b/arch/arm64/kernel/vmlinux.lds.S @@ -97,9 +97,9 @@ SECTIONS PERCPU_SECTION(64) + . = ALIGN(PAGE_SIZE); __init_end = .; - . = ALIGN(PAGE_SIZE); _data = .; _sdata = .; RW_DATA_SECTION(64, PAGE_SIZE, THREAD_SIZE) diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h index 5ba0360663a7..aa70cbda327c 100644 --- a/include/asm-generic/vmlinux.lds.h +++ b/include/asm-generic/vmlinux.lds.h @@ -40,6 +40,8 @@ * } * * [__init_begin, __init_end] is the init section that may be freed after init + * // __init_begin and __init_end should be page aligned, so that we can + * // free the whole .init memory * [_stext, _etext] is the text section * [_sdata, _edata] is the data section * -- cgit v1.2.3-58-ga151 From 421520ba98290a73b35b7644e877a48f18e06004 Mon Sep 17 00:00:00 2001 From: Yalin Wang Date: Fri, 26 Sep 2014 03:07:09 +0100 Subject: ARM: 8167/1: extend the reserved memory for initrd to be page aligned This patch extends the start and end address of initrd to be page aligned, so that we can free all memory including the un-page aligned head or tail page of initrd, if the start or end address of initrd are not page aligned, the page can't be freed by free_initrd_mem() function. Signed-off-by: Yalin Wang Acked-by: Catalin Marinas Signed-off-by: Russell King --- arch/arm/mm/init.c | 5 +++++ arch/arm64/mm/init.c | 8 +++++++- 2 files changed, 12 insertions(+), 1 deletion(-) (limited to 'arch/arm64') diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c index 659c75d808dc..9221645dd192 100644 --- a/arch/arm/mm/init.c +++ b/arch/arm/mm/init.c @@ -636,6 +636,11 @@ static int keep_initrd; void free_initrd_mem(unsigned long start, unsigned long end) { if (!keep_initrd) { + if (start == initrd_start) + start = round_down(start, PAGE_SIZE); + if (end == initrd_end) + end = round_up(end, PAGE_SIZE); + poison_init_mem((void *)start, PAGE_ALIGN(end) - start); free_reserved_area((void *)start, (void *)end, -1, "initrd"); } diff --git a/arch/arm64/mm/init.c b/arch/arm64/mm/init.c index 5472c2401876..c5512f694814 100644 --- a/arch/arm64/mm/init.c +++ b/arch/arm64/mm/init.c @@ -334,8 +334,14 @@ static int keep_initrd; void free_initrd_mem(unsigned long start, unsigned long end) { - if (!keep_initrd) + if (!keep_initrd) { + if (start == initrd_start) + start = round_down(start, PAGE_SIZE); + if (end == initrd_end) + end = round_up(end, PAGE_SIZE); + free_reserved_area((void *)start, (void *)end, 0, "initrd"); + } } static int __init keepinitrd_setup(char *__unused) -- cgit v1.2.3-58-ga151