Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S932976AbcKMJFK (ORCPT ); Sun, 13 Nov 2016 04:05:10 -0500 Received: from terminus.zytor.com ([198.137.202.10]:58228 "EHLO terminus.zytor.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S932467AbcKMJFF (ORCPT ); Sun, 13 Nov 2016 04:05:05 -0500 Date: Sun, 13 Nov 2016 01:04:19 -0800 From: tip-bot for Roy Franz Message-ID: Cc: roy.franz@hpe.com, ard.biesheuvel@linaro.org, mingo@kernel.org, torvalds@linux-foundation.org, hpa@zytor.com, peterz@infradead.org, matt@codeblueprint.co.uk, linux-kernel@vger.kernel.org, tglx@linutronix.de Reply-To: mingo@kernel.org, torvalds@linux-foundation.org, peterz@infradead.org, hpa@zytor.com, matt@codeblueprint.co.uk, linux-kernel@vger.kernel.org, tglx@linutronix.de, roy.franz@hpe.com, ard.biesheuvel@linaro.org In-Reply-To: <20161112213237.8804-2-matt@codeblueprint.co.uk> References: <20161112213237.8804-2-matt@codeblueprint.co.uk> To: linux-tip-commits@vger.kernel.org Subject: [tip:efi/core] efi/libstub: Fix allocation size calculations Git-Commit-ID: 5b88a31c222c47cb8997021cc8a576927ba0e77f 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: 3936 Lines: 97 Commit-ID: 5b88a31c222c47cb8997021cc8a576927ba0e77f Gitweb: http://git.kernel.org/tip/5b88a31c222c47cb8997021cc8a576927ba0e77f Author: Roy Franz AuthorDate: Sat, 12 Nov 2016 21:32:29 +0000 Committer: Ingo Molnar CommitDate: Sun, 13 Nov 2016 08:23:14 +0100 efi/libstub: Fix allocation size calculations Adjust the size used in calculations to match the actual size of allocation that will be performed based on EFI size/alignment constraints. efi_high_alloc() and efi_low_alloc() use the passed size in bytes directly to find space in the memory map for the allocation, rather than the actual allocation size that has been adjusted for size and alignment constraints. This results in failed allocations and retries in efi_high_alloc(). The same error is present in efi_low_alloc(), although failure will only happen if the lowest memory block is small. Also use EFI_PAGE_SIZE consistently and remove use of EFI_PAGE_SHIFT to calculate page size. Signed-off-by: Roy Franz Signed-off-by: Ard Biesheuvel Signed-off-by: Matt Fleming Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: linux-efi@vger.kernel.org Link: http://lkml.kernel.org/r/20161112213237.8804-2-matt@codeblueprint.co.uk Signed-off-by: Ingo Molnar --- drivers/firmware/efi/libstub/efi-stub-helper.c | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/drivers/firmware/efi/libstub/efi-stub-helper.c b/drivers/firmware/efi/libstub/efi-stub-helper.c index aded106..4b74bf8 100644 --- a/drivers/firmware/efi/libstub/efi-stub-helper.c +++ b/drivers/firmware/efi/libstub/efi-stub-helper.c @@ -186,14 +186,16 @@ efi_status_t efi_high_alloc(efi_system_table_t *sys_table_arg, goto fail; /* - * Enforce minimum alignment that EFI requires when requesting - * a specific address. We are doing page-based allocations, - * so we must be aligned to a page. + * Enforce minimum alignment that EFI or Linux requires when + * requesting a specific address. We are doing page-based (or + * larger) allocations, and both the address and size must meet + * alignment constraints. */ if (align < EFI_ALLOC_ALIGN) align = EFI_ALLOC_ALIGN; - nr_pages = round_up(size, EFI_ALLOC_ALIGN) / EFI_PAGE_SIZE; + size = round_up(size, EFI_ALLOC_ALIGN); + nr_pages = size / EFI_PAGE_SIZE; again: for (i = 0; i < map_size / desc_size; i++) { efi_memory_desc_t *desc; @@ -208,7 +210,7 @@ again: continue; start = desc->phys_addr; - end = start + desc->num_pages * (1UL << EFI_PAGE_SHIFT); + end = start + desc->num_pages * EFI_PAGE_SIZE; if (end > max) end = max; @@ -278,14 +280,16 @@ efi_status_t efi_low_alloc(efi_system_table_t *sys_table_arg, goto fail; /* - * Enforce minimum alignment that EFI requires when requesting - * a specific address. We are doing page-based allocations, - * so we must be aligned to a page. + * Enforce minimum alignment that EFI or Linux requires when + * requesting a specific address. We are doing page-based (or + * larger) allocations, and both the address and size must meet + * alignment constraints. */ if (align < EFI_ALLOC_ALIGN) align = EFI_ALLOC_ALIGN; - nr_pages = round_up(size, EFI_ALLOC_ALIGN) / EFI_PAGE_SIZE; + size = round_up(size, EFI_ALLOC_ALIGN); + nr_pages = size / EFI_PAGE_SIZE; for (i = 0; i < map_size / desc_size; i++) { efi_memory_desc_t *desc; unsigned long m = (unsigned long)map; @@ -300,7 +304,7 @@ efi_status_t efi_low_alloc(efi_system_table_t *sys_table_arg, continue; start = desc->phys_addr; - end = start + desc->num_pages * (1UL << EFI_PAGE_SHIFT); + end = start + desc->num_pages * EFI_PAGE_SIZE; /* * Don't allocate at 0x0. It will confuse code that