Received: by 2002:a25:8b12:0:0:0:0:0 with SMTP id i18csp1790481ybl; Thu, 15 Aug 2019 01:02:47 -0700 (PDT) X-Google-Smtp-Source: APXvYqzDlffMn/03bQ8hjZV9M8YhHAeNgOeXdBqheajI5QRRfAWBVZY2u/p4ROdTnm9Lk5BrAb0u X-Received: by 2002:a62:1a45:: with SMTP id a66mr4305755pfa.142.1565856167067; Thu, 15 Aug 2019 01:02:47 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1565856167; cv=none; d=google.com; s=arc-20160816; b=TW8W1Npy7Xa821vnpa4L7oh/YzQNTBZLCQBXu+dDh6dPtdgnR6if7bZA9RvnNxtcUw Z+EXPNXoSf5MZuXeWFlmz4hyqBmxODD4COymbQ/PIqea3ea/cXWqwTSkasrqLIUKGxT8 5u4v5fQbk7b/TmTlJRlGiKBUZVA3yY+PBsozVGF8WzTi0ntjxYX2bMKHLLgezOWuN6PJ 0kyn2F6LSPmvv69hT440+k1T5KYRVlqcPywaTzt3GlfyDtEXN/ylruw4yfSNHlbv7+0N /kEZ8dyaCMH+q/H/BveSVdCUWKB26U0f4rrVTqjMv3YScqhlsmd49gUTrmWY6bHTOAAs 8aog== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:cc:to:subject:message-id:date:from :in-reply-to:references:mime-version:dkim-signature; bh=LV+82vFyg5z4e0teXoGTrMA+EjOg7t6iT9Oj6uw7yPM=; b=JVBbDoMxJgBAaOewgXtiahr2z8cR2Hv/nNgDyFlf9nKOPzZnZrTvCc0Tk+VQdX75Qe 5c69AEVqIst4im4we+y16lERaMrL57ffn8eIy+Z/CTWCocD8afU8gLtTXrAOh0bB88yJ MtfXbW+om2E6/FhEoJo+If+RAz5SGKaA6pLe9yezuasMk5boOu3HKf1TH0pi8tVQHazc XJmR6cFv75EbC4IEPO7Kqh6at+G+ve7HsZrtWr5owrTMPSy92f5J5y67oPJBUxsbm6Jn 490ALZcb5VUi+UAsE9uOA0PLQJCdHBC2uyQovoZJF02bnJbxl+5YI+gPAPBi2hDBrDsD HZ1A== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=tfiL+28t; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id v184si1379628pgd.278.2019.08.15.01.02.30; Thu, 15 Aug 2019 01:02:47 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=tfiL+28t; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1730787AbfHOH76 (ORCPT + 99 others); Thu, 15 Aug 2019 03:59:58 -0400 Received: from mail-wm1-f68.google.com ([209.85.128.68]:40271 "EHLO mail-wm1-f68.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1725961AbfHOH76 (ORCPT ); Thu, 15 Aug 2019 03:59:58 -0400 Received: by mail-wm1-f68.google.com with SMTP id v19so548265wmj.5 for ; Thu, 15 Aug 2019 00:59:55 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=mime-version:references:in-reply-to:from:date:message-id:subject:to :cc; bh=LV+82vFyg5z4e0teXoGTrMA+EjOg7t6iT9Oj6uw7yPM=; b=tfiL+28tRTegf7fQ7sw0mV4Q7P8lfpj9JtTYtDiukQnb9y9ne3Dulj9KdIlK22ZAse gDt8h/2J05cT9QkpVdi1ow/cuCaEj+8xchRXqxGgxFgjjcqlMgFEBst0g0ctnEKpr0Ir FZpmKJ67PEc+JUsTKgim6NKr8d5S5kAy50YXK6oZE6MhmU0c96bcvJ76Eg7mltpfW42l cavPZ9TxiOZfTdQ+noIZIlQkFFHkb6WyunatIqDRxlJYKhmIvBUOZ9QzY7F3fevEc/gO 9LgACL3Rc2585SCCBxkbC2Q+B0xoIYQF2YrDkVI6uUg/Wr5AISvnu8bfCB+4esQgHkmB dhQQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:references:in-reply-to:from:date :message-id:subject:to:cc; bh=LV+82vFyg5z4e0teXoGTrMA+EjOg7t6iT9Oj6uw7yPM=; b=sVXrXCdQyAkTbmwe76pE7satSA5l2KrxCnjX9N+LLggxWeEN/cHFniiwLkyzyQ6XB+ h/WvZMDkRcBUoIM/imYiJXRUAuIGSwr5qDerAFPzrlNSp7z0Kl4U9OJBQJ9II5oRMkGO u0CKEOksmzeGVVpUbBvHBhAC+HYPuXzbq9WmnLPbd8h8+m2G2mYgPt/F9hKWcIhKMEl+ iNF/u84EjgF1WWicDZwD1tX576Dnp5MbjGnOs3atuOlXrJNZ0ILuh76ooy46Y2FOqbYk Hvn3gMbCArd2uoIaOBVpO0iUaQlTr/XgD8CjUtdErV1xiFaFpkOXCvBxHQo7c4fRxt9g /rVA== X-Gm-Message-State: APjAAAVPlZqryBqxxcfATqBD1M8JhsRFUOjYcQGixx3T84q2Z3xmOZUG fZmqm4VGTRSbrjZNzyo9F7oe/Py/o1tYl5+7kmp/fw== X-Received: by 2002:a1c:4b15:: with SMTP id y21mr1429804wma.53.1565855995011; Thu, 15 Aug 2019 00:59:55 -0700 (PDT) MIME-Version: 1.0 References: <20190802053744.5519-1-clin@suse.com> In-Reply-To: From: Ard Biesheuvel Date: Thu, 15 Aug 2019 10:59:43 +0300 Message-ID: Subject: Re: [PATCH] efi/arm: fix allocation failure when reserving the kernel base To: Chester Lin , "linux@armlinux.org.uk" Cc: "akpm@linux-foundation.org" , "rppt@linux.ibm.com" , "ren_guo@c-sky.com" , Juergen Gross , "geert@linux-m68k.org" , "mingo@kernel.org" , "linux-arm-kernel@lists.infradead.org" , "linux-kernel@vger.kernel.org" , "linux-efi@vger.kernel.org" , "guillaume.gardet@arm.com" , Joey Lee , Gary Lin Content-Type: text/plain; charset="UTF-8" Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On Sun, 4 Aug 2019 at 10:57, Ard Biesheuvel wrote: > > Hello Chester, > > On Fri, 2 Aug 2019 at 08:40, Chester Lin wrote: > > > > 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. > > > > This by itself is a violation of the Linux boot protocol for 32-bit > ARM when using the decompressor. The decompressor rounds down its own > base address to a multiple of 128 MB, and assumes the whole area is > available for the decompressed kernel and related data structures. > (The first TEXT_OFFSET bytes are no longer used in practice, which is > why putting a reserved region of 4 KB bytes works at the moment, but > this is fragile). Note that the decompressor does not look at any DT > or EFI provided memory maps *at all*. > > So unfortunately, this is not something we can fix in the kernel, but > we should fix it in the bootloader or in GRUB, so it does not put any > reserved regions in the first 128 MB of memory, > OK, perhaps we can fix this by taking TEXT_OFFSET into account. The ARM boot protocol docs are unclear about whether this memory should be used or not, but it is no longer used for its original purpose (page tables), and the RPi loader already keeps data there. Can you check whether the following patch works for you? diff --git a/drivers/firmware/efi/libstub/Makefile b/drivers/firmware/efi/libstub/Makefile index 0460c7581220..ee0661ddb25b 100644 --- a/drivers/firmware/efi/libstub/Makefile +++ b/drivers/firmware/efi/libstub/Makefile @@ -52,6 +52,7 @@ lib-$(CONFIG_EFI_ARMSTUB) += arm-stub.o fdt.o string.o random.o \ lib-$(CONFIG_ARM) += arm32-stub.o lib-$(CONFIG_ARM64) += arm64-stub.o +CFLAGS_arm32-stub.o := -DTEXT_OFFSET=$(TEXT_OFFSET) CFLAGS_arm64-stub.o := -DTEXT_OFFSET=$(TEXT_OFFSET) # diff --git a/drivers/firmware/efi/libstub/arm32-stub.c b/drivers/firmware/efi/libstub/arm32-stub.c index e8f7aefb6813..66ff0c8ec269 100644 --- a/drivers/firmware/efi/libstub/arm32-stub.c +++ b/drivers/firmware/efi/libstub/arm32-stub.c @@ -204,7 +204,7 @@ efi_status_t handle_kernel_image(efi_system_table_t *sys_table, * loaded. These assumptions are made by the decompressor, * before any memory map is available. */ - dram_base = round_up(dram_base, SZ_128M); + dram_base = round_up(dram_base, SZ_128M) + TEXT_OFFSET; status = reserve_kernel_base(sys_table, dram_base, reserve_addr, reserve_size); > > > 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. > > This is a separate issue, so it should be handled in a separate patch. > > Signed-off-by: Chester Lin > > --- > > 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 > >