From patchwork Fri Nov 7 14:59:12 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jean-Jacques Hiblot X-Patchwork-Id: 5253751 Return-Path: X-Original-To: patchwork-linux-arm@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork1.web.kernel.org (Postfix) with ESMTP id CB5819F387 for ; Fri, 7 Nov 2014 15:09:59 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id C5AA92012E for ; Fri, 7 Nov 2014 15:09:58 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.9]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 8652620125 for ; Fri, 7 Nov 2014 15:09:56 +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 1Xml8w-0003Sa-BJ; Fri, 07 Nov 2014 15:08:06 +0000 Received: from mail-wi0-f172.google.com ([209.85.212.172]) by bombadil.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1Xml8r-0003H9-GC for linux-arm-kernel@lists.infradead.org; Fri, 07 Nov 2014 15:08:03 +0000 Received: by mail-wi0-f172.google.com with SMTP id bs8so4993716wib.17 for ; Fri, 07 Nov 2014 07:07:39 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=2tQ6moxKKyUPTRHcFypPfxGLki8vjd7Qw1VXnjFg7dQ=; b=c9Vq6hBOj+JPCP3QN35qCJrra7hK8MKnhqOnUR9xXSVYbX7ynaknyfoqc3Ryne3gB6 HBv1Z3/RyNnHCrRs9VQLlNBqnp3xwK+h/Bj75D5gbePMPxjpltGQ37DVqFZkCBoM4y90 rVaSjIq95P/8lhzPV38TOgJnuYMqENNjURT7iAvdY/bYJOAHTWD7qBhGKZ+NMCE8WPxN 6B496rI2mg7OwTaT4mU4MmqyPrzRu20CUH6PrXCCspTGyKZfkSF15vFUpGZ6KCzS5DBt QvVC/n3UpeGiE/7QScvD7l4RqbZhL7Ob8cgfgkYLYTLHYHdCXMvwuZ7ytO/KOEG3URrs rhXQ== X-Received: by 10.180.182.195 with SMTP id eg3mr5942909wic.31.1415372504700; Fri, 07 Nov 2014 07:01:44 -0800 (PST) Received: from laptrap.localdomain (sch42-5-78-217-165-73.fbx.proxad.net. [78.217.165.73]) by mx.google.com with ESMTPSA id mw7sm2346467wib.14.2014.11.07.07.01.43 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Fri, 07 Nov 2014 07:01:44 -0800 (PST) From: Jean-Jacques Hiblot To: jslaby@suse.cz, linux@arm.linux.org.uk, rostedt@goodmis.org, mingo@redhat.com, nsekhar@ti.com, stefano.stabellini@eu.citrix.com, christoffer.dall@linaro.org Subject: [PATCH 01/01] arm: ftrace: Adds support for ftrace operations Date: Fri, 7 Nov 2014 15:59:12 +0100 Message-Id: <1415372352-15664-2-git-send-email-jjhiblot@traphandler.com> X-Mailer: git-send-email 2.1.3 In-Reply-To: <1415372352-15664-1-git-send-email-jjhiblot@traphandler.com> References: <1415372352-15664-1-git-send-email-jjhiblot@traphandler.com> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20141107_070801_841786_4E6D1D4C X-CRM114-Status: GOOD ( 16.36 ) X-Spam-Score: -0.7 (/) Cc: Jean-Jacques Hiblot , linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org 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+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Spam-Status: No, score=-2.5 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_NONE, 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 Ftrace operations require that DYNAMIC_FTRACE_WITH_REGS is enabled. This patch introduces a new ftrace handler that store the registers on the stack before calling the next stage. The registers are also restored from the stack before going back to the instrumented function. Signed-off-by: Jean-Jacques Hiblot --- arch/arm/Kconfig | 2 ++ arch/arm/include/asm/ftrace.h | 3 ++ arch/arm/kernel/entry-common.S | 68 +++++++++++++++++++++++++++++++++++++++++- arch/arm/kernel/ftrace.c | 34 +++++++++++++++++++++ 4 files changed, 106 insertions(+), 1 deletion(-) diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 32cbbd5..6f928ee 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -39,6 +39,7 @@ config ARM select HAVE_DMA_ATTRS select HAVE_DMA_CONTIGUOUS if MMU select HAVE_DYNAMIC_FTRACE if (!XIP_KERNEL) + select HAVE_DYNAMIC_FTRACE_WITH_REGS if HAVE_DYNAMIC_FTRACE select HAVE_EFFICIENT_UNALIGNED_ACCESS if (CPU_V6 || CPU_V6K || CPU_V7) && MMU select HAVE_FTRACE_MCOUNT_RECORD if (!XIP_KERNEL) select HAVE_FUNCTION_GRAPH_TRACER if (!THUMB2_KERNEL) @@ -72,6 +73,7 @@ config ARM select PERF_USE_VMALLOC select RTC_LIB select SYS_SUPPORTS_APM_EMULATION + select FRAME_POINTER if DYNAMIC_FTRACE_WITH_REGS && FUNCTION_GRAPH_TRACER # Above selects are sorted alphabetically; please add new ones # according to that. Thanks. help diff --git a/arch/arm/include/asm/ftrace.h b/arch/arm/include/asm/ftrace.h index 39eb16b..d8e9bea 100644 --- a/arch/arm/include/asm/ftrace.h +++ b/arch/arm/include/asm/ftrace.h @@ -10,6 +10,9 @@ extern void mcount(void); extern void __gnu_mcount_nc(void); #ifdef CONFIG_DYNAMIC_FTRACE + +#define ARCH_SUPPORTS_FTRACE_OPS 1 + struct dyn_arch_ftrace { #ifdef CONFIG_OLD_MCOUNT bool old_mcount; diff --git a/arch/arm/kernel/entry-common.S b/arch/arm/kernel/entry-common.S index e52fe5a..9594fe2 100644 --- a/arch/arm/kernel/entry-common.S +++ b/arch/arm/kernel/entry-common.S @@ -197,7 +197,10 @@ ENDPROC(ret_from_fork) mcount_get_lr r1 @ lr of instrumented func mcount_adjust_addr r0, lr @ instrumented function - + ldr r2, =function_trace_op + ldr r2, [r2] @ pointer to the current + @ function tracing op + mov r3, #0 @ regs is NULL .globl ftrace_call\suffix ftrace_call\suffix: bl ftrace_stub @@ -211,6 +214,38 @@ ftrace_graph_call\suffix: mcount_exit .endm +.macro __ftrace_regs_caller + + add ip, sp, #4 @ move in IP the value of SP as it was + @ before the push {lr} of the mcount mechanism + stmdb sp!, {ip,lr,pc} + stmdb sp!, {r0-r11,lr} + @ stack content at this point: + @ 0 4 44 48 52 56 60 64 + @ RO | R1 | ... | R11 | LR | SP + 4 | LR | PC | previous LR | + + mov r3, sp @ struct pt_regs* + ldr r2, =function_trace_op + ldr r2, [r2] @ pointer to the current + @ function tracing op + ldr r1, [sp, #64] @ lr of instrumented func + mcount_adjust_addr r0, lr @ instrumented function + + .globl ftrace_regs_call +ftrace_regs_call: + bl ftrace_stub + +#ifdef CONFIG_FUNCTION_GRAPH_TRACER + .globl ftrace_graph_regs_call +ftrace_graph_regs_call: + mov r0, r0 +#endif + ldr lr, [sp, #64] @ get the previous LR value from stack + ldmia sp, {r0-r11, ip, sp} @ pop the saved registers INCLUDING + @ the stack pointer + ret ip +.endm + .macro __ftrace_graph_caller sub r0, fp, #4 @ &lr of instrumented routine (&parent) #ifdef CONFIG_DYNAMIC_FTRACE @@ -226,6 +261,24 @@ ftrace_graph_call\suffix: mcount_exit .endm + +.macro __ftrace_graph_regs_caller + + sub r0, fp, #4 @ &lr of instrumented routine (&parent) + + @ called from __ftrace_regs_caller + ldr r1, [sp, #56] @ instrumented routine (func) + mcount_adjust_addr r1, r1 + + mov r2, fp @ frame pointer + bl prepare_ftrace_return + + ldr lr, [fp, #-4] @ restore LR from the stack + ldmia sp, {r0-r11, ip, sp} @ pop the saved registers INCLUDING + @ the stack pointer + ret ip +.endm + #ifdef CONFIG_OLD_MCOUNT /* * mcount @@ -312,14 +365,27 @@ UNWIND(.fnstart) __ftrace_caller UNWIND(.fnend) ENDPROC(ftrace_caller) + +ENTRY(ftrace_regs_caller) +UNWIND(.fnstart) + __ftrace_regs_caller +UNWIND(.fnend) +ENDPROC(ftrace_regs_caller) #endif + #ifdef CONFIG_FUNCTION_GRAPH_TRACER ENTRY(ftrace_graph_caller) UNWIND(.fnstart) __ftrace_graph_caller UNWIND(.fnend) ENDPROC(ftrace_graph_caller) + +ENTRY(ftrace_graph_regs_caller) +UNWIND(.fnstart) + __ftrace_graph_regs_caller +UNWIND(.fnend) +ENDPROC(ftrace_graph_regs_caller) #endif .purgem mcount_enter diff --git a/arch/arm/kernel/ftrace.c b/arch/arm/kernel/ftrace.c index af9a8a9..35c5743 100644 --- a/arch/arm/kernel/ftrace.c +++ b/arch/arm/kernel/ftrace.c @@ -130,6 +130,16 @@ int ftrace_update_ftrace_func(ftrace_func_t func) } #endif + +#ifdef CONFIG_DYNAMIC_FTRACE_WITH_REGS + if (!ret) { + pc = (unsigned long)&ftrace_regs_call; + new = ftrace_call_replace(pc, (unsigned long)func); + + ret = ftrace_modify_code(pc, 0, new, false); + } +#endif + return ret; } @@ -139,6 +149,20 @@ int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr) unsigned long ip = rec->ip; old = ftrace_nop_replace(rec); + + new = ftrace_call_replace(ip, adjust_address(rec, addr)); + + return ftrace_modify_code(rec->ip, old, new, true); +} + +int ftrace_modify_call(struct dyn_ftrace *rec, unsigned long old_addr, + unsigned long addr) +{ + unsigned long new, old; + unsigned long ip = rec->ip; + + old = ftrace_call_replace(ip, adjust_address(rec, old_addr)); + new = ftrace_call_replace(ip, adjust_address(rec, addr)); return ftrace_modify_code(rec->ip, old, new, true); @@ -211,6 +235,9 @@ void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr, extern unsigned long ftrace_graph_call; extern unsigned long ftrace_graph_call_old; extern void ftrace_graph_caller_old(void); +extern unsigned long ftrace_graph_regs_call; +extern void ftrace_graph_regs_caller(void); + static int __ftrace_modify_caller(unsigned long *callsite, void (*func) (void), bool enable) @@ -240,6 +267,13 @@ static int ftrace_modify_graph_caller(bool enable) enable); #endif +#ifdef CONFIG_DYNAMIC_FTRACE_WITH_REGS + if (!ret) + ret = __ftrace_modify_caller(&ftrace_graph_regs_call, + ftrace_graph_regs_caller, + enable); +#endif + return ret; }