From: Chester Lin <clin@suse.com>
To: "linux@armlinux.org.uk" <linux@armlinux.org.uk>,
"ard.biesheuvel@linaro.org" <ard.biesheuvel@linaro.org>,
"akpm@linux-foundation.org" <akpm@linux-foundation.org>,
"rppt@linux.ibm.com" <rppt@linux.ibm.com>,
"ren_guo@c-sky.com" <ren_guo@c-sky.com>,
Juergen Gross <JGross@suse.com>,
"geert@linux-m68k.org" <geert@linux-m68k.org>,
"mingo@kernel.org" <mingo@kernel.org>
Cc: Joey Lee <JLee@suse.com>,
"linux-efi@vger.kernel.org" <linux-efi@vger.kernel.org>,
"guillaume.gardet@arm.com" <guillaume.gardet@arm.com>,
"linux-kernel@vger.kernel.org" <linux-kernel@vger.kernel.org>,
Chester Lin <clin@suse.com>, Gary Lin <GLin@suse.com>,
"linux-arm-kernel@lists.infradead.org"
<linux-arm-kernel@lists.infradead.org>
Subject: [PATCH] efi/arm: fix allocation failure when reserving the kernel base
Date: Fri, 2 Aug 2019 05:38:54 +0000 [thread overview]
Message-ID: <20190802053744.5519-1-clin@suse.com> (raw)
In some cases the arm32 efistub could fail to allocate memory for
uncompressed kernel. For example, we got the following error message when
verifying EFI stub on Raspberry Pi-2 [kernel-5.2.1 + grub-2.04] :
EFI stub: Booting Linux Kernel...
EFI stub: ERROR: Unable to allocate memory for uncompressed kernel.
EFI stub: ERROR: Failed to relocate kernel
After checking the EFI memory map we found that the first page [0 - 0xfff]
had been reserved by Raspberry Pi-2's firmware, and the efistub tried to
set the dram base at 0, which was actually in a reserved region.
grub> lsefimmap
Type Physical start - end #Pages Size Attributes
reserved 0000000000000000-0000000000000fff 00000001 4KiB WB
conv-mem 0000000000001000-0000000007ef5fff 00007ef5 130004KiB WB
RT-data 0000000007ef6000-0000000007f09fff 00000014 80KiB RT WB
conv-mem 0000000007f0a000-000000002d871fff 00025968 615840KiB WB
.....
To avoid a reserved address, we have to ignore the memory regions which are
marked as EFI_RESERVED_TYPE, and only conventional memory regions can be
chosen. If the region before the kernel base is unaligned, it will be
marked as EFI_RESERVED_TYPE and let kernel ignore it so that memblock_limit
will not be sticked with a very low address such as 0x1000.
Signed-off-by: Chester Lin <clin@suse.com>
---
arch/arm/mm/mmu.c | 3 ++
drivers/firmware/efi/libstub/arm32-stub.c | 43 ++++++++++++++++++-----
2 files changed, 37 insertions(+), 9 deletions(-)
diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c
index f3ce34113f89..909b11ba48d8 100644
--- a/arch/arm/mm/mmu.c
+++ b/arch/arm/mm/mmu.c
@@ -1184,6 +1184,9 @@ void __init adjust_lowmem_bounds(void)
phys_addr_t block_start = reg->base;
phys_addr_t block_end = reg->base + reg->size;
+ if (memblock_is_nomap(reg))
+ continue;
+
if (reg->base < vmalloc_limit) {
if (block_end > lowmem_limit)
/*
diff --git a/drivers/firmware/efi/libstub/arm32-stub.c b/drivers/firmware/efi/libstub/arm32-stub.c
index e8f7aefb6813..10d33d36df00 100644
--- a/drivers/firmware/efi/libstub/arm32-stub.c
+++ b/drivers/firmware/efi/libstub/arm32-stub.c
@@ -128,7 +128,7 @@ static efi_status_t reserve_kernel_base(efi_system_table_t *sys_table_arg,
for (l = 0; l < map_size; l += desc_size) {
efi_memory_desc_t *desc;
- u64 start, end;
+ u64 start, end, spare, kernel_base;
desc = (void *)memory_map + l;
start = desc->phys_addr;
@@ -144,27 +144,52 @@ static efi_status_t reserve_kernel_base(efi_system_table_t *sys_table_arg,
case EFI_BOOT_SERVICES_DATA:
/* Ignore types that are released to the OS anyway */
continue;
-
+ case EFI_RESERVED_TYPE:
+ /* Ignore reserved regions */
+ continue;
case EFI_CONVENTIONAL_MEMORY:
/*
* Reserve the intersection between this entry and the
* region.
*/
start = max(start, (u64)dram_base);
- end = min(end, (u64)dram_base + MAX_UNCOMP_KERNEL_SIZE);
+ kernel_base = round_up(start, PMD_SIZE);
+ spare = kernel_base - start;
+ end = min(end, kernel_base + MAX_UNCOMP_KERNEL_SIZE);
+
+ status = efi_call_early(allocate_pages,
+ EFI_ALLOCATE_ADDRESS,
+ EFI_LOADER_DATA,
+ MAX_UNCOMP_KERNEL_SIZE / EFI_PAGE_SIZE,
+ &kernel_base);
+ if (status != EFI_SUCCESS) {
+ pr_efi_err(sys_table_arg,
+ "reserve_kernel_base: alloc failed.\n");
+ goto out;
+ }
+ *reserve_addr = kernel_base;
+ if (!spare)
+ break;
+ /*
+ * If there's a gap between start and kernel_base,
+ * it needs be reserved so that the memblock_limit
+ * will not fall on a very low address when running
+ * adjust_lowmem_bounds(), wchich could eventually
+ * cause CMA reservation issue.
+ */
status = efi_call_early(allocate_pages,
EFI_ALLOCATE_ADDRESS,
- EFI_LOADER_DATA,
- (end - start) / EFI_PAGE_SIZE,
+ EFI_RESERVED_TYPE,
+ spare / EFI_PAGE_SIZE,
&start);
if (status != EFI_SUCCESS) {
pr_efi_err(sys_table_arg,
- "reserve_kernel_base(): alloc failed.\n");
+ "reserve spare-region failed\n");
goto out;
}
- break;
+ break;
case EFI_LOADER_CODE:
case EFI_LOADER_DATA:
/*
@@ -220,7 +245,7 @@ efi_status_t handle_kernel_image(efi_system_table_t *sys_table,
*image_size = image->image_size;
status = efi_relocate_kernel(sys_table, image_addr, *image_size,
*image_size,
- dram_base + MAX_UNCOMP_KERNEL_SIZE, 0);
+ *reserve_addr + MAX_UNCOMP_KERNEL_SIZE, 0);
if (status != EFI_SUCCESS) {
pr_efi_err(sys_table, "Failed to relocate kernel.\n");
efi_free(sys_table, *reserve_size, *reserve_addr);
@@ -233,7 +258,7 @@ efi_status_t handle_kernel_image(efi_system_table_t *sys_table,
* in memory. The kernel determines the base of DRAM from the
* address at which the zImage is loaded.
*/
- if (*image_addr + *image_size > dram_base + ZIMAGE_OFFSET_LIMIT) {
+ if (*image_addr + *image_size > *reserve_addr + ZIMAGE_OFFSET_LIMIT) {
pr_efi_err(sys_table, "Failed to relocate kernel, no low memory available.\n");
efi_free(sys_table, *reserve_size, *reserve_addr);
*reserve_size = 0;
--
2.22.0
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
next reply other threads:[~2019-08-02 5:40 UTC|newest]
Thread overview: 24+ messages / expand[flat|nested] mbox.gz Atom feed top
2019-08-02 5:38 Chester Lin [this message]
2019-08-04 7:57 ` [PATCH] efi/arm: fix allocation failure when reserving the kernel base Ard Biesheuvel
2019-08-14 7:58 ` Guillaume Gardet
2019-08-15 7:59 ` Ard Biesheuvel
2019-08-15 11:16 ` Chester Lin
2019-08-15 11:32 ` Ard Biesheuvel
2019-08-15 13:37 ` Mike Rapoport
2019-08-19 7:56 ` Chester Lin
2019-08-19 14:56 ` Ard Biesheuvel
2019-08-20 7:33 ` Chester Lin
2019-08-20 7:49 ` Mike Rapoport
2019-08-20 10:29 ` Chester Lin
2019-08-20 11:00 ` Ard Biesheuvel
2019-08-20 11:54 ` Russell King - ARM Linux admin
2019-08-20 12:27 ` Ard Biesheuvel
2019-08-20 11:56 ` Russell King - ARM Linux admin
2019-08-20 12:28 ` Ard Biesheuvel
2019-08-21 6:10 ` Chester Lin
2019-08-21 6:35 ` Ard Biesheuvel
2019-08-21 7:11 ` Mike Rapoport
2019-08-21 7:22 ` Chester Lin
2019-08-21 7:29 ` Ard Biesheuvel
2019-08-21 8:29 ` Mike Rapoport
2019-08-21 9:42 ` Ard Biesheuvel
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20190802053744.5519-1-clin@suse.com \
--to=clin@suse.com \
--cc=GLin@suse.com \
--cc=JGross@suse.com \
--cc=JLee@suse.com \
--cc=akpm@linux-foundation.org \
--cc=ard.biesheuvel@linaro.org \
--cc=geert@linux-m68k.org \
--cc=guillaume.gardet@arm.com \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-efi@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux@armlinux.org.uk \
--cc=mingo@kernel.org \
--cc=ren_guo@c-sky.com \
--cc=rppt@linux.ibm.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).