From patchwork Mon Jul 14 18:40:48 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mark Salter X-Patchwork-Id: 33625 Return-Path: X-Original-To: linaro@patches.linaro.org Delivered-To: linaro@patches.linaro.org Received: from mail-pd0-f197.google.com (mail-pd0-f197.google.com [209.85.192.197]) by ip-10-151-82-157.ec2.internal (Postfix) with ESMTPS id 8F7712061E for ; Mon, 14 Jul 2014 18:42:48 +0000 (UTC) Received: by mail-pd0-f197.google.com with SMTP id y10sf5502241pdj.8 for ; Mon, 14 Jul 2014 11:42:47 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:delivered-to:message-id:subject:from:to:date :in-reply-to:references:organization:mime-version:cc:precedence :list-id:list-unsubscribe:list-archive:list-post:list-help :list-subscribe:sender:errors-to:x-original-sender :x-original-authentication-results:mailing-list:content-type :content-transfer-encoding; bh=9oDS8xaBPA7UtCSm7ICC1CtrMM/yxNsDlL5/Clb6P84=; b=GwQ7oYsU47yxEO7+I6q4zi4eYD2QktYFiyZZbkcpqJsDVzGqZXjv6X9Mn2YR0nFqX2 eoJ7EuGyT1YbZEjInMemLDyZ/j6kutX9s+jQylt6BgihZBOvhgozI7qq/B58BSX2oT+k neGgIvvS8cru5nQmPVXIhmYVZg1OHV/lmyOpZpAjP07+93hGTCliPBV9ZPc8PRdaVN5X vDzo3vja1GaYr1fnwp+6PyxwL2mH0R3DoHj2kHb/KxcvJ2ro3CwpOnGnplhWwxUgfqcU JsKopk8MO7OgEcPkGe4fcJSibb635qi/kMxLQjhdLBWnrvd91lBrQpKb/Z+CrTpIb3dV Vd8Q== X-Gm-Message-State: ALoCoQkQ1RBaudbOy7urGX2qwLahMzakZwVY5Qx7nKaIoUCpxRqIub2pp+LAWEVrBB+tJJbmiDle X-Received: by 10.66.122.101 with SMTP id lr5mr8511526pab.19.1405363367582; Mon, 14 Jul 2014 11:42:47 -0700 (PDT) X-BeenThere: patchwork-forward@linaro.org Received: by 10.140.40.70 with SMTP id w64ls1127454qgw.73.gmail; Mon, 14 Jul 2014 11:42:47 -0700 (PDT) X-Received: by 10.52.27.208 with SMTP id v16mr14810213vdg.21.1405363367402; Mon, 14 Jul 2014 11:42:47 -0700 (PDT) Received: from mail-vc0-f178.google.com (mail-vc0-f178.google.com [209.85.220.178]) by mx.google.com with ESMTPS id bk6si5694747vcb.55.2014.07.14.11.42.47 for (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Mon, 14 Jul 2014 11:42:47 -0700 (PDT) Received-SPF: pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 209.85.220.178 as permitted sender) client-ip=209.85.220.178; Received: by mail-vc0-f178.google.com with SMTP id la4so1352187vcb.23 for ; Mon, 14 Jul 2014 11:42:47 -0700 (PDT) X-Received: by 10.58.65.40 with SMTP id u8mr1617435ves.53.1405363367302; Mon, 14 Jul 2014 11:42:47 -0700 (PDT) X-Forwarded-To: patchwork-forward@linaro.org X-Forwarded-For: patch@linaro.org patchwork-forward@linaro.org Delivered-To: patch@linaro.org Received: by 10.221.37.5 with SMTP id tc5csp156545vcb; Mon, 14 Jul 2014 11:42:46 -0700 (PDT) X-Received: by 10.68.229.68 with SMTP id so4mr9482716pbc.110.1405363366426; Mon, 14 Jul 2014 11:42:46 -0700 (PDT) Received: from bombadil.infradead.org (bombadil.infradead.org. [2001:1868:205::9]) by mx.google.com with ESMTPS id to3si9796645pbc.40.2014.07.14.11.42.45 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 14 Jul 2014 11:42:46 -0700 (PDT) Received-SPF: none (google.com: linux-arm-kernel-bounces+patch=linaro.org@lists.infradead.org does not designate permitted sender hosts) client-ip=2001:1868:205::9; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1X6lBo-0008Ka-P0; Mon, 14 Jul 2014 18:41:28 +0000 Received: from mx1.redhat.com ([209.132.183.28]) by bombadil.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1X6lBm-0008FI-JG for linux-arm-kernel@lists.infradead.org; Mon, 14 Jul 2014 18:41:27 +0000 Received: from int-mx14.intmail.prod.int.phx2.redhat.com (int-mx14.intmail.prod.int.phx2.redhat.com [10.5.11.27]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id s6EIeoH2029472 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Mon, 14 Jul 2014 14:40:50 -0400 Received: from [10.3.113.32] (ovpn-113-32.phx2.redhat.com [10.3.113.32]) by int-mx14.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id s6EIen29025157; Mon, 14 Jul 2014 14:40:49 -0400 Message-ID: <1405363248.25580.12.camel@deneb.redhat.com> Subject: Re: [PATCH] efi/arm64: efistub: don't abort if base of DRAM is occupied From: Mark Salter To: Ard Biesheuvel Date: Mon, 14 Jul 2014 14:40:48 -0400 In-Reply-To: <1405351521-12010-1-git-send-email-ard.biesheuvel@linaro.org> References: <1405351521-12010-1-git-send-email-ard.biesheuvel@linaro.org> Organization: Red Hat, Inc Mime-Version: 1.0 X-Scanned-By: MIMEDefang 2.68 on 10.5.11.27 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20140714_114126_683264_2E017B0E X-CRM114-Status: GOOD ( 34.84 ) X-Spam-Score: -5.0 (-----) X-Spam-Report: SpamAssassin version 3.4.0 on bombadil.infradead.org summary: Content analysis details: (-5.0 points) pts rule name description ---- ---------------------- -------------------------------------------------- -5.0 RCVD_IN_DNSWL_HI RBL: Sender listed at http://www.dnswl.org/, high trust [209.132.183.28 listed in list.dnswl.org] -0.0 SPF_HELO_PASS SPF: HELO matches SPF record -0.0 RP_MATCHES_RCVD Envelope sender domain matches handover relay domain -0.0 SPF_PASS SPF: sender matches SPF record Cc: linux-efi@vger.kernel.org, catalin.marinas@arm.com, leif.lindholm@linaro.org, roy.franz@linaro.org, matt.fleming@intel.com, linux-arm-kernel@lists.infradead.org X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.18-1 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: , List-Help: , List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patch=linaro.org@lists.infradead.org X-Removed-Original-Auth: Dkim didn't pass. X-Original-Sender: msalter@redhat.com X-Original-Authentication-Results: mx.google.com; spf=pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 209.85.220.178 as permitted sender) smtp.mail=patch+caf_=patchwork-forward=linaro.org@linaro.org Mailing-list: list patchwork-forward@linaro.org; contact patchwork-forward+owners@linaro.org X-Google-Group-Id: 836684582541 On Mon, 2014-07-14 at 17:25 +0200, Ard Biesheuvel wrote: > If we fail to relocate the kernel Image to its preferred offset of TEXT_OFFSET > bytes above the base of DRAM, accept the lowest alternative mapping available > instead of aborting. We may lose a bit of memory at the low end, but we can > still proceed normally otherwise. This breaks APM Mustang because the spin-table holding pen for secondary CPUs is marked as reserved memory in the TEXT_OFFSET area and the kernel placement using your patch makes it unreachable by kernel. Here is a patch I've been working with to solve the same problem: From: Mark Salter Date: Thu, 10 Jul 2014 09:25:30 -0400 Subject: [PATCH] arm64/efi: try to handle firmware located below kernel The rule for arm64 kernel image placement is that it must be located TEXT_OFFSET bytes past a 2MiB boundary. The kernel itself will use the TEXT_OFFSET sized area for initial page tables but that area is not part of the kernel image itself. The current EFI stub code finds the base of DRAM from the EFI memmap and relocates the kernel to dram_base+TEXT_OFFSET. This assumes that the low memory is not being used and the kernel relocation simply fails if the base memory allocation fails. At least one vendor has firmware which occupies memory near dram_base so kernel relocations always fail. This patch attempts to work with such firmware by searching the EFI memmap for the lowest available memory which may be used for the kernel image. There are several pitfalls remaining which may lead to boot failure: * The stub does not allocate the TEXT_OFFSET region, so it is required that the firmware not be using that area for anything which may interfere or overlap with the initial kernel page tables. We can't simply include that area in our search for available memory because firmware using the spin-table method for booting secondary CPUs may place the CPU pen in an out of the way part of that region and mark it as reserved memory. * The current code requires FDT to be placed within first 512MiB of DRAM (with the kernel below it). This requirement can be removed in the future, but would involve changes to generic stub code shared by other architectures. Signed-off-by: Mark Salter --- arch/arm64/kernel/efi-stub.c | 45 +++++++++++++++++++++++++++++++++++++------- arch/arm64/kernel/efi.c | 19 ++++++++++++++++--- 2 files changed, 54 insertions(+), 10 deletions(-) diff --git a/arch/arm64/kernel/efi-stub.c b/arch/arm64/kernel/efi-stub.c index 60e98a63..f5da27f 100644 --- a/arch/arm64/kernel/efi-stub.c +++ b/arch/arm64/kernel/efi-stub.c @@ -54,21 +54,53 @@ static efi_status_t handle_kernel_image(efi_system_table_t *sys_table, efi_loaded_image_t *image) { efi_status_t status; - unsigned long kernel_size, kernel_memsize = 0; + unsigned long kernel_size, kernel_memsize; + unsigned long desired_base = dram_base + TEXT_OFFSET; + unsigned long desired_end; + unsigned long map_size; + struct efi_memory_map map; + efi_memory_desc_t *md; /* Relocate the image, if required. */ kernel_size = _edata - _text; - if (*image_addr != (dram_base + TEXT_OFFSET)) { - kernel_memsize = kernel_size + (_end - _edata); + kernel_memsize = kernel_size + (_end - _edata); + + desired_end = desired_base + kernel_size; + + /* find lowest available address for kernel to live */ + status = efi_get_memory_map(sys_table, (efi_memory_desc_t **)&map.map, + &map_size, &map.desc_size, NULL, NULL); + if (status == EFI_SUCCESS) { + map.map_end = map.map + map_size; + for_each_efi_memory_desc(&map, md) { + unsigned long start, end, offset; + if (!(md->attribute & EFI_MEMORY_WB)) + continue; + if (md->type != EFI_CONVENTIONAL_MEMORY) + continue; + start = md->phys_addr; + end = start + (md->num_pages << EFI_PAGE_SHIFT); + offset = start & (SZ_2M - 1); + if (offset < TEXT_OFFSET) + start += (TEXT_OFFSET - offset); + else if (offset > TEXT_OFFSET) + start = ALIGN(start, SZ_2M) + TEXT_OFFSET; + if (start < end && (start + kernel_memsize) <= end) { + desired_base = start; + break; + } + } + } + + if (*image_addr != desired_base) { status = efi_relocate_kernel(sys_table, image_addr, kernel_size, kernel_memsize, - dram_base + TEXT_OFFSET, - PAGE_SIZE); + desired_base, PAGE_SIZE); if (status != EFI_SUCCESS) { pr_efi_err(sys_table, "Failed to relocate kernel\n"); return status; } - if (*image_addr != (dram_base + TEXT_OFFSET)) { + if (*image_addr != desired_base) { pr_efi_err(sys_table, "Failed to alloc kernel memory\n"); efi_free(sys_table, kernel_memsize, *image_addr); return EFI_ERROR; @@ -76,6 +108,5 @@ static efi_status_t handle_kernel_image(efi_system_table_t *sys_table, *image_size = kernel_memsize; } - return EFI_SUCCESS; } diff --git a/arch/arm64/kernel/efi.c b/arch/arm64/kernel/efi.c index 453b7f8..2bc6469 100644 --- a/arch/arm64/kernel/efi.c +++ b/arch/arm64/kernel/efi.c @@ -180,9 +180,18 @@ static __init void reserve_regions(void) if (is_reserve_region(md) || md->type == EFI_BOOT_SERVICES_CODE || md->type == EFI_BOOT_SERVICES_DATA) { - memblock_reserve(paddr, size); - if (uefi_debug) - pr_cont("*"); + if (paddr < PHYS_OFFSET) { + if ((paddr + size) > PHYS_OFFSET) { + size -= (PHYS_OFFSET - paddr); + memblock_reserve(PHYS_OFFSET, size); + if (uefi_debug) + pr_cont("**"); + } + } else { + memblock_reserve(paddr, size); + if (uefi_debug) + pr_cont("*"); + } } if (uefi_debug) @@ -273,6 +282,10 @@ static void __init free_boot_services(void) continue; } + /* Don't free anything below kernel */ + if (md->phys_addr < PHYS_OFFSET) + continue; + /* * We want to free memory from this region. */