From patchwork Thu Feb 9 21:42:52 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ard Biesheuvel X-Patchwork-Id: 93782 Delivered-To: patch@linaro.org Received: by 10.140.20.99 with SMTP id 90csp221002qgi; Thu, 9 Feb 2017 14:07:41 -0800 (PST) X-Received: by 10.99.143.90 with SMTP id r26mr6627705pgn.128.1486678061314; Thu, 09 Feb 2017 14:07:41 -0800 (PST) Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id m63si11262745pfc.123.2017.02.09.14.07.41; Thu, 09 Feb 2017 14:07:41 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-efi-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=neutral (body hash did not verify) header.i=@linaro.org; spf=pass (google.com: best guess record for domain of linux-efi-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-efi-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752296AbdBIWHk (ORCPT + 2 others); Thu, 9 Feb 2017 17:07:40 -0500 Received: from mail-wr0-f182.google.com ([209.85.128.182]:36308 "EHLO mail-wr0-f182.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751111AbdBIWHj (ORCPT ); Thu, 9 Feb 2017 17:07:39 -0500 Received: by mail-wr0-f182.google.com with SMTP id k90so93751937wrc.3 for ; Thu, 09 Feb 2017 14:07:39 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id; bh=32mQw3cfpTtQclsa5t4DZRTai4+P01Tx4MzRtHOtWAQ=; b=Dpb3/o/7glQjsEPxuT6+a/dbHWRx1/APHkrjVrERfn8w3FAOBL5DpQk6ek3l8/KKbv MVdjEu9qSVn2a8CBh0IgoiTniWwUBLJBiIK0KrsccA5mqGtNItIxlF0B8jbPRlHFpdmn qoF9h98VZk1/xvvIl+MeZtrs/EHbg4c4cmpdc= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id; bh=32mQw3cfpTtQclsa5t4DZRTai4+P01Tx4MzRtHOtWAQ=; b=Jr1Pwjl78nC4zXmPY3AvPyy+H+UEkDAljxqYAj9Uc5UKOVsM0UgT9Fnjs2eelyOgV6 Md5Ro0OsRuXwkTyLJ6qtTWCwmtSCicZ1eXEeCyPbih0vS5Gi2rXnbhplIFr8+DyAaIew vIaJnX69jqSo6X9p4rMy4tDECJ5FCAtU5OpIsgrHk0DQMt4QWs2trsDpIqUi1t/TeUty aD7p15mjQx80aOyKP2iftfUU1RQsBBo3XVFcdQeBqmDLlKAOhW/z3lTbOKis6zF2tLc+ BdCT+d3D7VwMVamCN/4HpOfif6dhuRsHfsgp4uZ8UCe9EDrbNr3OrN7IY+Pf8pd6z8z2 S49g== X-Gm-Message-State: AMke39k/QST8UsjNH836y3I1LkNNpVgdGsx+QIurS6Ul7U8AcnWmfiQfmtjOhiTIzo0Pq4Xs X-Received: by 10.223.133.226 with SMTP id 31mr4477147wru.137.1486676590855; Thu, 09 Feb 2017 13:43:10 -0800 (PST) Received: from localhost.localdomain ([160.169.163.122]) by smtp.gmail.com with ESMTPSA id x25sm20493047wrx.27.2017.02.09.13.43.07 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Thu, 09 Feb 2017 13:43:10 -0800 (PST) From: Ard Biesheuvel To: linux-efi@vger.kernel.org, linux-arm-kernel@lists.infradead.org, matt@codeblueprint.co.uk, mark.rutland@arm.com Cc: timur@codeaurora.org, jhugo@codeaurora.org, leif.lindholm@linaro.org, catalin.marinas@arm.com, Ard Biesheuvel Subject: [PATCH v2 1/2] efi: arm-stub: Correct FDT and initrd allocation rules for arm64 Date: Thu, 9 Feb 2017 21:42:52 +0000 Message-Id: <1486676573-19237-1-git-send-email-ard.biesheuvel@linaro.org> X-Mailer: git-send-email 2.7.4 Sender: linux-efi-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-efi@vger.kernel.org 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. Signed-off-by: Ard Biesheuvel --- arch/arm/include/asm/efi.h | 14 +++++++++++++- arch/arm64/include/asm/efi.h | 18 +++++++++++++++++- drivers/firmware/efi/libstub/arm-stub.c | 7 ++++--- 3 files changed, 34 insertions(+), 5 deletions(-) -- 2.7.4 -- To unsubscribe from this list: send the line "unsubscribe linux-efi" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Reviewed-By: Jeffrey Hugo diff --git a/arch/arm/include/asm/efi.h b/arch/arm/include/asm/efi.h index 0b06f5341b45..2de0195dfd1e 100644 --- a/arch/arm/include/asm/efi.h +++ b/arch/arm/include/asm/efi.h @@ -84,6 +84,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 0b6b1633017f..342e90d6d204 100644 --- a/arch/arm64/include/asm/efi.h +++ b/arch/arm64/include/asm/efi.h @@ -46,7 +46,23 @@ 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. + */ +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 b4f7d78f9e8b..557281fe375f 100644 --- a/drivers/firmware/efi/libstub/arm-stub.c +++ b/drivers/firmware/efi/libstub/arm-stub.c @@ -333,8 +333,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) @@ -344,7 +345,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); From patchwork Thu Feb 9 21:42:53 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ard Biesheuvel X-Patchwork-Id: 93781 Delivered-To: patch@linaro.org Received: by 10.182.3.34 with SMTP id 2csp233914obz; Thu, 9 Feb 2017 13:51:45 -0800 (PST) X-Received: by 10.98.218.9 with SMTP id c9mr6033729pfh.99.1486677105325; Thu, 09 Feb 2017 13:51:45 -0800 (PST) Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id e9si11213729plj.315.2017.02.09.13.51.45; Thu, 09 Feb 2017 13:51:45 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-efi-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=neutral (body hash did not verify) header.i=@linaro.org; spf=pass (google.com: best guess record for domain of linux-efi-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-efi-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S932749AbdBIVvg (ORCPT + 2 others); Thu, 9 Feb 2017 16:51:36 -0500 Received: from mail-wm0-f42.google.com ([74.125.82.42]:37383 "EHLO mail-wm0-f42.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S932748AbdBIVvf (ORCPT ); Thu, 9 Feb 2017 16:51:35 -0500 Received: by mail-wm0-f42.google.com with SMTP id v77so32361996wmv.0 for ; Thu, 09 Feb 2017 13:51:34 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=mYuKBTc5IhVHeYxSIyXukNBt5xxhiI9lZb3Q6o9h4wc=; b=JYaUHQ6iLUV/KvoJ044qttb+YzPO95k0FfBBCf0ccCj76vqPdFYoWjgT6V6SRRNS09 o1IdB2ylAoZW29kplXGvRbkblpwStlLT37PTZHbVQFTfgjPbivaQCKbXaICloq75vvYA zGSNn4LwWo1HB/mMrxfLiir4GrFMbSyEzxKsE= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=mYuKBTc5IhVHeYxSIyXukNBt5xxhiI9lZb3Q6o9h4wc=; b=MjbVXhHuZAFOlMVdGiRsjOxHM3KWlcXvsPDpKBXVWIrfUGnDXffG+/gT+B579Ral81 xcgEDe4Hxy/Pso3zsaR0qqEdkhPOrRQUwsrAvgfkVPzh+RW9r61m0CyorpUmEx1AJx2E 1wPjJZgWOP0+zYtm5VDHFOzPANyYzXKZ+j0CcHzC/JV6GXKaoiFFSVY9F6hd7aBJFCXK 60owYCeK0fyVPg9RZfhKEvmd37Wc3MJM31Q+7Hnn6TWfyM53gK1D6fa+SWe22m3TUe2Y uIupJkKlOsYididZetyV5/nRieEK8GVPXbloRXv9e0tocvR2eZDHptBpuScD381dMG7N pwEQ== X-Gm-Message-State: AMke39k0eNz3qfExRzsz0DqMuHmJeoSsYTnsG7j+zF/Oyl6c7MBxvvfFABtPqUNbngutrgmu X-Received: by 10.28.186.197 with SMTP id k188mr24541825wmf.25.1486676593227; Thu, 09 Feb 2017 13:43:13 -0800 (PST) Received: from localhost.localdomain ([160.169.163.122]) by smtp.gmail.com with ESMTPSA id x25sm20493047wrx.27.2017.02.09.13.43.10 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Thu, 09 Feb 2017 13:43:12 -0800 (PST) From: Ard Biesheuvel To: linux-efi@vger.kernel.org, linux-arm-kernel@lists.infradead.org, matt@codeblueprint.co.uk, mark.rutland@arm.com Cc: timur@codeaurora.org, jhugo@codeaurora.org, leif.lindholm@linaro.org, catalin.marinas@arm.com, Ard Biesheuvel Subject: [PATCH v2 2/2] efi: arm-stub: Round up FDT allocation to mapping size Date: Thu, 9 Feb 2017 21:42:53 +0000 Message-Id: <1486676573-19237-2-git-send-email-ard.biesheuvel@linaro.org> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1486676573-19237-1-git-send-email-ard.biesheuvel@linaro.org> References: <1486676573-19237-1-git-send-email-ard.biesheuvel@linaro.org> Sender: linux-efi-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-efi@vger.kernel.org The FDT is mapped via a fixmap entry that is at least 2 MB in size and 2 MB aligned on 4 KB page size kernels. On UEFI systems, the FDT allocation may share this 2 MB block with a reserved region, or another memory region that we should never map, unless we account for this in the size of the allocation (the alignment is already 2 MB) So instead of taking guesses at the needed space, simply allocate 2 MB immediately. The allocation will be recorded as a EFI_LOADER_DATA, and the kernel only memblock_reserve()'s the actual size of the FDT, so the unused space will be released to the kernel. Signed-off-by: Ard Biesheuvel --- arch/arm64/include/asm/efi.h | 1 + drivers/firmware/efi/libstub/fdt.c | 57 +++++++++----------- 2 files changed, 25 insertions(+), 33 deletions(-) -- 2.7.4 -- To unsubscribe from this list: send the line "unsubscribe linux-efi" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Reviewed-By: Jeffrey Hugo diff --git a/arch/arm64/include/asm/efi.h b/arch/arm64/include/asm/efi.h index 342e90d6d204..f642565fc1d0 100644 --- a/arch/arm64/include/asm/efi.h +++ b/arch/arm64/include/asm/efi.h @@ -1,6 +1,7 @@ #ifndef _ASM_EFI_H #define _ASM_EFI_H +#include #include #include #include diff --git a/drivers/firmware/efi/libstub/fdt.c b/drivers/firmware/efi/libstub/fdt.c index 260c4b4b492e..41f457be64e8 100644 --- a/drivers/firmware/efi/libstub/fdt.c +++ b/drivers/firmware/efi/libstub/fdt.c @@ -206,6 +206,10 @@ static efi_status_t exit_boot_func(efi_system_table_t *sys_table_arg, return update_fdt_memmap(p->new_fdt_addr, map); } +#ifndef MAX_FDT_SIZE +#define MAX_FDT_SIZE SZ_2M +#endif + /* * Allocate memory for a new FDT, then add EFI, commandline, and * initrd related fields to the FDT. This routine increases the @@ -233,7 +237,6 @@ efi_status_t allocate_new_fdt_and_exit_boot(efi_system_table_t *sys_table, u32 desc_ver; unsigned long mmap_key; efi_memory_desc_t *memory_map, *runtime_map; - unsigned long new_fdt_size; efi_status_t status; int runtime_entry_count = 0; struct efi_boot_memmap map; @@ -262,41 +265,29 @@ efi_status_t allocate_new_fdt_and_exit_boot(efi_system_table_t *sys_table, "Exiting boot services and installing virtual address map...\n"); map.map = &memory_map; + status = efi_high_alloc(sys_table, MAX_FDT_SIZE, EFI_FDT_ALIGN, + new_fdt_addr, max_addr); + if (status != EFI_SUCCESS) { + pr_efi_err(sys_table, + "Unable to allocate memory for new device tree.\n"); + goto fail; + } + /* - * Estimate size of new FDT, and allocate memory for it. We - * will allocate a bigger buffer if this ends up being too - * small, so a rough guess is OK here. + * Now that we have done our final memory allocation (and free) + * we can get the memory map key needed for exit_boot_services(). */ - new_fdt_size = fdt_size + EFI_PAGE_SIZE; - while (1) { - status = efi_high_alloc(sys_table, new_fdt_size, EFI_FDT_ALIGN, - new_fdt_addr, max_addr); - if (status != EFI_SUCCESS) { - pr_efi_err(sys_table, "Unable to allocate memory for new device tree.\n"); - goto fail; - } - - status = update_fdt(sys_table, - (void *)fdt_addr, fdt_size, - (void *)*new_fdt_addr, new_fdt_size, - cmdline_ptr, initrd_addr, initrd_size); + status = efi_get_memory_map(sys_table, &map); + if (status != EFI_SUCCESS) + goto fail_free_new_fdt; - /* Succeeding the first time is the expected case. */ - if (status == EFI_SUCCESS) - break; + status = update_fdt(sys_table, (void *)fdt_addr, fdt_size, + (void *)*new_fdt_addr, MAX_FDT_SIZE, cmdline_ptr, + initrd_addr, initrd_size); - if (status == EFI_BUFFER_TOO_SMALL) { - /* - * We need to allocate more space for the new - * device tree, so free existing buffer that is - * too small. - */ - efi_free(sys_table, new_fdt_size, *new_fdt_addr); - new_fdt_size += EFI_PAGE_SIZE; - } else { - pr_efi_err(sys_table, "Unable to construct new device tree.\n"); - goto fail_free_new_fdt; - } + if (status != EFI_SUCCESS) { + pr_efi_err(sys_table, "Unable to construct new device tree.\n"); + goto fail_free_new_fdt; } priv.runtime_map = runtime_map; @@ -340,7 +331,7 @@ efi_status_t allocate_new_fdt_and_exit_boot(efi_system_table_t *sys_table, pr_efi_err(sys_table, "Exit boot services failed.\n"); fail_free_new_fdt: - efi_free(sys_table, new_fdt_size, *new_fdt_addr); + efi_free(sys_table, MAX_FDT_SIZE, *new_fdt_addr); fail: sys_table->boottime->free_pool(runtime_map);