From patchwork Mon Nov 20 14:12:59 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ard Biesheuvel X-Patchwork-Id: 10066533 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 18227603FA for ; Mon, 20 Nov 2017 14:13:42 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 07707292C6 for ; Mon, 20 Nov 2017 14:13:42 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id F084B292CF; Mon, 20 Nov 2017 14:13:41 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-4.2 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,RCVD_IN_DNSWL_MED autolearn=ham version=3.3.1 Received: from bombadil.infradead.org (bombadil.infradead.org [65.50.211.133]) (using TLSv1.2 with cipher AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 529DF292CD for ; Mon, 20 Nov 2017 14:13:39 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:MIME-Version:Cc:List-Subscribe: List-Help:List-Post:List-Archive:List-Unsubscribe:List-Id:Message-Id:Date: Subject:To:From:Reply-To:Content-ID:Content-Description:Resent-Date: Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:In-Reply-To: References:List-Owner; bh=pUNoh1j8pTsAV0iJsXcg3vc4cKTUqdbxILdH65PFyOw=; b=NVo kWjFn3JvvuvwfgDA9U7gABmUscOQSqTTYJef8kL3jX7A1yclYTh6NE76O6nXjJbn3KH3qVdVMLKpV 9TEZViAEDhzcoEnE1b9G/1nD7D4iAa3ZR3+n0kGgl9MgcL8dpkDJGM6fBUCHRmv3DQP0UgjSnI7ax zy4ae6Rx/6M/eW1m/k/6dYrc8KXA7SBQGE5hF9FjnAH/HCyFocALsDPlrLwt/f64AsvSh5XWWA8ZX M3XfMBvR8X0a2zWPGTZv0PayV4Ev1YYDxEBovPoXCgCIthCixHxwhj30w5J9I/m260E0RcAcGB52H /s7HlINzL7jvzFvmQSRksp0/mtRKELw==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.87 #1 (Red Hat Linux)) id 1eGmpO-0007QA-0f; Mon, 20 Nov 2017 14:13:38 +0000 Received: from mail-wm0-x241.google.com ([2a00:1450:400c:c09::241]) by bombadil.infradead.org with esmtps (Exim 4.87 #1 (Red Hat Linux)) id 1eGmpI-0007ON-MH for linux-arm-kernel@lists.infradead.org; Mon, 20 Nov 2017 14:13:36 +0000 Received: by mail-wm0-x241.google.com with SMTP id 5so17981721wmk.1 for ; Mon, 20 Nov 2017 06:13:12 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id; bh=B+4eGnGVbCql/COOTYgrV9zCGPquWTRhkxdlXAKq9yk=; b=EdHCPCiuJssuuU9/qjCPMQy7vLjZwmruo6eI+BouROKJEqhKOcOew7gm110DjhvGSQ w+9gkG966PBdVkC9ku3OwF+pCOFUmc1Pd94DtafHqbUHL2xgfJA3w+qj8JhD19j5UBMq t8Ug8PDb0RB2/hvo7TF9pajdmM0CWSOa65nqI= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id; bh=B+4eGnGVbCql/COOTYgrV9zCGPquWTRhkxdlXAKq9yk=; b=BhyNLUakqKNe8M3FtAU6A6fi1DWsX/ui/nzFzKN5gIL4kc6HzNFiFhYaAMfBlI+Ijr FYJzOaeoyg9H5FT4Pe9yObfCDVJv32w+d6BkwFrl/u0+WPhCcvAHyZ4lXuTWDfoZFhM7 fZ371T+nJac5u0555Et9aYbJEnxlprxX7mOYPBBdtWxM4RqxPzD+S2hiIjS0hyXeQ/rX KvHt9MEDQUggMJADXj9BGRkfWN2iMa89WTROS4EuKKq6X6SQGM7k2FxXemMOjAETjpok zoXI5jUSAIr7opnXsMbCFmvv7MWOjlrwrW1qHsORviKLDtgcGYNESF59Rdgm+57LzUjl d1SQ== X-Gm-Message-State: AJaThX5IpN4vesvi7c6pc+ewqF6iT6/ugCAq1PMPYBXXQTKg2lk/sqSB nIKNRVayfnizbfALyu/D8gIW4j/HxQI= X-Google-Smtp-Source: AGs4zMYMIWssy+hIf+EJBSx+EFfKXMj3YoXevvuoUqqUi97IJXHbo3JzRfdDvrY5eZCq30kl847+7Q== X-Received: by 10.28.69.136 with SMTP id l8mr536940wmi.19.1511187189342; Mon, 20 Nov 2017 06:13:09 -0800 (PST) Received: from localhost.localdomain ([154.145.25.106]) by smtp.gmail.com with ESMTPSA id d23sm15589938wma.48.2017.11.20.06.13.07 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 20 Nov 2017 06:13:08 -0800 (PST) From: Ard Biesheuvel To: linux-arm-kernel@lists.infradead.org Subject: [PATCH v2] arm64: ftrace: emit ftrace-mod.o contents through code Date: Mon, 20 Nov 2017 14:12:59 +0000 Message-Id: <20171120141259.6724-1-ard.biesheuvel@linaro.org> X-Mailer: git-send-email 2.11.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20171120_061333_374400_4FFE848A X-CRM114-Status: GOOD ( 26.08 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: radoslaw.biernacki@linaro.org, graeme.gregory@linaro.org, Ard Biesheuvel , riku.voipio@linaro.org, will.deacon@arm.com, koen.kooi@linaro.org MIME-Version: 1.0 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Virus-Scanned: ClamAV using ClamSMTP When building the arm64 kernel with both CONFIG_ARM64_MODULE_PLTS and CONFIG_DYNAMIC_FTRACE enabled, the ftrace-mod.o object file is built with the kernel and contains a trampoline that is linked into each module, so that modules can be loaded far away from the kernel and still reach the ftrace entry point in the core kernel with an ordinary relative branch, as is emitted by the compiler instrumentation code dynamic ftrace relies on. In order to be able to build out of tree modules, this object file needs to be included into the linux-headers or linux-devel packages, which is undesirable, as it makes arm64 a special case (although a precedent does exist for 32-bit PPC). Given that the trampoline only consists of two instructions, let's not bother with a source or object file for it, and simply patch in these instructions whenever the trampoline is being populated. Signed-off-by: Ard Biesheuvel --- v2: populate the two trampoline instruction slots from the ftrace code so there is no longer a need to have a template .o or .S in the first place don't use a separate linker scripts for ftrace+PLTs arch/arm64/Makefile | 3 --- arch/arm64/kernel/Makefile | 3 --- arch/arm64/kernel/ftrace-mod.S | 18 ------------------ arch/arm64/kernel/ftrace-trampoline.h | 18 ++++++++++++++++++ arch/arm64/kernel/ftrace.c | 16 ++++++++++------ arch/arm64/kernel/module-plts.c | 14 ++++++++++++++ arch/arm64/kernel/module.lds | 1 + 7 files changed, 43 insertions(+), 30 deletions(-) diff --git a/arch/arm64/Makefile b/arch/arm64/Makefile index b35788c909f1..b481b4a7c011 100644 --- a/arch/arm64/Makefile +++ b/arch/arm64/Makefile @@ -83,9 +83,6 @@ endif ifeq ($(CONFIG_ARM64_MODULE_PLTS),y) KBUILD_LDFLAGS_MODULE += -T $(srctree)/arch/arm64/kernel/module.lds -ifeq ($(CONFIG_DYNAMIC_FTRACE),y) -KBUILD_LDFLAGS_MODULE += $(objtree)/arch/arm64/kernel/ftrace-mod.o -endif endif # Default value diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile index 8265dd790895..067baace74a0 100644 --- a/arch/arm64/kernel/Makefile +++ b/arch/arm64/kernel/Makefile @@ -61,6 +61,3 @@ extra-y += $(head-y) vmlinux.lds ifeq ($(CONFIG_DEBUG_EFI),y) AFLAGS_head.o += -DVMLINUX_PATH="\"$(realpath $(objtree)/vmlinux)\"" endif - -# will be included by each individual module but not by the core kernel itself -extra-$(CONFIG_DYNAMIC_FTRACE) += ftrace-mod.o diff --git a/arch/arm64/kernel/ftrace-mod.S b/arch/arm64/kernel/ftrace-mod.S deleted file mode 100644 index 00c4025be4ff..000000000000 --- a/arch/arm64/kernel/ftrace-mod.S +++ /dev/null @@ -1,18 +0,0 @@ -/* - * Copyright (C) 2017 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 - - .section ".text.ftrace_trampoline", "ax" - .align 3 -0: .quad 0 -__ftrace_trampoline: - ldr x16, 0b - br x16 -ENDPROC(__ftrace_trampoline) diff --git a/arch/arm64/kernel/ftrace-trampoline.h b/arch/arm64/kernel/ftrace-trampoline.h new file mode 100644 index 000000000000..caf8434ca52a --- /dev/null +++ b/arch/arm64/kernel/ftrace-trampoline.h @@ -0,0 +1,18 @@ +/* + * Copyright (C) 2017 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 + +#define FTRACE_TRAMPOLINE_LDR cpu_to_le32(0x58ffffd0) +#define FTRACE_TRAMPOLINE_BR cpu_to_le32(0xd61f0200) + +struct ftrace_trampoline { + u64 literal; /* 0: .quad 0x0 */ + __le32 ldr; /* ldr x16, 0b */ + __le32 br; /* br x16 */ +}; diff --git a/arch/arm64/kernel/ftrace.c b/arch/arm64/kernel/ftrace.c index c13b1fca0e5b..2198b5a48871 100644 --- a/arch/arm64/kernel/ftrace.c +++ b/arch/arm64/kernel/ftrace.c @@ -19,6 +19,8 @@ #include #include +#include "ftrace-trampoline.h" + #ifdef CONFIG_DYNAMIC_FTRACE /* * Replace a single instruction, which may be a branch or NOP. @@ -76,7 +78,7 @@ int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr) if (offset < -SZ_128M || offset >= SZ_128M) { #ifdef CONFIG_ARM64_MODULE_PLTS - unsigned long *trampoline; + struct ftrace_trampoline *trampoline; struct module *mod; /* @@ -104,22 +106,24 @@ int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr) * is added in the future, but for now, the pr_err() below * deals with a theoretical issue only. */ - trampoline = (unsigned long *)mod->arch.ftrace_trampoline; - if (trampoline[0] != addr) { - if (trampoline[0] != 0) { + trampoline = (void *)mod->arch.ftrace_trampoline; + if (trampoline->literal != addr) { + if (trampoline->literal != 0) { pr_err("ftrace: far branches to multiple entry points unsupported inside a single module\n"); return -EINVAL; } /* point the trampoline to our ftrace entry point */ module_disable_ro(mod); - trampoline[0] = addr; + trampoline->literal = addr; + trampoline->ldr = FTRACE_TRAMPOLINE_LDR; + trampoline->br = FTRACE_TRAMPOLINE_BR; module_enable_ro(mod, true); /* update trampoline before patching in the branch */ smp_wmb(); } - addr = (unsigned long)&trampoline[1]; + addr = (unsigned long)&trampoline->ldr; #else /* CONFIG_ARM64_MODULE_PLTS */ return -EINVAL; #endif /* CONFIG_ARM64_MODULE_PLTS */ diff --git a/arch/arm64/kernel/module-plts.c b/arch/arm64/kernel/module-plts.c index d05dbe658409..c8fe9c98abc4 100644 --- a/arch/arm64/kernel/module-plts.c +++ b/arch/arm64/kernel/module-plts.c @@ -11,6 +11,8 @@ #include #include +#include "ftrace-trampoline.h" + struct plt_entry { /* * A program that conforms to the AArch64 Procedure Call Standard @@ -154,6 +156,7 @@ int module_frob_arch_sections(Elf_Ehdr *ehdr, Elf_Shdr *sechdrs, unsigned long core_plts = 0; unsigned long init_plts = 0; Elf64_Sym *syms = NULL; + Elf_Shdr *tramp = NULL; int i; /* @@ -165,6 +168,10 @@ int module_frob_arch_sections(Elf_Ehdr *ehdr, Elf_Shdr *sechdrs, mod->arch.core.plt = sechdrs + i; else if (!strcmp(secstrings + sechdrs[i].sh_name, ".init.plt")) mod->arch.init.plt = sechdrs + i; + else if (IS_ENABLED(CONFIG_DYNAMIC_FTRACE) && + !strcmp(secstrings + sechdrs[i].sh_name, + ".text.ftrace_trampoline")) + tramp = sechdrs + i; else if (sechdrs[i].sh_type == SHT_SYMTAB) syms = (Elf64_Sym *)sechdrs[i].sh_addr; } @@ -215,5 +222,12 @@ int module_frob_arch_sections(Elf_Ehdr *ehdr, Elf_Shdr *sechdrs, mod->arch.init.plt_num_entries = 0; mod->arch.init.plt_max_entries = init_plts; + if (tramp) { + tramp->sh_type = SHT_NOBITS; + tramp->sh_flags = SHF_EXECINSTR | SHF_ALLOC; + tramp->sh_addralign = __alignof__(struct ftrace_trampoline); + tramp->sh_size = sizeof(struct ftrace_trampoline); + } + return 0; } diff --git a/arch/arm64/kernel/module.lds b/arch/arm64/kernel/module.lds index f7c9781a9d48..22e36a21c113 100644 --- a/arch/arm64/kernel/module.lds +++ b/arch/arm64/kernel/module.lds @@ -1,4 +1,5 @@ SECTIONS { .plt (NOLOAD) : { BYTE(0) } .init.plt (NOLOAD) : { BYTE(0) } + .text.ftrace_trampoline (NOLOAD) : { BYTE(0) } }