From patchwork Tue Jul 15 16:50:30 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ard Biesheuvel X-Patchwork-Id: 33674 Return-Path: X-Original-To: linaro@patches.linaro.org Delivered-To: linaro@patches.linaro.org Received: from mail-qc0-f200.google.com (mail-qc0-f200.google.com [209.85.216.200]) by ip-10-151-82-157.ec2.internal (Postfix) with ESMTPS id 323BA201F1 for ; Tue, 15 Jul 2014 16:52:44 +0000 (UTC) Received: by mail-qc0-f200.google.com with SMTP id m20sf8979652qcx.3 for ; Tue, 15 Jul 2014 09:52:44 -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:from:to:subject:date:message-id:cc :precedence:list-id:list-unsubscribe:list-archive:list-post :list-help:list-subscribe:mime-version:sender:errors-to :x-original-sender:x-original-authentication-results:mailing-list :content-type:content-transfer-encoding; bh=6zB6M1lR2lnmJ0dy+lynSAOhUib6zr8TUYHDVi0t51E=; b=ghssKGOX00FfP2HUNlfZdQmfoXJ95K22ZPY76dAi/hR7UA9a0qLIirk0CU1/XOl1SS 9JYKH6T6i+KIcNRb081aNctK6A9b/InQWwKOejQPfH+tOjRk+ozr7qgRSMIzS+qZTZwp bO9Qw8qI/QAT4BrtEQqC5FocAz261ZGF78SCpSioFEkcR3vWtwyAT+VjtxMcobFXG1WG 5aVzTQF6GtRJf5tIb783bpRxcCeP/MmJhyBktdusYUX/0RYxd6gshJqVMoAOX+LeQ3qG 1EZKtD9bRTJg4IEFhvimrXwn9pHgYSBJrWJPUMco+gC7vMCfZJjcBGb8VYqKAxRdX8d4 SG0g== X-Gm-Message-State: ALoCoQnqk8XLYnlv+1cY7WKrqDcYgXu5H/VAE036mHGWGaFn0YzMWR2ysrNnFinkEzyAsMeNHOfG X-Received: by 10.58.94.166 with SMTP id dd6mr11743524veb.12.1405443164053; Tue, 15 Jul 2014 09:52:44 -0700 (PDT) X-BeenThere: patchwork-forward@linaro.org Received: by 10.140.51.3 with SMTP id t3ls155682qga.82.gmail; Tue, 15 Jul 2014 09:52:44 -0700 (PDT) X-Received: by 10.58.152.234 with SMTP id vb10mr23352027veb.21.1405443163977; Tue, 15 Jul 2014 09:52:43 -0700 (PDT) Received: from mail-vc0-f179.google.com (mail-vc0-f179.google.com [209.85.220.179]) by mx.google.com with ESMTPS id sj4si7052878vec.18.2014.07.15.09.52.43 for (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Tue, 15 Jul 2014 09:52:43 -0700 (PDT) Received-SPF: pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 209.85.220.179 as permitted sender) client-ip=209.85.220.179; Received: by mail-vc0-f179.google.com with SMTP id id10so10726953vcb.38 for ; Tue, 15 Jul 2014 09:52:43 -0700 (PDT) X-Received: by 10.58.188.199 with SMTP id gc7mr23413633vec.4.1405443163872; Tue, 15 Jul 2014 09:52:43 -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 tc5csp229859vcb; Tue, 15 Jul 2014 09:52:43 -0700 (PDT) X-Received: by 10.68.132.42 with SMTP id or10mr24041083pbb.80.1405443162469; Tue, 15 Jul 2014 09:52:42 -0700 (PDT) Received: from bombadil.infradead.org (bombadil.infradead.org. [2001:1868:205::9]) by mx.google.com with ESMTPS id zi2si12158200pbb.138.2014.07.15.09.52.41 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 15 Jul 2014 09:52:42 -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 1X75wW-0005Iu-UQ; Tue, 15 Jul 2014 16:51:04 +0000 Received: from mail-we0-f175.google.com ([74.125.82.175]) by bombadil.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1X75wT-0005Gi-UV for linux-arm-kernel@lists.infradead.org; Tue, 15 Jul 2014 16:51:02 +0000 Received: by mail-we0-f175.google.com with SMTP id t60so103306wes.34 for ; Tue, 15 Jul 2014 09:50:37 -0700 (PDT) X-Received: by 10.194.92.177 with SMTP id cn17mr29431521wjb.71.1405443037080; Tue, 15 Jul 2014 09:50:37 -0700 (PDT) Received: from ards-macbook-pro.local ([77.237.116.228]) by mx.google.com with ESMTPSA id wd7sm32647740wjc.36.2014.07.15.09.50.34 for (version=TLSv1.1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Tue, 15 Jul 2014 09:50:36 -0700 (PDT) From: Ard Biesheuvel To: matt.fleming@intel.com, mark.rutland@arm.com Subject: [RFC PATCH] arm64/efi: efistub: reuse EFI mapping for Image if it is lower Date: Tue, 15 Jul 2014 18:50:30 +0200 Message-Id: <1405443030-4202-1-git-send-email-ard.biesheuvel@linaro.org> X-Mailer: git-send-email 1.8.3.2 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20140715_095102_283438_FA5356B8 X-CRM114-Status: GOOD ( 18.53 ) X-Spam-Score: -0.7 (/) X-Spam-Report: SpamAssassin version 3.4.0 on bombadil.infradead.org summary: Content analysis details: (-0.7 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.7 RCVD_IN_DNSWL_LOW RBL: Sender listed at http://www.dnswl.org/, low trust [74.125.82.175 listed in list.dnswl.org] -0.0 SPF_PASS SPF: sender matches SPF record -0.0 RCVD_IN_MSPIKE_H3 RBL: Good reputation (+3) [74.125.82.175 listed in wl.mailspike.net] -0.0 RCVD_IN_MSPIKE_WL Mailspike good senders Cc: linux-efi@vger.kernel.org, Ard Biesheuvel , catalin.marinas@arm.com, leif.lindholm@linaro.org, roy.franz@linaro.org, msalter@redhat.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: , MIME-Version: 1.0 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: ard.biesheuvel@linaro.org 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.179 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 The EFI loader may load Image at any available offset. This means Image may reside very close to or at the base of DRAM, in which case the relocation done by efi_entry() results in Image being moved up in memory, which is undesirable (memory below the kernel is currently not usable). To work around this, we check in the stub whether the relocated offset is higher than the original offset. If this is the case, the original and relocated Images switch roles, and we move the original Image inside its original lower mapping while executing from the relocated Image. To ensure the original mapping has sufficient size, we add 2 megs + TEXT_OFFSET of padding to the PE/COFF .text section, this should be sufficient to cover rounding and adding TEXT_OFFSET. Signed-off-by: Ard Biesheuvel --- This was tested on a Foundation Model using the patch below, which forces the Image to be loaded at 0x80000000 (base of DRAM). diff --git a/arch/arm64/kernel/head.S b/arch/arm64/kernel/head.S index 2b7bd5eff776..eeadc073bad3 100644 --- a/arch/arm64/kernel/head.S +++ b/arch/arm64/kernel/head.S @@ -138,12 +138,12 @@ pe_header: .short 0 coff_header: .short 0xaa64 // AArch64 - .short 2 // nr_sections + .short 1 // nr_sections .long 0 // TimeDateStamp .long 0 // PointerToSymbolTable .long 1 // NumberOfSymbols .short section_table - optional_header // SizeOfOptionalHeader - .short 0x206 // Characteristics. + .short 0x207 // Characteristics. // IMAGE_FILE_DEBUG_STRIPPED | // IMAGE_FILE_EXECUTABLE_IMAGE | // IMAGE_FILE_LINE_NUMS_STRIPPED @@ -158,7 +158,7 @@ optional_header: .long stext_offset // BaseOfCode extra_header_fields: - .quad 0 // ImageBase + .quad 0x80000000 // ImageBase .long 0x20 // SectionAlignment .long 0x8 // FileAlignment .short 0 // MajorOperatingSystemVersion @@ -193,6 +193,7 @@ extra_header_fields: // Section table section_table: +#if 0 /* * The EFI application loader requires a relocation section * because EFI applications must be relocatable. This is a @@ -212,6 +213,7 @@ section_table: .long 0x42100040 // Characteristics (section flags) +#endif .ascii ".text" .byte 0 .byte 0 arch/arm64/kernel/Makefile | 1 + arch/arm64/kernel/efi-entry.S | 48 +++++++++++++++++++++++++++++++++---------- arch/arm64/kernel/head.S | 7 ++++--- 3 files changed, 42 insertions(+), 14 deletions(-) diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile index cdaedad3afe5..d55da3cd8a97 100644 --- a/arch/arm64/kernel/Makefile +++ b/arch/arm64/kernel/Makefile @@ -6,6 +6,7 @@ CPPFLAGS_vmlinux.lds := -DTEXT_OFFSET=$(TEXT_OFFSET) AFLAGS_head.o := -DTEXT_OFFSET=$(TEXT_OFFSET) CFLAGS_efi-stub.o := -DTEXT_OFFSET=$(TEXT_OFFSET) \ -I$(src)/../../../scripts/dtc/libfdt +AFLAGS_efi-entry.o := -DTEXT_OFFSET=$(TEXT_OFFSET) CFLAGS_REMOVE_ftrace.o = -pg CFLAGS_REMOVE_insn.o = -pg diff --git a/arch/arm64/kernel/efi-entry.S b/arch/arm64/kernel/efi-entry.S index a0016d3a17da..d154f3c73937 100644 --- a/arch/arm64/kernel/efi-entry.S +++ b/arch/arm64/kernel/efi-entry.S @@ -11,6 +11,7 @@ */ #include #include +#include #include @@ -45,10 +46,13 @@ ENTRY(efi_stub_entry) * efi_system_table_t *sys_table, * unsigned long *image_addr) ; */ - adrp x8, _text - add x8, x8, #:lo12:_text + adrp x22, _text + add x22, x22, #:lo12:_text // x22: base of Image + adrp x24, _edata + add x24, x24, #:lo12:_edata + sub x24, x24, x22 // x24: size of Image add x2, sp, 16 - str x8, [x2] + str x22, [x2] bl efi_entry cmn x0, #1 b.eq efi_load_fail @@ -61,19 +65,41 @@ ENTRY(efi_stub_entry) */ mov x20, x0 // DTB address ldr x0, [sp, #16] // relocated _text address - ldr x21, =stext_offset - add x21, x0, x21 + ldr x23, =stext_offset + add x21, x0, x23 /* + * Check whether the original allocation done by the EFI loader is more + * favorable (i.e., closer to the base of DRAM) than the new one created + * by efi_entry(). If so, reuse the original one. + */ + adr x3, 0f + cmp x3, x0 + bgt 1f // this image is loaded higher, so just proceed normally + + /* + * Jump into the relocated image so we can move the original Image to + * a 2 MB boundary + TEXT_OFFSET inside the original mapping without + * overwriting ourselves. + */ + sub x3, x3, x22 // subtract current base offset + add x3, x3, x0 // add base offset of relocated image + br x3 // jump to next line, but in relocated image + +0: mov x1, x0 // copy from relocated Image + sub x0, x22, #1 // copy to base of original Image + orr x0, x0, #(SZ_2M - 1) // .. rounded up to 2 MB + ldr x3, =(TEXT_OFFSET + 1) // .. plus TEXT_OFFSET + add x0, x0, x3 + mov x2, x24 // copy 'size of Image' bytes + bl memcpy + add x21, x0, x23 // add stext_offset to entry point +1: + /* * Flush dcache covering current runtime addresses * of kernel text/data. Then flush all of icache. */ - adrp x1, _text - add x1, x1, #:lo12:_text - adrp x2, _edata - add x2, x2, #:lo12:_edata - sub x1, x2, x1 - + mov x1, x24 // size of Image bl __flush_dcache_area ic ialluis diff --git a/arch/arm64/kernel/head.S b/arch/arm64/kernel/head.S index 5cd1f3491df5..2b7bd5eff776 100644 --- a/arch/arm64/kernel/head.S +++ b/arch/arm64/kernel/head.S @@ -129,6 +129,7 @@ efi_head: #endif #ifdef CONFIG_EFI +#define PE_TEXT_PAD SZ_2M + TEXT_OFFSET .globl stext_offset .set stext_offset, stext - efi_head .align 3 @@ -150,7 +151,7 @@ optional_header: .short 0x20b // PE32+ format .byte 0x02 // MajorLinkerVersion .byte 0x14 // MinorLinkerVersion - .long _edata - stext // SizeOfCode + .long _edata - stext + PE_TEXT_PAD // SizeOfCode .long 0 // SizeOfInitializedData .long 0 // SizeOfUninitializedData .long efi_stub_entry - efi_head // AddressOfEntryPoint @@ -168,7 +169,7 @@ extra_header_fields: .short 0 // MinorSubsystemVersion .long 0 // Win32VersionValue - .long _edata - efi_head // SizeOfImage + .long _edata - efi_head + PE_TEXT_PAD // SizeOfImage // Everything before the kernel image is considered part of the header .long stext_offset // SizeOfHeaders @@ -215,7 +216,7 @@ section_table: .byte 0 .byte 0 .byte 0 // end of 0 padding of section name - .long _edata - stext // VirtualSize + .long _edata - stext + PE_TEXT_PAD // VirtualSize .long stext_offset // VirtualAddress .long _edata - stext // SizeOfRawData .long stext_offset // PointerToRawData