Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S933564AbdDEKix (ORCPT ); Wed, 5 Apr 2017 06:38:53 -0400 Received: from terminus.zytor.com ([65.50.211.136]:42243 "EHLO terminus.zytor.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S933386AbdDEKi0 (ORCPT ); Wed, 5 Apr 2017 06:38:26 -0400 Date: Wed, 5 Apr 2017 03:33:47 -0700 From: tip-bot for Ard Biesheuvel Message-ID: Cc: tglx@linutronix.de, linux-kernel@vger.kernel.org, ard.biesheuvel@linaro.org, peterz@infradead.org, rruigrok@codeaurora.org, jhugo@codeaurora.org, torvalds@linux-foundation.org, hpa@zytor.com, mingo@kernel.org, matt@codeblueprint.co.uk Reply-To: jhugo@codeaurora.org, torvalds@linux-foundation.org, rruigrok@codeaurora.org, peterz@infradead.org, ard.biesheuvel@linaro.org, linux-kernel@vger.kernel.org, tglx@linutronix.de, matt@codeblueprint.co.uk, hpa@zytor.com, mingo@kernel.org In-Reply-To: <20170404160245.27812-4-ard.biesheuvel@linaro.org> References: <20170404160245.27812-4-ard.biesheuvel@linaro.org> To: linux-tip-commits@vger.kernel.org Subject: [tip:efi/core] efi/arm-stub: Correct FDT and initrd allocation rules for arm64 Git-Commit-ID: 138728dd4ee30d3f35587c269c46cc829ec4d58b X-Mailer: tip-git-log-daemon Robot-ID: Robot-Unsubscribe: Contact to get blacklisted from these emails MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Content-Type: text/plain; charset=UTF-8 Content-Disposition: inline Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 5276 Lines: 124 Commit-ID: 138728dd4ee30d3f35587c269c46cc829ec4d58b Gitweb: http://git.kernel.org/tip/138728dd4ee30d3f35587c269c46cc829ec4d58b Author: Ard Biesheuvel AuthorDate: Tue, 4 Apr 2017 17:02:37 +0100 Committer: Ingo Molnar CommitDate: Wed, 5 Apr 2017 12:27:23 +0200 efi/arm-stub: Correct FDT and initrd allocation rules for arm64 On arm64, we have made some changes over the past year to the way the kernel itself is allocated and to how it deals with the initrd and FDT. This patch brings the allocation logic in the EFI stub in line with that, which is necessary because the introduction of KASLR has created the possibility for the initrd to be allocated in a place where the kernel may not be able to map it. (This is mostly a theoretical scenario, since it only affects systems where the physical memory footprint exceeds the size of the linear mapping.) Since we know the kernel itself will be covered by the linear mapping, choose a suitably sized window (i.e., based on the size of the linear region) covering the kernel when allocating memory for the initrd. The FDT may be anywhere in memory on arm64 now that we map it via the fixmap, so we can lift the address restriction there completely. Tested-by: Richard Ruigrok Signed-off-by: Ard Biesheuvel Reviewed-by: Jeffrey Hugo Cc: Linus Torvalds Cc: Matt Fleming Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: linux-efi@vger.kernel.org Link: http://lkml.kernel.org/r/20170404160245.27812-4-ard.biesheuvel@linaro.org Signed-off-by: Ingo Molnar --- arch/arm/include/asm/efi.h | 14 +++++++++++++- arch/arm64/include/asm/efi.h | 23 ++++++++++++++++++++++- drivers/firmware/efi/libstub/arm-stub.c | 7 ++++--- 3 files changed, 39 insertions(+), 5 deletions(-) diff --git a/arch/arm/include/asm/efi.h b/arch/arm/include/asm/efi.h index e4e6a9d6..17f1f1a 100644 --- a/arch/arm/include/asm/efi.h +++ b/arch/arm/include/asm/efi.h @@ -85,6 +85,18 @@ static inline void efifb_setup_from_dmi(struct screen_info *si, const char *opt) */ #define ZIMAGE_OFFSET_LIMIT SZ_128M #define MIN_ZIMAGE_OFFSET MAX_UNCOMP_KERNEL_SIZE -#define MAX_FDT_OFFSET ZIMAGE_OFFSET_LIMIT + +/* on ARM, the FDT should be located in the first 128 MB of RAM */ +static inline unsigned long efi_get_max_fdt_addr(unsigned long dram_base) +{ + return dram_base + ZIMAGE_OFFSET_LIMIT; +} + +/* on ARM, the initrd should be loaded in a lowmem region */ +static inline unsigned long efi_get_max_initrd_addr(unsigned long dram_base, + unsigned long image_addr) +{ + return dram_base + SZ_512M; +} #endif /* _ASM_ARM_EFI_H */ diff --git a/arch/arm64/include/asm/efi.h b/arch/arm64/include/asm/efi.h index e744528..083a52d3 100644 --- a/arch/arm64/include/asm/efi.h +++ b/arch/arm64/include/asm/efi.h @@ -46,7 +46,28 @@ int efi_set_mapping_permissions(struct mm_struct *mm, efi_memory_desc_t *md); * 2MiB so we know it won't cross a 2MiB boundary. */ #define EFI_FDT_ALIGN SZ_2M /* used by allocate_new_fdt_and_exit_boot() */ -#define MAX_FDT_OFFSET SZ_512M + +/* on arm64, the FDT may be located anywhere in system RAM */ +static inline unsigned long efi_get_max_fdt_addr(unsigned long dram_base) +{ + return ULONG_MAX; +} + +/* + * On arm64, we have to ensure that the initrd ends up in the linear region, + * which is a 1 GB aligned region of size '1UL << (VA_BITS - 1)' that is + * guaranteed to cover the kernel Image. + * + * Since the EFI stub is part of the kernel Image, we can relax the + * usual requirements in Documentation/arm64/booting.txt, which still + * apply to other bootloaders, and are required for some kernel + * configurations. + */ +static inline unsigned long efi_get_max_initrd_addr(unsigned long dram_base, + unsigned long image_addr) +{ + return (image_addr & ~(SZ_1G - 1UL)) + (1UL << (VA_BITS - 1)); +} #define efi_call_early(f, ...) sys_table_arg->boottime->f(__VA_ARGS__) #define __efi_call_early(f, ...) f(__VA_ARGS__) diff --git a/drivers/firmware/efi/libstub/arm-stub.c b/drivers/firmware/efi/libstub/arm-stub.c index d4056c6..02049ff 100644 --- a/drivers/firmware/efi/libstub/arm-stub.c +++ b/drivers/firmware/efi/libstub/arm-stub.c @@ -213,8 +213,9 @@ unsigned long efi_entry(void *handle, efi_system_table_t *sys_table, if (!fdt_addr) pr_efi(sys_table, "Generating empty DTB\n"); - status = handle_cmdline_files(sys_table, image, cmdline_ptr, - "initrd=", dram_base + SZ_512M, + status = handle_cmdline_files(sys_table, image, cmdline_ptr, "initrd=", + efi_get_max_initrd_addr(dram_base, + *image_addr), (unsigned long *)&initrd_addr, (unsigned long *)&initrd_size); if (status != EFI_SUCCESS) @@ -224,7 +225,7 @@ unsigned long efi_entry(void *handle, efi_system_table_t *sys_table, new_fdt_addr = fdt_addr; status = allocate_new_fdt_and_exit_boot(sys_table, handle, - &new_fdt_addr, dram_base + MAX_FDT_OFFSET, + &new_fdt_addr, efi_get_max_fdt_addr(dram_base), initrd_addr, initrd_size, cmdline_ptr, fdt_addr, fdt_size);