From patchwork Fri Sep 18 15:39:59 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ard Biesheuvel X-Patchwork-Id: 53919 Return-Path: X-Original-To: linaro@patches.linaro.org Delivered-To: linaro@patches.linaro.org Received: from mail-lb0-f198.google.com (mail-lb0-f198.google.com [209.85.217.198]) by patches.linaro.org (Postfix) with ESMTPS id A9591218E3 for ; Fri, 18 Sep 2015 15:42:11 +0000 (UTC) Received: by lbot4 with SMTP id t4sf18416878lbo.0 for ; Fri, 18 Sep 2015 08:42:10 -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:precedence:list-id:list-unsubscribe :list-archive:list-post:list-help:list-subscribe:cc:mime-version :content-type:content-transfer-encoding:sender:errors-to :x-original-sender:x-original-authentication-results:mailing-list; bh=omQlTNxVHkmxxI+ohg6ESdT5PPiBL5XR4Fik/f9awLI=; b=XB97mI1YOJTiBRRRXfFJK/A3Dr4kXHHPGoVfHIA83CBnsPo406f7e5YSpeMTnqU6ck A0CQYDqWHjGu1xac6z4VstHScRXvvFLntF9o/m6q200dGc2W5hNKS3+EIcXUMHgwY7N4 mXh4C5PioCeZQ745IEySCylS1gQxs7YvXJeQ5CLCidjVS3bZvLr98xoTjGJbLyC7E3pT e6Hz/jHDCuo+FvvNn5oMYO9jZOf+FwScDrgXrIK8CRMWK7Npb6qaxwFH5ELHnuW6ag+I gTCI7J5pufV51dlrb/4uNbip3fRWd774gEMZPjnCiUTxKJAcwi/gMveLJAh6wiF2Kqpv JusQ== X-Gm-Message-State: ALoCoQmNVNBZYx/JB2l4CzFUnRN8al3E7RrDSPxlPN+cpq9uHxw0/HVllT91tBLWXXiQMwb5oSeV X-Received: by 10.152.163.97 with SMTP id yh1mr1031783lab.10.1442590930422; Fri, 18 Sep 2015 08:42:10 -0700 (PDT) X-BeenThere: patchwork-forward@linaro.org Received: by 10.152.37.199 with SMTP id a7ls221625lak.75.gmail; Fri, 18 Sep 2015 08:42:10 -0700 (PDT) X-Received: by 10.112.53.131 with SMTP id b3mr3473388lbp.55.1442590930277; Fri, 18 Sep 2015 08:42:10 -0700 (PDT) Received: from mail-lb0-f177.google.com (mail-lb0-f177.google.com. [209.85.217.177]) by mx.google.com with ESMTPS id b20si25661lfe.177.2015.09.18.08.42.10 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 18 Sep 2015 08:42:10 -0700 (PDT) Received-SPF: pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 209.85.217.177 as permitted sender) client-ip=209.85.217.177; Received: by lbpo4 with SMTP id o4so27214544lbp.2 for ; Fri, 18 Sep 2015 08:42:10 -0700 (PDT) X-Received: by 10.152.26.98 with SMTP id k2mr3367804lag.41.1442590930000; Fri, 18 Sep 2015 08:42:10 -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.59.35 with SMTP id w3csp374920lbq; Fri, 18 Sep 2015 08:42:08 -0700 (PDT) X-Received: by 10.107.3.170 with SMTP id e42mr14380655ioi.72.1442590928566; Fri, 18 Sep 2015 08:42:08 -0700 (PDT) Received: from bombadil.infradead.org (bombadil.infradead.org. [198.137.202.9]) by mx.google.com with ESMTPS id 76si7310956ioi.23.2015.09.18.08.42.08 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 18 Sep 2015 08:42:08 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-arm-kernel-bounces+patch=linaro.org@lists.infradead.org designates 198.137.202.9 as permitted sender) client-ip=198.137.202.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 1ZcxmN-00024b-4K; Fri, 18 Sep 2015 15:40:51 +0000 Received: from mail-wi0-f182.google.com ([209.85.212.182]) by bombadil.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1Zcxm2-0001aJ-Jl for linux-arm-kernel@lists.infradead.org; Fri, 18 Sep 2015 15:40:33 +0000 Received: by wiclk2 with SMTP id lk2so36150559wic.1 for ; Fri, 18 Sep 2015 08:40:08 -0700 (PDT) X-Received: by 10.180.184.134 with SMTP id eu6mr17468837wic.77.1442590808721; Fri, 18 Sep 2015 08:40:08 -0700 (PDT) Received: from localhost.localdomain ([5.90.15.235]) by smtp.gmail.com with ESMTPSA id lu5sm9478601wjb.9.2015.09.18.08.40.06 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Fri, 18 Sep 2015 08:40:08 -0700 (PDT) From: Ard Biesheuvel To: linux-arm-kernel@lists.infradead.org, will.deacon@arm.com, catalin.marinas@arm.com Subject: [PATCH v1 1/2] arm64: introduce infrastructure for emitting veneers at module reloc time Date: Fri, 18 Sep 2015 17:39:59 +0200 Message-Id: <1442590800-14645-2-git-send-email-ard.biesheuvel@linaro.org> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1442590800-14645-1-git-send-email-ard.biesheuvel@linaro.org> References: <1442590800-14645-1-git-send-email-ard.biesheuvel@linaro.org> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20150918_084031_022317_2077C40F X-CRM114-Status: GOOD ( 21.73 ) X-Spam-Score: -2.6 (--) X-Spam-Report: SpamAssassin version 3.4.0 on bombadil.infradead.org summary: Content analysis details: (-2.6 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.7 RCVD_IN_DNSWL_LOW RBL: Sender listed at http://www.dnswl.org/, low trust [209.85.212.182 listed in list.dnswl.org] -0.0 RCVD_IN_MSPIKE_H3 RBL: Good reputation (+3) [209.85.212.182 listed in wl.mailspike.net] -0.0 SPF_PASS SPF: sender matches SPF record -1.9 BAYES_00 BODY: Bayes spam probability is 0 to 1% [score: 0.0000] -0.0 RCVD_IN_MSPIKE_WL Mailspike good senders X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: , List-Help: , List-Subscribe: , Cc: andre.przywara@arm.com, Ard Biesheuvel , suzuki.poulose@arm.com 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.177 as permitted sender) smtp.mailfrom=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 Introduce a framework for arm64 that allows errata fixups to be implemented by replacing problematic instruction sequences with calls into veneers that are generated on the fly. This is based on the module PLT support for ARM. Signed-off-by: Ard Biesheuvel --- arch/arm64/Kconfig | 3 + arch/arm64/include/asm/module.h | 11 ++ arch/arm64/kernel/Makefile | 1 + arch/arm64/kernel/mod_veneers.c | 105 ++++++++++++++++++++ 4 files changed, 120 insertions(+) diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig index 7d95663c0160..b591aac06fed 100644 --- a/arch/arm64/Kconfig +++ b/arch/arm64/Kconfig @@ -68,6 +68,7 @@ config ARM64 select HAVE_GENERIC_DMA_COHERENT select HAVE_HW_BREAKPOINT if PERF_EVENTS select HAVE_MEMBLOCK + select HAVE_MOD_ARCH_SPECIFIC if ARM64_MOD_VENEERS select HAVE_PATA_PLATFORM select HAVE_PERF_EVENTS select HAVE_PERF_REGS @@ -333,6 +334,8 @@ config ARM64_ERRATUM_845719 endmenu +config ARM64_MOD_VENEERS + bool choice prompt "Page size" diff --git a/arch/arm64/include/asm/module.h b/arch/arm64/include/asm/module.h index e80e232b730e..d9ce63386e33 100644 --- a/arch/arm64/include/asm/module.h +++ b/arch/arm64/include/asm/module.h @@ -20,4 +20,15 @@ #define MODULE_ARCH_VERMAGIC "aarch64" +#ifdef CONFIG_HAVE_MOD_ARCH_SPECIFIC +struct mod_arch_specific { +#ifdef CONFIG_ARM64_MOD_VENEERS + struct veneer_section { + int sec_index; + unsigned int sec_offset; + } core, init; +#endif +}; +#endif + #endif /* __ASM_MODULE_H */ diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile index 22dc9bc781be..29eb0c8c33a8 100644 --- a/arch/arm64/kernel/Makefile +++ b/arch/arm64/kernel/Makefile @@ -25,6 +25,7 @@ arm64-obj-$(CONFIG_COMPAT) += sys32.o kuser32.o signal32.o \ ../../arm/kernel/opcodes.o arm64-obj-$(CONFIG_FUNCTION_TRACER) += ftrace.o entry-ftrace.o arm64-obj-$(CONFIG_MODULES) += arm64ksyms.o module.o +arm64-obj-$(CONFIG_ARM64_MOD_VENEERS) += mod_veneers.o arm64-obj-$(CONFIG_PERF_EVENTS) += perf_regs.o perf_callchain.o arm64-obj-$(CONFIG_HW_PERF_EVENTS) += perf_event.o arm64-obj-$(CONFIG_HAVE_HW_BREAKPOINT) += hw_breakpoint.o diff --git a/arch/arm64/kernel/mod_veneers.c b/arch/arm64/kernel/mod_veneers.c new file mode 100644 index 000000000000..9649c4f305bd --- /dev/null +++ b/arch/arm64/kernel/mod_veneers.c @@ -0,0 +1,105 @@ +/* + * Copyright (C) 2015 Linaro Ltd. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include + +static bool in_init(const struct module *mod, u64 addr) +{ + return addr - (u64)mod->module_init < mod->init_size; +} + +static void *alloc_veneer(struct module *mod, u64 loc, int size, + Elf64_Shdr *sechdrs) +{ + struct veneer_section *vs; + void *ret; + + if (in_init(mod, loc) && mod->arch.init.sec_index != -1) + vs = &mod->arch.init; + else + vs = &mod->arch.core; + + ret = (void*)sechdrs[vs->sec_index].sh_addr + vs->sec_offset; + vs->sec_offset += size; + + return ret; +} + +/* estimate the maximum size of the veneer for this relocation */ +static unsigned long get_veneers_size(Elf64_Addr base, const Elf64_Rela *rel, + int num) +{ + unsigned long ret = 0; + int i; + + for (i = 0; i < num; i++) + switch (ELF64_R_TYPE(rel[i].r_info)) { + } + return ret; +} + +int module_frob_arch_sections(Elf64_Ehdr *ehdr, Elf64_Shdr *sechdrs, + char *secstrings, struct module *mod) +{ + unsigned long core_veneers_maxsize = 0, init_veneers_maxsize = 0; + int core_sec_idx = -1, init_sec_idx = -1; + int i; + + /* find the .text and .init.text sections */ + for (i = 0; i < ehdr->e_shnum; i++) { + const char *sec_name = secstrings + sechdrs[i].sh_name; + + if (strcmp(sec_name, ".text") == 0) + core_sec_idx = i; + else if (strcmp(sec_name, ".init.text") == 0) + init_sec_idx = i; + + if (core_sec_idx != -1 && init_sec_idx != -1) + break; + } + + for (i = 0; i < ehdr->e_shnum; i++) { + Elf64_Shdr *s = &sechdrs[i]; + Elf64_Rela *rels = (void *)ehdr + s->sh_offset; + int numrels = s->sh_size / sizeof(Elf64_Rela); + Elf64_Shdr *dstsec = sechdrs + s->sh_info; + + if (s->sh_type != SHT_RELA) + continue; + + if (strstr(secstrings + s->sh_name, ".init")) + init_veneers_maxsize += get_veneers_size( + dstsec->sh_addr, rels, numrels); + else + core_veneers_maxsize += get_veneers_size( + dstsec->sh_addr, rels, numrels); + } + + if (init_sec_idx == -1 && init_veneers_maxsize > 0) + core_veneers_maxsize += init_veneers_maxsize; + + if (core_sec_idx == -1 && core_veneers_maxsize > 0) { + pr_err("%s: .text section missing\n", mod->name); + return -ENOEXEC; + } + + mod->arch.core.sec_index = core_sec_idx; + mod->arch.core.sec_offset = sechdrs[core_sec_idx].sh_size; + sechdrs[core_sec_idx].sh_size += core_veneers_maxsize; + + mod->arch.init.sec_index = init_sec_idx; + if (init_sec_idx != -1) { + mod->arch.init.sec_offset = sechdrs[init_sec_idx].sh_size; + sechdrs[init_sec_idx].sh_size += init_veneers_maxsize; + } + pr_debug("module %s: core_veneers_maxsize == %lu, init_veneers_maxsize == %lu\n", + mod->name, core_veneers_maxsize, init_veneers_maxsize); + return 0; +}