From patchwork Thu Sep 17 19:38:54 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ard Biesheuvel X-Patchwork-Id: 53840 Return-Path: X-Original-To: linaro@patches.linaro.org Delivered-To: linaro@patches.linaro.org Received: from mail-lb0-f200.google.com (mail-lb0-f200.google.com [209.85.217.200]) by patches.linaro.org (Postfix) with ESMTPS id C9A3322E57 for ; Thu, 17 Sep 2015 19:54:09 +0000 (UTC) Received: by lbot4 with SMTP id t4sf9791325lbo.0 for ; Thu, 17 Sep 2015 12:54:08 -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=2MiEeuzdVSwib1GAKj1VN21mCYgLw0DNqYQcLXCLfmc=; b=Cmg0MtRSUuTNGDcCcvbFqxYrZZOZgH5A2nHpaQ7d7s30l+iSqtUd745a0dgzgvJqDR o3de5WXOSgr4dca7i5NXwh+vbSJnaQAWXx0W7GvotbCRMQRbMWiHH8Sp+zKegwRbAbk3 3uI9aBKu3Gyx8ITMR3/YlkRk2QF0CaqX8chPK2hTdJUioSi3iPAOW1KYFR0GArLUmSUS Lcs5igIYLW7RqvpXBPTTj/ZGjaoSlXydbcTm8gYEMWNblGCmXPf7h8A/NGaCug1kQpz9 Yl449X1FKTqdssN11IevkPPWbN1r9aajctjvhOo+TFAB4I396OwpWBN7mUf4C8eeHz5e emuQ== X-Gm-Message-State: ALoCoQlkqvA4g1CHE+SzPx2+JGFovgKjeumEtsAJv4ILhnvrZgcE2R/DYrAehqpIKedhnVXoBU2A X-Received: by 10.194.109.233 with SMTP id hv9mr161678wjb.1.1442519648628; Thu, 17 Sep 2015 12:54:08 -0700 (PDT) X-BeenThere: patchwork-forward@linaro.org Received: by 10.152.45.39 with SMTP id j7ls125570lam.77.gmail; Thu, 17 Sep 2015 12:54:08 -0700 (PDT) X-Received: by 10.112.205.231 with SMTP id lj7mr1128968lbc.57.1442519648459; Thu, 17 Sep 2015 12:54:08 -0700 (PDT) Received: from mail-la0-f53.google.com (mail-la0-f53.google.com. [209.85.215.53]) by mx.google.com with ESMTPS id o9si3319759lbc.25.2015.09.17.12.54.08 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 17 Sep 2015 12:54:08 -0700 (PDT) Received-SPF: pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 209.85.215.53 as permitted sender) client-ip=209.85.215.53; Received: by lamp12 with SMTP id p12so17694510lam.0 for ; Thu, 17 Sep 2015 12:54:08 -0700 (PDT) X-Received: by 10.112.135.9 with SMTP id po9mr1216999lbb.56.1442519648086; Thu, 17 Sep 2015 12:54:08 -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 w3csp3260603lbq; Thu, 17 Sep 2015 12:54:07 -0700 (PDT) X-Received: by 10.66.248.72 with SMTP id yk8mr1791132pac.112.1442519646960; Thu, 17 Sep 2015 12:54:06 -0700 (PDT) Received: from bombadil.infradead.org (bombadil.infradead.org. [2001:1868:205::9]) by mx.google.com with ESMTPS id cj4si7535711pbc.126.2015.09.17.12.54.06 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 17 Sep 2015 12:54:06 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-arm-kernel-bounces+patch=linaro.org@lists.infradead.org designates 2001:1868:205::9 as permitted sender) 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 1ZcfEY-0004q5-Al; Thu, 17 Sep 2015 19:52:42 +0000 Received: from casper.infradead.org ([2001:770:15f::2]) by bombadil.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1ZcfEW-0004nw-6Q for linux-arm-kernel@bombadil.infradead.org; Thu, 17 Sep 2015 19:52:40 +0000 Received: from mail-wi0-f177.google.com ([209.85.212.177]) by casper.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1Zcf1l-0003mT-U2 for linux-arm-kernel@lists.infradead.org; Thu, 17 Sep 2015 19:39:31 +0000 Received: by wiclk2 with SMTP id lk2so37698513wic.0 for ; Thu, 17 Sep 2015 12:39:05 -0700 (PDT) X-Received: by 10.180.19.68 with SMTP id c4mr33473206wie.50.1442518745138; Thu, 17 Sep 2015 12:39:05 -0700 (PDT) Received: from localhost.localdomain (228.202.154.77.rev.sfr.net. [77.154.202.228]) by smtp.gmail.com with ESMTPSA id lf10sm4989873wjb.23.2015.09.17.12.39.03 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Thu, 17 Sep 2015 12:39:04 -0700 (PDT) From: Ard Biesheuvel To: linux-arm-kernel@lists.infradead.org, will.deacon@arm.com, catalin.marinas@arm.com Subject: [RFC PATCH 1/2] arm64: introduce infrastructure for emitting veneers at module reloc time Date: Thu, 17 Sep 2015 21:38:54 +0200 Message-Id: <1442518735-16625-2-git-send-email-ard.biesheuvel@linaro.org> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1442518735-16625-1-git-send-email-ard.biesheuvel@linaro.org> References: <1442518735-16625-1-git-send-email-ard.biesheuvel@linaro.org> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20150917_203930_371062_2C1A5BE2 X-CRM114-Status: GOOD ( 24.36 ) X-Spam-Score: -2.6 (--) X-Spam-Report: SpamAssassin version 3.4.0 on casper.infradead.org summary: Content analysis details: (-2.6 points, 5.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 RCVD_IN_MSPIKE_H3 RBL: Good reputation (+3) [209.85.212.177 listed in wl.mailspike.net] -0.7 RCVD_IN_DNSWL_LOW RBL: Sender listed at http://www.dnswl.org/, low trust [209.85.212.177 listed in list.dnswl.org] -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.215.53 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 | 4 + arch/arm64/Makefile | 4 + arch/arm64/include/asm/module.h | 9 ++ arch/arm64/kernel/Makefile | 1 + arch/arm64/kernel/module.lds | 4 + arch/arm64/kernel/veneers.c | 100 ++++++++++++++++++++ 6 files changed, 122 insertions(+) diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig index 7d95663c0160..115586d8299b 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_MODULE_VENEERS select HAVE_PATA_PLATFORM select HAVE_PERF_EVENTS select HAVE_PERF_REGS @@ -333,6 +334,9 @@ config ARM64_ERRATUM_845719 endmenu +config ARM64_MODULE_VENEERS + bool + depends on MODULES choice prompt "Page size" diff --git a/arch/arm64/Makefile b/arch/arm64/Makefile index 15ff5b4156fd..ccbcb399b9f1 100644 --- a/arch/arm64/Makefile +++ b/arch/arm64/Makefile @@ -41,6 +41,10 @@ endif CHECKFLAGS += -D__aarch64__ +ifeq ($(CONFIG_ARM64_MODULE_VENEERS),y) +LDFLAGS_MODULE += -T $(srctree)/arch/arm64/kernel/module.lds +endif + # Default value head-y := arch/arm64/kernel/head.o diff --git a/arch/arm64/include/asm/module.h b/arch/arm64/include/asm/module.h index e80e232b730e..87e1f097a500 100644 --- a/arch/arm64/include/asm/module.h +++ b/arch/arm64/include/asm/module.h @@ -20,4 +20,13 @@ #define MODULE_ARCH_VERMAGIC "aarch64" +#ifdef CONFIG_ARM64_MODULE_VENEERS +struct mod_arch_specific { + struct veneer_section { + struct elf64_shdr *veneers; + unsigned long size; + } core, init; +}; +#endif + #endif /* __ASM_MODULE_H */ diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile index 22dc9bc781be..0016e042848f 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_MODULE_VENEERS)+= 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/module.lds b/arch/arm64/kernel/module.lds new file mode 100644 index 000000000000..845b75ee0f93 --- /dev/null +++ b/arch/arm64/kernel/module.lds @@ -0,0 +1,4 @@ +SECTIONS { + .core.veneers : { BYTE(0) } + .init.veneers : { BYTE(0) } +} diff --git a/arch/arm64/kernel/veneers.c b/arch/arm64/kernel/veneers.c new file mode 100644 index 000000000000..0a33a63a9b46 --- /dev/null +++ b/arch/arm64/kernel/veneers.c @@ -0,0 +1,100 @@ +/* + * 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 __maybe_unused *alloc_veneer(struct module *mod, u64 loc, int size) +{ + struct veneer_section *vs; + void *ret; + + if (in_init(mod, loc)) + vs = &mod->arch.init; + else + vs = &mod->arch.core; + + ret = (void*)vs->veneers->sh_addr + vs->size; + vs->size += size; + + return ret; +} + +/* estimate the maximum size of the veneer for this relocation */ +static unsigned long get_veneers_size(Elf64_Addr base, const Elf64_Rel *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; + Elf64_Shdr *s, *sechdrs_end = sechdrs + ehdr->e_shnum; + + /* + * To store the veneers, we expand the .text section for core module + * code and the .init.text section for initialization code. + */ + for (s = sechdrs; s < sechdrs_end; ++s) + if (strcmp(".core.veneers", secstrings + s->sh_name) == 0) + mod->arch.core.veneers = s; + else if (strcmp(".init.veneers", secstrings + s->sh_name) == 0) + mod->arch.init.veneers = s; + + if (!mod->arch.core.veneers || !mod->arch.init.veneers) { + pr_err("%s: sections missing\n", mod->name); + return -ENOEXEC; + } + + for (s = sechdrs + 1; s < sechdrs_end; ++s) { + const Elf64_Rel *rels = (void *)ehdr + s->sh_offset; + int numrels = s->sh_size / sizeof(Elf64_Rel); + Elf64_Shdr *dstsec = sechdrs + s->sh_info; + + if (s->sh_type != SHT_REL) + 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); + } + + mod->arch.core.veneers->sh_type = SHT_NOBITS; + mod->arch.core.veneers->sh_flags = SHF_EXECINSTR | SHF_ALLOC; + mod->arch.core.veneers->sh_addralign = L1_CACHE_BYTES; + mod->arch.core.veneers->sh_size = core_veneers_maxsize; + mod->arch.core.size = 0; + + mod->arch.init.veneers->sh_type = SHT_NOBITS; + mod->arch.init.veneers->sh_flags = SHF_EXECINSTR | SHF_ALLOC; + mod->arch.init.veneers->sh_addralign = L1_CACHE_BYTES; + mod->arch.init.veneers->sh_size = init_veneers_maxsize; + mod->arch.init.size = 0; + pr_debug("%s: core.veneers=%llx, init.veneers=%llx\n", + __func__, + mod->arch.core.veneers->sh_size, + mod->arch.init.veneers->sh_size); + return 0; +}