From patchwork Mon Mar 16 15:23:42 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ard Biesheuvel X-Patchwork-Id: 45856 Return-Path: X-Original-To: linaro@patches.linaro.org Delivered-To: linaro@patches.linaro.org Received: from mail-wg0-f69.google.com (mail-wg0-f69.google.com [74.125.82.69]) by ip-10-151-82-157.ec2.internal (Postfix) with ESMTPS id 865B421523 for ; Mon, 16 Mar 2015 15:28:48 +0000 (UTC) Received: by wghk14 with SMTP id k14sf27220499wgh.3 for ; Mon, 16 Mar 2015 08:28: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:from:to:subject:date:message-id :in-reply-to:references:cc:precedence:list-id:list-unsubscribe :list-archive:list-post:list-help:list-subscribe:mime-version :content-type:content-transfer-encoding:sender:errors-to :x-original-sender:x-original-authentication-results:mailing-list; bh=P/k5kRSW9MXm/wpuyUTJZ92gAduuUuDcdPmaJ4ogm3w=; b=FgrM36P+jR140yGoZrbcZuj5wblrP2ZYp4jC3U7IA9zyTOW5SxTGdOzdQFyuaIx/gm nq0flMezHp/54q9OzFlyQ45tfAgHYJPWHcoHl9in759HsqEY8OMYc3bsfBtRjCIJpv9w jPZjxDSj60zWNhLWeRVbnngW8/cVnSIpIv0joeGmtj5PxQsWTeUmA+iLNuA4QQYtRPZv 3jFdM/LKSAU6xofsNfSRRfbcKW1/v2c76+rsE8mF6ZerA0kAODjSl0AAW6D0ZUbOGRFV f7OGpYs1/nP0iB3m9W1XrAZCQiR5aErtcOjdi2Klwk0apWaIy/uudW/A/yInM0gLOPca AfQw== X-Gm-Message-State: ALoCoQls8VEeYHHG9+JbMxywF7SRRJe7H5VmzV4AUGEpHPB46nXRI+L/9PiGC4NIRfbs+n4fo66E X-Received: by 10.112.73.33 with SMTP id i1mr764080lbv.0.1426519727857; Mon, 16 Mar 2015 08:28:47 -0700 (PDT) X-BeenThere: patchwork-forward@linaro.org Received: by 10.152.29.225 with SMTP id n1ls699159lah.52.gmail; Mon, 16 Mar 2015 08:28:47 -0700 (PDT) X-Received: by 10.152.1.1 with SMTP id 1mr54888353lai.63.1426519727642; Mon, 16 Mar 2015 08:28:47 -0700 (PDT) Received: from mail-lb0-f173.google.com (mail-lb0-f173.google.com. [209.85.217.173]) by mx.google.com with ESMTPS id b17si8400983lbo.82.2015.03.16.08.28.47 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 16 Mar 2015 08:28:47 -0700 (PDT) Received-SPF: pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 209.85.217.173 as permitted sender) client-ip=209.85.217.173; Received: by lbbzq9 with SMTP id zq9so33466634lbb.0 for ; Mon, 16 Mar 2015 08:28:47 -0700 (PDT) X-Received: by 10.152.197.34 with SMTP id ir2mr55642314lac.36.1426519727525; Mon, 16 Mar 2015 08:28: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.112.35.133 with SMTP id h5csp2659008lbj; Mon, 16 Mar 2015 08:28:46 -0700 (PDT) X-Received: by 10.66.218.168 with SMTP id ph8mr139261470pac.95.1426519725566; Mon, 16 Mar 2015 08:28:45 -0700 (PDT) Received: from bombadil.infradead.org (bombadil.infradead.org. [2001:1868:205::9]) by mx.google.com with ESMTPS id by8si23260997pdb.43.2015.03.16.08.28.44 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 16 Mar 2015 08:28:45 -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 1YXWvH-0007BH-PQ; Mon, 16 Mar 2015 15:27:19 +0000 Received: from mail-we0-f179.google.com ([74.125.82.179]) by bombadil.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1YXWuv-0006mU-VR for linux-arm-kernel@lists.infradead.org; Mon, 16 Mar 2015 15:26:59 +0000 Received: by webcq43 with SMTP id cq43so40951407web.2 for ; Mon, 16 Mar 2015 08:26:35 -0700 (PDT) X-Received: by 10.180.83.102 with SMTP id p6mr141185824wiy.78.1426519595875; Mon, 16 Mar 2015 08:26:35 -0700 (PDT) Received: from ards-macbook-pro.local ([90.174.4.220]) by mx.google.com with ESMTPSA id u16sm15876983wjr.5.2015.03.16.08.26.32 (version=TLSv1.1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Mon, 16 Mar 2015 08:26:34 -0700 (PDT) From: Ard Biesheuvel To: linux-arm-kernel@lists.infradead.org, lkml@vger.kernel.org, keescook@chromium.org, catalin.marinas@arm.com, will.deacon@arm.com, mark.rutland@arm.com, marc.zyngier@arm.com Subject: [RFC PATCH 2/3] arm64: add support for relocatable kernel Date: Mon, 16 Mar 2015 16:23:42 +0100 Message-Id: <1426519423-28263-3-git-send-email-ard.biesheuvel@linaro.org> X-Mailer: git-send-email 1.8.3.2 In-Reply-To: <1426519423-28263-1-git-send-email-ard.biesheuvel@linaro.org> References: <1426519423-28263-1-git-send-email-ard.biesheuvel@linaro.org> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20150316_082658_222437_1FD1B844 X-CRM114-Status: GOOD ( 15.35 ) 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.179 listed in list.dnswl.org] -0.0 RCVD_IN_MSPIKE_H3 RBL: Good reputation (+3) [74.125.82.179 listed in wl.mailspike.net] -0.0 SPF_PASS SPF: sender matches SPF record -0.0 RCVD_IN_MSPIKE_WL Mailspike good senders Cc: joakim.bech@linaro.org, Ard Biesheuvel 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.217.173 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 This adds support for runtime relocation of the kernel Image, by building it as a PIE (ET_DYN) executable and applying the relocations in the early boot code. Signed-off-by: Ard Biesheuvel --- arch/arm64/Kconfig | 3 +++ arch/arm64/Makefile | 4 +++ arch/arm64/kernel/head.S | 58 ++++++++++++++++++++++++++++++++++++++++- arch/arm64/kernel/image.h | 8 +++++- arch/arm64/kernel/vmlinux.lds.S | 12 +++++++++ scripts/sortextable.c | 4 +-- 6 files changed, 85 insertions(+), 4 deletions(-) diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig index 1b8e97331ffb..cc6504998f2c 100644 --- a/arch/arm64/Kconfig +++ b/arch/arm64/Kconfig @@ -143,6 +143,9 @@ config KERNEL_MODE_NEON config FIX_EARLYCON_MEM def_bool y +config RELOCATABLE_KERNEL + def_bool y + source "init/Kconfig" source "kernel/Kconfig.freezer" diff --git a/arch/arm64/Makefile b/arch/arm64/Makefile index 69ceedc982a5..e3914049c389 100644 --- a/arch/arm64/Makefile +++ b/arch/arm64/Makefile @@ -15,6 +15,10 @@ CPPFLAGS_vmlinux.lds = -DTEXT_OFFSET=$(TEXT_OFFSET) OBJCOPYFLAGS :=-O binary -R .note -R .note.gnu.build-id -R .comment -S GZFLAGS :=-9 +ifneq ($(CONFIG_RELOCATABLE_KERNEL),) +LDFLAGS_vmlinux += -pie +endif + KBUILD_DEFCONFIG := defconfig KBUILD_CFLAGS += -mgeneral-regs-only diff --git a/arch/arm64/kernel/head.S b/arch/arm64/kernel/head.S index 1ea3cd2aba34..874754794b25 100644 --- a/arch/arm64/kernel/head.S +++ b/arch/arm64/kernel/head.S @@ -239,6 +239,7 @@ section_table: ENTRY(stext) mov x21, x0 // x21=FDT + mov x23, x1 // x23=image offset bl el2_setup // Drop to EL1, w20=cpu_boot_mode bl __calc_phys_offset // x24=PHYS_OFFSET, x28=PHYS_OFFSET-PAGE_OFFSET bl set_cpu_boot_mode_flag @@ -249,8 +250,12 @@ ENTRY(stext) * On return, the CPU will be ready for the MMU to be turned on and * the TCR will have been set. */ +#ifndef CONFIG_RELOCATABLE_KERNEL ldr x27, =__mmap_switched // address to jump to after // MMU has been enabled +#else + adr x27, __relocate_kernel +#endif adrp lr, __enable_mmu // return (PIC) address add lr, lr, #:lo12:__enable_mmu b __cpu_setup // initialise processor @@ -397,9 +402,10 @@ __create_page_tables: */ mov x0, x26 // swapper_pg_dir mov x5, #PAGE_OFFSET + add x5, x5, x23 // __va(KERNEL_START) create_pgd_entry x0, x5, x3, x6 adr_l x6, KERNEL_END - mov x3, x24 // phys offset + add x3, x23, x24 // phys offset + image offset sub x6, x6, x3 // kernel memsize add x6, x6, x5 // __va(KERNEL_END) create_block_map x0, x7, x3, x5, x6 @@ -438,6 +444,55 @@ __mmap_switched: b start_kernel ENDPROC(__mmap_switched) +#ifdef CONFIG_RELOCATABLE_KERNEL + +#define R_AARCH64_RELATIVE 0x403 +#define R_AARCH64_ABS64 0x101 + + /* + * Iterate over each entry in the relocation table, and apply the + * relocations in place. + */ +__relocate_kernel: + adr_l x8, __dynsym_start // start of symbol table + adr_l x9, __reloc_start // start of reloc table + adr_l x10, __reloc_end // end of reloc table +0: cmp x9, x10 + b.hs 2f + ldp x11, x12, [x9], #24 + cmp x12, #R_AARCH64_RELATIVE + b.ne 1f + ldr x12, [x9, #-8] + add x12, x12, x23 // relocate + str x12, [x11, x28] + b 0b + +1: ubfx x13, x12, #0, #32 + cmp x13, #R_AARCH64_ABS64 + b.ne 0b + lsr x13, x12, #32 // symbol index + ldr x12, [x9, #-8] + add x13, x13, x13, lsl #1 // x 3 + add x13, x8, x13, lsl #3 // x 8 + ldrsh w14, [x13, #6] // Elf64_Sym::st_shndx + ldr x15, [x13, #8] // Elf64_Sym::st_value + cmp w14, #-0xf // SHN_ABS (0xfff1) ? + add x14, x15, x23 // relocate + csel x15, x14, x15, ne + add x15, x12, x15 + str x15, [x11, x28] + b 0b + +2: ldr x8, =vectors // reload VBAR_EL1 with + msr vbar_el1, x8 // relocated address + isb + + ldr x9, =__mmap_switched + br x9 +ENDPROC(__relocate_kernel) + +#endif + /* * end early head section, begin head code that is also used for * hotplug and needs to have the same protections as the text region @@ -657,6 +712,7 @@ __calc_phys_offset: mov x2, PAGE_OFFSET sub x28, x0, x1 // x28 = PHYS_OFFSET - PAGE_OFFSET add x24, x2, x28 // x24 = PHYS_OFFSET + sub x24, x24, x23 // subtract image offset ret ENDPROC(__calc_phys_offset) diff --git a/arch/arm64/kernel/image.h b/arch/arm64/kernel/image.h index 8fae0756e175..8b1e9fa8fc8c 100644 --- a/arch/arm64/kernel/image.h +++ b/arch/arm64/kernel/image.h @@ -47,7 +47,13 @@ #define __HEAD_FLAG_BE 0 #endif -#define __HEAD_FLAGS (__HEAD_FLAG_BE << 0) +#ifdef CONFIG_RELOCATABLE_KERNEL +#define __HEAD_FLAG_RELOC 1 +#else +#define __HEAD_FLAG_RELOC 0 +#endif + +#define __HEAD_FLAGS (__HEAD_FLAG_BE << 0) | (__HEAD_FLAG_RELOC << 1) /* * These will output as part of the Image header, which should be little-endian diff --git a/arch/arm64/kernel/vmlinux.lds.S b/arch/arm64/kernel/vmlinux.lds.S index a2c29865c3fe..df706a8c22f1 100644 --- a/arch/arm64/kernel/vmlinux.lds.S +++ b/arch/arm64/kernel/vmlinux.lds.S @@ -131,6 +131,18 @@ SECTIONS PERCPU_SECTION(64) + .rela : { + . = ALIGN(8); + __reloc_start = .; + *(.rela .rela*) + __reloc_end = .; + } + .dynsym : { + . = ALIGN(8); + __dynsym_start = .; + *(.dynsym) + } + . = ALIGN(PAGE_SIZE); __init_end = .; diff --git a/scripts/sortextable.c b/scripts/sortextable.c index 1052d4834a44..77fcc1a80011 100644 --- a/scripts/sortextable.c +++ b/scripts/sortextable.c @@ -262,9 +262,9 @@ do_file(char const *const fname) break; } /* end switch */ if (memcmp(ELFMAG, ehdr->e_ident, SELFMAG) != 0 - || r2(&ehdr->e_type) != ET_EXEC + || (r2(&ehdr->e_type) != ET_EXEC && r2(&ehdr->e_type) != ET_DYN) || ehdr->e_ident[EI_VERSION] != EV_CURRENT) { - fprintf(stderr, "unrecognized ET_EXEC file %s\n", fname); + fprintf(stderr, "unrecognized ET_EXEC/ET_DYN file %s\n", fname); fail_file(); }