From patchwork Mon Jan 25 17:05:20 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jean-Philippe Brucker X-Patchwork-Id: 8113481 Return-Path: X-Original-To: patchwork-linux-arm@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork2.web.kernel.org (Postfix) with ESMTP id 265E9BEEE5 for ; Mon, 25 Jan 2016 17:19:27 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id F23F82027D for ; Mon, 25 Jan 2016 17:19:25 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.9]) (using TLSv1.2 with cipher AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id C304320279 for ; Mon, 25 Jan 2016 17:19:24 +0000 (UTC) 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 1aNklm-0005LF-3g; Mon, 25 Jan 2016 17:17:38 +0000 Received: from foss.arm.com ([217.140.101.70]) by bombadil.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1aNkaR-0002XN-3c for linux-arm-kernel@lists.infradead.org; Mon, 25 Jan 2016 17:06:22 +0000 Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.72.51.249]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id DAE8A3F8; Mon, 25 Jan 2016 09:04:52 -0800 (PST) Received: from e106794-lin.cambridge.arm.com (e106794-lin.cambridge.arm.com [10.1.207.63]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 6CC8A3F24D; Mon, 25 Jan 2016 09:05:32 -0800 (PST) From: Jean-Philippe Brucker To: linux-arm-kernel@lists.infradead.org Subject: [RFC PATCH 1/2] ARM: deprecate old APCS frame format Date: Mon, 25 Jan 2016 17:05:20 +0000 Message-Id: <1453741521-6878-2-git-send-email-jean-philippe.brucker@arm.com> X-Mailer: git-send-email 1.7.9.5 In-Reply-To: <1453741521-6878-1-git-send-email-jean-philippe.brucker@arm.com> References: <1453741521-6878-1-git-send-email-jean-philippe.brucker@arm.com> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20160125_090556_078856_2584D8E9 X-CRM114-Status: GOOD ( 15.80 ) X-Spam-Score: -6.9 (------) 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: Lorenzo Pieralisi , Ingo Molnar , Russell King , Steven Rostedt , Nicolas Pitre MIME-Version: 1.0 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Spam-Status: No, score=-4.2 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_MED, RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP GCC 5 deprecated option -mapcs-frame, which generated frames following the old ABI format. In preparation for a possible removal in future versions of GCC, deprecate use of this flag in Linux as well. Instead of completely removing the bits that depend on APCS frame, we move them behind a DEPRECATED config option to smoothen the transition. Neither AAPCS nor EABI guarantees any frame format, so only ARM_UNWIND should now be used for stack traces and introspection. It is already selected by most defconfigs. Furthermore, frames currently generated by GCC are different for leaf and non-leaf functions, which would make adaptation quite tricky. Signed-off-by: Jean-Philippe Brucker --- arch/arm/Kconfig.debug | 16 ++++++++++++---- arch/arm/Makefile | 6 +++++- arch/arm/include/asm/ftrace.h | 8 ++++---- arch/arm/kernel/entry-ftrace.S | 2 +- arch/arm/kernel/return_address.c | 4 ++-- arch/arm/kernel/stacktrace.c | 13 ++++++++++--- arch/arm/lib/backtrace.S | 2 +- arch/arm/net/bpf_jit_32.c | 6 +++--- 8 files changed, 38 insertions(+), 19 deletions(-) diff --git a/arch/arm/Kconfig.debug b/arch/arm/Kconfig.debug index 259c0ca..95b85ee 100644 --- a/arch/arm/Kconfig.debug +++ b/arch/arm/Kconfig.debug @@ -39,9 +39,17 @@ config FRAME_POINTER default y if !ARM_UNWIND || FUNCTION_GRAPH_TRACER help If you say N here, the resulting kernel will be slightly smaller and - faster. However, if neither FRAME_POINTER nor ARM_UNWIND are enabled, - when a problem occurs with the kernel, the information that is - reported is severely limited. + faster. When ARM_UNWIND is disabled, enabling FRAME_POINTER alone is + not sufficient to get meaningful information in case of a kernel bug; + you will also need DEPRECATED_APCS_FRAME. + +config DEPRECATED_APCS_FRAME + bool "Enable deprecated frame format" + depends on FRAME_POINTER + default n + help + Use the legacy APCS frame format. This is required for ftrace with + GCC < 4.4, as well as stack traces without ARM_UNWIND. config ARM_UNWIND bool "Enable stack unwinding support (EXPERIMENTAL)" @@ -56,7 +64,7 @@ config ARM_UNWIND config OLD_MCOUNT bool - depends on FUNCTION_TRACER && FRAME_POINTER + depends on FUNCTION_TRACER && DEPRECATED_APCS_FRAME default y config DEBUG_USER diff --git a/arch/arm/Makefile b/arch/arm/Makefile index 2c2b28e..66a3adc 100644 --- a/arch/arm/Makefile +++ b/arch/arm/Makefile @@ -41,7 +41,11 @@ KBUILD_CFLAGS += $(call cc-option,-mno-unaligned-access) endif ifeq ($(CONFIG_FRAME_POINTER),y) -KBUILD_CFLAGS +=-fno-omit-frame-pointer -mapcs -mno-sched-prolog +KBUILD_CFLAGS +=-fno-omit-frame-pointer -mno-sched-prolog +endif + +ifeq ($(CONFIG_DEPRECATED_APCS_FRAME),y) +KBUILD_CFLAGS +=-mapcs endif ifeq ($(CONFIG_CPU_BIG_ENDIAN),y) diff --git a/arch/arm/include/asm/ftrace.h b/arch/arm/include/asm/ftrace.h index bfe2a2f..a1ad19e 100644 --- a/arch/arm/include/asm/ftrace.h +++ b/arch/arm/include/asm/ftrace.h @@ -32,12 +32,12 @@ extern void ftrace_call_old(void); #ifndef __ASSEMBLY__ -#if defined(CONFIG_FRAME_POINTER) && !defined(CONFIG_ARM_UNWIND) +#if defined(CONFIG_DEPRECATED_APCS_FRAME) && !defined(CONFIG_ARM_UNWIND) /* * return_address uses walk_stackframe to do it's work. If both - * CONFIG_FRAME_POINTER=y and CONFIG_ARM_UNWIND=y walk_stackframe uses unwind - * information. For this to work in the function tracer many functions would - * have to be marked with __notrace. So for now just depend on + * CONFIG_DEPRECATED_APCS_FRAME=y and CONFIG_ARM_UNWIND=y walk_stackframe uses + * unwind information. For this to work in the function tracer many functions + * would have to be marked with __notrace. So for now just depend on * !CONFIG_ARM_UNWIND. */ diff --git a/arch/arm/kernel/entry-ftrace.S b/arch/arm/kernel/entry-ftrace.S index c73c403..b9984b5 100644 --- a/arch/arm/kernel/entry-ftrace.S +++ b/arch/arm/kernel/entry-ftrace.S @@ -53,7 +53,7 @@ #ifndef CONFIG_OLD_MCOUNT #if (__GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 4)) -#error Ftrace requires CONFIG_FRAME_POINTER=y with GCC older than 4.4.0. +#error Ftrace requires CONFIG_DEPRECATED_APCS_FRAME=y with GCC older than 4.4.0. #endif #endif diff --git a/arch/arm/kernel/return_address.c b/arch/arm/kernel/return_address.c index 36ed350..3728026 100644 --- a/arch/arm/kernel/return_address.c +++ b/arch/arm/kernel/return_address.c @@ -11,7 +11,7 @@ #include #include -#if defined(CONFIG_FRAME_POINTER) && !defined(CONFIG_ARM_UNWIND) +#if defined(CONFIG_DEPRECATED_APCS_FRAME) && !defined(CONFIG_ARM_UNWIND) #include #include @@ -56,6 +56,6 @@ void *return_address(unsigned int level) return NULL; } -#endif /* if defined(CONFIG_FRAME_POINTER) && !defined(CONFIG_ARM_UNWIND) */ +#endif /* if defined(CONFIG_DEPRECATED_APCS_FRAME) && !defined(CONFIG_ARM_UNWIND) */ EXPORT_SYMBOL_GPL(return_address); diff --git a/arch/arm/kernel/stacktrace.c b/arch/arm/kernel/stacktrace.c index 92b7237..20e9a7f 100644 --- a/arch/arm/kernel/stacktrace.c +++ b/arch/arm/kernel/stacktrace.c @@ -5,13 +5,14 @@ #include #include -#if defined(CONFIG_FRAME_POINTER) && !defined(CONFIG_ARM_UNWIND) +#ifndef CONFIG_ARM_UNWIND +#ifdef CONFIG_DEPRECATED_APCS_FRAME /* * Unwind the current stack frame and store the new register values in the * structure passed as argument. Unwinding is equivalent to a function return, * hence the new PC value rather than LR should be used for backtrace. * - * With framepointer enabled, a simple function prologue looks like this: + * With APCS frames enabled, a simple function prologue looks like this: * mov ip, sp * stmdb sp!, {fp, ip, lr, pc} * sub fp, ip, #4 @@ -19,7 +20,7 @@ * A simple function epilogue looks like this: * ldm sp, {fp, sp, pc} * - * Note that with framepointer enabled, even the leaf functions have the same + * Note that with APCS frames enabled, even the leaf functions have the same * prologue and epilogue, therefore we can ignore the LR value in this case. */ int notrace unwind_frame(struct stackframe *frame) @@ -42,7 +43,13 @@ int notrace unwind_frame(struct stackframe *frame) return 0; } +#else /* !defined(CONFIG_DEPRECATED_APCS_FRAME) */ +int notrace unwind_frame(struct stackframe *frame) +{ + return -EINVAL; +} #endif +#endif /* !defined(CONFIG_ARM_UNWIND) */ void notrace walk_stackframe(struct stackframe *frame, int (*fn)(struct stackframe *, void *), void *data) diff --git a/arch/arm/lib/backtrace.S b/arch/arm/lib/backtrace.S index fab5a50..3041ccb 100644 --- a/arch/arm/lib/backtrace.S +++ b/arch/arm/lib/backtrace.S @@ -24,7 +24,7 @@ ENTRY(c_backtrace) -#if !defined(CONFIG_FRAME_POINTER) || !defined(CONFIG_PRINTK) +#if !defined(CONFIG_DEPRECATED_APCS_FRAME) || !defined(CONFIG_PRINTK) ret lr ENDPROC(c_backtrace) #else diff --git a/arch/arm/net/bpf_jit_32.c b/arch/arm/net/bpf_jit_32.c index 93d0b6d..8f7b718 100644 --- a/arch/arm/net/bpf_jit_32.c +++ b/arch/arm/net/bpf_jit_32.c @@ -165,7 +165,7 @@ static u16 saved_regs(struct jit_ctx *ctx) (ctx->skf->insns[0].code == (BPF_RET | BPF_A))) ret |= 1 << r_A; -#ifdef CONFIG_FRAME_POINTER +#ifdef CONFIG_DEPRECATED_APCS_FRAME ret |= (1 << ARM_FP) | (1 << ARM_IP) | (1 << ARM_LR) | (1 << ARM_PC); #else if (ctx->seen & SEEN_CALL) @@ -200,7 +200,7 @@ static void build_prologue(struct jit_ctx *ctx) u16 reg_set = saved_regs(ctx); u16 off; -#ifdef CONFIG_FRAME_POINTER +#ifdef CONFIG_DEPRECATED_APCS_FRAME emit(ARM_MOV_R(ARM_IP, ARM_SP), ctx); emit(ARM_PUSH(reg_set), ctx); emit(ARM_SUB_I(ARM_FP, ARM_IP, 4), ctx); @@ -244,7 +244,7 @@ static void build_epilogue(struct jit_ctx *ctx) reg_set &= ~(1 << ARM_LR); -#ifdef CONFIG_FRAME_POINTER +#ifdef CONFIG_DEPRECATED_APCS_FRAME /* the first instruction of the prologue was: mov ip, sp */ reg_set &= ~(1 << ARM_IP); reg_set |= (1 << ARM_SP);