All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 0/6] arm64: Add ftrace support
@ 2013-10-24  7:08 AKASHI Takahiro
  2013-10-24  7:08 ` [PATCH v2 1/6] " AKASHI Takahiro
                   ` (6 more replies)
  0 siblings, 7 replies; 235+ messages in thread
From: AKASHI Takahiro @ 2013-10-24  7:08 UTC (permalink / raw)
  To: linux-arm-kernel

This is my second version of patchset for ftrace support.
Actually v1 was submitted serveral weeks ago, but is still moderated.
(Just ignore them for now.)
There is another implementation from Cavium network, but both works
are independent, and my code has additional system call trace support.

I confirmed that I could compile the patches on v3.12-rc4 by Linaro's
coming 2013.10 gcc (4.8.2), and that the kernel worked on Fast Model
with the following tracers:
     function tracer with dynamic ftrace
     function graph tracer with dynamic ftrace
     syscall tracepoint
     irqsoff & preemptirqsoff (which use CALLER_ADDRx)
Also verified with in-kernel tests, FTRACE_SELFTEST, FTRACE_STARTUP_TEST
and EVENT_TRACE_TEST_SYSCALLS.

Patch[3/6] has warnings from checkpatch, but they follow other arch's style.

Please be careful that host's elf.h must have AArch64 definitions,
EM_AARCH64 and R_AARCH64_ABS64, to build the kernel. See [4/6].

Issues
* Can we optimize register usages in asm (by not saving x0, x1 and x2)? [1/6]
* Do we need "fault protection" code in ftrace_modify_code()? [1/6]
  It exists in x86 and other architectures, but not in arm.
* We may be able to use aarch64_insn_patch_text_nosync() instead of
  ftrace_modify_code().[2/6] But the former function does not use
  probe_kernel_write(). Is this safe?

Changes from v1 to v2:
* splitted one patch into some pieces for easier review
  (especially function tracer + dynamic ftrace + CALLER_ADDRx)
* put return_address() in a separate file
* renamed __mcount to _mcount (it was my mistake)
* changed stackframe handling to get parent's frame pointer
* removed ARCH_SUPPORTS_FTRACE_OPS
* switched to "hotpatch" interfaces from Huawai
* revised descriptions in comments

AKASHI Takahiro (6):
  arm64: Add ftrace support
  arm64: ftrace: Add dynamic ftrace support
  arm64: ftrace: Add CALLER_ADDRx macros
  ftrace: Add arm64 support to recordmcount
  arm64: ftrace: Add system call tracepoint
  arm64: Add 'notrace' attribute to unwind_frame() for ftrace

 arch/arm64/Kconfig                   |    6 +
 arch/arm64/include/asm/ftrace.h      |   54 +++++++++
 arch/arm64/include/asm/syscall.h     |    1 +
 arch/arm64/include/asm/thread_info.h |    1 +
 arch/arm64/include/asm/unistd.h      |    2 +
 arch/arm64/kernel/Makefile           |    9 +-
 arch/arm64/kernel/arm64ksyms.c       |    4 +
 arch/arm64/kernel/entry-ftrace.S     |  211 ++++++++++++++++++++++++++++++++++
 arch/arm64/kernel/entry.S            |    1 +
 arch/arm64/kernel/ftrace.c           |  186 ++++++++++++++++++++++++++++++
 arch/arm64/kernel/ptrace.c           |   10 ++
 arch/arm64/kernel/return_address.c   |   55 +++++++++
 arch/arm64/kernel/stacktrace.c       |    2 +-
 scripts/recordmcount.c               |    4 +
 scripts/recordmcount.pl              |    5 +
 15 files changed, 549 insertions(+), 2 deletions(-)
 create mode 100644 arch/arm64/include/asm/ftrace.h
 create mode 100644 arch/arm64/kernel/entry-ftrace.S
 create mode 100644 arch/arm64/kernel/ftrace.c
 create mode 100644 arch/arm64/kernel/return_address.c

-- 
1.7.9.5

^ permalink raw reply	[flat|nested] 235+ messages in thread

* [PATCH v2 1/6] arm64: Add ftrace support
  2013-10-24  7:08 [PATCH v2 0/6] arm64: Add ftrace support AKASHI Takahiro
@ 2013-10-24  7:08 ` AKASHI Takahiro
  2013-10-24  7:08 ` [PATCH v2 2/6] arm64: ftrace: Add dynamic " AKASHI Takahiro
                   ` (5 subsequent siblings)
  6 siblings, 0 replies; 235+ messages in thread
From: AKASHI Takahiro @ 2013-10-24  7:08 UTC (permalink / raw)
  To: linux-arm-kernel

This enables FUNCTION_TRACER and FUNCTION_GRAPH_TRACER, and also
provides the base for other tracers which depend on FUNCTION_TRACER.

_mcount() is the entry point which is inserted at the very beginning
of every function by gcc with -pg option.
function graph tracer intercepts instrumented function's return path
by faking the return address (lr) stored in stack in order to trace
a call graph.

See Documentation/trace/ftrace-design.txt

Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
---
 arch/arm64/Kconfig               |    2 +
 arch/arm64/include/asm/ftrace.h  |   23 +++++
 arch/arm64/kernel/Makefile       |    6 ++
 arch/arm64/kernel/arm64ksyms.c   |    4 +
 arch/arm64/kernel/entry-ftrace.S |  172 ++++++++++++++++++++++++++++++++++++++
 arch/arm64/kernel/ftrace.c       |   83 ++++++++++++++++++
 6 files changed, 290 insertions(+)
 create mode 100644 arch/arm64/include/asm/ftrace.h
 create mode 100644 arch/arm64/kernel/entry-ftrace.S
 create mode 100644 arch/arm64/kernel/ftrace.c

diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index da388e4..3776319 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -23,6 +23,8 @@ config ARM64
 	select HAVE_DEBUG_KMEMLEAK
 	select HAVE_DMA_API_DEBUG
 	select HAVE_DMA_ATTRS
+	select HAVE_FUNCTION_TRACER
+	select HAVE_FUNCTION_GRAPH_TRACER
 	select HAVE_GENERIC_DMA_COHERENT
 	select HAVE_HW_BREAKPOINT if PERF_EVENTS
 	select HAVE_MEMBLOCK
diff --git a/arch/arm64/include/asm/ftrace.h b/arch/arm64/include/asm/ftrace.h
new file mode 100644
index 0000000..0d5dfdb
--- /dev/null
+++ b/arch/arm64/include/asm/ftrace.h
@@ -0,0 +1,23 @@
+/*
+ * arch/arm64/include/asm/ftrace.h
+ *
+ * Copyright (C) 2013 Linaro Limited
+ * Author: AKASHI Takahiro <takahiro.akashi@linaro.org>
+ *
+ * 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.
+ */
+#ifndef __ASM_FTRACE_H
+#define __ASM_FTRACE_H
+
+#ifdef CONFIG_FUNCTION_TRACER
+#define MCOUNT_ADDR		((unsigned long)_mcount)
+#define MCOUNT_INSN_SIZE	4 /* sizeof mcount call */
+
+#ifndef __ASSEMBLY__
+extern void _mcount(unsigned long);
+#endif /* __ASSEMBLY__ */
+#endif /* CONFIG_FUNCTION_TRACER */
+
+#endif /* __ASM_FTRACE_H */
diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile
index b7db65e..92429e4 100644
--- a/arch/arm64/kernel/Makefile
+++ b/arch/arm64/kernel/Makefile
@@ -5,6 +5,11 @@
 CPPFLAGS_vmlinux.lds	:= -DTEXT_OFFSET=$(TEXT_OFFSET)
 AFLAGS_head.o		:= -DTEXT_OFFSET=$(TEXT_OFFSET)
 
+ifdef CONFIG_FUNCTION_TRACER
+CFLAGS_REMOVE_ftrace.o = -pg
+CFLAGS_REMOVE_insn.o = -pg
+endif
+
 # Object file lists.
 arm64-obj-y		:= cputable.o debug-monitors.o entry.o irq.o fpsimd.o	\
 			   entry-fpsimd.o process.o ptrace.o setup.o signal.o	\
@@ -13,6 +18,7 @@ arm64-obj-y		:= cputable.o debug-monitors.o entry.o irq.o fpsimd.o	\
 
 arm64-obj-$(CONFIG_COMPAT)		+= sys32.o kuser32.o signal32.o 	\
 					   sys_compat.o
+arm64-obj-$(CONFIG_FUNCTION_TRACER)	+= ftrace.o entry-ftrace.o
 arm64-obj-$(CONFIG_MODULES)		+= arm64ksyms.o module.o
 arm64-obj-$(CONFIG_SMP)			+= smp.o smp_spin_table.o smp_psci.o
 arm64-obj-$(CONFIG_HW_PERF_EVENTS)	+= perf_event.o
diff --git a/arch/arm64/kernel/arm64ksyms.c b/arch/arm64/kernel/arm64ksyms.c
index 41b4f62..ef9b63d 100644
--- a/arch/arm64/kernel/arm64ksyms.c
+++ b/arch/arm64/kernel/arm64ksyms.c
@@ -58,3 +58,7 @@ EXPORT_SYMBOL(clear_bit);
 EXPORT_SYMBOL(test_and_clear_bit);
 EXPORT_SYMBOL(change_bit);
 EXPORT_SYMBOL(test_and_change_bit);
+
+#ifdef CONFIG_FUNCTION_TRACER
+EXPORT_SYMBOL(_mcount);
+#endif
diff --git a/arch/arm64/kernel/entry-ftrace.S b/arch/arm64/kernel/entry-ftrace.S
new file mode 100644
index 0000000..ae14ece
--- /dev/null
+++ b/arch/arm64/kernel/entry-ftrace.S
@@ -0,0 +1,172 @@
+/*
+ * arch/arm64/kernel/entry-ftrace.S
+ *
+ * Copyright (C) 2013 Linaro Limited
+ * Author: AKASHI Takahiro <takahiro.akashi@linaro.org>
+ *
+ * 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 <linux/linkage.h>
+#include <asm/ftrace.h>
+
+/*
+ * Gcc with -pg will put the following code in the beginning of each function:
+ *      mov x0, x30
+ *      bl _mcount
+ * On contrary to tricky arm(32) implementation, this is a normal function
+ * call and so x0 & x30 will be safely saved and restored around tracer
+ * call (_mcount/ftrace_caller) in an instrumented function (callsite).
+ *
+ * stack layout:
+ *   0 ---------------------------------------- sp in tracer function
+ *      x29: fp in instrumented function	fp is not winded
+ *     --------------------
+ *      x30: lr in tracer function
+ * +16 --------------------
+ *      x0: arg 0 (lr in instrumented function)
+ *     --------------------
+ *      x1 (temporary)
+ * +32 --------------------
+ *      x2 (temporary)
+ *     --------------------
+ *      (don't care)
+ * +48 ---------------------------------------- sp in instrumented function
+ *
+ *     ....
+ *
+ * +xx ---------------------------------------- fp in instrumented function
+ *      x29: fp in parent function
+ *     --------------------
+ *      x30: lr in insturmented function
+ *     --------------------
+ *      xxx
+ */
+
+	.macro mcount_enter
+	stp	x29, x30, [sp, #-48]!
+	stp	x0, x1,   [sp, #16]
+	str	x2,       [sp, #32]
+	.endm
+
+	.macro mcount_exit
+	ldr	x2,       [sp, #32]
+	ldp	x0, x1,   [sp, #16]
+	ldp	x29, x30, [sp], #48
+	ret
+	.endm
+
+	.macro mcount_adjust_addr rd, rn
+	sub	\rd, \rn, #MCOUNT_INSN_SIZE
+	.endm
+
+	/* for instrumented function's parent */
+	.macro mcount_get_parent_fp reg
+	ldr	\reg, [sp]
+	ldr	\reg, [\reg]
+	.endm
+
+	/* for instrumented function */
+	.macro mcount_get_pc0 reg
+	mcount_adjust_addr	\reg, x30
+	.endm
+
+	.macro mcount_get_pc reg
+	ldr	\reg, [sp, #8]
+	mcount_adjust_addr	\reg, \reg
+	.endm
+
+	.macro mcount_get_lr reg
+	ldr	\reg, [sp, #16]
+	mcount_adjust_addr	\reg, \reg
+	.endm
+
+	.macro mcount_get_saved_lr_addr reg
+	ldr	\reg, [sp]
+	add	\reg, \reg, #8
+	.endm
+
+/*
+ * void _mcount(unsigned long return_address)
+ * @return_address: return address to instrumented function (callsite)
+ */
+ENTRY(_mcount)
+#ifdef CONFIG_HAVE_FUNCTION_TRACE_MCOUNT_TEST
+	ldr	x0, =ftrace_trace_stop
+	ldr	x0, [x0]		// if ftrace_trace_stop
+	ret				//   return;
+#endif
+	mcount_enter
+
+	ldr	x0, =ftrace_trace_function
+	ldr	x2, [x0]
+	adr	x0, ftrace_stub
+	cmp	x0, x2			// if (ftrace_trace_function
+	b.eq	skip_ftrace_call	//     != ftrace_stub) {
+
+	mcount_get_pc	x0		//       pc in callsite
+	mcount_get_lr	x1		//       callsite's lr (adjusted)
+	blr	x2			//   (*ftrace_trace_function)(pc, lr);
+
+#ifndef CONFIG_FUNCTION_GRAPH_TRACER
+skip_ftrace_call:			//   return;
+	mcount_exit			// }
+#else
+	mcount_exit			//   return;
+					// }
+skip_ftrace_call:
+	ldr	x1, =ftrace_graph_return
+	ldr	x2, [x1]		//   if ((ftrace_graph_return
+	cmp	x0, x2			//        != ftrace_stub)
+	b.ne	ftrace_graph_caller
+
+	ldr	x1, =ftrace_graph_entry	//     || (ftrace_graph_entry
+	ldr	x2, [x1]		//        != ftrace_graph_entry_stub))
+	ldr	x0, =ftrace_graph_entry_stub
+	cmp	x0, x2
+	b.ne	ftrace_graph_caller	//     ftrace_graph_caller();
+
+	mcount_exit
+#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
+ENDPROC(_mcount)
+
+ENTRY(ftrace_stub)
+	ret
+ENDPROC(ftrace_stub)
+
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+/*
+ * void ftrace_graph_caller(void)
+ *
+ * This function fakes instrumented function's return address to make a hook
+ * on function return path by calling prepare_ftrace_return(). This function
+ * is assumed to be jumped into from  _mcount() or ftrace_caller() and so no
+ * context need be saved here.
+ */
+ENTRY(ftrace_graph_caller)
+	mcount_get_saved_lr_addr  x0	//     pointer to callsite's saved lr
+	mcount_get_pc		  x1	//     pc in callsite
+	mcount_get_parent_fp	  x2	//     parent's fp
+	bl	prepare_ftrace_return	// prepare_ftrace_return(&lr, pc, fp)
+
+	mcount_exit
+ENDPROC(ftrace_graph_caller)
+
+/*
+ * void return_to_handler(void)
+ *
+ * return hook handler
+ * @fp is used to check against the value specified in ftrace_graph_caller()
+ * only when CONFIG_FUNCTION_GRAPH_FP_TEST is enabled.
+ */
+	.global return_to_handler
+return_to_handler:
+	str	x0, [sp, #-16]!
+	mov	x0, x29			//     parent's fp
+	bl	ftrace_return_to_handler// addr = ftrace_return_to_hander(fp);
+	mov	x30, x0			// restore the original return address
+	ldr	x0, [sp], #16
+	ret
+#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
diff --git a/arch/arm64/kernel/ftrace.c b/arch/arm64/kernel/ftrace.c
new file mode 100644
index 0000000..e779e16
--- /dev/null
+++ b/arch/arm64/kernel/ftrace.c
@@ -0,0 +1,83 @@
+/*
+ * arch/arm64/kernel/ftrace.c
+ *
+ * Copyright (C) 2013 Linaro Limited
+ * Author: AKASHI Takahiro <takahiro.akashi@linaro.org>
+ *
+ * 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 <linux/ftrace.h>
+#include <linux/swab.h>
+#include <linux/uaccess.h>
+
+#include <asm/cacheflush.h>
+#include <asm/ftrace.h>
+#include <asm/insn.h>
+
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr,
+			   unsigned long frame_pointer)
+{
+	unsigned long return_hooker = (unsigned long)&return_to_handler;
+	unsigned long old, faulted;
+	struct ftrace_graph_ent trace;
+	int err;
+
+	if (unlikely(atomic_read(&current->tracing_graph_pause)))
+		return;
+
+#if 1 /* FIXME */
+	/*
+	 * Protect against fault, even if it shouldn't
+	 * happen. This tool is too much intrusive to
+	 * ignore such a protection.
+	 * Actually we want to do
+	 *     old = *parent;
+	 *     parent = return_hooker;
+	 */
+	asm volatile(
+"1:	ldr	%0, [%2]\n"
+"2:	str	%3, [%2]\n"
+"	mov	%1, #0\n"
+"3:\n"
+"	.pushsection .fixup, \"ax\"\n"
+"4:	mov	%1, #1\n"
+"	b	3b\n"
+"	.popsection\n"
+"	.pushsection __ex_table, \"a\"\n"
+"	.align 3\n"
+"	.quad 1b, 4b, 2b, 4b\n"
+"	.popsection\n"
+	: "=&r" (old), "=r" (faulted) : "r" (parent), "r" (return_hooker)
+	);
+
+	if (unlikely(faulted)) {
+		ftrace_graph_stop();
+		WARN_ON(1);
+		return;
+	}
+#else
+	old = *parent;
+	*parent = return_hooker;
+#endif
+
+	trace.func = self_addr;
+	trace.depth = current->curr_ret_stack + 1;
+
+	/* Only trace if the calling function expects to */
+	if (!ftrace_graph_entry(&trace)) {
+		*parent = old;
+		return;
+	}
+
+	err = ftrace_push_return_trace(old, self_addr, &trace.depth,
+				       frame_pointer);
+	if (err == -EBUSY) {
+		*parent = old;
+		return;
+	}
+}
+#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 235+ messages in thread

* [PATCH v2 2/6] arm64: ftrace: Add dynamic ftrace support
  2013-10-24  7:08 [PATCH v2 0/6] arm64: Add ftrace support AKASHI Takahiro
  2013-10-24  7:08 ` [PATCH v2 1/6] " AKASHI Takahiro
@ 2013-10-24  7:08 ` AKASHI Takahiro
  2013-10-24  7:08 ` [PATCH v2 3/6] arm64: ftrace: Add CALLER_ADDRx macros AKASHI Takahiro
                   ` (4 subsequent siblings)
  6 siblings, 0 replies; 235+ messages in thread
From: AKASHI Takahiro @ 2013-10-24  7:08 UTC (permalink / raw)
  To: linux-arm-kernel

This enables DYNAMIC_FTRACE configuration.
ftrace_caller() is the entry function which is a replacement of _mcount().
If tracing is enabled on a function, the branch instruction to _mcount()
is replaced to that of ftace_caller() and if disabled, replaced to nop.

See Documentation/trace/ftrace-design.txt

Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
---
 arch/arm64/Kconfig               |    1 +
 arch/arm64/include/asm/ftrace.h  |   17 +++++++
 arch/arm64/kernel/entry-ftrace.S |   39 +++++++++++++++
 arch/arm64/kernel/ftrace.c       |  103 ++++++++++++++++++++++++++++++++++++++
 4 files changed, 160 insertions(+)

diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 3776319..c150430 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -23,6 +23,7 @@ config ARM64
 	select HAVE_DEBUG_KMEMLEAK
 	select HAVE_DMA_API_DEBUG
 	select HAVE_DMA_ATTRS
+	select HAVE_DYNAMIC_FTRACE
 	select HAVE_FUNCTION_TRACER
 	select HAVE_FUNCTION_GRAPH_TRACER
 	select HAVE_GENERIC_DMA_COHERENT
diff --git a/arch/arm64/include/asm/ftrace.h b/arch/arm64/include/asm/ftrace.h
index 0d5dfdb..37a379d 100644
--- a/arch/arm64/include/asm/ftrace.h
+++ b/arch/arm64/include/asm/ftrace.h
@@ -17,6 +17,23 @@
 
 #ifndef __ASSEMBLY__
 extern void _mcount(unsigned long);
+
+#ifdef CONFIG_DYNAMIC_FTRACE
+struct dyn_arch_ftrace {
+	/* No extra data needed for arm64 */
+};
+
+extern unsigned long ftrace_graph_call;
+
+static inline unsigned long ftrace_call_adjust(unsigned long addr)
+{
+	/*
+	 * addr is the address of the mcount call instruction.
+	 * recordmcount does the necessary offset calculation.
+	 */
+	return addr;
+}
+#endif /* CONFIG_DYNAMIC_FTRACE */
 #endif /* __ASSEMBLY__ */
 #endif /* CONFIG_FUNCTION_TRACER */
 
diff --git a/arch/arm64/kernel/entry-ftrace.S b/arch/arm64/kernel/entry-ftrace.S
index ae14ece..c35c650 100644
--- a/arch/arm64/kernel/entry-ftrace.S
+++ b/arch/arm64/kernel/entry-ftrace.S
@@ -88,6 +88,7 @@
 	add	\reg, \reg, #8
 	.endm
 
+#ifndef CONFIG_DYNAMIC_FTRACE
 /*
  * void _mcount(unsigned long return_address)
  * @return_address: return address to instrumented function (callsite)
@@ -132,6 +133,44 @@ skip_ftrace_call:
 #endif /* CONFIG_FUNCTION_GRAPH_TRACER */
 ENDPROC(_mcount)
 
+#else /* CONFIG_DYNAMIC_FTRACE */
+/*
+ * This code is executed only at boot time.
+ * Once after initialized, "bl _mcount" generated by gcc -pg option will be
+ * replaced to "nop" if tracing is disabled or "b ftrace_caller" if enabled.
+ */
+ENTRY(_mcount)
+	ret
+ENDPROC(_mcount)
+
+/*
+ * void ftrace_caller(unsigned long return_address)
+ * @return_address: return address to instrumented function (callsite)
+ *
+ * Call any kind of tracer function and/or function graph tracer.
+ */
+ENTRY(ftrace_caller)
+	mcount_enter
+
+	mcount_get_pc0	x0		//     pc in callsite
+	mcount_get_lr	x1		//     callsite's lr (adjusted)
+
+	.global ftrace_call
+ftrace_call:				// tracer(pc, lr);
+	nop				// This will be replaced with "bl xxx"
+					// where xxx can be any kind of tracer.
+
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+	.global ftrace_graph_call
+ftrace_graph_call:			// ftrace_graph_caller();
+	nop				// If enabled, this will be replaced
+					// "b ftrace_graph_caller"
+#endif
+
+	mcount_exit
+ENDPROC(ftrace_caller)
+#endif /* CONFIG_DYNAMIC_FTRACE */
+
 ENTRY(ftrace_stub)
 	ret
 ENDPROC(ftrace_stub)
diff --git a/arch/arm64/kernel/ftrace.c b/arch/arm64/kernel/ftrace.c
index e779e16..da481c1 100644
--- a/arch/arm64/kernel/ftrace.c
+++ b/arch/arm64/kernel/ftrace.c
@@ -17,6 +17,76 @@
 #include <asm/ftrace.h>
 #include <asm/insn.h>
 
+#ifdef CONFIG_DYNAMIC_FTRACE
+/* FIXME: can be replaced by aarch64_insn_patch_text_nosync() */
+static int ftrace_modify_code(unsigned long pc, unsigned int old,
+			      unsigned int new, bool validate)
+{
+	unsigned int replaced;
+
+#ifdef __AARCH64EB__
+	old = swab32(old);
+	new = swab32(new);
+#endif
+
+	if (validate) {
+		if (probe_kernel_read(&replaced, (void *)pc, MCOUNT_INSN_SIZE))
+			return -EFAULT;
+
+		if (replaced != old)
+			return -EINVAL;
+	}
+
+	if (probe_kernel_write((void *)pc, &new, MCOUNT_INSN_SIZE))
+		return -EPERM;
+
+	flush_icache_range(pc, pc + MCOUNT_INSN_SIZE);
+
+	return 0;
+}
+
+int ftrace_update_ftrace_func(ftrace_func_t func)
+{
+	unsigned long pc;
+	unsigned int new;
+
+	pc = (unsigned long)&ftrace_call;
+	new = aarch64_insn_gen_branch_imm(pc, (unsigned long)func, true);
+
+	return ftrace_modify_code(pc, 0, new, false);
+}
+
+int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
+{
+	unsigned long pc = rec->ip;
+	unsigned int old, new;
+
+	old = aarch64_insn_gen_nop();
+	new = aarch64_insn_gen_branch_imm(pc, addr, true);
+
+	return ftrace_modify_code(pc, old, new, true);
+}
+
+int ftrace_make_nop(struct module *mod,
+		    struct dyn_ftrace *rec, unsigned long addr)
+{
+	unsigned long pc = rec->ip;
+	unsigned int old, new;
+
+	old = aarch64_insn_gen_branch_imm(pc, addr, true);
+	new = aarch64_insn_gen_nop();
+
+	return ftrace_modify_code(pc, old, new, true);
+}
+
+int __init ftrace_dyn_arch_init(void *data)
+{
+	*(unsigned long *)data = 0;
+
+	return 0;
+}
+#endif /* CONFIG_DYNAMIC_FTRACE */
+
 #ifdef CONFIG_FUNCTION_GRAPH_TRACER
 void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr,
 			   unsigned long frame_pointer)
@@ -80,4 +150,37 @@ void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr,
 		return;
 	}
 }
+
+#ifdef CONFIG_DYNAMIC_FTRACE
+static int __ftrace_modify_caller(unsigned long *callsite,
+				  void (*func) (void), bool enable)
+{
+	unsigned long pc = (unsigned long)callsite;
+	unsigned int branch, nop, old, new;
+
+	branch = aarch64_insn_gen_branch_imm(pc, (unsigned long)func, false);
+	nop = aarch64_insn_gen_nop();
+	old = enable ? nop : branch;
+	new = enable ? branch : nop;
+
+	return ftrace_modify_code(pc, old, new, true);
+}
+
+static int ftrace_modify_graph_caller(bool enable)
+{
+	return __ftrace_modify_caller(&ftrace_graph_call,
+				     ftrace_graph_caller,
+				     enable);
+}
+
+int ftrace_enable_ftrace_graph_caller(void)
+{
+	return ftrace_modify_graph_caller(true);
+}
+
+int ftrace_disable_ftrace_graph_caller(void)
+{
+	return ftrace_modify_graph_caller(false);
+}
+#endif /* CONFIG_DYNAMIC_FTRACE */
 #endif /* CONFIG_FUNCTION_GRAPH_TRACER */
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 235+ messages in thread

* [PATCH v2 3/6] arm64: ftrace: Add CALLER_ADDRx macros
  2013-10-24  7:08 [PATCH v2 0/6] arm64: Add ftrace support AKASHI Takahiro
  2013-10-24  7:08 ` [PATCH v2 1/6] " AKASHI Takahiro
  2013-10-24  7:08 ` [PATCH v2 2/6] arm64: ftrace: Add dynamic " AKASHI Takahiro
@ 2013-10-24  7:08 ` AKASHI Takahiro
  2013-10-24  7:08 ` [PATCH v2 4/6] ftrace: Add arm64 support to recordmcount AKASHI Takahiro
                   ` (3 subsequent siblings)
  6 siblings, 0 replies; 235+ messages in thread
From: AKASHI Takahiro @ 2013-10-24  7:08 UTC (permalink / raw)
  To: linux-arm-kernel

These macro's unwind call stacks and return the specified caller address.
They are used for several tracers like irqsoff and preemptoff.
Strange to say, however, they are refered even without FTRACE.

Please not that this implementation assumes that we have frame pointers.
(which means kernel should be compiled with -fno-omit-frame-pointer.)

Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
---
 arch/arm64/include/asm/ftrace.h    |   14 +++++++++
 arch/arm64/kernel/Makefile         |    3 +-
 arch/arm64/kernel/return_address.c |   55 ++++++++++++++++++++++++++++++++++++
 3 files changed, 71 insertions(+), 1 deletion(-)
 create mode 100644 arch/arm64/kernel/return_address.c

diff --git a/arch/arm64/include/asm/ftrace.h b/arch/arm64/include/asm/ftrace.h
index 37a379d..4c6ac03 100644
--- a/arch/arm64/include/asm/ftrace.h
+++ b/arch/arm64/include/asm/ftrace.h
@@ -37,4 +37,18 @@ static inline unsigned long ftrace_call_adjust(unsigned long addr)
 #endif /* __ASSEMBLY__ */
 #endif /* CONFIG_FUNCTION_TRACER */
 
+#ifndef __ASSEMBLY__
+#define HAVE_ARCH_CALLER_ADDR
+
+extern void *return_address(unsigned int);
+
+#define CALLER_ADDR0 ((unsigned long)__builtin_return_address(0))
+#define CALLER_ADDR1 ((unsigned long)return_address(1))
+#define CALLER_ADDR2 ((unsigned long)return_address(2))
+#define CALLER_ADDR3 ((unsigned long)return_address(3))
+#define CALLER_ADDR4 ((unsigned long)return_address(4))
+#define CALLER_ADDR5 ((unsigned long)return_address(5))
+#define CALLER_ADDR6 ((unsigned long)return_address(6))
+#endif /* ifndef __ASSEMBLY__ */
+
 #endif /* __ASM_FTRACE_H */
diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile
index 92429e4..94d1876 100644
--- a/arch/arm64/kernel/Makefile
+++ b/arch/arm64/kernel/Makefile
@@ -9,12 +9,13 @@ ifdef CONFIG_FUNCTION_TRACER
 CFLAGS_REMOVE_ftrace.o = -pg
 CFLAGS_REMOVE_insn.o = -pg
 endif
+CFLAGS_REMOVE_return_address.o = -pg
 
 # Object file lists.
 arm64-obj-y		:= cputable.o debug-monitors.o entry.o irq.o fpsimd.o	\
 			   entry-fpsimd.o process.o ptrace.o setup.o signal.o	\
 			   sys.o stacktrace.o time.o traps.o io.o vdso.o	\
-			   hyp-stub.o psci.o insn.o
+			   hyp-stub.o psci.o insn.o return_address.o
 
 arm64-obj-$(CONFIG_COMPAT)		+= sys32.o kuser32.o signal32.o 	\
 					   sys_compat.o
diff --git a/arch/arm64/kernel/return_address.c b/arch/arm64/kernel/return_address.c
new file mode 100644
index 0000000..89102a6
--- /dev/null
+++ b/arch/arm64/kernel/return_address.c
@@ -0,0 +1,55 @@
+/*
+ * arch/arm64/kernel/return_address.c
+ *
+ * Copyright (C) 2013 Linaro Limited
+ * Author: AKASHI Takahiro <takahiro.akashi@linaro.org>
+ *
+ * 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 <linux/export.h>
+#include <linux/ftrace.h>
+
+#include <asm/stacktrace.h>
+
+struct return_address_data {
+	unsigned int level;
+	void *addr;
+};
+
+static int save_return_addr(struct stackframe *frame, void *d)
+{
+	struct return_address_data *data = d;
+
+	if (!data->level) {
+		data->addr = (void *)frame->pc;
+		return 1;
+	} else {
+		--data->level;
+		return 0;
+	}
+}
+
+void *return_address(unsigned int level)
+{
+	struct return_address_data data;
+	struct stackframe frame;
+	register unsigned long current_sp asm ("sp");
+
+	data.level = level + 2;
+	data.addr = NULL;
+
+	frame.fp = (unsigned long)__builtin_frame_address(0);
+	frame.sp = current_sp;
+	frame.pc = (unsigned long)return_address; /* dummy */
+
+	walk_stackframe(&frame, save_return_addr, &data);
+
+	if (!data.level)
+		return data.addr;
+	else
+		return NULL;
+}
+EXPORT_SYMBOL_GPL(return_address);
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 235+ messages in thread

* [PATCH v2 4/6] ftrace: Add arm64 support to recordmcount
  2013-10-24  7:08 [PATCH v2 0/6] arm64: Add ftrace support AKASHI Takahiro
                   ` (2 preceding siblings ...)
  2013-10-24  7:08 ` [PATCH v2 3/6] arm64: ftrace: Add CALLER_ADDRx macros AKASHI Takahiro
@ 2013-10-24  7:08 ` AKASHI Takahiro
  2013-10-24  7:08 ` [PATCH v2 5/6] arm64: ftrace: Add system call tracepoint AKASHI Takahiro
                   ` (2 subsequent siblings)
  6 siblings, 0 replies; 235+ messages in thread
From: AKASHI Takahiro @ 2013-10-24  7:08 UTC (permalink / raw)
  To: linux-arm-kernel

Recordmcount utility scans every object, finds out all the locations
of calling _mcount() and puts them into __mcount_loc section.
linker compiles all the information in between __start_mcount_loc
and __stop_mcount_loc for later use by ftrace.

There are two types of implementation, C or Perl.
In arm64, only C version is used since HAVE_C_RECORDMCOUNT is defined.

Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
---
 arch/arm64/Kconfig      |    2 ++
 scripts/recordmcount.c  |    4 ++++
 scripts/recordmcount.pl |    5 +++++
 3 files changed, 11 insertions(+)

diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index c150430..4f4a0dc 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -19,11 +19,13 @@ config ARM64
 	select HARDIRQS_SW_RESEND
 	select HAVE_ARCH_JUMP_LABEL
 	select HAVE_ARCH_TRACEHOOK
+	select HAVE_C_RECORDMCOUNT
 	select HAVE_DEBUG_BUGVERBOSE
 	select HAVE_DEBUG_KMEMLEAK
 	select HAVE_DMA_API_DEBUG
 	select HAVE_DMA_ATTRS
 	select HAVE_DYNAMIC_FTRACE
+	select HAVE_FTRACE_MCOUNT_RECORD
 	select HAVE_FUNCTION_TRACER
 	select HAVE_FUNCTION_GRAPH_TRACER
 	select HAVE_GENERIC_DMA_COHERENT
diff --git a/scripts/recordmcount.c b/scripts/recordmcount.c
index 9c22317..b92d9f7 100644
--- a/scripts/recordmcount.c
+++ b/scripts/recordmcount.c
@@ -347,6 +347,10 @@ do_file(char const *const fname)
 	case EM_ARM:	 reltype = R_ARM_ABS32;
 			 altmcount = "__gnu_mcount_nc";
 			 break;
+	case EM_AARCH64:
+			 reltype = R_AARCH64_ABS64;
+			 altmcount = "_mcount";
+			 break;
 	case EM_IA_64:	 reltype = R_IA64_IMM64;   gpfx = '_'; break;
 	case EM_METAG:	 reltype = R_METAG_ADDR32;
 			 altmcount = "_mcount_wrapper";
diff --git a/scripts/recordmcount.pl b/scripts/recordmcount.pl
index a674fd5..ae8b0fe 100755
--- a/scripts/recordmcount.pl
+++ b/scripts/recordmcount.pl
@@ -279,6 +279,11 @@ if ($arch eq "x86_64") {
     $mcount_regex = "^\\s*([0-9a-fA-F]+):\\s*R_ARM_(CALL|PC24|THM_CALL)" .
 			"\\s+(__gnu_mcount_nc|mcount)\$";
 
+} elsif ($arch eq "arm64") {
+    $alignment = 3;
+    $section_type = '%progbits';
+    $mcount_regex = "^\\s*([0-9a-fA-F]+):\\s*R_AARCH64_CALL26\\s+_mcount\$";
+    $type = ".quad";
 } elsif ($arch eq "ia64") {
     $mcount_regex = "^\\s*([0-9a-fA-F]+):.*\\s_mcount\$";
     $type = "data8";
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 235+ messages in thread

* [PATCH v2 5/6] arm64: ftrace: Add system call tracepoint
  2013-10-24  7:08 [PATCH v2 0/6] arm64: Add ftrace support AKASHI Takahiro
                   ` (3 preceding siblings ...)
  2013-10-24  7:08 ` [PATCH v2 4/6] ftrace: Add arm64 support to recordmcount AKASHI Takahiro
@ 2013-10-24  7:08 ` AKASHI Takahiro
  2013-10-24  7:08 ` [PATCH v2 6/6] arm64: Add 'notrace' attribute to unwind_frame() for ftrace AKASHI Takahiro
  2014-02-07 10:18   ` AKASHI Takahiro
  6 siblings, 0 replies; 235+ messages in thread
From: AKASHI Takahiro @ 2013-10-24  7:08 UTC (permalink / raw)
  To: linux-arm-kernel

This enables FTRACE_SYSCALLS configuration.
Entry and/or exit to any system call can be traced as a ftrace event.

Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
---
 arch/arm64/Kconfig                   |    1 +
 arch/arm64/include/asm/syscall.h     |    1 +
 arch/arm64/include/asm/thread_info.h |    1 +
 arch/arm64/include/asm/unistd.h      |    2 ++
 arch/arm64/kernel/entry.S            |    1 +
 arch/arm64/kernel/ptrace.c           |   10 ++++++++++
 6 files changed, 16 insertions(+)

diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 4f4a0dc..f01d84e 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -32,6 +32,7 @@ config ARM64
 	select HAVE_HW_BREAKPOINT if PERF_EVENTS
 	select HAVE_MEMBLOCK
 	select HAVE_PERF_EVENTS
+	select HAVE_SYSCALL_TRACEPOINTS
 	select IRQ_DOMAIN
 	select MODULES_USE_ELF_RELA
 	select NO_BOOTMEM
diff --git a/arch/arm64/include/asm/syscall.h b/arch/arm64/include/asm/syscall.h
index 70ba9d4..383771e 100644
--- a/arch/arm64/include/asm/syscall.h
+++ b/arch/arm64/include/asm/syscall.h
@@ -18,6 +18,7 @@
 
 #include <linux/err.h>
 
+extern const void *sys_call_table[];
 
 static inline int syscall_get_nr(struct task_struct *task,
 				 struct pt_regs *regs)
diff --git a/arch/arm64/include/asm/thread_info.h b/arch/arm64/include/asm/thread_info.h
index 23a3c47..6f5d977 100644
--- a/arch/arm64/include/asm/thread_info.h
+++ b/arch/arm64/include/asm/thread_info.h
@@ -107,6 +107,7 @@ static inline struct thread_info *current_thread_info(void)
 #define TIF_NEED_RESCHED	1
 #define TIF_NOTIFY_RESUME	2	/* callback before returning to user */
 #define TIF_SYSCALL_TRACE	8
+#define TIF_SYSCALL_TRACEPOINT	10
 #define TIF_POLLING_NRFLAG	16
 #define TIF_MEMDIE		18	/* is terminating due to OOM killer */
 #define TIF_FREEZE		19
diff --git a/arch/arm64/include/asm/unistd.h b/arch/arm64/include/asm/unistd.h
index 82ce217..c335479 100644
--- a/arch/arm64/include/asm/unistd.h
+++ b/arch/arm64/include/asm/unistd.h
@@ -28,3 +28,5 @@
 #endif
 #define __ARCH_WANT_SYS_CLONE
 #include <uapi/asm/unistd.h>
+
+#define NR_syscalls (__NR_syscalls)
diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S
index 3881fd1..7f81bfe 100644
--- a/arch/arm64/kernel/entry.S
+++ b/arch/arm64/kernel/entry.S
@@ -646,6 +646,7 @@ el0_svc_naked:					// compat entry point
 	get_thread_info tsk
 	ldr	x16, [tsk, #TI_FLAGS]		// check for syscall tracing
 	tbnz	x16, #TIF_SYSCALL_TRACE, __sys_trace // are we tracing syscalls?
+	tbnz	x16, #TIF_SYSCALL_TRACEPOINT, __sys_trace
 	adr	lr, ret_fast_syscall		// return address
 	cmp     scno, sc_nr                     // check upper syscall limit
 	b.hs	ni_sys
diff --git a/arch/arm64/kernel/ptrace.c b/arch/arm64/kernel/ptrace.c
index fecdbf7..548baa3 100644
--- a/arch/arm64/kernel/ptrace.c
+++ b/arch/arm64/kernel/ptrace.c
@@ -41,6 +41,9 @@
 #include <asm/traps.h>
 #include <asm/system_misc.h>
 
+#define CREATE_TRACE_POINTS
+#include <trace/events/syscalls.h>
+
 /*
  * TODO: does not yet catch signals sent when the child dies.
  * in exit.c or in signal.c.
@@ -1066,6 +1069,13 @@ asmlinkage int syscall_trace(int dir, struct pt_regs *regs)
 {
 	unsigned long saved_reg;
 
+	if (test_thread_flag(TIF_SYSCALL_TRACEPOINT)) {
+		if (dir)
+			trace_sys_exit(regs, regs->syscallno);
+		else
+			trace_sys_enter(regs, regs->syscallno);
+	}
+
 	if (!test_thread_flag(TIF_SYSCALL_TRACE))
 		return regs->syscallno;
 
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 235+ messages in thread

* [PATCH v2 6/6] arm64: Add 'notrace' attribute to unwind_frame() for ftrace
  2013-10-24  7:08 [PATCH v2 0/6] arm64: Add ftrace support AKASHI Takahiro
                   ` (4 preceding siblings ...)
  2013-10-24  7:08 ` [PATCH v2 5/6] arm64: ftrace: Add system call tracepoint AKASHI Takahiro
@ 2013-10-24  7:08 ` AKASHI Takahiro
  2014-02-07 10:18   ` AKASHI Takahiro
  6 siblings, 0 replies; 235+ messages in thread
From: AKASHI Takahiro @ 2013-10-24  7:08 UTC (permalink / raw)
  To: linux-arm-kernel

walk_stackframe() calls unwind_frame(), and if walk_stackframe() is
"notrace", unwind_frame() should be also "notrace".

Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
---
 arch/arm64/kernel/stacktrace.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm64/kernel/stacktrace.c b/arch/arm64/kernel/stacktrace.c
index d25459f..03dd5a2 100644
--- a/arch/arm64/kernel/stacktrace.c
+++ b/arch/arm64/kernel/stacktrace.c
@@ -35,7 +35,7 @@
  *	ldp	x29, x30, [sp]
  *	add	sp, sp, #0x10
  */
-int unwind_frame(struct stackframe *frame)
+int notrace unwind_frame(struct stackframe *frame)
 {
 	unsigned long high, low;
 	unsigned long fp = frame->fp;
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 235+ messages in thread

* [PATCH v3 0/6] arm64: Add ftrace support
  2013-10-24  7:08 [PATCH v2 0/6] arm64: Add ftrace support AKASHI Takahiro
@ 2014-02-07 10:18   ` AKASHI Takahiro
  2013-10-24  7:08 ` [PATCH v2 2/6] arm64: ftrace: Add dynamic " AKASHI Takahiro
                     ` (5 subsequent siblings)
  6 siblings, 0 replies; 235+ messages in thread
From: AKASHI Takahiro @ 2014-02-07 10:18 UTC (permalink / raw)
  To: rostedt, fweisbec, mingo, catalin.marinas, will.deacon,
	gkulkarni, tim.bird
  Cc: arndb, linux-arm-kernel, linaro-kernel, linux-kernel, patches,
	AKASHI Takahiro

This is my third version of patchset for ftrace support.
There was another implementation from Cavium network, but both of us agreed
to use my patchset as future base. He is supposed to review this code, too.

The only issue that I had some concern on was "fault protection" code
in prepare_ftrace_return(). With discussions with Steven and Tim (as author
of arm ftrace), I removed that code since I'm not quite sure about possibility
of "fault" occurrences in this function.

The code is tested on ARMv8 Fast Model with the following tracers & events:
     function tracer with dynamic ftrace
     function graph tracer with dynamic ftrace
     syscall tracepoint
     irqsoff & preemptirqsoff (which use CALLER_ADDRx)
and also verified with in-kernel tests, FTRACE_SELFTEST, FTRACE_STARTUP_TEST
and EVENT_TRACE_TEST_SYSCALLS.

Please be careful:
* elf.h on cross-build host must have AArch64 definitions, EM_AARCH64 and
  R_AARCH64_ABS64, to compile recordmcount utility. See [4/6].
  [4/6] also gets warnings from checkpatch, but they are based on the
  original's coding style.
* This patch may conflict with my audit patch because both changes the same
  location in syscall_trace(). I expect the functions are called in this
  order:
  On entry,
     * tracehook_report_syscall(ENTER)
     * trace_sys_enter()
     * audit_syscall_entry()
  On exit,
     * audit_sysscall_exit()
     * trace_sys_exit()
     * tracehook_report_syscall(EXIT) 

Changes from v1 to v2:
* splitted one patch into some pieces for easier review
  (especially function tracer + dynamic ftrace + CALLER_ADDRx)
* put return_address() in a separate file
* renamed __mcount to _mcount (it was my mistake)
* changed stackframe handling to get parent's frame pointer
* removed ARCH_SUPPORTS_FTRACE_OPS
* switched to "hotpatch" interfaces from Huawai
* revised descriptions in comments

Changes from v2 to v3:
* optimized register usages in asm (by not saving x0, x1, and x2)
* removed "fault protection" code in prepare_ftrace_return()
* rewrote ftrace_modify_code() using "hotpatch" interfaces
* revised descriptions in comments

AKASHI Takahiro (6):
  arm64: Add ftrace support
  arm64: ftrace: Add dynamic ftrace support
  arm64: ftrace: Add CALLER_ADDRx macros
  ftrace: Add arm64 support to recordmcount
  arm64: ftrace: Add system call tracepoint
  arm64: Add 'notrace' attribute to unwind_frame() for ftrace

 arch/arm64/Kconfig                 |    6 +
 arch/arm64/include/asm/ftrace.h    |   54 +++++++++
 arch/arm64/include/asm/syscall.h   |    1 +
 arch/arm64/include/asm/unistd.h    |    2 +
 arch/arm64/kernel/Makefile         |    9 +-
 arch/arm64/kernel/arm64ksyms.c     |    4 +
 arch/arm64/kernel/entry-ftrace.S   |  215 ++++++++++++++++++++++++++++++++++++
 arch/arm64/kernel/ftrace.c         |  177 +++++++++++++++++++++++++++++
 arch/arm64/kernel/ptrace.c         |    5 +
 arch/arm64/kernel/return_address.c |   55 +++++++++
 arch/arm64/kernel/stacktrace.c     |    2 +-
 scripts/recordmcount.c             |    4 +
 scripts/recordmcount.pl            |    5 +
 13 files changed, 537 insertions(+), 2 deletions(-)
 create mode 100644 arch/arm64/include/asm/ftrace.h
 create mode 100644 arch/arm64/kernel/entry-ftrace.S
 create mode 100644 arch/arm64/kernel/ftrace.c
 create mode 100644 arch/arm64/kernel/return_address.c

-- 
1.7.9.5


^ permalink raw reply	[flat|nested] 235+ messages in thread

* [PATCH v3 0/6] arm64: Add ftrace support
@ 2014-02-07 10:18   ` AKASHI Takahiro
  0 siblings, 0 replies; 235+ messages in thread
From: AKASHI Takahiro @ 2014-02-07 10:18 UTC (permalink / raw)
  To: linux-arm-kernel

This is my third version of patchset for ftrace support.
There was another implementation from Cavium network, but both of us agreed
to use my patchset as future base. He is supposed to review this code, too.

The only issue that I had some concern on was "fault protection" code
in prepare_ftrace_return(). With discussions with Steven and Tim (as author
of arm ftrace), I removed that code since I'm not quite sure about possibility
of "fault" occurrences in this function.

The code is tested on ARMv8 Fast Model with the following tracers & events:
     function tracer with dynamic ftrace
     function graph tracer with dynamic ftrace
     syscall tracepoint
     irqsoff & preemptirqsoff (which use CALLER_ADDRx)
and also verified with in-kernel tests, FTRACE_SELFTEST, FTRACE_STARTUP_TEST
and EVENT_TRACE_TEST_SYSCALLS.

Please be careful:
* elf.h on cross-build host must have AArch64 definitions, EM_AARCH64 and
  R_AARCH64_ABS64, to compile recordmcount utility. See [4/6].
  [4/6] also gets warnings from checkpatch, but they are based on the
  original's coding style.
* This patch may conflict with my audit patch because both changes the same
  location in syscall_trace(). I expect the functions are called in this
  order:
  On entry,
     * tracehook_report_syscall(ENTER)
     * trace_sys_enter()
     * audit_syscall_entry()
  On exit,
     * audit_sysscall_exit()
     * trace_sys_exit()
     * tracehook_report_syscall(EXIT) 

Changes from v1 to v2:
* splitted one patch into some pieces for easier review
  (especially function tracer + dynamic ftrace + CALLER_ADDRx)
* put return_address() in a separate file
* renamed __mcount to _mcount (it was my mistake)
* changed stackframe handling to get parent's frame pointer
* removed ARCH_SUPPORTS_FTRACE_OPS
* switched to "hotpatch" interfaces from Huawai
* revised descriptions in comments

Changes from v2 to v3:
* optimized register usages in asm (by not saving x0, x1, and x2)
* removed "fault protection" code in prepare_ftrace_return()
* rewrote ftrace_modify_code() using "hotpatch" interfaces
* revised descriptions in comments

AKASHI Takahiro (6):
  arm64: Add ftrace support
  arm64: ftrace: Add dynamic ftrace support
  arm64: ftrace: Add CALLER_ADDRx macros
  ftrace: Add arm64 support to recordmcount
  arm64: ftrace: Add system call tracepoint
  arm64: Add 'notrace' attribute to unwind_frame() for ftrace

 arch/arm64/Kconfig                 |    6 +
 arch/arm64/include/asm/ftrace.h    |   54 +++++++++
 arch/arm64/include/asm/syscall.h   |    1 +
 arch/arm64/include/asm/unistd.h    |    2 +
 arch/arm64/kernel/Makefile         |    9 +-
 arch/arm64/kernel/arm64ksyms.c     |    4 +
 arch/arm64/kernel/entry-ftrace.S   |  215 ++++++++++++++++++++++++++++++++++++
 arch/arm64/kernel/ftrace.c         |  177 +++++++++++++++++++++++++++++
 arch/arm64/kernel/ptrace.c         |    5 +
 arch/arm64/kernel/return_address.c |   55 +++++++++
 arch/arm64/kernel/stacktrace.c     |    2 +-
 scripts/recordmcount.c             |    4 +
 scripts/recordmcount.pl            |    5 +
 13 files changed, 537 insertions(+), 2 deletions(-)
 create mode 100644 arch/arm64/include/asm/ftrace.h
 create mode 100644 arch/arm64/kernel/entry-ftrace.S
 create mode 100644 arch/arm64/kernel/ftrace.c
 create mode 100644 arch/arm64/kernel/return_address.c

-- 
1.7.9.5

^ permalink raw reply	[flat|nested] 235+ messages in thread

* [PATCH v3 1/6] arm64: Add ftrace support
  2014-02-07 10:18   ` AKASHI Takahiro
@ 2014-02-07 10:18     ` AKASHI Takahiro
  -1 siblings, 0 replies; 235+ messages in thread
From: AKASHI Takahiro @ 2014-02-07 10:18 UTC (permalink / raw)
  To: rostedt, fweisbec, mingo, catalin.marinas, will.deacon,
	gkulkarni, tim.bird
  Cc: arndb, linux-arm-kernel, linaro-kernel, linux-kernel, patches,
	AKASHI Takahiro

This patch implements arm64 specific part to support function tracers,
such as function (CONFIG_FUNCTION_TRACER), function_graph
(CONFIG_FUNCTION_GRAPH_TRACER) and function profiler
(CONFIG_FUNCTION_PROFILER).

With 'function' tracer, all the functions in the kernel are traced with
timestamps in ${sysfs}/tracing/trace. If function_graph tracer is
specified, call graph is generated.

The kernel must be compiled with -pg option so that _mcount() is inserted
at the beginning of functions. This function is called on every function's
entry as long as tracing is enabled.
In addition, function_graph tracer also needs to be able to probe function's
exit. ftrace_graph_caller() & return_to_handler do this by faking link
register's value to intercept function's return path.

More details on architecture specific requirements are described in
Documentation/trace/ftrace-design.txt.

Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
---
 arch/arm64/Kconfig               |    2 +
 arch/arm64/include/asm/ftrace.h  |   23 +++++
 arch/arm64/kernel/Makefile       |    6 ++
 arch/arm64/kernel/arm64ksyms.c   |    4 +
 arch/arm64/kernel/entry-ftrace.S |  172 ++++++++++++++++++++++++++++++++++++++
 arch/arm64/kernel/ftrace.c       |   64 ++++++++++++++
 6 files changed, 271 insertions(+)
 create mode 100644 arch/arm64/include/asm/ftrace.h
 create mode 100644 arch/arm64/kernel/entry-ftrace.S
 create mode 100644 arch/arm64/kernel/ftrace.c

diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index dd4327f..332e50c 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -33,6 +33,8 @@ config ARM64
 	select HAVE_DMA_ATTRS
 	select HAVE_DMA_CONTIGUOUS
 	select HAVE_EFFICIENT_UNALIGNED_ACCESS
+	select HAVE_FUNCTION_TRACER
+	select HAVE_FUNCTION_GRAPH_TRACER
 	select HAVE_GENERIC_DMA_COHERENT
 	select HAVE_HW_BREAKPOINT if PERF_EVENTS
 	select HAVE_MEMBLOCK
diff --git a/arch/arm64/include/asm/ftrace.h b/arch/arm64/include/asm/ftrace.h
new file mode 100644
index 0000000..0d5dfdb
--- /dev/null
+++ b/arch/arm64/include/asm/ftrace.h
@@ -0,0 +1,23 @@
+/*
+ * arch/arm64/include/asm/ftrace.h
+ *
+ * Copyright (C) 2013 Linaro Limited
+ * Author: AKASHI Takahiro <takahiro.akashi@linaro.org>
+ *
+ * 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.
+ */
+#ifndef __ASM_FTRACE_H
+#define __ASM_FTRACE_H
+
+#ifdef CONFIG_FUNCTION_TRACER
+#define MCOUNT_ADDR		((unsigned long)_mcount)
+#define MCOUNT_INSN_SIZE	4 /* sizeof mcount call */
+
+#ifndef __ASSEMBLY__
+extern void _mcount(unsigned long);
+#endif /* __ASSEMBLY__ */
+#endif /* CONFIG_FUNCTION_TRACER */
+
+#endif /* __ASM_FTRACE_H */
diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile
index 2d4554b..ca921fb 100644
--- a/arch/arm64/kernel/Makefile
+++ b/arch/arm64/kernel/Makefile
@@ -5,6 +5,11 @@
 CPPFLAGS_vmlinux.lds	:= -DTEXT_OFFSET=$(TEXT_OFFSET)
 AFLAGS_head.o		:= -DTEXT_OFFSET=$(TEXT_OFFSET)
 
+ifdef CONFIG_FUNCTION_TRACER
+CFLAGS_REMOVE_ftrace.o = -pg
+CFLAGS_REMOVE_insn.o = -pg
+endif
+
 # Object file lists.
 arm64-obj-y		:= cputable.o debug-monitors.o entry.o irq.o fpsimd.o	\
 			   entry-fpsimd.o process.o ptrace.o setup.o signal.o	\
@@ -13,6 +18,7 @@ arm64-obj-y		:= cputable.o debug-monitors.o entry.o irq.o fpsimd.o	\
 
 arm64-obj-$(CONFIG_COMPAT)		+= sys32.o kuser32.o signal32.o 	\
 					   sys_compat.o
+arm64-obj-$(CONFIG_FUNCTION_TRACER)	+= ftrace.o entry-ftrace.o
 arm64-obj-$(CONFIG_MODULES)		+= arm64ksyms.o module.o
 arm64-obj-$(CONFIG_SMP)			+= smp.o smp_spin_table.o
 arm64-obj-$(CONFIG_HW_PERF_EVENTS)	+= perf_event.o
diff --git a/arch/arm64/kernel/arm64ksyms.c b/arch/arm64/kernel/arm64ksyms.c
index 338b568..7f0512f 100644
--- a/arch/arm64/kernel/arm64ksyms.c
+++ b/arch/arm64/kernel/arm64ksyms.c
@@ -56,3 +56,7 @@ EXPORT_SYMBOL(clear_bit);
 EXPORT_SYMBOL(test_and_clear_bit);
 EXPORT_SYMBOL(change_bit);
 EXPORT_SYMBOL(test_and_change_bit);
+
+#ifdef CONFIG_FUNCTION_TRACER
+EXPORT_SYMBOL(_mcount);
+#endif
diff --git a/arch/arm64/kernel/entry-ftrace.S b/arch/arm64/kernel/entry-ftrace.S
new file mode 100644
index 0000000..065f426
--- /dev/null
+++ b/arch/arm64/kernel/entry-ftrace.S
@@ -0,0 +1,172 @@
+/*
+ * arch/arm64/kernel/entry-ftrace.S
+ *
+ * Copyright (C) 2013 Linaro Limited
+ * Author: AKASHI Takahiro <takahiro.akashi@linaro.org>
+ *
+ * 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 <linux/linkage.h>
+#include <asm/ftrace.h>
+
+/*
+ * Gcc with -pg will put the following code in the beginning of each function:
+ *      mov x0, x30
+ *      bl _mcount
+ *	[function's body ...]
+ * "bl _mcount" may be replaced to "bl ftrace_caller" or NOP if dynamic
+ * ftrace is enabled.
+ *
+ * Please note that x0 as an argument will not be used here because we can
+ * get lr(x30) of insturmented function at any time by winding up call stack
+ * as long as the kernel is compiled without -fomit-frame-pointer.
+ * (or CONFIG_FRAME_POINTER, this is forced on arm64)
+ *
+ * stack layout after mcount_enter:
+ *
+ *   0 ---------------------------------------- sp of _mcount()
+ *      x29: fp of instrumented function	fp is not winded
+ *     --------------------
+ *      x30: lr of _mcount() (= instrumented function's pc)
+ * +16 ---------------------------------------- sp of instrumented function
+ *
+ *     ....
+ *
+ * +xx ---------------------------------------- fp of instrumented function
+ *      x29: fp of parent
+ *     --------------------
+ *      x30: lr of insturmented function (= parent's pc)
+ *     --------------------
+ *      xxx
+ */
+
+	.macro mcount_enter
+	stp	x29, x30, [sp, #-48]!
+	.endm
+
+	.macro mcount_exit
+	ldp	x29, x30, [sp], #48
+	ret
+	.endm
+
+	.macro mcount_adjust_addr rd, rn
+	sub	\rd, \rn, #MCOUNT_INSN_SIZE
+	.endm
+
+	/* for instrumented function's parent */
+	.macro mcount_get_parent_fp reg
+	ldr	\reg, [sp]
+	ldr	\reg, [\reg]
+	.endm
+
+	/* for instrumented function */
+	.macro mcount_get_pc0 reg
+	mcount_adjust_addr	\reg, x30
+	.endm
+
+	.macro mcount_get_pc reg
+	ldr	\reg, [sp, #8]
+	mcount_adjust_addr	\reg, \reg
+	.endm
+
+	.macro mcount_get_lr reg
+	ldr	\reg, [sp]
+	ldr	\reg, [\reg, #8]
+	mcount_adjust_addr	\reg, \reg
+	.endm
+
+	.macro mcount_get_saved_lr_addr reg
+	ldr	\reg, [sp]
+	add	\reg, \reg, #8
+	.endm
+
+/*
+ * void _mcount(unsigned long return_address)
+ * @return_address: return address to instrumented function
+ *
+ * This function makes calls, if enabled, to:
+ *     - tracer function to probe instrumented function's entry,
+ *     - ftrace_graph_caller to set up an exit hook
+ */
+ENTRY(_mcount)
+#ifdef CONFIG_HAVE_FUNCTION_TRACE_MCOUNT_TEST
+	ldr	x0, =ftrace_trace_stop
+	ldr	x0, [x0]		// if ftrace_trace_stop
+	ret				//   return;
+#endif
+	mcount_enter
+
+	ldr	x0, =ftrace_trace_function
+	ldr	x2, [x0]
+	adr	x0, ftrace_stub
+	cmp	x0, x2			// if (ftrace_trace_function
+	b.eq	skip_ftrace_call	//     != ftrace_stub) {
+
+	mcount_get_pc	x0		//       function's pc
+	mcount_get_lr	x1		//       function's lr (= parent's pc)
+	blr	x2			//   (*ftrace_trace_function)(pc, lr);
+
+#ifndef CONFIG_FUNCTION_GRAPH_TRACER
+skip_ftrace_call:			//   return;
+	mcount_exit			// }
+#else
+	mcount_exit			//   return;
+					// }
+skip_ftrace_call:
+	ldr	x1, =ftrace_graph_return
+	ldr	x2, [x1]		//   if ((ftrace_graph_return
+	cmp	x0, x2			//        != ftrace_stub)
+	b.ne	ftrace_graph_caller
+
+	ldr	x1, =ftrace_graph_entry	//     || (ftrace_graph_entry
+	ldr	x2, [x1]		//        != ftrace_graph_entry_stub))
+	ldr	x0, =ftrace_graph_entry_stub
+	cmp	x0, x2
+	b.ne	ftrace_graph_caller	//     ftrace_graph_caller();
+
+	mcount_exit
+#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
+ENDPROC(_mcount)
+
+ENTRY(ftrace_stub)
+	ret
+ENDPROC(ftrace_stub)
+
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+/*
+ * void ftrace_graph_caller(void)
+ *
+ * Called from _mcount() or ftrace_caller() when function_graph tracer is
+ * selected.
+ * This function w/ prepare_ftrace_return() fakes link register's value on
+ * the call stack in order to intercept instrumented function's return path
+ * and run return_to_handler() later on its exit.
+ */
+ENTRY(ftrace_graph_caller)
+	mcount_get_saved_lr_addr  x0	//     pointer to function's saved lr
+	mcount_get_pc		  x1	//     function's pc
+	mcount_get_parent_fp	  x2	//     parent's fp
+	bl	prepare_ftrace_return	// prepare_ftrace_return(&lr, pc, fp)
+
+	mcount_exit
+ENDPROC(ftrace_graph_caller)
+
+/*
+ * void return_to_handler(void)
+ *
+ * Run ftrace_return_to_handler() before going back to parent.
+ * @fp is checked against the value passed by ftrace_graph_caller()
+ * only when CONFIG_FUNCTION_GRAPH_FP_TEST is enabled.
+ */
+	.global return_to_handler
+return_to_handler:
+	str	x0, [sp, #-16]!
+	mov	x0, x29			//     parent's fp
+	bl	ftrace_return_to_handler// addr = ftrace_return_to_hander(fp);
+	mov	x30, x0			// restore the original return address
+	ldr	x0, [sp], #16
+	ret
+#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
diff --git a/arch/arm64/kernel/ftrace.c b/arch/arm64/kernel/ftrace.c
new file mode 100644
index 0000000..a559ab8
--- /dev/null
+++ b/arch/arm64/kernel/ftrace.c
@@ -0,0 +1,64 @@
+/*
+ * arch/arm64/kernel/ftrace.c
+ *
+ * Copyright (C) 2013 Linaro Limited
+ * Author: AKASHI Takahiro <takahiro.akashi@linaro.org>
+ *
+ * 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 <linux/ftrace.h>
+#include <linux/swab.h>
+#include <linux/uaccess.h>
+
+#include <asm/cacheflush.h>
+#include <asm/ftrace.h>
+#include <asm/insn.h>
+
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+/*
+ * function_graph tracer expects ftrace_return_to_handler() to be called
+ * on the way back to parent. For this purpose, this function is called
+ * in _mcount() or ftrace_caller() to replace return address (*parent) on
+ * the call stack to return_to_handler.
+ *
+ * Note that @frame_pointer is used only for sanity check later.
+ */
+void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr,
+			   unsigned long frame_pointer)
+{
+	unsigned long return_hooker = (unsigned long)&return_to_handler;
+	unsigned long old;
+	struct ftrace_graph_ent trace;
+	int err;
+
+	if (unlikely(atomic_read(&current->tracing_graph_pause)))
+		return;
+
+	/*
+	 * Note:
+	 * No protection against faulting at *parent, which may be seen
+	 * on other archs. It's unlikely on AArch64.
+	 */
+	old = *parent;
+	*parent = return_hooker;
+
+	trace.func = self_addr;
+	trace.depth = current->curr_ret_stack + 1;
+
+	/* Only trace if the calling function expects to */
+	if (!ftrace_graph_entry(&trace)) {
+		*parent = old;
+		return;
+	}
+
+	err = ftrace_push_return_trace(old, self_addr, &trace.depth,
+				       frame_pointer);
+	if (err == -EBUSY) {
+		*parent = old;
+		return;
+	}
+}
+#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 235+ messages in thread

* [PATCH v3 1/6] arm64: Add ftrace support
@ 2014-02-07 10:18     ` AKASHI Takahiro
  0 siblings, 0 replies; 235+ messages in thread
From: AKASHI Takahiro @ 2014-02-07 10:18 UTC (permalink / raw)
  To: linux-arm-kernel

This patch implements arm64 specific part to support function tracers,
such as function (CONFIG_FUNCTION_TRACER), function_graph
(CONFIG_FUNCTION_GRAPH_TRACER) and function profiler
(CONFIG_FUNCTION_PROFILER).

With 'function' tracer, all the functions in the kernel are traced with
timestamps in ${sysfs}/tracing/trace. If function_graph tracer is
specified, call graph is generated.

The kernel must be compiled with -pg option so that _mcount() is inserted
at the beginning of functions. This function is called on every function's
entry as long as tracing is enabled.
In addition, function_graph tracer also needs to be able to probe function's
exit. ftrace_graph_caller() & return_to_handler do this by faking link
register's value to intercept function's return path.

More details on architecture specific requirements are described in
Documentation/trace/ftrace-design.txt.

Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
---
 arch/arm64/Kconfig               |    2 +
 arch/arm64/include/asm/ftrace.h  |   23 +++++
 arch/arm64/kernel/Makefile       |    6 ++
 arch/arm64/kernel/arm64ksyms.c   |    4 +
 arch/arm64/kernel/entry-ftrace.S |  172 ++++++++++++++++++++++++++++++++++++++
 arch/arm64/kernel/ftrace.c       |   64 ++++++++++++++
 6 files changed, 271 insertions(+)
 create mode 100644 arch/arm64/include/asm/ftrace.h
 create mode 100644 arch/arm64/kernel/entry-ftrace.S
 create mode 100644 arch/arm64/kernel/ftrace.c

diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index dd4327f..332e50c 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -33,6 +33,8 @@ config ARM64
 	select HAVE_DMA_ATTRS
 	select HAVE_DMA_CONTIGUOUS
 	select HAVE_EFFICIENT_UNALIGNED_ACCESS
+	select HAVE_FUNCTION_TRACER
+	select HAVE_FUNCTION_GRAPH_TRACER
 	select HAVE_GENERIC_DMA_COHERENT
 	select HAVE_HW_BREAKPOINT if PERF_EVENTS
 	select HAVE_MEMBLOCK
diff --git a/arch/arm64/include/asm/ftrace.h b/arch/arm64/include/asm/ftrace.h
new file mode 100644
index 0000000..0d5dfdb
--- /dev/null
+++ b/arch/arm64/include/asm/ftrace.h
@@ -0,0 +1,23 @@
+/*
+ * arch/arm64/include/asm/ftrace.h
+ *
+ * Copyright (C) 2013 Linaro Limited
+ * Author: AKASHI Takahiro <takahiro.akashi@linaro.org>
+ *
+ * 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.
+ */
+#ifndef __ASM_FTRACE_H
+#define __ASM_FTRACE_H
+
+#ifdef CONFIG_FUNCTION_TRACER
+#define MCOUNT_ADDR		((unsigned long)_mcount)
+#define MCOUNT_INSN_SIZE	4 /* sizeof mcount call */
+
+#ifndef __ASSEMBLY__
+extern void _mcount(unsigned long);
+#endif /* __ASSEMBLY__ */
+#endif /* CONFIG_FUNCTION_TRACER */
+
+#endif /* __ASM_FTRACE_H */
diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile
index 2d4554b..ca921fb 100644
--- a/arch/arm64/kernel/Makefile
+++ b/arch/arm64/kernel/Makefile
@@ -5,6 +5,11 @@
 CPPFLAGS_vmlinux.lds	:= -DTEXT_OFFSET=$(TEXT_OFFSET)
 AFLAGS_head.o		:= -DTEXT_OFFSET=$(TEXT_OFFSET)
 
+ifdef CONFIG_FUNCTION_TRACER
+CFLAGS_REMOVE_ftrace.o = -pg
+CFLAGS_REMOVE_insn.o = -pg
+endif
+
 # Object file lists.
 arm64-obj-y		:= cputable.o debug-monitors.o entry.o irq.o fpsimd.o	\
 			   entry-fpsimd.o process.o ptrace.o setup.o signal.o	\
@@ -13,6 +18,7 @@ arm64-obj-y		:= cputable.o debug-monitors.o entry.o irq.o fpsimd.o	\
 
 arm64-obj-$(CONFIG_COMPAT)		+= sys32.o kuser32.o signal32.o 	\
 					   sys_compat.o
+arm64-obj-$(CONFIG_FUNCTION_TRACER)	+= ftrace.o entry-ftrace.o
 arm64-obj-$(CONFIG_MODULES)		+= arm64ksyms.o module.o
 arm64-obj-$(CONFIG_SMP)			+= smp.o smp_spin_table.o
 arm64-obj-$(CONFIG_HW_PERF_EVENTS)	+= perf_event.o
diff --git a/arch/arm64/kernel/arm64ksyms.c b/arch/arm64/kernel/arm64ksyms.c
index 338b568..7f0512f 100644
--- a/arch/arm64/kernel/arm64ksyms.c
+++ b/arch/arm64/kernel/arm64ksyms.c
@@ -56,3 +56,7 @@ EXPORT_SYMBOL(clear_bit);
 EXPORT_SYMBOL(test_and_clear_bit);
 EXPORT_SYMBOL(change_bit);
 EXPORT_SYMBOL(test_and_change_bit);
+
+#ifdef CONFIG_FUNCTION_TRACER
+EXPORT_SYMBOL(_mcount);
+#endif
diff --git a/arch/arm64/kernel/entry-ftrace.S b/arch/arm64/kernel/entry-ftrace.S
new file mode 100644
index 0000000..065f426
--- /dev/null
+++ b/arch/arm64/kernel/entry-ftrace.S
@@ -0,0 +1,172 @@
+/*
+ * arch/arm64/kernel/entry-ftrace.S
+ *
+ * Copyright (C) 2013 Linaro Limited
+ * Author: AKASHI Takahiro <takahiro.akashi@linaro.org>
+ *
+ * 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 <linux/linkage.h>
+#include <asm/ftrace.h>
+
+/*
+ * Gcc with -pg will put the following code in the beginning of each function:
+ *      mov x0, x30
+ *      bl _mcount
+ *	[function's body ...]
+ * "bl _mcount" may be replaced to "bl ftrace_caller" or NOP if dynamic
+ * ftrace is enabled.
+ *
+ * Please note that x0 as an argument will not be used here because we can
+ * get lr(x30) of insturmented function at any time by winding up call stack
+ * as long as the kernel is compiled without -fomit-frame-pointer.
+ * (or CONFIG_FRAME_POINTER, this is forced on arm64)
+ *
+ * stack layout after mcount_enter:
+ *
+ *   0 ---------------------------------------- sp of _mcount()
+ *      x29: fp of instrumented function	fp is not winded
+ *     --------------------
+ *      x30: lr of _mcount() (= instrumented function's pc)
+ * +16 ---------------------------------------- sp of instrumented function
+ *
+ *     ....
+ *
+ * +xx ---------------------------------------- fp of instrumented function
+ *      x29: fp of parent
+ *     --------------------
+ *      x30: lr of insturmented function (= parent's pc)
+ *     --------------------
+ *      xxx
+ */
+
+	.macro mcount_enter
+	stp	x29, x30, [sp, #-48]!
+	.endm
+
+	.macro mcount_exit
+	ldp	x29, x30, [sp], #48
+	ret
+	.endm
+
+	.macro mcount_adjust_addr rd, rn
+	sub	\rd, \rn, #MCOUNT_INSN_SIZE
+	.endm
+
+	/* for instrumented function's parent */
+	.macro mcount_get_parent_fp reg
+	ldr	\reg, [sp]
+	ldr	\reg, [\reg]
+	.endm
+
+	/* for instrumented function */
+	.macro mcount_get_pc0 reg
+	mcount_adjust_addr	\reg, x30
+	.endm
+
+	.macro mcount_get_pc reg
+	ldr	\reg, [sp, #8]
+	mcount_adjust_addr	\reg, \reg
+	.endm
+
+	.macro mcount_get_lr reg
+	ldr	\reg, [sp]
+	ldr	\reg, [\reg, #8]
+	mcount_adjust_addr	\reg, \reg
+	.endm
+
+	.macro mcount_get_saved_lr_addr reg
+	ldr	\reg, [sp]
+	add	\reg, \reg, #8
+	.endm
+
+/*
+ * void _mcount(unsigned long return_address)
+ * @return_address: return address to instrumented function
+ *
+ * This function makes calls, if enabled, to:
+ *     - tracer function to probe instrumented function's entry,
+ *     - ftrace_graph_caller to set up an exit hook
+ */
+ENTRY(_mcount)
+#ifdef CONFIG_HAVE_FUNCTION_TRACE_MCOUNT_TEST
+	ldr	x0, =ftrace_trace_stop
+	ldr	x0, [x0]		// if ftrace_trace_stop
+	ret				//   return;
+#endif
+	mcount_enter
+
+	ldr	x0, =ftrace_trace_function
+	ldr	x2, [x0]
+	adr	x0, ftrace_stub
+	cmp	x0, x2			// if (ftrace_trace_function
+	b.eq	skip_ftrace_call	//     != ftrace_stub) {
+
+	mcount_get_pc	x0		//       function's pc
+	mcount_get_lr	x1		//       function's lr (= parent's pc)
+	blr	x2			//   (*ftrace_trace_function)(pc, lr);
+
+#ifndef CONFIG_FUNCTION_GRAPH_TRACER
+skip_ftrace_call:			//   return;
+	mcount_exit			// }
+#else
+	mcount_exit			//   return;
+					// }
+skip_ftrace_call:
+	ldr	x1, =ftrace_graph_return
+	ldr	x2, [x1]		//   if ((ftrace_graph_return
+	cmp	x0, x2			//        != ftrace_stub)
+	b.ne	ftrace_graph_caller
+
+	ldr	x1, =ftrace_graph_entry	//     || (ftrace_graph_entry
+	ldr	x2, [x1]		//        != ftrace_graph_entry_stub))
+	ldr	x0, =ftrace_graph_entry_stub
+	cmp	x0, x2
+	b.ne	ftrace_graph_caller	//     ftrace_graph_caller();
+
+	mcount_exit
+#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
+ENDPROC(_mcount)
+
+ENTRY(ftrace_stub)
+	ret
+ENDPROC(ftrace_stub)
+
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+/*
+ * void ftrace_graph_caller(void)
+ *
+ * Called from _mcount() or ftrace_caller() when function_graph tracer is
+ * selected.
+ * This function w/ prepare_ftrace_return() fakes link register's value on
+ * the call stack in order to intercept instrumented function's return path
+ * and run return_to_handler() later on its exit.
+ */
+ENTRY(ftrace_graph_caller)
+	mcount_get_saved_lr_addr  x0	//     pointer to function's saved lr
+	mcount_get_pc		  x1	//     function's pc
+	mcount_get_parent_fp	  x2	//     parent's fp
+	bl	prepare_ftrace_return	// prepare_ftrace_return(&lr, pc, fp)
+
+	mcount_exit
+ENDPROC(ftrace_graph_caller)
+
+/*
+ * void return_to_handler(void)
+ *
+ * Run ftrace_return_to_handler() before going back to parent.
+ * @fp is checked against the value passed by ftrace_graph_caller()
+ * only when CONFIG_FUNCTION_GRAPH_FP_TEST is enabled.
+ */
+	.global return_to_handler
+return_to_handler:
+	str	x0, [sp, #-16]!
+	mov	x0, x29			//     parent's fp
+	bl	ftrace_return_to_handler// addr = ftrace_return_to_hander(fp);
+	mov	x30, x0			// restore the original return address
+	ldr	x0, [sp], #16
+	ret
+#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
diff --git a/arch/arm64/kernel/ftrace.c b/arch/arm64/kernel/ftrace.c
new file mode 100644
index 0000000..a559ab8
--- /dev/null
+++ b/arch/arm64/kernel/ftrace.c
@@ -0,0 +1,64 @@
+/*
+ * arch/arm64/kernel/ftrace.c
+ *
+ * Copyright (C) 2013 Linaro Limited
+ * Author: AKASHI Takahiro <takahiro.akashi@linaro.org>
+ *
+ * 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 <linux/ftrace.h>
+#include <linux/swab.h>
+#include <linux/uaccess.h>
+
+#include <asm/cacheflush.h>
+#include <asm/ftrace.h>
+#include <asm/insn.h>
+
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+/*
+ * function_graph tracer expects ftrace_return_to_handler() to be called
+ * on the way back to parent. For this purpose, this function is called
+ * in _mcount() or ftrace_caller() to replace return address (*parent) on
+ * the call stack to return_to_handler.
+ *
+ * Note that @frame_pointer is used only for sanity check later.
+ */
+void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr,
+			   unsigned long frame_pointer)
+{
+	unsigned long return_hooker = (unsigned long)&return_to_handler;
+	unsigned long old;
+	struct ftrace_graph_ent trace;
+	int err;
+
+	if (unlikely(atomic_read(&current->tracing_graph_pause)))
+		return;
+
+	/*
+	 * Note:
+	 * No protection against faulting at *parent, which may be seen
+	 * on other archs. It's unlikely on AArch64.
+	 */
+	old = *parent;
+	*parent = return_hooker;
+
+	trace.func = self_addr;
+	trace.depth = current->curr_ret_stack + 1;
+
+	/* Only trace if the calling function expects to */
+	if (!ftrace_graph_entry(&trace)) {
+		*parent = old;
+		return;
+	}
+
+	err = ftrace_push_return_trace(old, self_addr, &trace.depth,
+				       frame_pointer);
+	if (err == -EBUSY) {
+		*parent = old;
+		return;
+	}
+}
+#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 235+ messages in thread

* [PATCH v3 2/6] arm64: ftrace: Add dynamic ftrace support
  2014-02-07 10:18   ` AKASHI Takahiro
@ 2014-02-07 10:18     ` AKASHI Takahiro
  -1 siblings, 0 replies; 235+ messages in thread
From: AKASHI Takahiro @ 2014-02-07 10:18 UTC (permalink / raw)
  To: rostedt, fweisbec, mingo, catalin.marinas, will.deacon,
	gkulkarni, tim.bird
  Cc: arndb, linux-arm-kernel, linaro-kernel, linux-kernel, patches,
	AKASHI Takahiro

This patch allows "dynamic ftrace" if CONFIG_DYNAMIC_FTRACE is enabled.
Here we can turn on and off tracing dynamically per-function base.

On arm64, this is done by patching single branch instruction to _mcount()
inserted by gcc -pg option. The branch is replaced to NOP initially at
kernel start up, and later on, NOP to branch to ftrace_caller() when
enabled or branch to NOP when disabled.
Please note that ftrace_caller() is a counterpart of _mcount() in case of
'static' ftrace.

More details on architecture specific requirements are described in
Documentation/trace/ftrace-design.txt.

Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
---
 arch/arm64/Kconfig               |    1 +
 arch/arm64/include/asm/ftrace.h  |   17 ++++++
 arch/arm64/kernel/entry-ftrace.S |   43 +++++++++++++++
 arch/arm64/kernel/ftrace.c       |  113 ++++++++++++++++++++++++++++++++++++++
 4 files changed, 174 insertions(+)

diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 332e50c..4d81791 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -32,6 +32,7 @@ config ARM64
 	select HAVE_DMA_API_DEBUG
 	select HAVE_DMA_ATTRS
 	select HAVE_DMA_CONTIGUOUS
+	select HAVE_DYNAMIC_FTRACE
 	select HAVE_EFFICIENT_UNALIGNED_ACCESS
 	select HAVE_FUNCTION_TRACER
 	select HAVE_FUNCTION_GRAPH_TRACER
diff --git a/arch/arm64/include/asm/ftrace.h b/arch/arm64/include/asm/ftrace.h
index 0d5dfdb..37a379d 100644
--- a/arch/arm64/include/asm/ftrace.h
+++ b/arch/arm64/include/asm/ftrace.h
@@ -17,6 +17,23 @@
 
 #ifndef __ASSEMBLY__
 extern void _mcount(unsigned long);
+
+#ifdef CONFIG_DYNAMIC_FTRACE
+struct dyn_arch_ftrace {
+	/* No extra data needed for arm64 */
+};
+
+extern unsigned long ftrace_graph_call;
+
+static inline unsigned long ftrace_call_adjust(unsigned long addr)
+{
+	/*
+	 * addr is the address of the mcount call instruction.
+	 * recordmcount does the necessary offset calculation.
+	 */
+	return addr;
+}
+#endif /* CONFIG_DYNAMIC_FTRACE */
 #endif /* __ASSEMBLY__ */
 #endif /* CONFIG_FUNCTION_TRACER */
 
diff --git a/arch/arm64/kernel/entry-ftrace.S b/arch/arm64/kernel/entry-ftrace.S
index 065f426..d8dd298 100644
--- a/arch/arm64/kernel/entry-ftrace.S
+++ b/arch/arm64/kernel/entry-ftrace.S
@@ -83,6 +83,7 @@
 	add	\reg, \reg, #8
 	.endm
 
+#ifndef CONFIG_DYNAMIC_FTRACE
 /*
  * void _mcount(unsigned long return_address)
  * @return_address: return address to instrumented function
@@ -131,6 +132,48 @@ skip_ftrace_call:
 #endif /* CONFIG_FUNCTION_GRAPH_TRACER */
 ENDPROC(_mcount)
 
+#else /* CONFIG_DYNAMIC_FTRACE */
+/*
+ * _mcount() is used to build the kernel with -pg option, but all the branch
+ * instructions to _mcount() are replaced to NOP initially at kernel start up,
+ * and later on, NOP to branch to ftrace_caller() when enabled or branch to
+ * NOP when disabled per-function base.
+ */
+ENTRY(_mcount)
+	ret
+ENDPROC(_mcount)
+
+/*
+ * void ftrace_caller(unsigned long return_address)
+ * @return_address: return address to instrumented function
+ *
+ * This function is a counterpart of _mcount() in 'static' ftrace, and
+ * makes calls to:
+ *     - tracer function to probe instrumented function's entry,
+ *     - ftrace_graph_caller to set up an exit hook
+ */
+ENTRY(ftrace_caller)
+	mcount_enter
+
+	mcount_get_pc0	x0		//     function's pc
+	mcount_get_lr	x1		//     function's lr
+
+	.global ftrace_call
+ftrace_call:				// tracer(pc, lr);
+	nop				// This will be replaced with "bl xxx"
+					// where xxx can be any kind of tracer.
+
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+	.global ftrace_graph_call
+ftrace_graph_call:			// ftrace_graph_caller();
+	nop				// If enabled, this will be replaced
+					// "b ftrace_graph_caller"
+#endif
+
+	mcount_exit
+ENDPROC(ftrace_caller)
+#endif /* CONFIG_DYNAMIC_FTRACE */
+
 ENTRY(ftrace_stub)
 	ret
 ENDPROC(ftrace_stub)
diff --git a/arch/arm64/kernel/ftrace.c b/arch/arm64/kernel/ftrace.c
index a559ab8..8c26476 100644
--- a/arch/arm64/kernel/ftrace.c
+++ b/arch/arm64/kernel/ftrace.c
@@ -17,6 +17,89 @@
 #include <asm/ftrace.h>
 #include <asm/insn.h>
 
+#ifdef CONFIG_DYNAMIC_FTRACE
+/*
+ * Replace a single instruction, which may be a branch or NOP.
+ * If @validate == true, a replaced instruction is checked against 'old'.
+ */
+static int ftrace_modify_code(unsigned long pc, unsigned int old,
+			      unsigned int new, bool validate)
+{
+	unsigned int replaced;
+
+	/*
+	 * Note:
+	 * Due to modules and __init, code can disappear and change,
+	 * we need to protect against faulting as well as code changing.
+	 * We do this by aarch64_insn_*() which use the probe_kernel_*().
+	 *
+	 * No lock is held here because all the modifications are run
+	 * through stop_machine().
+	 */
+	if (validate) {
+		if (aarch64_insn_read((void *)pc, &replaced))
+			return -EFAULT;
+
+		if (replaced != old)
+			return -EINVAL;
+	}
+	if (aarch64_insn_patch_text_nosync((void *)pc, new))
+		return -EPERM;
+
+	return 0;
+}
+
+/*
+ * Replace tracer function in ftrace_caller()
+ */
+int ftrace_update_ftrace_func(ftrace_func_t func)
+{
+	unsigned long pc;
+	unsigned int new;
+
+	pc = (unsigned long)&ftrace_call;
+	new = aarch64_insn_gen_branch_imm(pc, (unsigned long)func, true);
+
+	return ftrace_modify_code(pc, 0, new, false);
+}
+
+/*
+ * Turn on the call to ftrace_caller() in instrumented function
+ */
+int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
+{
+	unsigned long pc = rec->ip;
+	unsigned int old, new;
+
+	old = aarch64_insn_gen_nop();
+	new = aarch64_insn_gen_branch_imm(pc, addr, true);
+
+	return ftrace_modify_code(pc, old, new, true);
+}
+
+/*
+ * Turn off the call to ftrace_caller() in instrumented function
+ */
+int ftrace_make_nop(struct module *mod,
+		    struct dyn_ftrace *rec, unsigned long addr)
+{
+	unsigned long pc = rec->ip;
+	unsigned int old, new;
+
+	old = aarch64_insn_gen_branch_imm(pc, addr, true);
+	new = aarch64_insn_gen_nop();
+
+	return ftrace_modify_code(pc, old, new, true);
+}
+
+int __init ftrace_dyn_arch_init(void *data)
+{
+	*(unsigned long *)data = 0;
+
+	return 0;
+}
+#endif /* CONFIG_DYNAMIC_FTRACE */
+
 #ifdef CONFIG_FUNCTION_GRAPH_TRACER
 /*
  * function_graph tracer expects ftrace_return_to_handler() to be called
@@ -61,4 +144,34 @@ void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr,
 		return;
 	}
 }
+
+#ifdef CONFIG_DYNAMIC_FTRACE
+/*
+ * Turn on/off the call to ftrace_graph_caller() in ftrace_caller()
+ * depending on @enable.
+ */
+static int ftrace_modify_graph_caller(bool enable)
+{
+	unsigned long pc = (unsigned long)&ftrace_graph_call;
+	unsigned int branch, nop, old, new;
+
+	branch = aarch64_insn_gen_branch_imm(pc,
+			(unsigned long)ftrace_graph_caller, false);
+	nop = aarch64_insn_gen_nop();
+	old = enable ? nop : branch;
+	new = enable ? branch : nop;
+
+	return ftrace_modify_code(pc, old, new, true);
+}
+
+int ftrace_enable_ftrace_graph_caller(void)
+{
+	return ftrace_modify_graph_caller(true);
+}
+
+int ftrace_disable_ftrace_graph_caller(void)
+{
+	return ftrace_modify_graph_caller(false);
+}
+#endif /* CONFIG_DYNAMIC_FTRACE */
 #endif /* CONFIG_FUNCTION_GRAPH_TRACER */
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 235+ messages in thread

* [PATCH v3 2/6] arm64: ftrace: Add dynamic ftrace support
@ 2014-02-07 10:18     ` AKASHI Takahiro
  0 siblings, 0 replies; 235+ messages in thread
From: AKASHI Takahiro @ 2014-02-07 10:18 UTC (permalink / raw)
  To: linux-arm-kernel

This patch allows "dynamic ftrace" if CONFIG_DYNAMIC_FTRACE is enabled.
Here we can turn on and off tracing dynamically per-function base.

On arm64, this is done by patching single branch instruction to _mcount()
inserted by gcc -pg option. The branch is replaced to NOP initially at
kernel start up, and later on, NOP to branch to ftrace_caller() when
enabled or branch to NOP when disabled.
Please note that ftrace_caller() is a counterpart of _mcount() in case of
'static' ftrace.

More details on architecture specific requirements are described in
Documentation/trace/ftrace-design.txt.

Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
---
 arch/arm64/Kconfig               |    1 +
 arch/arm64/include/asm/ftrace.h  |   17 ++++++
 arch/arm64/kernel/entry-ftrace.S |   43 +++++++++++++++
 arch/arm64/kernel/ftrace.c       |  113 ++++++++++++++++++++++++++++++++++++++
 4 files changed, 174 insertions(+)

diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 332e50c..4d81791 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -32,6 +32,7 @@ config ARM64
 	select HAVE_DMA_API_DEBUG
 	select HAVE_DMA_ATTRS
 	select HAVE_DMA_CONTIGUOUS
+	select HAVE_DYNAMIC_FTRACE
 	select HAVE_EFFICIENT_UNALIGNED_ACCESS
 	select HAVE_FUNCTION_TRACER
 	select HAVE_FUNCTION_GRAPH_TRACER
diff --git a/arch/arm64/include/asm/ftrace.h b/arch/arm64/include/asm/ftrace.h
index 0d5dfdb..37a379d 100644
--- a/arch/arm64/include/asm/ftrace.h
+++ b/arch/arm64/include/asm/ftrace.h
@@ -17,6 +17,23 @@
 
 #ifndef __ASSEMBLY__
 extern void _mcount(unsigned long);
+
+#ifdef CONFIG_DYNAMIC_FTRACE
+struct dyn_arch_ftrace {
+	/* No extra data needed for arm64 */
+};
+
+extern unsigned long ftrace_graph_call;
+
+static inline unsigned long ftrace_call_adjust(unsigned long addr)
+{
+	/*
+	 * addr is the address of the mcount call instruction.
+	 * recordmcount does the necessary offset calculation.
+	 */
+	return addr;
+}
+#endif /* CONFIG_DYNAMIC_FTRACE */
 #endif /* __ASSEMBLY__ */
 #endif /* CONFIG_FUNCTION_TRACER */
 
diff --git a/arch/arm64/kernel/entry-ftrace.S b/arch/arm64/kernel/entry-ftrace.S
index 065f426..d8dd298 100644
--- a/arch/arm64/kernel/entry-ftrace.S
+++ b/arch/arm64/kernel/entry-ftrace.S
@@ -83,6 +83,7 @@
 	add	\reg, \reg, #8
 	.endm
 
+#ifndef CONFIG_DYNAMIC_FTRACE
 /*
  * void _mcount(unsigned long return_address)
  * @return_address: return address to instrumented function
@@ -131,6 +132,48 @@ skip_ftrace_call:
 #endif /* CONFIG_FUNCTION_GRAPH_TRACER */
 ENDPROC(_mcount)
 
+#else /* CONFIG_DYNAMIC_FTRACE */
+/*
+ * _mcount() is used to build the kernel with -pg option, but all the branch
+ * instructions to _mcount() are replaced to NOP initially at kernel start up,
+ * and later on, NOP to branch to ftrace_caller() when enabled or branch to
+ * NOP when disabled per-function base.
+ */
+ENTRY(_mcount)
+	ret
+ENDPROC(_mcount)
+
+/*
+ * void ftrace_caller(unsigned long return_address)
+ * @return_address: return address to instrumented function
+ *
+ * This function is a counterpart of _mcount() in 'static' ftrace, and
+ * makes calls to:
+ *     - tracer function to probe instrumented function's entry,
+ *     - ftrace_graph_caller to set up an exit hook
+ */
+ENTRY(ftrace_caller)
+	mcount_enter
+
+	mcount_get_pc0	x0		//     function's pc
+	mcount_get_lr	x1		//     function's lr
+
+	.global ftrace_call
+ftrace_call:				// tracer(pc, lr);
+	nop				// This will be replaced with "bl xxx"
+					// where xxx can be any kind of tracer.
+
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+	.global ftrace_graph_call
+ftrace_graph_call:			// ftrace_graph_caller();
+	nop				// If enabled, this will be replaced
+					// "b ftrace_graph_caller"
+#endif
+
+	mcount_exit
+ENDPROC(ftrace_caller)
+#endif /* CONFIG_DYNAMIC_FTRACE */
+
 ENTRY(ftrace_stub)
 	ret
 ENDPROC(ftrace_stub)
diff --git a/arch/arm64/kernel/ftrace.c b/arch/arm64/kernel/ftrace.c
index a559ab8..8c26476 100644
--- a/arch/arm64/kernel/ftrace.c
+++ b/arch/arm64/kernel/ftrace.c
@@ -17,6 +17,89 @@
 #include <asm/ftrace.h>
 #include <asm/insn.h>
 
+#ifdef CONFIG_DYNAMIC_FTRACE
+/*
+ * Replace a single instruction, which may be a branch or NOP.
+ * If @validate == true, a replaced instruction is checked against 'old'.
+ */
+static int ftrace_modify_code(unsigned long pc, unsigned int old,
+			      unsigned int new, bool validate)
+{
+	unsigned int replaced;
+
+	/*
+	 * Note:
+	 * Due to modules and __init, code can disappear and change,
+	 * we need to protect against faulting as well as code changing.
+	 * We do this by aarch64_insn_*() which use the probe_kernel_*().
+	 *
+	 * No lock is held here because all the modifications are run
+	 * through stop_machine().
+	 */
+	if (validate) {
+		if (aarch64_insn_read((void *)pc, &replaced))
+			return -EFAULT;
+
+		if (replaced != old)
+			return -EINVAL;
+	}
+	if (aarch64_insn_patch_text_nosync((void *)pc, new))
+		return -EPERM;
+
+	return 0;
+}
+
+/*
+ * Replace tracer function in ftrace_caller()
+ */
+int ftrace_update_ftrace_func(ftrace_func_t func)
+{
+	unsigned long pc;
+	unsigned int new;
+
+	pc = (unsigned long)&ftrace_call;
+	new = aarch64_insn_gen_branch_imm(pc, (unsigned long)func, true);
+
+	return ftrace_modify_code(pc, 0, new, false);
+}
+
+/*
+ * Turn on the call to ftrace_caller() in instrumented function
+ */
+int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
+{
+	unsigned long pc = rec->ip;
+	unsigned int old, new;
+
+	old = aarch64_insn_gen_nop();
+	new = aarch64_insn_gen_branch_imm(pc, addr, true);
+
+	return ftrace_modify_code(pc, old, new, true);
+}
+
+/*
+ * Turn off the call to ftrace_caller() in instrumented function
+ */
+int ftrace_make_nop(struct module *mod,
+		    struct dyn_ftrace *rec, unsigned long addr)
+{
+	unsigned long pc = rec->ip;
+	unsigned int old, new;
+
+	old = aarch64_insn_gen_branch_imm(pc, addr, true);
+	new = aarch64_insn_gen_nop();
+
+	return ftrace_modify_code(pc, old, new, true);
+}
+
+int __init ftrace_dyn_arch_init(void *data)
+{
+	*(unsigned long *)data = 0;
+
+	return 0;
+}
+#endif /* CONFIG_DYNAMIC_FTRACE */
+
 #ifdef CONFIG_FUNCTION_GRAPH_TRACER
 /*
  * function_graph tracer expects ftrace_return_to_handler() to be called
@@ -61,4 +144,34 @@ void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr,
 		return;
 	}
 }
+
+#ifdef CONFIG_DYNAMIC_FTRACE
+/*
+ * Turn on/off the call to ftrace_graph_caller() in ftrace_caller()
+ * depending on @enable.
+ */
+static int ftrace_modify_graph_caller(bool enable)
+{
+	unsigned long pc = (unsigned long)&ftrace_graph_call;
+	unsigned int branch, nop, old, new;
+
+	branch = aarch64_insn_gen_branch_imm(pc,
+			(unsigned long)ftrace_graph_caller, false);
+	nop = aarch64_insn_gen_nop();
+	old = enable ? nop : branch;
+	new = enable ? branch : nop;
+
+	return ftrace_modify_code(pc, old, new, true);
+}
+
+int ftrace_enable_ftrace_graph_caller(void)
+{
+	return ftrace_modify_graph_caller(true);
+}
+
+int ftrace_disable_ftrace_graph_caller(void)
+{
+	return ftrace_modify_graph_caller(false);
+}
+#endif /* CONFIG_DYNAMIC_FTRACE */
 #endif /* CONFIG_FUNCTION_GRAPH_TRACER */
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 235+ messages in thread

* [PATCH v3 3/6] arm64: ftrace: Add CALLER_ADDRx macros
  2014-02-07 10:18   ` AKASHI Takahiro
@ 2014-02-07 10:18     ` AKASHI Takahiro
  -1 siblings, 0 replies; 235+ messages in thread
From: AKASHI Takahiro @ 2014-02-07 10:18 UTC (permalink / raw)
  To: rostedt, fweisbec, mingo, catalin.marinas, will.deacon,
	gkulkarni, tim.bird
  Cc: arndb, linux-arm-kernel, linaro-kernel, linux-kernel, patches,
	AKASHI Takahiro

CALLER_ADDRx returns caller's address at specified level in call stacks.
They are used for several tracers like irqsoff and preemptoff.
Strange to say, however, they are refered even without FTRACE.

Please note that this implementation assumes that we have frame pointers.
(which means kernel should be compiled with -fno-omit-frame-pointer.)

Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
---
 arch/arm64/include/asm/ftrace.h    |   14 +++++++++
 arch/arm64/kernel/Makefile         |    3 +-
 arch/arm64/kernel/return_address.c |   55 ++++++++++++++++++++++++++++++++++++
 3 files changed, 71 insertions(+), 1 deletion(-)
 create mode 100644 arch/arm64/kernel/return_address.c

diff --git a/arch/arm64/include/asm/ftrace.h b/arch/arm64/include/asm/ftrace.h
index 37a379d..4c6ac03 100644
--- a/arch/arm64/include/asm/ftrace.h
+++ b/arch/arm64/include/asm/ftrace.h
@@ -37,4 +37,18 @@ static inline unsigned long ftrace_call_adjust(unsigned long addr)
 #endif /* __ASSEMBLY__ */
 #endif /* CONFIG_FUNCTION_TRACER */
 
+#ifndef __ASSEMBLY__
+#define HAVE_ARCH_CALLER_ADDR
+
+extern void *return_address(unsigned int);
+
+#define CALLER_ADDR0 ((unsigned long)__builtin_return_address(0))
+#define CALLER_ADDR1 ((unsigned long)return_address(1))
+#define CALLER_ADDR2 ((unsigned long)return_address(2))
+#define CALLER_ADDR3 ((unsigned long)return_address(3))
+#define CALLER_ADDR4 ((unsigned long)return_address(4))
+#define CALLER_ADDR5 ((unsigned long)return_address(5))
+#define CALLER_ADDR6 ((unsigned long)return_address(6))
+#endif /* ifndef __ASSEMBLY__ */
+
 #endif /* __ASM_FTRACE_H */
diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile
index ca921fb..55e0b6e 100644
--- a/arch/arm64/kernel/Makefile
+++ b/arch/arm64/kernel/Makefile
@@ -9,12 +9,13 @@ ifdef CONFIG_FUNCTION_TRACER
 CFLAGS_REMOVE_ftrace.o = -pg
 CFLAGS_REMOVE_insn.o = -pg
 endif
+CFLAGS_REMOVE_return_address.o = -pg
 
 # Object file lists.
 arm64-obj-y		:= cputable.o debug-monitors.o entry.o irq.o fpsimd.o	\
 			   entry-fpsimd.o process.o ptrace.o setup.o signal.o	\
 			   sys.o stacktrace.o time.o traps.o io.o vdso.o	\
-			   hyp-stub.o psci.o cpu_ops.o insn.o
+			   hyp-stub.o psci.o cpu_ops.o insn.o return_address.o
 
 arm64-obj-$(CONFIG_COMPAT)		+= sys32.o kuser32.o signal32.o 	\
 					   sys_compat.o
diff --git a/arch/arm64/kernel/return_address.c b/arch/arm64/kernel/return_address.c
new file mode 100644
index 0000000..89102a6
--- /dev/null
+++ b/arch/arm64/kernel/return_address.c
@@ -0,0 +1,55 @@
+/*
+ * arch/arm64/kernel/return_address.c
+ *
+ * Copyright (C) 2013 Linaro Limited
+ * Author: AKASHI Takahiro <takahiro.akashi@linaro.org>
+ *
+ * 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 <linux/export.h>
+#include <linux/ftrace.h>
+
+#include <asm/stacktrace.h>
+
+struct return_address_data {
+	unsigned int level;
+	void *addr;
+};
+
+static int save_return_addr(struct stackframe *frame, void *d)
+{
+	struct return_address_data *data = d;
+
+	if (!data->level) {
+		data->addr = (void *)frame->pc;
+		return 1;
+	} else {
+		--data->level;
+		return 0;
+	}
+}
+
+void *return_address(unsigned int level)
+{
+	struct return_address_data data;
+	struct stackframe frame;
+	register unsigned long current_sp asm ("sp");
+
+	data.level = level + 2;
+	data.addr = NULL;
+
+	frame.fp = (unsigned long)__builtin_frame_address(0);
+	frame.sp = current_sp;
+	frame.pc = (unsigned long)return_address; /* dummy */
+
+	walk_stackframe(&frame, save_return_addr, &data);
+
+	if (!data.level)
+		return data.addr;
+	else
+		return NULL;
+}
+EXPORT_SYMBOL_GPL(return_address);
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 235+ messages in thread

* [PATCH v3 3/6] arm64: ftrace: Add CALLER_ADDRx macros
@ 2014-02-07 10:18     ` AKASHI Takahiro
  0 siblings, 0 replies; 235+ messages in thread
From: AKASHI Takahiro @ 2014-02-07 10:18 UTC (permalink / raw)
  To: linux-arm-kernel

CALLER_ADDRx returns caller's address at specified level in call stacks.
They are used for several tracers like irqsoff and preemptoff.
Strange to say, however, they are refered even without FTRACE.

Please note that this implementation assumes that we have frame pointers.
(which means kernel should be compiled with -fno-omit-frame-pointer.)

Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
---
 arch/arm64/include/asm/ftrace.h    |   14 +++++++++
 arch/arm64/kernel/Makefile         |    3 +-
 arch/arm64/kernel/return_address.c |   55 ++++++++++++++++++++++++++++++++++++
 3 files changed, 71 insertions(+), 1 deletion(-)
 create mode 100644 arch/arm64/kernel/return_address.c

diff --git a/arch/arm64/include/asm/ftrace.h b/arch/arm64/include/asm/ftrace.h
index 37a379d..4c6ac03 100644
--- a/arch/arm64/include/asm/ftrace.h
+++ b/arch/arm64/include/asm/ftrace.h
@@ -37,4 +37,18 @@ static inline unsigned long ftrace_call_adjust(unsigned long addr)
 #endif /* __ASSEMBLY__ */
 #endif /* CONFIG_FUNCTION_TRACER */
 
+#ifndef __ASSEMBLY__
+#define HAVE_ARCH_CALLER_ADDR
+
+extern void *return_address(unsigned int);
+
+#define CALLER_ADDR0 ((unsigned long)__builtin_return_address(0))
+#define CALLER_ADDR1 ((unsigned long)return_address(1))
+#define CALLER_ADDR2 ((unsigned long)return_address(2))
+#define CALLER_ADDR3 ((unsigned long)return_address(3))
+#define CALLER_ADDR4 ((unsigned long)return_address(4))
+#define CALLER_ADDR5 ((unsigned long)return_address(5))
+#define CALLER_ADDR6 ((unsigned long)return_address(6))
+#endif /* ifndef __ASSEMBLY__ */
+
 #endif /* __ASM_FTRACE_H */
diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile
index ca921fb..55e0b6e 100644
--- a/arch/arm64/kernel/Makefile
+++ b/arch/arm64/kernel/Makefile
@@ -9,12 +9,13 @@ ifdef CONFIG_FUNCTION_TRACER
 CFLAGS_REMOVE_ftrace.o = -pg
 CFLAGS_REMOVE_insn.o = -pg
 endif
+CFLAGS_REMOVE_return_address.o = -pg
 
 # Object file lists.
 arm64-obj-y		:= cputable.o debug-monitors.o entry.o irq.o fpsimd.o	\
 			   entry-fpsimd.o process.o ptrace.o setup.o signal.o	\
 			   sys.o stacktrace.o time.o traps.o io.o vdso.o	\
-			   hyp-stub.o psci.o cpu_ops.o insn.o
+			   hyp-stub.o psci.o cpu_ops.o insn.o return_address.o
 
 arm64-obj-$(CONFIG_COMPAT)		+= sys32.o kuser32.o signal32.o 	\
 					   sys_compat.o
diff --git a/arch/arm64/kernel/return_address.c b/arch/arm64/kernel/return_address.c
new file mode 100644
index 0000000..89102a6
--- /dev/null
+++ b/arch/arm64/kernel/return_address.c
@@ -0,0 +1,55 @@
+/*
+ * arch/arm64/kernel/return_address.c
+ *
+ * Copyright (C) 2013 Linaro Limited
+ * Author: AKASHI Takahiro <takahiro.akashi@linaro.org>
+ *
+ * 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 <linux/export.h>
+#include <linux/ftrace.h>
+
+#include <asm/stacktrace.h>
+
+struct return_address_data {
+	unsigned int level;
+	void *addr;
+};
+
+static int save_return_addr(struct stackframe *frame, void *d)
+{
+	struct return_address_data *data = d;
+
+	if (!data->level) {
+		data->addr = (void *)frame->pc;
+		return 1;
+	} else {
+		--data->level;
+		return 0;
+	}
+}
+
+void *return_address(unsigned int level)
+{
+	struct return_address_data data;
+	struct stackframe frame;
+	register unsigned long current_sp asm ("sp");
+
+	data.level = level + 2;
+	data.addr = NULL;
+
+	frame.fp = (unsigned long)__builtin_frame_address(0);
+	frame.sp = current_sp;
+	frame.pc = (unsigned long)return_address; /* dummy */
+
+	walk_stackframe(&frame, save_return_addr, &data);
+
+	if (!data.level)
+		return data.addr;
+	else
+		return NULL;
+}
+EXPORT_SYMBOL_GPL(return_address);
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 235+ messages in thread

* [PATCH v3 4/6] ftrace: Add arm64 support to recordmcount
  2014-02-07 10:18   ` AKASHI Takahiro
@ 2014-02-07 10:18     ` AKASHI Takahiro
  -1 siblings, 0 replies; 235+ messages in thread
From: AKASHI Takahiro @ 2014-02-07 10:18 UTC (permalink / raw)
  To: rostedt, fweisbec, mingo, catalin.marinas, will.deacon,
	gkulkarni, tim.bird
  Cc: arndb, linux-arm-kernel, linaro-kernel, linux-kernel, patches,
	AKASHI Takahiro

Recordmcount utility under scripts is run, after compiling each object,
to find out all the locations of calling _mcount() and put them into
specific seciton named __mcount_loc.
Then linker collects all such information into a table in the kernel image
(between __start_mcount_loc and __stop_mcount_loc) for later use by ftrace.

This patch adds arm64 specific definitions to identify such locations.
There are two types of implementation, C and Perl. On arm64, only C version
is used to build the kernel now that CONFIG_HAVE_C_RECORDMCOUNT is on.
But Perl version is also maintained.

Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
---
 arch/arm64/Kconfig      |    2 ++
 scripts/recordmcount.c  |    4 ++++
 scripts/recordmcount.pl |    5 +++++
 3 files changed, 11 insertions(+)

diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 4d81791..43fce76 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -27,6 +27,7 @@ config ARM64
 	select HARDIRQS_SW_RESEND
 	select HAVE_ARCH_JUMP_LABEL
 	select HAVE_ARCH_TRACEHOOK
+	select HAVE_C_RECORDMCOUNT
 	select HAVE_DEBUG_BUGVERBOSE
 	select HAVE_DEBUG_KMEMLEAK
 	select HAVE_DMA_API_DEBUG
@@ -34,6 +35,7 @@ config ARM64
 	select HAVE_DMA_CONTIGUOUS
 	select HAVE_DYNAMIC_FTRACE
 	select HAVE_EFFICIENT_UNALIGNED_ACCESS
+	select HAVE_FTRACE_MCOUNT_RECORD
 	select HAVE_FUNCTION_TRACER
 	select HAVE_FUNCTION_GRAPH_TRACER
 	select HAVE_GENERIC_DMA_COHERENT
diff --git a/scripts/recordmcount.c b/scripts/recordmcount.c
index 9c22317..b92d9f7 100644
--- a/scripts/recordmcount.c
+++ b/scripts/recordmcount.c
@@ -347,6 +347,10 @@ do_file(char const *const fname)
 	case EM_ARM:	 reltype = R_ARM_ABS32;
 			 altmcount = "__gnu_mcount_nc";
 			 break;
+	case EM_AARCH64:
+			 reltype = R_AARCH64_ABS64;
+			 altmcount = "_mcount";
+			 break;
 	case EM_IA_64:	 reltype = R_IA64_IMM64;   gpfx = '_'; break;
 	case EM_METAG:	 reltype = R_METAG_ADDR32;
 			 altmcount = "_mcount_wrapper";
diff --git a/scripts/recordmcount.pl b/scripts/recordmcount.pl
index 91280b8..397b6b8 100755
--- a/scripts/recordmcount.pl
+++ b/scripts/recordmcount.pl
@@ -279,6 +279,11 @@ if ($arch eq "x86_64") {
     $mcount_regex = "^\\s*([0-9a-fA-F]+):\\s*R_ARM_(CALL|PC24|THM_CALL)" .
 			"\\s+(__gnu_mcount_nc|mcount)\$";
 
+} elsif ($arch eq "arm64") {
+    $alignment = 3;
+    $section_type = '%progbits';
+    $mcount_regex = "^\\s*([0-9a-fA-F]+):\\s*R_AARCH64_CALL26\\s+_mcount\$";
+    $type = ".quad";
 } elsif ($arch eq "ia64") {
     $mcount_regex = "^\\s*([0-9a-fA-F]+):.*\\s_mcount\$";
     $type = "data8";
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 235+ messages in thread

* [PATCH v3 4/6] ftrace: Add arm64 support to recordmcount
@ 2014-02-07 10:18     ` AKASHI Takahiro
  0 siblings, 0 replies; 235+ messages in thread
From: AKASHI Takahiro @ 2014-02-07 10:18 UTC (permalink / raw)
  To: linux-arm-kernel

Recordmcount utility under scripts is run, after compiling each object,
to find out all the locations of calling _mcount() and put them into
specific seciton named __mcount_loc.
Then linker collects all such information into a table in the kernel image
(between __start_mcount_loc and __stop_mcount_loc) for later use by ftrace.

This patch adds arm64 specific definitions to identify such locations.
There are two types of implementation, C and Perl. On arm64, only C version
is used to build the kernel now that CONFIG_HAVE_C_RECORDMCOUNT is on.
But Perl version is also maintained.

Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
---
 arch/arm64/Kconfig      |    2 ++
 scripts/recordmcount.c  |    4 ++++
 scripts/recordmcount.pl |    5 +++++
 3 files changed, 11 insertions(+)

diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 4d81791..43fce76 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -27,6 +27,7 @@ config ARM64
 	select HARDIRQS_SW_RESEND
 	select HAVE_ARCH_JUMP_LABEL
 	select HAVE_ARCH_TRACEHOOK
+	select HAVE_C_RECORDMCOUNT
 	select HAVE_DEBUG_BUGVERBOSE
 	select HAVE_DEBUG_KMEMLEAK
 	select HAVE_DMA_API_DEBUG
@@ -34,6 +35,7 @@ config ARM64
 	select HAVE_DMA_CONTIGUOUS
 	select HAVE_DYNAMIC_FTRACE
 	select HAVE_EFFICIENT_UNALIGNED_ACCESS
+	select HAVE_FTRACE_MCOUNT_RECORD
 	select HAVE_FUNCTION_TRACER
 	select HAVE_FUNCTION_GRAPH_TRACER
 	select HAVE_GENERIC_DMA_COHERENT
diff --git a/scripts/recordmcount.c b/scripts/recordmcount.c
index 9c22317..b92d9f7 100644
--- a/scripts/recordmcount.c
+++ b/scripts/recordmcount.c
@@ -347,6 +347,10 @@ do_file(char const *const fname)
 	case EM_ARM:	 reltype = R_ARM_ABS32;
 			 altmcount = "__gnu_mcount_nc";
 			 break;
+	case EM_AARCH64:
+			 reltype = R_AARCH64_ABS64;
+			 altmcount = "_mcount";
+			 break;
 	case EM_IA_64:	 reltype = R_IA64_IMM64;   gpfx = '_'; break;
 	case EM_METAG:	 reltype = R_METAG_ADDR32;
 			 altmcount = "_mcount_wrapper";
diff --git a/scripts/recordmcount.pl b/scripts/recordmcount.pl
index 91280b8..397b6b8 100755
--- a/scripts/recordmcount.pl
+++ b/scripts/recordmcount.pl
@@ -279,6 +279,11 @@ if ($arch eq "x86_64") {
     $mcount_regex = "^\\s*([0-9a-fA-F]+):\\s*R_ARM_(CALL|PC24|THM_CALL)" .
 			"\\s+(__gnu_mcount_nc|mcount)\$";
 
+} elsif ($arch eq "arm64") {
+    $alignment = 3;
+    $section_type = '%progbits';
+    $mcount_regex = "^\\s*([0-9a-fA-F]+):\\s*R_AARCH64_CALL26\\s+_mcount\$";
+    $type = ".quad";
 } elsif ($arch eq "ia64") {
     $mcount_regex = "^\\s*([0-9a-fA-F]+):.*\\s_mcount\$";
     $type = "data8";
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 235+ messages in thread

* [PATCH v3 5/6] arm64: ftrace: Add system call tracepoint
  2014-02-07 10:18   ` AKASHI Takahiro
@ 2014-02-07 10:18     ` AKASHI Takahiro
  -1 siblings, 0 replies; 235+ messages in thread
From: AKASHI Takahiro @ 2014-02-07 10:18 UTC (permalink / raw)
  To: rostedt, fweisbec, mingo, catalin.marinas, will.deacon,
	gkulkarni, tim.bird
  Cc: arndb, linux-arm-kernel, linaro-kernel, linux-kernel, patches,
	AKASHI Takahiro

This patch allows system call entry or exit to be traced as ftrace events,
ie. sys_enter_*/sys_exit_*, if CONFIG_FTRACE_SYSCALLS is enabled.
Those events appear and can be controlled under
    ${sysfs}/tracing/events/syscalls/

Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
---
 arch/arm64/Kconfig               |    1 +
 arch/arm64/include/asm/syscall.h |    1 +
 arch/arm64/include/asm/unistd.h  |    2 ++
 arch/arm64/kernel/ptrace.c       |    5 +++++
 4 files changed, 9 insertions(+)

diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 43fce76..9bdaf5c 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -42,6 +42,7 @@ config ARM64
 	select HAVE_HW_BREAKPOINT if PERF_EVENTS
 	select HAVE_MEMBLOCK
 	select HAVE_PERF_EVENTS
+	select HAVE_SYSCALL_TRACEPOINTS
 	select IRQ_DOMAIN
 	select MODULES_USE_ELF_RELA
 	select NO_BOOTMEM
diff --git a/arch/arm64/include/asm/syscall.h b/arch/arm64/include/asm/syscall.h
index 70ba9d4..383771e 100644
--- a/arch/arm64/include/asm/syscall.h
+++ b/arch/arm64/include/asm/syscall.h
@@ -18,6 +18,7 @@
 
 #include <linux/err.h>
 
+extern const void *sys_call_table[];
 
 static inline int syscall_get_nr(struct task_struct *task,
 				 struct pt_regs *regs)
diff --git a/arch/arm64/include/asm/unistd.h b/arch/arm64/include/asm/unistd.h
index 82ce217..c335479 100644
--- a/arch/arm64/include/asm/unistd.h
+++ b/arch/arm64/include/asm/unistd.h
@@ -28,3 +28,5 @@
 #endif
 #define __ARCH_WANT_SYS_CLONE
 #include <uapi/asm/unistd.h>
+
+#define NR_syscalls (__NR_syscalls)
diff --git a/arch/arm64/kernel/ptrace.c b/arch/arm64/kernel/ptrace.c
index 64ce39f..f4c3c4e 100644
--- a/arch/arm64/kernel/ptrace.c
+++ b/arch/arm64/kernel/ptrace.c
@@ -41,6 +41,9 @@
 #include <asm/traps.h>
 #include <asm/system_misc.h>
 
+#define CREATE_TRACE_POINTS
+#include <trace/events/syscalls.h>
+
 /*
  * TODO: does not yet catch signals sent when the child dies.
  * in exit.c or in signal.c.
@@ -1076,10 +1079,12 @@ asmlinkage int syscall_trace(int dir, struct pt_regs *regs)
 	}
 
 	if (dir) {
+		trace_sys_exit(regs, regs->syscallno);
 		tracehook_report_syscall_exit(regs, 0);
 	} else {
 		if (tracehook_report_syscall_entry(regs))
 			regs->syscallno = ~0UL;
+		trace_sys_enter(regs, regs->syscallno);
 	}
 
 	if (is_compat_task())
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 235+ messages in thread

* [PATCH v3 5/6] arm64: ftrace: Add system call tracepoint
@ 2014-02-07 10:18     ` AKASHI Takahiro
  0 siblings, 0 replies; 235+ messages in thread
From: AKASHI Takahiro @ 2014-02-07 10:18 UTC (permalink / raw)
  To: linux-arm-kernel

This patch allows system call entry or exit to be traced as ftrace events,
ie. sys_enter_*/sys_exit_*, if CONFIG_FTRACE_SYSCALLS is enabled.
Those events appear and can be controlled under
    ${sysfs}/tracing/events/syscalls/

Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
---
 arch/arm64/Kconfig               |    1 +
 arch/arm64/include/asm/syscall.h |    1 +
 arch/arm64/include/asm/unistd.h  |    2 ++
 arch/arm64/kernel/ptrace.c       |    5 +++++
 4 files changed, 9 insertions(+)

diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 43fce76..9bdaf5c 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -42,6 +42,7 @@ config ARM64
 	select HAVE_HW_BREAKPOINT if PERF_EVENTS
 	select HAVE_MEMBLOCK
 	select HAVE_PERF_EVENTS
+	select HAVE_SYSCALL_TRACEPOINTS
 	select IRQ_DOMAIN
 	select MODULES_USE_ELF_RELA
 	select NO_BOOTMEM
diff --git a/arch/arm64/include/asm/syscall.h b/arch/arm64/include/asm/syscall.h
index 70ba9d4..383771e 100644
--- a/arch/arm64/include/asm/syscall.h
+++ b/arch/arm64/include/asm/syscall.h
@@ -18,6 +18,7 @@
 
 #include <linux/err.h>
 
+extern const void *sys_call_table[];
 
 static inline int syscall_get_nr(struct task_struct *task,
 				 struct pt_regs *regs)
diff --git a/arch/arm64/include/asm/unistd.h b/arch/arm64/include/asm/unistd.h
index 82ce217..c335479 100644
--- a/arch/arm64/include/asm/unistd.h
+++ b/arch/arm64/include/asm/unistd.h
@@ -28,3 +28,5 @@
 #endif
 #define __ARCH_WANT_SYS_CLONE
 #include <uapi/asm/unistd.h>
+
+#define NR_syscalls (__NR_syscalls)
diff --git a/arch/arm64/kernel/ptrace.c b/arch/arm64/kernel/ptrace.c
index 64ce39f..f4c3c4e 100644
--- a/arch/arm64/kernel/ptrace.c
+++ b/arch/arm64/kernel/ptrace.c
@@ -41,6 +41,9 @@
 #include <asm/traps.h>
 #include <asm/system_misc.h>
 
+#define CREATE_TRACE_POINTS
+#include <trace/events/syscalls.h>
+
 /*
  * TODO: does not yet catch signals sent when the child dies.
  * in exit.c or in signal.c.
@@ -1076,10 +1079,12 @@ asmlinkage int syscall_trace(int dir, struct pt_regs *regs)
 	}
 
 	if (dir) {
+		trace_sys_exit(regs, regs->syscallno);
 		tracehook_report_syscall_exit(regs, 0);
 	} else {
 		if (tracehook_report_syscall_entry(regs))
 			regs->syscallno = ~0UL;
+		trace_sys_enter(regs, regs->syscallno);
 	}
 
 	if (is_compat_task())
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 235+ messages in thread

* [PATCH v3 6/6] arm64: Add 'notrace' attribute to unwind_frame() for ftrace
  2014-02-07 10:18   ` AKASHI Takahiro
@ 2014-02-07 10:18     ` AKASHI Takahiro
  -1 siblings, 0 replies; 235+ messages in thread
From: AKASHI Takahiro @ 2014-02-07 10:18 UTC (permalink / raw)
  To: rostedt, fweisbec, mingo, catalin.marinas, will.deacon,
	gkulkarni, tim.bird
  Cc: arndb, linux-arm-kernel, linaro-kernel, linux-kernel, patches,
	AKASHI Takahiro

walk_stackframe() calls unwind_frame(), and if walk_stackframe() is
"notrace", unwind_frame() should be also "notrace".

Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
---
 arch/arm64/kernel/stacktrace.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm64/kernel/stacktrace.c b/arch/arm64/kernel/stacktrace.c
index c3b6c63..54122c4 100644
--- a/arch/arm64/kernel/stacktrace.c
+++ b/arch/arm64/kernel/stacktrace.c
@@ -35,7 +35,7 @@
  *	ldp	x29, x30, [sp]
  *	add	sp, sp, #0x10
  */
-int unwind_frame(struct stackframe *frame)
+int notrace unwind_frame(struct stackframe *frame)
 {
 	unsigned long high, low;
 	unsigned long fp = frame->fp;
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 235+ messages in thread

* [PATCH v3 6/6] arm64: Add 'notrace' attribute to unwind_frame() for ftrace
@ 2014-02-07 10:18     ` AKASHI Takahiro
  0 siblings, 0 replies; 235+ messages in thread
From: AKASHI Takahiro @ 2014-02-07 10:18 UTC (permalink / raw)
  To: linux-arm-kernel

walk_stackframe() calls unwind_frame(), and if walk_stackframe() is
"notrace", unwind_frame() should be also "notrace".

Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
---
 arch/arm64/kernel/stacktrace.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm64/kernel/stacktrace.c b/arch/arm64/kernel/stacktrace.c
index c3b6c63..54122c4 100644
--- a/arch/arm64/kernel/stacktrace.c
+++ b/arch/arm64/kernel/stacktrace.c
@@ -35,7 +35,7 @@
  *	ldp	x29, x30, [sp]
  *	add	sp, sp, #0x10
  */
-int unwind_frame(struct stackframe *frame)
+int notrace unwind_frame(struct stackframe *frame)
 {
 	unsigned long high, low;
 	unsigned long fp = frame->fp;
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 235+ messages in thread

* RE: [PATCH v3 0/6] arm64: Add ftrace support
  2014-02-07 10:18   ` AKASHI Takahiro
@ 2014-02-10 14:21     ` Kulkarni, Ganapatrao
  -1 siblings, 0 replies; 235+ messages in thread
From: Kulkarni, Ganapatrao @ 2014-02-10 14:21 UTC (permalink / raw)
  To: AKASHI Takahiro, rostedt, fweisbec, mingo, catalin.marinas,
	will.deacon, tim.bird
  Cc: arndb, linux-arm-kernel, linaro-kernel, linux-kernel, patches

Looks OK to me.

Reviewed-by: Ganapatrao Kulkarni <ganapatrao.kulkarni@cavium.com>

regards,
Ganapat

________________________________________
From: AKASHI Takahiro <takahiro.akashi@linaro.org>
Sent: Friday, February 7, 2014 3:48 PM
To: rostedt@goodmis.org; fweisbec@gmail.com; mingo@redhat.com; catalin.marinas@arm.com; will.deacon@arm.com; Kulkarni, Ganapatrao; tim.bird@sonymobile.com
Cc: arndb@arndb.de; linux-arm-kernel@lists.infradead.org; linaro-kernel@lists.linaro.org; linux-kernel@vger.kernel.org; patches@linaro.org; AKASHI Takahiro
Subject: [PATCH v3 0/6] arm64: Add ftrace support

This is my third version of patchset for ftrace support.
There was another implementation from Cavium network, but both of us agreed
to use my patchset as future base. He is supposed to review this code, too.

The only issue that I had some concern on was "fault protection" code
in prepare_ftrace_return(). With discussions with Steven and Tim (as author
of arm ftrace), I removed that code since I'm not quite sure about possibility
of "fault" occurrences in this function.

The code is tested on ARMv8 Fast Model with the following tracers & events:
     function tracer with dynamic ftrace
     function graph tracer with dynamic ftrace
     syscall tracepoint
     irqsoff & preemptirqsoff (which use CALLER_ADDRx)
and also verified with in-kernel tests, FTRACE_SELFTEST, FTRACE_STARTUP_TEST
and EVENT_TRACE_TEST_SYSCALLS.

Please be careful:
* elf.h on cross-build host must have AArch64 definitions, EM_AARCH64 and
  R_AARCH64_ABS64, to compile recordmcount utility. See [4/6].
  [4/6] also gets warnings from checkpatch, but they are based on the
  original's coding style.
* This patch may conflict with my audit patch because both changes the same
  location in syscall_trace(). I expect the functions are called in this
  order:
  On entry,
     * tracehook_report_syscall(ENTER)
     * trace_sys_enter()
     * audit_syscall_entry()
  On exit,
     * audit_sysscall_exit()
     * trace_sys_exit()
     * tracehook_report_syscall(EXIT)

Changes from v1 to v2:
* splitted one patch into some pieces for easier review
  (especially function tracer + dynamic ftrace + CALLER_ADDRx)
* put return_address() in a separate file
* renamed __mcount to _mcount (it was my mistake)
* changed stackframe handling to get parent's frame pointer
* removed ARCH_SUPPORTS_FTRACE_OPS
* switched to "hotpatch" interfaces from Huawai
* revised descriptions in comments

Changes from v2 to v3:
* optimized register usages in asm (by not saving x0, x1, and x2)
* removed "fault protection" code in prepare_ftrace_return()
* rewrote ftrace_modify_code() using "hotpatch" interfaces
* revised descriptions in comments

AKASHI Takahiro (6):
  arm64: Add ftrace support
  arm64: ftrace: Add dynamic ftrace support
  arm64: ftrace: Add CALLER_ADDRx macros
  ftrace: Add arm64 support to recordmcount
  arm64: ftrace: Add system call tracepoint
  arm64: Add 'notrace' attribute to unwind_frame() for ftrace

 arch/arm64/Kconfig                 |    6 +
 arch/arm64/include/asm/ftrace.h    |   54 +++++++++
 arch/arm64/include/asm/syscall.h   |    1 +
 arch/arm64/include/asm/unistd.h    |    2 +
 arch/arm64/kernel/Makefile         |    9 +-
 arch/arm64/kernel/arm64ksyms.c     |    4 +
 arch/arm64/kernel/entry-ftrace.S   |  215 ++++++++++++++++++++++++++++++++++++
 arch/arm64/kernel/ftrace.c         |  177 +++++++++++++++++++++++++++++
 arch/arm64/kernel/ptrace.c         |    5 +
 arch/arm64/kernel/return_address.c |   55 +++++++++
 arch/arm64/kernel/stacktrace.c     |    2 +-
 scripts/recordmcount.c             |    4 +
 scripts/recordmcount.pl            |    5 +
 13 files changed, 537 insertions(+), 2 deletions(-)
 create mode 100644 arch/arm64/include/asm/ftrace.h
 create mode 100644 arch/arm64/kernel/entry-ftrace.S
 create mode 100644 arch/arm64/kernel/ftrace.c
 create mode 100644 arch/arm64/kernel/return_address.c

--
1.7.9.5


^ permalink raw reply	[flat|nested] 235+ messages in thread

* [PATCH v3 0/6] arm64: Add ftrace support
@ 2014-02-10 14:21     ` Kulkarni, Ganapatrao
  0 siblings, 0 replies; 235+ messages in thread
From: Kulkarni, Ganapatrao @ 2014-02-10 14:21 UTC (permalink / raw)
  To: linux-arm-kernel

Looks OK to me.

Reviewed-by: Ganapatrao Kulkarni <ganapatrao.kulkarni@cavium.com>

regards,
Ganapat

________________________________________
From: AKASHI Takahiro <takahiro.akashi@linaro.org>
Sent: Friday, February 7, 2014 3:48 PM
To: rostedt at goodmis.org; fweisbec at gmail.com; mingo at redhat.com; catalin.marinas at arm.com; will.deacon at arm.com; Kulkarni, Ganapatrao; tim.bird at sonymobile.com
Cc: arndb at arndb.de; linux-arm-kernel at lists.infradead.org; linaro-kernel at lists.linaro.org; linux-kernel at vger.kernel.org; patches at linaro.org; AKASHI Takahiro
Subject: [PATCH v3 0/6] arm64: Add ftrace support

This is my third version of patchset for ftrace support.
There was another implementation from Cavium network, but both of us agreed
to use my patchset as future base. He is supposed to review this code, too.

The only issue that I had some concern on was "fault protection" code
in prepare_ftrace_return(). With discussions with Steven and Tim (as author
of arm ftrace), I removed that code since I'm not quite sure about possibility
of "fault" occurrences in this function.

The code is tested on ARMv8 Fast Model with the following tracers & events:
     function tracer with dynamic ftrace
     function graph tracer with dynamic ftrace
     syscall tracepoint
     irqsoff & preemptirqsoff (which use CALLER_ADDRx)
and also verified with in-kernel tests, FTRACE_SELFTEST, FTRACE_STARTUP_TEST
and EVENT_TRACE_TEST_SYSCALLS.

Please be careful:
* elf.h on cross-build host must have AArch64 definitions, EM_AARCH64 and
  R_AARCH64_ABS64, to compile recordmcount utility. See [4/6].
  [4/6] also gets warnings from checkpatch, but they are based on the
  original's coding style.
* This patch may conflict with my audit patch because both changes the same
  location in syscall_trace(). I expect the functions are called in this
  order:
  On entry,
     * tracehook_report_syscall(ENTER)
     * trace_sys_enter()
     * audit_syscall_entry()
  On exit,
     * audit_sysscall_exit()
     * trace_sys_exit()
     * tracehook_report_syscall(EXIT)

Changes from v1 to v2:
* splitted one patch into some pieces for easier review
  (especially function tracer + dynamic ftrace + CALLER_ADDRx)
* put return_address() in a separate file
* renamed __mcount to _mcount (it was my mistake)
* changed stackframe handling to get parent's frame pointer
* removed ARCH_SUPPORTS_FTRACE_OPS
* switched to "hotpatch" interfaces from Huawai
* revised descriptions in comments

Changes from v2 to v3:
* optimized register usages in asm (by not saving x0, x1, and x2)
* removed "fault protection" code in prepare_ftrace_return()
* rewrote ftrace_modify_code() using "hotpatch" interfaces
* revised descriptions in comments

AKASHI Takahiro (6):
  arm64: Add ftrace support
  arm64: ftrace: Add dynamic ftrace support
  arm64: ftrace: Add CALLER_ADDRx macros
  ftrace: Add arm64 support to recordmcount
  arm64: ftrace: Add system call tracepoint
  arm64: Add 'notrace' attribute to unwind_frame() for ftrace

 arch/arm64/Kconfig                 |    6 +
 arch/arm64/include/asm/ftrace.h    |   54 +++++++++
 arch/arm64/include/asm/syscall.h   |    1 +
 arch/arm64/include/asm/unistd.h    |    2 +
 arch/arm64/kernel/Makefile         |    9 +-
 arch/arm64/kernel/arm64ksyms.c     |    4 +
 arch/arm64/kernel/entry-ftrace.S   |  215 ++++++++++++++++++++++++++++++++++++
 arch/arm64/kernel/ftrace.c         |  177 +++++++++++++++++++++++++++++
 arch/arm64/kernel/ptrace.c         |    5 +
 arch/arm64/kernel/return_address.c |   55 +++++++++
 arch/arm64/kernel/stacktrace.c     |    2 +-
 scripts/recordmcount.c             |    4 +
 scripts/recordmcount.pl            |    5 +
 13 files changed, 537 insertions(+), 2 deletions(-)
 create mode 100644 arch/arm64/include/asm/ftrace.h
 create mode 100644 arch/arm64/kernel/entry-ftrace.S
 create mode 100644 arch/arm64/kernel/ftrace.c
 create mode 100644 arch/arm64/kernel/return_address.c

--
1.7.9.5

^ permalink raw reply	[flat|nested] 235+ messages in thread

* Re: [PATCH v3 1/6] arm64: Add ftrace support
  2014-02-07 10:18     ` AKASHI Takahiro
@ 2014-02-10 15:03       ` Arnd Bergmann
  -1 siblings, 0 replies; 235+ messages in thread
From: Arnd Bergmann @ 2014-02-10 15:03 UTC (permalink / raw)
  To: AKASHI Takahiro
  Cc: rostedt, fweisbec, mingo, catalin.marinas, will.deacon,
	gkulkarni, tim.bird, arndb, linux-arm-kernel, linaro-kernel,
	linux-kernel, patches

On Friday 07 February 2014, AKASHI Takahiro wrote:
> @@ -0,0 +1,23 @@

> +
> +#ifdef CONFIG_FUNCTION_TRACER
> +#define MCOUNT_ADDR		((unsigned long)_mcount)
> +#define MCOUNT_INSN_SIZE	4 /* sizeof mcount call */
> +
> +#ifndef __ASSEMBLY__
> +extern void _mcount(unsigned long);
> +#endif /* __ASSEMBLY__ */
> +#endif /* CONFIG_FUNCTION_TRACER */

We generally like to have as few #ifdef as possible, and I think the
#ifdef CONFIG_FUNCTION_TRACER here is not needed.

> +#endif /* __ASM_FTRACE_H */
> diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile
> index 2d4554b..ca921fb 100644
> --- a/arch/arm64/kernel/Makefile
> +++ b/arch/arm64/kernel/Makefile
> @@ -5,6 +5,11 @@
>  CPPFLAGS_vmlinux.lds	:= -DTEXT_OFFSET=$(TEXT_OFFSET)
>  AFLAGS_head.o		:= -DTEXT_OFFSET=$(TEXT_OFFSET)
>  
> +ifdef CONFIG_FUNCTION_TRACER
> +CFLAGS_REMOVE_ftrace.o = -pg
> +CFLAGS_REMOVE_insn.o = -pg
> +endif

Same here. It never hurts to have the CFLAGS_REMOVE_* statements here, since
you will not want to build these files for profiling.

> diff --git a/arch/arm64/kernel/arm64ksyms.c b/arch/arm64/kernel/arm64ksyms.c
> index 338b568..7f0512f 100644
> --- a/arch/arm64/kernel/arm64ksyms.c
> +++ b/arch/arm64/kernel/arm64ksyms.c
> @@ -56,3 +56,7 @@ EXPORT_SYMBOL(clear_bit);
>  EXPORT_SYMBOL(test_and_clear_bit);
>  EXPORT_SYMBOL(change_bit);
>  EXPORT_SYMBOL(test_and_change_bit);
> +
> +#ifdef CONFIG_FUNCTION_TRACER
> +EXPORT_SYMBOL(_mcount);
> +#endif

This one is clearly needed of course.

> +/*
> + * Gcc with -pg will put the following code in the beginning of each function:
> + *      mov x0, x30
> + *      bl _mcount
> + *	[function's body ...]
> + * "bl _mcount" may be replaced to "bl ftrace_caller" or NOP if dynamic
> + * ftrace is enabled.

Unrelated to your patch, I have run into problems with this on arm32, maybe
someone on Cc to this mail has an idea what to do about it:

If I build a large "randconfig" kernel or "allyesconfig", the kernel image
size exceeds 32MB, which means I can no longer link callers with a 26
bit signed immediate argument like the "bl _mcount" here. For any other
function calls, "gcc -mlong-calls" can be used to work around this, but
this particular instance is created by inserting assembly statements
into the output without considering the long-call options. Is there
a way to get the kernel to link anyway?

> +#ifdef CONFIG_FUNCTION_GRAPH_TRACER

Here, again, you an remove the #ifdef by making the entire file built
only for CONFIG_FUNCTION_GRAPH_TRACER.

	Arnd

^ permalink raw reply	[flat|nested] 235+ messages in thread

* [PATCH v3 1/6] arm64: Add ftrace support
@ 2014-02-10 15:03       ` Arnd Bergmann
  0 siblings, 0 replies; 235+ messages in thread
From: Arnd Bergmann @ 2014-02-10 15:03 UTC (permalink / raw)
  To: linux-arm-kernel

On Friday 07 February 2014, AKASHI Takahiro wrote:
> @@ -0,0 +1,23 @@

> +
> +#ifdef CONFIG_FUNCTION_TRACER
> +#define MCOUNT_ADDR		((unsigned long)_mcount)
> +#define MCOUNT_INSN_SIZE	4 /* sizeof mcount call */
> +
> +#ifndef __ASSEMBLY__
> +extern void _mcount(unsigned long);
> +#endif /* __ASSEMBLY__ */
> +#endif /* CONFIG_FUNCTION_TRACER */

We generally like to have as few #ifdef as possible, and I think the
#ifdef CONFIG_FUNCTION_TRACER here is not needed.

> +#endif /* __ASM_FTRACE_H */
> diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile
> index 2d4554b..ca921fb 100644
> --- a/arch/arm64/kernel/Makefile
> +++ b/arch/arm64/kernel/Makefile
> @@ -5,6 +5,11 @@
>  CPPFLAGS_vmlinux.lds	:= -DTEXT_OFFSET=$(TEXT_OFFSET)
>  AFLAGS_head.o		:= -DTEXT_OFFSET=$(TEXT_OFFSET)
>  
> +ifdef CONFIG_FUNCTION_TRACER
> +CFLAGS_REMOVE_ftrace.o = -pg
> +CFLAGS_REMOVE_insn.o = -pg
> +endif

Same here. It never hurts to have the CFLAGS_REMOVE_* statements here, since
you will not want to build these files for profiling.

> diff --git a/arch/arm64/kernel/arm64ksyms.c b/arch/arm64/kernel/arm64ksyms.c
> index 338b568..7f0512f 100644
> --- a/arch/arm64/kernel/arm64ksyms.c
> +++ b/arch/arm64/kernel/arm64ksyms.c
> @@ -56,3 +56,7 @@ EXPORT_SYMBOL(clear_bit);
>  EXPORT_SYMBOL(test_and_clear_bit);
>  EXPORT_SYMBOL(change_bit);
>  EXPORT_SYMBOL(test_and_change_bit);
> +
> +#ifdef CONFIG_FUNCTION_TRACER
> +EXPORT_SYMBOL(_mcount);
> +#endif

This one is clearly needed of course.

> +/*
> + * Gcc with -pg will put the following code in the beginning of each function:
> + *      mov x0, x30
> + *      bl _mcount
> + *	[function's body ...]
> + * "bl _mcount" may be replaced to "bl ftrace_caller" or NOP if dynamic
> + * ftrace is enabled.

Unrelated to your patch, I have run into problems with this on arm32, maybe
someone on Cc to this mail has an idea what to do about it:

If I build a large "randconfig" kernel or "allyesconfig", the kernel image
size exceeds 32MB, which means I can no longer link callers with a 26
bit signed immediate argument like the "bl _mcount" here. For any other
function calls, "gcc -mlong-calls" can be used to work around this, but
this particular instance is created by inserting assembly statements
into the output without considering the long-call options. Is there
a way to get the kernel to link anyway?

> +#ifdef CONFIG_FUNCTION_GRAPH_TRACER

Here, again, you an remove the #ifdef by making the entire file built
only for CONFIG_FUNCTION_GRAPH_TRACER.

	Arnd

^ permalink raw reply	[flat|nested] 235+ messages in thread

* Re: [PATCH v3 1/6] arm64: Add ftrace support
  2014-02-10 15:03       ` Arnd Bergmann
@ 2014-02-10 15:19         ` Steven Rostedt
  -1 siblings, 0 replies; 235+ messages in thread
From: Steven Rostedt @ 2014-02-10 15:19 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: AKASHI Takahiro, fweisbec, mingo, catalin.marinas, will.deacon,
	gkulkarni, tim.bird, arndb, linux-arm-kernel, linaro-kernel,
	linux-kernel, patches

On Mon, 10 Feb 2014 16:03:21 +0100
Arnd Bergmann <arnd@arndb.de> wrote:

> On Friday 07 February 2014, AKASHI Takahiro wrote:
> > @@ -0,0 +1,23 @@
> 
> > +
> > +#ifdef CONFIG_FUNCTION_TRACER
> > +#define MCOUNT_ADDR		((unsigned long)_mcount)
> > +#define MCOUNT_INSN_SIZE	4 /* sizeof mcount call */
> > +
> > +#ifndef __ASSEMBLY__
> > +extern void _mcount(unsigned long);
> > +#endif /* __ASSEMBLY__ */
> > +#endif /* CONFIG_FUNCTION_TRACER */
> 
> We generally like to have as few #ifdef as possible, and I think the
> #ifdef CONFIG_FUNCTION_TRACER here is not needed.
> 
> > +#endif /* __ASM_FTRACE_H */
> > diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile
> > index 2d4554b..ca921fb 100644
> > --- a/arch/arm64/kernel/Makefile
> > +++ b/arch/arm64/kernel/Makefile
> > @@ -5,6 +5,11 @@
> >  CPPFLAGS_vmlinux.lds	:= -DTEXT_OFFSET=$(TEXT_OFFSET)
> >  AFLAGS_head.o		:= -DTEXT_OFFSET=$(TEXT_OFFSET)
> >  
> > +ifdef CONFIG_FUNCTION_TRACER
> > +CFLAGS_REMOVE_ftrace.o = -pg
> > +CFLAGS_REMOVE_insn.o = -pg
> > +endif
> 
> Same here. It never hurts to have the CFLAGS_REMOVE_* statements here, since
> you will not want to build these files for profiling.

I agree to this. I will admit, this was probably just a copy from my
code as I did the same in other Makefiles. I think I added the ifdef
statements as more of documenting what the REMOVE was for, when ftrace
was just being added to the kernel, and not well known.

I should probably go back and remove the ifdef's from other Makefiles
too.

A comment about what the -pg is for wouldn't hurt, though:

 # For files that should not have any function tracing done to them,
 # we must remove the -pg flag.

Something like that.

> 
> > diff --git a/arch/arm64/kernel/arm64ksyms.c b/arch/arm64/kernel/arm64ksyms.c
> > index 338b568..7f0512f 100644
> > --- a/arch/arm64/kernel/arm64ksyms.c
> > +++ b/arch/arm64/kernel/arm64ksyms.c
> > @@ -56,3 +56,7 @@ EXPORT_SYMBOL(clear_bit);
> >  EXPORT_SYMBOL(test_and_clear_bit);
> >  EXPORT_SYMBOL(change_bit);
> >  EXPORT_SYMBOL(test_and_change_bit);
> > +
> > +#ifdef CONFIG_FUNCTION_TRACER
> > +EXPORT_SYMBOL(_mcount);
> > +#endif
> 
> This one is clearly needed of course.
> 
> > +/*
> > + * Gcc with -pg will put the following code in the beginning of each function:
> > + *      mov x0, x30
> > + *      bl _mcount
> > + *	[function's body ...]
> > + * "bl _mcount" may be replaced to "bl ftrace_caller" or NOP if dynamic
> > + * ftrace is enabled.
> 
> Unrelated to your patch, I have run into problems with this on arm32, maybe
> someone on Cc to this mail has an idea what to do about it:
> 
> If I build a large "randconfig" kernel or "allyesconfig", the kernel image
> size exceeds 32MB, which means I can no longer link callers with a 26
> bit signed immediate argument like the "bl _mcount" here. For any other
> function calls, "gcc -mlong-calls" can be used to work around this, but
> this particular instance is created by inserting assembly statements
> into the output without considering the long-call options. Is there
> a way to get the kernel to link anyway?

I wonder if we play linker games and move the _mcount and ftrace_caller
and friends into the middle of the kernel? If it is only missing it by
a slight overflow of a 32bit jump, then maybe moving it will work.

> 
> > +#ifdef CONFIG_FUNCTION_GRAPH_TRACER
> 
> Here, again, you an remove the #ifdef by making the entire file built
> only for CONFIG_FUNCTION_GRAPH_TRACER.

Interesting. Other archs (at least x86 and powerpc) required this file
for function tracing too. Seems this is only needed for function graph
tracer.

-- Steve


^ permalink raw reply	[flat|nested] 235+ messages in thread

* [PATCH v3 1/6] arm64: Add ftrace support
@ 2014-02-10 15:19         ` Steven Rostedt
  0 siblings, 0 replies; 235+ messages in thread
From: Steven Rostedt @ 2014-02-10 15:19 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, 10 Feb 2014 16:03:21 +0100
Arnd Bergmann <arnd@arndb.de> wrote:

> On Friday 07 February 2014, AKASHI Takahiro wrote:
> > @@ -0,0 +1,23 @@
> 
> > +
> > +#ifdef CONFIG_FUNCTION_TRACER
> > +#define MCOUNT_ADDR		((unsigned long)_mcount)
> > +#define MCOUNT_INSN_SIZE	4 /* sizeof mcount call */
> > +
> > +#ifndef __ASSEMBLY__
> > +extern void _mcount(unsigned long);
> > +#endif /* __ASSEMBLY__ */
> > +#endif /* CONFIG_FUNCTION_TRACER */
> 
> We generally like to have as few #ifdef as possible, and I think the
> #ifdef CONFIG_FUNCTION_TRACER here is not needed.
> 
> > +#endif /* __ASM_FTRACE_H */
> > diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile
> > index 2d4554b..ca921fb 100644
> > --- a/arch/arm64/kernel/Makefile
> > +++ b/arch/arm64/kernel/Makefile
> > @@ -5,6 +5,11 @@
> >  CPPFLAGS_vmlinux.lds	:= -DTEXT_OFFSET=$(TEXT_OFFSET)
> >  AFLAGS_head.o		:= -DTEXT_OFFSET=$(TEXT_OFFSET)
> >  
> > +ifdef CONFIG_FUNCTION_TRACER
> > +CFLAGS_REMOVE_ftrace.o = -pg
> > +CFLAGS_REMOVE_insn.o = -pg
> > +endif
> 
> Same here. It never hurts to have the CFLAGS_REMOVE_* statements here, since
> you will not want to build these files for profiling.

I agree to this. I will admit, this was probably just a copy from my
code as I did the same in other Makefiles. I think I added the ifdef
statements as more of documenting what the REMOVE was for, when ftrace
was just being added to the kernel, and not well known.

I should probably go back and remove the ifdef's from other Makefiles
too.

A comment about what the -pg is for wouldn't hurt, though:

 # For files that should not have any function tracing done to them,
 # we must remove the -pg flag.

Something like that.

> 
> > diff --git a/arch/arm64/kernel/arm64ksyms.c b/arch/arm64/kernel/arm64ksyms.c
> > index 338b568..7f0512f 100644
> > --- a/arch/arm64/kernel/arm64ksyms.c
> > +++ b/arch/arm64/kernel/arm64ksyms.c
> > @@ -56,3 +56,7 @@ EXPORT_SYMBOL(clear_bit);
> >  EXPORT_SYMBOL(test_and_clear_bit);
> >  EXPORT_SYMBOL(change_bit);
> >  EXPORT_SYMBOL(test_and_change_bit);
> > +
> > +#ifdef CONFIG_FUNCTION_TRACER
> > +EXPORT_SYMBOL(_mcount);
> > +#endif
> 
> This one is clearly needed of course.
> 
> > +/*
> > + * Gcc with -pg will put the following code in the beginning of each function:
> > + *      mov x0, x30
> > + *      bl _mcount
> > + *	[function's body ...]
> > + * "bl _mcount" may be replaced to "bl ftrace_caller" or NOP if dynamic
> > + * ftrace is enabled.
> 
> Unrelated to your patch, I have run into problems with this on arm32, maybe
> someone on Cc to this mail has an idea what to do about it:
> 
> If I build a large "randconfig" kernel or "allyesconfig", the kernel image
> size exceeds 32MB, which means I can no longer link callers with a 26
> bit signed immediate argument like the "bl _mcount" here. For any other
> function calls, "gcc -mlong-calls" can be used to work around this, but
> this particular instance is created by inserting assembly statements
> into the output without considering the long-call options. Is there
> a way to get the kernel to link anyway?

I wonder if we play linker games and move the _mcount and ftrace_caller
and friends into the middle of the kernel? If it is only missing it by
a slight overflow of a 32bit jump, then maybe moving it will work.

> 
> > +#ifdef CONFIG_FUNCTION_GRAPH_TRACER
> 
> Here, again, you an remove the #ifdef by making the entire file built
> only for CONFIG_FUNCTION_GRAPH_TRACER.

Interesting. Other archs (at least x86 and powerpc) required this file
for function tracing too. Seems this is only needed for function graph
tracer.

-- Steve

^ permalink raw reply	[flat|nested] 235+ messages in thread

* Re: [PATCH v3 1/6] arm64: Add ftrace support
       [not found]       ` <CAB5YjtCr2KL_q1FF8kO_VKe+feg7f9qFRKtwf3xj2h0ENwuB5g@mail.gmail.com>
@ 2014-02-12 11:03           ` Arnd Bergmann
  0 siblings, 0 replies; 235+ messages in thread
From: Arnd Bergmann @ 2014-02-12 11:03 UTC (permalink / raw)
  To: Takahiro Akashi
  Cc: rostedt, Frédéric Weisbecker, mingo, Catalin Marinas,
	Will Deacon, gkulkarni, Bird, Tim, arndb, linux-arm-kernel,
	linaro-kernel, linux-kernel, Patch Tracking

On Wednesday 12 February 2014, Takahiro Akashi wrote:
> > If I build a large "randconfig" kernel or "allyesconfig", the kernel image
> > size exceeds 32MB, which means I can no longer link callers with a 26
> > bit signed immediate argument like the "bl _mcount" here. For any other
> > function calls, "gcc -mlong-calls" can be used to work around this, but
> > this particular instance is created by inserting assembly statements
> > into the output without considering the long-call options. Is there
> > a way to get the kernel to link anyway?
> 
> I hope that this won't happen on arm64 because a branch offset range is
> +/- 128MB.

Yes, we should be safe for the next decade on arm64. My question was really
about arm32 here, hoping someone has an idea.

> > > +#ifdef CONFIG_FUNCTION_GRAPH_TRACER
> >
> > Here, again, you an remove the #ifdef by making the entire file built
> > only for CONFIG_FUNCTION_GRAPH_TRACER.
> 
> You're right as far as patch [1/6] is concerned, but once patch [2/6] is
> applied,
> this file (ftrace.c) may be compiled even if CONFIG_FUNCTION_GRAPH_TRACER
> is not enabled. (That is CONFIG_DYNAMIC_FTRACE.)
> Sorry for any confusion by poorly-divided patchset.

No, that was my fault. I saw it later after I had already sent out the
message.

	Arnd

^ permalink raw reply	[flat|nested] 235+ messages in thread

* [PATCH v3 1/6] arm64: Add ftrace support
@ 2014-02-12 11:03           ` Arnd Bergmann
  0 siblings, 0 replies; 235+ messages in thread
From: Arnd Bergmann @ 2014-02-12 11:03 UTC (permalink / raw)
  To: linux-arm-kernel

On Wednesday 12 February 2014, Takahiro Akashi wrote:
> > If I build a large "randconfig" kernel or "allyesconfig", the kernel image
> > size exceeds 32MB, which means I can no longer link callers with a 26
> > bit signed immediate argument like the "bl _mcount" here. For any other
> > function calls, "gcc -mlong-calls" can be used to work around this, but
> > this particular instance is created by inserting assembly statements
> > into the output without considering the long-call options. Is there
> > a way to get the kernel to link anyway?
> 
> I hope that this won't happen on arm64 because a branch offset range is
> +/- 128MB.

Yes, we should be safe for the next decade on arm64. My question was really
about arm32 here, hoping someone has an idea.

> > > +#ifdef CONFIG_FUNCTION_GRAPH_TRACER
> >
> > Here, again, you an remove the #ifdef by making the entire file built
> > only for CONFIG_FUNCTION_GRAPH_TRACER.
> 
> You're right as far as patch [1/6] is concerned, but once patch [2/6] is
> applied,
> this file (ftrace.c) may be compiled even if CONFIG_FUNCTION_GRAPH_TRACER
> is not enabled. (That is CONFIG_DYNAMIC_FTRACE.)
> Sorry for any confusion by poorly-divided patchset.

No, that was my fault. I saw it later after I had already sent out the
message.

	Arnd

^ permalink raw reply	[flat|nested] 235+ messages in thread

* Re: [PATCH v3 1/6] arm64: Add ftrace support
  2014-02-07 10:18     ` AKASHI Takahiro
@ 2014-02-17 18:12       ` Will Deacon
  -1 siblings, 0 replies; 235+ messages in thread
From: Will Deacon @ 2014-02-17 18:12 UTC (permalink / raw)
  To: AKASHI Takahiro
  Cc: rostedt, fweisbec, mingo, Catalin Marinas, gkulkarni, tim.bird,
	arndb, linux-arm-kernel, linaro-kernel, linux-kernel, patches

On Fri, Feb 07, 2014 at 10:18:51AM +0000, AKASHI Takahiro wrote:
> This patch implements arm64 specific part to support function tracers,
> such as function (CONFIG_FUNCTION_TRACER), function_graph
> (CONFIG_FUNCTION_GRAPH_TRACER) and function profiler
> (CONFIG_FUNCTION_PROFILER).
> 
> With 'function' tracer, all the functions in the kernel are traced with
> timestamps in ${sysfs}/tracing/trace. If function_graph tracer is
> specified, call graph is generated.
> 
> The kernel must be compiled with -pg option so that _mcount() is inserted
> at the beginning of functions. This function is called on every function's
> entry as long as tracing is enabled.
> In addition, function_graph tracer also needs to be able to probe function's
> exit. ftrace_graph_caller() & return_to_handler do this by faking link
> register's value to intercept function's return path.
> 
> More details on architecture specific requirements are described in
> Documentation/trace/ftrace-design.txt.

[...]

> diff --git a/arch/arm64/include/asm/ftrace.h b/arch/arm64/include/asm/ftrace.h
> new file mode 100644
> index 0000000..0d5dfdb
> --- /dev/null
> +++ b/arch/arm64/include/asm/ftrace.h
> @@ -0,0 +1,23 @@
> +/*
> + * arch/arm64/include/asm/ftrace.h
> + *
> + * Copyright (C) 2013 Linaro Limited
> + * Author: AKASHI Takahiro <takahiro.akashi@linaro.org>
> + *
> + * 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.
> + */
> +#ifndef __ASM_FTRACE_H
> +#define __ASM_FTRACE_H
> +
> +#ifdef CONFIG_FUNCTION_TRACER
> +#define MCOUNT_ADDR            ((unsigned long)_mcount)
> +#define MCOUNT_INSN_SIZE       4 /* sizeof mcount call */

You can use AARCH64_INSN_SIZE here.

> +#include <linux/linkage.h>
> +#include <asm/ftrace.h>
> +
> +/*
> + * Gcc with -pg will put the following code in the beginning of each function:
> + *      mov x0, x30
> + *      bl _mcount
> + *     [function's body ...]
> + * "bl _mcount" may be replaced to "bl ftrace_caller" or NOP if dynamic
> + * ftrace is enabled.
> + *
> + * Please note that x0 as an argument will not be used here because we can
> + * get lr(x30) of insturmented function at any time by winding up call stack

instrumented

> + * as long as the kernel is compiled without -fomit-frame-pointer.
> + * (or CONFIG_FRAME_POINTER, this is forced on arm64)
> + *
> + * stack layout after mcount_enter:
> + *
> + *   0 ---------------------------------------- sp of _mcount()
> + *      x29: fp of instrumented function       fp is not winded
> + *     --------------------
> + *      x30: lr of _mcount() (= instrumented function's pc)
> + * +16 ---------------------------------------- sp of instrumented function
> + *
> + *     ....
> + *
> + * +xx ---------------------------------------- fp of instrumented function
> + *      x29: fp of parent
> + *     --------------------
> + *      x30: lr of insturmented function (= parent's pc)
> + *     --------------------
> + *      xxx
> + */
> +
> +       .macro mcount_enter
> +       stp     x29, x30, [sp, #-48]!
> +       .endm

Can you elaborate in your comment about where this 48 comes from please? I
can't join it up with your ascii art.

Will

^ permalink raw reply	[flat|nested] 235+ messages in thread

* [PATCH v3 1/6] arm64: Add ftrace support
@ 2014-02-17 18:12       ` Will Deacon
  0 siblings, 0 replies; 235+ messages in thread
From: Will Deacon @ 2014-02-17 18:12 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, Feb 07, 2014 at 10:18:51AM +0000, AKASHI Takahiro wrote:
> This patch implements arm64 specific part to support function tracers,
> such as function (CONFIG_FUNCTION_TRACER), function_graph
> (CONFIG_FUNCTION_GRAPH_TRACER) and function profiler
> (CONFIG_FUNCTION_PROFILER).
> 
> With 'function' tracer, all the functions in the kernel are traced with
> timestamps in ${sysfs}/tracing/trace. If function_graph tracer is
> specified, call graph is generated.
> 
> The kernel must be compiled with -pg option so that _mcount() is inserted
> at the beginning of functions. This function is called on every function's
> entry as long as tracing is enabled.
> In addition, function_graph tracer also needs to be able to probe function's
> exit. ftrace_graph_caller() & return_to_handler do this by faking link
> register's value to intercept function's return path.
> 
> More details on architecture specific requirements are described in
> Documentation/trace/ftrace-design.txt.

[...]

> diff --git a/arch/arm64/include/asm/ftrace.h b/arch/arm64/include/asm/ftrace.h
> new file mode 100644
> index 0000000..0d5dfdb
> --- /dev/null
> +++ b/arch/arm64/include/asm/ftrace.h
> @@ -0,0 +1,23 @@
> +/*
> + * arch/arm64/include/asm/ftrace.h
> + *
> + * Copyright (C) 2013 Linaro Limited
> + * Author: AKASHI Takahiro <takahiro.akashi@linaro.org>
> + *
> + * 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.
> + */
> +#ifndef __ASM_FTRACE_H
> +#define __ASM_FTRACE_H
> +
> +#ifdef CONFIG_FUNCTION_TRACER
> +#define MCOUNT_ADDR            ((unsigned long)_mcount)
> +#define MCOUNT_INSN_SIZE       4 /* sizeof mcount call */

You can use AARCH64_INSN_SIZE here.

> +#include <linux/linkage.h>
> +#include <asm/ftrace.h>
> +
> +/*
> + * Gcc with -pg will put the following code in the beginning of each function:
> + *      mov x0, x30
> + *      bl _mcount
> + *     [function's body ...]
> + * "bl _mcount" may be replaced to "bl ftrace_caller" or NOP if dynamic
> + * ftrace is enabled.
> + *
> + * Please note that x0 as an argument will not be used here because we can
> + * get lr(x30) of insturmented function at any time by winding up call stack

instrumented

> + * as long as the kernel is compiled without -fomit-frame-pointer.
> + * (or CONFIG_FRAME_POINTER, this is forced on arm64)
> + *
> + * stack layout after mcount_enter:
> + *
> + *   0 ---------------------------------------- sp of _mcount()
> + *      x29: fp of instrumented function       fp is not winded
> + *     --------------------
> + *      x30: lr of _mcount() (= instrumented function's pc)
> + * +16 ---------------------------------------- sp of instrumented function
> + *
> + *     ....
> + *
> + * +xx ---------------------------------------- fp of instrumented function
> + *      x29: fp of parent
> + *     --------------------
> + *      x30: lr of insturmented function (= parent's pc)
> + *     --------------------
> + *      xxx
> + */
> +
> +       .macro mcount_enter
> +       stp     x29, x30, [sp, #-48]!
> +       .endm

Can you elaborate in your comment about where this 48 comes from please? I
can't join it up with your ascii art.

Will

^ permalink raw reply	[flat|nested] 235+ messages in thread

* Re: [PATCH v3 5/6] arm64: ftrace: Add system call tracepoint
  2014-02-07 10:18     ` AKASHI Takahiro
@ 2014-02-17 19:29       ` Will Deacon
  -1 siblings, 0 replies; 235+ messages in thread
From: Will Deacon @ 2014-02-17 19:29 UTC (permalink / raw)
  To: AKASHI Takahiro
  Cc: rostedt, fweisbec, mingo, Catalin Marinas, gkulkarni, tim.bird,
	arndb, linux-arm-kernel, linaro-kernel, linux-kernel, patches

On Fri, Feb 07, 2014 at 10:18:55AM +0000, AKASHI Takahiro wrote:
> This patch allows system call entry or exit to be traced as ftrace events,
> ie. sys_enter_*/sys_exit_*, if CONFIG_FTRACE_SYSCALLS is enabled.
> Those events appear and can be controlled under
>     ${sysfs}/tracing/events/syscalls/
> 
> Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
> ---
>  arch/arm64/Kconfig               |    1 +
>  arch/arm64/include/asm/syscall.h |    1 +
>  arch/arm64/include/asm/unistd.h  |    2 ++
>  arch/arm64/kernel/ptrace.c       |    5 +++++
>  4 files changed, 9 insertions(+)
> 
> diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
> index 43fce76..9bdaf5c 100644
> --- a/arch/arm64/Kconfig
> +++ b/arch/arm64/Kconfig
> @@ -42,6 +42,7 @@ config ARM64
>  	select HAVE_HW_BREAKPOINT if PERF_EVENTS
>  	select HAVE_MEMBLOCK
>  	select HAVE_PERF_EVENTS
> +	select HAVE_SYSCALL_TRACEPOINTS
>  	select IRQ_DOMAIN
>  	select MODULES_USE_ELF_RELA
>  	select NO_BOOTMEM
> diff --git a/arch/arm64/include/asm/syscall.h b/arch/arm64/include/asm/syscall.h
> index 70ba9d4..383771e 100644
> --- a/arch/arm64/include/asm/syscall.h
> +++ b/arch/arm64/include/asm/syscall.h
> @@ -18,6 +18,7 @@
>  
>  #include <linux/err.h>
>  
> +extern const void *sys_call_table[];
>  
>  static inline int syscall_get_nr(struct task_struct *task,
>  				 struct pt_regs *regs)
> diff --git a/arch/arm64/include/asm/unistd.h b/arch/arm64/include/asm/unistd.h
> index 82ce217..c335479 100644
> --- a/arch/arm64/include/asm/unistd.h
> +++ b/arch/arm64/include/asm/unistd.h
> @@ -28,3 +28,5 @@
>  #endif
>  #define __ARCH_WANT_SYS_CLONE
>  #include <uapi/asm/unistd.h>
> +
> +#define NR_syscalls (__NR_syscalls)
> diff --git a/arch/arm64/kernel/ptrace.c b/arch/arm64/kernel/ptrace.c
> index 64ce39f..f4c3c4e 100644
> --- a/arch/arm64/kernel/ptrace.c
> +++ b/arch/arm64/kernel/ptrace.c
> @@ -41,6 +41,9 @@
>  #include <asm/traps.h>
>  #include <asm/system_misc.h>
>  
> +#define CREATE_TRACE_POINTS
> +#include <trace/events/syscalls.h>
> +
>  /*
>   * TODO: does not yet catch signals sent when the child dies.
>   * in exit.c or in signal.c.
> @@ -1076,10 +1079,12 @@ asmlinkage int syscall_trace(int dir, struct pt_regs *regs)
>  	}
>  
>  	if (dir) {
> +		trace_sys_exit(regs, regs->syscallno);
>  		tracehook_report_syscall_exit(regs, 0);
>  	} else {
>  		if (tracehook_report_syscall_entry(regs))
>  			regs->syscallno = ~0UL;
> +		trace_sys_enter(regs, regs->syscallno);

Shouldn't these calls be guarded by a TIF_SYSCALL_TRACEPOINT check?

Will

^ permalink raw reply	[flat|nested] 235+ messages in thread

* [PATCH v3 5/6] arm64: ftrace: Add system call tracepoint
@ 2014-02-17 19:29       ` Will Deacon
  0 siblings, 0 replies; 235+ messages in thread
From: Will Deacon @ 2014-02-17 19:29 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, Feb 07, 2014 at 10:18:55AM +0000, AKASHI Takahiro wrote:
> This patch allows system call entry or exit to be traced as ftrace events,
> ie. sys_enter_*/sys_exit_*, if CONFIG_FTRACE_SYSCALLS is enabled.
> Those events appear and can be controlled under
>     ${sysfs}/tracing/events/syscalls/
> 
> Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
> ---
>  arch/arm64/Kconfig               |    1 +
>  arch/arm64/include/asm/syscall.h |    1 +
>  arch/arm64/include/asm/unistd.h  |    2 ++
>  arch/arm64/kernel/ptrace.c       |    5 +++++
>  4 files changed, 9 insertions(+)
> 
> diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
> index 43fce76..9bdaf5c 100644
> --- a/arch/arm64/Kconfig
> +++ b/arch/arm64/Kconfig
> @@ -42,6 +42,7 @@ config ARM64
>  	select HAVE_HW_BREAKPOINT if PERF_EVENTS
>  	select HAVE_MEMBLOCK
>  	select HAVE_PERF_EVENTS
> +	select HAVE_SYSCALL_TRACEPOINTS
>  	select IRQ_DOMAIN
>  	select MODULES_USE_ELF_RELA
>  	select NO_BOOTMEM
> diff --git a/arch/arm64/include/asm/syscall.h b/arch/arm64/include/asm/syscall.h
> index 70ba9d4..383771e 100644
> --- a/arch/arm64/include/asm/syscall.h
> +++ b/arch/arm64/include/asm/syscall.h
> @@ -18,6 +18,7 @@
>  
>  #include <linux/err.h>
>  
> +extern const void *sys_call_table[];
>  
>  static inline int syscall_get_nr(struct task_struct *task,
>  				 struct pt_regs *regs)
> diff --git a/arch/arm64/include/asm/unistd.h b/arch/arm64/include/asm/unistd.h
> index 82ce217..c335479 100644
> --- a/arch/arm64/include/asm/unistd.h
> +++ b/arch/arm64/include/asm/unistd.h
> @@ -28,3 +28,5 @@
>  #endif
>  #define __ARCH_WANT_SYS_CLONE
>  #include <uapi/asm/unistd.h>
> +
> +#define NR_syscalls (__NR_syscalls)
> diff --git a/arch/arm64/kernel/ptrace.c b/arch/arm64/kernel/ptrace.c
> index 64ce39f..f4c3c4e 100644
> --- a/arch/arm64/kernel/ptrace.c
> +++ b/arch/arm64/kernel/ptrace.c
> @@ -41,6 +41,9 @@
>  #include <asm/traps.h>
>  #include <asm/system_misc.h>
>  
> +#define CREATE_TRACE_POINTS
> +#include <trace/events/syscalls.h>
> +
>  /*
>   * TODO: does not yet catch signals sent when the child dies.
>   * in exit.c or in signal.c.
> @@ -1076,10 +1079,12 @@ asmlinkage int syscall_trace(int dir, struct pt_regs *regs)
>  	}
>  
>  	if (dir) {
> +		trace_sys_exit(regs, regs->syscallno);
>  		tracehook_report_syscall_exit(regs, 0);
>  	} else {
>  		if (tracehook_report_syscall_entry(regs))
>  			regs->syscallno = ~0UL;
> +		trace_sys_enter(regs, regs->syscallno);

Shouldn't these calls be guarded by a TIF_SYSCALL_TRACEPOINT check?

Will

^ permalink raw reply	[flat|nested] 235+ messages in thread

* Re: [PATCH v3 1/6] arm64: Add ftrace support
  2014-02-17 18:12       ` Will Deacon
@ 2014-02-19 10:46         ` AKASHI Takahiro
  -1 siblings, 0 replies; 235+ messages in thread
From: AKASHI Takahiro @ 2014-02-19 10:46 UTC (permalink / raw)
  To: Will Deacon
  Cc: rostedt, fweisbec, mingo, Catalin Marinas, gkulkarni, tim.bird,
	arndb, linux-arm-kernel, linaro-kernel, linux-kernel, patches

On 02/18/2014 03:12 AM, Will Deacon wrote:
> On Fri, Feb 07, 2014 at 10:18:51AM +0000, AKASHI Takahiro wrote:
>> This patch implements arm64 specific part to support function tracers,
>> such as function (CONFIG_FUNCTION_TRACER), function_graph
>> (CONFIG_FUNCTION_GRAPH_TRACER) and function profiler
>> (CONFIG_FUNCTION_PROFILER).
>>
>> With 'function' tracer, all the functions in the kernel are traced with
>> timestamps in ${sysfs}/tracing/trace. If function_graph tracer is
>> specified, call graph is generated.
>>
>> The kernel must be compiled with -pg option so that _mcount() is inserted
>> at the beginning of functions. This function is called on every function's
>> entry as long as tracing is enabled.
>> In addition, function_graph tracer also needs to be able to probe function's
>> exit. ftrace_graph_caller() & return_to_handler do this by faking link
>> register's value to intercept function's return path.
>>
>> More details on architecture specific requirements are described in
>> Documentation/trace/ftrace-design.txt.
>
> [...]
>
>> diff --git a/arch/arm64/include/asm/ftrace.h b/arch/arm64/include/asm/ftrace.h
>> new file mode 100644
>> index 0000000..0d5dfdb
>> --- /dev/null
>> +++ b/arch/arm64/include/asm/ftrace.h
>> @@ -0,0 +1,23 @@
>> +/*
>> + * arch/arm64/include/asm/ftrace.h
>> + *
>> + * Copyright (C) 2013 Linaro Limited
>> + * Author: AKASHI Takahiro <takahiro.akashi@linaro.org>
>> + *
>> + * 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.
>> + */
>> +#ifndef __ASM_FTRACE_H
>> +#define __ASM_FTRACE_H
>> +
>> +#ifdef CONFIG_FUNCTION_TRACER
>> +#define MCOUNT_ADDR            ((unsigned long)_mcount)
>> +#define MCOUNT_INSN_SIZE       4 /* sizeof mcount call */
>
> You can use AARCH64_INSN_SIZE here.

OK, but MCOUNT_INSN_SIZE can't be removed here because it is also used in
kernel/trace/ftrace.c. So I will redefine it as
#define MCOUNT_INSN_SIZE AARCH64_INSN_SIZE

In this case, I need to add __ASSEMBLY__ in asm/insn.h because
asm/ftrace.h (and so asm/insn.h) is included in entry-ftrace.S.

Is it OK?


>> +#include <linux/linkage.h>
>> +#include <asm/ftrace.h>
>> +
>> +/*
>> + * Gcc with -pg will put the following code in the beginning of each function:
>> + *      mov x0, x30
>> + *      bl _mcount
>> + *     [function's body ...]
>> + * "bl _mcount" may be replaced to "bl ftrace_caller" or NOP if dynamic
>> + * ftrace is enabled.
>> + *
>> + * Please note that x0 as an argument will not be used here because we can
>> + * get lr(x30) of insturmented function at any time by winding up call stack
>
> instrumented

I  will fix two occurences of "insturmented" :-)
Just a question: Is there any better word than "instrument"?

>> + * as long as the kernel is compiled without -fomit-frame-pointer.
>> + * (or CONFIG_FRAME_POINTER, this is forced on arm64)
>> + *
>> + * stack layout after mcount_enter:
>> + *
>> + *   0 ---------------------------------------- sp of _mcount()
>> + *      x29: fp of instrumented function       fp is not winded
>> + *     --------------------
>> + *      x30: lr of _mcount() (= instrumented function's pc)
>> + * +16 ---------------------------------------- sp of instrumented function
>> + *
>> + *     ....
>> + *
>> + * +xx ---------------------------------------- fp of instrumented function
>> + *      x29: fp of parent
>> + *     --------------------
>> + *      x30: lr of insturmented function (= parent's pc)
>> + *     --------------------
>> + *      xxx
>> + */
>> +
>> +       .macro mcount_enter
>> +       stp     x29, x30, [sp, #-48]!
>> +       .endm
>
> Can you elaborate in your comment about where this 48 comes from please? I
> can't join it up with your ascii art.

Right. It should be -16 as shown in the stack layout.
When I removed an operation of saving/restoring x0-x3 at v3 patch, this value
should also have been changed.

-Takahiro AKASHI

> Will
>

^ permalink raw reply	[flat|nested] 235+ messages in thread

* [PATCH v3 1/6] arm64: Add ftrace support
@ 2014-02-19 10:46         ` AKASHI Takahiro
  0 siblings, 0 replies; 235+ messages in thread
From: AKASHI Takahiro @ 2014-02-19 10:46 UTC (permalink / raw)
  To: linux-arm-kernel

On 02/18/2014 03:12 AM, Will Deacon wrote:
> On Fri, Feb 07, 2014 at 10:18:51AM +0000, AKASHI Takahiro wrote:
>> This patch implements arm64 specific part to support function tracers,
>> such as function (CONFIG_FUNCTION_TRACER), function_graph
>> (CONFIG_FUNCTION_GRAPH_TRACER) and function profiler
>> (CONFIG_FUNCTION_PROFILER).
>>
>> With 'function' tracer, all the functions in the kernel are traced with
>> timestamps in ${sysfs}/tracing/trace. If function_graph tracer is
>> specified, call graph is generated.
>>
>> The kernel must be compiled with -pg option so that _mcount() is inserted
>> at the beginning of functions. This function is called on every function's
>> entry as long as tracing is enabled.
>> In addition, function_graph tracer also needs to be able to probe function's
>> exit. ftrace_graph_caller() & return_to_handler do this by faking link
>> register's value to intercept function's return path.
>>
>> More details on architecture specific requirements are described in
>> Documentation/trace/ftrace-design.txt.
>
> [...]
>
>> diff --git a/arch/arm64/include/asm/ftrace.h b/arch/arm64/include/asm/ftrace.h
>> new file mode 100644
>> index 0000000..0d5dfdb
>> --- /dev/null
>> +++ b/arch/arm64/include/asm/ftrace.h
>> @@ -0,0 +1,23 @@
>> +/*
>> + * arch/arm64/include/asm/ftrace.h
>> + *
>> + * Copyright (C) 2013 Linaro Limited
>> + * Author: AKASHI Takahiro <takahiro.akashi@linaro.org>
>> + *
>> + * 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.
>> + */
>> +#ifndef __ASM_FTRACE_H
>> +#define __ASM_FTRACE_H
>> +
>> +#ifdef CONFIG_FUNCTION_TRACER
>> +#define MCOUNT_ADDR            ((unsigned long)_mcount)
>> +#define MCOUNT_INSN_SIZE       4 /* sizeof mcount call */
>
> You can use AARCH64_INSN_SIZE here.

OK, but MCOUNT_INSN_SIZE can't be removed here because it is also used in
kernel/trace/ftrace.c. So I will redefine it as
#define MCOUNT_INSN_SIZE AARCH64_INSN_SIZE

In this case, I need to add __ASSEMBLY__ in asm/insn.h because
asm/ftrace.h (and so asm/insn.h) is included in entry-ftrace.S.

Is it OK?


>> +#include <linux/linkage.h>
>> +#include <asm/ftrace.h>
>> +
>> +/*
>> + * Gcc with -pg will put the following code in the beginning of each function:
>> + *      mov x0, x30
>> + *      bl _mcount
>> + *     [function's body ...]
>> + * "bl _mcount" may be replaced to "bl ftrace_caller" or NOP if dynamic
>> + * ftrace is enabled.
>> + *
>> + * Please note that x0 as an argument will not be used here because we can
>> + * get lr(x30) of insturmented function at any time by winding up call stack
>
> instrumented

I  will fix two occurences of "insturmented" :-)
Just a question: Is there any better word than "instrument"?

>> + * as long as the kernel is compiled without -fomit-frame-pointer.
>> + * (or CONFIG_FRAME_POINTER, this is forced on arm64)
>> + *
>> + * stack layout after mcount_enter:
>> + *
>> + *   0 ---------------------------------------- sp of _mcount()
>> + *      x29: fp of instrumented function       fp is not winded
>> + *     --------------------
>> + *      x30: lr of _mcount() (= instrumented function's pc)
>> + * +16 ---------------------------------------- sp of instrumented function
>> + *
>> + *     ....
>> + *
>> + * +xx ---------------------------------------- fp of instrumented function
>> + *      x29: fp of parent
>> + *     --------------------
>> + *      x30: lr of insturmented function (= parent's pc)
>> + *     --------------------
>> + *      xxx
>> + */
>> +
>> +       .macro mcount_enter
>> +       stp     x29, x30, [sp, #-48]!
>> +       .endm
>
> Can you elaborate in your comment about where this 48 comes from please? I
> can't join it up with your ascii art.

Right. It should be -16 as shown in the stack layout.
When I removed an operation of saving/restoring x0-x3 at v3 patch, this value
should also have been changed.

-Takahiro AKASHI

> Will
>

^ permalink raw reply	[flat|nested] 235+ messages in thread

* Re: [PATCH v3 5/6] arm64: ftrace: Add system call tracepoint
  2014-02-17 19:29       ` Will Deacon
@ 2014-02-19 10:48         ` AKASHI Takahiro
  -1 siblings, 0 replies; 235+ messages in thread
From: AKASHI Takahiro @ 2014-02-19 10:48 UTC (permalink / raw)
  To: Will Deacon
  Cc: rostedt, fweisbec, mingo, Catalin Marinas, gkulkarni, tim.bird,
	arndb, linux-arm-kernel, linaro-kernel, linux-kernel, patches

On 02/18/2014 04:29 AM, Will Deacon wrote:
> On Fri, Feb 07, 2014 at 10:18:55AM +0000, AKASHI Takahiro wrote:
>> This patch allows system call entry or exit to be traced as ftrace events,
>> ie. sys_enter_*/sys_exit_*, if CONFIG_FTRACE_SYSCALLS is enabled.
>> Those events appear and can be controlled under
>>      ${sysfs}/tracing/events/syscalls/
>>
>> Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
>> ---
>>   arch/arm64/Kconfig               |    1 +
>>   arch/arm64/include/asm/syscall.h |    1 +
>>   arch/arm64/include/asm/unistd.h  |    2 ++
>>   arch/arm64/kernel/ptrace.c       |    5 +++++
>>   4 files changed, 9 insertions(+)
>>
>> diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
>> index 43fce76..9bdaf5c 100644
>> --- a/arch/arm64/Kconfig
>> +++ b/arch/arm64/Kconfig
>> @@ -42,6 +42,7 @@ config ARM64
>>   	select HAVE_HW_BREAKPOINT if PERF_EVENTS
>>   	select HAVE_MEMBLOCK
>>   	select HAVE_PERF_EVENTS
>> +	select HAVE_SYSCALL_TRACEPOINTS
>>   	select IRQ_DOMAIN
>>   	select MODULES_USE_ELF_RELA
>>   	select NO_BOOTMEM
>> diff --git a/arch/arm64/include/asm/syscall.h b/arch/arm64/include/asm/syscall.h
>> index 70ba9d4..383771e 100644
>> --- a/arch/arm64/include/asm/syscall.h
>> +++ b/arch/arm64/include/asm/syscall.h
>> @@ -18,6 +18,7 @@
>>
>>   #include <linux/err.h>
>>
>> +extern const void *sys_call_table[];
>>
>>   static inline int syscall_get_nr(struct task_struct *task,
>>   				 struct pt_regs *regs)
>> diff --git a/arch/arm64/include/asm/unistd.h b/arch/arm64/include/asm/unistd.h
>> index 82ce217..c335479 100644
>> --- a/arch/arm64/include/asm/unistd.h
>> +++ b/arch/arm64/include/asm/unistd.h
>> @@ -28,3 +28,5 @@
>>   #endif
>>   #define __ARCH_WANT_SYS_CLONE
>>   #include <uapi/asm/unistd.h>
>> +
>> +#define NR_syscalls (__NR_syscalls)
>> diff --git a/arch/arm64/kernel/ptrace.c b/arch/arm64/kernel/ptrace.c
>> index 64ce39f..f4c3c4e 100644
>> --- a/arch/arm64/kernel/ptrace.c
>> +++ b/arch/arm64/kernel/ptrace.c
>> @@ -41,6 +41,9 @@
>>   #include <asm/traps.h>
>>   #include <asm/system_misc.h>
>>
>> +#define CREATE_TRACE_POINTS
>> +#include <trace/events/syscalls.h>
>> +
>>   /*
>>    * TODO: does not yet catch signals sent when the child dies.
>>    * in exit.c or in signal.c.
>> @@ -1076,10 +1079,12 @@ asmlinkage int syscall_trace(int dir, struct pt_regs *regs)
>>   	}
>>
>>   	if (dir) {
>> +		trace_sys_exit(regs, regs->syscallno);
>>   		tracehook_report_syscall_exit(regs, 0);
>>   	} else {
>>   		if (tracehook_report_syscall_entry(regs))
>>   			regs->syscallno = ~0UL;
>> +		trace_sys_enter(regs, regs->syscallno);
>
> Shouldn't these calls be guarded by a TIF_SYSCALL_TRACEPOINT check?

Yes. I will add the guard.

-Takahiro AKASHI

> Will
>

^ permalink raw reply	[flat|nested] 235+ messages in thread

* [PATCH v3 5/6] arm64: ftrace: Add system call tracepoint
@ 2014-02-19 10:48         ` AKASHI Takahiro
  0 siblings, 0 replies; 235+ messages in thread
From: AKASHI Takahiro @ 2014-02-19 10:48 UTC (permalink / raw)
  To: linux-arm-kernel

On 02/18/2014 04:29 AM, Will Deacon wrote:
> On Fri, Feb 07, 2014 at 10:18:55AM +0000, AKASHI Takahiro wrote:
>> This patch allows system call entry or exit to be traced as ftrace events,
>> ie. sys_enter_*/sys_exit_*, if CONFIG_FTRACE_SYSCALLS is enabled.
>> Those events appear and can be controlled under
>>      ${sysfs}/tracing/events/syscalls/
>>
>> Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
>> ---
>>   arch/arm64/Kconfig               |    1 +
>>   arch/arm64/include/asm/syscall.h |    1 +
>>   arch/arm64/include/asm/unistd.h  |    2 ++
>>   arch/arm64/kernel/ptrace.c       |    5 +++++
>>   4 files changed, 9 insertions(+)
>>
>> diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
>> index 43fce76..9bdaf5c 100644
>> --- a/arch/arm64/Kconfig
>> +++ b/arch/arm64/Kconfig
>> @@ -42,6 +42,7 @@ config ARM64
>>   	select HAVE_HW_BREAKPOINT if PERF_EVENTS
>>   	select HAVE_MEMBLOCK
>>   	select HAVE_PERF_EVENTS
>> +	select HAVE_SYSCALL_TRACEPOINTS
>>   	select IRQ_DOMAIN
>>   	select MODULES_USE_ELF_RELA
>>   	select NO_BOOTMEM
>> diff --git a/arch/arm64/include/asm/syscall.h b/arch/arm64/include/asm/syscall.h
>> index 70ba9d4..383771e 100644
>> --- a/arch/arm64/include/asm/syscall.h
>> +++ b/arch/arm64/include/asm/syscall.h
>> @@ -18,6 +18,7 @@
>>
>>   #include <linux/err.h>
>>
>> +extern const void *sys_call_table[];
>>
>>   static inline int syscall_get_nr(struct task_struct *task,
>>   				 struct pt_regs *regs)
>> diff --git a/arch/arm64/include/asm/unistd.h b/arch/arm64/include/asm/unistd.h
>> index 82ce217..c335479 100644
>> --- a/arch/arm64/include/asm/unistd.h
>> +++ b/arch/arm64/include/asm/unistd.h
>> @@ -28,3 +28,5 @@
>>   #endif
>>   #define __ARCH_WANT_SYS_CLONE
>>   #include <uapi/asm/unistd.h>
>> +
>> +#define NR_syscalls (__NR_syscalls)
>> diff --git a/arch/arm64/kernel/ptrace.c b/arch/arm64/kernel/ptrace.c
>> index 64ce39f..f4c3c4e 100644
>> --- a/arch/arm64/kernel/ptrace.c
>> +++ b/arch/arm64/kernel/ptrace.c
>> @@ -41,6 +41,9 @@
>>   #include <asm/traps.h>
>>   #include <asm/system_misc.h>
>>
>> +#define CREATE_TRACE_POINTS
>> +#include <trace/events/syscalls.h>
>> +
>>   /*
>>    * TODO: does not yet catch signals sent when the child dies.
>>    * in exit.c or in signal.c.
>> @@ -1076,10 +1079,12 @@ asmlinkage int syscall_trace(int dir, struct pt_regs *regs)
>>   	}
>>
>>   	if (dir) {
>> +		trace_sys_exit(regs, regs->syscallno);
>>   		tracehook_report_syscall_exit(regs, 0);
>>   	} else {
>>   		if (tracehook_report_syscall_entry(regs))
>>   			regs->syscallno = ~0UL;
>> +		trace_sys_enter(regs, regs->syscallno);
>
> Shouldn't these calls be guarded by a TIF_SYSCALL_TRACEPOINT check?

Yes. I will add the guard.

-Takahiro AKASHI

> Will
>

^ permalink raw reply	[flat|nested] 235+ messages in thread

* [PATCH v4 0/7] arm64: Add ftrace support
  2014-02-07 10:18   ` AKASHI Takahiro
@ 2014-02-25  9:23     ` AKASHI Takahiro
  -1 siblings, 0 replies; 235+ messages in thread
From: AKASHI Takahiro @ 2014-02-25  9:23 UTC (permalink / raw)
  To: rostedt, fweisbec, mingo, catalin.marinas, will.deacon, tim.bird
  Cc: gkulkarni, dsaxena, arndb, linux-arm-kernel, linaro-kernel,
	linux-kernel, AKASHI Takahiro

This patchset implements a function tracer on arm64.
There was another implementation from Cavium network, but both of us agreed
to use my patchset as future base. He is supposed to review this code, too.

The only issue that I had some concern on was "fault protection" code
in prepare_ftrace_return(). With discussions with Steven and Tim (as author
of arm ftrace), I removed that code since I'm not quite sure about possibility
of "fault" occurrences in this function.

The code is tested on ARMv8 Fast Model with the following tracers & events:
     function tracer with dynamic ftrace
     function graph tracer with dynamic ftrace
     syscall tracepoint
     irqsoff & preemptirqsoff (which use CALLER_ADDRx)
and also verified with in-kernel tests, FTRACE_SELFTEST, FTRACE_STARTUP_TEST
and EVENT_TRACE_TEST_SYSCALLS.

Prerequisites are:
 * "arm64: Add regs_return_value() in syscall.h" patch included in
   "arm64: Add audit support" patchset
 * "arm64: make a single hook to syscall_trace() for all syscall features" patch

Please be careful:
* elf.h on cross-build host must have AArch64 definitions, EM_AARCH64 and
  R_AARCH64_ABS64, to compile recordmcount utility. See [4/6].
  [4/6] also gets warnings from checkpatch, but they are based on the
  original's coding style.
* This patch may conflict with my audit patch because both changes the same
  location in syscall_trace(). I expect the functions are called in this
  order:
  On entry,
     * tracehook_report_syscall(ENTER)
     * trace_sys_enter()
     * audit_syscall_entry()
  On exit,
     * audit_sysscall_exit()
     * trace_sys_exit()
     * tracehook_report_syscall(EXIT) 

Changes from v1 to v2:
* splitted one patch into some pieces for easier review
  (especially function tracer + dynamic ftrace + CALLER_ADDRx)
* put return_address() in a separate file
* renamed __mcount to _mcount (it was my mistake)
* changed stackframe handling to get parent's frame pointer
* removed ARCH_SUPPORTS_FTRACE_OPS
* switched to "hotpatch" interfaces from Huawai
* revised descriptions in comments

Changes from v2 to v3:
* optimized register usages in asm (by not saving x0, x1, and x2)
* removed "fault protection" code in prepare_ftrace_return()
* rewrote ftrace_modify_code() using "hotpatch" interfaces
* revised descriptions in comments

Changes from v3 to v4:
* removed unnecessary "#ifdef" [1,2/7]
* changed stack depth from 48B to 16B in mcount()/ftrace_caller() (a bug) [1/7]
* changed MCOUNT_INSN_SIZE to AARCH64_INSN_SIZE [1,7/7]
* added a guard againt TIF_SYSCALL_TRACEPOINT [5/7]
* corrected the second argument passed to trace_sys_exit() (a bug) [5/7]
* aligned with the change in "arm64: make a single hook to syscall_trace()
  for all syscall features" v2 [5/7]

AKASHI Takahiro (7):
  arm64: Add ftrace support
  arm64: ftrace: Add dynamic ftrace support
  arm64: ftrace: Add CALLER_ADDRx macros
  ftrace: Add arm64 support to recordmcount
  arm64: ftrace: Add system call tracepoint
  arm64: Add 'notrace' attribute to unwind_frame() for ftrace
  arm64: add __ASSEMBLY__ in asm/insn.h

 arch/arm64/Kconfig                 |    6 +
 arch/arm64/include/asm/ftrace.h    |   52 +++++++++
 arch/arm64/include/asm/insn.h      |    2 +
 arch/arm64/include/asm/syscall.h   |    1 +
 arch/arm64/include/asm/unistd.h    |    2 +
 arch/arm64/kernel/Makefile         |    7 +-
 arch/arm64/kernel/arm64ksyms.c     |    4 +
 arch/arm64/kernel/entry-ftrace.S   |  216 ++++++++++++++++++++++++++++++++++++
 arch/arm64/kernel/ftrace.c         |  177 +++++++++++++++++++++++++++++
 arch/arm64/kernel/ptrace.c         |    9 ++
 arch/arm64/kernel/return_address.c |   55 +++++++++
 arch/arm64/kernel/stacktrace.c     |    2 +-
 scripts/recordmcount.c             |    4 +
 scripts/recordmcount.pl            |    5 +
 14 files changed, 540 insertions(+), 2 deletions(-)
 create mode 100644 arch/arm64/include/asm/ftrace.h
 create mode 100644 arch/arm64/kernel/entry-ftrace.S
 create mode 100644 arch/arm64/kernel/ftrace.c
 create mode 100644 arch/arm64/kernel/return_address.c

-- 
1.7.9.5


^ permalink raw reply	[flat|nested] 235+ messages in thread

* [PATCH v4 0/7] arm64: Add ftrace support
@ 2014-02-25  9:23     ` AKASHI Takahiro
  0 siblings, 0 replies; 235+ messages in thread
From: AKASHI Takahiro @ 2014-02-25  9:23 UTC (permalink / raw)
  To: linux-arm-kernel

This patchset implements a function tracer on arm64.
There was another implementation from Cavium network, but both of us agreed
to use my patchset as future base. He is supposed to review this code, too.

The only issue that I had some concern on was "fault protection" code
in prepare_ftrace_return(). With discussions with Steven and Tim (as author
of arm ftrace), I removed that code since I'm not quite sure about possibility
of "fault" occurrences in this function.

The code is tested on ARMv8 Fast Model with the following tracers & events:
     function tracer with dynamic ftrace
     function graph tracer with dynamic ftrace
     syscall tracepoint
     irqsoff & preemptirqsoff (which use CALLER_ADDRx)
and also verified with in-kernel tests, FTRACE_SELFTEST, FTRACE_STARTUP_TEST
and EVENT_TRACE_TEST_SYSCALLS.

Prerequisites are:
 * "arm64: Add regs_return_value() in syscall.h" patch included in
   "arm64: Add audit support" patchset
 * "arm64: make a single hook to syscall_trace() for all syscall features" patch

Please be careful:
* elf.h on cross-build host must have AArch64 definitions, EM_AARCH64 and
  R_AARCH64_ABS64, to compile recordmcount utility. See [4/6].
  [4/6] also gets warnings from checkpatch, but they are based on the
  original's coding style.
* This patch may conflict with my audit patch because both changes the same
  location in syscall_trace(). I expect the functions are called in this
  order:
  On entry,
     * tracehook_report_syscall(ENTER)
     * trace_sys_enter()
     * audit_syscall_entry()
  On exit,
     * audit_sysscall_exit()
     * trace_sys_exit()
     * tracehook_report_syscall(EXIT) 

Changes from v1 to v2:
* splitted one patch into some pieces for easier review
  (especially function tracer + dynamic ftrace + CALLER_ADDRx)
* put return_address() in a separate file
* renamed __mcount to _mcount (it was my mistake)
* changed stackframe handling to get parent's frame pointer
* removed ARCH_SUPPORTS_FTRACE_OPS
* switched to "hotpatch" interfaces from Huawai
* revised descriptions in comments

Changes from v2 to v3:
* optimized register usages in asm (by not saving x0, x1, and x2)
* removed "fault protection" code in prepare_ftrace_return()
* rewrote ftrace_modify_code() using "hotpatch" interfaces
* revised descriptions in comments

Changes from v3 to v4:
* removed unnecessary "#ifdef" [1,2/7]
* changed stack depth from 48B to 16B in mcount()/ftrace_caller() (a bug) [1/7]
* changed MCOUNT_INSN_SIZE to AARCH64_INSN_SIZE [1,7/7]
* added a guard againt TIF_SYSCALL_TRACEPOINT [5/7]
* corrected the second argument passed to trace_sys_exit() (a bug) [5/7]
* aligned with the change in "arm64: make a single hook to syscall_trace()
  for all syscall features" v2 [5/7]

AKASHI Takahiro (7):
  arm64: Add ftrace support
  arm64: ftrace: Add dynamic ftrace support
  arm64: ftrace: Add CALLER_ADDRx macros
  ftrace: Add arm64 support to recordmcount
  arm64: ftrace: Add system call tracepoint
  arm64: Add 'notrace' attribute to unwind_frame() for ftrace
  arm64: add __ASSEMBLY__ in asm/insn.h

 arch/arm64/Kconfig                 |    6 +
 arch/arm64/include/asm/ftrace.h    |   52 +++++++++
 arch/arm64/include/asm/insn.h      |    2 +
 arch/arm64/include/asm/syscall.h   |    1 +
 arch/arm64/include/asm/unistd.h    |    2 +
 arch/arm64/kernel/Makefile         |    7 +-
 arch/arm64/kernel/arm64ksyms.c     |    4 +
 arch/arm64/kernel/entry-ftrace.S   |  216 ++++++++++++++++++++++++++++++++++++
 arch/arm64/kernel/ftrace.c         |  177 +++++++++++++++++++++++++++++
 arch/arm64/kernel/ptrace.c         |    9 ++
 arch/arm64/kernel/return_address.c |   55 +++++++++
 arch/arm64/kernel/stacktrace.c     |    2 +-
 scripts/recordmcount.c             |    4 +
 scripts/recordmcount.pl            |    5 +
 14 files changed, 540 insertions(+), 2 deletions(-)
 create mode 100644 arch/arm64/include/asm/ftrace.h
 create mode 100644 arch/arm64/kernel/entry-ftrace.S
 create mode 100644 arch/arm64/kernel/ftrace.c
 create mode 100644 arch/arm64/kernel/return_address.c

-- 
1.7.9.5

^ permalink raw reply	[flat|nested] 235+ messages in thread

* [PATCH v4 1/7] arm64: Add ftrace support
  2014-02-25  9:23     ` AKASHI Takahiro
@ 2014-02-25  9:23       ` AKASHI Takahiro
  -1 siblings, 0 replies; 235+ messages in thread
From: AKASHI Takahiro @ 2014-02-25  9:23 UTC (permalink / raw)
  To: rostedt, fweisbec, mingo, catalin.marinas, will.deacon, tim.bird
  Cc: gkulkarni, dsaxena, arndb, linux-arm-kernel, linaro-kernel,
	linux-kernel, AKASHI Takahiro

This patch implements arm64 specific part to support function tracers,
such as function (CONFIG_FUNCTION_TRACER), function_graph
(CONFIG_FUNCTION_GRAPH_TRACER) and function profiler
(CONFIG_FUNCTION_PROFILER).

With 'function' tracer, all the functions in the kernel are traced with
timestamps in ${sysfs}/tracing/trace. If function_graph tracer is
specified, call graph is generated.

The kernel must be compiled with -pg option so that _mcount() is inserted
at the beginning of functions. This function is called on every function's
entry as long as tracing is enabled.
In addition, function_graph tracer also needs to be able to probe function's
exit. ftrace_graph_caller() & return_to_handler do this by faking link
register's value to intercept function's return path.

More details on architecture specific requirements are described in
Documentation/trace/ftrace-design.txt.

Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
---
 arch/arm64/Kconfig               |    2 +
 arch/arm64/include/asm/ftrace.h  |   23 +++++
 arch/arm64/kernel/Makefile       |    4 +
 arch/arm64/kernel/arm64ksyms.c   |    4 +
 arch/arm64/kernel/entry-ftrace.S |  173 ++++++++++++++++++++++++++++++++++++++
 arch/arm64/kernel/ftrace.c       |   64 ++++++++++++++
 6 files changed, 270 insertions(+)
 create mode 100644 arch/arm64/include/asm/ftrace.h
 create mode 100644 arch/arm64/kernel/entry-ftrace.S
 create mode 100644 arch/arm64/kernel/ftrace.c

diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 27bbcfc..5783641 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -33,6 +33,8 @@ config ARM64
 	select HAVE_DMA_ATTRS
 	select HAVE_DMA_CONTIGUOUS
 	select HAVE_EFFICIENT_UNALIGNED_ACCESS
+	select HAVE_FUNCTION_TRACER
+	select HAVE_FUNCTION_GRAPH_TRACER
 	select HAVE_GENERIC_DMA_COHERENT
 	select HAVE_HW_BREAKPOINT if PERF_EVENTS
 	select HAVE_MEMBLOCK
diff --git a/arch/arm64/include/asm/ftrace.h b/arch/arm64/include/asm/ftrace.h
new file mode 100644
index 0000000..58ea595
--- /dev/null
+++ b/arch/arm64/include/asm/ftrace.h
@@ -0,0 +1,23 @@
+/*
+ * arch/arm64/include/asm/ftrace.h
+ *
+ * Copyright (C) 2013 Linaro Limited
+ * Author: AKASHI Takahiro <takahiro.akashi@linaro.org>
+ *
+ * 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.
+ */
+#ifndef __ASM_FTRACE_H
+#define __ASM_FTRACE_H
+
+#include <asm/insn.h>
+
+#define MCOUNT_ADDR		((unsigned long)_mcount)
+#define MCOUNT_INSN_SIZE	AARCH64_INSN_SIZE
+
+#ifndef __ASSEMBLY__
+extern void _mcount(unsigned long);
+#endif /* __ASSEMBLY__ */
+
+#endif /* __ASM_FTRACE_H */
diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile
index 2d4554b..ac67fd0 100644
--- a/arch/arm64/kernel/Makefile
+++ b/arch/arm64/kernel/Makefile
@@ -5,6 +5,9 @@
 CPPFLAGS_vmlinux.lds	:= -DTEXT_OFFSET=$(TEXT_OFFSET)
 AFLAGS_head.o		:= -DTEXT_OFFSET=$(TEXT_OFFSET)
 
+CFLAGS_REMOVE_ftrace.o = -pg
+CFLAGS_REMOVE_insn.o = -pg
+
 # Object file lists.
 arm64-obj-y		:= cputable.o debug-monitors.o entry.o irq.o fpsimd.o	\
 			   entry-fpsimd.o process.o ptrace.o setup.o signal.o	\
@@ -13,6 +16,7 @@ arm64-obj-y		:= cputable.o debug-monitors.o entry.o irq.o fpsimd.o	\
 
 arm64-obj-$(CONFIG_COMPAT)		+= sys32.o kuser32.o signal32.o 	\
 					   sys_compat.o
+arm64-obj-$(CONFIG_FUNCTION_TRACER)	+= ftrace.o entry-ftrace.o
 arm64-obj-$(CONFIG_MODULES)		+= arm64ksyms.o module.o
 arm64-obj-$(CONFIG_SMP)			+= smp.o smp_spin_table.o
 arm64-obj-$(CONFIG_HW_PERF_EVENTS)	+= perf_event.o
diff --git a/arch/arm64/kernel/arm64ksyms.c b/arch/arm64/kernel/arm64ksyms.c
index 338b568..7f0512f 100644
--- a/arch/arm64/kernel/arm64ksyms.c
+++ b/arch/arm64/kernel/arm64ksyms.c
@@ -56,3 +56,7 @@ EXPORT_SYMBOL(clear_bit);
 EXPORT_SYMBOL(test_and_clear_bit);
 EXPORT_SYMBOL(change_bit);
 EXPORT_SYMBOL(test_and_change_bit);
+
+#ifdef CONFIG_FUNCTION_TRACER
+EXPORT_SYMBOL(_mcount);
+#endif
diff --git a/arch/arm64/kernel/entry-ftrace.S b/arch/arm64/kernel/entry-ftrace.S
new file mode 100644
index 0000000..2e8162e
--- /dev/null
+++ b/arch/arm64/kernel/entry-ftrace.S
@@ -0,0 +1,173 @@
+/*
+ * arch/arm64/kernel/entry-ftrace.S
+ *
+ * Copyright (C) 2013 Linaro Limited
+ * Author: AKASHI Takahiro <takahiro.akashi@linaro.org>
+ *
+ * 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 <linux/linkage.h>
+#include <asm/ftrace.h>
+#include <asm/insn.h>
+
+/*
+ * Gcc with -pg will put the following code in the beginning of each function:
+ *      mov x0, x30
+ *      bl _mcount
+ *	[function's body ...]
+ * "bl _mcount" may be replaced to "bl ftrace_caller" or NOP if dynamic
+ * ftrace is enabled.
+ *
+ * Please note that x0 as an argument will not be used here because we can
+ * get lr(x30) of instrumented function at any time by winding up call stack
+ * as long as the kernel is compiled without -fomit-frame-pointer.
+ * (or CONFIG_FRAME_POINTER, this is forced on arm64)
+ *
+ * stack layout after mcount_enter:
+ *
+ *   0 ---------------------------------------- sp of _mcount()
+ *      x29: fp of instrumented function	fp is not winded
+ *     --------------------
+ *      x30: lr of _mcount() (= instrumented function's pc)
+ * +16 ---------------------------------------- sp of instrumented function
+ *
+ *     ....
+ *
+ * +xx ---------------------------------------- fp of instrumented function
+ *      x29: fp of parent
+ *     --------------------
+ *      x30: lr of instrumented function (= parent's pc)
+ *     --------------------
+ *      xxx
+ */
+
+	.macro mcount_enter
+	stp	x29, x30, [sp, #-16]!
+	.endm
+
+	.macro mcount_exit
+	ldp	x29, x30, [sp], #16
+	ret
+	.endm
+
+	.macro mcount_adjust_addr rd, rn
+	sub	\rd, \rn, #AARCH64_INSN_SIZE
+	.endm
+
+	/* for instrumented function's parent */
+	.macro mcount_get_parent_fp reg
+	ldr	\reg, [sp]
+	ldr	\reg, [\reg]
+	.endm
+
+	/* for instrumented function */
+	.macro mcount_get_pc0 reg
+	mcount_adjust_addr	\reg, x30
+	.endm
+
+	.macro mcount_get_pc reg
+	ldr	\reg, [sp, #8]
+	mcount_adjust_addr	\reg, \reg
+	.endm
+
+	.macro mcount_get_lr reg
+	ldr	\reg, [sp]
+	ldr	\reg, [\reg, #8]
+	mcount_adjust_addr	\reg, \reg
+	.endm
+
+	.macro mcount_get_saved_lr_addr reg
+	ldr	\reg, [sp]
+	add	\reg, \reg, #8
+	.endm
+
+/*
+ * void _mcount(unsigned long return_address)
+ * @return_address: return address to instrumented function
+ *
+ * This function makes calls, if enabled, to:
+ *     - tracer function to probe instrumented function's entry,
+ *     - ftrace_graph_caller to set up an exit hook
+ */
+ENTRY(_mcount)
+#ifdef CONFIG_HAVE_FUNCTION_TRACE_MCOUNT_TEST
+	ldr	x0, =ftrace_trace_stop
+	ldr	x0, [x0]		// if ftrace_trace_stop
+	ret				//   return;
+#endif
+	mcount_enter
+
+	ldr	x0, =ftrace_trace_function
+	ldr	x2, [x0]
+	adr	x0, ftrace_stub
+	cmp	x0, x2			// if (ftrace_trace_function
+	b.eq	skip_ftrace_call	//     != ftrace_stub) {
+
+	mcount_get_pc	x0		//       function's pc
+	mcount_get_lr	x1		//       function's lr (= parent's pc)
+	blr	x2			//   (*ftrace_trace_function)(pc, lr);
+
+#ifndef CONFIG_FUNCTION_GRAPH_TRACER
+skip_ftrace_call:			//   return;
+	mcount_exit			// }
+#else
+	mcount_exit			//   return;
+					// }
+skip_ftrace_call:
+	ldr	x1, =ftrace_graph_return
+	ldr	x2, [x1]		//   if ((ftrace_graph_return
+	cmp	x0, x2			//        != ftrace_stub)
+	b.ne	ftrace_graph_caller
+
+	ldr	x1, =ftrace_graph_entry	//     || (ftrace_graph_entry
+	ldr	x2, [x1]		//        != ftrace_graph_entry_stub))
+	ldr	x0, =ftrace_graph_entry_stub
+	cmp	x0, x2
+	b.ne	ftrace_graph_caller	//     ftrace_graph_caller();
+
+	mcount_exit
+#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
+ENDPROC(_mcount)
+
+ENTRY(ftrace_stub)
+	ret
+ENDPROC(ftrace_stub)
+
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+/*
+ * void ftrace_graph_caller(void)
+ *
+ * Called from _mcount() or ftrace_caller() when function_graph tracer is
+ * selected.
+ * This function w/ prepare_ftrace_return() fakes link register's value on
+ * the call stack in order to intercept instrumented function's return path
+ * and run return_to_handler() later on its exit.
+ */
+ENTRY(ftrace_graph_caller)
+	mcount_get_saved_lr_addr  x0	//     pointer to function's saved lr
+	mcount_get_pc		  x1	//     function's pc
+	mcount_get_parent_fp	  x2	//     parent's fp
+	bl	prepare_ftrace_return	// prepare_ftrace_return(&lr, pc, fp)
+
+	mcount_exit
+ENDPROC(ftrace_graph_caller)
+
+/*
+ * void return_to_handler(void)
+ *
+ * Run ftrace_return_to_handler() before going back to parent.
+ * @fp is checked against the value passed by ftrace_graph_caller()
+ * only when CONFIG_FUNCTION_GRAPH_FP_TEST is enabled.
+ */
+	.global return_to_handler
+return_to_handler:
+	str	x0, [sp, #-16]!
+	mov	x0, x29			//     parent's fp
+	bl	ftrace_return_to_handler// addr = ftrace_return_to_hander(fp);
+	mov	x30, x0			// restore the original return address
+	ldr	x0, [sp], #16
+	ret
+#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
diff --git a/arch/arm64/kernel/ftrace.c b/arch/arm64/kernel/ftrace.c
new file mode 100644
index 0000000..a559ab8
--- /dev/null
+++ b/arch/arm64/kernel/ftrace.c
@@ -0,0 +1,64 @@
+/*
+ * arch/arm64/kernel/ftrace.c
+ *
+ * Copyright (C) 2013 Linaro Limited
+ * Author: AKASHI Takahiro <takahiro.akashi@linaro.org>
+ *
+ * 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 <linux/ftrace.h>
+#include <linux/swab.h>
+#include <linux/uaccess.h>
+
+#include <asm/cacheflush.h>
+#include <asm/ftrace.h>
+#include <asm/insn.h>
+
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+/*
+ * function_graph tracer expects ftrace_return_to_handler() to be called
+ * on the way back to parent. For this purpose, this function is called
+ * in _mcount() or ftrace_caller() to replace return address (*parent) on
+ * the call stack to return_to_handler.
+ *
+ * Note that @frame_pointer is used only for sanity check later.
+ */
+void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr,
+			   unsigned long frame_pointer)
+{
+	unsigned long return_hooker = (unsigned long)&return_to_handler;
+	unsigned long old;
+	struct ftrace_graph_ent trace;
+	int err;
+
+	if (unlikely(atomic_read(&current->tracing_graph_pause)))
+		return;
+
+	/*
+	 * Note:
+	 * No protection against faulting at *parent, which may be seen
+	 * on other archs. It's unlikely on AArch64.
+	 */
+	old = *parent;
+	*parent = return_hooker;
+
+	trace.func = self_addr;
+	trace.depth = current->curr_ret_stack + 1;
+
+	/* Only trace if the calling function expects to */
+	if (!ftrace_graph_entry(&trace)) {
+		*parent = old;
+		return;
+	}
+
+	err = ftrace_push_return_trace(old, self_addr, &trace.depth,
+				       frame_pointer);
+	if (err == -EBUSY) {
+		*parent = old;
+		return;
+	}
+}
+#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 235+ messages in thread

* [PATCH v4 1/7] arm64: Add ftrace support
@ 2014-02-25  9:23       ` AKASHI Takahiro
  0 siblings, 0 replies; 235+ messages in thread
From: AKASHI Takahiro @ 2014-02-25  9:23 UTC (permalink / raw)
  To: linux-arm-kernel

This patch implements arm64 specific part to support function tracers,
such as function (CONFIG_FUNCTION_TRACER), function_graph
(CONFIG_FUNCTION_GRAPH_TRACER) and function profiler
(CONFIG_FUNCTION_PROFILER).

With 'function' tracer, all the functions in the kernel are traced with
timestamps in ${sysfs}/tracing/trace. If function_graph tracer is
specified, call graph is generated.

The kernel must be compiled with -pg option so that _mcount() is inserted
at the beginning of functions. This function is called on every function's
entry as long as tracing is enabled.
In addition, function_graph tracer also needs to be able to probe function's
exit. ftrace_graph_caller() & return_to_handler do this by faking link
register's value to intercept function's return path.

More details on architecture specific requirements are described in
Documentation/trace/ftrace-design.txt.

Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
---
 arch/arm64/Kconfig               |    2 +
 arch/arm64/include/asm/ftrace.h  |   23 +++++
 arch/arm64/kernel/Makefile       |    4 +
 arch/arm64/kernel/arm64ksyms.c   |    4 +
 arch/arm64/kernel/entry-ftrace.S |  173 ++++++++++++++++++++++++++++++++++++++
 arch/arm64/kernel/ftrace.c       |   64 ++++++++++++++
 6 files changed, 270 insertions(+)
 create mode 100644 arch/arm64/include/asm/ftrace.h
 create mode 100644 arch/arm64/kernel/entry-ftrace.S
 create mode 100644 arch/arm64/kernel/ftrace.c

diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 27bbcfc..5783641 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -33,6 +33,8 @@ config ARM64
 	select HAVE_DMA_ATTRS
 	select HAVE_DMA_CONTIGUOUS
 	select HAVE_EFFICIENT_UNALIGNED_ACCESS
+	select HAVE_FUNCTION_TRACER
+	select HAVE_FUNCTION_GRAPH_TRACER
 	select HAVE_GENERIC_DMA_COHERENT
 	select HAVE_HW_BREAKPOINT if PERF_EVENTS
 	select HAVE_MEMBLOCK
diff --git a/arch/arm64/include/asm/ftrace.h b/arch/arm64/include/asm/ftrace.h
new file mode 100644
index 0000000..58ea595
--- /dev/null
+++ b/arch/arm64/include/asm/ftrace.h
@@ -0,0 +1,23 @@
+/*
+ * arch/arm64/include/asm/ftrace.h
+ *
+ * Copyright (C) 2013 Linaro Limited
+ * Author: AKASHI Takahiro <takahiro.akashi@linaro.org>
+ *
+ * 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.
+ */
+#ifndef __ASM_FTRACE_H
+#define __ASM_FTRACE_H
+
+#include <asm/insn.h>
+
+#define MCOUNT_ADDR		((unsigned long)_mcount)
+#define MCOUNT_INSN_SIZE	AARCH64_INSN_SIZE
+
+#ifndef __ASSEMBLY__
+extern void _mcount(unsigned long);
+#endif /* __ASSEMBLY__ */
+
+#endif /* __ASM_FTRACE_H */
diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile
index 2d4554b..ac67fd0 100644
--- a/arch/arm64/kernel/Makefile
+++ b/arch/arm64/kernel/Makefile
@@ -5,6 +5,9 @@
 CPPFLAGS_vmlinux.lds	:= -DTEXT_OFFSET=$(TEXT_OFFSET)
 AFLAGS_head.o		:= -DTEXT_OFFSET=$(TEXT_OFFSET)
 
+CFLAGS_REMOVE_ftrace.o = -pg
+CFLAGS_REMOVE_insn.o = -pg
+
 # Object file lists.
 arm64-obj-y		:= cputable.o debug-monitors.o entry.o irq.o fpsimd.o	\
 			   entry-fpsimd.o process.o ptrace.o setup.o signal.o	\
@@ -13,6 +16,7 @@ arm64-obj-y		:= cputable.o debug-monitors.o entry.o irq.o fpsimd.o	\
 
 arm64-obj-$(CONFIG_COMPAT)		+= sys32.o kuser32.o signal32.o 	\
 					   sys_compat.o
+arm64-obj-$(CONFIG_FUNCTION_TRACER)	+= ftrace.o entry-ftrace.o
 arm64-obj-$(CONFIG_MODULES)		+= arm64ksyms.o module.o
 arm64-obj-$(CONFIG_SMP)			+= smp.o smp_spin_table.o
 arm64-obj-$(CONFIG_HW_PERF_EVENTS)	+= perf_event.o
diff --git a/arch/arm64/kernel/arm64ksyms.c b/arch/arm64/kernel/arm64ksyms.c
index 338b568..7f0512f 100644
--- a/arch/arm64/kernel/arm64ksyms.c
+++ b/arch/arm64/kernel/arm64ksyms.c
@@ -56,3 +56,7 @@ EXPORT_SYMBOL(clear_bit);
 EXPORT_SYMBOL(test_and_clear_bit);
 EXPORT_SYMBOL(change_bit);
 EXPORT_SYMBOL(test_and_change_bit);
+
+#ifdef CONFIG_FUNCTION_TRACER
+EXPORT_SYMBOL(_mcount);
+#endif
diff --git a/arch/arm64/kernel/entry-ftrace.S b/arch/arm64/kernel/entry-ftrace.S
new file mode 100644
index 0000000..2e8162e
--- /dev/null
+++ b/arch/arm64/kernel/entry-ftrace.S
@@ -0,0 +1,173 @@
+/*
+ * arch/arm64/kernel/entry-ftrace.S
+ *
+ * Copyright (C) 2013 Linaro Limited
+ * Author: AKASHI Takahiro <takahiro.akashi@linaro.org>
+ *
+ * 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 <linux/linkage.h>
+#include <asm/ftrace.h>
+#include <asm/insn.h>
+
+/*
+ * Gcc with -pg will put the following code in the beginning of each function:
+ *      mov x0, x30
+ *      bl _mcount
+ *	[function's body ...]
+ * "bl _mcount" may be replaced to "bl ftrace_caller" or NOP if dynamic
+ * ftrace is enabled.
+ *
+ * Please note that x0 as an argument will not be used here because we can
+ * get lr(x30) of instrumented function at any time by winding up call stack
+ * as long as the kernel is compiled without -fomit-frame-pointer.
+ * (or CONFIG_FRAME_POINTER, this is forced on arm64)
+ *
+ * stack layout after mcount_enter:
+ *
+ *   0 ---------------------------------------- sp of _mcount()
+ *      x29: fp of instrumented function	fp is not winded
+ *     --------------------
+ *      x30: lr of _mcount() (= instrumented function's pc)
+ * +16 ---------------------------------------- sp of instrumented function
+ *
+ *     ....
+ *
+ * +xx ---------------------------------------- fp of instrumented function
+ *      x29: fp of parent
+ *     --------------------
+ *      x30: lr of instrumented function (= parent's pc)
+ *     --------------------
+ *      xxx
+ */
+
+	.macro mcount_enter
+	stp	x29, x30, [sp, #-16]!
+	.endm
+
+	.macro mcount_exit
+	ldp	x29, x30, [sp], #16
+	ret
+	.endm
+
+	.macro mcount_adjust_addr rd, rn
+	sub	\rd, \rn, #AARCH64_INSN_SIZE
+	.endm
+
+	/* for instrumented function's parent */
+	.macro mcount_get_parent_fp reg
+	ldr	\reg, [sp]
+	ldr	\reg, [\reg]
+	.endm
+
+	/* for instrumented function */
+	.macro mcount_get_pc0 reg
+	mcount_adjust_addr	\reg, x30
+	.endm
+
+	.macro mcount_get_pc reg
+	ldr	\reg, [sp, #8]
+	mcount_adjust_addr	\reg, \reg
+	.endm
+
+	.macro mcount_get_lr reg
+	ldr	\reg, [sp]
+	ldr	\reg, [\reg, #8]
+	mcount_adjust_addr	\reg, \reg
+	.endm
+
+	.macro mcount_get_saved_lr_addr reg
+	ldr	\reg, [sp]
+	add	\reg, \reg, #8
+	.endm
+
+/*
+ * void _mcount(unsigned long return_address)
+ * @return_address: return address to instrumented function
+ *
+ * This function makes calls, if enabled, to:
+ *     - tracer function to probe instrumented function's entry,
+ *     - ftrace_graph_caller to set up an exit hook
+ */
+ENTRY(_mcount)
+#ifdef CONFIG_HAVE_FUNCTION_TRACE_MCOUNT_TEST
+	ldr	x0, =ftrace_trace_stop
+	ldr	x0, [x0]		// if ftrace_trace_stop
+	ret				//   return;
+#endif
+	mcount_enter
+
+	ldr	x0, =ftrace_trace_function
+	ldr	x2, [x0]
+	adr	x0, ftrace_stub
+	cmp	x0, x2			// if (ftrace_trace_function
+	b.eq	skip_ftrace_call	//     != ftrace_stub) {
+
+	mcount_get_pc	x0		//       function's pc
+	mcount_get_lr	x1		//       function's lr (= parent's pc)
+	blr	x2			//   (*ftrace_trace_function)(pc, lr);
+
+#ifndef CONFIG_FUNCTION_GRAPH_TRACER
+skip_ftrace_call:			//   return;
+	mcount_exit			// }
+#else
+	mcount_exit			//   return;
+					// }
+skip_ftrace_call:
+	ldr	x1, =ftrace_graph_return
+	ldr	x2, [x1]		//   if ((ftrace_graph_return
+	cmp	x0, x2			//        != ftrace_stub)
+	b.ne	ftrace_graph_caller
+
+	ldr	x1, =ftrace_graph_entry	//     || (ftrace_graph_entry
+	ldr	x2, [x1]		//        != ftrace_graph_entry_stub))
+	ldr	x0, =ftrace_graph_entry_stub
+	cmp	x0, x2
+	b.ne	ftrace_graph_caller	//     ftrace_graph_caller();
+
+	mcount_exit
+#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
+ENDPROC(_mcount)
+
+ENTRY(ftrace_stub)
+	ret
+ENDPROC(ftrace_stub)
+
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+/*
+ * void ftrace_graph_caller(void)
+ *
+ * Called from _mcount() or ftrace_caller() when function_graph tracer is
+ * selected.
+ * This function w/ prepare_ftrace_return() fakes link register's value on
+ * the call stack in order to intercept instrumented function's return path
+ * and run return_to_handler() later on its exit.
+ */
+ENTRY(ftrace_graph_caller)
+	mcount_get_saved_lr_addr  x0	//     pointer to function's saved lr
+	mcount_get_pc		  x1	//     function's pc
+	mcount_get_parent_fp	  x2	//     parent's fp
+	bl	prepare_ftrace_return	// prepare_ftrace_return(&lr, pc, fp)
+
+	mcount_exit
+ENDPROC(ftrace_graph_caller)
+
+/*
+ * void return_to_handler(void)
+ *
+ * Run ftrace_return_to_handler() before going back to parent.
+ * @fp is checked against the value passed by ftrace_graph_caller()
+ * only when CONFIG_FUNCTION_GRAPH_FP_TEST is enabled.
+ */
+	.global return_to_handler
+return_to_handler:
+	str	x0, [sp, #-16]!
+	mov	x0, x29			//     parent's fp
+	bl	ftrace_return_to_handler// addr = ftrace_return_to_hander(fp);
+	mov	x30, x0			// restore the original return address
+	ldr	x0, [sp], #16
+	ret
+#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
diff --git a/arch/arm64/kernel/ftrace.c b/arch/arm64/kernel/ftrace.c
new file mode 100644
index 0000000..a559ab8
--- /dev/null
+++ b/arch/arm64/kernel/ftrace.c
@@ -0,0 +1,64 @@
+/*
+ * arch/arm64/kernel/ftrace.c
+ *
+ * Copyright (C) 2013 Linaro Limited
+ * Author: AKASHI Takahiro <takahiro.akashi@linaro.org>
+ *
+ * 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 <linux/ftrace.h>
+#include <linux/swab.h>
+#include <linux/uaccess.h>
+
+#include <asm/cacheflush.h>
+#include <asm/ftrace.h>
+#include <asm/insn.h>
+
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+/*
+ * function_graph tracer expects ftrace_return_to_handler() to be called
+ * on the way back to parent. For this purpose, this function is called
+ * in _mcount() or ftrace_caller() to replace return address (*parent) on
+ * the call stack to return_to_handler.
+ *
+ * Note that @frame_pointer is used only for sanity check later.
+ */
+void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr,
+			   unsigned long frame_pointer)
+{
+	unsigned long return_hooker = (unsigned long)&return_to_handler;
+	unsigned long old;
+	struct ftrace_graph_ent trace;
+	int err;
+
+	if (unlikely(atomic_read(&current->tracing_graph_pause)))
+		return;
+
+	/*
+	 * Note:
+	 * No protection against faulting at *parent, which may be seen
+	 * on other archs. It's unlikely on AArch64.
+	 */
+	old = *parent;
+	*parent = return_hooker;
+
+	trace.func = self_addr;
+	trace.depth = current->curr_ret_stack + 1;
+
+	/* Only trace if the calling function expects to */
+	if (!ftrace_graph_entry(&trace)) {
+		*parent = old;
+		return;
+	}
+
+	err = ftrace_push_return_trace(old, self_addr, &trace.depth,
+				       frame_pointer);
+	if (err == -EBUSY) {
+		*parent = old;
+		return;
+	}
+}
+#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 235+ messages in thread

* [PATCH v4 2/7] arm64: ftrace: Add dynamic ftrace support
  2014-02-25  9:23     ` AKASHI Takahiro
@ 2014-02-25  9:23       ` AKASHI Takahiro
  -1 siblings, 0 replies; 235+ messages in thread
From: AKASHI Takahiro @ 2014-02-25  9:23 UTC (permalink / raw)
  To: rostedt, fweisbec, mingo, catalin.marinas, will.deacon, tim.bird
  Cc: gkulkarni, dsaxena, arndb, linux-arm-kernel, linaro-kernel,
	linux-kernel, AKASHI Takahiro

This patch allows "dynamic ftrace" if CONFIG_DYNAMIC_FTRACE is enabled.
Here we can turn on and off tracing dynamically per-function base.

On arm64, this is done by patching single branch instruction to _mcount()
inserted by gcc -pg option. The branch is replaced to NOP initially at
kernel start up, and later on, NOP to branch to ftrace_caller() when
enabled or branch to NOP when disabled.
Please note that ftrace_caller() is a counterpart of _mcount() in case of
'static' ftrace.

More details on architecture specific requirements are described in
Documentation/trace/ftrace-design.txt.

Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
---
 arch/arm64/Kconfig               |    1 +
 arch/arm64/include/asm/ftrace.h  |   15 +++++
 arch/arm64/kernel/entry-ftrace.S |   43 +++++++++++++++
 arch/arm64/kernel/ftrace.c       |  113 ++++++++++++++++++++++++++++++++++++++
 4 files changed, 172 insertions(+)

diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 5783641..b176bc0 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -32,6 +32,7 @@ config ARM64
 	select HAVE_DMA_API_DEBUG
 	select HAVE_DMA_ATTRS
 	select HAVE_DMA_CONTIGUOUS
+	select HAVE_DYNAMIC_FTRACE
 	select HAVE_EFFICIENT_UNALIGNED_ACCESS
 	select HAVE_FUNCTION_TRACER
 	select HAVE_FUNCTION_GRAPH_TRACER
diff --git a/arch/arm64/include/asm/ftrace.h b/arch/arm64/include/asm/ftrace.h
index 58ea595..ed5c448 100644
--- a/arch/arm64/include/asm/ftrace.h
+++ b/arch/arm64/include/asm/ftrace.h
@@ -18,6 +18,21 @@
 
 #ifndef __ASSEMBLY__
 extern void _mcount(unsigned long);
+
+struct dyn_arch_ftrace {
+	/* No extra data needed for arm64 */
+};
+
+extern unsigned long ftrace_graph_call;
+
+static inline unsigned long ftrace_call_adjust(unsigned long addr)
+{
+	/*
+	 * addr is the address of the mcount call instruction.
+	 * recordmcount does the necessary offset calculation.
+	 */
+	return addr;
+}
 #endif /* __ASSEMBLY__ */
 
 #endif /* __ASM_FTRACE_H */
diff --git a/arch/arm64/kernel/entry-ftrace.S b/arch/arm64/kernel/entry-ftrace.S
index 2e8162e..b948878 100644
--- a/arch/arm64/kernel/entry-ftrace.S
+++ b/arch/arm64/kernel/entry-ftrace.S
@@ -84,6 +84,7 @@
 	add	\reg, \reg, #8
 	.endm
 
+#ifndef CONFIG_DYNAMIC_FTRACE
 /*
  * void _mcount(unsigned long return_address)
  * @return_address: return address to instrumented function
@@ -132,6 +133,48 @@ skip_ftrace_call:
 #endif /* CONFIG_FUNCTION_GRAPH_TRACER */
 ENDPROC(_mcount)
 
+#else /* CONFIG_DYNAMIC_FTRACE */
+/*
+ * _mcount() is used to build the kernel with -pg option, but all the branch
+ * instructions to _mcount() are replaced to NOP initially at kernel start up,
+ * and later on, NOP to branch to ftrace_caller() when enabled or branch to
+ * NOP when disabled per-function base.
+ */
+ENTRY(_mcount)
+	ret
+ENDPROC(_mcount)
+
+/*
+ * void ftrace_caller(unsigned long return_address)
+ * @return_address: return address to instrumented function
+ *
+ * This function is a counterpart of _mcount() in 'static' ftrace, and
+ * makes calls to:
+ *     - tracer function to probe instrumented function's entry,
+ *     - ftrace_graph_caller to set up an exit hook
+ */
+ENTRY(ftrace_caller)
+	mcount_enter
+
+	mcount_get_pc0	x0		//     function's pc
+	mcount_get_lr	x1		//     function's lr
+
+	.global ftrace_call
+ftrace_call:				// tracer(pc, lr);
+	nop				// This will be replaced with "bl xxx"
+					// where xxx can be any kind of tracer.
+
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+	.global ftrace_graph_call
+ftrace_graph_call:			// ftrace_graph_caller();
+	nop				// If enabled, this will be replaced
+					// "b ftrace_graph_caller"
+#endif
+
+	mcount_exit
+ENDPROC(ftrace_caller)
+#endif /* CONFIG_DYNAMIC_FTRACE */
+
 ENTRY(ftrace_stub)
 	ret
 ENDPROC(ftrace_stub)
diff --git a/arch/arm64/kernel/ftrace.c b/arch/arm64/kernel/ftrace.c
index a559ab8..8c26476 100644
--- a/arch/arm64/kernel/ftrace.c
+++ b/arch/arm64/kernel/ftrace.c
@@ -17,6 +17,89 @@
 #include <asm/ftrace.h>
 #include <asm/insn.h>
 
+#ifdef CONFIG_DYNAMIC_FTRACE
+/*
+ * Replace a single instruction, which may be a branch or NOP.
+ * If @validate == true, a replaced instruction is checked against 'old'.
+ */
+static int ftrace_modify_code(unsigned long pc, unsigned int old,
+			      unsigned int new, bool validate)
+{
+	unsigned int replaced;
+
+	/*
+	 * Note:
+	 * Due to modules and __init, code can disappear and change,
+	 * we need to protect against faulting as well as code changing.
+	 * We do this by aarch64_insn_*() which use the probe_kernel_*().
+	 *
+	 * No lock is held here because all the modifications are run
+	 * through stop_machine().
+	 */
+	if (validate) {
+		if (aarch64_insn_read((void *)pc, &replaced))
+			return -EFAULT;
+
+		if (replaced != old)
+			return -EINVAL;
+	}
+	if (aarch64_insn_patch_text_nosync((void *)pc, new))
+		return -EPERM;
+
+	return 0;
+}
+
+/*
+ * Replace tracer function in ftrace_caller()
+ */
+int ftrace_update_ftrace_func(ftrace_func_t func)
+{
+	unsigned long pc;
+	unsigned int new;
+
+	pc = (unsigned long)&ftrace_call;
+	new = aarch64_insn_gen_branch_imm(pc, (unsigned long)func, true);
+
+	return ftrace_modify_code(pc, 0, new, false);
+}
+
+/*
+ * Turn on the call to ftrace_caller() in instrumented function
+ */
+int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
+{
+	unsigned long pc = rec->ip;
+	unsigned int old, new;
+
+	old = aarch64_insn_gen_nop();
+	new = aarch64_insn_gen_branch_imm(pc, addr, true);
+
+	return ftrace_modify_code(pc, old, new, true);
+}
+
+/*
+ * Turn off the call to ftrace_caller() in instrumented function
+ */
+int ftrace_make_nop(struct module *mod,
+		    struct dyn_ftrace *rec, unsigned long addr)
+{
+	unsigned long pc = rec->ip;
+	unsigned int old, new;
+
+	old = aarch64_insn_gen_branch_imm(pc, addr, true);
+	new = aarch64_insn_gen_nop();
+
+	return ftrace_modify_code(pc, old, new, true);
+}
+
+int __init ftrace_dyn_arch_init(void *data)
+{
+	*(unsigned long *)data = 0;
+
+	return 0;
+}
+#endif /* CONFIG_DYNAMIC_FTRACE */
+
 #ifdef CONFIG_FUNCTION_GRAPH_TRACER
 /*
  * function_graph tracer expects ftrace_return_to_handler() to be called
@@ -61,4 +144,34 @@ void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr,
 		return;
 	}
 }
+
+#ifdef CONFIG_DYNAMIC_FTRACE
+/*
+ * Turn on/off the call to ftrace_graph_caller() in ftrace_caller()
+ * depending on @enable.
+ */
+static int ftrace_modify_graph_caller(bool enable)
+{
+	unsigned long pc = (unsigned long)&ftrace_graph_call;
+	unsigned int branch, nop, old, new;
+
+	branch = aarch64_insn_gen_branch_imm(pc,
+			(unsigned long)ftrace_graph_caller, false);
+	nop = aarch64_insn_gen_nop();
+	old = enable ? nop : branch;
+	new = enable ? branch : nop;
+
+	return ftrace_modify_code(pc, old, new, true);
+}
+
+int ftrace_enable_ftrace_graph_caller(void)
+{
+	return ftrace_modify_graph_caller(true);
+}
+
+int ftrace_disable_ftrace_graph_caller(void)
+{
+	return ftrace_modify_graph_caller(false);
+}
+#endif /* CONFIG_DYNAMIC_FTRACE */
 #endif /* CONFIG_FUNCTION_GRAPH_TRACER */
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 235+ messages in thread

* [PATCH v4 2/7] arm64: ftrace: Add dynamic ftrace support
@ 2014-02-25  9:23       ` AKASHI Takahiro
  0 siblings, 0 replies; 235+ messages in thread
From: AKASHI Takahiro @ 2014-02-25  9:23 UTC (permalink / raw)
  To: linux-arm-kernel

This patch allows "dynamic ftrace" if CONFIG_DYNAMIC_FTRACE is enabled.
Here we can turn on and off tracing dynamically per-function base.

On arm64, this is done by patching single branch instruction to _mcount()
inserted by gcc -pg option. The branch is replaced to NOP initially at
kernel start up, and later on, NOP to branch to ftrace_caller() when
enabled or branch to NOP when disabled.
Please note that ftrace_caller() is a counterpart of _mcount() in case of
'static' ftrace.

More details on architecture specific requirements are described in
Documentation/trace/ftrace-design.txt.

Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
---
 arch/arm64/Kconfig               |    1 +
 arch/arm64/include/asm/ftrace.h  |   15 +++++
 arch/arm64/kernel/entry-ftrace.S |   43 +++++++++++++++
 arch/arm64/kernel/ftrace.c       |  113 ++++++++++++++++++++++++++++++++++++++
 4 files changed, 172 insertions(+)

diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 5783641..b176bc0 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -32,6 +32,7 @@ config ARM64
 	select HAVE_DMA_API_DEBUG
 	select HAVE_DMA_ATTRS
 	select HAVE_DMA_CONTIGUOUS
+	select HAVE_DYNAMIC_FTRACE
 	select HAVE_EFFICIENT_UNALIGNED_ACCESS
 	select HAVE_FUNCTION_TRACER
 	select HAVE_FUNCTION_GRAPH_TRACER
diff --git a/arch/arm64/include/asm/ftrace.h b/arch/arm64/include/asm/ftrace.h
index 58ea595..ed5c448 100644
--- a/arch/arm64/include/asm/ftrace.h
+++ b/arch/arm64/include/asm/ftrace.h
@@ -18,6 +18,21 @@
 
 #ifndef __ASSEMBLY__
 extern void _mcount(unsigned long);
+
+struct dyn_arch_ftrace {
+	/* No extra data needed for arm64 */
+};
+
+extern unsigned long ftrace_graph_call;
+
+static inline unsigned long ftrace_call_adjust(unsigned long addr)
+{
+	/*
+	 * addr is the address of the mcount call instruction.
+	 * recordmcount does the necessary offset calculation.
+	 */
+	return addr;
+}
 #endif /* __ASSEMBLY__ */
 
 #endif /* __ASM_FTRACE_H */
diff --git a/arch/arm64/kernel/entry-ftrace.S b/arch/arm64/kernel/entry-ftrace.S
index 2e8162e..b948878 100644
--- a/arch/arm64/kernel/entry-ftrace.S
+++ b/arch/arm64/kernel/entry-ftrace.S
@@ -84,6 +84,7 @@
 	add	\reg, \reg, #8
 	.endm
 
+#ifndef CONFIG_DYNAMIC_FTRACE
 /*
  * void _mcount(unsigned long return_address)
  * @return_address: return address to instrumented function
@@ -132,6 +133,48 @@ skip_ftrace_call:
 #endif /* CONFIG_FUNCTION_GRAPH_TRACER */
 ENDPROC(_mcount)
 
+#else /* CONFIG_DYNAMIC_FTRACE */
+/*
+ * _mcount() is used to build the kernel with -pg option, but all the branch
+ * instructions to _mcount() are replaced to NOP initially at kernel start up,
+ * and later on, NOP to branch to ftrace_caller() when enabled or branch to
+ * NOP when disabled per-function base.
+ */
+ENTRY(_mcount)
+	ret
+ENDPROC(_mcount)
+
+/*
+ * void ftrace_caller(unsigned long return_address)
+ * @return_address: return address to instrumented function
+ *
+ * This function is a counterpart of _mcount() in 'static' ftrace, and
+ * makes calls to:
+ *     - tracer function to probe instrumented function's entry,
+ *     - ftrace_graph_caller to set up an exit hook
+ */
+ENTRY(ftrace_caller)
+	mcount_enter
+
+	mcount_get_pc0	x0		//     function's pc
+	mcount_get_lr	x1		//     function's lr
+
+	.global ftrace_call
+ftrace_call:				// tracer(pc, lr);
+	nop				// This will be replaced with "bl xxx"
+					// where xxx can be any kind of tracer.
+
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+	.global ftrace_graph_call
+ftrace_graph_call:			// ftrace_graph_caller();
+	nop				// If enabled, this will be replaced
+					// "b ftrace_graph_caller"
+#endif
+
+	mcount_exit
+ENDPROC(ftrace_caller)
+#endif /* CONFIG_DYNAMIC_FTRACE */
+
 ENTRY(ftrace_stub)
 	ret
 ENDPROC(ftrace_stub)
diff --git a/arch/arm64/kernel/ftrace.c b/arch/arm64/kernel/ftrace.c
index a559ab8..8c26476 100644
--- a/arch/arm64/kernel/ftrace.c
+++ b/arch/arm64/kernel/ftrace.c
@@ -17,6 +17,89 @@
 #include <asm/ftrace.h>
 #include <asm/insn.h>
 
+#ifdef CONFIG_DYNAMIC_FTRACE
+/*
+ * Replace a single instruction, which may be a branch or NOP.
+ * If @validate == true, a replaced instruction is checked against 'old'.
+ */
+static int ftrace_modify_code(unsigned long pc, unsigned int old,
+			      unsigned int new, bool validate)
+{
+	unsigned int replaced;
+
+	/*
+	 * Note:
+	 * Due to modules and __init, code can disappear and change,
+	 * we need to protect against faulting as well as code changing.
+	 * We do this by aarch64_insn_*() which use the probe_kernel_*().
+	 *
+	 * No lock is held here because all the modifications are run
+	 * through stop_machine().
+	 */
+	if (validate) {
+		if (aarch64_insn_read((void *)pc, &replaced))
+			return -EFAULT;
+
+		if (replaced != old)
+			return -EINVAL;
+	}
+	if (aarch64_insn_patch_text_nosync((void *)pc, new))
+		return -EPERM;
+
+	return 0;
+}
+
+/*
+ * Replace tracer function in ftrace_caller()
+ */
+int ftrace_update_ftrace_func(ftrace_func_t func)
+{
+	unsigned long pc;
+	unsigned int new;
+
+	pc = (unsigned long)&ftrace_call;
+	new = aarch64_insn_gen_branch_imm(pc, (unsigned long)func, true);
+
+	return ftrace_modify_code(pc, 0, new, false);
+}
+
+/*
+ * Turn on the call to ftrace_caller() in instrumented function
+ */
+int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
+{
+	unsigned long pc = rec->ip;
+	unsigned int old, new;
+
+	old = aarch64_insn_gen_nop();
+	new = aarch64_insn_gen_branch_imm(pc, addr, true);
+
+	return ftrace_modify_code(pc, old, new, true);
+}
+
+/*
+ * Turn off the call to ftrace_caller() in instrumented function
+ */
+int ftrace_make_nop(struct module *mod,
+		    struct dyn_ftrace *rec, unsigned long addr)
+{
+	unsigned long pc = rec->ip;
+	unsigned int old, new;
+
+	old = aarch64_insn_gen_branch_imm(pc, addr, true);
+	new = aarch64_insn_gen_nop();
+
+	return ftrace_modify_code(pc, old, new, true);
+}
+
+int __init ftrace_dyn_arch_init(void *data)
+{
+	*(unsigned long *)data = 0;
+
+	return 0;
+}
+#endif /* CONFIG_DYNAMIC_FTRACE */
+
 #ifdef CONFIG_FUNCTION_GRAPH_TRACER
 /*
  * function_graph tracer expects ftrace_return_to_handler() to be called
@@ -61,4 +144,34 @@ void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr,
 		return;
 	}
 }
+
+#ifdef CONFIG_DYNAMIC_FTRACE
+/*
+ * Turn on/off the call to ftrace_graph_caller() in ftrace_caller()
+ * depending on @enable.
+ */
+static int ftrace_modify_graph_caller(bool enable)
+{
+	unsigned long pc = (unsigned long)&ftrace_graph_call;
+	unsigned int branch, nop, old, new;
+
+	branch = aarch64_insn_gen_branch_imm(pc,
+			(unsigned long)ftrace_graph_caller, false);
+	nop = aarch64_insn_gen_nop();
+	old = enable ? nop : branch;
+	new = enable ? branch : nop;
+
+	return ftrace_modify_code(pc, old, new, true);
+}
+
+int ftrace_enable_ftrace_graph_caller(void)
+{
+	return ftrace_modify_graph_caller(true);
+}
+
+int ftrace_disable_ftrace_graph_caller(void)
+{
+	return ftrace_modify_graph_caller(false);
+}
+#endif /* CONFIG_DYNAMIC_FTRACE */
 #endif /* CONFIG_FUNCTION_GRAPH_TRACER */
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 235+ messages in thread

* [PATCH v4 3/7] arm64: ftrace: Add CALLER_ADDRx macros
  2014-02-25  9:23     ` AKASHI Takahiro
@ 2014-02-25  9:23       ` AKASHI Takahiro
  -1 siblings, 0 replies; 235+ messages in thread
From: AKASHI Takahiro @ 2014-02-25  9:23 UTC (permalink / raw)
  To: rostedt, fweisbec, mingo, catalin.marinas, will.deacon, tim.bird
  Cc: gkulkarni, dsaxena, arndb, linux-arm-kernel, linaro-kernel,
	linux-kernel, AKASHI Takahiro

CALLER_ADDRx returns caller's address at specified level in call stacks.
They are used for several tracers like irqsoff and preemptoff.
Strange to say, however, they are refered even without FTRACE.

Please note that this implementation assumes that we have frame pointers.
(which means kernel should be compiled with -fno-omit-frame-pointer.)

Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
---
 arch/arm64/include/asm/ftrace.h    |   14 +++++++++
 arch/arm64/kernel/Makefile         |    3 +-
 arch/arm64/kernel/return_address.c |   55 ++++++++++++++++++++++++++++++++++++
 3 files changed, 71 insertions(+), 1 deletion(-)
 create mode 100644 arch/arm64/kernel/return_address.c

diff --git a/arch/arm64/include/asm/ftrace.h b/arch/arm64/include/asm/ftrace.h
index ed5c448..f93da72 100644
--- a/arch/arm64/include/asm/ftrace.h
+++ b/arch/arm64/include/asm/ftrace.h
@@ -35,4 +35,18 @@ static inline unsigned long ftrace_call_adjust(unsigned long addr)
 }
 #endif /* __ASSEMBLY__ */
 
+#ifndef __ASSEMBLY__
+#define HAVE_ARCH_CALLER_ADDR
+
+extern void *return_address(unsigned int);
+
+#define CALLER_ADDR0 ((unsigned long)__builtin_return_address(0))
+#define CALLER_ADDR1 ((unsigned long)return_address(1))
+#define CALLER_ADDR2 ((unsigned long)return_address(2))
+#define CALLER_ADDR3 ((unsigned long)return_address(3))
+#define CALLER_ADDR4 ((unsigned long)return_address(4))
+#define CALLER_ADDR5 ((unsigned long)return_address(5))
+#define CALLER_ADDR6 ((unsigned long)return_address(6))
+#endif /* ifndef __ASSEMBLY__ */
+
 #endif /* __ASM_FTRACE_H */
diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile
index ac67fd0..b5bfa7f 100644
--- a/arch/arm64/kernel/Makefile
+++ b/arch/arm64/kernel/Makefile
@@ -7,12 +7,13 @@ AFLAGS_head.o		:= -DTEXT_OFFSET=$(TEXT_OFFSET)
 
 CFLAGS_REMOVE_ftrace.o = -pg
 CFLAGS_REMOVE_insn.o = -pg
+CFLAGS_REMOVE_return_address.o = -pg
 
 # Object file lists.
 arm64-obj-y		:= cputable.o debug-monitors.o entry.o irq.o fpsimd.o	\
 			   entry-fpsimd.o process.o ptrace.o setup.o signal.o	\
 			   sys.o stacktrace.o time.o traps.o io.o vdso.o	\
-			   hyp-stub.o psci.o cpu_ops.o insn.o
+			   hyp-stub.o psci.o cpu_ops.o insn.o return_address.o
 
 arm64-obj-$(CONFIG_COMPAT)		+= sys32.o kuser32.o signal32.o 	\
 					   sys_compat.o
diff --git a/arch/arm64/kernel/return_address.c b/arch/arm64/kernel/return_address.c
new file mode 100644
index 0000000..89102a6
--- /dev/null
+++ b/arch/arm64/kernel/return_address.c
@@ -0,0 +1,55 @@
+/*
+ * arch/arm64/kernel/return_address.c
+ *
+ * Copyright (C) 2013 Linaro Limited
+ * Author: AKASHI Takahiro <takahiro.akashi@linaro.org>
+ *
+ * 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 <linux/export.h>
+#include <linux/ftrace.h>
+
+#include <asm/stacktrace.h>
+
+struct return_address_data {
+	unsigned int level;
+	void *addr;
+};
+
+static int save_return_addr(struct stackframe *frame, void *d)
+{
+	struct return_address_data *data = d;
+
+	if (!data->level) {
+		data->addr = (void *)frame->pc;
+		return 1;
+	} else {
+		--data->level;
+		return 0;
+	}
+}
+
+void *return_address(unsigned int level)
+{
+	struct return_address_data data;
+	struct stackframe frame;
+	register unsigned long current_sp asm ("sp");
+
+	data.level = level + 2;
+	data.addr = NULL;
+
+	frame.fp = (unsigned long)__builtin_frame_address(0);
+	frame.sp = current_sp;
+	frame.pc = (unsigned long)return_address; /* dummy */
+
+	walk_stackframe(&frame, save_return_addr, &data);
+
+	if (!data.level)
+		return data.addr;
+	else
+		return NULL;
+}
+EXPORT_SYMBOL_GPL(return_address);
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 235+ messages in thread

* [PATCH v4 3/7] arm64: ftrace: Add CALLER_ADDRx macros
@ 2014-02-25  9:23       ` AKASHI Takahiro
  0 siblings, 0 replies; 235+ messages in thread
From: AKASHI Takahiro @ 2014-02-25  9:23 UTC (permalink / raw)
  To: linux-arm-kernel

CALLER_ADDRx returns caller's address at specified level in call stacks.
They are used for several tracers like irqsoff and preemptoff.
Strange to say, however, they are refered even without FTRACE.

Please note that this implementation assumes that we have frame pointers.
(which means kernel should be compiled with -fno-omit-frame-pointer.)

Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
---
 arch/arm64/include/asm/ftrace.h    |   14 +++++++++
 arch/arm64/kernel/Makefile         |    3 +-
 arch/arm64/kernel/return_address.c |   55 ++++++++++++++++++++++++++++++++++++
 3 files changed, 71 insertions(+), 1 deletion(-)
 create mode 100644 arch/arm64/kernel/return_address.c

diff --git a/arch/arm64/include/asm/ftrace.h b/arch/arm64/include/asm/ftrace.h
index ed5c448..f93da72 100644
--- a/arch/arm64/include/asm/ftrace.h
+++ b/arch/arm64/include/asm/ftrace.h
@@ -35,4 +35,18 @@ static inline unsigned long ftrace_call_adjust(unsigned long addr)
 }
 #endif /* __ASSEMBLY__ */
 
+#ifndef __ASSEMBLY__
+#define HAVE_ARCH_CALLER_ADDR
+
+extern void *return_address(unsigned int);
+
+#define CALLER_ADDR0 ((unsigned long)__builtin_return_address(0))
+#define CALLER_ADDR1 ((unsigned long)return_address(1))
+#define CALLER_ADDR2 ((unsigned long)return_address(2))
+#define CALLER_ADDR3 ((unsigned long)return_address(3))
+#define CALLER_ADDR4 ((unsigned long)return_address(4))
+#define CALLER_ADDR5 ((unsigned long)return_address(5))
+#define CALLER_ADDR6 ((unsigned long)return_address(6))
+#endif /* ifndef __ASSEMBLY__ */
+
 #endif /* __ASM_FTRACE_H */
diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile
index ac67fd0..b5bfa7f 100644
--- a/arch/arm64/kernel/Makefile
+++ b/arch/arm64/kernel/Makefile
@@ -7,12 +7,13 @@ AFLAGS_head.o		:= -DTEXT_OFFSET=$(TEXT_OFFSET)
 
 CFLAGS_REMOVE_ftrace.o = -pg
 CFLAGS_REMOVE_insn.o = -pg
+CFLAGS_REMOVE_return_address.o = -pg
 
 # Object file lists.
 arm64-obj-y		:= cputable.o debug-monitors.o entry.o irq.o fpsimd.o	\
 			   entry-fpsimd.o process.o ptrace.o setup.o signal.o	\
 			   sys.o stacktrace.o time.o traps.o io.o vdso.o	\
-			   hyp-stub.o psci.o cpu_ops.o insn.o
+			   hyp-stub.o psci.o cpu_ops.o insn.o return_address.o
 
 arm64-obj-$(CONFIG_COMPAT)		+= sys32.o kuser32.o signal32.o 	\
 					   sys_compat.o
diff --git a/arch/arm64/kernel/return_address.c b/arch/arm64/kernel/return_address.c
new file mode 100644
index 0000000..89102a6
--- /dev/null
+++ b/arch/arm64/kernel/return_address.c
@@ -0,0 +1,55 @@
+/*
+ * arch/arm64/kernel/return_address.c
+ *
+ * Copyright (C) 2013 Linaro Limited
+ * Author: AKASHI Takahiro <takahiro.akashi@linaro.org>
+ *
+ * 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 <linux/export.h>
+#include <linux/ftrace.h>
+
+#include <asm/stacktrace.h>
+
+struct return_address_data {
+	unsigned int level;
+	void *addr;
+};
+
+static int save_return_addr(struct stackframe *frame, void *d)
+{
+	struct return_address_data *data = d;
+
+	if (!data->level) {
+		data->addr = (void *)frame->pc;
+		return 1;
+	} else {
+		--data->level;
+		return 0;
+	}
+}
+
+void *return_address(unsigned int level)
+{
+	struct return_address_data data;
+	struct stackframe frame;
+	register unsigned long current_sp asm ("sp");
+
+	data.level = level + 2;
+	data.addr = NULL;
+
+	frame.fp = (unsigned long)__builtin_frame_address(0);
+	frame.sp = current_sp;
+	frame.pc = (unsigned long)return_address; /* dummy */
+
+	walk_stackframe(&frame, save_return_addr, &data);
+
+	if (!data.level)
+		return data.addr;
+	else
+		return NULL;
+}
+EXPORT_SYMBOL_GPL(return_address);
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 235+ messages in thread

* [PATCH v4 4/7] ftrace: Add arm64 support to recordmcount
  2014-02-25  9:23     ` AKASHI Takahiro
@ 2014-02-25  9:23       ` AKASHI Takahiro
  -1 siblings, 0 replies; 235+ messages in thread
From: AKASHI Takahiro @ 2014-02-25  9:23 UTC (permalink / raw)
  To: rostedt, fweisbec, mingo, catalin.marinas, will.deacon, tim.bird
  Cc: gkulkarni, dsaxena, arndb, linux-arm-kernel, linaro-kernel,
	linux-kernel, AKASHI Takahiro

Recordmcount utility under scripts is run, after compiling each object,
to find out all the locations of calling _mcount() and put them into
specific seciton named __mcount_loc.
Then linker collects all such information into a table in the kernel image
(between __start_mcount_loc and __stop_mcount_loc) for later use by ftrace.

This patch adds arm64 specific definitions to identify such locations.
There are two types of implementation, C and Perl. On arm64, only C version
is used to build the kernel now that CONFIG_HAVE_C_RECORDMCOUNT is on.
But Perl version is also maintained.

Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
---
 arch/arm64/Kconfig      |    2 ++
 scripts/recordmcount.c  |    4 ++++
 scripts/recordmcount.pl |    5 +++++
 3 files changed, 11 insertions(+)

diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index b176bc0..6954959 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -27,6 +27,7 @@ config ARM64
 	select HARDIRQS_SW_RESEND
 	select HAVE_ARCH_JUMP_LABEL
 	select HAVE_ARCH_TRACEHOOK
+	select HAVE_C_RECORDMCOUNT
 	select HAVE_DEBUG_BUGVERBOSE
 	select HAVE_DEBUG_KMEMLEAK
 	select HAVE_DMA_API_DEBUG
@@ -34,6 +35,7 @@ config ARM64
 	select HAVE_DMA_CONTIGUOUS
 	select HAVE_DYNAMIC_FTRACE
 	select HAVE_EFFICIENT_UNALIGNED_ACCESS
+	select HAVE_FTRACE_MCOUNT_RECORD
 	select HAVE_FUNCTION_TRACER
 	select HAVE_FUNCTION_GRAPH_TRACER
 	select HAVE_GENERIC_DMA_COHERENT
diff --git a/scripts/recordmcount.c b/scripts/recordmcount.c
index 9c22317..b92d9f7 100644
--- a/scripts/recordmcount.c
+++ b/scripts/recordmcount.c
@@ -347,6 +347,10 @@ do_file(char const *const fname)
 	case EM_ARM:	 reltype = R_ARM_ABS32;
 			 altmcount = "__gnu_mcount_nc";
 			 break;
+	case EM_AARCH64:
+			 reltype = R_AARCH64_ABS64;
+			 altmcount = "_mcount";
+			 break;
 	case EM_IA_64:	 reltype = R_IA64_IMM64;   gpfx = '_'; break;
 	case EM_METAG:	 reltype = R_METAG_ADDR32;
 			 altmcount = "_mcount_wrapper";
diff --git a/scripts/recordmcount.pl b/scripts/recordmcount.pl
index 91280b8..397b6b8 100755
--- a/scripts/recordmcount.pl
+++ b/scripts/recordmcount.pl
@@ -279,6 +279,11 @@ if ($arch eq "x86_64") {
     $mcount_regex = "^\\s*([0-9a-fA-F]+):\\s*R_ARM_(CALL|PC24|THM_CALL)" .
 			"\\s+(__gnu_mcount_nc|mcount)\$";
 
+} elsif ($arch eq "arm64") {
+    $alignment = 3;
+    $section_type = '%progbits';
+    $mcount_regex = "^\\s*([0-9a-fA-F]+):\\s*R_AARCH64_CALL26\\s+_mcount\$";
+    $type = ".quad";
 } elsif ($arch eq "ia64") {
     $mcount_regex = "^\\s*([0-9a-fA-F]+):.*\\s_mcount\$";
     $type = "data8";
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 235+ messages in thread

* [PATCH v4 4/7] ftrace: Add arm64 support to recordmcount
@ 2014-02-25  9:23       ` AKASHI Takahiro
  0 siblings, 0 replies; 235+ messages in thread
From: AKASHI Takahiro @ 2014-02-25  9:23 UTC (permalink / raw)
  To: linux-arm-kernel

Recordmcount utility under scripts is run, after compiling each object,
to find out all the locations of calling _mcount() and put them into
specific seciton named __mcount_loc.
Then linker collects all such information into a table in the kernel image
(between __start_mcount_loc and __stop_mcount_loc) for later use by ftrace.

This patch adds arm64 specific definitions to identify such locations.
There are two types of implementation, C and Perl. On arm64, only C version
is used to build the kernel now that CONFIG_HAVE_C_RECORDMCOUNT is on.
But Perl version is also maintained.

Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
---
 arch/arm64/Kconfig      |    2 ++
 scripts/recordmcount.c  |    4 ++++
 scripts/recordmcount.pl |    5 +++++
 3 files changed, 11 insertions(+)

diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index b176bc0..6954959 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -27,6 +27,7 @@ config ARM64
 	select HARDIRQS_SW_RESEND
 	select HAVE_ARCH_JUMP_LABEL
 	select HAVE_ARCH_TRACEHOOK
+	select HAVE_C_RECORDMCOUNT
 	select HAVE_DEBUG_BUGVERBOSE
 	select HAVE_DEBUG_KMEMLEAK
 	select HAVE_DMA_API_DEBUG
@@ -34,6 +35,7 @@ config ARM64
 	select HAVE_DMA_CONTIGUOUS
 	select HAVE_DYNAMIC_FTRACE
 	select HAVE_EFFICIENT_UNALIGNED_ACCESS
+	select HAVE_FTRACE_MCOUNT_RECORD
 	select HAVE_FUNCTION_TRACER
 	select HAVE_FUNCTION_GRAPH_TRACER
 	select HAVE_GENERIC_DMA_COHERENT
diff --git a/scripts/recordmcount.c b/scripts/recordmcount.c
index 9c22317..b92d9f7 100644
--- a/scripts/recordmcount.c
+++ b/scripts/recordmcount.c
@@ -347,6 +347,10 @@ do_file(char const *const fname)
 	case EM_ARM:	 reltype = R_ARM_ABS32;
 			 altmcount = "__gnu_mcount_nc";
 			 break;
+	case EM_AARCH64:
+			 reltype = R_AARCH64_ABS64;
+			 altmcount = "_mcount";
+			 break;
 	case EM_IA_64:	 reltype = R_IA64_IMM64;   gpfx = '_'; break;
 	case EM_METAG:	 reltype = R_METAG_ADDR32;
 			 altmcount = "_mcount_wrapper";
diff --git a/scripts/recordmcount.pl b/scripts/recordmcount.pl
index 91280b8..397b6b8 100755
--- a/scripts/recordmcount.pl
+++ b/scripts/recordmcount.pl
@@ -279,6 +279,11 @@ if ($arch eq "x86_64") {
     $mcount_regex = "^\\s*([0-9a-fA-F]+):\\s*R_ARM_(CALL|PC24|THM_CALL)" .
 			"\\s+(__gnu_mcount_nc|mcount)\$";
 
+} elsif ($arch eq "arm64") {
+    $alignment = 3;
+    $section_type = '%progbits';
+    $mcount_regex = "^\\s*([0-9a-fA-F]+):\\s*R_AARCH64_CALL26\\s+_mcount\$";
+    $type = ".quad";
 } elsif ($arch eq "ia64") {
     $mcount_regex = "^\\s*([0-9a-fA-F]+):.*\\s_mcount\$";
     $type = "data8";
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 235+ messages in thread

* [PATCH v4 5/7] arm64: ftrace: Add system call tracepoint
  2014-02-25  9:23     ` AKASHI Takahiro
@ 2014-02-25  9:23       ` AKASHI Takahiro
  -1 siblings, 0 replies; 235+ messages in thread
From: AKASHI Takahiro @ 2014-02-25  9:23 UTC (permalink / raw)
  To: rostedt, fweisbec, mingo, catalin.marinas, will.deacon, tim.bird
  Cc: gkulkarni, dsaxena, arndb, linux-arm-kernel, linaro-kernel,
	linux-kernel, AKASHI Takahiro

This patch allows system call entry or exit to be traced as ftrace events,
ie. sys_enter_*/sys_exit_*, if CONFIG_FTRACE_SYSCALLS is enabled.
Those events appear and can be controlled under
    ${sysfs}/tracing/events/syscalls/

Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
---
 arch/arm64/Kconfig               |    1 +
 arch/arm64/include/asm/syscall.h |    1 +
 arch/arm64/include/asm/unistd.h  |    2 ++
 arch/arm64/kernel/ptrace.c       |    9 +++++++++
 4 files changed, 13 insertions(+)

diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 6954959..b1dcdb4 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -43,6 +43,7 @@ config ARM64
 	select HAVE_MEMBLOCK
 	select HAVE_PATA_PLATFORM
 	select HAVE_PERF_EVENTS
+	select HAVE_SYSCALL_TRACEPOINTS
 	select IRQ_DOMAIN
 	select MODULES_USE_ELF_RELA
 	select NO_BOOTMEM
diff --git a/arch/arm64/include/asm/syscall.h b/arch/arm64/include/asm/syscall.h
index 70ba9d4..383771e 100644
--- a/arch/arm64/include/asm/syscall.h
+++ b/arch/arm64/include/asm/syscall.h
@@ -18,6 +18,7 @@
 
 #include <linux/err.h>
 
+extern const void *sys_call_table[];
 
 static inline int syscall_get_nr(struct task_struct *task,
 				 struct pt_regs *regs)
diff --git a/arch/arm64/include/asm/unistd.h b/arch/arm64/include/asm/unistd.h
index 82ce217..c335479 100644
--- a/arch/arm64/include/asm/unistd.h
+++ b/arch/arm64/include/asm/unistd.h
@@ -28,3 +28,5 @@
 #endif
 #define __ARCH_WANT_SYS_CLONE
 #include <uapi/asm/unistd.h>
+
+#define NR_syscalls (__NR_syscalls)
diff --git a/arch/arm64/kernel/ptrace.c b/arch/arm64/kernel/ptrace.c
index c70133e..dc90f9f 100644
--- a/arch/arm64/kernel/ptrace.c
+++ b/arch/arm64/kernel/ptrace.c
@@ -41,6 +41,9 @@
 #include <asm/traps.h>
 #include <asm/system_misc.h>
 
+#define CREATE_TRACE_POINTS
+#include <trace/events/syscalls.h>
+
 /*
  * TODO: does not yet catch signals sent when the child dies.
  * in exit.c or in signal.c.
@@ -1062,6 +1065,9 @@ asmlinkage int syscall_trace(int dir, struct pt_regs *regs)
 {
 	unsigned long saved_reg;
 
+	if (dir && unlikely(test_thread_flag(TIF_SYSCALL_TRACEPOINT)))
+		trace_sys_exit(regs, regs_return_value(regs));
+
 	if (test_thread_flag(TIF_SYSCALL_TRACE)) {
 		if (is_compat_task()) {
 			/* AArch32 uses ip (r12) for scratch */
@@ -1087,5 +1093,8 @@ asmlinkage int syscall_trace(int dir, struct pt_regs *regs)
 			regs->regs[7] = saved_reg;
 	}
 
+	if (!dir && unlikely(test_thread_flag(TIF_SYSCALL_TRACEPOINT)))
+		trace_sys_enter(regs, regs->syscallno);
+
 	return regs->syscallno;
 }
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 235+ messages in thread

* [PATCH v4 5/7] arm64: ftrace: Add system call tracepoint
@ 2014-02-25  9:23       ` AKASHI Takahiro
  0 siblings, 0 replies; 235+ messages in thread
From: AKASHI Takahiro @ 2014-02-25  9:23 UTC (permalink / raw)
  To: linux-arm-kernel

This patch allows system call entry or exit to be traced as ftrace events,
ie. sys_enter_*/sys_exit_*, if CONFIG_FTRACE_SYSCALLS is enabled.
Those events appear and can be controlled under
    ${sysfs}/tracing/events/syscalls/

Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
---
 arch/arm64/Kconfig               |    1 +
 arch/arm64/include/asm/syscall.h |    1 +
 arch/arm64/include/asm/unistd.h  |    2 ++
 arch/arm64/kernel/ptrace.c       |    9 +++++++++
 4 files changed, 13 insertions(+)

diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 6954959..b1dcdb4 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -43,6 +43,7 @@ config ARM64
 	select HAVE_MEMBLOCK
 	select HAVE_PATA_PLATFORM
 	select HAVE_PERF_EVENTS
+	select HAVE_SYSCALL_TRACEPOINTS
 	select IRQ_DOMAIN
 	select MODULES_USE_ELF_RELA
 	select NO_BOOTMEM
diff --git a/arch/arm64/include/asm/syscall.h b/arch/arm64/include/asm/syscall.h
index 70ba9d4..383771e 100644
--- a/arch/arm64/include/asm/syscall.h
+++ b/arch/arm64/include/asm/syscall.h
@@ -18,6 +18,7 @@
 
 #include <linux/err.h>
 
+extern const void *sys_call_table[];
 
 static inline int syscall_get_nr(struct task_struct *task,
 				 struct pt_regs *regs)
diff --git a/arch/arm64/include/asm/unistd.h b/arch/arm64/include/asm/unistd.h
index 82ce217..c335479 100644
--- a/arch/arm64/include/asm/unistd.h
+++ b/arch/arm64/include/asm/unistd.h
@@ -28,3 +28,5 @@
 #endif
 #define __ARCH_WANT_SYS_CLONE
 #include <uapi/asm/unistd.h>
+
+#define NR_syscalls (__NR_syscalls)
diff --git a/arch/arm64/kernel/ptrace.c b/arch/arm64/kernel/ptrace.c
index c70133e..dc90f9f 100644
--- a/arch/arm64/kernel/ptrace.c
+++ b/arch/arm64/kernel/ptrace.c
@@ -41,6 +41,9 @@
 #include <asm/traps.h>
 #include <asm/system_misc.h>
 
+#define CREATE_TRACE_POINTS
+#include <trace/events/syscalls.h>
+
 /*
  * TODO: does not yet catch signals sent when the child dies.
  * in exit.c or in signal.c.
@@ -1062,6 +1065,9 @@ asmlinkage int syscall_trace(int dir, struct pt_regs *regs)
 {
 	unsigned long saved_reg;
 
+	if (dir && unlikely(test_thread_flag(TIF_SYSCALL_TRACEPOINT)))
+		trace_sys_exit(regs, regs_return_value(regs));
+
 	if (test_thread_flag(TIF_SYSCALL_TRACE)) {
 		if (is_compat_task()) {
 			/* AArch32 uses ip (r12) for scratch */
@@ -1087,5 +1093,8 @@ asmlinkage int syscall_trace(int dir, struct pt_regs *regs)
 			regs->regs[7] = saved_reg;
 	}
 
+	if (!dir && unlikely(test_thread_flag(TIF_SYSCALL_TRACEPOINT)))
+		trace_sys_enter(regs, regs->syscallno);
+
 	return regs->syscallno;
 }
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 235+ messages in thread

* [PATCH v4 6/7] arm64: Add 'notrace' attribute to unwind_frame() for ftrace
  2014-02-25  9:23     ` AKASHI Takahiro
@ 2014-02-25  9:23       ` AKASHI Takahiro
  -1 siblings, 0 replies; 235+ messages in thread
From: AKASHI Takahiro @ 2014-02-25  9:23 UTC (permalink / raw)
  To: rostedt, fweisbec, mingo, catalin.marinas, will.deacon, tim.bird
  Cc: gkulkarni, dsaxena, arndb, linux-arm-kernel, linaro-kernel,
	linux-kernel, AKASHI Takahiro

walk_stackframe() calls unwind_frame(), and if walk_stackframe() is
"notrace", unwind_frame() should be also "notrace".

Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
---
 arch/arm64/kernel/stacktrace.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm64/kernel/stacktrace.c b/arch/arm64/kernel/stacktrace.c
index c3b6c63..54122c4 100644
--- a/arch/arm64/kernel/stacktrace.c
+++ b/arch/arm64/kernel/stacktrace.c
@@ -35,7 +35,7 @@
  *	ldp	x29, x30, [sp]
  *	add	sp, sp, #0x10
  */
-int unwind_frame(struct stackframe *frame)
+int notrace unwind_frame(struct stackframe *frame)
 {
 	unsigned long high, low;
 	unsigned long fp = frame->fp;
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 235+ messages in thread

* [PATCH v4 6/7] arm64: Add 'notrace' attribute to unwind_frame() for ftrace
@ 2014-02-25  9:23       ` AKASHI Takahiro
  0 siblings, 0 replies; 235+ messages in thread
From: AKASHI Takahiro @ 2014-02-25  9:23 UTC (permalink / raw)
  To: linux-arm-kernel

walk_stackframe() calls unwind_frame(), and if walk_stackframe() is
"notrace", unwind_frame() should be also "notrace".

Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
---
 arch/arm64/kernel/stacktrace.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm64/kernel/stacktrace.c b/arch/arm64/kernel/stacktrace.c
index c3b6c63..54122c4 100644
--- a/arch/arm64/kernel/stacktrace.c
+++ b/arch/arm64/kernel/stacktrace.c
@@ -35,7 +35,7 @@
  *	ldp	x29, x30, [sp]
  *	add	sp, sp, #0x10
  */
-int unwind_frame(struct stackframe *frame)
+int notrace unwind_frame(struct stackframe *frame)
 {
 	unsigned long high, low;
 	unsigned long fp = frame->fp;
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 235+ messages in thread

* [PATCH v4 7/7] arm64: add __ASSEMBLY__ in asm/insn.h
  2014-02-25  9:23     ` AKASHI Takahiro
@ 2014-02-25  9:23       ` AKASHI Takahiro
  -1 siblings, 0 replies; 235+ messages in thread
From: AKASHI Takahiro @ 2014-02-25  9:23 UTC (permalink / raw)
  To: rostedt, fweisbec, mingo, catalin.marinas, will.deacon, tim.bird
  Cc: gkulkarni, dsaxena, arndb, linux-arm-kernel, linaro-kernel,
	linux-kernel, AKASHI Takahiro

Since insn.h is indirectly included in asm/entry-ftrace.S,
we need to exclude some declarations by __ASSEMBLY__.

Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
---
 arch/arm64/include/asm/insn.h |    2 ++
 1 file changed, 2 insertions(+)

diff --git a/arch/arm64/include/asm/insn.h b/arch/arm64/include/asm/insn.h
index c44ad39..dc1f73b 100644
--- a/arch/arm64/include/asm/insn.h
+++ b/arch/arm64/include/asm/insn.h
@@ -21,6 +21,7 @@
 /* A64 instructions are always 32 bits. */
 #define	AARCH64_INSN_SIZE		4
 
+#ifndef __ASSEMBLY__
 /*
  * ARM Architecture Reference Manual for ARMv8 Profile-A, Issue A.a
  * Section C3.1 "A64 instruction index by encoding":
@@ -104,5 +105,6 @@ bool aarch64_insn_hotpatch_safe(u32 old_insn, u32 new_insn);
 int aarch64_insn_patch_text_nosync(void *addr, u32 insn);
 int aarch64_insn_patch_text_sync(void *addrs[], u32 insns[], int cnt);
 int aarch64_insn_patch_text(void *addrs[], u32 insns[], int cnt);
+#endif /* __ASSEMBLY__ */
 
 #endif	/* __ASM_INSN_H */
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 235+ messages in thread

* [PATCH v4 7/7] arm64: add __ASSEMBLY__ in asm/insn.h
@ 2014-02-25  9:23       ` AKASHI Takahiro
  0 siblings, 0 replies; 235+ messages in thread
From: AKASHI Takahiro @ 2014-02-25  9:23 UTC (permalink / raw)
  To: linux-arm-kernel

Since insn.h is indirectly included in asm/entry-ftrace.S,
we need to exclude some declarations by __ASSEMBLY__.

Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
---
 arch/arm64/include/asm/insn.h |    2 ++
 1 file changed, 2 insertions(+)

diff --git a/arch/arm64/include/asm/insn.h b/arch/arm64/include/asm/insn.h
index c44ad39..dc1f73b 100644
--- a/arch/arm64/include/asm/insn.h
+++ b/arch/arm64/include/asm/insn.h
@@ -21,6 +21,7 @@
 /* A64 instructions are always 32 bits. */
 #define	AARCH64_INSN_SIZE		4
 
+#ifndef __ASSEMBLY__
 /*
  * ARM Architecture Reference Manual for ARMv8 Profile-A, Issue A.a
  * Section C3.1 "A64 instruction index by encoding":
@@ -104,5 +105,6 @@ bool aarch64_insn_hotpatch_safe(u32 old_insn, u32 new_insn);
 int aarch64_insn_patch_text_nosync(void *addr, u32 insn);
 int aarch64_insn_patch_text_sync(void *addrs[], u32 insns[], int cnt);
 int aarch64_insn_patch_text(void *addrs[], u32 insns[], int cnt);
+#endif /* __ASSEMBLY__ */
 
 #endif	/* __ASM_INSN_H */
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 235+ messages in thread

* RE: [PATCH v4 1/7] arm64: Add ftrace support
  2014-02-25  9:23       ` AKASHI Takahiro
@ 2014-02-25 15:38         ` Kulkarni, Ganapatrao
  -1 siblings, 0 replies; 235+ messages in thread
From: Kulkarni, Ganapatrao @ 2014-02-25 15:38 UTC (permalink / raw)
  To: AKASHI Takahiro, rostedt, fweisbec, mingo, catalin.marinas,
	will.deacon, tim.bird
  Cc: dsaxena, arndb, linux-arm-kernel, linaro-kernel, linux-kernel


________________________________________
From: AKASHI Takahiro <takahiro.akashi@linaro.org>
Sent: Tuesday, February 25, 2014 2:53 PM
To: rostedt@goodmis.org; fweisbec@gmail.com; mingo@redhat.com; catalin.marinas@arm.com; will.deacon@arm.com; tim.bird@sonymobile.com
Cc: Kulkarni, Ganapatrao; dsaxena@linaro.org; arndb@arndb.de; linux-arm-kernel@lists.infradead.org; linaro-kernel@lists.linaro.org; linux-kernel@vger.kernel.org; AKASHI Takahiro
Subject: [PATCH v4 1/7] arm64: Add ftrace support

This patch implements arm64 specific part to support function tracers,
such as function (CONFIG_FUNCTION_TRACER), function_graph
(CONFIG_FUNCTION_GRAPH_TRACER) and function profiler
(CONFIG_FUNCTION_PROFILER).

With 'function' tracer, all the functions in the kernel are traced with
timestamps in ${sysfs}/tracing/trace. If function_graph tracer is
specified, call graph is generated.

The kernel must be compiled with -pg option so that _mcount() is inserted
at the beginning of functions. This function is called on every function's
entry as long as tracing is enabled.
In addition, function_graph tracer also needs to be able to probe function's
exit. ftrace_graph_caller() & return_to_handler do this by faking link
register's value to intercept function's return path.

More details on architecture specific requirements are described in
Documentation/trace/ftrace-design.txt.

Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
---
 arch/arm64/Kconfig               |    2 +
 arch/arm64/include/asm/ftrace.h  |   23 +++++
 arch/arm64/kernel/Makefile       |    4 +
 arch/arm64/kernel/arm64ksyms.c   |    4 +
 arch/arm64/kernel/entry-ftrace.S |  173 ++++++++++++++++++++++++++++++++++++++
 arch/arm64/kernel/ftrace.c       |   64 ++++++++++++++
 6 files changed, 270 insertions(+)
 create mode 100644 arch/arm64/include/asm/ftrace.h
 create mode 100644 arch/arm64/kernel/entry-ftrace.S
 create mode 100644 arch/arm64/kernel/ftrace.c

diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 27bbcfc..5783641 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -33,6 +33,8 @@ config ARM64
        select HAVE_DMA_ATTRS
        select HAVE_DMA_CONTIGUOUS
        select HAVE_EFFICIENT_UNALIGNED_ACCESS
+       select HAVE_FUNCTION_TRACER
+       select HAVE_FUNCTION_GRAPH_TRACER
        select HAVE_GENERIC_DMA_COHERENT
        select HAVE_HW_BREAKPOINT if PERF_EVENTS
        select HAVE_MEMBLOCK
diff --git a/arch/arm64/include/asm/ftrace.h b/arch/arm64/include/asm/ftrace.h
new file mode 100644
index 0000000..58ea595
--- /dev/null
+++ b/arch/arm64/include/asm/ftrace.h
@@ -0,0 +1,23 @@
+/*
+ * arch/arm64/include/asm/ftrace.h
+ *
+ * Copyright (C) 2013 Linaro Limited
+ * Author: AKASHI Takahiro <takahiro.akashi@linaro.org>
+ *
+ * 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.
+ */
+#ifndef __ASM_FTRACE_H
+#define __ASM_FTRACE_H
+
+#include <asm/insn.h>
+
+#define MCOUNT_ADDR            ((unsigned long)_mcount)
+#define MCOUNT_INSN_SIZE       AARCH64_INSN_SIZE
+
+#ifndef __ASSEMBLY__
+extern void _mcount(unsigned long);
+#endif /* __ASSEMBLY__ */
+
+#endif /* __ASM_FTRACE_H */
diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile
index 2d4554b..ac67fd0 100644
--- a/arch/arm64/kernel/Makefile
+++ b/arch/arm64/kernel/Makefile
@@ -5,6 +5,9 @@
 CPPFLAGS_vmlinux.lds   := -DTEXT_OFFSET=$(TEXT_OFFSET)
 AFLAGS_head.o          := -DTEXT_OFFSET=$(TEXT_OFFSET)

+CFLAGS_REMOVE_ftrace.o = -pg
+CFLAGS_REMOVE_insn.o = -pg
+
 # Object file lists.
 arm64-obj-y            := cputable.o debug-monitors.o entry.o irq.o fpsimd.o   \
                           entry-fpsimd.o process.o ptrace.o setup.o signal.o   \
@@ -13,6 +16,7 @@ arm64-obj-y           := cputable.o debug-monitors.o entry.o irq.o fpsimd.o   \

 arm64-obj-$(CONFIG_COMPAT)             += sys32.o kuser32.o signal32.o         \
                                           sys_compat.o
+arm64-obj-$(CONFIG_FUNCTION_TRACER)    += ftrace.o entry-ftrace.o
 arm64-obj-$(CONFIG_MODULES)            += arm64ksyms.o module.o
 arm64-obj-$(CONFIG_SMP)                        += smp.o smp_spin_table.o
 arm64-obj-$(CONFIG_HW_PERF_EVENTS)     += perf_event.o
diff --git a/arch/arm64/kernel/arm64ksyms.c b/arch/arm64/kernel/arm64ksyms.c
index 338b568..7f0512f 100644
--- a/arch/arm64/kernel/arm64ksyms.c
+++ b/arch/arm64/kernel/arm64ksyms.c
@@ -56,3 +56,7 @@ EXPORT_SYMBOL(clear_bit);
 EXPORT_SYMBOL(test_and_clear_bit);
 EXPORT_SYMBOL(change_bit);
 EXPORT_SYMBOL(test_and_change_bit);
+
+#ifdef CONFIG_FUNCTION_TRACER
+EXPORT_SYMBOL(_mcount);
+#endif
diff --git a/arch/arm64/kernel/entry-ftrace.S b/arch/arm64/kernel/entry-ftrace.S
new file mode 100644
index 0000000..2e8162e
--- /dev/null
+++ b/arch/arm64/kernel/entry-ftrace.S
@@ -0,0 +1,173 @@
+/*
+ * arch/arm64/kernel/entry-ftrace.S
+ *
+ * Copyright (C) 2013 Linaro Limited
+ * Author: AKASHI Takahiro <takahiro.akashi@linaro.org>
+ *
+ * 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 <linux/linkage.h>
+#include <asm/ftrace.h>
+#include <asm/insn.h>
+
+/*
+ * Gcc with -pg will put the following code in the beginning of each function:
+ *      mov x0, x30
+ *      bl _mcount
+ *     [function's body ...]
+ * "bl _mcount" may be replaced to "bl ftrace_caller" or NOP if dynamic
+ * ftrace is enabled.
+ *
+ * Please note that x0 as an argument will not be used here because we can
+ * get lr(x30) of instrumented function at any time by winding up call stack
+ * as long as the kernel is compiled without -fomit-frame-pointer.
+ * (or CONFIG_FRAME_POINTER, this is forced on arm64)
+ *
+ * stack layout after mcount_enter:
+ *
+ *   0 ---------------------------------------- sp of _mcount()
+ *      x29: fp of instrumented function       fp is not winded
+ *     --------------------
+ *      x30: lr of _mcount() (= instrumented function's pc)
+ * +16 ---------------------------------------- sp of instrumented function
+ *
+ *     ....
+ *
+ * +xx ---------------------------------------- fp of instrumented function
+ *      x29: fp of parent
+ *     --------------------
+ *      x30: lr of instrumented function (= parent's pc)
+ *     --------------------
+ *      xxx
+ */
+
can stack layout be more readable as below?

Stack layout of _mcount after mcount_enter

       |------------------| sp + 16   <= frame pointer of _mcount.
       |                       |
       |       x30          | <=  lr of _mcount (instrumented func's pc)
       |                       |
       |------------------| sp + 8
       |                       |
       |       x29          | <= value of x29 is sp of instrumented function.
       |                       |
       |------------------| sp   <= stack pointer of _mcount

   
Stack layout of instrumented function.
                .
                .
                .
                .
       |------------------| sp + 16
       |                      |
       |       x30         | <=  lr of instrumented function (= parent's pc)
       |                      |
       |------------------| sp + 8
       |                      |
       |       x29         | <= sp of parent.
       |                      |
       |------------------| sp  <= this address is stored at sp of _mcount

 
+       .macro mcount_enter
+       stp     x29, x30, [sp, #-16]!
+       .endm
+
+       .macro mcount_exit
+       ldp     x29, x30, [sp], #16
+       ret
+       .endm
+
+       .macro mcount_adjust_addr rd, rn
+       sub     \rd, \rn, #AARCH64_INSN_SIZE
+       .endm
+
+       /* for instrumented function's parent */
+       .macro mcount_get_parent_fp reg
+       ldr     \reg, [sp]
+       ldr     \reg, [\reg]
+       .endm
+
+       /* for instrumented function */
+       .macro mcount_get_pc0 reg
+       mcount_adjust_addr      \reg, x30
+       .endm
+
+       .macro mcount_get_pc reg
+       ldr     \reg, [sp, #8]
+       mcount_adjust_addr      \reg, \reg
+       .endm
+
+       .macro mcount_get_lr reg
+       ldr     \reg, [sp]
+       ldr     \reg, [\reg, #8]
+       mcount_adjust_addr      \reg, \reg
+       .endm
+
+       .macro mcount_get_saved_lr_addr reg
+       ldr     \reg, [sp]
+       add     \reg, \reg, #8
+       .endm
+
+/*
+ * void _mcount(unsigned long return_address)
+ * @return_address: return address to instrumented function
+ *
+ * This function makes calls, if enabled, to:
+ *     - tracer function to probe instrumented function's entry,
+ *     - ftrace_graph_caller to set up an exit hook
+ */
+ENTRY(_mcount)
+#ifdef CONFIG_HAVE_FUNCTION_TRACE_MCOUNT_TEST
+       ldr     x0, =ftrace_trace_stop
+       ldr     x0, [x0]                // if ftrace_trace_stop
+       ret                             //   return;
+#endif
+       mcount_enter
+
+       ldr     x0, =ftrace_trace_function
+       ldr     x2, [x0]
+       adr     x0, ftrace_stub
+       cmp     x0, x2                  // if (ftrace_trace_function
+       b.eq    skip_ftrace_call        //     != ftrace_stub) {
+
+       mcount_get_pc   x0              //       function's pc
+       mcount_get_lr   x1              //       function's lr (= parent's pc)
+       blr     x2                      //   (*ftrace_trace_function)(pc, lr);
+
+#ifndef CONFIG_FUNCTION_GRAPH_TRACER
+skip_ftrace_call:                      //   return;
+       mcount_exit                     // }
+#else
+       mcount_exit                     //   return;
+                                       // }
+skip_ftrace_call:
+       ldr     x1, =ftrace_graph_return
+       ldr     x2, [x1]                //   if ((ftrace_graph_return
+       cmp     x0, x2                  //        != ftrace_stub)
+       b.ne    ftrace_graph_caller
+
+       ldr     x1, =ftrace_graph_entry //     || (ftrace_graph_entry
+       ldr     x2, [x1]                //        != ftrace_graph_entry_stub))
+       ldr     x0, =ftrace_graph_entry_stub
+       cmp     x0, x2
+       b.ne    ftrace_graph_caller     //     ftrace_graph_caller();
+
+       mcount_exit
+#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
+ENDPROC(_mcount)
+
+ENTRY(ftrace_stub)
+       ret
+ENDPROC(ftrace_stub)
+
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+/*
+ * void ftrace_graph_caller(void)
+ *
+ * Called from _mcount() or ftrace_caller() when function_graph tracer is
+ * selected.
+ * This function w/ prepare_ftrace_return() fakes link register's value on
+ * the call stack in order to intercept instrumented function's return path
+ * and run return_to_handler() later on its exit.
+ */
+ENTRY(ftrace_graph_caller)
+       mcount_get_saved_lr_addr  x0    //     pointer to function's saved lr
+       mcount_get_pc             x1    //     function's pc
+       mcount_get_parent_fp      x2    //     parent's fp
+       bl      prepare_ftrace_return   // prepare_ftrace_return(&lr, pc, fp)
+
+       mcount_exit
+ENDPROC(ftrace_graph_caller)
+
+/*
+ * void return_to_handler(void)
+ *
+ * Run ftrace_return_to_handler() before going back to parent.
+ * @fp is checked against the value passed by ftrace_graph_caller()
+ * only when CONFIG_FUNCTION_GRAPH_FP_TEST is enabled.
+ */
+       .global return_to_handler
+return_to_handler:
+       str     x0, [sp, #-16]!
+       mov     x0, x29                 //     parent's fp
+       bl      ftrace_return_to_handler// addr = ftrace_return_to_hander(fp);
+       mov     x30, x0                 // restore the original return address
+       ldr     x0, [sp], #16
+       ret
+#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
diff --git a/arch/arm64/kernel/ftrace.c b/arch/arm64/kernel/ftrace.c
new file mode 100644
index 0000000..a559ab8
--- /dev/null
+++ b/arch/arm64/kernel/ftrace.c
@@ -0,0 +1,64 @@
+/*
+ * arch/arm64/kernel/ftrace.c
+ *
+ * Copyright (C) 2013 Linaro Limited
+ * Author: AKASHI Takahiro <takahiro.akashi@linaro.org>
+ *
+ * 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 <linux/ftrace.h>
+#include <linux/swab.h>
+#include <linux/uaccess.h>
+
+#include <asm/cacheflush.h>
+#include <asm/ftrace.h>
+#include <asm/insn.h>
+
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+/*
+ * function_graph tracer expects ftrace_return_to_handler() to be called
+ * on the way back to parent. For this purpose, this function is called
+ * in _mcount() or ftrace_caller() to replace return address (*parent) on
+ * the call stack to return_to_handler.
+ *
+ * Note that @frame_pointer is used only for sanity check later.
+ */
+void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr,
+                          unsigned long frame_pointer)
+{
+       unsigned long return_hooker = (unsigned long)&return_to_handler;
+       unsigned long old;
+       struct ftrace_graph_ent trace;
+       int err;
+
+       if (unlikely(atomic_read(&current->tracing_graph_pause)))
+               return;
+
+       /*
+        * Note:
+        * No protection against faulting at *parent, which may be seen
+        * on other archs. It's unlikely on AArch64.
+        */
+       old = *parent;
+       *parent = return_hooker;
+
+       trace.func = self_addr;
+       trace.depth = current->curr_ret_stack + 1;
+
+       /* Only trace if the calling function expects to */
+       if (!ftrace_graph_entry(&trace)) {
+               *parent = old;
+               return;
+       }
+
+       err = ftrace_push_return_trace(old, self_addr, &trace.depth,
+                                      frame_pointer);
+       if (err == -EBUSY) {
+               *parent = old;
+               return;
+       }
+}
+#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
--
1.7.9.5


^ permalink raw reply related	[flat|nested] 235+ messages in thread

* [PATCH v4 1/7] arm64: Add ftrace support
@ 2014-02-25 15:38         ` Kulkarni, Ganapatrao
  0 siblings, 0 replies; 235+ messages in thread
From: Kulkarni, Ganapatrao @ 2014-02-25 15:38 UTC (permalink / raw)
  To: linux-arm-kernel


________________________________________
From: AKASHI Takahiro <takahiro.akashi@linaro.org>
Sent: Tuesday, February 25, 2014 2:53 PM
To: rostedt at goodmis.org; fweisbec at gmail.com; mingo at redhat.com; catalin.marinas at arm.com; will.deacon at arm.com; tim.bird at sonymobile.com
Cc: Kulkarni, Ganapatrao; dsaxena at linaro.org; arndb at arndb.de; linux-arm-kernel at lists.infradead.org; linaro-kernel at lists.linaro.org; linux-kernel at vger.kernel.org; AKASHI Takahiro
Subject: [PATCH v4 1/7] arm64: Add ftrace support

This patch implements arm64 specific part to support function tracers,
such as function (CONFIG_FUNCTION_TRACER), function_graph
(CONFIG_FUNCTION_GRAPH_TRACER) and function profiler
(CONFIG_FUNCTION_PROFILER).

With 'function' tracer, all the functions in the kernel are traced with
timestamps in ${sysfs}/tracing/trace. If function_graph tracer is
specified, call graph is generated.

The kernel must be compiled with -pg option so that _mcount() is inserted
at the beginning of functions. This function is called on every function's
entry as long as tracing is enabled.
In addition, function_graph tracer also needs to be able to probe function's
exit. ftrace_graph_caller() & return_to_handler do this by faking link
register's value to intercept function's return path.

More details on architecture specific requirements are described in
Documentation/trace/ftrace-design.txt.

Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
---
 arch/arm64/Kconfig               |    2 +
 arch/arm64/include/asm/ftrace.h  |   23 +++++
 arch/arm64/kernel/Makefile       |    4 +
 arch/arm64/kernel/arm64ksyms.c   |    4 +
 arch/arm64/kernel/entry-ftrace.S |  173 ++++++++++++++++++++++++++++++++++++++
 arch/arm64/kernel/ftrace.c       |   64 ++++++++++++++
 6 files changed, 270 insertions(+)
 create mode 100644 arch/arm64/include/asm/ftrace.h
 create mode 100644 arch/arm64/kernel/entry-ftrace.S
 create mode 100644 arch/arm64/kernel/ftrace.c

diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 27bbcfc..5783641 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -33,6 +33,8 @@ config ARM64
        select HAVE_DMA_ATTRS
        select HAVE_DMA_CONTIGUOUS
        select HAVE_EFFICIENT_UNALIGNED_ACCESS
+       select HAVE_FUNCTION_TRACER
+       select HAVE_FUNCTION_GRAPH_TRACER
        select HAVE_GENERIC_DMA_COHERENT
        select HAVE_HW_BREAKPOINT if PERF_EVENTS
        select HAVE_MEMBLOCK
diff --git a/arch/arm64/include/asm/ftrace.h b/arch/arm64/include/asm/ftrace.h
new file mode 100644
index 0000000..58ea595
--- /dev/null
+++ b/arch/arm64/include/asm/ftrace.h
@@ -0,0 +1,23 @@
+/*
+ * arch/arm64/include/asm/ftrace.h
+ *
+ * Copyright (C) 2013 Linaro Limited
+ * Author: AKASHI Takahiro <takahiro.akashi@linaro.org>
+ *
+ * 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.
+ */
+#ifndef __ASM_FTRACE_H
+#define __ASM_FTRACE_H
+
+#include <asm/insn.h>
+
+#define MCOUNT_ADDR            ((unsigned long)_mcount)
+#define MCOUNT_INSN_SIZE       AARCH64_INSN_SIZE
+
+#ifndef __ASSEMBLY__
+extern void _mcount(unsigned long);
+#endif /* __ASSEMBLY__ */
+
+#endif /* __ASM_FTRACE_H */
diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile
index 2d4554b..ac67fd0 100644
--- a/arch/arm64/kernel/Makefile
+++ b/arch/arm64/kernel/Makefile
@@ -5,6 +5,9 @@
 CPPFLAGS_vmlinux.lds   := -DTEXT_OFFSET=$(TEXT_OFFSET)
 AFLAGS_head.o          := -DTEXT_OFFSET=$(TEXT_OFFSET)

+CFLAGS_REMOVE_ftrace.o = -pg
+CFLAGS_REMOVE_insn.o = -pg
+
 # Object file lists.
 arm64-obj-y            := cputable.o debug-monitors.o entry.o irq.o fpsimd.o   \
                           entry-fpsimd.o process.o ptrace.o setup.o signal.o   \
@@ -13,6 +16,7 @@ arm64-obj-y           := cputable.o debug-monitors.o entry.o irq.o fpsimd.o   \

 arm64-obj-$(CONFIG_COMPAT)             += sys32.o kuser32.o signal32.o         \
                                           sys_compat.o
+arm64-obj-$(CONFIG_FUNCTION_TRACER)    += ftrace.o entry-ftrace.o
 arm64-obj-$(CONFIG_MODULES)            += arm64ksyms.o module.o
 arm64-obj-$(CONFIG_SMP)                        += smp.o smp_spin_table.o
 arm64-obj-$(CONFIG_HW_PERF_EVENTS)     += perf_event.o
diff --git a/arch/arm64/kernel/arm64ksyms.c b/arch/arm64/kernel/arm64ksyms.c
index 338b568..7f0512f 100644
--- a/arch/arm64/kernel/arm64ksyms.c
+++ b/arch/arm64/kernel/arm64ksyms.c
@@ -56,3 +56,7 @@ EXPORT_SYMBOL(clear_bit);
 EXPORT_SYMBOL(test_and_clear_bit);
 EXPORT_SYMBOL(change_bit);
 EXPORT_SYMBOL(test_and_change_bit);
+
+#ifdef CONFIG_FUNCTION_TRACER
+EXPORT_SYMBOL(_mcount);
+#endif
diff --git a/arch/arm64/kernel/entry-ftrace.S b/arch/arm64/kernel/entry-ftrace.S
new file mode 100644
index 0000000..2e8162e
--- /dev/null
+++ b/arch/arm64/kernel/entry-ftrace.S
@@ -0,0 +1,173 @@
+/*
+ * arch/arm64/kernel/entry-ftrace.S
+ *
+ * Copyright (C) 2013 Linaro Limited
+ * Author: AKASHI Takahiro <takahiro.akashi@linaro.org>
+ *
+ * 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 <linux/linkage.h>
+#include <asm/ftrace.h>
+#include <asm/insn.h>
+
+/*
+ * Gcc with -pg will put the following code in the beginning of each function:
+ *      mov x0, x30
+ *      bl _mcount
+ *     [function's body ...]
+ * "bl _mcount" may be replaced to "bl ftrace_caller" or NOP if dynamic
+ * ftrace is enabled.
+ *
+ * Please note that x0 as an argument will not be used here because we can
+ * get lr(x30) of instrumented function at any time by winding up call stack
+ * as long as the kernel is compiled without -fomit-frame-pointer.
+ * (or CONFIG_FRAME_POINTER, this is forced on arm64)
+ *
+ * stack layout after mcount_enter:
+ *
+ *   0 ---------------------------------------- sp of _mcount()
+ *      x29: fp of instrumented function       fp is not winded
+ *     --------------------
+ *      x30: lr of _mcount() (= instrumented function's pc)
+ * +16 ---------------------------------------- sp of instrumented function
+ *
+ *     ....
+ *
+ * +xx ---------------------------------------- fp of instrumented function
+ *      x29: fp of parent
+ *     --------------------
+ *      x30: lr of instrumented function (= parent's pc)
+ *     --------------------
+ *      xxx
+ */
+
can stack layout be more readable as below?

Stack layout of _mcount after mcount_enter

       |------------------| sp + 16   <= frame pointer of _mcount.
       |                       |
       |       x30          | <=  lr of _mcount (instrumented func's pc)
       |                       |
       |------------------| sp + 8
       |                       |
       |       x29          | <= value of x29 is sp of instrumented function.
       |                       |
       |------------------| sp   <= stack pointer of _mcount

   
Stack layout of instrumented function.
                .
                .
                .
                .
       |------------------| sp + 16
       |                      |
       |       x30         | <=  lr of instrumented function (= parent's pc)
       |                      |
       |------------------| sp + 8
       |                      |
       |       x29         | <= sp of parent.
       |                      |
       |------------------| sp  <= this address is stored at sp of _mcount

 
+       .macro mcount_enter
+       stp     x29, x30, [sp, #-16]!
+       .endm
+
+       .macro mcount_exit
+       ldp     x29, x30, [sp], #16
+       ret
+       .endm
+
+       .macro mcount_adjust_addr rd, rn
+       sub     \rd, \rn, #AARCH64_INSN_SIZE
+       .endm
+
+       /* for instrumented function's parent */
+       .macro mcount_get_parent_fp reg
+       ldr     \reg, [sp]
+       ldr     \reg, [\reg]
+       .endm
+
+       /* for instrumented function */
+       .macro mcount_get_pc0 reg
+       mcount_adjust_addr      \reg, x30
+       .endm
+
+       .macro mcount_get_pc reg
+       ldr     \reg, [sp, #8]
+       mcount_adjust_addr      \reg, \reg
+       .endm
+
+       .macro mcount_get_lr reg
+       ldr     \reg, [sp]
+       ldr     \reg, [\reg, #8]
+       mcount_adjust_addr      \reg, \reg
+       .endm
+
+       .macro mcount_get_saved_lr_addr reg
+       ldr     \reg, [sp]
+       add     \reg, \reg, #8
+       .endm
+
+/*
+ * void _mcount(unsigned long return_address)
+ * @return_address: return address to instrumented function
+ *
+ * This function makes calls, if enabled, to:
+ *     - tracer function to probe instrumented function's entry,
+ *     - ftrace_graph_caller to set up an exit hook
+ */
+ENTRY(_mcount)
+#ifdef CONFIG_HAVE_FUNCTION_TRACE_MCOUNT_TEST
+       ldr     x0, =ftrace_trace_stop
+       ldr     x0, [x0]                // if ftrace_trace_stop
+       ret                             //   return;
+#endif
+       mcount_enter
+
+       ldr     x0, =ftrace_trace_function
+       ldr     x2, [x0]
+       adr     x0, ftrace_stub
+       cmp     x0, x2                  // if (ftrace_trace_function
+       b.eq    skip_ftrace_call        //     != ftrace_stub) {
+
+       mcount_get_pc   x0              //       function's pc
+       mcount_get_lr   x1              //       function's lr (= parent's pc)
+       blr     x2                      //   (*ftrace_trace_function)(pc, lr);
+
+#ifndef CONFIG_FUNCTION_GRAPH_TRACER
+skip_ftrace_call:                      //   return;
+       mcount_exit                     // }
+#else
+       mcount_exit                     //   return;
+                                       // }
+skip_ftrace_call:
+       ldr     x1, =ftrace_graph_return
+       ldr     x2, [x1]                //   if ((ftrace_graph_return
+       cmp     x0, x2                  //        != ftrace_stub)
+       b.ne    ftrace_graph_caller
+
+       ldr     x1, =ftrace_graph_entry //     || (ftrace_graph_entry
+       ldr     x2, [x1]                //        != ftrace_graph_entry_stub))
+       ldr     x0, =ftrace_graph_entry_stub
+       cmp     x0, x2
+       b.ne    ftrace_graph_caller     //     ftrace_graph_caller();
+
+       mcount_exit
+#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
+ENDPROC(_mcount)
+
+ENTRY(ftrace_stub)
+       ret
+ENDPROC(ftrace_stub)
+
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+/*
+ * void ftrace_graph_caller(void)
+ *
+ * Called from _mcount() or ftrace_caller() when function_graph tracer is
+ * selected.
+ * This function w/ prepare_ftrace_return() fakes link register's value on
+ * the call stack in order to intercept instrumented function's return path
+ * and run return_to_handler() later on its exit.
+ */
+ENTRY(ftrace_graph_caller)
+       mcount_get_saved_lr_addr  x0    //     pointer to function's saved lr
+       mcount_get_pc             x1    //     function's pc
+       mcount_get_parent_fp      x2    //     parent's fp
+       bl      prepare_ftrace_return   // prepare_ftrace_return(&lr, pc, fp)
+
+       mcount_exit
+ENDPROC(ftrace_graph_caller)
+
+/*
+ * void return_to_handler(void)
+ *
+ * Run ftrace_return_to_handler() before going back to parent.
+ * @fp is checked against the value passed by ftrace_graph_caller()
+ * only when CONFIG_FUNCTION_GRAPH_FP_TEST is enabled.
+ */
+       .global return_to_handler
+return_to_handler:
+       str     x0, [sp, #-16]!
+       mov     x0, x29                 //     parent's fp
+       bl      ftrace_return_to_handler// addr = ftrace_return_to_hander(fp);
+       mov     x30, x0                 // restore the original return address
+       ldr     x0, [sp], #16
+       ret
+#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
diff --git a/arch/arm64/kernel/ftrace.c b/arch/arm64/kernel/ftrace.c
new file mode 100644
index 0000000..a559ab8
--- /dev/null
+++ b/arch/arm64/kernel/ftrace.c
@@ -0,0 +1,64 @@
+/*
+ * arch/arm64/kernel/ftrace.c
+ *
+ * Copyright (C) 2013 Linaro Limited
+ * Author: AKASHI Takahiro <takahiro.akashi@linaro.org>
+ *
+ * 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 <linux/ftrace.h>
+#include <linux/swab.h>
+#include <linux/uaccess.h>
+
+#include <asm/cacheflush.h>
+#include <asm/ftrace.h>
+#include <asm/insn.h>
+
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+/*
+ * function_graph tracer expects ftrace_return_to_handler() to be called
+ * on the way back to parent. For this purpose, this function is called
+ * in _mcount() or ftrace_caller() to replace return address (*parent) on
+ * the call stack to return_to_handler.
+ *
+ * Note that @frame_pointer is used only for sanity check later.
+ */
+void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr,
+                          unsigned long frame_pointer)
+{
+       unsigned long return_hooker = (unsigned long)&return_to_handler;
+       unsigned long old;
+       struct ftrace_graph_ent trace;
+       int err;
+
+       if (unlikely(atomic_read(&current->tracing_graph_pause)))
+               return;
+
+       /*
+        * Note:
+        * No protection against faulting at *parent, which may be seen
+        * on other archs. It's unlikely on AArch64.
+        */
+       old = *parent;
+       *parent = return_hooker;
+
+       trace.func = self_addr;
+       trace.depth = current->curr_ret_stack + 1;
+
+       /* Only trace if the calling function expects to */
+       if (!ftrace_graph_entry(&trace)) {
+               *parent = old;
+               return;
+       }
+
+       err = ftrace_push_return_trace(old, self_addr, &trace.depth,
+                                      frame_pointer);
+       if (err == -EBUSY) {
+               *parent = old;
+               return;
+       }
+}
+#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
--
1.7.9.5

^ permalink raw reply related	[flat|nested] 235+ messages in thread

* Re: [PATCH v4 1/7] arm64: Add ftrace support
  2014-02-25 15:38         ` Kulkarni, Ganapatrao
@ 2014-02-28  5:06           ` AKASHI Takahiro
  -1 siblings, 0 replies; 235+ messages in thread
From: AKASHI Takahiro @ 2014-02-28  5:06 UTC (permalink / raw)
  To: Kulkarni, Ganapatrao, rostedt, fweisbec, mingo, catalin.marinas,
	will.deacon, tim.bird
  Cc: dsaxena, arndb, linux-arm-kernel, linaro-kernel, linux-kernel

Ganapatrao,

On 02/26/2014 12:38 AM, Kulkarni, Ganapatrao wrote:
>
> ________________________________________
> From: AKASHI Takahiro <takahiro.akashi@linaro.org>
> Sent: Tuesday, February 25, 2014 2:53 PM
> To: rostedt@goodmis.org; fweisbec@gmail.com; mingo@redhat.com; catalin.marinas@arm.com; will.deacon@arm.com; tim.bird@sonymobile.com
> Cc: Kulkarni, Ganapatrao; dsaxena@linaro.org; arndb@arndb.de; linux-arm-kernel@lists.infradead.org; linaro-kernel@lists.linaro.org; linux-kernel@vger.kernel.org; AKASHI Takahiro
> Subject: [PATCH v4 1/7] arm64: Add ftrace support
>
> This patch implements arm64 specific part to support function tracers,
> such as function (CONFIG_FUNCTION_TRACER), function_graph
> (CONFIG_FUNCTION_GRAPH_TRACER) and function profiler
> (CONFIG_FUNCTION_PROFILER).
>
> With 'function' tracer, all the functions in the kernel are traced with
> timestamps in ${sysfs}/tracing/trace. If function_graph tracer is
> specified, call graph is generated.
>
> The kernel must be compiled with -pg option so that _mcount() is inserted
> at the beginning of functions. This function is called on every function's
> entry as long as tracing is enabled.
> In addition, function_graph tracer also needs to be able to probe function's
> exit. ftrace_graph_caller() & return_to_handler do this by faking link
> register's value to intercept function's return path.
>
> More details on architecture specific requirements are described in
> Documentation/trace/ftrace-design.txt.
>
> Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
> ---
>   arch/arm64/Kconfig               |    2 +
>   arch/arm64/include/asm/ftrace.h  |   23 +++++
>   arch/arm64/kernel/Makefile       |    4 +
>   arch/arm64/kernel/arm64ksyms.c   |    4 +
>   arch/arm64/kernel/entry-ftrace.S |  173 ++++++++++++++++++++++++++++++++++++++
>   arch/arm64/kernel/ftrace.c       |   64 ++++++++++++++
>   6 files changed, 270 insertions(+)
>   create mode 100644 arch/arm64/include/asm/ftrace.h
>   create mode 100644 arch/arm64/kernel/entry-ftrace.S
>   create mode 100644 arch/arm64/kernel/ftrace.c
>
> diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
> index 27bbcfc..5783641 100644
> --- a/arch/arm64/Kconfig
> +++ b/arch/arm64/Kconfig
> @@ -33,6 +33,8 @@ config ARM64
>          select HAVE_DMA_ATTRS
>          select HAVE_DMA_CONTIGUOUS
>          select HAVE_EFFICIENT_UNALIGNED_ACCESS
> +       select HAVE_FUNCTION_TRACER
> +       select HAVE_FUNCTION_GRAPH_TRACER
>          select HAVE_GENERIC_DMA_COHERENT
>          select HAVE_HW_BREAKPOINT if PERF_EVENTS
>          select HAVE_MEMBLOCK
> diff --git a/arch/arm64/include/asm/ftrace.h b/arch/arm64/include/asm/ftrace.h
> new file mode 100644
> index 0000000..58ea595
> --- /dev/null
> +++ b/arch/arm64/include/asm/ftrace.h
> @@ -0,0 +1,23 @@
> +/*
> + * arch/arm64/include/asm/ftrace.h
> + *
> + * Copyright (C) 2013 Linaro Limited
> + * Author: AKASHI Takahiro <takahiro.akashi@linaro.org>
> + *
> + * 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.
> + */
> +#ifndef __ASM_FTRACE_H
> +#define __ASM_FTRACE_H
> +
> +#include <asm/insn.h>
> +
> +#define MCOUNT_ADDR            ((unsigned long)_mcount)
> +#define MCOUNT_INSN_SIZE       AARCH64_INSN_SIZE
> +
> +#ifndef __ASSEMBLY__
> +extern void _mcount(unsigned long);
> +#endif /* __ASSEMBLY__ */
> +
> +#endif /* __ASM_FTRACE_H */
> diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile
> index 2d4554b..ac67fd0 100644
> --- a/arch/arm64/kernel/Makefile
> +++ b/arch/arm64/kernel/Makefile
> @@ -5,6 +5,9 @@
>   CPPFLAGS_vmlinux.lds   := -DTEXT_OFFSET=$(TEXT_OFFSET)
>   AFLAGS_head.o          := -DTEXT_OFFSET=$(TEXT_OFFSET)
>
> +CFLAGS_REMOVE_ftrace.o = -pg
> +CFLAGS_REMOVE_insn.o = -pg
> +
>   # Object file lists.
>   arm64-obj-y            := cputable.o debug-monitors.o entry.o irq.o fpsimd.o   \
>                             entry-fpsimd.o process.o ptrace.o setup.o signal.o   \
> @@ -13,6 +16,7 @@ arm64-obj-y           := cputable.o debug-monitors.o entry.o irq.o fpsimd.o   \
>
>   arm64-obj-$(CONFIG_COMPAT)             += sys32.o kuser32.o signal32.o         \
>                                             sys_compat.o
> +arm64-obj-$(CONFIG_FUNCTION_TRACER)    += ftrace.o entry-ftrace.o
>   arm64-obj-$(CONFIG_MODULES)            += arm64ksyms.o module.o
>   arm64-obj-$(CONFIG_SMP)                        += smp.o smp_spin_table.o
>   arm64-obj-$(CONFIG_HW_PERF_EVENTS)     += perf_event.o
> diff --git a/arch/arm64/kernel/arm64ksyms.c b/arch/arm64/kernel/arm64ksyms.c
> index 338b568..7f0512f 100644
> --- a/arch/arm64/kernel/arm64ksyms.c
> +++ b/arch/arm64/kernel/arm64ksyms.c
> @@ -56,3 +56,7 @@ EXPORT_SYMBOL(clear_bit);
>   EXPORT_SYMBOL(test_and_clear_bit);
>   EXPORT_SYMBOL(change_bit);
>   EXPORT_SYMBOL(test_and_change_bit);
> +
> +#ifdef CONFIG_FUNCTION_TRACER
> +EXPORT_SYMBOL(_mcount);
> +#endif
> diff --git a/arch/arm64/kernel/entry-ftrace.S b/arch/arm64/kernel/entry-ftrace.S
> new file mode 100644
> index 0000000..2e8162e
> --- /dev/null
> +++ b/arch/arm64/kernel/entry-ftrace.S
> @@ -0,0 +1,173 @@
> +/*
> + * arch/arm64/kernel/entry-ftrace.S
> + *
> + * Copyright (C) 2013 Linaro Limited
> + * Author: AKASHI Takahiro <takahiro.akashi@linaro.org>
> + *
> + * 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 <linux/linkage.h>
> +#include <asm/ftrace.h>
> +#include <asm/insn.h>
> +
> +/*
> + * Gcc with -pg will put the following code in the beginning of each function:
> + *      mov x0, x30
> + *      bl _mcount
> + *     [function's body ...]
> + * "bl _mcount" may be replaced to "bl ftrace_caller" or NOP if dynamic
> + * ftrace is enabled.
> + *
> + * Please note that x0 as an argument will not be used here because we can
> + * get lr(x30) of instrumented function at any time by winding up call stack
> + * as long as the kernel is compiled without -fomit-frame-pointer.
> + * (or CONFIG_FRAME_POINTER, this is forced on arm64)
> + *
> + * stack layout after mcount_enter:
> + *
> + *   0 ---------------------------------------- sp of _mcount()
> + *      x29: fp of instrumented function       fp is not winded
> + *     --------------------
> + *      x30: lr of _mcount() (= instrumented function's pc)
> + * +16 ---------------------------------------- sp of instrumented function
> + *
> + *     ....
> + *
> + * +xx ---------------------------------------- fp of instrumented function
> + *      x29: fp of parent
> + *     --------------------
> + *      x30: lr of instrumented function (= parent's pc)
> + *     --------------------
> + *      xxx
> + */
> +
> can stack layout be more readable as below?
 >
> Stack layout of _mcount after mcount_enter
>
>         |------------------| sp + 16   <= frame pointer of _mcount.
>         |                       |
>         |       x30          | <=  lr of _mcount (instrumented func's pc)
>         |                       |
>         |------------------| sp + 8
>         |                       |
>         |       x29          | <= value of x29 is sp of instrumented function.

not sp, but fp.
Anyway pls check with my new patch v5.

Thanks,
-Takahiro AKASHI

>         |                       |
>         |------------------| sp   <= stack pointer of _mcount
>
>
> Stack layout of instrumented function.
>                  .
>                  .
>                  .
>                  .
>         |------------------| sp + 16
>         |                      |
>         |       x30         | <=  lr of instrumented function (= parent's pc)
>         |                      |
>         |------------------| sp + 8
>         |                      |
>         |       x29         | <= sp of parent.
>         |                      |
>         |------------------| sp  <= this address is stored at sp of _mcount
>
>
> +       .macro mcount_enter
> +       stp     x29, x30, [sp, #-16]!
> +       .endm
> +
> +       .macro mcount_exit
> +       ldp     x29, x30, [sp], #16
> +       ret
> +       .endm
> +
> +       .macro mcount_adjust_addr rd, rn
> +       sub     \rd, \rn, #AARCH64_INSN_SIZE
> +       .endm
> +
> +       /* for instrumented function's parent */
> +       .macro mcount_get_parent_fp reg
> +       ldr     \reg, [sp]
> +       ldr     \reg, [\reg]
> +       .endm
> +
> +       /* for instrumented function */
> +       .macro mcount_get_pc0 reg
> +       mcount_adjust_addr      \reg, x30
> +       .endm
> +
> +       .macro mcount_get_pc reg
> +       ldr     \reg, [sp, #8]
> +       mcount_adjust_addr      \reg, \reg
> +       .endm
> +
> +       .macro mcount_get_lr reg
> +       ldr     \reg, [sp]
> +       ldr     \reg, [\reg, #8]
> +       mcount_adjust_addr      \reg, \reg
> +       .endm
> +
> +       .macro mcount_get_saved_lr_addr reg
> +       ldr     \reg, [sp]
> +       add     \reg, \reg, #8
> +       .endm
> +
> +/*
> + * void _mcount(unsigned long return_address)
> + * @return_address: return address to instrumented function
> + *
> + * This function makes calls, if enabled, to:
> + *     - tracer function to probe instrumented function's entry,
> + *     - ftrace_graph_caller to set up an exit hook
> + */
> +ENTRY(_mcount)
> +#ifdef CONFIG_HAVE_FUNCTION_TRACE_MCOUNT_TEST
> +       ldr     x0, =ftrace_trace_stop
> +       ldr     x0, [x0]                // if ftrace_trace_stop
> +       ret                             //   return;
> +#endif
> +       mcount_enter
> +
> +       ldr     x0, =ftrace_trace_function
> +       ldr     x2, [x0]
> +       adr     x0, ftrace_stub
> +       cmp     x0, x2                  // if (ftrace_trace_function
> +       b.eq    skip_ftrace_call        //     != ftrace_stub) {
> +
> +       mcount_get_pc   x0              //       function's pc
> +       mcount_get_lr   x1              //       function's lr (= parent's pc)
> +       blr     x2                      //   (*ftrace_trace_function)(pc, lr);
> +
> +#ifndef CONFIG_FUNCTION_GRAPH_TRACER
> +skip_ftrace_call:                      //   return;
> +       mcount_exit                     // }
> +#else
> +       mcount_exit                     //   return;
> +                                       // }
> +skip_ftrace_call:
> +       ldr     x1, =ftrace_graph_return
> +       ldr     x2, [x1]                //   if ((ftrace_graph_return
> +       cmp     x0, x2                  //        != ftrace_stub)
> +       b.ne    ftrace_graph_caller
> +
> +       ldr     x1, =ftrace_graph_entry //     || (ftrace_graph_entry
> +       ldr     x2, [x1]                //        != ftrace_graph_entry_stub))
> +       ldr     x0, =ftrace_graph_entry_stub
> +       cmp     x0, x2
> +       b.ne    ftrace_graph_caller     //     ftrace_graph_caller();
> +
> +       mcount_exit
> +#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
> +ENDPROC(_mcount)
> +
> +ENTRY(ftrace_stub)
> +       ret
> +ENDPROC(ftrace_stub)
> +
> +#ifdef CONFIG_FUNCTION_GRAPH_TRACER
> +/*
> + * void ftrace_graph_caller(void)
> + *
> + * Called from _mcount() or ftrace_caller() when function_graph tracer is
> + * selected.
> + * This function w/ prepare_ftrace_return() fakes link register's value on
> + * the call stack in order to intercept instrumented function's return path
> + * and run return_to_handler() later on its exit.
> + */
> +ENTRY(ftrace_graph_caller)
> +       mcount_get_saved_lr_addr  x0    //     pointer to function's saved lr
> +       mcount_get_pc             x1    //     function's pc
> +       mcount_get_parent_fp      x2    //     parent's fp
> +       bl      prepare_ftrace_return   // prepare_ftrace_return(&lr, pc, fp)
> +
> +       mcount_exit
> +ENDPROC(ftrace_graph_caller)
> +
> +/*
> + * void return_to_handler(void)
> + *
> + * Run ftrace_return_to_handler() before going back to parent.
> + * @fp is checked against the value passed by ftrace_graph_caller()
> + * only when CONFIG_FUNCTION_GRAPH_FP_TEST is enabled.
> + */
> +       .global return_to_handler
> +return_to_handler:
> +       str     x0, [sp, #-16]!
> +       mov     x0, x29                 //     parent's fp
> +       bl      ftrace_return_to_handler// addr = ftrace_return_to_hander(fp);
> +       mov     x30, x0                 // restore the original return address
> +       ldr     x0, [sp], #16
> +       ret
> +#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
> diff --git a/arch/arm64/kernel/ftrace.c b/arch/arm64/kernel/ftrace.c
> new file mode 100644
> index 0000000..a559ab8
> --- /dev/null
> +++ b/arch/arm64/kernel/ftrace.c
> @@ -0,0 +1,64 @@
> +/*
> + * arch/arm64/kernel/ftrace.c
> + *
> + * Copyright (C) 2013 Linaro Limited
> + * Author: AKASHI Takahiro <takahiro.akashi@linaro.org>
> + *
> + * 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 <linux/ftrace.h>
> +#include <linux/swab.h>
> +#include <linux/uaccess.h>
> +
> +#include <asm/cacheflush.h>
> +#include <asm/ftrace.h>
> +#include <asm/insn.h>
> +
> +#ifdef CONFIG_FUNCTION_GRAPH_TRACER
> +/*
> + * function_graph tracer expects ftrace_return_to_handler() to be called
> + * on the way back to parent. For this purpose, this function is called
> + * in _mcount() or ftrace_caller() to replace return address (*parent) on
> + * the call stack to return_to_handler.
> + *
> + * Note that @frame_pointer is used only for sanity check later.
> + */
> +void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr,
> +                          unsigned long frame_pointer)
> +{
> +       unsigned long return_hooker = (unsigned long)&return_to_handler;
> +       unsigned long old;
> +       struct ftrace_graph_ent trace;
> +       int err;
> +
> +       if (unlikely(atomic_read(&current->tracing_graph_pause)))
> +               return;
> +
> +       /*
> +        * Note:
> +        * No protection against faulting at *parent, which may be seen
> +        * on other archs. It's unlikely on AArch64.
> +        */
> +       old = *parent;
> +       *parent = return_hooker;
> +
> +       trace.func = self_addr;
> +       trace.depth = current->curr_ret_stack + 1;
> +
> +       /* Only trace if the calling function expects to */
> +       if (!ftrace_graph_entry(&trace)) {
> +               *parent = old;
> +               return;
> +       }
> +
> +       err = ftrace_push_return_trace(old, self_addr, &trace.depth,
> +                                      frame_pointer);
> +       if (err == -EBUSY) {
> +               *parent = old;
> +               return;
> +       }
> +}
> +#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
> --
> 1.7.9.5
>

^ permalink raw reply	[flat|nested] 235+ messages in thread

* [PATCH v4 1/7] arm64: Add ftrace support
@ 2014-02-28  5:06           ` AKASHI Takahiro
  0 siblings, 0 replies; 235+ messages in thread
From: AKASHI Takahiro @ 2014-02-28  5:06 UTC (permalink / raw)
  To: linux-arm-kernel

Ganapatrao,

On 02/26/2014 12:38 AM, Kulkarni, Ganapatrao wrote:
>
> ________________________________________
> From: AKASHI Takahiro <takahiro.akashi@linaro.org>
> Sent: Tuesday, February 25, 2014 2:53 PM
> To: rostedt at goodmis.org; fweisbec at gmail.com; mingo at redhat.com; catalin.marinas at arm.com; will.deacon at arm.com; tim.bird at sonymobile.com
> Cc: Kulkarni, Ganapatrao; dsaxena at linaro.org; arndb at arndb.de; linux-arm-kernel at lists.infradead.org; linaro-kernel at lists.linaro.org; linux-kernel at vger.kernel.org; AKASHI Takahiro
> Subject: [PATCH v4 1/7] arm64: Add ftrace support
>
> This patch implements arm64 specific part to support function tracers,
> such as function (CONFIG_FUNCTION_TRACER), function_graph
> (CONFIG_FUNCTION_GRAPH_TRACER) and function profiler
> (CONFIG_FUNCTION_PROFILER).
>
> With 'function' tracer, all the functions in the kernel are traced with
> timestamps in ${sysfs}/tracing/trace. If function_graph tracer is
> specified, call graph is generated.
>
> The kernel must be compiled with -pg option so that _mcount() is inserted
> at the beginning of functions. This function is called on every function's
> entry as long as tracing is enabled.
> In addition, function_graph tracer also needs to be able to probe function's
> exit. ftrace_graph_caller() & return_to_handler do this by faking link
> register's value to intercept function's return path.
>
> More details on architecture specific requirements are described in
> Documentation/trace/ftrace-design.txt.
>
> Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
> ---
>   arch/arm64/Kconfig               |    2 +
>   arch/arm64/include/asm/ftrace.h  |   23 +++++
>   arch/arm64/kernel/Makefile       |    4 +
>   arch/arm64/kernel/arm64ksyms.c   |    4 +
>   arch/arm64/kernel/entry-ftrace.S |  173 ++++++++++++++++++++++++++++++++++++++
>   arch/arm64/kernel/ftrace.c       |   64 ++++++++++++++
>   6 files changed, 270 insertions(+)
>   create mode 100644 arch/arm64/include/asm/ftrace.h
>   create mode 100644 arch/arm64/kernel/entry-ftrace.S
>   create mode 100644 arch/arm64/kernel/ftrace.c
>
> diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
> index 27bbcfc..5783641 100644
> --- a/arch/arm64/Kconfig
> +++ b/arch/arm64/Kconfig
> @@ -33,6 +33,8 @@ config ARM64
>          select HAVE_DMA_ATTRS
>          select HAVE_DMA_CONTIGUOUS
>          select HAVE_EFFICIENT_UNALIGNED_ACCESS
> +       select HAVE_FUNCTION_TRACER
> +       select HAVE_FUNCTION_GRAPH_TRACER
>          select HAVE_GENERIC_DMA_COHERENT
>          select HAVE_HW_BREAKPOINT if PERF_EVENTS
>          select HAVE_MEMBLOCK
> diff --git a/arch/arm64/include/asm/ftrace.h b/arch/arm64/include/asm/ftrace.h
> new file mode 100644
> index 0000000..58ea595
> --- /dev/null
> +++ b/arch/arm64/include/asm/ftrace.h
> @@ -0,0 +1,23 @@
> +/*
> + * arch/arm64/include/asm/ftrace.h
> + *
> + * Copyright (C) 2013 Linaro Limited
> + * Author: AKASHI Takahiro <takahiro.akashi@linaro.org>
> + *
> + * 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.
> + */
> +#ifndef __ASM_FTRACE_H
> +#define __ASM_FTRACE_H
> +
> +#include <asm/insn.h>
> +
> +#define MCOUNT_ADDR            ((unsigned long)_mcount)
> +#define MCOUNT_INSN_SIZE       AARCH64_INSN_SIZE
> +
> +#ifndef __ASSEMBLY__
> +extern void _mcount(unsigned long);
> +#endif /* __ASSEMBLY__ */
> +
> +#endif /* __ASM_FTRACE_H */
> diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile
> index 2d4554b..ac67fd0 100644
> --- a/arch/arm64/kernel/Makefile
> +++ b/arch/arm64/kernel/Makefile
> @@ -5,6 +5,9 @@
>   CPPFLAGS_vmlinux.lds   := -DTEXT_OFFSET=$(TEXT_OFFSET)
>   AFLAGS_head.o          := -DTEXT_OFFSET=$(TEXT_OFFSET)
>
> +CFLAGS_REMOVE_ftrace.o = -pg
> +CFLAGS_REMOVE_insn.o = -pg
> +
>   # Object file lists.
>   arm64-obj-y            := cputable.o debug-monitors.o entry.o irq.o fpsimd.o   \
>                             entry-fpsimd.o process.o ptrace.o setup.o signal.o   \
> @@ -13,6 +16,7 @@ arm64-obj-y           := cputable.o debug-monitors.o entry.o irq.o fpsimd.o   \
>
>   arm64-obj-$(CONFIG_COMPAT)             += sys32.o kuser32.o signal32.o         \
>                                             sys_compat.o
> +arm64-obj-$(CONFIG_FUNCTION_TRACER)    += ftrace.o entry-ftrace.o
>   arm64-obj-$(CONFIG_MODULES)            += arm64ksyms.o module.o
>   arm64-obj-$(CONFIG_SMP)                        += smp.o smp_spin_table.o
>   arm64-obj-$(CONFIG_HW_PERF_EVENTS)     += perf_event.o
> diff --git a/arch/arm64/kernel/arm64ksyms.c b/arch/arm64/kernel/arm64ksyms.c
> index 338b568..7f0512f 100644
> --- a/arch/arm64/kernel/arm64ksyms.c
> +++ b/arch/arm64/kernel/arm64ksyms.c
> @@ -56,3 +56,7 @@ EXPORT_SYMBOL(clear_bit);
>   EXPORT_SYMBOL(test_and_clear_bit);
>   EXPORT_SYMBOL(change_bit);
>   EXPORT_SYMBOL(test_and_change_bit);
> +
> +#ifdef CONFIG_FUNCTION_TRACER
> +EXPORT_SYMBOL(_mcount);
> +#endif
> diff --git a/arch/arm64/kernel/entry-ftrace.S b/arch/arm64/kernel/entry-ftrace.S
> new file mode 100644
> index 0000000..2e8162e
> --- /dev/null
> +++ b/arch/arm64/kernel/entry-ftrace.S
> @@ -0,0 +1,173 @@
> +/*
> + * arch/arm64/kernel/entry-ftrace.S
> + *
> + * Copyright (C) 2013 Linaro Limited
> + * Author: AKASHI Takahiro <takahiro.akashi@linaro.org>
> + *
> + * 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 <linux/linkage.h>
> +#include <asm/ftrace.h>
> +#include <asm/insn.h>
> +
> +/*
> + * Gcc with -pg will put the following code in the beginning of each function:
> + *      mov x0, x30
> + *      bl _mcount
> + *     [function's body ...]
> + * "bl _mcount" may be replaced to "bl ftrace_caller" or NOP if dynamic
> + * ftrace is enabled.
> + *
> + * Please note that x0 as an argument will not be used here because we can
> + * get lr(x30) of instrumented function at any time by winding up call stack
> + * as long as the kernel is compiled without -fomit-frame-pointer.
> + * (or CONFIG_FRAME_POINTER, this is forced on arm64)
> + *
> + * stack layout after mcount_enter:
> + *
> + *   0 ---------------------------------------- sp of _mcount()
> + *      x29: fp of instrumented function       fp is not winded
> + *     --------------------
> + *      x30: lr of _mcount() (= instrumented function's pc)
> + * +16 ---------------------------------------- sp of instrumented function
> + *
> + *     ....
> + *
> + * +xx ---------------------------------------- fp of instrumented function
> + *      x29: fp of parent
> + *     --------------------
> + *      x30: lr of instrumented function (= parent's pc)
> + *     --------------------
> + *      xxx
> + */
> +
> can stack layout be more readable as below?
 >
> Stack layout of _mcount after mcount_enter
>
>         |------------------| sp + 16   <= frame pointer of _mcount.
>         |                       |
>         |       x30          | <=  lr of _mcount (instrumented func's pc)
>         |                       |
>         |------------------| sp + 8
>         |                       |
>         |       x29          | <= value of x29 is sp of instrumented function.

not sp, but fp.
Anyway pls check with my new patch v5.

Thanks,
-Takahiro AKASHI

>         |                       |
>         |------------------| sp   <= stack pointer of _mcount
>
>
> Stack layout of instrumented function.
>                  .
>                  .
>                  .
>                  .
>         |------------------| sp + 16
>         |                      |
>         |       x30         | <=  lr of instrumented function (= parent's pc)
>         |                      |
>         |------------------| sp + 8
>         |                      |
>         |       x29         | <= sp of parent.
>         |                      |
>         |------------------| sp  <= this address is stored@sp of _mcount
>
>
> +       .macro mcount_enter
> +       stp     x29, x30, [sp, #-16]!
> +       .endm
> +
> +       .macro mcount_exit
> +       ldp     x29, x30, [sp], #16
> +       ret
> +       .endm
> +
> +       .macro mcount_adjust_addr rd, rn
> +       sub     \rd, \rn, #AARCH64_INSN_SIZE
> +       .endm
> +
> +       /* for instrumented function's parent */
> +       .macro mcount_get_parent_fp reg
> +       ldr     \reg, [sp]
> +       ldr     \reg, [\reg]
> +       .endm
> +
> +       /* for instrumented function */
> +       .macro mcount_get_pc0 reg
> +       mcount_adjust_addr      \reg, x30
> +       .endm
> +
> +       .macro mcount_get_pc reg
> +       ldr     \reg, [sp, #8]
> +       mcount_adjust_addr      \reg, \reg
> +       .endm
> +
> +       .macro mcount_get_lr reg
> +       ldr     \reg, [sp]
> +       ldr     \reg, [\reg, #8]
> +       mcount_adjust_addr      \reg, \reg
> +       .endm
> +
> +       .macro mcount_get_saved_lr_addr reg
> +       ldr     \reg, [sp]
> +       add     \reg, \reg, #8
> +       .endm
> +
> +/*
> + * void _mcount(unsigned long return_address)
> + * @return_address: return address to instrumented function
> + *
> + * This function makes calls, if enabled, to:
> + *     - tracer function to probe instrumented function's entry,
> + *     - ftrace_graph_caller to set up an exit hook
> + */
> +ENTRY(_mcount)
> +#ifdef CONFIG_HAVE_FUNCTION_TRACE_MCOUNT_TEST
> +       ldr     x0, =ftrace_trace_stop
> +       ldr     x0, [x0]                // if ftrace_trace_stop
> +       ret                             //   return;
> +#endif
> +       mcount_enter
> +
> +       ldr     x0, =ftrace_trace_function
> +       ldr     x2, [x0]
> +       adr     x0, ftrace_stub
> +       cmp     x0, x2                  // if (ftrace_trace_function
> +       b.eq    skip_ftrace_call        //     != ftrace_stub) {
> +
> +       mcount_get_pc   x0              //       function's pc
> +       mcount_get_lr   x1              //       function's lr (= parent's pc)
> +       blr     x2                      //   (*ftrace_trace_function)(pc, lr);
> +
> +#ifndef CONFIG_FUNCTION_GRAPH_TRACER
> +skip_ftrace_call:                      //   return;
> +       mcount_exit                     // }
> +#else
> +       mcount_exit                     //   return;
> +                                       // }
> +skip_ftrace_call:
> +       ldr     x1, =ftrace_graph_return
> +       ldr     x2, [x1]                //   if ((ftrace_graph_return
> +       cmp     x0, x2                  //        != ftrace_stub)
> +       b.ne    ftrace_graph_caller
> +
> +       ldr     x1, =ftrace_graph_entry //     || (ftrace_graph_entry
> +       ldr     x2, [x1]                //        != ftrace_graph_entry_stub))
> +       ldr     x0, =ftrace_graph_entry_stub
> +       cmp     x0, x2
> +       b.ne    ftrace_graph_caller     //     ftrace_graph_caller();
> +
> +       mcount_exit
> +#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
> +ENDPROC(_mcount)
> +
> +ENTRY(ftrace_stub)
> +       ret
> +ENDPROC(ftrace_stub)
> +
> +#ifdef CONFIG_FUNCTION_GRAPH_TRACER
> +/*
> + * void ftrace_graph_caller(void)
> + *
> + * Called from _mcount() or ftrace_caller() when function_graph tracer is
> + * selected.
> + * This function w/ prepare_ftrace_return() fakes link register's value on
> + * the call stack in order to intercept instrumented function's return path
> + * and run return_to_handler() later on its exit.
> + */
> +ENTRY(ftrace_graph_caller)
> +       mcount_get_saved_lr_addr  x0    //     pointer to function's saved lr
> +       mcount_get_pc             x1    //     function's pc
> +       mcount_get_parent_fp      x2    //     parent's fp
> +       bl      prepare_ftrace_return   // prepare_ftrace_return(&lr, pc, fp)
> +
> +       mcount_exit
> +ENDPROC(ftrace_graph_caller)
> +
> +/*
> + * void return_to_handler(void)
> + *
> + * Run ftrace_return_to_handler() before going back to parent.
> + * @fp is checked against the value passed by ftrace_graph_caller()
> + * only when CONFIG_FUNCTION_GRAPH_FP_TEST is enabled.
> + */
> +       .global return_to_handler
> +return_to_handler:
> +       str     x0, [sp, #-16]!
> +       mov     x0, x29                 //     parent's fp
> +       bl      ftrace_return_to_handler// addr = ftrace_return_to_hander(fp);
> +       mov     x30, x0                 // restore the original return address
> +       ldr     x0, [sp], #16
> +       ret
> +#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
> diff --git a/arch/arm64/kernel/ftrace.c b/arch/arm64/kernel/ftrace.c
> new file mode 100644
> index 0000000..a559ab8
> --- /dev/null
> +++ b/arch/arm64/kernel/ftrace.c
> @@ -0,0 +1,64 @@
> +/*
> + * arch/arm64/kernel/ftrace.c
> + *
> + * Copyright (C) 2013 Linaro Limited
> + * Author: AKASHI Takahiro <takahiro.akashi@linaro.org>
> + *
> + * 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 <linux/ftrace.h>
> +#include <linux/swab.h>
> +#include <linux/uaccess.h>
> +
> +#include <asm/cacheflush.h>
> +#include <asm/ftrace.h>
> +#include <asm/insn.h>
> +
> +#ifdef CONFIG_FUNCTION_GRAPH_TRACER
> +/*
> + * function_graph tracer expects ftrace_return_to_handler() to be called
> + * on the way back to parent. For this purpose, this function is called
> + * in _mcount() or ftrace_caller() to replace return address (*parent) on
> + * the call stack to return_to_handler.
> + *
> + * Note that @frame_pointer is used only for sanity check later.
> + */
> +void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr,
> +                          unsigned long frame_pointer)
> +{
> +       unsigned long return_hooker = (unsigned long)&return_to_handler;
> +       unsigned long old;
> +       struct ftrace_graph_ent trace;
> +       int err;
> +
> +       if (unlikely(atomic_read(&current->tracing_graph_pause)))
> +               return;
> +
> +       /*
> +        * Note:
> +        * No protection against faulting at *parent, which may be seen
> +        * on other archs. It's unlikely on AArch64.
> +        */
> +       old = *parent;
> +       *parent = return_hooker;
> +
> +       trace.func = self_addr;
> +       trace.depth = current->curr_ret_stack + 1;
> +
> +       /* Only trace if the calling function expects to */
> +       if (!ftrace_graph_entry(&trace)) {
> +               *parent = old;
> +               return;
> +       }
> +
> +       err = ftrace_push_return_trace(old, self_addr, &trace.depth,
> +                                      frame_pointer);
> +       if (err == -EBUSY) {
> +               *parent = old;
> +               return;
> +       }
> +}
> +#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
> --
> 1.7.9.5
>

^ permalink raw reply	[flat|nested] 235+ messages in thread

* [PATCH v5 0/7] arm64: Add ftrace support
  2014-02-25  9:23     ` AKASHI Takahiro
@ 2014-02-28  5:18       ` AKASHI Takahiro
  -1 siblings, 0 replies; 235+ messages in thread
From: AKASHI Takahiro @ 2014-02-28  5:18 UTC (permalink / raw)
  To: rostedt, fweisbec, mingo, catalin.marinas, will.deacon, tim.bird
  Cc: gkulkarni, dsaxena, arndb, linux-arm-kernel, linaro-kernel,
	linux-kernel, AKASHI Takahiro

This patchset implements a function tracer on arm64.
There was another implementation from Cavium network, but both of us agreed
to use my patchset as future base. He is supposed to review this code, too.

The only issue that I had some concern on was "fault protection" code
in prepare_ftrace_return(). With discussions with Steven and Tim (as author
of arm ftrace), I removed that code since I'm not quite sure about possibility
of "fault" occurrences in this function.

The code is tested on ARMv8 Fast Model with the following tracers & events:
     function tracer with dynamic ftrace
     function graph tracer with dynamic ftrace
     syscall tracepoint
     irqsoff & preemptirqsoff (which use CALLER_ADDRx)
and also verified with in-kernel tests, FTRACE_SELFTEST, FTRACE_STARTUP_TEST
and EVENT_TRACE_TEST_SYSCALLS.

Prerequisites are:
 * "arm64: Add regs_return_value() in syscall.h"
 * "arm64: make a single hook to syscall_trace() for all syscall features" patch

Please be careful:
* elf.h on cross-build host must have AArch64 definitions, EM_AARCH64 and
  R_AARCH64_ABS64, to compile recordmcount utility. See [4/6].
  [4/6] also gets warnings from checkpatch, but they are based on the
  original's coding style.
* This patch may conflict with my audit patch because both changes the same
  location in syscall_trace(). I expect the functions are called in this
  order:
  On entry,
     * tracehook_report_syscall(ENTER)
     * trace_sys_enter()
     * audit_syscall_entry()
  On exit,
     * audit_sysscall_exit()
     * trace_sys_exit()
     * tracehook_report_syscall(EXIT) 

Changes from v1 to v2:
* splitted one patch into some pieces for easier review
  (especially function tracer + dynamic ftrace + CALLER_ADDRx)
* put return_address() in a separate file
* renamed __mcount to _mcount (it was my mistake)
* changed stackframe handling to get parent's frame pointer
* removed ARCH_SUPPORTS_FTRACE_OPS
* switched to "hotpatch" interfaces from Huawai
* revised descriptions in comments

Changes from v2 to v3:
* optimized register usages in asm (by not saving x0, x1, and x2)
* removed "fault protection" code in prepare_ftrace_return()
* rewrote ftrace_modify_code() using "hotpatch" interfaces
* revised descriptions in comments

Changes from v3 to v4:
* removed unnecessary "#ifdef" [1,2/7]
* changed stack depth from 48B to 16B in mcount()/ftrace_caller() (a bug) [1/7]
* changed MCOUNT_INSN_SIZE to AARCH64_INSN_SIZE [1,7/7]
* added a guard againt TIF_SYSCALL_TRACEPOINT [5/7]
* corrected the second argument passed to trace_sys_exit() (a bug) [5/7]
* aligned with the change in "arm64: make a single hook to syscall_trace()
  for all syscall features" v2 [5/7]

Chnages from v4 to v5:
* improved the description of stack layout [1/7]
* aligned with the change in "arm64: make a single hook to syscall_trace()
  for all syscall features" v3 [5/7]

AKASHI Takahiro (7):
  arm64: Add ftrace support
  arm64: ftrace: Add dynamic ftrace support
  arm64: ftrace: Add CALLER_ADDRx macros
  ftrace: Add arm64 support to recordmcount
  arm64: ftrace: Add system call tracepoint
  arm64: Add 'notrace' attribute to unwind_frame() for ftrace
  arm64: add __ASSEMBLY__ in asm/insn.h

 arch/arm64/Kconfig                 |    6 +
 arch/arm64/include/asm/ftrace.h    |   52 +++++++++
 arch/arm64/include/asm/insn.h      |    2 +
 arch/arm64/include/asm/syscall.h   |    1 +
 arch/arm64/include/asm/unistd.h    |    2 +
 arch/arm64/kernel/Makefile         |    7 +-
 arch/arm64/kernel/arm64ksyms.c     |    4 +
 arch/arm64/kernel/entry-ftrace.S   |  217 ++++++++++++++++++++++++++++++++++++
 arch/arm64/kernel/ftrace.c         |  177 +++++++++++++++++++++++++++++
 arch/arm64/kernel/ptrace.c         |   52 +++++----
 arch/arm64/kernel/return_address.c |   55 +++++++++
 arch/arm64/kernel/stacktrace.c     |    2 +-
 scripts/recordmcount.c             |    4 +
 scripts/recordmcount.pl            |    5 +
 14 files changed, 562 insertions(+), 24 deletions(-)
 create mode 100644 arch/arm64/include/asm/ftrace.h
 create mode 100644 arch/arm64/kernel/entry-ftrace.S
 create mode 100644 arch/arm64/kernel/ftrace.c
 create mode 100644 arch/arm64/kernel/return_address.c

-- 
1.7.9.5


^ permalink raw reply	[flat|nested] 235+ messages in thread

* [PATCH v5 0/7] arm64: Add ftrace support
@ 2014-02-28  5:18       ` AKASHI Takahiro
  0 siblings, 0 replies; 235+ messages in thread
From: AKASHI Takahiro @ 2014-02-28  5:18 UTC (permalink / raw)
  To: linux-arm-kernel

This patchset implements a function tracer on arm64.
There was another implementation from Cavium network, but both of us agreed
to use my patchset as future base. He is supposed to review this code, too.

The only issue that I had some concern on was "fault protection" code
in prepare_ftrace_return(). With discussions with Steven and Tim (as author
of arm ftrace), I removed that code since I'm not quite sure about possibility
of "fault" occurrences in this function.

The code is tested on ARMv8 Fast Model with the following tracers & events:
     function tracer with dynamic ftrace
     function graph tracer with dynamic ftrace
     syscall tracepoint
     irqsoff & preemptirqsoff (which use CALLER_ADDRx)
and also verified with in-kernel tests, FTRACE_SELFTEST, FTRACE_STARTUP_TEST
and EVENT_TRACE_TEST_SYSCALLS.

Prerequisites are:
 * "arm64: Add regs_return_value() in syscall.h"
 * "arm64: make a single hook to syscall_trace() for all syscall features" patch

Please be careful:
* elf.h on cross-build host must have AArch64 definitions, EM_AARCH64 and
  R_AARCH64_ABS64, to compile recordmcount utility. See [4/6].
  [4/6] also gets warnings from checkpatch, but they are based on the
  original's coding style.
* This patch may conflict with my audit patch because both changes the same
  location in syscall_trace(). I expect the functions are called in this
  order:
  On entry,
     * tracehook_report_syscall(ENTER)
     * trace_sys_enter()
     * audit_syscall_entry()
  On exit,
     * audit_sysscall_exit()
     * trace_sys_exit()
     * tracehook_report_syscall(EXIT) 

Changes from v1 to v2:
* splitted one patch into some pieces for easier review
  (especially function tracer + dynamic ftrace + CALLER_ADDRx)
* put return_address() in a separate file
* renamed __mcount to _mcount (it was my mistake)
* changed stackframe handling to get parent's frame pointer
* removed ARCH_SUPPORTS_FTRACE_OPS
* switched to "hotpatch" interfaces from Huawai
* revised descriptions in comments

Changes from v2 to v3:
* optimized register usages in asm (by not saving x0, x1, and x2)
* removed "fault protection" code in prepare_ftrace_return()
* rewrote ftrace_modify_code() using "hotpatch" interfaces
* revised descriptions in comments

Changes from v3 to v4:
* removed unnecessary "#ifdef" [1,2/7]
* changed stack depth from 48B to 16B in mcount()/ftrace_caller() (a bug) [1/7]
* changed MCOUNT_INSN_SIZE to AARCH64_INSN_SIZE [1,7/7]
* added a guard againt TIF_SYSCALL_TRACEPOINT [5/7]
* corrected the second argument passed to trace_sys_exit() (a bug) [5/7]
* aligned with the change in "arm64: make a single hook to syscall_trace()
  for all syscall features" v2 [5/7]

Chnages from v4 to v5:
* improved the description of stack layout [1/7]
* aligned with the change in "arm64: make a single hook to syscall_trace()
  for all syscall features" v3 [5/7]

AKASHI Takahiro (7):
  arm64: Add ftrace support
  arm64: ftrace: Add dynamic ftrace support
  arm64: ftrace: Add CALLER_ADDRx macros
  ftrace: Add arm64 support to recordmcount
  arm64: ftrace: Add system call tracepoint
  arm64: Add 'notrace' attribute to unwind_frame() for ftrace
  arm64: add __ASSEMBLY__ in asm/insn.h

 arch/arm64/Kconfig                 |    6 +
 arch/arm64/include/asm/ftrace.h    |   52 +++++++++
 arch/arm64/include/asm/insn.h      |    2 +
 arch/arm64/include/asm/syscall.h   |    1 +
 arch/arm64/include/asm/unistd.h    |    2 +
 arch/arm64/kernel/Makefile         |    7 +-
 arch/arm64/kernel/arm64ksyms.c     |    4 +
 arch/arm64/kernel/entry-ftrace.S   |  217 ++++++++++++++++++++++++++++++++++++
 arch/arm64/kernel/ftrace.c         |  177 +++++++++++++++++++++++++++++
 arch/arm64/kernel/ptrace.c         |   52 +++++----
 arch/arm64/kernel/return_address.c |   55 +++++++++
 arch/arm64/kernel/stacktrace.c     |    2 +-
 scripts/recordmcount.c             |    4 +
 scripts/recordmcount.pl            |    5 +
 14 files changed, 562 insertions(+), 24 deletions(-)
 create mode 100644 arch/arm64/include/asm/ftrace.h
 create mode 100644 arch/arm64/kernel/entry-ftrace.S
 create mode 100644 arch/arm64/kernel/ftrace.c
 create mode 100644 arch/arm64/kernel/return_address.c

-- 
1.7.9.5

^ permalink raw reply	[flat|nested] 235+ messages in thread

* [PATCH v5 1/7] arm64: Add ftrace support
  2014-02-28  5:18       ` AKASHI Takahiro
@ 2014-02-28  5:18         ` AKASHI Takahiro
  -1 siblings, 0 replies; 235+ messages in thread
From: AKASHI Takahiro @ 2014-02-28  5:18 UTC (permalink / raw)
  To: rostedt, fweisbec, mingo, catalin.marinas, will.deacon, tim.bird
  Cc: gkulkarni, dsaxena, arndb, linux-arm-kernel, linaro-kernel,
	linux-kernel, AKASHI Takahiro

This patch implements arm64 specific part to support function tracers,
such as function (CONFIG_FUNCTION_TRACER), function_graph
(CONFIG_FUNCTION_GRAPH_TRACER) and function profiler
(CONFIG_FUNCTION_PROFILER).

With 'function' tracer, all the functions in the kernel are traced with
timestamps in ${sysfs}/tracing/trace. If function_graph tracer is
specified, call graph is generated.

The kernel must be compiled with -pg option so that _mcount() is inserted
at the beginning of functions. This function is called on every function's
entry as long as tracing is enabled.
In addition, function_graph tracer also needs to be able to probe function's
exit. ftrace_graph_caller() & return_to_handler do this by faking link
register's value to intercept function's return path.

More details on architecture specific requirements are described in
Documentation/trace/ftrace-design.txt.

Reviewed-by: Ganapatrao Kulkarni <ganapatrao.kulkarni@cavium.com>
Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
---
 arch/arm64/Kconfig               |    2 +
 arch/arm64/include/asm/ftrace.h  |   23 +++++
 arch/arm64/kernel/Makefile       |    4 +
 arch/arm64/kernel/arm64ksyms.c   |    4 +
 arch/arm64/kernel/entry-ftrace.S |  174 ++++++++++++++++++++++++++++++++++++++
 arch/arm64/kernel/ftrace.c       |   64 ++++++++++++++
 6 files changed, 271 insertions(+)
 create mode 100644 arch/arm64/include/asm/ftrace.h
 create mode 100644 arch/arm64/kernel/entry-ftrace.S
 create mode 100644 arch/arm64/kernel/ftrace.c

diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 27bbcfc..5783641 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -33,6 +33,8 @@ config ARM64
 	select HAVE_DMA_ATTRS
 	select HAVE_DMA_CONTIGUOUS
 	select HAVE_EFFICIENT_UNALIGNED_ACCESS
+	select HAVE_FUNCTION_TRACER
+	select HAVE_FUNCTION_GRAPH_TRACER
 	select HAVE_GENERIC_DMA_COHERENT
 	select HAVE_HW_BREAKPOINT if PERF_EVENTS
 	select HAVE_MEMBLOCK
diff --git a/arch/arm64/include/asm/ftrace.h b/arch/arm64/include/asm/ftrace.h
new file mode 100644
index 0000000..58ea595
--- /dev/null
+++ b/arch/arm64/include/asm/ftrace.h
@@ -0,0 +1,23 @@
+/*
+ * arch/arm64/include/asm/ftrace.h
+ *
+ * Copyright (C) 2013 Linaro Limited
+ * Author: AKASHI Takahiro <takahiro.akashi@linaro.org>
+ *
+ * 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.
+ */
+#ifndef __ASM_FTRACE_H
+#define __ASM_FTRACE_H
+
+#include <asm/insn.h>
+
+#define MCOUNT_ADDR		((unsigned long)_mcount)
+#define MCOUNT_INSN_SIZE	AARCH64_INSN_SIZE
+
+#ifndef __ASSEMBLY__
+extern void _mcount(unsigned long);
+#endif /* __ASSEMBLY__ */
+
+#endif /* __ASM_FTRACE_H */
diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile
index 2d4554b..ac67fd0 100644
--- a/arch/arm64/kernel/Makefile
+++ b/arch/arm64/kernel/Makefile
@@ -5,6 +5,9 @@
 CPPFLAGS_vmlinux.lds	:= -DTEXT_OFFSET=$(TEXT_OFFSET)
 AFLAGS_head.o		:= -DTEXT_OFFSET=$(TEXT_OFFSET)
 
+CFLAGS_REMOVE_ftrace.o = -pg
+CFLAGS_REMOVE_insn.o = -pg
+
 # Object file lists.
 arm64-obj-y		:= cputable.o debug-monitors.o entry.o irq.o fpsimd.o	\
 			   entry-fpsimd.o process.o ptrace.o setup.o signal.o	\
@@ -13,6 +16,7 @@ arm64-obj-y		:= cputable.o debug-monitors.o entry.o irq.o fpsimd.o	\
 
 arm64-obj-$(CONFIG_COMPAT)		+= sys32.o kuser32.o signal32.o 	\
 					   sys_compat.o
+arm64-obj-$(CONFIG_FUNCTION_TRACER)	+= ftrace.o entry-ftrace.o
 arm64-obj-$(CONFIG_MODULES)		+= arm64ksyms.o module.o
 arm64-obj-$(CONFIG_SMP)			+= smp.o smp_spin_table.o
 arm64-obj-$(CONFIG_HW_PERF_EVENTS)	+= perf_event.o
diff --git a/arch/arm64/kernel/arm64ksyms.c b/arch/arm64/kernel/arm64ksyms.c
index 338b568..7f0512f 100644
--- a/arch/arm64/kernel/arm64ksyms.c
+++ b/arch/arm64/kernel/arm64ksyms.c
@@ -56,3 +56,7 @@ EXPORT_SYMBOL(clear_bit);
 EXPORT_SYMBOL(test_and_clear_bit);
 EXPORT_SYMBOL(change_bit);
 EXPORT_SYMBOL(test_and_change_bit);
+
+#ifdef CONFIG_FUNCTION_TRACER
+EXPORT_SYMBOL(_mcount);
+#endif
diff --git a/arch/arm64/kernel/entry-ftrace.S b/arch/arm64/kernel/entry-ftrace.S
new file mode 100644
index 0000000..0e5b8b0
--- /dev/null
+++ b/arch/arm64/kernel/entry-ftrace.S
@@ -0,0 +1,174 @@
+/*
+ * arch/arm64/kernel/entry-ftrace.S
+ *
+ * Copyright (C) 2013 Linaro Limited
+ * Author: AKASHI Takahiro <takahiro.akashi@linaro.org>
+ *
+ * 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 <linux/linkage.h>
+#include <asm/ftrace.h>
+#include <asm/insn.h>
+
+/*
+ * Gcc with -pg will put the following code in the beginning of each function:
+ *      mov x0, x30
+ *      bl _mcount
+ *	[function's body ...]
+ * "bl _mcount" may be replaced to "bl ftrace_caller" or NOP if dynamic
+ * ftrace is enabled.
+ *
+ * Please note that x0 as an argument will not be used here because we can
+ * get lr(x30) of instrumented function at any time by winding up call stack
+ * as long as the kernel is compiled without -fomit-frame-pointer.
+ * (or CONFIG_FRAME_POINTER, this is forced on arm64)
+ *
+ * stack layout after mcount_enter in _mcount():
+ *
+ * current sp =>     0:+-----+
+ *		       | x29 | -> instrumented function's fp
+ *		       +-----+
+ *		       | x30 | -> _mcount()'s lr (= instrumented function's pc)
+ * old sp     =>   +16:+-----+
+ * when instrumented   |     |
+ * function calls      | ... |
+ * _mcount()	       |     |
+ *		       |     |
+ * instrumented => +xx:+-----+
+ * function's fp       | x29 | -> parent's fp
+ *		       +-----+
+ *		       | x30 | -> instrumented function's lr (= parent's pc)
+ *		       +-----+
+ *		       | ... |
+ */
+
+	.macro mcount_enter
+	stp	x29, x30, [sp, #-16]!
+	.endm
+
+	.macro mcount_exit
+	ldp	x29, x30, [sp], #16
+	ret
+	.endm
+
+	.macro mcount_adjust_addr rd, rn
+	sub	\rd, \rn, #AARCH64_INSN_SIZE
+	.endm
+
+	/* for instrumented function's parent */
+	.macro mcount_get_parent_fp reg
+	ldr	\reg, [sp]
+	ldr	\reg, [\reg]
+	.endm
+
+	/* for instrumented function */
+	.macro mcount_get_pc0 reg
+	mcount_adjust_addr	\reg, x30
+	.endm
+
+	.macro mcount_get_pc reg
+	ldr	\reg, [sp, #8]
+	mcount_adjust_addr	\reg, \reg
+	.endm
+
+	.macro mcount_get_lr reg
+	ldr	\reg, [sp]
+	ldr	\reg, [\reg, #8]
+	mcount_adjust_addr	\reg, \reg
+	.endm
+
+	.macro mcount_get_lr_addr reg
+	ldr	\reg, [sp]
+	add	\reg, \reg, #8
+	.endm
+
+/*
+ * void _mcount(unsigned long return_address)
+ * @return_address: return address to instrumented function
+ *
+ * This function makes calls, if enabled, to:
+ *     - tracer function to probe instrumented function's entry,
+ *     - ftrace_graph_caller to set up an exit hook
+ */
+ENTRY(_mcount)
+#ifdef CONFIG_HAVE_FUNCTION_TRACE_MCOUNT_TEST
+	ldr	x0, =ftrace_trace_stop
+	ldr	x0, [x0]		// if ftrace_trace_stop
+	ret				//   return;
+#endif
+	mcount_enter
+
+	ldr	x0, =ftrace_trace_function
+	ldr	x2, [x0]
+	adr	x0, ftrace_stub
+	cmp	x0, x2			// if (ftrace_trace_function
+	b.eq	skip_ftrace_call	//     != ftrace_stub) {
+
+	mcount_get_pc	x0		//       function's pc
+	mcount_get_lr	x1		//       function's lr (= parent's pc)
+	blr	x2			//   (*ftrace_trace_function)(pc, lr);
+
+#ifndef CONFIG_FUNCTION_GRAPH_TRACER
+skip_ftrace_call:			//   return;
+	mcount_exit			// }
+#else
+	mcount_exit			//   return;
+					// }
+skip_ftrace_call:
+	ldr	x1, =ftrace_graph_return
+	ldr	x2, [x1]		//   if ((ftrace_graph_return
+	cmp	x0, x2			//        != ftrace_stub)
+	b.ne	ftrace_graph_caller
+
+	ldr	x1, =ftrace_graph_entry	//     || (ftrace_graph_entry
+	ldr	x2, [x1]		//        != ftrace_graph_entry_stub))
+	ldr	x0, =ftrace_graph_entry_stub
+	cmp	x0, x2
+	b.ne	ftrace_graph_caller	//     ftrace_graph_caller();
+
+	mcount_exit
+#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
+ENDPROC(_mcount)
+
+ENTRY(ftrace_stub)
+	ret
+ENDPROC(ftrace_stub)
+
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+/*
+ * void ftrace_graph_caller(void)
+ *
+ * Called from _mcount() or ftrace_caller() when function_graph tracer is
+ * selected.
+ * This function w/ prepare_ftrace_return() fakes link register's value on
+ * the call stack in order to intercept instrumented function's return path
+ * and run return_to_handler() later on its exit.
+ */
+ENTRY(ftrace_graph_caller)
+	mcount_get_lr_addr	  x0	//     pointer to function's saved lr
+	mcount_get_pc		  x1	//     function's pc
+	mcount_get_parent_fp	  x2	//     parent's fp
+	bl	prepare_ftrace_return	// prepare_ftrace_return(&lr, pc, fp)
+
+	mcount_exit
+ENDPROC(ftrace_graph_caller)
+
+/*
+ * void return_to_handler(void)
+ *
+ * Run ftrace_return_to_handler() before going back to parent.
+ * @fp is checked against the value passed by ftrace_graph_caller()
+ * only when CONFIG_FUNCTION_GRAPH_FP_TEST is enabled.
+ */
+	.global return_to_handler
+return_to_handler:
+	str	x0, [sp, #-16]!
+	mov	x0, x29			//     parent's fp
+	bl	ftrace_return_to_handler// addr = ftrace_return_to_hander(fp);
+	mov	x30, x0			// restore the original return address
+	ldr	x0, [sp], #16
+	ret
+#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
diff --git a/arch/arm64/kernel/ftrace.c b/arch/arm64/kernel/ftrace.c
new file mode 100644
index 0000000..a559ab8
--- /dev/null
+++ b/arch/arm64/kernel/ftrace.c
@@ -0,0 +1,64 @@
+/*
+ * arch/arm64/kernel/ftrace.c
+ *
+ * Copyright (C) 2013 Linaro Limited
+ * Author: AKASHI Takahiro <takahiro.akashi@linaro.org>
+ *
+ * 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 <linux/ftrace.h>
+#include <linux/swab.h>
+#include <linux/uaccess.h>
+
+#include <asm/cacheflush.h>
+#include <asm/ftrace.h>
+#include <asm/insn.h>
+
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+/*
+ * function_graph tracer expects ftrace_return_to_handler() to be called
+ * on the way back to parent. For this purpose, this function is called
+ * in _mcount() or ftrace_caller() to replace return address (*parent) on
+ * the call stack to return_to_handler.
+ *
+ * Note that @frame_pointer is used only for sanity check later.
+ */
+void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr,
+			   unsigned long frame_pointer)
+{
+	unsigned long return_hooker = (unsigned long)&return_to_handler;
+	unsigned long old;
+	struct ftrace_graph_ent trace;
+	int err;
+
+	if (unlikely(atomic_read(&current->tracing_graph_pause)))
+		return;
+
+	/*
+	 * Note:
+	 * No protection against faulting at *parent, which may be seen
+	 * on other archs. It's unlikely on AArch64.
+	 */
+	old = *parent;
+	*parent = return_hooker;
+
+	trace.func = self_addr;
+	trace.depth = current->curr_ret_stack + 1;
+
+	/* Only trace if the calling function expects to */
+	if (!ftrace_graph_entry(&trace)) {
+		*parent = old;
+		return;
+	}
+
+	err = ftrace_push_return_trace(old, self_addr, &trace.depth,
+				       frame_pointer);
+	if (err == -EBUSY) {
+		*parent = old;
+		return;
+	}
+}
+#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 235+ messages in thread

* [PATCH v5 1/7] arm64: Add ftrace support
@ 2014-02-28  5:18         ` AKASHI Takahiro
  0 siblings, 0 replies; 235+ messages in thread
From: AKASHI Takahiro @ 2014-02-28  5:18 UTC (permalink / raw)
  To: linux-arm-kernel

This patch implements arm64 specific part to support function tracers,
such as function (CONFIG_FUNCTION_TRACER), function_graph
(CONFIG_FUNCTION_GRAPH_TRACER) and function profiler
(CONFIG_FUNCTION_PROFILER).

With 'function' tracer, all the functions in the kernel are traced with
timestamps in ${sysfs}/tracing/trace. If function_graph tracer is
specified, call graph is generated.

The kernel must be compiled with -pg option so that _mcount() is inserted
at the beginning of functions. This function is called on every function's
entry as long as tracing is enabled.
In addition, function_graph tracer also needs to be able to probe function's
exit. ftrace_graph_caller() & return_to_handler do this by faking link
register's value to intercept function's return path.

More details on architecture specific requirements are described in
Documentation/trace/ftrace-design.txt.

Reviewed-by: Ganapatrao Kulkarni <ganapatrao.kulkarni@cavium.com>
Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
---
 arch/arm64/Kconfig               |    2 +
 arch/arm64/include/asm/ftrace.h  |   23 +++++
 arch/arm64/kernel/Makefile       |    4 +
 arch/arm64/kernel/arm64ksyms.c   |    4 +
 arch/arm64/kernel/entry-ftrace.S |  174 ++++++++++++++++++++++++++++++++++++++
 arch/arm64/kernel/ftrace.c       |   64 ++++++++++++++
 6 files changed, 271 insertions(+)
 create mode 100644 arch/arm64/include/asm/ftrace.h
 create mode 100644 arch/arm64/kernel/entry-ftrace.S
 create mode 100644 arch/arm64/kernel/ftrace.c

diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 27bbcfc..5783641 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -33,6 +33,8 @@ config ARM64
 	select HAVE_DMA_ATTRS
 	select HAVE_DMA_CONTIGUOUS
 	select HAVE_EFFICIENT_UNALIGNED_ACCESS
+	select HAVE_FUNCTION_TRACER
+	select HAVE_FUNCTION_GRAPH_TRACER
 	select HAVE_GENERIC_DMA_COHERENT
 	select HAVE_HW_BREAKPOINT if PERF_EVENTS
 	select HAVE_MEMBLOCK
diff --git a/arch/arm64/include/asm/ftrace.h b/arch/arm64/include/asm/ftrace.h
new file mode 100644
index 0000000..58ea595
--- /dev/null
+++ b/arch/arm64/include/asm/ftrace.h
@@ -0,0 +1,23 @@
+/*
+ * arch/arm64/include/asm/ftrace.h
+ *
+ * Copyright (C) 2013 Linaro Limited
+ * Author: AKASHI Takahiro <takahiro.akashi@linaro.org>
+ *
+ * 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.
+ */
+#ifndef __ASM_FTRACE_H
+#define __ASM_FTRACE_H
+
+#include <asm/insn.h>
+
+#define MCOUNT_ADDR		((unsigned long)_mcount)
+#define MCOUNT_INSN_SIZE	AARCH64_INSN_SIZE
+
+#ifndef __ASSEMBLY__
+extern void _mcount(unsigned long);
+#endif /* __ASSEMBLY__ */
+
+#endif /* __ASM_FTRACE_H */
diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile
index 2d4554b..ac67fd0 100644
--- a/arch/arm64/kernel/Makefile
+++ b/arch/arm64/kernel/Makefile
@@ -5,6 +5,9 @@
 CPPFLAGS_vmlinux.lds	:= -DTEXT_OFFSET=$(TEXT_OFFSET)
 AFLAGS_head.o		:= -DTEXT_OFFSET=$(TEXT_OFFSET)
 
+CFLAGS_REMOVE_ftrace.o = -pg
+CFLAGS_REMOVE_insn.o = -pg
+
 # Object file lists.
 arm64-obj-y		:= cputable.o debug-monitors.o entry.o irq.o fpsimd.o	\
 			   entry-fpsimd.o process.o ptrace.o setup.o signal.o	\
@@ -13,6 +16,7 @@ arm64-obj-y		:= cputable.o debug-monitors.o entry.o irq.o fpsimd.o	\
 
 arm64-obj-$(CONFIG_COMPAT)		+= sys32.o kuser32.o signal32.o 	\
 					   sys_compat.o
+arm64-obj-$(CONFIG_FUNCTION_TRACER)	+= ftrace.o entry-ftrace.o
 arm64-obj-$(CONFIG_MODULES)		+= arm64ksyms.o module.o
 arm64-obj-$(CONFIG_SMP)			+= smp.o smp_spin_table.o
 arm64-obj-$(CONFIG_HW_PERF_EVENTS)	+= perf_event.o
diff --git a/arch/arm64/kernel/arm64ksyms.c b/arch/arm64/kernel/arm64ksyms.c
index 338b568..7f0512f 100644
--- a/arch/arm64/kernel/arm64ksyms.c
+++ b/arch/arm64/kernel/arm64ksyms.c
@@ -56,3 +56,7 @@ EXPORT_SYMBOL(clear_bit);
 EXPORT_SYMBOL(test_and_clear_bit);
 EXPORT_SYMBOL(change_bit);
 EXPORT_SYMBOL(test_and_change_bit);
+
+#ifdef CONFIG_FUNCTION_TRACER
+EXPORT_SYMBOL(_mcount);
+#endif
diff --git a/arch/arm64/kernel/entry-ftrace.S b/arch/arm64/kernel/entry-ftrace.S
new file mode 100644
index 0000000..0e5b8b0
--- /dev/null
+++ b/arch/arm64/kernel/entry-ftrace.S
@@ -0,0 +1,174 @@
+/*
+ * arch/arm64/kernel/entry-ftrace.S
+ *
+ * Copyright (C) 2013 Linaro Limited
+ * Author: AKASHI Takahiro <takahiro.akashi@linaro.org>
+ *
+ * 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 <linux/linkage.h>
+#include <asm/ftrace.h>
+#include <asm/insn.h>
+
+/*
+ * Gcc with -pg will put the following code in the beginning of each function:
+ *      mov x0, x30
+ *      bl _mcount
+ *	[function's body ...]
+ * "bl _mcount" may be replaced to "bl ftrace_caller" or NOP if dynamic
+ * ftrace is enabled.
+ *
+ * Please note that x0 as an argument will not be used here because we can
+ * get lr(x30) of instrumented function at any time by winding up call stack
+ * as long as the kernel is compiled without -fomit-frame-pointer.
+ * (or CONFIG_FRAME_POINTER, this is forced on arm64)
+ *
+ * stack layout after mcount_enter in _mcount():
+ *
+ * current sp =>     0:+-----+
+ *		       | x29 | -> instrumented function's fp
+ *		       +-----+
+ *		       | x30 | -> _mcount()'s lr (= instrumented function's pc)
+ * old sp     =>   +16:+-----+
+ * when instrumented   |     |
+ * function calls      | ... |
+ * _mcount()	       |     |
+ *		       |     |
+ * instrumented => +xx:+-----+
+ * function's fp       | x29 | -> parent's fp
+ *		       +-----+
+ *		       | x30 | -> instrumented function's lr (= parent's pc)
+ *		       +-----+
+ *		       | ... |
+ */
+
+	.macro mcount_enter
+	stp	x29, x30, [sp, #-16]!
+	.endm
+
+	.macro mcount_exit
+	ldp	x29, x30, [sp], #16
+	ret
+	.endm
+
+	.macro mcount_adjust_addr rd, rn
+	sub	\rd, \rn, #AARCH64_INSN_SIZE
+	.endm
+
+	/* for instrumented function's parent */
+	.macro mcount_get_parent_fp reg
+	ldr	\reg, [sp]
+	ldr	\reg, [\reg]
+	.endm
+
+	/* for instrumented function */
+	.macro mcount_get_pc0 reg
+	mcount_adjust_addr	\reg, x30
+	.endm
+
+	.macro mcount_get_pc reg
+	ldr	\reg, [sp, #8]
+	mcount_adjust_addr	\reg, \reg
+	.endm
+
+	.macro mcount_get_lr reg
+	ldr	\reg, [sp]
+	ldr	\reg, [\reg, #8]
+	mcount_adjust_addr	\reg, \reg
+	.endm
+
+	.macro mcount_get_lr_addr reg
+	ldr	\reg, [sp]
+	add	\reg, \reg, #8
+	.endm
+
+/*
+ * void _mcount(unsigned long return_address)
+ * @return_address: return address to instrumented function
+ *
+ * This function makes calls, if enabled, to:
+ *     - tracer function to probe instrumented function's entry,
+ *     - ftrace_graph_caller to set up an exit hook
+ */
+ENTRY(_mcount)
+#ifdef CONFIG_HAVE_FUNCTION_TRACE_MCOUNT_TEST
+	ldr	x0, =ftrace_trace_stop
+	ldr	x0, [x0]		// if ftrace_trace_stop
+	ret				//   return;
+#endif
+	mcount_enter
+
+	ldr	x0, =ftrace_trace_function
+	ldr	x2, [x0]
+	adr	x0, ftrace_stub
+	cmp	x0, x2			// if (ftrace_trace_function
+	b.eq	skip_ftrace_call	//     != ftrace_stub) {
+
+	mcount_get_pc	x0		//       function's pc
+	mcount_get_lr	x1		//       function's lr (= parent's pc)
+	blr	x2			//   (*ftrace_trace_function)(pc, lr);
+
+#ifndef CONFIG_FUNCTION_GRAPH_TRACER
+skip_ftrace_call:			//   return;
+	mcount_exit			// }
+#else
+	mcount_exit			//   return;
+					// }
+skip_ftrace_call:
+	ldr	x1, =ftrace_graph_return
+	ldr	x2, [x1]		//   if ((ftrace_graph_return
+	cmp	x0, x2			//        != ftrace_stub)
+	b.ne	ftrace_graph_caller
+
+	ldr	x1, =ftrace_graph_entry	//     || (ftrace_graph_entry
+	ldr	x2, [x1]		//        != ftrace_graph_entry_stub))
+	ldr	x0, =ftrace_graph_entry_stub
+	cmp	x0, x2
+	b.ne	ftrace_graph_caller	//     ftrace_graph_caller();
+
+	mcount_exit
+#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
+ENDPROC(_mcount)
+
+ENTRY(ftrace_stub)
+	ret
+ENDPROC(ftrace_stub)
+
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+/*
+ * void ftrace_graph_caller(void)
+ *
+ * Called from _mcount() or ftrace_caller() when function_graph tracer is
+ * selected.
+ * This function w/ prepare_ftrace_return() fakes link register's value on
+ * the call stack in order to intercept instrumented function's return path
+ * and run return_to_handler() later on its exit.
+ */
+ENTRY(ftrace_graph_caller)
+	mcount_get_lr_addr	  x0	//     pointer to function's saved lr
+	mcount_get_pc		  x1	//     function's pc
+	mcount_get_parent_fp	  x2	//     parent's fp
+	bl	prepare_ftrace_return	// prepare_ftrace_return(&lr, pc, fp)
+
+	mcount_exit
+ENDPROC(ftrace_graph_caller)
+
+/*
+ * void return_to_handler(void)
+ *
+ * Run ftrace_return_to_handler() before going back to parent.
+ * @fp is checked against the value passed by ftrace_graph_caller()
+ * only when CONFIG_FUNCTION_GRAPH_FP_TEST is enabled.
+ */
+	.global return_to_handler
+return_to_handler:
+	str	x0, [sp, #-16]!
+	mov	x0, x29			//     parent's fp
+	bl	ftrace_return_to_handler// addr = ftrace_return_to_hander(fp);
+	mov	x30, x0			// restore the original return address
+	ldr	x0, [sp], #16
+	ret
+#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
diff --git a/arch/arm64/kernel/ftrace.c b/arch/arm64/kernel/ftrace.c
new file mode 100644
index 0000000..a559ab8
--- /dev/null
+++ b/arch/arm64/kernel/ftrace.c
@@ -0,0 +1,64 @@
+/*
+ * arch/arm64/kernel/ftrace.c
+ *
+ * Copyright (C) 2013 Linaro Limited
+ * Author: AKASHI Takahiro <takahiro.akashi@linaro.org>
+ *
+ * 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 <linux/ftrace.h>
+#include <linux/swab.h>
+#include <linux/uaccess.h>
+
+#include <asm/cacheflush.h>
+#include <asm/ftrace.h>
+#include <asm/insn.h>
+
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+/*
+ * function_graph tracer expects ftrace_return_to_handler() to be called
+ * on the way back to parent. For this purpose, this function is called
+ * in _mcount() or ftrace_caller() to replace return address (*parent) on
+ * the call stack to return_to_handler.
+ *
+ * Note that @frame_pointer is used only for sanity check later.
+ */
+void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr,
+			   unsigned long frame_pointer)
+{
+	unsigned long return_hooker = (unsigned long)&return_to_handler;
+	unsigned long old;
+	struct ftrace_graph_ent trace;
+	int err;
+
+	if (unlikely(atomic_read(&current->tracing_graph_pause)))
+		return;
+
+	/*
+	 * Note:
+	 * No protection against faulting at *parent, which may be seen
+	 * on other archs. It's unlikely on AArch64.
+	 */
+	old = *parent;
+	*parent = return_hooker;
+
+	trace.func = self_addr;
+	trace.depth = current->curr_ret_stack + 1;
+
+	/* Only trace if the calling function expects to */
+	if (!ftrace_graph_entry(&trace)) {
+		*parent = old;
+		return;
+	}
+
+	err = ftrace_push_return_trace(old, self_addr, &trace.depth,
+				       frame_pointer);
+	if (err == -EBUSY) {
+		*parent = old;
+		return;
+	}
+}
+#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 235+ messages in thread

* [PATCH v5 2/7] arm64: ftrace: Add dynamic ftrace support
  2014-02-28  5:18       ` AKASHI Takahiro
@ 2014-02-28  5:18         ` AKASHI Takahiro
  -1 siblings, 0 replies; 235+ messages in thread
From: AKASHI Takahiro @ 2014-02-28  5:18 UTC (permalink / raw)
  To: rostedt, fweisbec, mingo, catalin.marinas, will.deacon, tim.bird
  Cc: gkulkarni, dsaxena, arndb, linux-arm-kernel, linaro-kernel,
	linux-kernel, AKASHI Takahiro

This patch allows "dynamic ftrace" if CONFIG_DYNAMIC_FTRACE is enabled.
Here we can turn on and off tracing dynamically per-function base.

On arm64, this is done by patching single branch instruction to _mcount()
inserted by gcc -pg option. The branch is replaced to NOP initially at
kernel start up, and later on, NOP to branch to ftrace_caller() when
enabled or branch to NOP when disabled.
Please note that ftrace_caller() is a counterpart of _mcount() in case of
'static' ftrace.

More details on architecture specific requirements are described in
Documentation/trace/ftrace-design.txt.

Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
---
 arch/arm64/Kconfig               |    1 +
 arch/arm64/include/asm/ftrace.h  |   15 +++++
 arch/arm64/kernel/entry-ftrace.S |   43 +++++++++++++++
 arch/arm64/kernel/ftrace.c       |  113 ++++++++++++++++++++++++++++++++++++++
 4 files changed, 172 insertions(+)

diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 5783641..b176bc0 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -32,6 +32,7 @@ config ARM64
 	select HAVE_DMA_API_DEBUG
 	select HAVE_DMA_ATTRS
 	select HAVE_DMA_CONTIGUOUS
+	select HAVE_DYNAMIC_FTRACE
 	select HAVE_EFFICIENT_UNALIGNED_ACCESS
 	select HAVE_FUNCTION_TRACER
 	select HAVE_FUNCTION_GRAPH_TRACER
diff --git a/arch/arm64/include/asm/ftrace.h b/arch/arm64/include/asm/ftrace.h
index 58ea595..ed5c448 100644
--- a/arch/arm64/include/asm/ftrace.h
+++ b/arch/arm64/include/asm/ftrace.h
@@ -18,6 +18,21 @@
 
 #ifndef __ASSEMBLY__
 extern void _mcount(unsigned long);
+
+struct dyn_arch_ftrace {
+	/* No extra data needed for arm64 */
+};
+
+extern unsigned long ftrace_graph_call;
+
+static inline unsigned long ftrace_call_adjust(unsigned long addr)
+{
+	/*
+	 * addr is the address of the mcount call instruction.
+	 * recordmcount does the necessary offset calculation.
+	 */
+	return addr;
+}
 #endif /* __ASSEMBLY__ */
 
 #endif /* __ASM_FTRACE_H */
diff --git a/arch/arm64/kernel/entry-ftrace.S b/arch/arm64/kernel/entry-ftrace.S
index 0e5b8b0..c012cf0 100644
--- a/arch/arm64/kernel/entry-ftrace.S
+++ b/arch/arm64/kernel/entry-ftrace.S
@@ -85,6 +85,7 @@
 	add	\reg, \reg, #8
 	.endm
 
+#ifndef CONFIG_DYNAMIC_FTRACE
 /*
  * void _mcount(unsigned long return_address)
  * @return_address: return address to instrumented function
@@ -133,6 +134,48 @@ skip_ftrace_call:
 #endif /* CONFIG_FUNCTION_GRAPH_TRACER */
 ENDPROC(_mcount)
 
+#else /* CONFIG_DYNAMIC_FTRACE */
+/*
+ * _mcount() is used to build the kernel with -pg option, but all the branch
+ * instructions to _mcount() are replaced to NOP initially at kernel start up,
+ * and later on, NOP to branch to ftrace_caller() when enabled or branch to
+ * NOP when disabled per-function base.
+ */
+ENTRY(_mcount)
+	ret
+ENDPROC(_mcount)
+
+/*
+ * void ftrace_caller(unsigned long return_address)
+ * @return_address: return address to instrumented function
+ *
+ * This function is a counterpart of _mcount() in 'static' ftrace, and
+ * makes calls to:
+ *     - tracer function to probe instrumented function's entry,
+ *     - ftrace_graph_caller to set up an exit hook
+ */
+ENTRY(ftrace_caller)
+	mcount_enter
+
+	mcount_get_pc0	x0		//     function's pc
+	mcount_get_lr	x1		//     function's lr
+
+	.global ftrace_call
+ftrace_call:				// tracer(pc, lr);
+	nop				// This will be replaced with "bl xxx"
+					// where xxx can be any kind of tracer.
+
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+	.global ftrace_graph_call
+ftrace_graph_call:			// ftrace_graph_caller();
+	nop				// If enabled, this will be replaced
+					// "b ftrace_graph_caller"
+#endif
+
+	mcount_exit
+ENDPROC(ftrace_caller)
+#endif /* CONFIG_DYNAMIC_FTRACE */
+
 ENTRY(ftrace_stub)
 	ret
 ENDPROC(ftrace_stub)
diff --git a/arch/arm64/kernel/ftrace.c b/arch/arm64/kernel/ftrace.c
index a559ab8..8c26476 100644
--- a/arch/arm64/kernel/ftrace.c
+++ b/arch/arm64/kernel/ftrace.c
@@ -17,6 +17,89 @@
 #include <asm/ftrace.h>
 #include <asm/insn.h>
 
+#ifdef CONFIG_DYNAMIC_FTRACE
+/*
+ * Replace a single instruction, which may be a branch or NOP.
+ * If @validate == true, a replaced instruction is checked against 'old'.
+ */
+static int ftrace_modify_code(unsigned long pc, unsigned int old,
+			      unsigned int new, bool validate)
+{
+	unsigned int replaced;
+
+	/*
+	 * Note:
+	 * Due to modules and __init, code can disappear and change,
+	 * we need to protect against faulting as well as code changing.
+	 * We do this by aarch64_insn_*() which use the probe_kernel_*().
+	 *
+	 * No lock is held here because all the modifications are run
+	 * through stop_machine().
+	 */
+	if (validate) {
+		if (aarch64_insn_read((void *)pc, &replaced))
+			return -EFAULT;
+
+		if (replaced != old)
+			return -EINVAL;
+	}
+	if (aarch64_insn_patch_text_nosync((void *)pc, new))
+		return -EPERM;
+
+	return 0;
+}
+
+/*
+ * Replace tracer function in ftrace_caller()
+ */
+int ftrace_update_ftrace_func(ftrace_func_t func)
+{
+	unsigned long pc;
+	unsigned int new;
+
+	pc = (unsigned long)&ftrace_call;
+	new = aarch64_insn_gen_branch_imm(pc, (unsigned long)func, true);
+
+	return ftrace_modify_code(pc, 0, new, false);
+}
+
+/*
+ * Turn on the call to ftrace_caller() in instrumented function
+ */
+int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
+{
+	unsigned long pc = rec->ip;
+	unsigned int old, new;
+
+	old = aarch64_insn_gen_nop();
+	new = aarch64_insn_gen_branch_imm(pc, addr, true);
+
+	return ftrace_modify_code(pc, old, new, true);
+}
+
+/*
+ * Turn off the call to ftrace_caller() in instrumented function
+ */
+int ftrace_make_nop(struct module *mod,
+		    struct dyn_ftrace *rec, unsigned long addr)
+{
+	unsigned long pc = rec->ip;
+	unsigned int old, new;
+
+	old = aarch64_insn_gen_branch_imm(pc, addr, true);
+	new = aarch64_insn_gen_nop();
+
+	return ftrace_modify_code(pc, old, new, true);
+}
+
+int __init ftrace_dyn_arch_init(void *data)
+{
+	*(unsigned long *)data = 0;
+
+	return 0;
+}
+#endif /* CONFIG_DYNAMIC_FTRACE */
+
 #ifdef CONFIG_FUNCTION_GRAPH_TRACER
 /*
  * function_graph tracer expects ftrace_return_to_handler() to be called
@@ -61,4 +144,34 @@ void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr,
 		return;
 	}
 }
+
+#ifdef CONFIG_DYNAMIC_FTRACE
+/*
+ * Turn on/off the call to ftrace_graph_caller() in ftrace_caller()
+ * depending on @enable.
+ */
+static int ftrace_modify_graph_caller(bool enable)
+{
+	unsigned long pc = (unsigned long)&ftrace_graph_call;
+	unsigned int branch, nop, old, new;
+
+	branch = aarch64_insn_gen_branch_imm(pc,
+			(unsigned long)ftrace_graph_caller, false);
+	nop = aarch64_insn_gen_nop();
+	old = enable ? nop : branch;
+	new = enable ? branch : nop;
+
+	return ftrace_modify_code(pc, old, new, true);
+}
+
+int ftrace_enable_ftrace_graph_caller(void)
+{
+	return ftrace_modify_graph_caller(true);
+}
+
+int ftrace_disable_ftrace_graph_caller(void)
+{
+	return ftrace_modify_graph_caller(false);
+}
+#endif /* CONFIG_DYNAMIC_FTRACE */
 #endif /* CONFIG_FUNCTION_GRAPH_TRACER */
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 235+ messages in thread

* [PATCH v5 2/7] arm64: ftrace: Add dynamic ftrace support
@ 2014-02-28  5:18         ` AKASHI Takahiro
  0 siblings, 0 replies; 235+ messages in thread
From: AKASHI Takahiro @ 2014-02-28  5:18 UTC (permalink / raw)
  To: linux-arm-kernel

This patch allows "dynamic ftrace" if CONFIG_DYNAMIC_FTRACE is enabled.
Here we can turn on and off tracing dynamically per-function base.

On arm64, this is done by patching single branch instruction to _mcount()
inserted by gcc -pg option. The branch is replaced to NOP initially at
kernel start up, and later on, NOP to branch to ftrace_caller() when
enabled or branch to NOP when disabled.
Please note that ftrace_caller() is a counterpart of _mcount() in case of
'static' ftrace.

More details on architecture specific requirements are described in
Documentation/trace/ftrace-design.txt.

Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
---
 arch/arm64/Kconfig               |    1 +
 arch/arm64/include/asm/ftrace.h  |   15 +++++
 arch/arm64/kernel/entry-ftrace.S |   43 +++++++++++++++
 arch/arm64/kernel/ftrace.c       |  113 ++++++++++++++++++++++++++++++++++++++
 4 files changed, 172 insertions(+)

diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 5783641..b176bc0 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -32,6 +32,7 @@ config ARM64
 	select HAVE_DMA_API_DEBUG
 	select HAVE_DMA_ATTRS
 	select HAVE_DMA_CONTIGUOUS
+	select HAVE_DYNAMIC_FTRACE
 	select HAVE_EFFICIENT_UNALIGNED_ACCESS
 	select HAVE_FUNCTION_TRACER
 	select HAVE_FUNCTION_GRAPH_TRACER
diff --git a/arch/arm64/include/asm/ftrace.h b/arch/arm64/include/asm/ftrace.h
index 58ea595..ed5c448 100644
--- a/arch/arm64/include/asm/ftrace.h
+++ b/arch/arm64/include/asm/ftrace.h
@@ -18,6 +18,21 @@
 
 #ifndef __ASSEMBLY__
 extern void _mcount(unsigned long);
+
+struct dyn_arch_ftrace {
+	/* No extra data needed for arm64 */
+};
+
+extern unsigned long ftrace_graph_call;
+
+static inline unsigned long ftrace_call_adjust(unsigned long addr)
+{
+	/*
+	 * addr is the address of the mcount call instruction.
+	 * recordmcount does the necessary offset calculation.
+	 */
+	return addr;
+}
 #endif /* __ASSEMBLY__ */
 
 #endif /* __ASM_FTRACE_H */
diff --git a/arch/arm64/kernel/entry-ftrace.S b/arch/arm64/kernel/entry-ftrace.S
index 0e5b8b0..c012cf0 100644
--- a/arch/arm64/kernel/entry-ftrace.S
+++ b/arch/arm64/kernel/entry-ftrace.S
@@ -85,6 +85,7 @@
 	add	\reg, \reg, #8
 	.endm
 
+#ifndef CONFIG_DYNAMIC_FTRACE
 /*
  * void _mcount(unsigned long return_address)
  * @return_address: return address to instrumented function
@@ -133,6 +134,48 @@ skip_ftrace_call:
 #endif /* CONFIG_FUNCTION_GRAPH_TRACER */
 ENDPROC(_mcount)
 
+#else /* CONFIG_DYNAMIC_FTRACE */
+/*
+ * _mcount() is used to build the kernel with -pg option, but all the branch
+ * instructions to _mcount() are replaced to NOP initially at kernel start up,
+ * and later on, NOP to branch to ftrace_caller() when enabled or branch to
+ * NOP when disabled per-function base.
+ */
+ENTRY(_mcount)
+	ret
+ENDPROC(_mcount)
+
+/*
+ * void ftrace_caller(unsigned long return_address)
+ * @return_address: return address to instrumented function
+ *
+ * This function is a counterpart of _mcount() in 'static' ftrace, and
+ * makes calls to:
+ *     - tracer function to probe instrumented function's entry,
+ *     - ftrace_graph_caller to set up an exit hook
+ */
+ENTRY(ftrace_caller)
+	mcount_enter
+
+	mcount_get_pc0	x0		//     function's pc
+	mcount_get_lr	x1		//     function's lr
+
+	.global ftrace_call
+ftrace_call:				// tracer(pc, lr);
+	nop				// This will be replaced with "bl xxx"
+					// where xxx can be any kind of tracer.
+
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+	.global ftrace_graph_call
+ftrace_graph_call:			// ftrace_graph_caller();
+	nop				// If enabled, this will be replaced
+					// "b ftrace_graph_caller"
+#endif
+
+	mcount_exit
+ENDPROC(ftrace_caller)
+#endif /* CONFIG_DYNAMIC_FTRACE */
+
 ENTRY(ftrace_stub)
 	ret
 ENDPROC(ftrace_stub)
diff --git a/arch/arm64/kernel/ftrace.c b/arch/arm64/kernel/ftrace.c
index a559ab8..8c26476 100644
--- a/arch/arm64/kernel/ftrace.c
+++ b/arch/arm64/kernel/ftrace.c
@@ -17,6 +17,89 @@
 #include <asm/ftrace.h>
 #include <asm/insn.h>
 
+#ifdef CONFIG_DYNAMIC_FTRACE
+/*
+ * Replace a single instruction, which may be a branch or NOP.
+ * If @validate == true, a replaced instruction is checked against 'old'.
+ */
+static int ftrace_modify_code(unsigned long pc, unsigned int old,
+			      unsigned int new, bool validate)
+{
+	unsigned int replaced;
+
+	/*
+	 * Note:
+	 * Due to modules and __init, code can disappear and change,
+	 * we need to protect against faulting as well as code changing.
+	 * We do this by aarch64_insn_*() which use the probe_kernel_*().
+	 *
+	 * No lock is held here because all the modifications are run
+	 * through stop_machine().
+	 */
+	if (validate) {
+		if (aarch64_insn_read((void *)pc, &replaced))
+			return -EFAULT;
+
+		if (replaced != old)
+			return -EINVAL;
+	}
+	if (aarch64_insn_patch_text_nosync((void *)pc, new))
+		return -EPERM;
+
+	return 0;
+}
+
+/*
+ * Replace tracer function in ftrace_caller()
+ */
+int ftrace_update_ftrace_func(ftrace_func_t func)
+{
+	unsigned long pc;
+	unsigned int new;
+
+	pc = (unsigned long)&ftrace_call;
+	new = aarch64_insn_gen_branch_imm(pc, (unsigned long)func, true);
+
+	return ftrace_modify_code(pc, 0, new, false);
+}
+
+/*
+ * Turn on the call to ftrace_caller() in instrumented function
+ */
+int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
+{
+	unsigned long pc = rec->ip;
+	unsigned int old, new;
+
+	old = aarch64_insn_gen_nop();
+	new = aarch64_insn_gen_branch_imm(pc, addr, true);
+
+	return ftrace_modify_code(pc, old, new, true);
+}
+
+/*
+ * Turn off the call to ftrace_caller() in instrumented function
+ */
+int ftrace_make_nop(struct module *mod,
+		    struct dyn_ftrace *rec, unsigned long addr)
+{
+	unsigned long pc = rec->ip;
+	unsigned int old, new;
+
+	old = aarch64_insn_gen_branch_imm(pc, addr, true);
+	new = aarch64_insn_gen_nop();
+
+	return ftrace_modify_code(pc, old, new, true);
+}
+
+int __init ftrace_dyn_arch_init(void *data)
+{
+	*(unsigned long *)data = 0;
+
+	return 0;
+}
+#endif /* CONFIG_DYNAMIC_FTRACE */
+
 #ifdef CONFIG_FUNCTION_GRAPH_TRACER
 /*
  * function_graph tracer expects ftrace_return_to_handler() to be called
@@ -61,4 +144,34 @@ void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr,
 		return;
 	}
 }
+
+#ifdef CONFIG_DYNAMIC_FTRACE
+/*
+ * Turn on/off the call to ftrace_graph_caller() in ftrace_caller()
+ * depending on @enable.
+ */
+static int ftrace_modify_graph_caller(bool enable)
+{
+	unsigned long pc = (unsigned long)&ftrace_graph_call;
+	unsigned int branch, nop, old, new;
+
+	branch = aarch64_insn_gen_branch_imm(pc,
+			(unsigned long)ftrace_graph_caller, false);
+	nop = aarch64_insn_gen_nop();
+	old = enable ? nop : branch;
+	new = enable ? branch : nop;
+
+	return ftrace_modify_code(pc, old, new, true);
+}
+
+int ftrace_enable_ftrace_graph_caller(void)
+{
+	return ftrace_modify_graph_caller(true);
+}
+
+int ftrace_disable_ftrace_graph_caller(void)
+{
+	return ftrace_modify_graph_caller(false);
+}
+#endif /* CONFIG_DYNAMIC_FTRACE */
 #endif /* CONFIG_FUNCTION_GRAPH_TRACER */
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 235+ messages in thread

* [PATCH v5 3/7] arm64: ftrace: Add CALLER_ADDRx macros
  2014-02-28  5:18       ` AKASHI Takahiro
@ 2014-02-28  5:18         ` AKASHI Takahiro
  -1 siblings, 0 replies; 235+ messages in thread
From: AKASHI Takahiro @ 2014-02-28  5:18 UTC (permalink / raw)
  To: rostedt, fweisbec, mingo, catalin.marinas, will.deacon, tim.bird
  Cc: gkulkarni, dsaxena, arndb, linux-arm-kernel, linaro-kernel,
	linux-kernel, AKASHI Takahiro

CALLER_ADDRx returns caller's address at specified level in call stacks.
They are used for several tracers like irqsoff and preemptoff.
Strange to say, however, they are refered even without FTRACE.

Please note that this implementation assumes that we have frame pointers.
(which means kernel should be compiled with -fno-omit-frame-pointer.)

Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
---
 arch/arm64/include/asm/ftrace.h    |   14 +++++++++
 arch/arm64/kernel/Makefile         |    3 +-
 arch/arm64/kernel/return_address.c |   55 ++++++++++++++++++++++++++++++++++++
 3 files changed, 71 insertions(+), 1 deletion(-)
 create mode 100644 arch/arm64/kernel/return_address.c

diff --git a/arch/arm64/include/asm/ftrace.h b/arch/arm64/include/asm/ftrace.h
index ed5c448..f93da72 100644
--- a/arch/arm64/include/asm/ftrace.h
+++ b/arch/arm64/include/asm/ftrace.h
@@ -35,4 +35,18 @@ static inline unsigned long ftrace_call_adjust(unsigned long addr)
 }
 #endif /* __ASSEMBLY__ */
 
+#ifndef __ASSEMBLY__
+#define HAVE_ARCH_CALLER_ADDR
+
+extern void *return_address(unsigned int);
+
+#define CALLER_ADDR0 ((unsigned long)__builtin_return_address(0))
+#define CALLER_ADDR1 ((unsigned long)return_address(1))
+#define CALLER_ADDR2 ((unsigned long)return_address(2))
+#define CALLER_ADDR3 ((unsigned long)return_address(3))
+#define CALLER_ADDR4 ((unsigned long)return_address(4))
+#define CALLER_ADDR5 ((unsigned long)return_address(5))
+#define CALLER_ADDR6 ((unsigned long)return_address(6))
+#endif /* ifndef __ASSEMBLY__ */
+
 #endif /* __ASM_FTRACE_H */
diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile
index ac67fd0..b5bfa7f 100644
--- a/arch/arm64/kernel/Makefile
+++ b/arch/arm64/kernel/Makefile
@@ -7,12 +7,13 @@ AFLAGS_head.o		:= -DTEXT_OFFSET=$(TEXT_OFFSET)
 
 CFLAGS_REMOVE_ftrace.o = -pg
 CFLAGS_REMOVE_insn.o = -pg
+CFLAGS_REMOVE_return_address.o = -pg
 
 # Object file lists.
 arm64-obj-y		:= cputable.o debug-monitors.o entry.o irq.o fpsimd.o	\
 			   entry-fpsimd.o process.o ptrace.o setup.o signal.o	\
 			   sys.o stacktrace.o time.o traps.o io.o vdso.o	\
-			   hyp-stub.o psci.o cpu_ops.o insn.o
+			   hyp-stub.o psci.o cpu_ops.o insn.o return_address.o
 
 arm64-obj-$(CONFIG_COMPAT)		+= sys32.o kuser32.o signal32.o 	\
 					   sys_compat.o
diff --git a/arch/arm64/kernel/return_address.c b/arch/arm64/kernel/return_address.c
new file mode 100644
index 0000000..89102a6
--- /dev/null
+++ b/arch/arm64/kernel/return_address.c
@@ -0,0 +1,55 @@
+/*
+ * arch/arm64/kernel/return_address.c
+ *
+ * Copyright (C) 2013 Linaro Limited
+ * Author: AKASHI Takahiro <takahiro.akashi@linaro.org>
+ *
+ * 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 <linux/export.h>
+#include <linux/ftrace.h>
+
+#include <asm/stacktrace.h>
+
+struct return_address_data {
+	unsigned int level;
+	void *addr;
+};
+
+static int save_return_addr(struct stackframe *frame, void *d)
+{
+	struct return_address_data *data = d;
+
+	if (!data->level) {
+		data->addr = (void *)frame->pc;
+		return 1;
+	} else {
+		--data->level;
+		return 0;
+	}
+}
+
+void *return_address(unsigned int level)
+{
+	struct return_address_data data;
+	struct stackframe frame;
+	register unsigned long current_sp asm ("sp");
+
+	data.level = level + 2;
+	data.addr = NULL;
+
+	frame.fp = (unsigned long)__builtin_frame_address(0);
+	frame.sp = current_sp;
+	frame.pc = (unsigned long)return_address; /* dummy */
+
+	walk_stackframe(&frame, save_return_addr, &data);
+
+	if (!data.level)
+		return data.addr;
+	else
+		return NULL;
+}
+EXPORT_SYMBOL_GPL(return_address);
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 235+ messages in thread

* [PATCH v5 3/7] arm64: ftrace: Add CALLER_ADDRx macros
@ 2014-02-28  5:18         ` AKASHI Takahiro
  0 siblings, 0 replies; 235+ messages in thread
From: AKASHI Takahiro @ 2014-02-28  5:18 UTC (permalink / raw)
  To: linux-arm-kernel

CALLER_ADDRx returns caller's address at specified level in call stacks.
They are used for several tracers like irqsoff and preemptoff.
Strange to say, however, they are refered even without FTRACE.

Please note that this implementation assumes that we have frame pointers.
(which means kernel should be compiled with -fno-omit-frame-pointer.)

Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
---
 arch/arm64/include/asm/ftrace.h    |   14 +++++++++
 arch/arm64/kernel/Makefile         |    3 +-
 arch/arm64/kernel/return_address.c |   55 ++++++++++++++++++++++++++++++++++++
 3 files changed, 71 insertions(+), 1 deletion(-)
 create mode 100644 arch/arm64/kernel/return_address.c

diff --git a/arch/arm64/include/asm/ftrace.h b/arch/arm64/include/asm/ftrace.h
index ed5c448..f93da72 100644
--- a/arch/arm64/include/asm/ftrace.h
+++ b/arch/arm64/include/asm/ftrace.h
@@ -35,4 +35,18 @@ static inline unsigned long ftrace_call_adjust(unsigned long addr)
 }
 #endif /* __ASSEMBLY__ */
 
+#ifndef __ASSEMBLY__
+#define HAVE_ARCH_CALLER_ADDR
+
+extern void *return_address(unsigned int);
+
+#define CALLER_ADDR0 ((unsigned long)__builtin_return_address(0))
+#define CALLER_ADDR1 ((unsigned long)return_address(1))
+#define CALLER_ADDR2 ((unsigned long)return_address(2))
+#define CALLER_ADDR3 ((unsigned long)return_address(3))
+#define CALLER_ADDR4 ((unsigned long)return_address(4))
+#define CALLER_ADDR5 ((unsigned long)return_address(5))
+#define CALLER_ADDR6 ((unsigned long)return_address(6))
+#endif /* ifndef __ASSEMBLY__ */
+
 #endif /* __ASM_FTRACE_H */
diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile
index ac67fd0..b5bfa7f 100644
--- a/arch/arm64/kernel/Makefile
+++ b/arch/arm64/kernel/Makefile
@@ -7,12 +7,13 @@ AFLAGS_head.o		:= -DTEXT_OFFSET=$(TEXT_OFFSET)
 
 CFLAGS_REMOVE_ftrace.o = -pg
 CFLAGS_REMOVE_insn.o = -pg
+CFLAGS_REMOVE_return_address.o = -pg
 
 # Object file lists.
 arm64-obj-y		:= cputable.o debug-monitors.o entry.o irq.o fpsimd.o	\
 			   entry-fpsimd.o process.o ptrace.o setup.o signal.o	\
 			   sys.o stacktrace.o time.o traps.o io.o vdso.o	\
-			   hyp-stub.o psci.o cpu_ops.o insn.o
+			   hyp-stub.o psci.o cpu_ops.o insn.o return_address.o
 
 arm64-obj-$(CONFIG_COMPAT)		+= sys32.o kuser32.o signal32.o 	\
 					   sys_compat.o
diff --git a/arch/arm64/kernel/return_address.c b/arch/arm64/kernel/return_address.c
new file mode 100644
index 0000000..89102a6
--- /dev/null
+++ b/arch/arm64/kernel/return_address.c
@@ -0,0 +1,55 @@
+/*
+ * arch/arm64/kernel/return_address.c
+ *
+ * Copyright (C) 2013 Linaro Limited
+ * Author: AKASHI Takahiro <takahiro.akashi@linaro.org>
+ *
+ * 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 <linux/export.h>
+#include <linux/ftrace.h>
+
+#include <asm/stacktrace.h>
+
+struct return_address_data {
+	unsigned int level;
+	void *addr;
+};
+
+static int save_return_addr(struct stackframe *frame, void *d)
+{
+	struct return_address_data *data = d;
+
+	if (!data->level) {
+		data->addr = (void *)frame->pc;
+		return 1;
+	} else {
+		--data->level;
+		return 0;
+	}
+}
+
+void *return_address(unsigned int level)
+{
+	struct return_address_data data;
+	struct stackframe frame;
+	register unsigned long current_sp asm ("sp");
+
+	data.level = level + 2;
+	data.addr = NULL;
+
+	frame.fp = (unsigned long)__builtin_frame_address(0);
+	frame.sp = current_sp;
+	frame.pc = (unsigned long)return_address; /* dummy */
+
+	walk_stackframe(&frame, save_return_addr, &data);
+
+	if (!data.level)
+		return data.addr;
+	else
+		return NULL;
+}
+EXPORT_SYMBOL_GPL(return_address);
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 235+ messages in thread

* [PATCH v5 4/7] ftrace: Add arm64 support to recordmcount
  2014-02-28  5:18       ` AKASHI Takahiro
@ 2014-02-28  5:18         ` AKASHI Takahiro
  -1 siblings, 0 replies; 235+ messages in thread
From: AKASHI Takahiro @ 2014-02-28  5:18 UTC (permalink / raw)
  To: rostedt, fweisbec, mingo, catalin.marinas, will.deacon, tim.bird
  Cc: gkulkarni, dsaxena, arndb, linux-arm-kernel, linaro-kernel,
	linux-kernel, AKASHI Takahiro

Recordmcount utility under scripts is run, after compiling each object,
to find out all the locations of calling _mcount() and put them into
specific seciton named __mcount_loc.
Then linker collects all such information into a table in the kernel image
(between __start_mcount_loc and __stop_mcount_loc) for later use by ftrace.

This patch adds arm64 specific definitions to identify such locations.
There are two types of implementation, C and Perl. On arm64, only C version
is used to build the kernel now that CONFIG_HAVE_C_RECORDMCOUNT is on.
But Perl version is also maintained.

Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
---
 arch/arm64/Kconfig      |    2 ++
 scripts/recordmcount.c  |    4 ++++
 scripts/recordmcount.pl |    5 +++++
 3 files changed, 11 insertions(+)

diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index b176bc0..6954959 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -27,6 +27,7 @@ config ARM64
 	select HARDIRQS_SW_RESEND
 	select HAVE_ARCH_JUMP_LABEL
 	select HAVE_ARCH_TRACEHOOK
+	select HAVE_C_RECORDMCOUNT
 	select HAVE_DEBUG_BUGVERBOSE
 	select HAVE_DEBUG_KMEMLEAK
 	select HAVE_DMA_API_DEBUG
@@ -34,6 +35,7 @@ config ARM64
 	select HAVE_DMA_CONTIGUOUS
 	select HAVE_DYNAMIC_FTRACE
 	select HAVE_EFFICIENT_UNALIGNED_ACCESS
+	select HAVE_FTRACE_MCOUNT_RECORD
 	select HAVE_FUNCTION_TRACER
 	select HAVE_FUNCTION_GRAPH_TRACER
 	select HAVE_GENERIC_DMA_COHERENT
diff --git a/scripts/recordmcount.c b/scripts/recordmcount.c
index 9c22317..b92d9f7 100644
--- a/scripts/recordmcount.c
+++ b/scripts/recordmcount.c
@@ -347,6 +347,10 @@ do_file(char const *const fname)
 	case EM_ARM:	 reltype = R_ARM_ABS32;
 			 altmcount = "__gnu_mcount_nc";
 			 break;
+	case EM_AARCH64:
+			 reltype = R_AARCH64_ABS64;
+			 altmcount = "_mcount";
+			 break;
 	case EM_IA_64:	 reltype = R_IA64_IMM64;   gpfx = '_'; break;
 	case EM_METAG:	 reltype = R_METAG_ADDR32;
 			 altmcount = "_mcount_wrapper";
diff --git a/scripts/recordmcount.pl b/scripts/recordmcount.pl
index 91280b8..397b6b8 100755
--- a/scripts/recordmcount.pl
+++ b/scripts/recordmcount.pl
@@ -279,6 +279,11 @@ if ($arch eq "x86_64") {
     $mcount_regex = "^\\s*([0-9a-fA-F]+):\\s*R_ARM_(CALL|PC24|THM_CALL)" .
 			"\\s+(__gnu_mcount_nc|mcount)\$";
 
+} elsif ($arch eq "arm64") {
+    $alignment = 3;
+    $section_type = '%progbits';
+    $mcount_regex = "^\\s*([0-9a-fA-F]+):\\s*R_AARCH64_CALL26\\s+_mcount\$";
+    $type = ".quad";
 } elsif ($arch eq "ia64") {
     $mcount_regex = "^\\s*([0-9a-fA-F]+):.*\\s_mcount\$";
     $type = "data8";
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 235+ messages in thread

* [PATCH v5 4/7] ftrace: Add arm64 support to recordmcount
@ 2014-02-28  5:18         ` AKASHI Takahiro
  0 siblings, 0 replies; 235+ messages in thread
From: AKASHI Takahiro @ 2014-02-28  5:18 UTC (permalink / raw)
  To: linux-arm-kernel

Recordmcount utility under scripts is run, after compiling each object,
to find out all the locations of calling _mcount() and put them into
specific seciton named __mcount_loc.
Then linker collects all such information into a table in the kernel image
(between __start_mcount_loc and __stop_mcount_loc) for later use by ftrace.

This patch adds arm64 specific definitions to identify such locations.
There are two types of implementation, C and Perl. On arm64, only C version
is used to build the kernel now that CONFIG_HAVE_C_RECORDMCOUNT is on.
But Perl version is also maintained.

Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
---
 arch/arm64/Kconfig      |    2 ++
 scripts/recordmcount.c  |    4 ++++
 scripts/recordmcount.pl |    5 +++++
 3 files changed, 11 insertions(+)

diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index b176bc0..6954959 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -27,6 +27,7 @@ config ARM64
 	select HARDIRQS_SW_RESEND
 	select HAVE_ARCH_JUMP_LABEL
 	select HAVE_ARCH_TRACEHOOK
+	select HAVE_C_RECORDMCOUNT
 	select HAVE_DEBUG_BUGVERBOSE
 	select HAVE_DEBUG_KMEMLEAK
 	select HAVE_DMA_API_DEBUG
@@ -34,6 +35,7 @@ config ARM64
 	select HAVE_DMA_CONTIGUOUS
 	select HAVE_DYNAMIC_FTRACE
 	select HAVE_EFFICIENT_UNALIGNED_ACCESS
+	select HAVE_FTRACE_MCOUNT_RECORD
 	select HAVE_FUNCTION_TRACER
 	select HAVE_FUNCTION_GRAPH_TRACER
 	select HAVE_GENERIC_DMA_COHERENT
diff --git a/scripts/recordmcount.c b/scripts/recordmcount.c
index 9c22317..b92d9f7 100644
--- a/scripts/recordmcount.c
+++ b/scripts/recordmcount.c
@@ -347,6 +347,10 @@ do_file(char const *const fname)
 	case EM_ARM:	 reltype = R_ARM_ABS32;
 			 altmcount = "__gnu_mcount_nc";
 			 break;
+	case EM_AARCH64:
+			 reltype = R_AARCH64_ABS64;
+			 altmcount = "_mcount";
+			 break;
 	case EM_IA_64:	 reltype = R_IA64_IMM64;   gpfx = '_'; break;
 	case EM_METAG:	 reltype = R_METAG_ADDR32;
 			 altmcount = "_mcount_wrapper";
diff --git a/scripts/recordmcount.pl b/scripts/recordmcount.pl
index 91280b8..397b6b8 100755
--- a/scripts/recordmcount.pl
+++ b/scripts/recordmcount.pl
@@ -279,6 +279,11 @@ if ($arch eq "x86_64") {
     $mcount_regex = "^\\s*([0-9a-fA-F]+):\\s*R_ARM_(CALL|PC24|THM_CALL)" .
 			"\\s+(__gnu_mcount_nc|mcount)\$";
 
+} elsif ($arch eq "arm64") {
+    $alignment = 3;
+    $section_type = '%progbits';
+    $mcount_regex = "^\\s*([0-9a-fA-F]+):\\s*R_AARCH64_CALL26\\s+_mcount\$";
+    $type = ".quad";
 } elsif ($arch eq "ia64") {
     $mcount_regex = "^\\s*([0-9a-fA-F]+):.*\\s_mcount\$";
     $type = "data8";
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 235+ messages in thread

* [PATCH v5 5/7] arm64: ftrace: Add system call tracepoint
  2014-02-28  5:18       ` AKASHI Takahiro
@ 2014-02-28  5:18         ` AKASHI Takahiro
  -1 siblings, 0 replies; 235+ messages in thread
From: AKASHI Takahiro @ 2014-02-28  5:18 UTC (permalink / raw)
  To: rostedt, fweisbec, mingo, catalin.marinas, will.deacon, tim.bird
  Cc: gkulkarni, dsaxena, arndb, linux-arm-kernel, linaro-kernel,
	linux-kernel, AKASHI Takahiro

This patch allows system call entry or exit to be traced as ftrace events,
ie. sys_enter_*/sys_exit_*, if CONFIG_FTRACE_SYSCALLS is enabled.
Those events appear and can be controlled under
    ${sysfs}/tracing/events/syscalls/

Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
---
 arch/arm64/Kconfig               |    1 +
 arch/arm64/include/asm/syscall.h |    1 +
 arch/arm64/include/asm/unistd.h  |    2 ++
 arch/arm64/kernel/ptrace.c       |   52 ++++++++++++++++++++++----------------
 4 files changed, 34 insertions(+), 22 deletions(-)

diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 6954959..b1dcdb4 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -43,6 +43,7 @@ config ARM64
 	select HAVE_MEMBLOCK
 	select HAVE_PATA_PLATFORM
 	select HAVE_PERF_EVENTS
+	select HAVE_SYSCALL_TRACEPOINTS
 	select IRQ_DOMAIN
 	select MODULES_USE_ELF_RELA
 	select NO_BOOTMEM
diff --git a/arch/arm64/include/asm/syscall.h b/arch/arm64/include/asm/syscall.h
index 70ba9d4..383771e 100644
--- a/arch/arm64/include/asm/syscall.h
+++ b/arch/arm64/include/asm/syscall.h
@@ -18,6 +18,7 @@
 
 #include <linux/err.h>
 
+extern const void *sys_call_table[];
 
 static inline int syscall_get_nr(struct task_struct *task,
 				 struct pt_regs *regs)
diff --git a/arch/arm64/include/asm/unistd.h b/arch/arm64/include/asm/unistd.h
index 82ce217..c335479 100644
--- a/arch/arm64/include/asm/unistd.h
+++ b/arch/arm64/include/asm/unistd.h
@@ -28,3 +28,5 @@
 #endif
 #define __ARCH_WANT_SYS_CLONE
 #include <uapi/asm/unistd.h>
+
+#define NR_syscalls (__NR_syscalls)
diff --git a/arch/arm64/kernel/ptrace.c b/arch/arm64/kernel/ptrace.c
index 6a8928b..dc90f9f 100644
--- a/arch/arm64/kernel/ptrace.c
+++ b/arch/arm64/kernel/ptrace.c
@@ -41,6 +41,9 @@
 #include <asm/traps.h>
 #include <asm/system_misc.h>
 
+#define CREATE_TRACE_POINTS
+#include <trace/events/syscalls.h>
+
 /*
  * TODO: does not yet catch signals sent when the child dies.
  * in exit.c or in signal.c.
@@ -1062,31 +1065,36 @@ asmlinkage int syscall_trace(int dir, struct pt_regs *regs)
 {
 	unsigned long saved_reg;
 
-	if (!test_thread_flag(TIF_SYSCALL_TRACE))
-		return regs->syscallno;
+	if (dir && unlikely(test_thread_flag(TIF_SYSCALL_TRACEPOINT)))
+		trace_sys_exit(regs, regs_return_value(regs));
+
+	if (test_thread_flag(TIF_SYSCALL_TRACE)) {
+		if (is_compat_task()) {
+			/* AArch32 uses ip (r12) for scratch */
+			saved_reg = regs->regs[12];
+			regs->regs[12] = dir;
+		} else {
+			/*
+			 * Save X7. X7 is used to denote syscall entry/exit:
+			 *   X7 = 0 -> entry, = 1 -> exit
+			 */
+			saved_reg = regs->regs[7];
+			regs->regs[7] = dir;
+		}
 
-	if (is_compat_task()) {
-		/* AArch32 uses ip (r12) for scratch */
-		saved_reg = regs->regs[12];
-		regs->regs[12] = dir;
-	} else {
-		/*
-		 * Save X7. X7 is used to denote syscall entry/exit:
-		 *   X7 = 0 -> entry, = 1 -> exit
-		 */
-		saved_reg = regs->regs[7];
-		regs->regs[7] = dir;
-	}
+		if (dir)
+			tracehook_report_syscall_exit(regs, 0);
+		else if (tracehook_report_syscall_entry(regs))
+			regs->syscallno = ~0UL;
 
-	if (dir)
-		tracehook_report_syscall_exit(regs, 0);
-	else if (tracehook_report_syscall_entry(regs))
-		regs->syscallno = ~0UL;
+		if (is_compat_task())
+			regs->regs[12] = saved_reg;
+		else
+			regs->regs[7] = saved_reg;
+	}
 
-	if (is_compat_task())
-		regs->regs[12] = saved_reg;
-	else
-		regs->regs[7] = saved_reg;
+	if (!dir && unlikely(test_thread_flag(TIF_SYSCALL_TRACEPOINT)))
+		trace_sys_enter(regs, regs->syscallno);
 
 	return regs->syscallno;
 }
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 235+ messages in thread

* [PATCH v5 5/7] arm64: ftrace: Add system call tracepoint
@ 2014-02-28  5:18         ` AKASHI Takahiro
  0 siblings, 0 replies; 235+ messages in thread
From: AKASHI Takahiro @ 2014-02-28  5:18 UTC (permalink / raw)
  To: linux-arm-kernel

This patch allows system call entry or exit to be traced as ftrace events,
ie. sys_enter_*/sys_exit_*, if CONFIG_FTRACE_SYSCALLS is enabled.
Those events appear and can be controlled under
    ${sysfs}/tracing/events/syscalls/

Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
---
 arch/arm64/Kconfig               |    1 +
 arch/arm64/include/asm/syscall.h |    1 +
 arch/arm64/include/asm/unistd.h  |    2 ++
 arch/arm64/kernel/ptrace.c       |   52 ++++++++++++++++++++++----------------
 4 files changed, 34 insertions(+), 22 deletions(-)

diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 6954959..b1dcdb4 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -43,6 +43,7 @@ config ARM64
 	select HAVE_MEMBLOCK
 	select HAVE_PATA_PLATFORM
 	select HAVE_PERF_EVENTS
+	select HAVE_SYSCALL_TRACEPOINTS
 	select IRQ_DOMAIN
 	select MODULES_USE_ELF_RELA
 	select NO_BOOTMEM
diff --git a/arch/arm64/include/asm/syscall.h b/arch/arm64/include/asm/syscall.h
index 70ba9d4..383771e 100644
--- a/arch/arm64/include/asm/syscall.h
+++ b/arch/arm64/include/asm/syscall.h
@@ -18,6 +18,7 @@
 
 #include <linux/err.h>
 
+extern const void *sys_call_table[];
 
 static inline int syscall_get_nr(struct task_struct *task,
 				 struct pt_regs *regs)
diff --git a/arch/arm64/include/asm/unistd.h b/arch/arm64/include/asm/unistd.h
index 82ce217..c335479 100644
--- a/arch/arm64/include/asm/unistd.h
+++ b/arch/arm64/include/asm/unistd.h
@@ -28,3 +28,5 @@
 #endif
 #define __ARCH_WANT_SYS_CLONE
 #include <uapi/asm/unistd.h>
+
+#define NR_syscalls (__NR_syscalls)
diff --git a/arch/arm64/kernel/ptrace.c b/arch/arm64/kernel/ptrace.c
index 6a8928b..dc90f9f 100644
--- a/arch/arm64/kernel/ptrace.c
+++ b/arch/arm64/kernel/ptrace.c
@@ -41,6 +41,9 @@
 #include <asm/traps.h>
 #include <asm/system_misc.h>
 
+#define CREATE_TRACE_POINTS
+#include <trace/events/syscalls.h>
+
 /*
  * TODO: does not yet catch signals sent when the child dies.
  * in exit.c or in signal.c.
@@ -1062,31 +1065,36 @@ asmlinkage int syscall_trace(int dir, struct pt_regs *regs)
 {
 	unsigned long saved_reg;
 
-	if (!test_thread_flag(TIF_SYSCALL_TRACE))
-		return regs->syscallno;
+	if (dir && unlikely(test_thread_flag(TIF_SYSCALL_TRACEPOINT)))
+		trace_sys_exit(regs, regs_return_value(regs));
+
+	if (test_thread_flag(TIF_SYSCALL_TRACE)) {
+		if (is_compat_task()) {
+			/* AArch32 uses ip (r12) for scratch */
+			saved_reg = regs->regs[12];
+			regs->regs[12] = dir;
+		} else {
+			/*
+			 * Save X7. X7 is used to denote syscall entry/exit:
+			 *   X7 = 0 -> entry, = 1 -> exit
+			 */
+			saved_reg = regs->regs[7];
+			regs->regs[7] = dir;
+		}
 
-	if (is_compat_task()) {
-		/* AArch32 uses ip (r12) for scratch */
-		saved_reg = regs->regs[12];
-		regs->regs[12] = dir;
-	} else {
-		/*
-		 * Save X7. X7 is used to denote syscall entry/exit:
-		 *   X7 = 0 -> entry, = 1 -> exit
-		 */
-		saved_reg = regs->regs[7];
-		regs->regs[7] = dir;
-	}
+		if (dir)
+			tracehook_report_syscall_exit(regs, 0);
+		else if (tracehook_report_syscall_entry(regs))
+			regs->syscallno = ~0UL;
 
-	if (dir)
-		tracehook_report_syscall_exit(regs, 0);
-	else if (tracehook_report_syscall_entry(regs))
-		regs->syscallno = ~0UL;
+		if (is_compat_task())
+			regs->regs[12] = saved_reg;
+		else
+			regs->regs[7] = saved_reg;
+	}
 
-	if (is_compat_task())
-		regs->regs[12] = saved_reg;
-	else
-		regs->regs[7] = saved_reg;
+	if (!dir && unlikely(test_thread_flag(TIF_SYSCALL_TRACEPOINT)))
+		trace_sys_enter(regs, regs->syscallno);
 
 	return regs->syscallno;
 }
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 235+ messages in thread

* [PATCH v5 6/7] arm64: Add 'notrace' attribute to unwind_frame() for ftrace
  2014-02-28  5:18       ` AKASHI Takahiro
@ 2014-02-28  5:18         ` AKASHI Takahiro
  -1 siblings, 0 replies; 235+ messages in thread
From: AKASHI Takahiro @ 2014-02-28  5:18 UTC (permalink / raw)
  To: rostedt, fweisbec, mingo, catalin.marinas, will.deacon, tim.bird
  Cc: gkulkarni, dsaxena, arndb, linux-arm-kernel, linaro-kernel,
	linux-kernel, AKASHI Takahiro

walk_stackframe() calls unwind_frame(), and if walk_stackframe() is
"notrace", unwind_frame() should be also "notrace".

Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
---
 arch/arm64/kernel/stacktrace.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm64/kernel/stacktrace.c b/arch/arm64/kernel/stacktrace.c
index c3b6c63..54122c4 100644
--- a/arch/arm64/kernel/stacktrace.c
+++ b/arch/arm64/kernel/stacktrace.c
@@ -35,7 +35,7 @@
  *	ldp	x29, x30, [sp]
  *	add	sp, sp, #0x10
  */
-int unwind_frame(struct stackframe *frame)
+int notrace unwind_frame(struct stackframe *frame)
 {
 	unsigned long high, low;
 	unsigned long fp = frame->fp;
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 235+ messages in thread

* [PATCH v5 6/7] arm64: Add 'notrace' attribute to unwind_frame() for ftrace
@ 2014-02-28  5:18         ` AKASHI Takahiro
  0 siblings, 0 replies; 235+ messages in thread
From: AKASHI Takahiro @ 2014-02-28  5:18 UTC (permalink / raw)
  To: linux-arm-kernel

walk_stackframe() calls unwind_frame(), and if walk_stackframe() is
"notrace", unwind_frame() should be also "notrace".

Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
---
 arch/arm64/kernel/stacktrace.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm64/kernel/stacktrace.c b/arch/arm64/kernel/stacktrace.c
index c3b6c63..54122c4 100644
--- a/arch/arm64/kernel/stacktrace.c
+++ b/arch/arm64/kernel/stacktrace.c
@@ -35,7 +35,7 @@
  *	ldp	x29, x30, [sp]
  *	add	sp, sp, #0x10
  */
-int unwind_frame(struct stackframe *frame)
+int notrace unwind_frame(struct stackframe *frame)
 {
 	unsigned long high, low;
 	unsigned long fp = frame->fp;
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 235+ messages in thread

* [PATCH v5 7/7] arm64: add __ASSEMBLY__ in asm/insn.h
  2014-02-28  5:18       ` AKASHI Takahiro
@ 2014-02-28  5:18         ` AKASHI Takahiro
  -1 siblings, 0 replies; 235+ messages in thread
From: AKASHI Takahiro @ 2014-02-28  5:18 UTC (permalink / raw)
  To: rostedt, fweisbec, mingo, catalin.marinas, will.deacon, tim.bird
  Cc: gkulkarni, dsaxena, arndb, linux-arm-kernel, linaro-kernel,
	linux-kernel, AKASHI Takahiro

Since insn.h is indirectly included in asm/entry-ftrace.S,
we need to exclude some declarations by __ASSEMBLY__.

Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
---
 arch/arm64/include/asm/insn.h |    2 ++
 1 file changed, 2 insertions(+)

diff --git a/arch/arm64/include/asm/insn.h b/arch/arm64/include/asm/insn.h
index c44ad39..dc1f73b 100644
--- a/arch/arm64/include/asm/insn.h
+++ b/arch/arm64/include/asm/insn.h
@@ -21,6 +21,7 @@
 /* A64 instructions are always 32 bits. */
 #define	AARCH64_INSN_SIZE		4
 
+#ifndef __ASSEMBLY__
 /*
  * ARM Architecture Reference Manual for ARMv8 Profile-A, Issue A.a
  * Section C3.1 "A64 instruction index by encoding":
@@ -104,5 +105,6 @@ bool aarch64_insn_hotpatch_safe(u32 old_insn, u32 new_insn);
 int aarch64_insn_patch_text_nosync(void *addr, u32 insn);
 int aarch64_insn_patch_text_sync(void *addrs[], u32 insns[], int cnt);
 int aarch64_insn_patch_text(void *addrs[], u32 insns[], int cnt);
+#endif /* __ASSEMBLY__ */
 
 #endif	/* __ASM_INSN_H */
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 235+ messages in thread

* [PATCH v5 7/7] arm64: add __ASSEMBLY__ in asm/insn.h
@ 2014-02-28  5:18         ` AKASHI Takahiro
  0 siblings, 0 replies; 235+ messages in thread
From: AKASHI Takahiro @ 2014-02-28  5:18 UTC (permalink / raw)
  To: linux-arm-kernel

Since insn.h is indirectly included in asm/entry-ftrace.S,
we need to exclude some declarations by __ASSEMBLY__.

Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
---
 arch/arm64/include/asm/insn.h |    2 ++
 1 file changed, 2 insertions(+)

diff --git a/arch/arm64/include/asm/insn.h b/arch/arm64/include/asm/insn.h
index c44ad39..dc1f73b 100644
--- a/arch/arm64/include/asm/insn.h
+++ b/arch/arm64/include/asm/insn.h
@@ -21,6 +21,7 @@
 /* A64 instructions are always 32 bits. */
 #define	AARCH64_INSN_SIZE		4
 
+#ifndef __ASSEMBLY__
 /*
  * ARM Architecture Reference Manual for ARMv8 Profile-A, Issue A.a
  * Section C3.1 "A64 instruction index by encoding":
@@ -104,5 +105,6 @@ bool aarch64_insn_hotpatch_safe(u32 old_insn, u32 new_insn);
 int aarch64_insn_patch_text_nosync(void *addr, u32 insn);
 int aarch64_insn_patch_text_sync(void *addrs[], u32 insns[], int cnt);
 int aarch64_insn_patch_text(void *addrs[], u32 insns[], int cnt);
+#endif /* __ASSEMBLY__ */
 
 #endif	/* __ASM_INSN_H */
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 235+ messages in thread

* Re: [PATCH v5 0/7] arm64: Add ftrace support
  2014-02-28  5:18       ` AKASHI Takahiro
@ 2014-03-11 14:35         ` Will Deacon
  -1 siblings, 0 replies; 235+ messages in thread
From: Will Deacon @ 2014-03-11 14:35 UTC (permalink / raw)
  To: AKASHI Takahiro
  Cc: rostedt, fweisbec, mingo, Catalin Marinas, tim.bird, gkulkarni,
	dsaxena, arndb, linux-arm-kernel, linaro-kernel, linux-kernel

Hi Akashi,

On Fri, Feb 28, 2014 at 05:18:37AM +0000, AKASHI Takahiro wrote:
> This patchset implements a function tracer on arm64.
> There was another implementation from Cavium network, but both of us agreed
> to use my patchset as future base. He is supposed to review this code, too.
> 
> The only issue that I had some concern on was "fault protection" code
> in prepare_ftrace_return(). With discussions with Steven and Tim (as author
> of arm ftrace), I removed that code since I'm not quite sure about possibility
> of "fault" occurrences in this function.
> 
> The code is tested on ARMv8 Fast Model with the following tracers & events:
>      function tracer with dynamic ftrace
>      function graph tracer with dynamic ftrace
>      syscall tracepoint
>      irqsoff & preemptirqsoff (which use CALLER_ADDRx)
> and also verified with in-kernel tests, FTRACE_SELFTEST, FTRACE_STARTUP_TEST
> and EVENT_TRACE_TEST_SYSCALLS.
> 
> Prerequisites are:
>  * "arm64: Add regs_return_value() in syscall.h"
>  * "arm64: make a single hook to syscall_trace() for all syscall features" patch

It looks like there might be some more dependencies that that. Do you have a
branch anywhere containing this series, along with all the dependencies so I
can have a play?

Cheers,

Will

^ permalink raw reply	[flat|nested] 235+ messages in thread

* [PATCH v5 0/7] arm64: Add ftrace support
@ 2014-03-11 14:35         ` Will Deacon
  0 siblings, 0 replies; 235+ messages in thread
From: Will Deacon @ 2014-03-11 14:35 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Akashi,

On Fri, Feb 28, 2014 at 05:18:37AM +0000, AKASHI Takahiro wrote:
> This patchset implements a function tracer on arm64.
> There was another implementation from Cavium network, but both of us agreed
> to use my patchset as future base. He is supposed to review this code, too.
> 
> The only issue that I had some concern on was "fault protection" code
> in prepare_ftrace_return(). With discussions with Steven and Tim (as author
> of arm ftrace), I removed that code since I'm not quite sure about possibility
> of "fault" occurrences in this function.
> 
> The code is tested on ARMv8 Fast Model with the following tracers & events:
>      function tracer with dynamic ftrace
>      function graph tracer with dynamic ftrace
>      syscall tracepoint
>      irqsoff & preemptirqsoff (which use CALLER_ADDRx)
> and also verified with in-kernel tests, FTRACE_SELFTEST, FTRACE_STARTUP_TEST
> and EVENT_TRACE_TEST_SYSCALLS.
> 
> Prerequisites are:
>  * "arm64: Add regs_return_value() in syscall.h"
>  * "arm64: make a single hook to syscall_trace() for all syscall features" patch

It looks like there might be some more dependencies that that. Do you have a
branch anywhere containing this series, along with all the dependencies so I
can have a play?

Cheers,

Will

^ permalink raw reply	[flat|nested] 235+ messages in thread

* Re: [PATCH v5 0/7] arm64: Add ftrace support
  2014-03-11 14:35         ` Will Deacon
@ 2014-03-12  1:47           ` AKASHI Takahiro
  -1 siblings, 0 replies; 235+ messages in thread
From: AKASHI Takahiro @ 2014-03-12  1:47 UTC (permalink / raw)
  To: Will Deacon
  Cc: rostedt, fweisbec, mingo, Catalin Marinas, tim.bird, gkulkarni,
	dsaxena, arndb, linux-arm-kernel, linaro-kernel, linux-kernel

Hi,

On 03/11/2014 11:35 PM, Will Deacon wrote:
> Hi Akashi,
>
> On Fri, Feb 28, 2014 at 05:18:37AM +0000, AKASHI Takahiro wrote:
>> This patchset implements a function tracer on arm64.
>> There was another implementation from Cavium network, but both of us agreed
>> to use my patchset as future base. He is supposed to review this code, too.
>>
>> The only issue that I had some concern on was "fault protection" code
>> in prepare_ftrace_return(). With discussions with Steven and Tim (as author
>> of arm ftrace), I removed that code since I'm not quite sure about possibility
>> of "fault" occurrences in this function.
>>
>> The code is tested on ARMv8 Fast Model with the following tracers & events:
>>       function tracer with dynamic ftrace
>>       function graph tracer with dynamic ftrace
>>       syscall tracepoint
>>       irqsoff & preemptirqsoff (which use CALLER_ADDRx)
>> and also verified with in-kernel tests, FTRACE_SELFTEST, FTRACE_STARTUP_TEST
>> and EVENT_TRACE_TEST_SYSCALLS.
>>
>> Prerequisites are:
>>   * "arm64: Add regs_return_value() in syscall.h"
>>   * "arm64: make a single hook to syscall_trace() for all syscall features" patch
>
> It looks like there might be some more dependencies that that. Do you have a
> branch anywhere containing this series, along with all the dependencies so I
> can have a play?

I think you saw the following messages:

 >   HOSTCC  scripts/recordmcount
 > /.../linux-aarch64/scripts/recordmcount.c: In function 'do_file':
 > /.../linux-aarch64/scripts/recordmcount.c:350:7: error:
 > 'EM_AARCH64' undeclared (first use in this function)
 > /.../linux-aarch64/scripts/recordmcount.c:350:7: note:
 > each undeclared identifier is reported only once for each function it appears in
 > /.../linux-aarch64/scripts/recordmcount.c:351:15: error:
 > 'R_AARCH64_ABS64' undeclared (first > use in this function)
 > make[2]: *** [scripts/recordmcount] Error 1
 > make[1]: *** [scripts] Error 2
 > make: *** [sub-make] Error 2

This happens when a header file, elf.h, on "your host machine" does not have
definitions of EM_AARCH64 nor R_AARCH64_ABS64 because "recordmcount" is a binary
utility on host(x86), not target. It is very likely for most distros.
(I mentioned this in the cover letter, but the description might not be clear.)

Possible solutions are:
1) Define both macros directly in scripts/recordmcount.c
2) Use perl version of recordmcount

Currently I take 1), but it is a workaround.
2) should work with my current patch, too. But you need to remove HAVE_C_RECORDCOUNT
from arm64/Kconfig.

Which one do you prefer? I will include a fix for 1) in the next revision, anyway.

Thanks,
-Takahiro AKASHI

> Cheers,
>
> Will
>

^ permalink raw reply	[flat|nested] 235+ messages in thread

* [PATCH v5 0/7] arm64: Add ftrace support
@ 2014-03-12  1:47           ` AKASHI Takahiro
  0 siblings, 0 replies; 235+ messages in thread
From: AKASHI Takahiro @ 2014-03-12  1:47 UTC (permalink / raw)
  To: linux-arm-kernel

Hi,

On 03/11/2014 11:35 PM, Will Deacon wrote:
> Hi Akashi,
>
> On Fri, Feb 28, 2014 at 05:18:37AM +0000, AKASHI Takahiro wrote:
>> This patchset implements a function tracer on arm64.
>> There was another implementation from Cavium network, but both of us agreed
>> to use my patchset as future base. He is supposed to review this code, too.
>>
>> The only issue that I had some concern on was "fault protection" code
>> in prepare_ftrace_return(). With discussions with Steven and Tim (as author
>> of arm ftrace), I removed that code since I'm not quite sure about possibility
>> of "fault" occurrences in this function.
>>
>> The code is tested on ARMv8 Fast Model with the following tracers & events:
>>       function tracer with dynamic ftrace
>>       function graph tracer with dynamic ftrace
>>       syscall tracepoint
>>       irqsoff & preemptirqsoff (which use CALLER_ADDRx)
>> and also verified with in-kernel tests, FTRACE_SELFTEST, FTRACE_STARTUP_TEST
>> and EVENT_TRACE_TEST_SYSCALLS.
>>
>> Prerequisites are:
>>   * "arm64: Add regs_return_value() in syscall.h"
>>   * "arm64: make a single hook to syscall_trace() for all syscall features" patch
>
> It looks like there might be some more dependencies that that. Do you have a
> branch anywhere containing this series, along with all the dependencies so I
> can have a play?

I think you saw the following messages:

 >   HOSTCC  scripts/recordmcount
 > /.../linux-aarch64/scripts/recordmcount.c: In function 'do_file':
 > /.../linux-aarch64/scripts/recordmcount.c:350:7: error:
 > 'EM_AARCH64' undeclared (first use in this function)
 > /.../linux-aarch64/scripts/recordmcount.c:350:7: note:
 > each undeclared identifier is reported only once for each function it appears in
 > /.../linux-aarch64/scripts/recordmcount.c:351:15: error:
 > 'R_AARCH64_ABS64' undeclared (first > use in this function)
 > make[2]: *** [scripts/recordmcount] Error 1
 > make[1]: *** [scripts] Error 2
 > make: *** [sub-make] Error 2

This happens when a header file, elf.h, on "your host machine" does not have
definitions of EM_AARCH64 nor R_AARCH64_ABS64 because "recordmcount" is a binary
utility on host(x86), not target. It is very likely for most distros.
(I mentioned this in the cover letter, but the description might not be clear.)

Possible solutions are:
1) Define both macros directly in scripts/recordmcount.c
2) Use perl version of recordmcount

Currently I take 1), but it is a workaround.
2) should work with my current patch, too. But you need to remove HAVE_C_RECORDCOUNT
from arm64/Kconfig.

Which one do you prefer? I will include a fix for 1) in the next revision, anyway.

Thanks,
-Takahiro AKASHI

> Cheers,
>
> Will
>

^ permalink raw reply	[flat|nested] 235+ messages in thread

* Re: [PATCH v5 0/7] arm64: Add ftrace support
  2014-03-12  1:47           ` AKASHI Takahiro
@ 2014-03-12  1:58             ` Steven Rostedt
  -1 siblings, 0 replies; 235+ messages in thread
From: Steven Rostedt @ 2014-03-12  1:58 UTC (permalink / raw)
  To: AKASHI Takahiro
  Cc: Will Deacon, fweisbec, mingo, Catalin Marinas, tim.bird,
	gkulkarni, dsaxena, arndb, linux-arm-kernel, linaro-kernel,
	linux-kernel

On Wed, 12 Mar 2014 10:47:20 +0900
AKASHI Takahiro <takahiro.akashi@linaro.org> wrote:

> This happens when a header file, elf.h, on "your host machine" does not have
> definitions of EM_AARCH64 nor R_AARCH64_ABS64 because "recordmcount" is a binary
> utility on host(x86), not target. It is very likely for most distros.
> (I mentioned this in the cover letter, but the description might not be clear.)
> 
> Possible solutions are:
> 1) Define both macros directly in scripts/recordmcount.c
> 2) Use perl version of recordmcount
> 
> Currently I take 1), but it is a workaround.
> 2) should work with my current patch, too. But you need to remove HAVE_C_RECORDCOUNT
> from arm64/Kconfig.
> 
> Which one do you prefer? I will include a fix for 1) in the next revision, anyway.
> 

I'd recommend #1, where you add this:

/* AARCH64 is new, and most headers don't define it. */
#ifndef EM_AARCH64
#define EM_AARCH64  ##
#define R_AARCH64_ABS64 ##
#endif

Obviously fill in the blank for ##

-- Steve

^ permalink raw reply	[flat|nested] 235+ messages in thread

* [PATCH v5 0/7] arm64: Add ftrace support
@ 2014-03-12  1:58             ` Steven Rostedt
  0 siblings, 0 replies; 235+ messages in thread
From: Steven Rostedt @ 2014-03-12  1:58 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, 12 Mar 2014 10:47:20 +0900
AKASHI Takahiro <takahiro.akashi@linaro.org> wrote:

> This happens when a header file, elf.h, on "your host machine" does not have
> definitions of EM_AARCH64 nor R_AARCH64_ABS64 because "recordmcount" is a binary
> utility on host(x86), not target. It is very likely for most distros.
> (I mentioned this in the cover letter, but the description might not be clear.)
> 
> Possible solutions are:
> 1) Define both macros directly in scripts/recordmcount.c
> 2) Use perl version of recordmcount
> 
> Currently I take 1), but it is a workaround.
> 2) should work with my current patch, too. But you need to remove HAVE_C_RECORDCOUNT
> from arm64/Kconfig.
> 
> Which one do you prefer? I will include a fix for 1) in the next revision, anyway.
> 

I'd recommend #1, where you add this:

/* AARCH64 is new, and most headers don't define it. */
#ifndef EM_AARCH64
#define EM_AARCH64  ##
#define R_AARCH64_ABS64 ##
#endif

Obviously fill in the blank for ##

-- Steve

^ permalink raw reply	[flat|nested] 235+ messages in thread

* Re: [PATCH v5 0/7] arm64: Add ftrace support
  2014-03-12  1:47           ` AKASHI Takahiro
@ 2014-03-12  2:02             ` Steven Rostedt
  -1 siblings, 0 replies; 235+ messages in thread
From: Steven Rostedt @ 2014-03-12  2:02 UTC (permalink / raw)
  To: AKASHI Takahiro
  Cc: Will Deacon, fweisbec, mingo, Catalin Marinas, tim.bird,
	gkulkarni, dsaxena, arndb, linux-arm-kernel, linaro-kernel,
	linux-kernel

On Wed, 12 Mar 2014 10:47:20 +0900
AKASHI Takahiro <takahiro.akashi@linaro.org> wrote:


> This happens when a header file, elf.h, on "your host machine" does not have
> definitions of EM_AARCH64 nor R_AARCH64_ABS64 because "recordmcount" is a binary
> utility on host(x86), not target. It is very likely for most distros.
> (I mentioned this in the cover letter, but the description might not be clear.)
> 
> Possible solutions are:
> 1) Define both macros directly in scripts/recordmcount.c
> 2) Use perl version of recordmcount
> 
> Currently I take 1), but it is a workaround.
> 2) should work with my current patch, too. But you need to remove HAVE_C_RECORDCOUNT
> from arm64/Kconfig.
> 
> Which one do you prefer? I will include a fix for 1) in the next revision, anyway.

Or even option 3)

3) I can update the main Makefile to check to see if EM_<ARCH> exists
in the elf.h header, and if not, we use the perl version and undef
HAVE_C_RECORDMCOUNT.

-- Steve


^ permalink raw reply	[flat|nested] 235+ messages in thread

* [PATCH v5 0/7] arm64: Add ftrace support
@ 2014-03-12  2:02             ` Steven Rostedt
  0 siblings, 0 replies; 235+ messages in thread
From: Steven Rostedt @ 2014-03-12  2:02 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, 12 Mar 2014 10:47:20 +0900
AKASHI Takahiro <takahiro.akashi@linaro.org> wrote:


> This happens when a header file, elf.h, on "your host machine" does not have
> definitions of EM_AARCH64 nor R_AARCH64_ABS64 because "recordmcount" is a binary
> utility on host(x86), not target. It is very likely for most distros.
> (I mentioned this in the cover letter, but the description might not be clear.)
> 
> Possible solutions are:
> 1) Define both macros directly in scripts/recordmcount.c
> 2) Use perl version of recordmcount
> 
> Currently I take 1), but it is a workaround.
> 2) should work with my current patch, too. But you need to remove HAVE_C_RECORDCOUNT
> from arm64/Kconfig.
> 
> Which one do you prefer? I will include a fix for 1) in the next revision, anyway.

Or even option 3)

3) I can update the main Makefile to check to see if EM_<ARCH> exists
in the elf.h header, and if not, we use the perl version and undef
HAVE_C_RECORDMCOUNT.

-- Steve

^ permalink raw reply	[flat|nested] 235+ messages in thread

* [PATCH v6 0/7] arm64: Add ftrace support
  2014-02-28  5:18       ` AKASHI Takahiro
@ 2014-03-13 10:13         ` AKASHI Takahiro
  -1 siblings, 0 replies; 235+ messages in thread
From: AKASHI Takahiro @ 2014-03-13 10:13 UTC (permalink / raw)
  To: rostedt, fweisbec, mingo, catalin.marinas, will.deacon, tim.bird
  Cc: gkulkarni, dsaxena, arndb, linux-arm-kernel, linaro-kernel,
	linux-kernel, AKASHI Takahiro

This patchset implements a function tracer on arm64.
There was another implementation from Cavium network, but both of us agreed
to use my patchset as future base. He is supposed to review this code, too.

The only issue that I had some concern on was "fault protection" code
in prepare_ftrace_return(). With discussions with Steven and Tim (as author
of arm ftrace), I removed that code since I'm not quite sure about possibility
of "fault" occurrences in this function.

The code is tested on ARMv8 Fast Model with the following tracers & events:
     function tracer with dynamic ftrace
     function graph tracer with dynamic ftrace
     syscall tracepoint (but only for AArch64 tasks)
     irqsoff & preemptirqsoff (which use CALLER_ADDRx)
and also verified with in-kernel tests, FTRACE_SELFTEST, FTRACE_STARTUP_TEST
and EVENT_TRACE_TEST_SYSCALLS.

Prerequisites are:
 * "arm64: make a single hook to syscall_trace() for all syscall features" patch
 * "arm64: split syscall_trace() into separate functions for enter/exit" patch
 * "arm64: Add regs_return_value() in syscall.h" patch

Please be careful:
* Patch [3/7] gets warnings from checkpatch, but they are based on the
  original's coding style.
* Patch [7/7] may conflict with my audit patch because both changes the same
  location in syscall_trace_enter/exit(). I expect the functions are called
  in this order:
  On entry,
     * tracehook_report_syscall(ENTER)
     * trace_sys_enter()
     * audit_syscall_entry()
  On exit,
     * audit_sysscall_exit()
     * trace_sys_exit()
     * tracehook_report_syscall(EXIT) 

Changes from v5 to v6:
* changed the order of patches to avoid any bisect error (I have not tried
  though)
* added EM_AARCH64 and R_AARCH64_ABS64 definitions in scripts/recordmcount.c
  just in case elf.h on host machine doesn't have them. [3/7]
* updated a frame pointer (x29) in _mcount() to make it look like a normal
  function [4/7]
* aligned with the patch, "arm64: split syscall_trace() into separate
  functions for enter/exit" [7/7]
* defined ARCH_TRACE_IGNORE_COMPAT_SYSCALLS in order not to trace compat
  syscalls [7/7]

Chnages from v4 to v5:
* improved the description of stack layout [1/7]
* aligned with the change in "arm64: make a single hook to syscall_trace()
  for all syscall features" v3 [5/7]

Changes from v3 to v4:
* removed unnecessary "#ifdef" [1,2/7]
* changed stack depth from 48B to 16B in mcount()/ftrace_caller() (a bug) [1/7]
* changed MCOUNT_INSN_SIZE to AARCH64_INSN_SIZE [1,7/7]
* added a guard againt TIF_SYSCALL_TRACEPOINT [5/7]
* corrected the second argument passed to trace_sys_exit() (a bug) [5/7]
* aligned with the change in "arm64: make a single hook to syscall_trace()
  for all syscall features" v2 [5/7]

Changes from v2 to v3:
* optimized register usages in asm (by not saving x0, x1, and x2)
* removed "fault protection" code in prepare_ftrace_return()
* rewrote ftrace_modify_code() using "hotpatch" interfaces
* revised descriptions in comments

Changes from v1 to v2:
* splitted one patch into some pieces for easier review
  (especially function tracer + dynamic ftrace + CALLER_ADDRx)
* put return_address() in a separate file
* renamed __mcount to _mcount (it was my mistake)
* changed stackframe handling to get parent's frame pointer
* removed ARCH_SUPPORTS_FTRACE_OPS
* switched to "hotpatch" interfaces from Huawai
* revised descriptions in comments

AKASHI Takahiro (7):
  arm64: add __ASSEMBLY__ in asm/insn.h
  arm64: Add 'notrace' attribute to unwind_frame() for ftrace
  ftrace: Add arm64 support to recordmcount
  arm64: Add ftrace support
  arm64: ftrace: Add dynamic ftrace support
  arm64: ftrace: Add CALLER_ADDRx macros
  arm64: ftrace: Add system call tracepoint

 arch/arm64/Kconfig                 |    6 +
 arch/arm64/include/asm/ftrace.h    |   69 ++++++++++++
 arch/arm64/include/asm/insn.h      |    2 +
 arch/arm64/include/asm/syscall.h   |    1 +
 arch/arm64/include/asm/unistd.h    |    2 +
 arch/arm64/kernel/Makefile         |    7 +-
 arch/arm64/kernel/arm64ksyms.c     |    4 +
 arch/arm64/kernel/entry-ftrace.S   |  218 ++++++++++++++++++++++++++++++++++++
 arch/arm64/kernel/ftrace.c         |  177 +++++++++++++++++++++++++++++
 arch/arm64/kernel/ptrace.c         |   48 ++++----
 arch/arm64/kernel/return_address.c |   55 +++++++++
 arch/arm64/kernel/stacktrace.c     |    2 +-
 scripts/recordmcount.c             |    9 ++
 scripts/recordmcount.pl            |    5 +
 14 files changed, 583 insertions(+), 22 deletions(-)
 create mode 100644 arch/arm64/include/asm/ftrace.h
 create mode 100644 arch/arm64/kernel/entry-ftrace.S
 create mode 100644 arch/arm64/kernel/ftrace.c
 create mode 100644 arch/arm64/kernel/return_address.c

-- 
1.7.9.5


^ permalink raw reply	[flat|nested] 235+ messages in thread

* [PATCH v6 0/7] arm64: Add ftrace support
@ 2014-03-13 10:13         ` AKASHI Takahiro
  0 siblings, 0 replies; 235+ messages in thread
From: AKASHI Takahiro @ 2014-03-13 10:13 UTC (permalink / raw)
  To: linux-arm-kernel

This patchset implements a function tracer on arm64.
There was another implementation from Cavium network, but both of us agreed
to use my patchset as future base. He is supposed to review this code, too.

The only issue that I had some concern on was "fault protection" code
in prepare_ftrace_return(). With discussions with Steven and Tim (as author
of arm ftrace), I removed that code since I'm not quite sure about possibility
of "fault" occurrences in this function.

The code is tested on ARMv8 Fast Model with the following tracers & events:
     function tracer with dynamic ftrace
     function graph tracer with dynamic ftrace
     syscall tracepoint (but only for AArch64 tasks)
     irqsoff & preemptirqsoff (which use CALLER_ADDRx)
and also verified with in-kernel tests, FTRACE_SELFTEST, FTRACE_STARTUP_TEST
and EVENT_TRACE_TEST_SYSCALLS.

Prerequisites are:
 * "arm64: make a single hook to syscall_trace() for all syscall features" patch
 * "arm64: split syscall_trace() into separate functions for enter/exit" patch
 * "arm64: Add regs_return_value() in syscall.h" patch

Please be careful:
* Patch [3/7] gets warnings from checkpatch, but they are based on the
  original's coding style.
* Patch [7/7] may conflict with my audit patch because both changes the same
  location in syscall_trace_enter/exit(). I expect the functions are called
  in this order:
  On entry,
     * tracehook_report_syscall(ENTER)
     * trace_sys_enter()
     * audit_syscall_entry()
  On exit,
     * audit_sysscall_exit()
     * trace_sys_exit()
     * tracehook_report_syscall(EXIT) 

Changes from v5 to v6:
* changed the order of patches to avoid any bisect error (I have not tried
  though)
* added EM_AARCH64 and R_AARCH64_ABS64 definitions in scripts/recordmcount.c
  just in case elf.h on host machine doesn't have them. [3/7]
* updated a frame pointer (x29) in _mcount() to make it look like a normal
  function [4/7]
* aligned with the patch, "arm64: split syscall_trace() into separate
  functions for enter/exit" [7/7]
* defined ARCH_TRACE_IGNORE_COMPAT_SYSCALLS in order not to trace compat
  syscalls [7/7]

Chnages from v4 to v5:
* improved the description of stack layout [1/7]
* aligned with the change in "arm64: make a single hook to syscall_trace()
  for all syscall features" v3 [5/7]

Changes from v3 to v4:
* removed unnecessary "#ifdef" [1,2/7]
* changed stack depth from 48B to 16B in mcount()/ftrace_caller() (a bug) [1/7]
* changed MCOUNT_INSN_SIZE to AARCH64_INSN_SIZE [1,7/7]
* added a guard againt TIF_SYSCALL_TRACEPOINT [5/7]
* corrected the second argument passed to trace_sys_exit() (a bug) [5/7]
* aligned with the change in "arm64: make a single hook to syscall_trace()
  for all syscall features" v2 [5/7]

Changes from v2 to v3:
* optimized register usages in asm (by not saving x0, x1, and x2)
* removed "fault protection" code in prepare_ftrace_return()
* rewrote ftrace_modify_code() using "hotpatch" interfaces
* revised descriptions in comments

Changes from v1 to v2:
* splitted one patch into some pieces for easier review
  (especially function tracer + dynamic ftrace + CALLER_ADDRx)
* put return_address() in a separate file
* renamed __mcount to _mcount (it was my mistake)
* changed stackframe handling to get parent's frame pointer
* removed ARCH_SUPPORTS_FTRACE_OPS
* switched to "hotpatch" interfaces from Huawai
* revised descriptions in comments

AKASHI Takahiro (7):
  arm64: add __ASSEMBLY__ in asm/insn.h
  arm64: Add 'notrace' attribute to unwind_frame() for ftrace
  ftrace: Add arm64 support to recordmcount
  arm64: Add ftrace support
  arm64: ftrace: Add dynamic ftrace support
  arm64: ftrace: Add CALLER_ADDRx macros
  arm64: ftrace: Add system call tracepoint

 arch/arm64/Kconfig                 |    6 +
 arch/arm64/include/asm/ftrace.h    |   69 ++++++++++++
 arch/arm64/include/asm/insn.h      |    2 +
 arch/arm64/include/asm/syscall.h   |    1 +
 arch/arm64/include/asm/unistd.h    |    2 +
 arch/arm64/kernel/Makefile         |    7 +-
 arch/arm64/kernel/arm64ksyms.c     |    4 +
 arch/arm64/kernel/entry-ftrace.S   |  218 ++++++++++++++++++++++++++++++++++++
 arch/arm64/kernel/ftrace.c         |  177 +++++++++++++++++++++++++++++
 arch/arm64/kernel/ptrace.c         |   48 ++++----
 arch/arm64/kernel/return_address.c |   55 +++++++++
 arch/arm64/kernel/stacktrace.c     |    2 +-
 scripts/recordmcount.c             |    9 ++
 scripts/recordmcount.pl            |    5 +
 14 files changed, 583 insertions(+), 22 deletions(-)
 create mode 100644 arch/arm64/include/asm/ftrace.h
 create mode 100644 arch/arm64/kernel/entry-ftrace.S
 create mode 100644 arch/arm64/kernel/ftrace.c
 create mode 100644 arch/arm64/kernel/return_address.c

-- 
1.7.9.5

^ permalink raw reply	[flat|nested] 235+ messages in thread

* [PATCH v6 1/7] arm64: add __ASSEMBLY__ in asm/insn.h
  2014-03-13 10:13         ` AKASHI Takahiro
@ 2014-03-13 10:13           ` AKASHI Takahiro
  -1 siblings, 0 replies; 235+ messages in thread
From: AKASHI Takahiro @ 2014-03-13 10:13 UTC (permalink / raw)
  To: rostedt, fweisbec, mingo, catalin.marinas, will.deacon, tim.bird
  Cc: gkulkarni, dsaxena, arndb, linux-arm-kernel, linaro-kernel,
	linux-kernel, AKASHI Takahiro

Since insn.h is indirectly included in asm/entry-ftrace.S,
we need to exclude some declarations by __ASSEMBLY__.

Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
---
 arch/arm64/include/asm/insn.h |    2 ++
 1 file changed, 2 insertions(+)

diff --git a/arch/arm64/include/asm/insn.h b/arch/arm64/include/asm/insn.h
index c44ad39..dc1f73b 100644
--- a/arch/arm64/include/asm/insn.h
+++ b/arch/arm64/include/asm/insn.h
@@ -21,6 +21,7 @@
 /* A64 instructions are always 32 bits. */
 #define	AARCH64_INSN_SIZE		4
 
+#ifndef __ASSEMBLY__
 /*
  * ARM Architecture Reference Manual for ARMv8 Profile-A, Issue A.a
  * Section C3.1 "A64 instruction index by encoding":
@@ -104,5 +105,6 @@ bool aarch64_insn_hotpatch_safe(u32 old_insn, u32 new_insn);
 int aarch64_insn_patch_text_nosync(void *addr, u32 insn);
 int aarch64_insn_patch_text_sync(void *addrs[], u32 insns[], int cnt);
 int aarch64_insn_patch_text(void *addrs[], u32 insns[], int cnt);
+#endif /* __ASSEMBLY__ */
 
 #endif	/* __ASM_INSN_H */
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 235+ messages in thread

* [PATCH v6 1/7] arm64: add __ASSEMBLY__ in asm/insn.h
@ 2014-03-13 10:13           ` AKASHI Takahiro
  0 siblings, 0 replies; 235+ messages in thread
From: AKASHI Takahiro @ 2014-03-13 10:13 UTC (permalink / raw)
  To: linux-arm-kernel

Since insn.h is indirectly included in asm/entry-ftrace.S,
we need to exclude some declarations by __ASSEMBLY__.

Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
---
 arch/arm64/include/asm/insn.h |    2 ++
 1 file changed, 2 insertions(+)

diff --git a/arch/arm64/include/asm/insn.h b/arch/arm64/include/asm/insn.h
index c44ad39..dc1f73b 100644
--- a/arch/arm64/include/asm/insn.h
+++ b/arch/arm64/include/asm/insn.h
@@ -21,6 +21,7 @@
 /* A64 instructions are always 32 bits. */
 #define	AARCH64_INSN_SIZE		4
 
+#ifndef __ASSEMBLY__
 /*
  * ARM Architecture Reference Manual for ARMv8 Profile-A, Issue A.a
  * Section C3.1 "A64 instruction index by encoding":
@@ -104,5 +105,6 @@ bool aarch64_insn_hotpatch_safe(u32 old_insn, u32 new_insn);
 int aarch64_insn_patch_text_nosync(void *addr, u32 insn);
 int aarch64_insn_patch_text_sync(void *addrs[], u32 insns[], int cnt);
 int aarch64_insn_patch_text(void *addrs[], u32 insns[], int cnt);
+#endif /* __ASSEMBLY__ */
 
 #endif	/* __ASM_INSN_H */
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 235+ messages in thread

* [PATCH v6 2/7] arm64: Add 'notrace' attribute to unwind_frame() for ftrace
  2014-03-13 10:13         ` AKASHI Takahiro
@ 2014-03-13 10:13           ` AKASHI Takahiro
  -1 siblings, 0 replies; 235+ messages in thread
From: AKASHI Takahiro @ 2014-03-13 10:13 UTC (permalink / raw)
  To: rostedt, fweisbec, mingo, catalin.marinas, will.deacon, tim.bird
  Cc: gkulkarni, dsaxena, arndb, linux-arm-kernel, linaro-kernel,
	linux-kernel, AKASHI Takahiro

walk_stackframe() calls unwind_frame(), and if walk_stackframe() is
"notrace", unwind_frame() should be also "notrace".

Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
---
 arch/arm64/kernel/stacktrace.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm64/kernel/stacktrace.c b/arch/arm64/kernel/stacktrace.c
index c3b6c63..54122c4 100644
--- a/arch/arm64/kernel/stacktrace.c
+++ b/arch/arm64/kernel/stacktrace.c
@@ -35,7 +35,7 @@
  *	ldp	x29, x30, [sp]
  *	add	sp, sp, #0x10
  */
-int unwind_frame(struct stackframe *frame)
+int notrace unwind_frame(struct stackframe *frame)
 {
 	unsigned long high, low;
 	unsigned long fp = frame->fp;
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 235+ messages in thread

* [PATCH v6 2/7] arm64: Add 'notrace' attribute to unwind_frame() for ftrace
@ 2014-03-13 10:13           ` AKASHI Takahiro
  0 siblings, 0 replies; 235+ messages in thread
From: AKASHI Takahiro @ 2014-03-13 10:13 UTC (permalink / raw)
  To: linux-arm-kernel

walk_stackframe() calls unwind_frame(), and if walk_stackframe() is
"notrace", unwind_frame() should be also "notrace".

Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
---
 arch/arm64/kernel/stacktrace.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm64/kernel/stacktrace.c b/arch/arm64/kernel/stacktrace.c
index c3b6c63..54122c4 100644
--- a/arch/arm64/kernel/stacktrace.c
+++ b/arch/arm64/kernel/stacktrace.c
@@ -35,7 +35,7 @@
  *	ldp	x29, x30, [sp]
  *	add	sp, sp, #0x10
  */
-int unwind_frame(struct stackframe *frame)
+int notrace unwind_frame(struct stackframe *frame)
 {
 	unsigned long high, low;
 	unsigned long fp = frame->fp;
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 235+ messages in thread

* [PATCH v6 3/7] ftrace: Add arm64 support to recordmcount
  2014-03-13 10:13         ` AKASHI Takahiro
@ 2014-03-13 10:13           ` AKASHI Takahiro
  -1 siblings, 0 replies; 235+ messages in thread
From: AKASHI Takahiro @ 2014-03-13 10:13 UTC (permalink / raw)
  To: rostedt, fweisbec, mingo, catalin.marinas, will.deacon, tim.bird
  Cc: gkulkarni, dsaxena, arndb, linux-arm-kernel, linaro-kernel,
	linux-kernel, AKASHI Takahiro

Recordmcount utility under scripts is run, after compiling each object,
to find out all the locations of calling _mcount() and put them into
specific seciton named __mcount_loc.
Then linker collects all such information into a table in the kernel image
(between __start_mcount_loc and __stop_mcount_loc) for later use by ftrace.

This patch adds arm64 specific definitions to identify such locations.
There are two types of implementation, C and Perl. On arm64, only C version
is used to build the kernel now that CONFIG_HAVE_C_RECORDMCOUNT is on.
But Perl version is also maintained.

This patch also contains a workaround just in case where a header file,
elf.h, on host machine doesn't have definitions of EM_AARCH64 nor
R_AARCH64_ABS64. Without them, compiling C version of recordmcount will
fail.

Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
---
 arch/arm64/Kconfig      |    2 ++
 scripts/recordmcount.c  |    9 +++++++++
 scripts/recordmcount.pl |    5 +++++
 3 files changed, 16 insertions(+)

diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 27bbcfc..340e344 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -27,12 +27,14 @@ config ARM64
 	select HARDIRQS_SW_RESEND
 	select HAVE_ARCH_JUMP_LABEL
 	select HAVE_ARCH_TRACEHOOK
+	select HAVE_C_RECORDMCOUNT
 	select HAVE_DEBUG_BUGVERBOSE
 	select HAVE_DEBUG_KMEMLEAK
 	select HAVE_DMA_API_DEBUG
 	select HAVE_DMA_ATTRS
 	select HAVE_DMA_CONTIGUOUS
 	select HAVE_EFFICIENT_UNALIGNED_ACCESS
+	select HAVE_FTRACE_MCOUNT_RECORD
 	select HAVE_GENERIC_DMA_COHERENT
 	select HAVE_HW_BREAKPOINT if PERF_EVENTS
 	select HAVE_MEMBLOCK
diff --git a/scripts/recordmcount.c b/scripts/recordmcount.c
index 9c22317..047c8cd 100644
--- a/scripts/recordmcount.c
+++ b/scripts/recordmcount.c
@@ -40,6 +40,11 @@
 #define R_METAG_NONE                     3
 #endif
 
+#ifndef EM_AARCH64
+#define EM_AARCH64	183
+#define R_AARCH64_ABS64	257
+#endif
+
 static int fd_map;	/* File descriptor for file being modified. */
 static int mmap_failed; /* Boolean flag. */
 static void *ehdr_curr; /* current ElfXX_Ehdr *  for resource cleanup */
@@ -347,6 +352,10 @@ do_file(char const *const fname)
 	case EM_ARM:	 reltype = R_ARM_ABS32;
 			 altmcount = "__gnu_mcount_nc";
 			 break;
+	case EM_AARCH64:
+			 reltype = R_AARCH64_ABS64;
+			 altmcount = "_mcount";
+			 break;
 	case EM_IA_64:	 reltype = R_IA64_IMM64;   gpfx = '_'; break;
 	case EM_METAG:	 reltype = R_METAG_ADDR32;
 			 altmcount = "_mcount_wrapper";
diff --git a/scripts/recordmcount.pl b/scripts/recordmcount.pl
index 91280b8..397b6b8 100755
--- a/scripts/recordmcount.pl
+++ b/scripts/recordmcount.pl
@@ -279,6 +279,11 @@ if ($arch eq "x86_64") {
     $mcount_regex = "^\\s*([0-9a-fA-F]+):\\s*R_ARM_(CALL|PC24|THM_CALL)" .
 			"\\s+(__gnu_mcount_nc|mcount)\$";
 
+} elsif ($arch eq "arm64") {
+    $alignment = 3;
+    $section_type = '%progbits';
+    $mcount_regex = "^\\s*([0-9a-fA-F]+):\\s*R_AARCH64_CALL26\\s+_mcount\$";
+    $type = ".quad";
 } elsif ($arch eq "ia64") {
     $mcount_regex = "^\\s*([0-9a-fA-F]+):.*\\s_mcount\$";
     $type = "data8";
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 235+ messages in thread

* [PATCH v6 3/7] ftrace: Add arm64 support to recordmcount
@ 2014-03-13 10:13           ` AKASHI Takahiro
  0 siblings, 0 replies; 235+ messages in thread
From: AKASHI Takahiro @ 2014-03-13 10:13 UTC (permalink / raw)
  To: linux-arm-kernel

Recordmcount utility under scripts is run, after compiling each object,
to find out all the locations of calling _mcount() and put them into
specific seciton named __mcount_loc.
Then linker collects all such information into a table in the kernel image
(between __start_mcount_loc and __stop_mcount_loc) for later use by ftrace.

This patch adds arm64 specific definitions to identify such locations.
There are two types of implementation, C and Perl. On arm64, only C version
is used to build the kernel now that CONFIG_HAVE_C_RECORDMCOUNT is on.
But Perl version is also maintained.

This patch also contains a workaround just in case where a header file,
elf.h, on host machine doesn't have definitions of EM_AARCH64 nor
R_AARCH64_ABS64. Without them, compiling C version of recordmcount will
fail.

Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
---
 arch/arm64/Kconfig      |    2 ++
 scripts/recordmcount.c  |    9 +++++++++
 scripts/recordmcount.pl |    5 +++++
 3 files changed, 16 insertions(+)

diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 27bbcfc..340e344 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -27,12 +27,14 @@ config ARM64
 	select HARDIRQS_SW_RESEND
 	select HAVE_ARCH_JUMP_LABEL
 	select HAVE_ARCH_TRACEHOOK
+	select HAVE_C_RECORDMCOUNT
 	select HAVE_DEBUG_BUGVERBOSE
 	select HAVE_DEBUG_KMEMLEAK
 	select HAVE_DMA_API_DEBUG
 	select HAVE_DMA_ATTRS
 	select HAVE_DMA_CONTIGUOUS
 	select HAVE_EFFICIENT_UNALIGNED_ACCESS
+	select HAVE_FTRACE_MCOUNT_RECORD
 	select HAVE_GENERIC_DMA_COHERENT
 	select HAVE_HW_BREAKPOINT if PERF_EVENTS
 	select HAVE_MEMBLOCK
diff --git a/scripts/recordmcount.c b/scripts/recordmcount.c
index 9c22317..047c8cd 100644
--- a/scripts/recordmcount.c
+++ b/scripts/recordmcount.c
@@ -40,6 +40,11 @@
 #define R_METAG_NONE                     3
 #endif
 
+#ifndef EM_AARCH64
+#define EM_AARCH64	183
+#define R_AARCH64_ABS64	257
+#endif
+
 static int fd_map;	/* File descriptor for file being modified. */
 static int mmap_failed; /* Boolean flag. */
 static void *ehdr_curr; /* current ElfXX_Ehdr *  for resource cleanup */
@@ -347,6 +352,10 @@ do_file(char const *const fname)
 	case EM_ARM:	 reltype = R_ARM_ABS32;
 			 altmcount = "__gnu_mcount_nc";
 			 break;
+	case EM_AARCH64:
+			 reltype = R_AARCH64_ABS64;
+			 altmcount = "_mcount";
+			 break;
 	case EM_IA_64:	 reltype = R_IA64_IMM64;   gpfx = '_'; break;
 	case EM_METAG:	 reltype = R_METAG_ADDR32;
 			 altmcount = "_mcount_wrapper";
diff --git a/scripts/recordmcount.pl b/scripts/recordmcount.pl
index 91280b8..397b6b8 100755
--- a/scripts/recordmcount.pl
+++ b/scripts/recordmcount.pl
@@ -279,6 +279,11 @@ if ($arch eq "x86_64") {
     $mcount_regex = "^\\s*([0-9a-fA-F]+):\\s*R_ARM_(CALL|PC24|THM_CALL)" .
 			"\\s+(__gnu_mcount_nc|mcount)\$";
 
+} elsif ($arch eq "arm64") {
+    $alignment = 3;
+    $section_type = '%progbits';
+    $mcount_regex = "^\\s*([0-9a-fA-F]+):\\s*R_AARCH64_CALL26\\s+_mcount\$";
+    $type = ".quad";
 } elsif ($arch eq "ia64") {
     $mcount_regex = "^\\s*([0-9a-fA-F]+):.*\\s_mcount\$";
     $type = "data8";
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 235+ messages in thread

* [PATCH v6 4/7] arm64: Add ftrace support
  2014-03-13 10:13         ` AKASHI Takahiro
@ 2014-03-13 10:13           ` AKASHI Takahiro
  -1 siblings, 0 replies; 235+ messages in thread
From: AKASHI Takahiro @ 2014-03-13 10:13 UTC (permalink / raw)
  To: rostedt, fweisbec, mingo, catalin.marinas, will.deacon, tim.bird
  Cc: gkulkarni, dsaxena, arndb, linux-arm-kernel, linaro-kernel,
	linux-kernel, AKASHI Takahiro

This patch implements arm64 specific part to support function tracers,
such as function (CONFIG_FUNCTION_TRACER), function_graph
(CONFIG_FUNCTION_GRAPH_TRACER) and function profiler
(CONFIG_FUNCTION_PROFILER).

With 'function' tracer, all the functions in the kernel are traced with
timestamps in ${sysfs}/tracing/trace. If function_graph tracer is
specified, call graph is generated.

The kernel must be compiled with -pg option so that _mcount() is inserted
at the beginning of functions. This function is called on every function's
entry as long as tracing is enabled.
In addition, function_graph tracer also needs to be able to probe function's
exit. ftrace_graph_caller() & return_to_handler do this by faking link
register's value to intercept function's return path.

More details on architecture specific requirements are described in
Documentation/trace/ftrace-design.txt.

Reviewed-by: Ganapatrao Kulkarni <ganapatrao.kulkarni@cavium.com>
Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
---
 arch/arm64/Kconfig               |    2 +
 arch/arm64/include/asm/ftrace.h  |   23 +++++
 arch/arm64/kernel/Makefile       |    4 +
 arch/arm64/kernel/arm64ksyms.c   |    4 +
 arch/arm64/kernel/entry-ftrace.S |  175 ++++++++++++++++++++++++++++++++++++++
 arch/arm64/kernel/ftrace.c       |   64 ++++++++++++++
 6 files changed, 272 insertions(+)
 create mode 100644 arch/arm64/include/asm/ftrace.h
 create mode 100644 arch/arm64/kernel/entry-ftrace.S
 create mode 100644 arch/arm64/kernel/ftrace.c

diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 340e344..6b3fef6 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -35,6 +35,8 @@ config ARM64
 	select HAVE_DMA_CONTIGUOUS
 	select HAVE_EFFICIENT_UNALIGNED_ACCESS
 	select HAVE_FTRACE_MCOUNT_RECORD
+	select HAVE_FUNCTION_TRACER
+	select HAVE_FUNCTION_GRAPH_TRACER
 	select HAVE_GENERIC_DMA_COHERENT
 	select HAVE_HW_BREAKPOINT if PERF_EVENTS
 	select HAVE_MEMBLOCK
diff --git a/arch/arm64/include/asm/ftrace.h b/arch/arm64/include/asm/ftrace.h
new file mode 100644
index 0000000..58ea595
--- /dev/null
+++ b/arch/arm64/include/asm/ftrace.h
@@ -0,0 +1,23 @@
+/*
+ * arch/arm64/include/asm/ftrace.h
+ *
+ * Copyright (C) 2013 Linaro Limited
+ * Author: AKASHI Takahiro <takahiro.akashi@linaro.org>
+ *
+ * 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.
+ */
+#ifndef __ASM_FTRACE_H
+#define __ASM_FTRACE_H
+
+#include <asm/insn.h>
+
+#define MCOUNT_ADDR		((unsigned long)_mcount)
+#define MCOUNT_INSN_SIZE	AARCH64_INSN_SIZE
+
+#ifndef __ASSEMBLY__
+extern void _mcount(unsigned long);
+#endif /* __ASSEMBLY__ */
+
+#endif /* __ASM_FTRACE_H */
diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile
index 2d4554b..ac67fd0 100644
--- a/arch/arm64/kernel/Makefile
+++ b/arch/arm64/kernel/Makefile
@@ -5,6 +5,9 @@
 CPPFLAGS_vmlinux.lds	:= -DTEXT_OFFSET=$(TEXT_OFFSET)
 AFLAGS_head.o		:= -DTEXT_OFFSET=$(TEXT_OFFSET)
 
+CFLAGS_REMOVE_ftrace.o = -pg
+CFLAGS_REMOVE_insn.o = -pg
+
 # Object file lists.
 arm64-obj-y		:= cputable.o debug-monitors.o entry.o irq.o fpsimd.o	\
 			   entry-fpsimd.o process.o ptrace.o setup.o signal.o	\
@@ -13,6 +16,7 @@ arm64-obj-y		:= cputable.o debug-monitors.o entry.o irq.o fpsimd.o	\
 
 arm64-obj-$(CONFIG_COMPAT)		+= sys32.o kuser32.o signal32.o 	\
 					   sys_compat.o
+arm64-obj-$(CONFIG_FUNCTION_TRACER)	+= ftrace.o entry-ftrace.o
 arm64-obj-$(CONFIG_MODULES)		+= arm64ksyms.o module.o
 arm64-obj-$(CONFIG_SMP)			+= smp.o smp_spin_table.o
 arm64-obj-$(CONFIG_HW_PERF_EVENTS)	+= perf_event.o
diff --git a/arch/arm64/kernel/arm64ksyms.c b/arch/arm64/kernel/arm64ksyms.c
index 338b568..7f0512f 100644
--- a/arch/arm64/kernel/arm64ksyms.c
+++ b/arch/arm64/kernel/arm64ksyms.c
@@ -56,3 +56,7 @@ EXPORT_SYMBOL(clear_bit);
 EXPORT_SYMBOL(test_and_clear_bit);
 EXPORT_SYMBOL(change_bit);
 EXPORT_SYMBOL(test_and_change_bit);
+
+#ifdef CONFIG_FUNCTION_TRACER
+EXPORT_SYMBOL(_mcount);
+#endif
diff --git a/arch/arm64/kernel/entry-ftrace.S b/arch/arm64/kernel/entry-ftrace.S
new file mode 100644
index 0000000..0ac31c8
--- /dev/null
+++ b/arch/arm64/kernel/entry-ftrace.S
@@ -0,0 +1,175 @@
+/*
+ * arch/arm64/kernel/entry-ftrace.S
+ *
+ * Copyright (C) 2013 Linaro Limited
+ * Author: AKASHI Takahiro <takahiro.akashi@linaro.org>
+ *
+ * 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 <linux/linkage.h>
+#include <asm/ftrace.h>
+#include <asm/insn.h>
+
+/*
+ * Gcc with -pg will put the following code in the beginning of each function:
+ *      mov x0, x30
+ *      bl _mcount
+ *	[function's body ...]
+ * "bl _mcount" may be replaced to "bl ftrace_caller" or NOP if dynamic
+ * ftrace is enabled.
+ *
+ * Please note that x0 as an argument will not be used here because we can
+ * get lr(x30) of instrumented function at any time by winding up call stack
+ * as long as the kernel is compiled without -fomit-frame-pointer.
+ * (or CONFIG_FRAME_POINTER, this is forced on arm64)
+ *
+ * stack layout after mcount_enter in _mcount():
+ *
+ * current sp/fp =>  0:+-----+
+ * in _mcount()	       | x29 | -> instrumented function's fp
+ *		       +-----+
+ *		       | x30 | -> _mcount()'s lr (= instrumented function's pc)
+ * old sp	=> +16:+-----+
+ * when instrumented   |     |
+ * function calls      | ... |
+ * _mcount()	       |     |
+ *		       |     |
+ * instrumented => +xx:+-----+
+ * function's fp       | x29 | -> parent's fp
+ *		       +-----+
+ *		       | x30 | -> instrumented function's lr (= parent's pc)
+ *		       +-----+
+ *		       | ... |
+ */
+
+	.macro mcount_enter
+	stp	x29, x30, [sp, #-16]!
+	mov	x29, sp
+	.endm
+
+	.macro mcount_exit
+	ldp	x29, x30, [sp], #16
+	ret
+	.endm
+
+	.macro mcount_adjust_addr rd, rn
+	sub	\rd, \rn, #AARCH64_INSN_SIZE
+	.endm
+
+	/* for instrumented function's parent */
+	.macro mcount_get_parent_fp reg
+	ldr	\reg, [x29]
+	ldr	\reg, [\reg]
+	.endm
+
+	/* for instrumented function */
+	.macro mcount_get_pc0 reg
+	mcount_adjust_addr	\reg, x30
+	.endm
+
+	.macro mcount_get_pc reg
+	ldr	\reg, [x29, #8]
+	mcount_adjust_addr	\reg, \reg
+	.endm
+
+	.macro mcount_get_lr reg
+	ldr	\reg, [x29]
+	ldr	\reg, [\reg, #8]
+	mcount_adjust_addr	\reg, \reg
+	.endm
+
+	.macro mcount_get_lr_addr reg
+	ldr	\reg, [x29]
+	add	\reg, \reg, #8
+	.endm
+
+/*
+ * void _mcount(unsigned long return_address)
+ * @return_address: return address to instrumented function
+ *
+ * This function makes calls, if enabled, to:
+ *     - tracer function to probe instrumented function's entry,
+ *     - ftrace_graph_caller to set up an exit hook
+ */
+ENTRY(_mcount)
+#ifdef CONFIG_HAVE_FUNCTION_TRACE_MCOUNT_TEST
+	ldr	x0, =ftrace_trace_stop
+	ldr	x0, [x0]		// if ftrace_trace_stop
+	ret				//   return;
+#endif
+	mcount_enter
+
+	ldr	x0, =ftrace_trace_function
+	ldr	x2, [x0]
+	adr	x0, ftrace_stub
+	cmp	x0, x2			// if (ftrace_trace_function
+	b.eq	skip_ftrace_call	//     != ftrace_stub) {
+
+	mcount_get_pc	x0		//       function's pc
+	mcount_get_lr	x1		//       function's lr (= parent's pc)
+	blr	x2			//   (*ftrace_trace_function)(pc, lr);
+
+#ifndef CONFIG_FUNCTION_GRAPH_TRACER
+skip_ftrace_call:			//   return;
+	mcount_exit			// }
+#else
+	mcount_exit			//   return;
+					// }
+skip_ftrace_call:
+	ldr	x1, =ftrace_graph_return
+	ldr	x2, [x1]		//   if ((ftrace_graph_return
+	cmp	x0, x2			//        != ftrace_stub)
+	b.ne	ftrace_graph_caller
+
+	ldr	x1, =ftrace_graph_entry	//     || (ftrace_graph_entry
+	ldr	x2, [x1]		//        != ftrace_graph_entry_stub))
+	ldr	x0, =ftrace_graph_entry_stub
+	cmp	x0, x2
+	b.ne	ftrace_graph_caller	//     ftrace_graph_caller();
+
+	mcount_exit
+#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
+ENDPROC(_mcount)
+
+ENTRY(ftrace_stub)
+	ret
+ENDPROC(ftrace_stub)
+
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+/*
+ * void ftrace_graph_caller(void)
+ *
+ * Called from _mcount() or ftrace_caller() when function_graph tracer is
+ * selected.
+ * This function w/ prepare_ftrace_return() fakes link register's value on
+ * the call stack in order to intercept instrumented function's return path
+ * and run return_to_handler() later on its exit.
+ */
+ENTRY(ftrace_graph_caller)
+	mcount_get_lr_addr	  x0	//     pointer to function's saved lr
+	mcount_get_pc		  x1	//     function's pc
+	mcount_get_parent_fp	  x2	//     parent's fp
+	bl	prepare_ftrace_return	// prepare_ftrace_return(&lr, pc, fp)
+
+	mcount_exit
+ENDPROC(ftrace_graph_caller)
+
+/*
+ * void return_to_handler(void)
+ *
+ * Run ftrace_return_to_handler() before going back to parent.
+ * @fp is checked against the value passed by ftrace_graph_caller()
+ * only when CONFIG_FUNCTION_GRAPH_FP_TEST is enabled.
+ */
+	.global return_to_handler
+return_to_handler:
+	str	x0, [sp, #-16]!
+	mov	x0, x29			//     parent's fp
+	bl	ftrace_return_to_handler// addr = ftrace_return_to_hander(fp);
+	mov	x30, x0			// restore the original return address
+	ldr	x0, [sp], #16
+	ret
+#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
diff --git a/arch/arm64/kernel/ftrace.c b/arch/arm64/kernel/ftrace.c
new file mode 100644
index 0000000..a559ab8
--- /dev/null
+++ b/arch/arm64/kernel/ftrace.c
@@ -0,0 +1,64 @@
+/*
+ * arch/arm64/kernel/ftrace.c
+ *
+ * Copyright (C) 2013 Linaro Limited
+ * Author: AKASHI Takahiro <takahiro.akashi@linaro.org>
+ *
+ * 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 <linux/ftrace.h>
+#include <linux/swab.h>
+#include <linux/uaccess.h>
+
+#include <asm/cacheflush.h>
+#include <asm/ftrace.h>
+#include <asm/insn.h>
+
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+/*
+ * function_graph tracer expects ftrace_return_to_handler() to be called
+ * on the way back to parent. For this purpose, this function is called
+ * in _mcount() or ftrace_caller() to replace return address (*parent) on
+ * the call stack to return_to_handler.
+ *
+ * Note that @frame_pointer is used only for sanity check later.
+ */
+void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr,
+			   unsigned long frame_pointer)
+{
+	unsigned long return_hooker = (unsigned long)&return_to_handler;
+	unsigned long old;
+	struct ftrace_graph_ent trace;
+	int err;
+
+	if (unlikely(atomic_read(&current->tracing_graph_pause)))
+		return;
+
+	/*
+	 * Note:
+	 * No protection against faulting at *parent, which may be seen
+	 * on other archs. It's unlikely on AArch64.
+	 */
+	old = *parent;
+	*parent = return_hooker;
+
+	trace.func = self_addr;
+	trace.depth = current->curr_ret_stack + 1;
+
+	/* Only trace if the calling function expects to */
+	if (!ftrace_graph_entry(&trace)) {
+		*parent = old;
+		return;
+	}
+
+	err = ftrace_push_return_trace(old, self_addr, &trace.depth,
+				       frame_pointer);
+	if (err == -EBUSY) {
+		*parent = old;
+		return;
+	}
+}
+#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 235+ messages in thread

* [PATCH v6 4/7] arm64: Add ftrace support
@ 2014-03-13 10:13           ` AKASHI Takahiro
  0 siblings, 0 replies; 235+ messages in thread
From: AKASHI Takahiro @ 2014-03-13 10:13 UTC (permalink / raw)
  To: linux-arm-kernel

This patch implements arm64 specific part to support function tracers,
such as function (CONFIG_FUNCTION_TRACER), function_graph
(CONFIG_FUNCTION_GRAPH_TRACER) and function profiler
(CONFIG_FUNCTION_PROFILER).

With 'function' tracer, all the functions in the kernel are traced with
timestamps in ${sysfs}/tracing/trace. If function_graph tracer is
specified, call graph is generated.

The kernel must be compiled with -pg option so that _mcount() is inserted
at the beginning of functions. This function is called on every function's
entry as long as tracing is enabled.
In addition, function_graph tracer also needs to be able to probe function's
exit. ftrace_graph_caller() & return_to_handler do this by faking link
register's value to intercept function's return path.

More details on architecture specific requirements are described in
Documentation/trace/ftrace-design.txt.

Reviewed-by: Ganapatrao Kulkarni <ganapatrao.kulkarni@cavium.com>
Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
---
 arch/arm64/Kconfig               |    2 +
 arch/arm64/include/asm/ftrace.h  |   23 +++++
 arch/arm64/kernel/Makefile       |    4 +
 arch/arm64/kernel/arm64ksyms.c   |    4 +
 arch/arm64/kernel/entry-ftrace.S |  175 ++++++++++++++++++++++++++++++++++++++
 arch/arm64/kernel/ftrace.c       |   64 ++++++++++++++
 6 files changed, 272 insertions(+)
 create mode 100644 arch/arm64/include/asm/ftrace.h
 create mode 100644 arch/arm64/kernel/entry-ftrace.S
 create mode 100644 arch/arm64/kernel/ftrace.c

diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 340e344..6b3fef6 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -35,6 +35,8 @@ config ARM64
 	select HAVE_DMA_CONTIGUOUS
 	select HAVE_EFFICIENT_UNALIGNED_ACCESS
 	select HAVE_FTRACE_MCOUNT_RECORD
+	select HAVE_FUNCTION_TRACER
+	select HAVE_FUNCTION_GRAPH_TRACER
 	select HAVE_GENERIC_DMA_COHERENT
 	select HAVE_HW_BREAKPOINT if PERF_EVENTS
 	select HAVE_MEMBLOCK
diff --git a/arch/arm64/include/asm/ftrace.h b/arch/arm64/include/asm/ftrace.h
new file mode 100644
index 0000000..58ea595
--- /dev/null
+++ b/arch/arm64/include/asm/ftrace.h
@@ -0,0 +1,23 @@
+/*
+ * arch/arm64/include/asm/ftrace.h
+ *
+ * Copyright (C) 2013 Linaro Limited
+ * Author: AKASHI Takahiro <takahiro.akashi@linaro.org>
+ *
+ * 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.
+ */
+#ifndef __ASM_FTRACE_H
+#define __ASM_FTRACE_H
+
+#include <asm/insn.h>
+
+#define MCOUNT_ADDR		((unsigned long)_mcount)
+#define MCOUNT_INSN_SIZE	AARCH64_INSN_SIZE
+
+#ifndef __ASSEMBLY__
+extern void _mcount(unsigned long);
+#endif /* __ASSEMBLY__ */
+
+#endif /* __ASM_FTRACE_H */
diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile
index 2d4554b..ac67fd0 100644
--- a/arch/arm64/kernel/Makefile
+++ b/arch/arm64/kernel/Makefile
@@ -5,6 +5,9 @@
 CPPFLAGS_vmlinux.lds	:= -DTEXT_OFFSET=$(TEXT_OFFSET)
 AFLAGS_head.o		:= -DTEXT_OFFSET=$(TEXT_OFFSET)
 
+CFLAGS_REMOVE_ftrace.o = -pg
+CFLAGS_REMOVE_insn.o = -pg
+
 # Object file lists.
 arm64-obj-y		:= cputable.o debug-monitors.o entry.o irq.o fpsimd.o	\
 			   entry-fpsimd.o process.o ptrace.o setup.o signal.o	\
@@ -13,6 +16,7 @@ arm64-obj-y		:= cputable.o debug-monitors.o entry.o irq.o fpsimd.o	\
 
 arm64-obj-$(CONFIG_COMPAT)		+= sys32.o kuser32.o signal32.o 	\
 					   sys_compat.o
+arm64-obj-$(CONFIG_FUNCTION_TRACER)	+= ftrace.o entry-ftrace.o
 arm64-obj-$(CONFIG_MODULES)		+= arm64ksyms.o module.o
 arm64-obj-$(CONFIG_SMP)			+= smp.o smp_spin_table.o
 arm64-obj-$(CONFIG_HW_PERF_EVENTS)	+= perf_event.o
diff --git a/arch/arm64/kernel/arm64ksyms.c b/arch/arm64/kernel/arm64ksyms.c
index 338b568..7f0512f 100644
--- a/arch/arm64/kernel/arm64ksyms.c
+++ b/arch/arm64/kernel/arm64ksyms.c
@@ -56,3 +56,7 @@ EXPORT_SYMBOL(clear_bit);
 EXPORT_SYMBOL(test_and_clear_bit);
 EXPORT_SYMBOL(change_bit);
 EXPORT_SYMBOL(test_and_change_bit);
+
+#ifdef CONFIG_FUNCTION_TRACER
+EXPORT_SYMBOL(_mcount);
+#endif
diff --git a/arch/arm64/kernel/entry-ftrace.S b/arch/arm64/kernel/entry-ftrace.S
new file mode 100644
index 0000000..0ac31c8
--- /dev/null
+++ b/arch/arm64/kernel/entry-ftrace.S
@@ -0,0 +1,175 @@
+/*
+ * arch/arm64/kernel/entry-ftrace.S
+ *
+ * Copyright (C) 2013 Linaro Limited
+ * Author: AKASHI Takahiro <takahiro.akashi@linaro.org>
+ *
+ * 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 <linux/linkage.h>
+#include <asm/ftrace.h>
+#include <asm/insn.h>
+
+/*
+ * Gcc with -pg will put the following code in the beginning of each function:
+ *      mov x0, x30
+ *      bl _mcount
+ *	[function's body ...]
+ * "bl _mcount" may be replaced to "bl ftrace_caller" or NOP if dynamic
+ * ftrace is enabled.
+ *
+ * Please note that x0 as an argument will not be used here because we can
+ * get lr(x30) of instrumented function at any time by winding up call stack
+ * as long as the kernel is compiled without -fomit-frame-pointer.
+ * (or CONFIG_FRAME_POINTER, this is forced on arm64)
+ *
+ * stack layout after mcount_enter in _mcount():
+ *
+ * current sp/fp =>  0:+-----+
+ * in _mcount()	       | x29 | -> instrumented function's fp
+ *		       +-----+
+ *		       | x30 | -> _mcount()'s lr (= instrumented function's pc)
+ * old sp	=> +16:+-----+
+ * when instrumented   |     |
+ * function calls      | ... |
+ * _mcount()	       |     |
+ *		       |     |
+ * instrumented => +xx:+-----+
+ * function's fp       | x29 | -> parent's fp
+ *		       +-----+
+ *		       | x30 | -> instrumented function's lr (= parent's pc)
+ *		       +-----+
+ *		       | ... |
+ */
+
+	.macro mcount_enter
+	stp	x29, x30, [sp, #-16]!
+	mov	x29, sp
+	.endm
+
+	.macro mcount_exit
+	ldp	x29, x30, [sp], #16
+	ret
+	.endm
+
+	.macro mcount_adjust_addr rd, rn
+	sub	\rd, \rn, #AARCH64_INSN_SIZE
+	.endm
+
+	/* for instrumented function's parent */
+	.macro mcount_get_parent_fp reg
+	ldr	\reg, [x29]
+	ldr	\reg, [\reg]
+	.endm
+
+	/* for instrumented function */
+	.macro mcount_get_pc0 reg
+	mcount_adjust_addr	\reg, x30
+	.endm
+
+	.macro mcount_get_pc reg
+	ldr	\reg, [x29, #8]
+	mcount_adjust_addr	\reg, \reg
+	.endm
+
+	.macro mcount_get_lr reg
+	ldr	\reg, [x29]
+	ldr	\reg, [\reg, #8]
+	mcount_adjust_addr	\reg, \reg
+	.endm
+
+	.macro mcount_get_lr_addr reg
+	ldr	\reg, [x29]
+	add	\reg, \reg, #8
+	.endm
+
+/*
+ * void _mcount(unsigned long return_address)
+ * @return_address: return address to instrumented function
+ *
+ * This function makes calls, if enabled, to:
+ *     - tracer function to probe instrumented function's entry,
+ *     - ftrace_graph_caller to set up an exit hook
+ */
+ENTRY(_mcount)
+#ifdef CONFIG_HAVE_FUNCTION_TRACE_MCOUNT_TEST
+	ldr	x0, =ftrace_trace_stop
+	ldr	x0, [x0]		// if ftrace_trace_stop
+	ret				//   return;
+#endif
+	mcount_enter
+
+	ldr	x0, =ftrace_trace_function
+	ldr	x2, [x0]
+	adr	x0, ftrace_stub
+	cmp	x0, x2			// if (ftrace_trace_function
+	b.eq	skip_ftrace_call	//     != ftrace_stub) {
+
+	mcount_get_pc	x0		//       function's pc
+	mcount_get_lr	x1		//       function's lr (= parent's pc)
+	blr	x2			//   (*ftrace_trace_function)(pc, lr);
+
+#ifndef CONFIG_FUNCTION_GRAPH_TRACER
+skip_ftrace_call:			//   return;
+	mcount_exit			// }
+#else
+	mcount_exit			//   return;
+					// }
+skip_ftrace_call:
+	ldr	x1, =ftrace_graph_return
+	ldr	x2, [x1]		//   if ((ftrace_graph_return
+	cmp	x0, x2			//        != ftrace_stub)
+	b.ne	ftrace_graph_caller
+
+	ldr	x1, =ftrace_graph_entry	//     || (ftrace_graph_entry
+	ldr	x2, [x1]		//        != ftrace_graph_entry_stub))
+	ldr	x0, =ftrace_graph_entry_stub
+	cmp	x0, x2
+	b.ne	ftrace_graph_caller	//     ftrace_graph_caller();
+
+	mcount_exit
+#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
+ENDPROC(_mcount)
+
+ENTRY(ftrace_stub)
+	ret
+ENDPROC(ftrace_stub)
+
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+/*
+ * void ftrace_graph_caller(void)
+ *
+ * Called from _mcount() or ftrace_caller() when function_graph tracer is
+ * selected.
+ * This function w/ prepare_ftrace_return() fakes link register's value on
+ * the call stack in order to intercept instrumented function's return path
+ * and run return_to_handler() later on its exit.
+ */
+ENTRY(ftrace_graph_caller)
+	mcount_get_lr_addr	  x0	//     pointer to function's saved lr
+	mcount_get_pc		  x1	//     function's pc
+	mcount_get_parent_fp	  x2	//     parent's fp
+	bl	prepare_ftrace_return	// prepare_ftrace_return(&lr, pc, fp)
+
+	mcount_exit
+ENDPROC(ftrace_graph_caller)
+
+/*
+ * void return_to_handler(void)
+ *
+ * Run ftrace_return_to_handler() before going back to parent.
+ * @fp is checked against the value passed by ftrace_graph_caller()
+ * only when CONFIG_FUNCTION_GRAPH_FP_TEST is enabled.
+ */
+	.global return_to_handler
+return_to_handler:
+	str	x0, [sp, #-16]!
+	mov	x0, x29			//     parent's fp
+	bl	ftrace_return_to_handler// addr = ftrace_return_to_hander(fp);
+	mov	x30, x0			// restore the original return address
+	ldr	x0, [sp], #16
+	ret
+#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
diff --git a/arch/arm64/kernel/ftrace.c b/arch/arm64/kernel/ftrace.c
new file mode 100644
index 0000000..a559ab8
--- /dev/null
+++ b/arch/arm64/kernel/ftrace.c
@@ -0,0 +1,64 @@
+/*
+ * arch/arm64/kernel/ftrace.c
+ *
+ * Copyright (C) 2013 Linaro Limited
+ * Author: AKASHI Takahiro <takahiro.akashi@linaro.org>
+ *
+ * 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 <linux/ftrace.h>
+#include <linux/swab.h>
+#include <linux/uaccess.h>
+
+#include <asm/cacheflush.h>
+#include <asm/ftrace.h>
+#include <asm/insn.h>
+
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+/*
+ * function_graph tracer expects ftrace_return_to_handler() to be called
+ * on the way back to parent. For this purpose, this function is called
+ * in _mcount() or ftrace_caller() to replace return address (*parent) on
+ * the call stack to return_to_handler.
+ *
+ * Note that @frame_pointer is used only for sanity check later.
+ */
+void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr,
+			   unsigned long frame_pointer)
+{
+	unsigned long return_hooker = (unsigned long)&return_to_handler;
+	unsigned long old;
+	struct ftrace_graph_ent trace;
+	int err;
+
+	if (unlikely(atomic_read(&current->tracing_graph_pause)))
+		return;
+
+	/*
+	 * Note:
+	 * No protection against faulting at *parent, which may be seen
+	 * on other archs. It's unlikely on AArch64.
+	 */
+	old = *parent;
+	*parent = return_hooker;
+
+	trace.func = self_addr;
+	trace.depth = current->curr_ret_stack + 1;
+
+	/* Only trace if the calling function expects to */
+	if (!ftrace_graph_entry(&trace)) {
+		*parent = old;
+		return;
+	}
+
+	err = ftrace_push_return_trace(old, self_addr, &trace.depth,
+				       frame_pointer);
+	if (err == -EBUSY) {
+		*parent = old;
+		return;
+	}
+}
+#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 235+ messages in thread

* [PATCH v6 5/7] arm64: ftrace: Add dynamic ftrace support
  2014-03-13 10:13         ` AKASHI Takahiro
@ 2014-03-13 10:13           ` AKASHI Takahiro
  -1 siblings, 0 replies; 235+ messages in thread
From: AKASHI Takahiro @ 2014-03-13 10:13 UTC (permalink / raw)
  To: rostedt, fweisbec, mingo, catalin.marinas, will.deacon, tim.bird
  Cc: gkulkarni, dsaxena, arndb, linux-arm-kernel, linaro-kernel,
	linux-kernel, AKASHI Takahiro

This patch allows "dynamic ftrace" if CONFIG_DYNAMIC_FTRACE is enabled.
Here we can turn on and off tracing dynamically per-function base.

On arm64, this is done by patching single branch instruction to _mcount()
inserted by gcc -pg option. The branch is replaced to NOP initially at
kernel start up, and later on, NOP to branch to ftrace_caller() when
enabled or branch to NOP when disabled.
Please note that ftrace_caller() is a counterpart of _mcount() in case of
'static' ftrace.

More details on architecture specific requirements are described in
Documentation/trace/ftrace-design.txt.

Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
---
 arch/arm64/Kconfig               |    1 +
 arch/arm64/include/asm/ftrace.h  |   15 +++++
 arch/arm64/kernel/entry-ftrace.S |   43 +++++++++++++++
 arch/arm64/kernel/ftrace.c       |  113 ++++++++++++++++++++++++++++++++++++++
 4 files changed, 172 insertions(+)

diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 6b3fef6..6954959 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -33,6 +33,7 @@ config ARM64
 	select HAVE_DMA_API_DEBUG
 	select HAVE_DMA_ATTRS
 	select HAVE_DMA_CONTIGUOUS
+	select HAVE_DYNAMIC_FTRACE
 	select HAVE_EFFICIENT_UNALIGNED_ACCESS
 	select HAVE_FTRACE_MCOUNT_RECORD
 	select HAVE_FUNCTION_TRACER
diff --git a/arch/arm64/include/asm/ftrace.h b/arch/arm64/include/asm/ftrace.h
index 58ea595..ed5c448 100644
--- a/arch/arm64/include/asm/ftrace.h
+++ b/arch/arm64/include/asm/ftrace.h
@@ -18,6 +18,21 @@
 
 #ifndef __ASSEMBLY__
 extern void _mcount(unsigned long);
+
+struct dyn_arch_ftrace {
+	/* No extra data needed for arm64 */
+};
+
+extern unsigned long ftrace_graph_call;
+
+static inline unsigned long ftrace_call_adjust(unsigned long addr)
+{
+	/*
+	 * addr is the address of the mcount call instruction.
+	 * recordmcount does the necessary offset calculation.
+	 */
+	return addr;
+}
 #endif /* __ASSEMBLY__ */
 
 #endif /* __ASM_FTRACE_H */
diff --git a/arch/arm64/kernel/entry-ftrace.S b/arch/arm64/kernel/entry-ftrace.S
index 0ac31c8..c0fbe10 100644
--- a/arch/arm64/kernel/entry-ftrace.S
+++ b/arch/arm64/kernel/entry-ftrace.S
@@ -86,6 +86,7 @@
 	add	\reg, \reg, #8
 	.endm
 
+#ifndef CONFIG_DYNAMIC_FTRACE
 /*
  * void _mcount(unsigned long return_address)
  * @return_address: return address to instrumented function
@@ -134,6 +135,48 @@ skip_ftrace_call:
 #endif /* CONFIG_FUNCTION_GRAPH_TRACER */
 ENDPROC(_mcount)
 
+#else /* CONFIG_DYNAMIC_FTRACE */
+/*
+ * _mcount() is used to build the kernel with -pg option, but all the branch
+ * instructions to _mcount() are replaced to NOP initially at kernel start up,
+ * and later on, NOP to branch to ftrace_caller() when enabled or branch to
+ * NOP when disabled per-function base.
+ */
+ENTRY(_mcount)
+	ret
+ENDPROC(_mcount)
+
+/*
+ * void ftrace_caller(unsigned long return_address)
+ * @return_address: return address to instrumented function
+ *
+ * This function is a counterpart of _mcount() in 'static' ftrace, and
+ * makes calls to:
+ *     - tracer function to probe instrumented function's entry,
+ *     - ftrace_graph_caller to set up an exit hook
+ */
+ENTRY(ftrace_caller)
+	mcount_enter
+
+	mcount_get_pc0	x0		//     function's pc
+	mcount_get_lr	x1		//     function's lr
+
+	.global ftrace_call
+ftrace_call:				// tracer(pc, lr);
+	nop				// This will be replaced with "bl xxx"
+					// where xxx can be any kind of tracer.
+
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+	.global ftrace_graph_call
+ftrace_graph_call:			// ftrace_graph_caller();
+	nop				// If enabled, this will be replaced
+					// "b ftrace_graph_caller"
+#endif
+
+	mcount_exit
+ENDPROC(ftrace_caller)
+#endif /* CONFIG_DYNAMIC_FTRACE */
+
 ENTRY(ftrace_stub)
 	ret
 ENDPROC(ftrace_stub)
diff --git a/arch/arm64/kernel/ftrace.c b/arch/arm64/kernel/ftrace.c
index a559ab8..8c26476 100644
--- a/arch/arm64/kernel/ftrace.c
+++ b/arch/arm64/kernel/ftrace.c
@@ -17,6 +17,89 @@
 #include <asm/ftrace.h>
 #include <asm/insn.h>
 
+#ifdef CONFIG_DYNAMIC_FTRACE
+/*
+ * Replace a single instruction, which may be a branch or NOP.
+ * If @validate == true, a replaced instruction is checked against 'old'.
+ */
+static int ftrace_modify_code(unsigned long pc, unsigned int old,
+			      unsigned int new, bool validate)
+{
+	unsigned int replaced;
+
+	/*
+	 * Note:
+	 * Due to modules and __init, code can disappear and change,
+	 * we need to protect against faulting as well as code changing.
+	 * We do this by aarch64_insn_*() which use the probe_kernel_*().
+	 *
+	 * No lock is held here because all the modifications are run
+	 * through stop_machine().
+	 */
+	if (validate) {
+		if (aarch64_insn_read((void *)pc, &replaced))
+			return -EFAULT;
+
+		if (replaced != old)
+			return -EINVAL;
+	}
+	if (aarch64_insn_patch_text_nosync((void *)pc, new))
+		return -EPERM;
+
+	return 0;
+}
+
+/*
+ * Replace tracer function in ftrace_caller()
+ */
+int ftrace_update_ftrace_func(ftrace_func_t func)
+{
+	unsigned long pc;
+	unsigned int new;
+
+	pc = (unsigned long)&ftrace_call;
+	new = aarch64_insn_gen_branch_imm(pc, (unsigned long)func, true);
+
+	return ftrace_modify_code(pc, 0, new, false);
+}
+
+/*
+ * Turn on the call to ftrace_caller() in instrumented function
+ */
+int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
+{
+	unsigned long pc = rec->ip;
+	unsigned int old, new;
+
+	old = aarch64_insn_gen_nop();
+	new = aarch64_insn_gen_branch_imm(pc, addr, true);
+
+	return ftrace_modify_code(pc, old, new, true);
+}
+
+/*
+ * Turn off the call to ftrace_caller() in instrumented function
+ */
+int ftrace_make_nop(struct module *mod,
+		    struct dyn_ftrace *rec, unsigned long addr)
+{
+	unsigned long pc = rec->ip;
+	unsigned int old, new;
+
+	old = aarch64_insn_gen_branch_imm(pc, addr, true);
+	new = aarch64_insn_gen_nop();
+
+	return ftrace_modify_code(pc, old, new, true);
+}
+
+int __init ftrace_dyn_arch_init(void *data)
+{
+	*(unsigned long *)data = 0;
+
+	return 0;
+}
+#endif /* CONFIG_DYNAMIC_FTRACE */
+
 #ifdef CONFIG_FUNCTION_GRAPH_TRACER
 /*
  * function_graph tracer expects ftrace_return_to_handler() to be called
@@ -61,4 +144,34 @@ void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr,
 		return;
 	}
 }
+
+#ifdef CONFIG_DYNAMIC_FTRACE
+/*
+ * Turn on/off the call to ftrace_graph_caller() in ftrace_caller()
+ * depending on @enable.
+ */
+static int ftrace_modify_graph_caller(bool enable)
+{
+	unsigned long pc = (unsigned long)&ftrace_graph_call;
+	unsigned int branch, nop, old, new;
+
+	branch = aarch64_insn_gen_branch_imm(pc,
+			(unsigned long)ftrace_graph_caller, false);
+	nop = aarch64_insn_gen_nop();
+	old = enable ? nop : branch;
+	new = enable ? branch : nop;
+
+	return ftrace_modify_code(pc, old, new, true);
+}
+
+int ftrace_enable_ftrace_graph_caller(void)
+{
+	return ftrace_modify_graph_caller(true);
+}
+
+int ftrace_disable_ftrace_graph_caller(void)
+{
+	return ftrace_modify_graph_caller(false);
+}
+#endif /* CONFIG_DYNAMIC_FTRACE */
 #endif /* CONFIG_FUNCTION_GRAPH_TRACER */
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 235+ messages in thread

* [PATCH v6 5/7] arm64: ftrace: Add dynamic ftrace support
@ 2014-03-13 10:13           ` AKASHI Takahiro
  0 siblings, 0 replies; 235+ messages in thread
From: AKASHI Takahiro @ 2014-03-13 10:13 UTC (permalink / raw)
  To: linux-arm-kernel

This patch allows "dynamic ftrace" if CONFIG_DYNAMIC_FTRACE is enabled.
Here we can turn on and off tracing dynamically per-function base.

On arm64, this is done by patching single branch instruction to _mcount()
inserted by gcc -pg option. The branch is replaced to NOP initially at
kernel start up, and later on, NOP to branch to ftrace_caller() when
enabled or branch to NOP when disabled.
Please note that ftrace_caller() is a counterpart of _mcount() in case of
'static' ftrace.

More details on architecture specific requirements are described in
Documentation/trace/ftrace-design.txt.

Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
---
 arch/arm64/Kconfig               |    1 +
 arch/arm64/include/asm/ftrace.h  |   15 +++++
 arch/arm64/kernel/entry-ftrace.S |   43 +++++++++++++++
 arch/arm64/kernel/ftrace.c       |  113 ++++++++++++++++++++++++++++++++++++++
 4 files changed, 172 insertions(+)

diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 6b3fef6..6954959 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -33,6 +33,7 @@ config ARM64
 	select HAVE_DMA_API_DEBUG
 	select HAVE_DMA_ATTRS
 	select HAVE_DMA_CONTIGUOUS
+	select HAVE_DYNAMIC_FTRACE
 	select HAVE_EFFICIENT_UNALIGNED_ACCESS
 	select HAVE_FTRACE_MCOUNT_RECORD
 	select HAVE_FUNCTION_TRACER
diff --git a/arch/arm64/include/asm/ftrace.h b/arch/arm64/include/asm/ftrace.h
index 58ea595..ed5c448 100644
--- a/arch/arm64/include/asm/ftrace.h
+++ b/arch/arm64/include/asm/ftrace.h
@@ -18,6 +18,21 @@
 
 #ifndef __ASSEMBLY__
 extern void _mcount(unsigned long);
+
+struct dyn_arch_ftrace {
+	/* No extra data needed for arm64 */
+};
+
+extern unsigned long ftrace_graph_call;
+
+static inline unsigned long ftrace_call_adjust(unsigned long addr)
+{
+	/*
+	 * addr is the address of the mcount call instruction.
+	 * recordmcount does the necessary offset calculation.
+	 */
+	return addr;
+}
 #endif /* __ASSEMBLY__ */
 
 #endif /* __ASM_FTRACE_H */
diff --git a/arch/arm64/kernel/entry-ftrace.S b/arch/arm64/kernel/entry-ftrace.S
index 0ac31c8..c0fbe10 100644
--- a/arch/arm64/kernel/entry-ftrace.S
+++ b/arch/arm64/kernel/entry-ftrace.S
@@ -86,6 +86,7 @@
 	add	\reg, \reg, #8
 	.endm
 
+#ifndef CONFIG_DYNAMIC_FTRACE
 /*
  * void _mcount(unsigned long return_address)
  * @return_address: return address to instrumented function
@@ -134,6 +135,48 @@ skip_ftrace_call:
 #endif /* CONFIG_FUNCTION_GRAPH_TRACER */
 ENDPROC(_mcount)
 
+#else /* CONFIG_DYNAMIC_FTRACE */
+/*
+ * _mcount() is used to build the kernel with -pg option, but all the branch
+ * instructions to _mcount() are replaced to NOP initially at kernel start up,
+ * and later on, NOP to branch to ftrace_caller() when enabled or branch to
+ * NOP when disabled per-function base.
+ */
+ENTRY(_mcount)
+	ret
+ENDPROC(_mcount)
+
+/*
+ * void ftrace_caller(unsigned long return_address)
+ * @return_address: return address to instrumented function
+ *
+ * This function is a counterpart of _mcount() in 'static' ftrace, and
+ * makes calls to:
+ *     - tracer function to probe instrumented function's entry,
+ *     - ftrace_graph_caller to set up an exit hook
+ */
+ENTRY(ftrace_caller)
+	mcount_enter
+
+	mcount_get_pc0	x0		//     function's pc
+	mcount_get_lr	x1		//     function's lr
+
+	.global ftrace_call
+ftrace_call:				// tracer(pc, lr);
+	nop				// This will be replaced with "bl xxx"
+					// where xxx can be any kind of tracer.
+
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+	.global ftrace_graph_call
+ftrace_graph_call:			// ftrace_graph_caller();
+	nop				// If enabled, this will be replaced
+					// "b ftrace_graph_caller"
+#endif
+
+	mcount_exit
+ENDPROC(ftrace_caller)
+#endif /* CONFIG_DYNAMIC_FTRACE */
+
 ENTRY(ftrace_stub)
 	ret
 ENDPROC(ftrace_stub)
diff --git a/arch/arm64/kernel/ftrace.c b/arch/arm64/kernel/ftrace.c
index a559ab8..8c26476 100644
--- a/arch/arm64/kernel/ftrace.c
+++ b/arch/arm64/kernel/ftrace.c
@@ -17,6 +17,89 @@
 #include <asm/ftrace.h>
 #include <asm/insn.h>
 
+#ifdef CONFIG_DYNAMIC_FTRACE
+/*
+ * Replace a single instruction, which may be a branch or NOP.
+ * If @validate == true, a replaced instruction is checked against 'old'.
+ */
+static int ftrace_modify_code(unsigned long pc, unsigned int old,
+			      unsigned int new, bool validate)
+{
+	unsigned int replaced;
+
+	/*
+	 * Note:
+	 * Due to modules and __init, code can disappear and change,
+	 * we need to protect against faulting as well as code changing.
+	 * We do this by aarch64_insn_*() which use the probe_kernel_*().
+	 *
+	 * No lock is held here because all the modifications are run
+	 * through stop_machine().
+	 */
+	if (validate) {
+		if (aarch64_insn_read((void *)pc, &replaced))
+			return -EFAULT;
+
+		if (replaced != old)
+			return -EINVAL;
+	}
+	if (aarch64_insn_patch_text_nosync((void *)pc, new))
+		return -EPERM;
+
+	return 0;
+}
+
+/*
+ * Replace tracer function in ftrace_caller()
+ */
+int ftrace_update_ftrace_func(ftrace_func_t func)
+{
+	unsigned long pc;
+	unsigned int new;
+
+	pc = (unsigned long)&ftrace_call;
+	new = aarch64_insn_gen_branch_imm(pc, (unsigned long)func, true);
+
+	return ftrace_modify_code(pc, 0, new, false);
+}
+
+/*
+ * Turn on the call to ftrace_caller() in instrumented function
+ */
+int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
+{
+	unsigned long pc = rec->ip;
+	unsigned int old, new;
+
+	old = aarch64_insn_gen_nop();
+	new = aarch64_insn_gen_branch_imm(pc, addr, true);
+
+	return ftrace_modify_code(pc, old, new, true);
+}
+
+/*
+ * Turn off the call to ftrace_caller() in instrumented function
+ */
+int ftrace_make_nop(struct module *mod,
+		    struct dyn_ftrace *rec, unsigned long addr)
+{
+	unsigned long pc = rec->ip;
+	unsigned int old, new;
+
+	old = aarch64_insn_gen_branch_imm(pc, addr, true);
+	new = aarch64_insn_gen_nop();
+
+	return ftrace_modify_code(pc, old, new, true);
+}
+
+int __init ftrace_dyn_arch_init(void *data)
+{
+	*(unsigned long *)data = 0;
+
+	return 0;
+}
+#endif /* CONFIG_DYNAMIC_FTRACE */
+
 #ifdef CONFIG_FUNCTION_GRAPH_TRACER
 /*
  * function_graph tracer expects ftrace_return_to_handler() to be called
@@ -61,4 +144,34 @@ void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr,
 		return;
 	}
 }
+
+#ifdef CONFIG_DYNAMIC_FTRACE
+/*
+ * Turn on/off the call to ftrace_graph_caller() in ftrace_caller()
+ * depending on @enable.
+ */
+static int ftrace_modify_graph_caller(bool enable)
+{
+	unsigned long pc = (unsigned long)&ftrace_graph_call;
+	unsigned int branch, nop, old, new;
+
+	branch = aarch64_insn_gen_branch_imm(pc,
+			(unsigned long)ftrace_graph_caller, false);
+	nop = aarch64_insn_gen_nop();
+	old = enable ? nop : branch;
+	new = enable ? branch : nop;
+
+	return ftrace_modify_code(pc, old, new, true);
+}
+
+int ftrace_enable_ftrace_graph_caller(void)
+{
+	return ftrace_modify_graph_caller(true);
+}
+
+int ftrace_disable_ftrace_graph_caller(void)
+{
+	return ftrace_modify_graph_caller(false);
+}
+#endif /* CONFIG_DYNAMIC_FTRACE */
 #endif /* CONFIG_FUNCTION_GRAPH_TRACER */
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 235+ messages in thread

* [PATCH v6 6/7] arm64: ftrace: Add CALLER_ADDRx macros
  2014-03-13 10:13         ` AKASHI Takahiro
@ 2014-03-13 10:13           ` AKASHI Takahiro
  -1 siblings, 0 replies; 235+ messages in thread
From: AKASHI Takahiro @ 2014-03-13 10:13 UTC (permalink / raw)
  To: rostedt, fweisbec, mingo, catalin.marinas, will.deacon, tim.bird
  Cc: gkulkarni, dsaxena, arndb, linux-arm-kernel, linaro-kernel,
	linux-kernel, AKASHI Takahiro

CALLER_ADDRx returns caller's address at specified level in call stacks.
They are used for several tracers like irqsoff and preemptoff.
Strange to say, however, they are refered even without FTRACE.

Please note that this implementation assumes that we have frame pointers.
(which means kernel should be compiled with -fno-omit-frame-pointer.)

Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
---
 arch/arm64/include/asm/ftrace.h    |   13 ++++++++-
 arch/arm64/kernel/Makefile         |    3 +-
 arch/arm64/kernel/return_address.c |   55 ++++++++++++++++++++++++++++++++++++
 3 files changed, 69 insertions(+), 2 deletions(-)
 create mode 100644 arch/arm64/kernel/return_address.c

diff --git a/arch/arm64/include/asm/ftrace.h b/arch/arm64/include/asm/ftrace.h
index ed5c448..c44c4b1 100644
--- a/arch/arm64/include/asm/ftrace.h
+++ b/arch/arm64/include/asm/ftrace.h
@@ -18,6 +18,7 @@
 
 #ifndef __ASSEMBLY__
 extern void _mcount(unsigned long);
+extern void *return_address(unsigned int);
 
 struct dyn_arch_ftrace {
 	/* No extra data needed for arm64 */
@@ -33,6 +34,16 @@ static inline unsigned long ftrace_call_adjust(unsigned long addr)
 	 */
 	return addr;
 }
-#endif /* __ASSEMBLY__ */
+
+#define HAVE_ARCH_CALLER_ADDR
+
+#define CALLER_ADDR0 ((unsigned long)__builtin_return_address(0))
+#define CALLER_ADDR1 ((unsigned long)return_address(1))
+#define CALLER_ADDR2 ((unsigned long)return_address(2))
+#define CALLER_ADDR3 ((unsigned long)return_address(3))
+#define CALLER_ADDR4 ((unsigned long)return_address(4))
+#define CALLER_ADDR5 ((unsigned long)return_address(5))
+#define CALLER_ADDR6 ((unsigned long)return_address(6))
+#endif /* ifndef __ASSEMBLY__ */
 
 #endif /* __ASM_FTRACE_H */
diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile
index ac67fd0..b5bfa7f 100644
--- a/arch/arm64/kernel/Makefile
+++ b/arch/arm64/kernel/Makefile
@@ -7,12 +7,13 @@ AFLAGS_head.o		:= -DTEXT_OFFSET=$(TEXT_OFFSET)
 
 CFLAGS_REMOVE_ftrace.o = -pg
 CFLAGS_REMOVE_insn.o = -pg
+CFLAGS_REMOVE_return_address.o = -pg
 
 # Object file lists.
 arm64-obj-y		:= cputable.o debug-monitors.o entry.o irq.o fpsimd.o	\
 			   entry-fpsimd.o process.o ptrace.o setup.o signal.o	\
 			   sys.o stacktrace.o time.o traps.o io.o vdso.o	\
-			   hyp-stub.o psci.o cpu_ops.o insn.o
+			   hyp-stub.o psci.o cpu_ops.o insn.o return_address.o
 
 arm64-obj-$(CONFIG_COMPAT)		+= sys32.o kuser32.o signal32.o 	\
 					   sys_compat.o
diff --git a/arch/arm64/kernel/return_address.c b/arch/arm64/kernel/return_address.c
new file mode 100644
index 0000000..89102a6
--- /dev/null
+++ b/arch/arm64/kernel/return_address.c
@@ -0,0 +1,55 @@
+/*
+ * arch/arm64/kernel/return_address.c
+ *
+ * Copyright (C) 2013 Linaro Limited
+ * Author: AKASHI Takahiro <takahiro.akashi@linaro.org>
+ *
+ * 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 <linux/export.h>
+#include <linux/ftrace.h>
+
+#include <asm/stacktrace.h>
+
+struct return_address_data {
+	unsigned int level;
+	void *addr;
+};
+
+static int save_return_addr(struct stackframe *frame, void *d)
+{
+	struct return_address_data *data = d;
+
+	if (!data->level) {
+		data->addr = (void *)frame->pc;
+		return 1;
+	} else {
+		--data->level;
+		return 0;
+	}
+}
+
+void *return_address(unsigned int level)
+{
+	struct return_address_data data;
+	struct stackframe frame;
+	register unsigned long current_sp asm ("sp");
+
+	data.level = level + 2;
+	data.addr = NULL;
+
+	frame.fp = (unsigned long)__builtin_frame_address(0);
+	frame.sp = current_sp;
+	frame.pc = (unsigned long)return_address; /* dummy */
+
+	walk_stackframe(&frame, save_return_addr, &data);
+
+	if (!data.level)
+		return data.addr;
+	else
+		return NULL;
+}
+EXPORT_SYMBOL_GPL(return_address);
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 235+ messages in thread

* [PATCH v6 6/7] arm64: ftrace: Add CALLER_ADDRx macros
@ 2014-03-13 10:13           ` AKASHI Takahiro
  0 siblings, 0 replies; 235+ messages in thread
From: AKASHI Takahiro @ 2014-03-13 10:13 UTC (permalink / raw)
  To: linux-arm-kernel

CALLER_ADDRx returns caller's address at specified level in call stacks.
They are used for several tracers like irqsoff and preemptoff.
Strange to say, however, they are refered even without FTRACE.

Please note that this implementation assumes that we have frame pointers.
(which means kernel should be compiled with -fno-omit-frame-pointer.)

Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
---
 arch/arm64/include/asm/ftrace.h    |   13 ++++++++-
 arch/arm64/kernel/Makefile         |    3 +-
 arch/arm64/kernel/return_address.c |   55 ++++++++++++++++++++++++++++++++++++
 3 files changed, 69 insertions(+), 2 deletions(-)
 create mode 100644 arch/arm64/kernel/return_address.c

diff --git a/arch/arm64/include/asm/ftrace.h b/arch/arm64/include/asm/ftrace.h
index ed5c448..c44c4b1 100644
--- a/arch/arm64/include/asm/ftrace.h
+++ b/arch/arm64/include/asm/ftrace.h
@@ -18,6 +18,7 @@
 
 #ifndef __ASSEMBLY__
 extern void _mcount(unsigned long);
+extern void *return_address(unsigned int);
 
 struct dyn_arch_ftrace {
 	/* No extra data needed for arm64 */
@@ -33,6 +34,16 @@ static inline unsigned long ftrace_call_adjust(unsigned long addr)
 	 */
 	return addr;
 }
-#endif /* __ASSEMBLY__ */
+
+#define HAVE_ARCH_CALLER_ADDR
+
+#define CALLER_ADDR0 ((unsigned long)__builtin_return_address(0))
+#define CALLER_ADDR1 ((unsigned long)return_address(1))
+#define CALLER_ADDR2 ((unsigned long)return_address(2))
+#define CALLER_ADDR3 ((unsigned long)return_address(3))
+#define CALLER_ADDR4 ((unsigned long)return_address(4))
+#define CALLER_ADDR5 ((unsigned long)return_address(5))
+#define CALLER_ADDR6 ((unsigned long)return_address(6))
+#endif /* ifndef __ASSEMBLY__ */
 
 #endif /* __ASM_FTRACE_H */
diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile
index ac67fd0..b5bfa7f 100644
--- a/arch/arm64/kernel/Makefile
+++ b/arch/arm64/kernel/Makefile
@@ -7,12 +7,13 @@ AFLAGS_head.o		:= -DTEXT_OFFSET=$(TEXT_OFFSET)
 
 CFLAGS_REMOVE_ftrace.o = -pg
 CFLAGS_REMOVE_insn.o = -pg
+CFLAGS_REMOVE_return_address.o = -pg
 
 # Object file lists.
 arm64-obj-y		:= cputable.o debug-monitors.o entry.o irq.o fpsimd.o	\
 			   entry-fpsimd.o process.o ptrace.o setup.o signal.o	\
 			   sys.o stacktrace.o time.o traps.o io.o vdso.o	\
-			   hyp-stub.o psci.o cpu_ops.o insn.o
+			   hyp-stub.o psci.o cpu_ops.o insn.o return_address.o
 
 arm64-obj-$(CONFIG_COMPAT)		+= sys32.o kuser32.o signal32.o 	\
 					   sys_compat.o
diff --git a/arch/arm64/kernel/return_address.c b/arch/arm64/kernel/return_address.c
new file mode 100644
index 0000000..89102a6
--- /dev/null
+++ b/arch/arm64/kernel/return_address.c
@@ -0,0 +1,55 @@
+/*
+ * arch/arm64/kernel/return_address.c
+ *
+ * Copyright (C) 2013 Linaro Limited
+ * Author: AKASHI Takahiro <takahiro.akashi@linaro.org>
+ *
+ * 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 <linux/export.h>
+#include <linux/ftrace.h>
+
+#include <asm/stacktrace.h>
+
+struct return_address_data {
+	unsigned int level;
+	void *addr;
+};
+
+static int save_return_addr(struct stackframe *frame, void *d)
+{
+	struct return_address_data *data = d;
+
+	if (!data->level) {
+		data->addr = (void *)frame->pc;
+		return 1;
+	} else {
+		--data->level;
+		return 0;
+	}
+}
+
+void *return_address(unsigned int level)
+{
+	struct return_address_data data;
+	struct stackframe frame;
+	register unsigned long current_sp asm ("sp");
+
+	data.level = level + 2;
+	data.addr = NULL;
+
+	frame.fp = (unsigned long)__builtin_frame_address(0);
+	frame.sp = current_sp;
+	frame.pc = (unsigned long)return_address; /* dummy */
+
+	walk_stackframe(&frame, save_return_addr, &data);
+
+	if (!data.level)
+		return data.addr;
+	else
+		return NULL;
+}
+EXPORT_SYMBOL_GPL(return_address);
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 235+ messages in thread

* [PATCH v6 7/7] arm64: ftrace: Add system call tracepoint
  2014-03-13 10:13         ` AKASHI Takahiro
@ 2014-03-13 10:13           ` AKASHI Takahiro
  -1 siblings, 0 replies; 235+ messages in thread
From: AKASHI Takahiro @ 2014-03-13 10:13 UTC (permalink / raw)
  To: rostedt, fweisbec, mingo, catalin.marinas, will.deacon, tim.bird
  Cc: gkulkarni, dsaxena, arndb, linux-arm-kernel, linaro-kernel,
	linux-kernel, AKASHI Takahiro

This patch allows system call entry or exit to be traced as ftrace events,
ie. sys_enter_*/sys_exit_*, if CONFIG_FTRACE_SYSCALLS is enabled.
Those events appear and can be controlled under
    ${sysfs}/tracing/events/syscalls/

Please note that we can't trace compat system calls here because
AArch32 mode does not share the same syscall table with AArch64.
Just define ARCH_TRACE_IGNORE_COMPAT_SYSCALLS in order to avoid unexpected
results (bogus syscalls reported or even hang-up).

Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
---
 arch/arm64/Kconfig               |    1 +
 arch/arm64/include/asm/ftrace.h  |   20 ++++++++++++++++
 arch/arm64/include/asm/syscall.h |    1 +
 arch/arm64/include/asm/unistd.h  |    2 ++
 arch/arm64/kernel/ptrace.c       |   48 ++++++++++++++++++++++----------------
 5 files changed, 52 insertions(+), 20 deletions(-)

diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 6954959..b1dcdb4 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -43,6 +43,7 @@ config ARM64
 	select HAVE_MEMBLOCK
 	select HAVE_PATA_PLATFORM
 	select HAVE_PERF_EVENTS
+	select HAVE_SYSCALL_TRACEPOINTS
 	select IRQ_DOMAIN
 	select MODULES_USE_ELF_RELA
 	select NO_BOOTMEM
diff --git a/arch/arm64/include/asm/ftrace.h b/arch/arm64/include/asm/ftrace.h
index c44c4b1..4ef06f1 100644
--- a/arch/arm64/include/asm/ftrace.h
+++ b/arch/arm64/include/asm/ftrace.h
@@ -44,6 +44,26 @@ static inline unsigned long ftrace_call_adjust(unsigned long addr)
 #define CALLER_ADDR4 ((unsigned long)return_address(4))
 #define CALLER_ADDR5 ((unsigned long)return_address(5))
 #define CALLER_ADDR6 ((unsigned long)return_address(6))
+
+#include <asm/compat.h>
+
+/*
+ * Because AArch32 mode does not share the same syscall table with AArch64,
+ * tracing compat syscalls may result in reporting bogus syscalls or even
+ * hang-up, so just do not trace them.
+ * See kernel/trace/trace_syscalls.c
+ *
+ * x86 code says:
+ * If the user realy wants these, then they should use the
+ * raw syscall tracepoints with filtering.
+ */
+#define ARCH_TRACE_IGNORE_COMPAT_SYSCALLS 1
+static inline bool arch_trace_is_compat_syscall(struct pt_regs *regs)
+{
+        if (is_compat_task())
+                return true;
+        return false;
+}
 #endif /* ifndef __ASSEMBLY__ */
 
 #endif /* __ASM_FTRACE_H */
diff --git a/arch/arm64/include/asm/syscall.h b/arch/arm64/include/asm/syscall.h
index 70ba9d4..383771e 100644
--- a/arch/arm64/include/asm/syscall.h
+++ b/arch/arm64/include/asm/syscall.h
@@ -18,6 +18,7 @@
 
 #include <linux/err.h>
 
+extern const void *sys_call_table[];
 
 static inline int syscall_get_nr(struct task_struct *task,
 				 struct pt_regs *regs)
diff --git a/arch/arm64/include/asm/unistd.h b/arch/arm64/include/asm/unistd.h
index 82ce217..c335479 100644
--- a/arch/arm64/include/asm/unistd.h
+++ b/arch/arm64/include/asm/unistd.h
@@ -28,3 +28,5 @@
 #endif
 #define __ARCH_WANT_SYS_CLONE
 #include <uapi/asm/unistd.h>
+
+#define NR_syscalls (__NR_syscalls)
diff --git a/arch/arm64/kernel/ptrace.c b/arch/arm64/kernel/ptrace.c
index 9993a8f..9c52b3e 100644
--- a/arch/arm64/kernel/ptrace.c
+++ b/arch/arm64/kernel/ptrace.c
@@ -41,6 +41,9 @@
 #include <asm/traps.h>
 #include <asm/system_misc.h>
 
+#define CREATE_TRACE_POINTS
+#include <trace/events/syscalls.h>
+
 /*
  * TODO: does not yet catch signals sent when the child dies.
  * in exit.c or in signal.c.
@@ -1062,29 +1065,31 @@ asmlinkage int syscall_trace_enter(struct pt_regs *regs)
 {
 	unsigned long saved_reg;
 
-	if (!test_thread_flag(TIF_SYSCALL_TRACE))
-		return regs->syscallno;
+	if (test_thread_flag(TIF_SYSCALL_TRACE)) {
+		/*
+		 * A scrach register (ip(r12) on AArch32, x7 on AArch64) is
+		 * used to denote syscall entry/exit:
+		 *   0 -> entry
+		 */
+		if (is_compat_task()) {
+			saved_reg = regs->regs[12];
+			regs->regs[12] = 0;
+		} else {
+			saved_reg = regs->regs[7];
+			regs->regs[7] = 0;
+		}
 
-	/*
-	 * A scrach register (ip(r12) on AArch32, x7 on AArch64) is
-	 * used to denote syscall entry/exit:
-	 *   0 -> entry
-	 */
-	if (is_compat_task()) {
-		saved_reg = regs->regs[12];
-		regs->regs[12] = 0;
-	} else {
-		saved_reg = regs->regs[7];
-		regs->regs[7] = 0;
-	}
+		if (tracehook_report_syscall_entry(regs))
+			regs->syscallno = ~0UL;
 
-	if (tracehook_report_syscall_entry(regs))
-		regs->syscallno = ~0UL;
+		if (is_compat_task())
+			regs->regs[12] = saved_reg;
+		else
+			regs->regs[7] = saved_reg;
+	}
 
-	if (is_compat_task())
-		regs->regs[12] = saved_reg;
-	else
-		regs->regs[7] = saved_reg;
+	if (test_thread_flag(TIF_SYSCALL_TRACEPOINT))
+		trace_sys_enter(regs, regs->syscallno);
 
 	return regs->syscallno;
 }
@@ -1093,6 +1098,9 @@ asmlinkage void syscall_trace_exit(struct pt_regs *regs)
 {
 	unsigned long saved_reg;
 
+	if (test_thread_flag(TIF_SYSCALL_TRACEPOINT))
+		trace_sys_exit(regs, regs_return_value(regs));
+
 	if (!test_thread_flag(TIF_SYSCALL_TRACE))
 		return;
 
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 235+ messages in thread

* [PATCH v6 7/7] arm64: ftrace: Add system call tracepoint
@ 2014-03-13 10:13           ` AKASHI Takahiro
  0 siblings, 0 replies; 235+ messages in thread
From: AKASHI Takahiro @ 2014-03-13 10:13 UTC (permalink / raw)
  To: linux-arm-kernel

This patch allows system call entry or exit to be traced as ftrace events,
ie. sys_enter_*/sys_exit_*, if CONFIG_FTRACE_SYSCALLS is enabled.
Those events appear and can be controlled under
    ${sysfs}/tracing/events/syscalls/

Please note that we can't trace compat system calls here because
AArch32 mode does not share the same syscall table with AArch64.
Just define ARCH_TRACE_IGNORE_COMPAT_SYSCALLS in order to avoid unexpected
results (bogus syscalls reported or even hang-up).

Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
---
 arch/arm64/Kconfig               |    1 +
 arch/arm64/include/asm/ftrace.h  |   20 ++++++++++++++++
 arch/arm64/include/asm/syscall.h |    1 +
 arch/arm64/include/asm/unistd.h  |    2 ++
 arch/arm64/kernel/ptrace.c       |   48 ++++++++++++++++++++++----------------
 5 files changed, 52 insertions(+), 20 deletions(-)

diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 6954959..b1dcdb4 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -43,6 +43,7 @@ config ARM64
 	select HAVE_MEMBLOCK
 	select HAVE_PATA_PLATFORM
 	select HAVE_PERF_EVENTS
+	select HAVE_SYSCALL_TRACEPOINTS
 	select IRQ_DOMAIN
 	select MODULES_USE_ELF_RELA
 	select NO_BOOTMEM
diff --git a/arch/arm64/include/asm/ftrace.h b/arch/arm64/include/asm/ftrace.h
index c44c4b1..4ef06f1 100644
--- a/arch/arm64/include/asm/ftrace.h
+++ b/arch/arm64/include/asm/ftrace.h
@@ -44,6 +44,26 @@ static inline unsigned long ftrace_call_adjust(unsigned long addr)
 #define CALLER_ADDR4 ((unsigned long)return_address(4))
 #define CALLER_ADDR5 ((unsigned long)return_address(5))
 #define CALLER_ADDR6 ((unsigned long)return_address(6))
+
+#include <asm/compat.h>
+
+/*
+ * Because AArch32 mode does not share the same syscall table with AArch64,
+ * tracing compat syscalls may result in reporting bogus syscalls or even
+ * hang-up, so just do not trace them.
+ * See kernel/trace/trace_syscalls.c
+ *
+ * x86 code says:
+ * If the user realy wants these, then they should use the
+ * raw syscall tracepoints with filtering.
+ */
+#define ARCH_TRACE_IGNORE_COMPAT_SYSCALLS 1
+static inline bool arch_trace_is_compat_syscall(struct pt_regs *regs)
+{
+        if (is_compat_task())
+                return true;
+        return false;
+}
 #endif /* ifndef __ASSEMBLY__ */
 
 #endif /* __ASM_FTRACE_H */
diff --git a/arch/arm64/include/asm/syscall.h b/arch/arm64/include/asm/syscall.h
index 70ba9d4..383771e 100644
--- a/arch/arm64/include/asm/syscall.h
+++ b/arch/arm64/include/asm/syscall.h
@@ -18,6 +18,7 @@
 
 #include <linux/err.h>
 
+extern const void *sys_call_table[];
 
 static inline int syscall_get_nr(struct task_struct *task,
 				 struct pt_regs *regs)
diff --git a/arch/arm64/include/asm/unistd.h b/arch/arm64/include/asm/unistd.h
index 82ce217..c335479 100644
--- a/arch/arm64/include/asm/unistd.h
+++ b/arch/arm64/include/asm/unistd.h
@@ -28,3 +28,5 @@
 #endif
 #define __ARCH_WANT_SYS_CLONE
 #include <uapi/asm/unistd.h>
+
+#define NR_syscalls (__NR_syscalls)
diff --git a/arch/arm64/kernel/ptrace.c b/arch/arm64/kernel/ptrace.c
index 9993a8f..9c52b3e 100644
--- a/arch/arm64/kernel/ptrace.c
+++ b/arch/arm64/kernel/ptrace.c
@@ -41,6 +41,9 @@
 #include <asm/traps.h>
 #include <asm/system_misc.h>
 
+#define CREATE_TRACE_POINTS
+#include <trace/events/syscalls.h>
+
 /*
  * TODO: does not yet catch signals sent when the child dies.
  * in exit.c or in signal.c.
@@ -1062,29 +1065,31 @@ asmlinkage int syscall_trace_enter(struct pt_regs *regs)
 {
 	unsigned long saved_reg;
 
-	if (!test_thread_flag(TIF_SYSCALL_TRACE))
-		return regs->syscallno;
+	if (test_thread_flag(TIF_SYSCALL_TRACE)) {
+		/*
+		 * A scrach register (ip(r12) on AArch32, x7 on AArch64) is
+		 * used to denote syscall entry/exit:
+		 *   0 -> entry
+		 */
+		if (is_compat_task()) {
+			saved_reg = regs->regs[12];
+			regs->regs[12] = 0;
+		} else {
+			saved_reg = regs->regs[7];
+			regs->regs[7] = 0;
+		}
 
-	/*
-	 * A scrach register (ip(r12) on AArch32, x7 on AArch64) is
-	 * used to denote syscall entry/exit:
-	 *   0 -> entry
-	 */
-	if (is_compat_task()) {
-		saved_reg = regs->regs[12];
-		regs->regs[12] = 0;
-	} else {
-		saved_reg = regs->regs[7];
-		regs->regs[7] = 0;
-	}
+		if (tracehook_report_syscall_entry(regs))
+			regs->syscallno = ~0UL;
 
-	if (tracehook_report_syscall_entry(regs))
-		regs->syscallno = ~0UL;
+		if (is_compat_task())
+			regs->regs[12] = saved_reg;
+		else
+			regs->regs[7] = saved_reg;
+	}
 
-	if (is_compat_task())
-		regs->regs[12] = saved_reg;
-	else
-		regs->regs[7] = saved_reg;
+	if (test_thread_flag(TIF_SYSCALL_TRACEPOINT))
+		trace_sys_enter(regs, regs->syscallno);
 
 	return regs->syscallno;
 }
@@ -1093,6 +1098,9 @@ asmlinkage void syscall_trace_exit(struct pt_regs *regs)
 {
 	unsigned long saved_reg;
 
+	if (test_thread_flag(TIF_SYSCALL_TRACEPOINT))
+		trace_sys_exit(regs, regs_return_value(regs));
+
 	if (!test_thread_flag(TIF_SYSCALL_TRACE))
 		return;
 
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 235+ messages in thread

* Re: [PATCH v6 1/7] arm64: add __ASSEMBLY__ in asm/insn.h
  2014-03-13 10:13           ` AKASHI Takahiro
@ 2014-03-13 12:19             ` Will Deacon
  -1 siblings, 0 replies; 235+ messages in thread
From: Will Deacon @ 2014-03-13 12:19 UTC (permalink / raw)
  To: AKASHI Takahiro
  Cc: rostedt, fweisbec, mingo, Catalin Marinas, tim.bird, gkulkarni,
	dsaxena, arndb, linux-arm-kernel, linaro-kernel, linux-kernel

On Thu, Mar 13, 2014 at 10:13:44AM +0000, AKASHI Takahiro wrote:
> Since insn.h is indirectly included in asm/entry-ftrace.S,
> we need to exclude some declarations by __ASSEMBLY__.
> 
> Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>

Acked-by: Will Deacon <will.deacon@arm.com>

Will

^ permalink raw reply	[flat|nested] 235+ messages in thread

* [PATCH v6 1/7] arm64: add __ASSEMBLY__ in asm/insn.h
@ 2014-03-13 12:19             ` Will Deacon
  0 siblings, 0 replies; 235+ messages in thread
From: Will Deacon @ 2014-03-13 12:19 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Mar 13, 2014 at 10:13:44AM +0000, AKASHI Takahiro wrote:
> Since insn.h is indirectly included in asm/entry-ftrace.S,
> we need to exclude some declarations by __ASSEMBLY__.
> 
> Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>

Acked-by: Will Deacon <will.deacon@arm.com>

Will

^ permalink raw reply	[flat|nested] 235+ messages in thread

* Re: [PATCH v6 2/7] arm64: Add 'notrace' attribute to unwind_frame() for ftrace
  2014-03-13 10:13           ` AKASHI Takahiro
@ 2014-03-13 12:19             ` Will Deacon
  -1 siblings, 0 replies; 235+ messages in thread
From: Will Deacon @ 2014-03-13 12:19 UTC (permalink / raw)
  To: AKASHI Takahiro
  Cc: rostedt, fweisbec, mingo, Catalin Marinas, tim.bird, gkulkarni,
	dsaxena, arndb, linux-arm-kernel, linaro-kernel, linux-kernel

On Thu, Mar 13, 2014 at 10:13:45AM +0000, AKASHI Takahiro wrote:
> walk_stackframe() calls unwind_frame(), and if walk_stackframe() is
> "notrace", unwind_frame() should be also "notrace".
> 
> Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>

Acked-by: Will Deacon <will.deacon@arm.com>

Will

^ permalink raw reply	[flat|nested] 235+ messages in thread

* [PATCH v6 2/7] arm64: Add 'notrace' attribute to unwind_frame() for ftrace
@ 2014-03-13 12:19             ` Will Deacon
  0 siblings, 0 replies; 235+ messages in thread
From: Will Deacon @ 2014-03-13 12:19 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Mar 13, 2014 at 10:13:45AM +0000, AKASHI Takahiro wrote:
> walk_stackframe() calls unwind_frame(), and if walk_stackframe() is
> "notrace", unwind_frame() should be also "notrace".
> 
> Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>

Acked-by: Will Deacon <will.deacon@arm.com>

Will

^ permalink raw reply	[flat|nested] 235+ messages in thread

* Re: [PATCH v6 3/7] ftrace: Add arm64 support to recordmcount
  2014-03-13 10:13           ` AKASHI Takahiro
@ 2014-03-13 12:38             ` Will Deacon
  -1 siblings, 0 replies; 235+ messages in thread
From: Will Deacon @ 2014-03-13 12:38 UTC (permalink / raw)
  To: AKASHI Takahiro
  Cc: rostedt, fweisbec, mingo, Catalin Marinas, tim.bird, gkulkarni,
	dsaxena, arndb, linux-arm-kernel, linaro-kernel, linux-kernel

On Thu, Mar 13, 2014 at 10:13:46AM +0000, AKASHI Takahiro wrote:
> Recordmcount utility under scripts is run, after compiling each object,
> to find out all the locations of calling _mcount() and put them into
> specific seciton named __mcount_loc.
> Then linker collects all such information into a table in the kernel image
> (between __start_mcount_loc and __stop_mcount_loc) for later use by ftrace.
> 
> This patch adds arm64 specific definitions to identify such locations.
> There are two types of implementation, C and Perl. On arm64, only C version
> is used to build the kernel now that CONFIG_HAVE_C_RECORDMCOUNT is on.
> But Perl version is also maintained.
> 
> This patch also contains a workaround just in case where a header file,
> elf.h, on host machine doesn't have definitions of EM_AARCH64 nor
> R_AARCH64_ABS64. Without them, compiling C version of recordmcount will
> fail.

[...]

> diff --git a/scripts/recordmcount.c b/scripts/recordmcount.c
> index 9c22317..047c8cd 100644
> --- a/scripts/recordmcount.c
> +++ b/scripts/recordmcount.c
> @@ -40,6 +40,11 @@
>  #define R_METAG_NONE                     3
>  #endif
>  
> +#ifndef EM_AARCH64
> +#define EM_AARCH64	183
> +#define R_AARCH64_ABS64	257
> +#endif
> +
>  static int fd_map;	/* File descriptor for file being modified. */
>  static int mmap_failed; /* Boolean flag. */
>  static void *ehdr_curr; /* current ElfXX_Ehdr *  for resource cleanup */
> @@ -347,6 +352,10 @@ do_file(char const *const fname)
>  	case EM_ARM:	 reltype = R_ARM_ABS32;
>  			 altmcount = "__gnu_mcount_nc";
>  			 break;
> +	case EM_AARCH64:
> +			 reltype = R_AARCH64_ABS64;
> +			 altmcount = "_mcount";

Shouldn't you be setting gpfx = '_' instead of overriding altmcount like
this?

> +			 break;
>  	case EM_IA_64:	 reltype = R_IA64_IMM64;   gpfx = '_'; break;
>  	case EM_METAG:	 reltype = R_METAG_ADDR32;
>  			 altmcount = "_mcount_wrapper";
> diff --git a/scripts/recordmcount.pl b/scripts/recordmcount.pl
> index 91280b8..397b6b8 100755
> --- a/scripts/recordmcount.pl
> +++ b/scripts/recordmcount.pl
> @@ -279,6 +279,11 @@ if ($arch eq "x86_64") {
>      $mcount_regex = "^\\s*([0-9a-fA-F]+):\\s*R_ARM_(CALL|PC24|THM_CALL)" .
>  			"\\s+(__gnu_mcount_nc|mcount)\$";
>  
> +} elsif ($arch eq "arm64") {
> +    $alignment = 3;
> +    $section_type = '%progbits';
> +    $mcount_regex = "^\\s*([0-9a-fA-F]+):\\s*R_AARCH64_CALL26\\s+_mcount\$";

What about "mcount" (i.e. no underscore)?

Will

^ permalink raw reply	[flat|nested] 235+ messages in thread

* [PATCH v6 3/7] ftrace: Add arm64 support to recordmcount
@ 2014-03-13 12:38             ` Will Deacon
  0 siblings, 0 replies; 235+ messages in thread
From: Will Deacon @ 2014-03-13 12:38 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Mar 13, 2014 at 10:13:46AM +0000, AKASHI Takahiro wrote:
> Recordmcount utility under scripts is run, after compiling each object,
> to find out all the locations of calling _mcount() and put them into
> specific seciton named __mcount_loc.
> Then linker collects all such information into a table in the kernel image
> (between __start_mcount_loc and __stop_mcount_loc) for later use by ftrace.
> 
> This patch adds arm64 specific definitions to identify such locations.
> There are two types of implementation, C and Perl. On arm64, only C version
> is used to build the kernel now that CONFIG_HAVE_C_RECORDMCOUNT is on.
> But Perl version is also maintained.
> 
> This patch also contains a workaround just in case where a header file,
> elf.h, on host machine doesn't have definitions of EM_AARCH64 nor
> R_AARCH64_ABS64. Without them, compiling C version of recordmcount will
> fail.

[...]

> diff --git a/scripts/recordmcount.c b/scripts/recordmcount.c
> index 9c22317..047c8cd 100644
> --- a/scripts/recordmcount.c
> +++ b/scripts/recordmcount.c
> @@ -40,6 +40,11 @@
>  #define R_METAG_NONE                     3
>  #endif
>  
> +#ifndef EM_AARCH64
> +#define EM_AARCH64	183
> +#define R_AARCH64_ABS64	257
> +#endif
> +
>  static int fd_map;	/* File descriptor for file being modified. */
>  static int mmap_failed; /* Boolean flag. */
>  static void *ehdr_curr; /* current ElfXX_Ehdr *  for resource cleanup */
> @@ -347,6 +352,10 @@ do_file(char const *const fname)
>  	case EM_ARM:	 reltype = R_ARM_ABS32;
>  			 altmcount = "__gnu_mcount_nc";
>  			 break;
> +	case EM_AARCH64:
> +			 reltype = R_AARCH64_ABS64;
> +			 altmcount = "_mcount";

Shouldn't you be setting gpfx = '_' instead of overriding altmcount like
this?

> +			 break;
>  	case EM_IA_64:	 reltype = R_IA64_IMM64;   gpfx = '_'; break;
>  	case EM_METAG:	 reltype = R_METAG_ADDR32;
>  			 altmcount = "_mcount_wrapper";
> diff --git a/scripts/recordmcount.pl b/scripts/recordmcount.pl
> index 91280b8..397b6b8 100755
> --- a/scripts/recordmcount.pl
> +++ b/scripts/recordmcount.pl
> @@ -279,6 +279,11 @@ if ($arch eq "x86_64") {
>      $mcount_regex = "^\\s*([0-9a-fA-F]+):\\s*R_ARM_(CALL|PC24|THM_CALL)" .
>  			"\\s+(__gnu_mcount_nc|mcount)\$";
>  
> +} elsif ($arch eq "arm64") {
> +    $alignment = 3;
> +    $section_type = '%progbits';
> +    $mcount_regex = "^\\s*([0-9a-fA-F]+):\\s*R_AARCH64_CALL26\\s+_mcount\$";

What about "mcount" (i.e. no underscore)?

Will

^ permalink raw reply	[flat|nested] 235+ messages in thread

* Re: [PATCH v6 3/7] ftrace: Add arm64 support to recordmcount
  2014-03-13 12:38             ` Will Deacon
@ 2014-03-13 14:57               ` AKASHI Takahiro
  -1 siblings, 0 replies; 235+ messages in thread
From: AKASHI Takahiro @ 2014-03-13 14:57 UTC (permalink / raw)
  To: Will Deacon
  Cc: rostedt, fweisbec, mingo, Catalin Marinas, tim.bird, gkulkarni,
	dsaxena, arndb, linux-arm-kernel, linaro-kernel, linux-kernel

On 03/13/2014 09:38 PM, Will Deacon wrote:
> On Thu, Mar 13, 2014 at 10:13:46AM +0000, AKASHI Takahiro wrote:
>> Recordmcount utility under scripts is run, after compiling each object,
>> to find out all the locations of calling _mcount() and put them into
>> specific seciton named __mcount_loc.
>> Then linker collects all such information into a table in the kernel image
>> (between __start_mcount_loc and __stop_mcount_loc) for later use by ftrace.
>>
>> This patch adds arm64 specific definitions to identify such locations.
>> There are two types of implementation, C and Perl. On arm64, only C version
>> is used to build the kernel now that CONFIG_HAVE_C_RECORDMCOUNT is on.
>> But Perl version is also maintained.
>>
>> This patch also contains a workaround just in case where a header file,
>> elf.h, on host machine doesn't have definitions of EM_AARCH64 nor
>> R_AARCH64_ABS64. Without them, compiling C version of recordmcount will
>> fail.
>
> [...]
>
>> diff --git a/scripts/recordmcount.c b/scripts/recordmcount.c
>> index 9c22317..047c8cd 100644
>> --- a/scripts/recordmcount.c
>> +++ b/scripts/recordmcount.c
>> @@ -40,6 +40,11 @@
>>   #define R_METAG_NONE                     3
>>   #endif
>>
>> +#ifndef EM_AARCH64
>> +#define EM_AARCH64	183
>> +#define R_AARCH64_ABS64	257
>> +#endif
>> +
>>   static int fd_map;	/* File descriptor for file being modified. */
>>   static int mmap_failed; /* Boolean flag. */
>>   static void *ehdr_curr; /* current ElfXX_Ehdr *  for resource cleanup */
>> @@ -347,6 +352,10 @@ do_file(char const *const fname)
>>   	case EM_ARM:	 reltype = R_ARM_ABS32;
>>   			 altmcount = "__gnu_mcount_nc";
>>   			 break;
>> +	case EM_AARCH64:
>> +			 reltype = R_AARCH64_ABS64;
>> +			 altmcount = "_mcount";
>
> Shouldn't you be setting gpfx = '_' instead of overriding altmcount like
> this?

Yep. Fix it.

>> +			 break;
>>   	case EM_IA_64:	 reltype = R_IA64_IMM64;   gpfx = '_'; break;
>>   	case EM_METAG:	 reltype = R_METAG_ADDR32;
>>   			 altmcount = "_mcount_wrapper";
>> diff --git a/scripts/recordmcount.pl b/scripts/recordmcount.pl
>> index 91280b8..397b6b8 100755
>> --- a/scripts/recordmcount.pl
>> +++ b/scripts/recordmcount.pl
>> @@ -279,6 +279,11 @@ if ($arch eq "x86_64") {
>>       $mcount_regex = "^\\s*([0-9a-fA-F]+):\\s*R_ARM_(CALL|PC24|THM_CALL)" .
>>   			"\\s+(__gnu_mcount_nc|mcount)\$";
>>
>> +} elsif ($arch eq "arm64") {
>> +    $alignment = 3;
>> +    $section_type = '%progbits';
>> +    $mcount_regex = "^\\s*([0-9a-fA-F]+):\\s*R_AARCH64_CALL26\\s+_mcount\$";
>
> What about "mcount" (i.e. no underscore)?

I don't think it works since such regex doesn't match to "CALL26   _mcount".

Thanks,
-Takahiro AKASHI

> Will
>

^ permalink raw reply	[flat|nested] 235+ messages in thread

* [PATCH v6 3/7] ftrace: Add arm64 support to recordmcount
@ 2014-03-13 14:57               ` AKASHI Takahiro
  0 siblings, 0 replies; 235+ messages in thread
From: AKASHI Takahiro @ 2014-03-13 14:57 UTC (permalink / raw)
  To: linux-arm-kernel

On 03/13/2014 09:38 PM, Will Deacon wrote:
> On Thu, Mar 13, 2014 at 10:13:46AM +0000, AKASHI Takahiro wrote:
>> Recordmcount utility under scripts is run, after compiling each object,
>> to find out all the locations of calling _mcount() and put them into
>> specific seciton named __mcount_loc.
>> Then linker collects all such information into a table in the kernel image
>> (between __start_mcount_loc and __stop_mcount_loc) for later use by ftrace.
>>
>> This patch adds arm64 specific definitions to identify such locations.
>> There are two types of implementation, C and Perl. On arm64, only C version
>> is used to build the kernel now that CONFIG_HAVE_C_RECORDMCOUNT is on.
>> But Perl version is also maintained.
>>
>> This patch also contains a workaround just in case where a header file,
>> elf.h, on host machine doesn't have definitions of EM_AARCH64 nor
>> R_AARCH64_ABS64. Without them, compiling C version of recordmcount will
>> fail.
>
> [...]
>
>> diff --git a/scripts/recordmcount.c b/scripts/recordmcount.c
>> index 9c22317..047c8cd 100644
>> --- a/scripts/recordmcount.c
>> +++ b/scripts/recordmcount.c
>> @@ -40,6 +40,11 @@
>>   #define R_METAG_NONE                     3
>>   #endif
>>
>> +#ifndef EM_AARCH64
>> +#define EM_AARCH64	183
>> +#define R_AARCH64_ABS64	257
>> +#endif
>> +
>>   static int fd_map;	/* File descriptor for file being modified. */
>>   static int mmap_failed; /* Boolean flag. */
>>   static void *ehdr_curr; /* current ElfXX_Ehdr *  for resource cleanup */
>> @@ -347,6 +352,10 @@ do_file(char const *const fname)
>>   	case EM_ARM:	 reltype = R_ARM_ABS32;
>>   			 altmcount = "__gnu_mcount_nc";
>>   			 break;
>> +	case EM_AARCH64:
>> +			 reltype = R_AARCH64_ABS64;
>> +			 altmcount = "_mcount";
>
> Shouldn't you be setting gpfx = '_' instead of overriding altmcount like
> this?

Yep. Fix it.

>> +			 break;
>>   	case EM_IA_64:	 reltype = R_IA64_IMM64;   gpfx = '_'; break;
>>   	case EM_METAG:	 reltype = R_METAG_ADDR32;
>>   			 altmcount = "_mcount_wrapper";
>> diff --git a/scripts/recordmcount.pl b/scripts/recordmcount.pl
>> index 91280b8..397b6b8 100755
>> --- a/scripts/recordmcount.pl
>> +++ b/scripts/recordmcount.pl
>> @@ -279,6 +279,11 @@ if ($arch eq "x86_64") {
>>       $mcount_regex = "^\\s*([0-9a-fA-F]+):\\s*R_ARM_(CALL|PC24|THM_CALL)" .
>>   			"\\s+(__gnu_mcount_nc|mcount)\$";
>>
>> +} elsif ($arch eq "arm64") {
>> +    $alignment = 3;
>> +    $section_type = '%progbits';
>> +    $mcount_regex = "^\\s*([0-9a-fA-F]+):\\s*R_AARCH64_CALL26\\s+_mcount\$";
>
> What about "mcount" (i.e. no underscore)?

I don't think it works since such regex doesn't match to "CALL26   _mcount".

Thanks,
-Takahiro AKASHI

> Will
>

^ permalink raw reply	[flat|nested] 235+ messages in thread

* Re: [PATCH v6 6/7] arm64: ftrace: Add CALLER_ADDRx macros
  2014-03-13 10:13           ` AKASHI Takahiro
@ 2014-03-13 15:54             ` Will Deacon
  -1 siblings, 0 replies; 235+ messages in thread
From: Will Deacon @ 2014-03-13 15:54 UTC (permalink / raw)
  To: AKASHI Takahiro
  Cc: rostedt, fweisbec, mingo, Catalin Marinas, tim.bird, gkulkarni,
	dsaxena, arndb, linux-arm-kernel, linaro-kernel, linux-kernel

On Thu, Mar 13, 2014 at 10:13:49AM +0000, AKASHI Takahiro wrote:
> CALLER_ADDRx returns caller's address at specified level in call stacks.
> They are used for several tracers like irqsoff and preemptoff.
> Strange to say, however, they are refered even without FTRACE.
> 
> Please note that this implementation assumes that we have frame pointers.
> (which means kernel should be compiled with -fno-omit-frame-pointer.)

How do you ensure that -fno-omit-frame-pointer is passed?

> Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
> ---
>  arch/arm64/include/asm/ftrace.h    |   13 ++++++++-
>  arch/arm64/kernel/Makefile         |    3 +-
>  arch/arm64/kernel/return_address.c |   55 ++++++++++++++++++++++++++++++++++++
>  3 files changed, 69 insertions(+), 2 deletions(-)
>  create mode 100644 arch/arm64/kernel/return_address.c
> 
> diff --git a/arch/arm64/include/asm/ftrace.h b/arch/arm64/include/asm/ftrace.h
> index ed5c448..c44c4b1 100644
> --- a/arch/arm64/include/asm/ftrace.h
> +++ b/arch/arm64/include/asm/ftrace.h
> @@ -18,6 +18,7 @@
>  
>  #ifndef __ASSEMBLY__
>  extern void _mcount(unsigned long);
> +extern void *return_address(unsigned int);
>  
>  struct dyn_arch_ftrace {
>  	/* No extra data needed for arm64 */
> @@ -33,6 +34,16 @@ static inline unsigned long ftrace_call_adjust(unsigned long addr)
>  	 */
>  	return addr;
>  }
> -#endif /* __ASSEMBLY__ */
> +
> +#define HAVE_ARCH_CALLER_ADDR
> +
> +#define CALLER_ADDR0 ((unsigned long)__builtin_return_address(0))
> +#define CALLER_ADDR1 ((unsigned long)return_address(1))
> +#define CALLER_ADDR2 ((unsigned long)return_address(2))
> +#define CALLER_ADDR3 ((unsigned long)return_address(3))
> +#define CALLER_ADDR4 ((unsigned long)return_address(4))
> +#define CALLER_ADDR5 ((unsigned long)return_address(5))
> +#define CALLER_ADDR6 ((unsigned long)return_address(6))

Could we change the core definitions of these macros (in linux/ftrace.h) to
use return_address, then provide an overridable version of return_address
that defaults to __builtin_return_address, instead of copy-pasting this
sequence?

> diff --git a/arch/arm64/kernel/return_address.c b/arch/arm64/kernel/return_address.c
> new file mode 100644
> index 0000000..89102a6
> --- /dev/null
> +++ b/arch/arm64/kernel/return_address.c
> @@ -0,0 +1,55 @@
> +/*
> + * arch/arm64/kernel/return_address.c
> + *
> + * Copyright (C) 2013 Linaro Limited
> + * Author: AKASHI Takahiro <takahiro.akashi@linaro.org>
> + *
> + * 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 <linux/export.h>
> +#include <linux/ftrace.h>
> +
> +#include <asm/stacktrace.h>
> +
> +struct return_address_data {
> +	unsigned int level;
> +	void *addr;
> +};
> +
> +static int save_return_addr(struct stackframe *frame, void *d)
> +{
> +	struct return_address_data *data = d;
> +
> +	if (!data->level) {
> +		data->addr = (void *)frame->pc;
> +		return 1;
> +	} else {
> +		--data->level;
> +		return 0;
> +	}
> +}
> +
> +void *return_address(unsigned int level)
> +{
> +	struct return_address_data data;
> +	struct stackframe frame;
> +	register unsigned long current_sp asm ("sp");
> +
> +	data.level = level + 2;
> +	data.addr = NULL;
> +
> +	frame.fp = (unsigned long)__builtin_frame_address(0);
> +	frame.sp = current_sp;
> +	frame.pc = (unsigned long)return_address; /* dummy */
> +
> +	walk_stackframe(&frame, save_return_addr, &data);
> +
> +	if (!data.level)
> +		return data.addr;
> +	else
> +		return NULL;
> +}
> +EXPORT_SYMBOL_GPL(return_address);

This whole file is basically copied from arch/arm/, but it's not too much
code. Ideally the toolchain would have made use of the frame pointer, but it
looks like it doesn't bother.

Will

^ permalink raw reply	[flat|nested] 235+ messages in thread

* [PATCH v6 6/7] arm64: ftrace: Add CALLER_ADDRx macros
@ 2014-03-13 15:54             ` Will Deacon
  0 siblings, 0 replies; 235+ messages in thread
From: Will Deacon @ 2014-03-13 15:54 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Mar 13, 2014 at 10:13:49AM +0000, AKASHI Takahiro wrote:
> CALLER_ADDRx returns caller's address at specified level in call stacks.
> They are used for several tracers like irqsoff and preemptoff.
> Strange to say, however, they are refered even without FTRACE.
> 
> Please note that this implementation assumes that we have frame pointers.
> (which means kernel should be compiled with -fno-omit-frame-pointer.)

How do you ensure that -fno-omit-frame-pointer is passed?

> Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
> ---
>  arch/arm64/include/asm/ftrace.h    |   13 ++++++++-
>  arch/arm64/kernel/Makefile         |    3 +-
>  arch/arm64/kernel/return_address.c |   55 ++++++++++++++++++++++++++++++++++++
>  3 files changed, 69 insertions(+), 2 deletions(-)
>  create mode 100644 arch/arm64/kernel/return_address.c
> 
> diff --git a/arch/arm64/include/asm/ftrace.h b/arch/arm64/include/asm/ftrace.h
> index ed5c448..c44c4b1 100644
> --- a/arch/arm64/include/asm/ftrace.h
> +++ b/arch/arm64/include/asm/ftrace.h
> @@ -18,6 +18,7 @@
>  
>  #ifndef __ASSEMBLY__
>  extern void _mcount(unsigned long);
> +extern void *return_address(unsigned int);
>  
>  struct dyn_arch_ftrace {
>  	/* No extra data needed for arm64 */
> @@ -33,6 +34,16 @@ static inline unsigned long ftrace_call_adjust(unsigned long addr)
>  	 */
>  	return addr;
>  }
> -#endif /* __ASSEMBLY__ */
> +
> +#define HAVE_ARCH_CALLER_ADDR
> +
> +#define CALLER_ADDR0 ((unsigned long)__builtin_return_address(0))
> +#define CALLER_ADDR1 ((unsigned long)return_address(1))
> +#define CALLER_ADDR2 ((unsigned long)return_address(2))
> +#define CALLER_ADDR3 ((unsigned long)return_address(3))
> +#define CALLER_ADDR4 ((unsigned long)return_address(4))
> +#define CALLER_ADDR5 ((unsigned long)return_address(5))
> +#define CALLER_ADDR6 ((unsigned long)return_address(6))

Could we change the core definitions of these macros (in linux/ftrace.h) to
use return_address, then provide an overridable version of return_address
that defaults to __builtin_return_address, instead of copy-pasting this
sequence?

> diff --git a/arch/arm64/kernel/return_address.c b/arch/arm64/kernel/return_address.c
> new file mode 100644
> index 0000000..89102a6
> --- /dev/null
> +++ b/arch/arm64/kernel/return_address.c
> @@ -0,0 +1,55 @@
> +/*
> + * arch/arm64/kernel/return_address.c
> + *
> + * Copyright (C) 2013 Linaro Limited
> + * Author: AKASHI Takahiro <takahiro.akashi@linaro.org>
> + *
> + * 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 <linux/export.h>
> +#include <linux/ftrace.h>
> +
> +#include <asm/stacktrace.h>
> +
> +struct return_address_data {
> +	unsigned int level;
> +	void *addr;
> +};
> +
> +static int save_return_addr(struct stackframe *frame, void *d)
> +{
> +	struct return_address_data *data = d;
> +
> +	if (!data->level) {
> +		data->addr = (void *)frame->pc;
> +		return 1;
> +	} else {
> +		--data->level;
> +		return 0;
> +	}
> +}
> +
> +void *return_address(unsigned int level)
> +{
> +	struct return_address_data data;
> +	struct stackframe frame;
> +	register unsigned long current_sp asm ("sp");
> +
> +	data.level = level + 2;
> +	data.addr = NULL;
> +
> +	frame.fp = (unsigned long)__builtin_frame_address(0);
> +	frame.sp = current_sp;
> +	frame.pc = (unsigned long)return_address; /* dummy */
> +
> +	walk_stackframe(&frame, save_return_addr, &data);
> +
> +	if (!data.level)
> +		return data.addr;
> +	else
> +		return NULL;
> +}
> +EXPORT_SYMBOL_GPL(return_address);

This whole file is basically copied from arch/arm/, but it's not too much
code. Ideally the toolchain would have made use of the frame pointer, but it
looks like it doesn't bother.

Will

^ permalink raw reply	[flat|nested] 235+ messages in thread

* Re: [PATCH v6 3/7] ftrace: Add arm64 support to recordmcount
  2014-03-13 14:57               ` AKASHI Takahiro
@ 2014-03-13 16:05                 ` Will Deacon
  -1 siblings, 0 replies; 235+ messages in thread
From: Will Deacon @ 2014-03-13 16:05 UTC (permalink / raw)
  To: AKASHI Takahiro
  Cc: rostedt, fweisbec, mingo, Catalin Marinas, tim.bird, gkulkarni,
	dsaxena, arndb, linux-arm-kernel, linaro-kernel, linux-kernel

On Thu, Mar 13, 2014 at 02:57:58PM +0000, AKASHI Takahiro wrote:
> On 03/13/2014 09:38 PM, Will Deacon wrote:
> > On Thu, Mar 13, 2014 at 10:13:46AM +0000, AKASHI Takahiro wrote:
> >> diff --git a/scripts/recordmcount.pl b/scripts/recordmcount.pl
> >> index 91280b8..397b6b8 100755
> >> --- a/scripts/recordmcount.pl
> >> +++ b/scripts/recordmcount.pl
> >> @@ -279,6 +279,11 @@ if ($arch eq "x86_64") {
> >>       $mcount_regex = "^\\s*([0-9a-fA-F]+):\\s*R_ARM_(CALL|PC24|THM_CALL)" .
> >>   			"\\s+(__gnu_mcount_nc|mcount)\$";
> >>
> >> +} elsif ($arch eq "arm64") {
> >> +    $alignment = 3;
> >> +    $section_type = '%progbits';
> >> +    $mcount_regex = "^\\s*([0-9a-fA-F]+):\\s*R_AARCH64_CALL26\\s+_mcount\$";
> >
> > What about "mcount" (i.e. no underscore)?
> 
> I don't think it works since such regex doesn't match to "CALL26   _mcount".

What I meant was, do you need to match "mcount" as well? However, after
speaking to our GCC guys, they say they only support "_mcount" (preferred)
and "__mcount" (which GCC itself doesn't emit) so you can leave this regex
as-is.

Will

^ permalink raw reply	[flat|nested] 235+ messages in thread

* [PATCH v6 3/7] ftrace: Add arm64 support to recordmcount
@ 2014-03-13 16:05                 ` Will Deacon
  0 siblings, 0 replies; 235+ messages in thread
From: Will Deacon @ 2014-03-13 16:05 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Mar 13, 2014 at 02:57:58PM +0000, AKASHI Takahiro wrote:
> On 03/13/2014 09:38 PM, Will Deacon wrote:
> > On Thu, Mar 13, 2014 at 10:13:46AM +0000, AKASHI Takahiro wrote:
> >> diff --git a/scripts/recordmcount.pl b/scripts/recordmcount.pl
> >> index 91280b8..397b6b8 100755
> >> --- a/scripts/recordmcount.pl
> >> +++ b/scripts/recordmcount.pl
> >> @@ -279,6 +279,11 @@ if ($arch eq "x86_64") {
> >>       $mcount_regex = "^\\s*([0-9a-fA-F]+):\\s*R_ARM_(CALL|PC24|THM_CALL)" .
> >>   			"\\s+(__gnu_mcount_nc|mcount)\$";
> >>
> >> +} elsif ($arch eq "arm64") {
> >> +    $alignment = 3;
> >> +    $section_type = '%progbits';
> >> +    $mcount_regex = "^\\s*([0-9a-fA-F]+):\\s*R_AARCH64_CALL26\\s+_mcount\$";
> >
> > What about "mcount" (i.e. no underscore)?
> 
> I don't think it works since such regex doesn't match to "CALL26   _mcount".

What I meant was, do you need to match "mcount" as well? However, after
speaking to our GCC guys, they say they only support "_mcount" (preferred)
and "__mcount" (which GCC itself doesn't emit) so you can leave this regex
as-is.

Will

^ permalink raw reply	[flat|nested] 235+ messages in thread

* Re: [PATCH v6 7/7] arm64: ftrace: Add system call tracepoint
  2014-03-13 10:13           ` AKASHI Takahiro
@ 2014-03-13 16:25             ` Will Deacon
  -1 siblings, 0 replies; 235+ messages in thread
From: Will Deacon @ 2014-03-13 16:25 UTC (permalink / raw)
  To: AKASHI Takahiro
  Cc: rostedt, fweisbec, mingo, Catalin Marinas, tim.bird, gkulkarni,
	dsaxena, arndb, linux-arm-kernel, linaro-kernel, linux-kernel

On Thu, Mar 13, 2014 at 10:13:50AM +0000, AKASHI Takahiro wrote:
> This patch allows system call entry or exit to be traced as ftrace events,
> ie. sys_enter_*/sys_exit_*, if CONFIG_FTRACE_SYSCALLS is enabled.
> Those events appear and can be controlled under
>     ${sysfs}/tracing/events/syscalls/
> 
> Please note that we can't trace compat system calls here because
> AArch32 mode does not share the same syscall table with AArch64.
> Just define ARCH_TRACE_IGNORE_COMPAT_SYSCALLS in order to avoid unexpected
> results (bogus syscalls reported or even hang-up).
> 
> Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
> ---
>  arch/arm64/Kconfig               |    1 +
>  arch/arm64/include/asm/ftrace.h  |   20 ++++++++++++++++
>  arch/arm64/include/asm/syscall.h |    1 +
>  arch/arm64/include/asm/unistd.h  |    2 ++
>  arch/arm64/kernel/ptrace.c       |   48 ++++++++++++++++++++++----------------
>  5 files changed, 52 insertions(+), 20 deletions(-)
> 
> diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
> index 6954959..b1dcdb4 100644
> --- a/arch/arm64/Kconfig
> +++ b/arch/arm64/Kconfig
> @@ -43,6 +43,7 @@ config ARM64
>  	select HAVE_MEMBLOCK
>  	select HAVE_PATA_PLATFORM
>  	select HAVE_PERF_EVENTS
> +	select HAVE_SYSCALL_TRACEPOINTS
>  	select IRQ_DOMAIN
>  	select MODULES_USE_ELF_RELA
>  	select NO_BOOTMEM
> diff --git a/arch/arm64/include/asm/ftrace.h b/arch/arm64/include/asm/ftrace.h
> index c44c4b1..4ef06f1 100644
> --- a/arch/arm64/include/asm/ftrace.h
> +++ b/arch/arm64/include/asm/ftrace.h
> @@ -44,6 +44,26 @@ static inline unsigned long ftrace_call_adjust(unsigned long addr)
>  #define CALLER_ADDR4 ((unsigned long)return_address(4))
>  #define CALLER_ADDR5 ((unsigned long)return_address(5))
>  #define CALLER_ADDR6 ((unsigned long)return_address(6))
> +
> +#include <asm/compat.h>
> +
> +/*
> + * Because AArch32 mode does not share the same syscall table with AArch64,
> + * tracing compat syscalls may result in reporting bogus syscalls or even
> + * hang-up, so just do not trace them.
> + * See kernel/trace/trace_syscalls.c
> + *
> + * x86 code says:
> + * If the user realy wants these, then they should use the
> + * raw syscall tracepoints with filtering.

Fair enough.

> + */
> +#define ARCH_TRACE_IGNORE_COMPAT_SYSCALLS 1

You don't need the '1' here.

> +static inline bool arch_trace_is_compat_syscall(struct pt_regs *regs)
> +{
> +        if (is_compat_task())
> +                return true;
> +        return false;
> +}

return is_compat_task();

>  #endif /* ifndef __ASSEMBLY__ */
>  
>  #endif /* __ASM_FTRACE_H */
> diff --git a/arch/arm64/include/asm/syscall.h b/arch/arm64/include/asm/syscall.h
> index 70ba9d4..383771e 100644
> --- a/arch/arm64/include/asm/syscall.h
> +++ b/arch/arm64/include/asm/syscall.h
> @@ -18,6 +18,7 @@
>  
>  #include <linux/err.h>
>  
> +extern const void *sys_call_table[];
>  
>  static inline int syscall_get_nr(struct task_struct *task,
>  				 struct pt_regs *regs)
> diff --git a/arch/arm64/include/asm/unistd.h b/arch/arm64/include/asm/unistd.h
> index 82ce217..c335479 100644
> --- a/arch/arm64/include/asm/unistd.h
> +++ b/arch/arm64/include/asm/unistd.h
> @@ -28,3 +28,5 @@
>  #endif
>  #define __ARCH_WANT_SYS_CLONE
>  #include <uapi/asm/unistd.h>
> +
> +#define NR_syscalls (__NR_syscalls)
> diff --git a/arch/arm64/kernel/ptrace.c b/arch/arm64/kernel/ptrace.c
> index 9993a8f..9c52b3e 100644
> --- a/arch/arm64/kernel/ptrace.c
> +++ b/arch/arm64/kernel/ptrace.c
> @@ -41,6 +41,9 @@
>  #include <asm/traps.h>
>  #include <asm/system_misc.h>
>  
> +#define CREATE_TRACE_POINTS
> +#include <trace/events/syscalls.h>
> +
>  /*
>   * TODO: does not yet catch signals sent when the child dies.
>   * in exit.c or in signal.c.
> @@ -1062,29 +1065,31 @@ asmlinkage int syscall_trace_enter(struct pt_regs *regs)
>  {
>  	unsigned long saved_reg;
>  
> -	if (!test_thread_flag(TIF_SYSCALL_TRACE))
> -		return regs->syscallno;
> +	if (test_thread_flag(TIF_SYSCALL_TRACE)) {
> +		/*
> +		 * A scrach register (ip(r12) on AArch32, x7 on AArch64) is
> +		 * used to denote syscall entry/exit:
> +		 *   0 -> entry
> +		 */
> +		if (is_compat_task()) {

if (arch_trace_is_compat_syscall())

With those changes:

  Acked-by: Will Deacon <will.deacon@arm.com>

Will

^ permalink raw reply	[flat|nested] 235+ messages in thread

* [PATCH v6 7/7] arm64: ftrace: Add system call tracepoint
@ 2014-03-13 16:25             ` Will Deacon
  0 siblings, 0 replies; 235+ messages in thread
From: Will Deacon @ 2014-03-13 16:25 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Mar 13, 2014 at 10:13:50AM +0000, AKASHI Takahiro wrote:
> This patch allows system call entry or exit to be traced as ftrace events,
> ie. sys_enter_*/sys_exit_*, if CONFIG_FTRACE_SYSCALLS is enabled.
> Those events appear and can be controlled under
>     ${sysfs}/tracing/events/syscalls/
> 
> Please note that we can't trace compat system calls here because
> AArch32 mode does not share the same syscall table with AArch64.
> Just define ARCH_TRACE_IGNORE_COMPAT_SYSCALLS in order to avoid unexpected
> results (bogus syscalls reported or even hang-up).
> 
> Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
> ---
>  arch/arm64/Kconfig               |    1 +
>  arch/arm64/include/asm/ftrace.h  |   20 ++++++++++++++++
>  arch/arm64/include/asm/syscall.h |    1 +
>  arch/arm64/include/asm/unistd.h  |    2 ++
>  arch/arm64/kernel/ptrace.c       |   48 ++++++++++++++++++++++----------------
>  5 files changed, 52 insertions(+), 20 deletions(-)
> 
> diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
> index 6954959..b1dcdb4 100644
> --- a/arch/arm64/Kconfig
> +++ b/arch/arm64/Kconfig
> @@ -43,6 +43,7 @@ config ARM64
>  	select HAVE_MEMBLOCK
>  	select HAVE_PATA_PLATFORM
>  	select HAVE_PERF_EVENTS
> +	select HAVE_SYSCALL_TRACEPOINTS
>  	select IRQ_DOMAIN
>  	select MODULES_USE_ELF_RELA
>  	select NO_BOOTMEM
> diff --git a/arch/arm64/include/asm/ftrace.h b/arch/arm64/include/asm/ftrace.h
> index c44c4b1..4ef06f1 100644
> --- a/arch/arm64/include/asm/ftrace.h
> +++ b/arch/arm64/include/asm/ftrace.h
> @@ -44,6 +44,26 @@ static inline unsigned long ftrace_call_adjust(unsigned long addr)
>  #define CALLER_ADDR4 ((unsigned long)return_address(4))
>  #define CALLER_ADDR5 ((unsigned long)return_address(5))
>  #define CALLER_ADDR6 ((unsigned long)return_address(6))
> +
> +#include <asm/compat.h>
> +
> +/*
> + * Because AArch32 mode does not share the same syscall table with AArch64,
> + * tracing compat syscalls may result in reporting bogus syscalls or even
> + * hang-up, so just do not trace them.
> + * See kernel/trace/trace_syscalls.c
> + *
> + * x86 code says:
> + * If the user realy wants these, then they should use the
> + * raw syscall tracepoints with filtering.

Fair enough.

> + */
> +#define ARCH_TRACE_IGNORE_COMPAT_SYSCALLS 1

You don't need the '1' here.

> +static inline bool arch_trace_is_compat_syscall(struct pt_regs *regs)
> +{
> +        if (is_compat_task())
> +                return true;
> +        return false;
> +}

return is_compat_task();

>  #endif /* ifndef __ASSEMBLY__ */
>  
>  #endif /* __ASM_FTRACE_H */
> diff --git a/arch/arm64/include/asm/syscall.h b/arch/arm64/include/asm/syscall.h
> index 70ba9d4..383771e 100644
> --- a/arch/arm64/include/asm/syscall.h
> +++ b/arch/arm64/include/asm/syscall.h
> @@ -18,6 +18,7 @@
>  
>  #include <linux/err.h>
>  
> +extern const void *sys_call_table[];
>  
>  static inline int syscall_get_nr(struct task_struct *task,
>  				 struct pt_regs *regs)
> diff --git a/arch/arm64/include/asm/unistd.h b/arch/arm64/include/asm/unistd.h
> index 82ce217..c335479 100644
> --- a/arch/arm64/include/asm/unistd.h
> +++ b/arch/arm64/include/asm/unistd.h
> @@ -28,3 +28,5 @@
>  #endif
>  #define __ARCH_WANT_SYS_CLONE
>  #include <uapi/asm/unistd.h>
> +
> +#define NR_syscalls (__NR_syscalls)
> diff --git a/arch/arm64/kernel/ptrace.c b/arch/arm64/kernel/ptrace.c
> index 9993a8f..9c52b3e 100644
> --- a/arch/arm64/kernel/ptrace.c
> +++ b/arch/arm64/kernel/ptrace.c
> @@ -41,6 +41,9 @@
>  #include <asm/traps.h>
>  #include <asm/system_misc.h>
>  
> +#define CREATE_TRACE_POINTS
> +#include <trace/events/syscalls.h>
> +
>  /*
>   * TODO: does not yet catch signals sent when the child dies.
>   * in exit.c or in signal.c.
> @@ -1062,29 +1065,31 @@ asmlinkage int syscall_trace_enter(struct pt_regs *regs)
>  {
>  	unsigned long saved_reg;
>  
> -	if (!test_thread_flag(TIF_SYSCALL_TRACE))
> -		return regs->syscallno;
> +	if (test_thread_flag(TIF_SYSCALL_TRACE)) {
> +		/*
> +		 * A scrach register (ip(r12) on AArch32, x7 on AArch64) is
> +		 * used to denote syscall entry/exit:
> +		 *   0 -> entry
> +		 */
> +		if (is_compat_task()) {

if (arch_trace_is_compat_syscall())

With those changes:

  Acked-by: Will Deacon <will.deacon@arm.com>

Will

^ permalink raw reply	[flat|nested] 235+ messages in thread

* Re: [PATCH v6 4/7] arm64: Add ftrace support
  2014-03-13 10:13           ` AKASHI Takahiro
@ 2014-03-13 17:08             ` Will Deacon
  -1 siblings, 0 replies; 235+ messages in thread
From: Will Deacon @ 2014-03-13 17:08 UTC (permalink / raw)
  To: AKASHI Takahiro
  Cc: rostedt, fweisbec, mingo, Catalin Marinas, tim.bird, gkulkarni,
	dsaxena, arndb, linux-arm-kernel, linaro-kernel, linux-kernel

On Thu, Mar 13, 2014 at 10:13:47AM +0000, AKASHI Takahiro wrote:
> This patch implements arm64 specific part to support function tracers,
> such as function (CONFIG_FUNCTION_TRACER), function_graph
> (CONFIG_FUNCTION_GRAPH_TRACER) and function profiler
> (CONFIG_FUNCTION_PROFILER).
> 
> With 'function' tracer, all the functions in the kernel are traced with
> timestamps in ${sysfs}/tracing/trace. If function_graph tracer is
> specified, call graph is generated.
> 
> The kernel must be compiled with -pg option so that _mcount() is inserted
> at the beginning of functions. This function is called on every function's
> entry as long as tracing is enabled.
> In addition, function_graph tracer also needs to be able to probe function's
> exit. ftrace_graph_caller() & return_to_handler do this by faking link
> register's value to intercept function's return path.
> 
> More details on architecture specific requirements are described in
> Documentation/trace/ftrace-design.txt.

[...]

> diff --git a/arch/arm64/kernel/entry-ftrace.S b/arch/arm64/kernel/entry-ftrace.S
> new file mode 100644
> index 0000000..0ac31c8
> --- /dev/null
> +++ b/arch/arm64/kernel/entry-ftrace.S
> @@ -0,0 +1,175 @@
> +/*
> + * arch/arm64/kernel/entry-ftrace.S
> + *
> + * Copyright (C) 2013 Linaro Limited
> + * Author: AKASHI Takahiro <takahiro.akashi@linaro.org>
> + *
> + * 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 <linux/linkage.h>
> +#include <asm/ftrace.h>
> +#include <asm/insn.h>
> +
> +/*
> + * Gcc with -pg will put the following code in the beginning of each function:
> + *      mov x0, x30
> + *      bl _mcount
> + *     [function's body ...]
> + * "bl _mcount" may be replaced to "bl ftrace_caller" or NOP if dynamic
> + * ftrace is enabled.
> + *
> + * Please note that x0 as an argument will not be used here because we can
> + * get lr(x30) of instrumented function at any time by winding up call stack
> + * as long as the kernel is compiled without -fomit-frame-pointer.
> + * (or CONFIG_FRAME_POINTER, this is forced on arm64)
> + *
> + * stack layout after mcount_enter in _mcount():
> + *
> + * current sp/fp =>  0:+-----+
> + * in _mcount()               | x29 | -> instrumented function's fp
> + *                    +-----+
> + *                    | x30 | -> _mcount()'s lr (= instrumented function's pc)
> + * old sp      => +16:+-----+
> + * when instrumented   |     |
> + * function calls      | ... |
> + * _mcount()          |     |
> + *                    |     |
> + * instrumented => +xx:+-----+
> + * function's fp       | x29 | -> parent's fp
> + *                    +-----+
> + *                    | x30 | -> instrumented function's lr (= parent's pc)
> + *                    +-----+
> + *                    | ... |

I guess it's just the diff that's misaligning your ASCII art here?

> +/*
> + * void return_to_handler(void)
> + *
> + * Run ftrace_return_to_handler() before going back to parent.
> + * @fp is checked against the value passed by ftrace_graph_caller()
> + * only when CONFIG_FUNCTION_GRAPH_FP_TEST is enabled.
> + */
> +       .global return_to_handler
> +return_to_handler:

ENTRY(return_to_handler)

> +       str     x0, [sp, #-16]!
> +       mov     x0, x29                 //     parent's fp
> +       bl      ftrace_return_to_handler// addr = ftrace_return_to_hander(fp);
> +       mov     x30, x0                 // restore the original return address
> +       ldr     x0, [sp], #16
> +       ret

and an ENDPROC here.

> +#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
> diff --git a/arch/arm64/kernel/ftrace.c b/arch/arm64/kernel/ftrace.c
> new file mode 100644
> index 0000000..a559ab8
> --- /dev/null
> +++ b/arch/arm64/kernel/ftrace.c
> @@ -0,0 +1,64 @@
> +/*
> + * arch/arm64/kernel/ftrace.c
> + *
> + * Copyright (C) 2013 Linaro Limited
> + * Author: AKASHI Takahiro <takahiro.akashi@linaro.org>
> + *
> + * 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 <linux/ftrace.h>
> +#include <linux/swab.h>
> +#include <linux/uaccess.h>
> +
> +#include <asm/cacheflush.h>
> +#include <asm/ftrace.h>
> +#include <asm/insn.h>
> +
> +#ifdef CONFIG_FUNCTION_GRAPH_TRACER
> +/*
> + * function_graph tracer expects ftrace_return_to_handler() to be called
> + * on the way back to parent. For this purpose, this function is called
> + * in _mcount() or ftrace_caller() to replace return address (*parent) on
> + * the call stack to return_to_handler.
> + *
> + * Note that @frame_pointer is used only for sanity check later.
> + */
> +void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr,
> +                          unsigned long frame_pointer)
> +{
> +       unsigned long return_hooker = (unsigned long)&return_to_handler;
> +       unsigned long old;
> +       struct ftrace_graph_ent trace;
> +       int err;
> +
> +       if (unlikely(atomic_read(&current->tracing_graph_pause)))
> +               return;
> +
> +       /*
> +        * Note:
> +        * No protection against faulting at *parent, which may be seen
> +        * on other archs. It's unlikely on AArch64.
> +        */
> +       old = *parent;
> +       *parent = return_hooker;

return_hook? People might take it personally otherwise ;)

> +       trace.func = self_addr;

in kernel/ftrace/ftrace.c there's an smb_wmb() between setting up
tracing_graph_pause and setting the ret_stack with a comment saying:

    /* Make sure the tasks see the -1 first: */

Why don't we have a corresponding read-barrier here?

Will

^ permalink raw reply	[flat|nested] 235+ messages in thread

* [PATCH v6 4/7] arm64: Add ftrace support
@ 2014-03-13 17:08             ` Will Deacon
  0 siblings, 0 replies; 235+ messages in thread
From: Will Deacon @ 2014-03-13 17:08 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Mar 13, 2014 at 10:13:47AM +0000, AKASHI Takahiro wrote:
> This patch implements arm64 specific part to support function tracers,
> such as function (CONFIG_FUNCTION_TRACER), function_graph
> (CONFIG_FUNCTION_GRAPH_TRACER) and function profiler
> (CONFIG_FUNCTION_PROFILER).
> 
> With 'function' tracer, all the functions in the kernel are traced with
> timestamps in ${sysfs}/tracing/trace. If function_graph tracer is
> specified, call graph is generated.
> 
> The kernel must be compiled with -pg option so that _mcount() is inserted
> at the beginning of functions. This function is called on every function's
> entry as long as tracing is enabled.
> In addition, function_graph tracer also needs to be able to probe function's
> exit. ftrace_graph_caller() & return_to_handler do this by faking link
> register's value to intercept function's return path.
> 
> More details on architecture specific requirements are described in
> Documentation/trace/ftrace-design.txt.

[...]

> diff --git a/arch/arm64/kernel/entry-ftrace.S b/arch/arm64/kernel/entry-ftrace.S
> new file mode 100644
> index 0000000..0ac31c8
> --- /dev/null
> +++ b/arch/arm64/kernel/entry-ftrace.S
> @@ -0,0 +1,175 @@
> +/*
> + * arch/arm64/kernel/entry-ftrace.S
> + *
> + * Copyright (C) 2013 Linaro Limited
> + * Author: AKASHI Takahiro <takahiro.akashi@linaro.org>
> + *
> + * 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 <linux/linkage.h>
> +#include <asm/ftrace.h>
> +#include <asm/insn.h>
> +
> +/*
> + * Gcc with -pg will put the following code in the beginning of each function:
> + *      mov x0, x30
> + *      bl _mcount
> + *     [function's body ...]
> + * "bl _mcount" may be replaced to "bl ftrace_caller" or NOP if dynamic
> + * ftrace is enabled.
> + *
> + * Please note that x0 as an argument will not be used here because we can
> + * get lr(x30) of instrumented function at any time by winding up call stack
> + * as long as the kernel is compiled without -fomit-frame-pointer.
> + * (or CONFIG_FRAME_POINTER, this is forced on arm64)
> + *
> + * stack layout after mcount_enter in _mcount():
> + *
> + * current sp/fp =>  0:+-----+
> + * in _mcount()               | x29 | -> instrumented function's fp
> + *                    +-----+
> + *                    | x30 | -> _mcount()'s lr (= instrumented function's pc)
> + * old sp      => +16:+-----+
> + * when instrumented   |     |
> + * function calls      | ... |
> + * _mcount()          |     |
> + *                    |     |
> + * instrumented => +xx:+-----+
> + * function's fp       | x29 | -> parent's fp
> + *                    +-----+
> + *                    | x30 | -> instrumented function's lr (= parent's pc)
> + *                    +-----+
> + *                    | ... |

I guess it's just the diff that's misaligning your ASCII art here?

> +/*
> + * void return_to_handler(void)
> + *
> + * Run ftrace_return_to_handler() before going back to parent.
> + * @fp is checked against the value passed by ftrace_graph_caller()
> + * only when CONFIG_FUNCTION_GRAPH_FP_TEST is enabled.
> + */
> +       .global return_to_handler
> +return_to_handler:

ENTRY(return_to_handler)

> +       str     x0, [sp, #-16]!
> +       mov     x0, x29                 //     parent's fp
> +       bl      ftrace_return_to_handler// addr = ftrace_return_to_hander(fp);
> +       mov     x30, x0                 // restore the original return address
> +       ldr     x0, [sp], #16
> +       ret

and an ENDPROC here.

> +#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
> diff --git a/arch/arm64/kernel/ftrace.c b/arch/arm64/kernel/ftrace.c
> new file mode 100644
> index 0000000..a559ab8
> --- /dev/null
> +++ b/arch/arm64/kernel/ftrace.c
> @@ -0,0 +1,64 @@
> +/*
> + * arch/arm64/kernel/ftrace.c
> + *
> + * Copyright (C) 2013 Linaro Limited
> + * Author: AKASHI Takahiro <takahiro.akashi@linaro.org>
> + *
> + * 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 <linux/ftrace.h>
> +#include <linux/swab.h>
> +#include <linux/uaccess.h>
> +
> +#include <asm/cacheflush.h>
> +#include <asm/ftrace.h>
> +#include <asm/insn.h>
> +
> +#ifdef CONFIG_FUNCTION_GRAPH_TRACER
> +/*
> + * function_graph tracer expects ftrace_return_to_handler() to be called
> + * on the way back to parent. For this purpose, this function is called
> + * in _mcount() or ftrace_caller() to replace return address (*parent) on
> + * the call stack to return_to_handler.
> + *
> + * Note that @frame_pointer is used only for sanity check later.
> + */
> +void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr,
> +                          unsigned long frame_pointer)
> +{
> +       unsigned long return_hooker = (unsigned long)&return_to_handler;
> +       unsigned long old;
> +       struct ftrace_graph_ent trace;
> +       int err;
> +
> +       if (unlikely(atomic_read(&current->tracing_graph_pause)))
> +               return;
> +
> +       /*
> +        * Note:
> +        * No protection against faulting at *parent, which may be seen
> +        * on other archs. It's unlikely on AArch64.
> +        */
> +       old = *parent;
> +       *parent = return_hooker;

return_hook? People might take it personally otherwise ;)

> +       trace.func = self_addr;

in kernel/ftrace/ftrace.c there's an smb_wmb() between setting up
tracing_graph_pause and setting the ret_stack with a comment saying:

    /* Make sure the tasks see the -1 first: */

Why don't we have a corresponding read-barrier here?

Will

^ permalink raw reply	[flat|nested] 235+ messages in thread

* Re: [PATCH v6 6/7] arm64: ftrace: Add CALLER_ADDRx macros
  2014-03-13 15:54             ` Will Deacon
@ 2014-03-13 18:07               ` Steven Rostedt
  -1 siblings, 0 replies; 235+ messages in thread
From: Steven Rostedt @ 2014-03-13 18:07 UTC (permalink / raw)
  To: Will Deacon
  Cc: AKASHI Takahiro, fweisbec, mingo, Catalin Marinas, tim.bird,
	gkulkarni, dsaxena, arndb, linux-arm-kernel, linaro-kernel,
	linux-kernel

On Thu, 2014-03-13 at 15:54 +0000, Will Deacon wrote:
> On Thu, Mar 13, 2014 at 10:13:49AM +0000, AKASHI Takahiro wrote:
> > CALLER_ADDRx returns caller's address at specified level in call stacks.
> > They are used for several tracers like irqsoff and preemptoff.
> > Strange to say, however, they are refered even without FTRACE.
> > 
> > Please note that this implementation assumes that we have frame pointers.
> > (which means kernel should be compiled with -fno-omit-frame-pointer.)
> 
> How do you ensure that -fno-omit-frame-pointer is passed?

Perhaps -pg does the same thing?

> > +#define HAVE_ARCH_CALLER_ADDR
> > +
> > +#define CALLER_ADDR0 ((unsigned long)__builtin_return_address(0))
> > +#define CALLER_ADDR1 ((unsigned long)return_address(1))
> > +#define CALLER_ADDR2 ((unsigned long)return_address(2))
> > +#define CALLER_ADDR3 ((unsigned long)return_address(3))
> > +#define CALLER_ADDR4 ((unsigned long)return_address(4))
> > +#define CALLER_ADDR5 ((unsigned long)return_address(5))
> > +#define CALLER_ADDR6 ((unsigned long)return_address(6))
> 
> Could we change the core definitions of these macros (in linux/ftrace.h) to
> use return_address, then provide an overridable version of return_address
> that defaults to __builtin_return_address, instead of copy-pasting this
> sequence?

We could add a new macro:

/* All archs should have this, but we define it for consistency */
#ifndef ftrace_return_address0
# define ftrace_return_address0  __builtin_return_address(0)
#endif
/* Archs may use other ways for ADDR1 and beyond */
#ifndef ftrace_return_address
# define ftrace_return_address(n) __builtin_return_address(n)
#endif

And then have:

#define CALLER_ADDR0 ((unsigned long)ftrace_return_address0)
#define CALLER_ADDR1 ((unsigned long)ftrace_return_address(1))
[...]

And then you would only need to redefine ftrace_return_address.

-- Steve



^ permalink raw reply	[flat|nested] 235+ messages in thread

* [PATCH v6 6/7] arm64: ftrace: Add CALLER_ADDRx macros
@ 2014-03-13 18:07               ` Steven Rostedt
  0 siblings, 0 replies; 235+ messages in thread
From: Steven Rostedt @ 2014-03-13 18:07 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, 2014-03-13 at 15:54 +0000, Will Deacon wrote:
> On Thu, Mar 13, 2014 at 10:13:49AM +0000, AKASHI Takahiro wrote:
> > CALLER_ADDRx returns caller's address at specified level in call stacks.
> > They are used for several tracers like irqsoff and preemptoff.
> > Strange to say, however, they are refered even without FTRACE.
> > 
> > Please note that this implementation assumes that we have frame pointers.
> > (which means kernel should be compiled with -fno-omit-frame-pointer.)
> 
> How do you ensure that -fno-omit-frame-pointer is passed?

Perhaps -pg does the same thing?

> > +#define HAVE_ARCH_CALLER_ADDR
> > +
> > +#define CALLER_ADDR0 ((unsigned long)__builtin_return_address(0))
> > +#define CALLER_ADDR1 ((unsigned long)return_address(1))
> > +#define CALLER_ADDR2 ((unsigned long)return_address(2))
> > +#define CALLER_ADDR3 ((unsigned long)return_address(3))
> > +#define CALLER_ADDR4 ((unsigned long)return_address(4))
> > +#define CALLER_ADDR5 ((unsigned long)return_address(5))
> > +#define CALLER_ADDR6 ((unsigned long)return_address(6))
> 
> Could we change the core definitions of these macros (in linux/ftrace.h) to
> use return_address, then provide an overridable version of return_address
> that defaults to __builtin_return_address, instead of copy-pasting this
> sequence?

We could add a new macro:

/* All archs should have this, but we define it for consistency */
#ifndef ftrace_return_address0
# define ftrace_return_address0  __builtin_return_address(0)
#endif
/* Archs may use other ways for ADDR1 and beyond */
#ifndef ftrace_return_address
# define ftrace_return_address(n) __builtin_return_address(n)
#endif

And then have:

#define CALLER_ADDR0 ((unsigned long)ftrace_return_address0)
#define CALLER_ADDR1 ((unsigned long)ftrace_return_address(1))
[...]

And then you would only need to redefine ftrace_return_address.

-- Steve

^ permalink raw reply	[flat|nested] 235+ messages in thread

* Re: [PATCH v6 5/7] arm64: ftrace: Add dynamic ftrace support
  2014-03-13 10:13           ` AKASHI Takahiro
@ 2014-03-13 18:10             ` Will Deacon
  -1 siblings, 0 replies; 235+ messages in thread
From: Will Deacon @ 2014-03-13 18:10 UTC (permalink / raw)
  To: AKASHI Takahiro
  Cc: rostedt, fweisbec, mingo, Catalin Marinas, tim.bird, gkulkarni,
	dsaxena, arndb, linux-arm-kernel, linaro-kernel, linux-kernel

On Thu, Mar 13, 2014 at 10:13:48AM +0000, AKASHI Takahiro wrote:
> This patch allows "dynamic ftrace" if CONFIG_DYNAMIC_FTRACE is enabled.
> Here we can turn on and off tracing dynamically per-function base.
> 
> On arm64, this is done by patching single branch instruction to _mcount()
> inserted by gcc -pg option. The branch is replaced to NOP initially at
> kernel start up, and later on, NOP to branch to ftrace_caller() when
> enabled or branch to NOP when disabled.
> Please note that ftrace_caller() is a counterpart of _mcount() in case of
> 'static' ftrace.
> 
> More details on architecture specific requirements are described in
> Documentation/trace/ftrace-design.txt.
> 
> Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
> ---
>  arch/arm64/Kconfig               |    1 +
>  arch/arm64/include/asm/ftrace.h  |   15 +++++
>  arch/arm64/kernel/entry-ftrace.S |   43 +++++++++++++++
>  arch/arm64/kernel/ftrace.c       |  113 ++++++++++++++++++++++++++++++++++++++
>  4 files changed, 172 insertions(+)
> 
> diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
> index 6b3fef6..6954959 100644
> --- a/arch/arm64/Kconfig
> +++ b/arch/arm64/Kconfig
> @@ -33,6 +33,7 @@ config ARM64
>  	select HAVE_DMA_API_DEBUG
>  	select HAVE_DMA_ATTRS
>  	select HAVE_DMA_CONTIGUOUS
> +	select HAVE_DYNAMIC_FTRACE
>  	select HAVE_EFFICIENT_UNALIGNED_ACCESS
>  	select HAVE_FTRACE_MCOUNT_RECORD
>  	select HAVE_FUNCTION_TRACER
> diff --git a/arch/arm64/include/asm/ftrace.h b/arch/arm64/include/asm/ftrace.h
> index 58ea595..ed5c448 100644
> --- a/arch/arm64/include/asm/ftrace.h
> +++ b/arch/arm64/include/asm/ftrace.h
> @@ -18,6 +18,21 @@
>  
>  #ifndef __ASSEMBLY__
>  extern void _mcount(unsigned long);
> +
> +struct dyn_arch_ftrace {
> +	/* No extra data needed for arm64 */
> +};
> +
> +extern unsigned long ftrace_graph_call;
> +
> +static inline unsigned long ftrace_call_adjust(unsigned long addr)
> +{
> +	/*
> +	 * addr is the address of the mcount call instruction.
> +	 * recordmcount does the necessary offset calculation.
> +	 */
> +	return addr;
> +}

You could just as easily implement this as a dummy macro, but I guess it
doesn't matter either way.

>  #endif /* __ASSEMBLY__ */
>  
>  #endif /* __ASM_FTRACE_H */
> diff --git a/arch/arm64/kernel/entry-ftrace.S b/arch/arm64/kernel/entry-ftrace.S
> index 0ac31c8..c0fbe10 100644
> --- a/arch/arm64/kernel/entry-ftrace.S
> +++ b/arch/arm64/kernel/entry-ftrace.S
> @@ -86,6 +86,7 @@
>  	add	\reg, \reg, #8
>  	.endm
>  
> +#ifndef CONFIG_DYNAMIC_FTRACE
>  /*
>   * void _mcount(unsigned long return_address)
>   * @return_address: return address to instrumented function
> @@ -134,6 +135,48 @@ skip_ftrace_call:
>  #endif /* CONFIG_FUNCTION_GRAPH_TRACER */
>  ENDPROC(_mcount)
>  
> +#else /* CONFIG_DYNAMIC_FTRACE */
> +/*
> + * _mcount() is used to build the kernel with -pg option, but all the branch
> + * instructions to _mcount() are replaced to NOP initially at kernel start up,
> + * and later on, NOP to branch to ftrace_caller() when enabled or branch to
> + * NOP when disabled per-function base.
> + */
> +ENTRY(_mcount)
> +	ret
> +ENDPROC(_mcount)

Judging by your comment then, this should never be called. Is that right? If
so, we could add a BUG-equivalent so we know if we missed an mcount during
patching.

> +/*
> + * void ftrace_caller(unsigned long return_address)
> + * @return_address: return address to instrumented function
> + *
> + * This function is a counterpart of _mcount() in 'static' ftrace, and
> + * makes calls to:
> + *     - tracer function to probe instrumented function's entry,
> + *     - ftrace_graph_caller to set up an exit hook
> + */
> +ENTRY(ftrace_caller)
> +	mcount_enter
> +
> +	mcount_get_pc0	x0		//     function's pc
> +	mcount_get_lr	x1		//     function's lr
> +
> +	.global ftrace_call
> +ftrace_call:				// tracer(pc, lr);
> +	nop				// This will be replaced with "bl xxx"
> +					// where xxx can be any kind of tracer.
> +
> +#ifdef CONFIG_FUNCTION_GRAPH_TRACER
> +	.global ftrace_graph_call
> +ftrace_graph_call:			// ftrace_graph_caller();
> +	nop				// If enabled, this will be replaced
> +					// "b ftrace_graph_caller"
> +#endif
> +
> +	mcount_exit
> +ENDPROC(ftrace_caller)
> +#endif /* CONFIG_DYNAMIC_FTRACE */
> +
>  ENTRY(ftrace_stub)
>  	ret
>  ENDPROC(ftrace_stub)
> diff --git a/arch/arm64/kernel/ftrace.c b/arch/arm64/kernel/ftrace.c
> index a559ab8..8c26476 100644
> --- a/arch/arm64/kernel/ftrace.c
> +++ b/arch/arm64/kernel/ftrace.c
> @@ -17,6 +17,89 @@
>  #include <asm/ftrace.h>
>  #include <asm/insn.h>
>  
> +#ifdef CONFIG_DYNAMIC_FTRACE
> +/*
> + * Replace a single instruction, which may be a branch or NOP.
> + * If @validate == true, a replaced instruction is checked against 'old'.
> + */
> +static int ftrace_modify_code(unsigned long pc, unsigned int old,
> +			      unsigned int new, bool validate)
> +{
> +	unsigned int replaced;

u32 is a bit clearer for instructions.

> +	/*
> +	 * Note:
> +	 * Due to modules and __init, code can disappear and change,
> +	 * we need to protect against faulting as well as code changing.
> +	 * We do this by aarch64_insn_*() which use the probe_kernel_*().
> +	 *
> +	 * No lock is held here because all the modifications are run
> +	 * through stop_machine().
> +	 */
> +	if (validate) {
> +		if (aarch64_insn_read((void *)pc, &replaced))
> +			return -EFAULT;
> +
> +		if (replaced != old)
> +			return -EINVAL;
> +	}
> +	if (aarch64_insn_patch_text_nosync((void *)pc, new))
> +		return -EPERM;

I think you're better off propagating the errors here, rather than
overriding them with EFAULT/EINVAL/EPERM.

> +
> +	return 0;
> +}
> +
> +/*
> + * Replace tracer function in ftrace_caller()
> + */
> +int ftrace_update_ftrace_func(ftrace_func_t func)
> +{
> +	unsigned long pc;
> +	unsigned int new;
> +
> +	pc = (unsigned long)&ftrace_call;
> +	new = aarch64_insn_gen_branch_imm(pc, (unsigned long)func, true);
> +
> +	return ftrace_modify_code(pc, 0, new, false);
> +}
> +
> +/*
> + * Turn on the call to ftrace_caller() in instrumented function
> + */
> +int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
> +{
> +	unsigned long pc = rec->ip;
> +	unsigned int old, new;
> +
> +	old = aarch64_insn_gen_nop();
> +	new = aarch64_insn_gen_branch_imm(pc, addr, true);
> +
> +	return ftrace_modify_code(pc, old, new, true);
> +}
> +
> +/*
> + * Turn off the call to ftrace_caller() in instrumented function
> + */
> +int ftrace_make_nop(struct module *mod,
> +		    struct dyn_ftrace *rec, unsigned long addr)
> +{
> +	unsigned long pc = rec->ip;
> +	unsigned int old, new;
> +
> +	old = aarch64_insn_gen_branch_imm(pc, addr, true);
> +	new = aarch64_insn_gen_nop();
> +
> +	return ftrace_modify_code(pc, old, new, true);
> +}
> +
> +int __init ftrace_dyn_arch_init(void *data)
> +{
> +	*(unsigned long *)data = 0;
> +
> +	return 0;
> +}
> +#endif /* CONFIG_DYNAMIC_FTRACE */
> +
>  #ifdef CONFIG_FUNCTION_GRAPH_TRACER
>  /*
>   * function_graph tracer expects ftrace_return_to_handler() to be called
> @@ -61,4 +144,34 @@ void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr,
>  		return;
>  	}
>  }
> +
> +#ifdef CONFIG_DYNAMIC_FTRACE
> +/*
> + * Turn on/off the call to ftrace_graph_caller() in ftrace_caller()
> + * depending on @enable.
> + */
> +static int ftrace_modify_graph_caller(bool enable)
> +{
> +	unsigned long pc = (unsigned long)&ftrace_graph_call;
> +	unsigned int branch, nop, old, new;
> +
> +	branch = aarch64_insn_gen_branch_imm(pc,
> +			(unsigned long)ftrace_graph_caller, false);
> +	nop = aarch64_insn_gen_nop();
> +	old = enable ? nop : branch;
> +	new = enable ? branch : nop;
> +
> +	return ftrace_modify_code(pc, old, new, true);

You could rewrite this as:

	if (enable)
		return ftrace_modify_code(pc, nop, branch, true);
	else
		return ftrace_modify_code(pc, branch, nop, true);

which I find easier to read.

Will

^ permalink raw reply	[flat|nested] 235+ messages in thread

* [PATCH v6 5/7] arm64: ftrace: Add dynamic ftrace support
@ 2014-03-13 18:10             ` Will Deacon
  0 siblings, 0 replies; 235+ messages in thread
From: Will Deacon @ 2014-03-13 18:10 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Mar 13, 2014 at 10:13:48AM +0000, AKASHI Takahiro wrote:
> This patch allows "dynamic ftrace" if CONFIG_DYNAMIC_FTRACE is enabled.
> Here we can turn on and off tracing dynamically per-function base.
> 
> On arm64, this is done by patching single branch instruction to _mcount()
> inserted by gcc -pg option. The branch is replaced to NOP initially at
> kernel start up, and later on, NOP to branch to ftrace_caller() when
> enabled or branch to NOP when disabled.
> Please note that ftrace_caller() is a counterpart of _mcount() in case of
> 'static' ftrace.
> 
> More details on architecture specific requirements are described in
> Documentation/trace/ftrace-design.txt.
> 
> Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
> ---
>  arch/arm64/Kconfig               |    1 +
>  arch/arm64/include/asm/ftrace.h  |   15 +++++
>  arch/arm64/kernel/entry-ftrace.S |   43 +++++++++++++++
>  arch/arm64/kernel/ftrace.c       |  113 ++++++++++++++++++++++++++++++++++++++
>  4 files changed, 172 insertions(+)
> 
> diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
> index 6b3fef6..6954959 100644
> --- a/arch/arm64/Kconfig
> +++ b/arch/arm64/Kconfig
> @@ -33,6 +33,7 @@ config ARM64
>  	select HAVE_DMA_API_DEBUG
>  	select HAVE_DMA_ATTRS
>  	select HAVE_DMA_CONTIGUOUS
> +	select HAVE_DYNAMIC_FTRACE
>  	select HAVE_EFFICIENT_UNALIGNED_ACCESS
>  	select HAVE_FTRACE_MCOUNT_RECORD
>  	select HAVE_FUNCTION_TRACER
> diff --git a/arch/arm64/include/asm/ftrace.h b/arch/arm64/include/asm/ftrace.h
> index 58ea595..ed5c448 100644
> --- a/arch/arm64/include/asm/ftrace.h
> +++ b/arch/arm64/include/asm/ftrace.h
> @@ -18,6 +18,21 @@
>  
>  #ifndef __ASSEMBLY__
>  extern void _mcount(unsigned long);
> +
> +struct dyn_arch_ftrace {
> +	/* No extra data needed for arm64 */
> +};
> +
> +extern unsigned long ftrace_graph_call;
> +
> +static inline unsigned long ftrace_call_adjust(unsigned long addr)
> +{
> +	/*
> +	 * addr is the address of the mcount call instruction.
> +	 * recordmcount does the necessary offset calculation.
> +	 */
> +	return addr;
> +}

You could just as easily implement this as a dummy macro, but I guess it
doesn't matter either way.

>  #endif /* __ASSEMBLY__ */
>  
>  #endif /* __ASM_FTRACE_H */
> diff --git a/arch/arm64/kernel/entry-ftrace.S b/arch/arm64/kernel/entry-ftrace.S
> index 0ac31c8..c0fbe10 100644
> --- a/arch/arm64/kernel/entry-ftrace.S
> +++ b/arch/arm64/kernel/entry-ftrace.S
> @@ -86,6 +86,7 @@
>  	add	\reg, \reg, #8
>  	.endm
>  
> +#ifndef CONFIG_DYNAMIC_FTRACE
>  /*
>   * void _mcount(unsigned long return_address)
>   * @return_address: return address to instrumented function
> @@ -134,6 +135,48 @@ skip_ftrace_call:
>  #endif /* CONFIG_FUNCTION_GRAPH_TRACER */
>  ENDPROC(_mcount)
>  
> +#else /* CONFIG_DYNAMIC_FTRACE */
> +/*
> + * _mcount() is used to build the kernel with -pg option, but all the branch
> + * instructions to _mcount() are replaced to NOP initially at kernel start up,
> + * and later on, NOP to branch to ftrace_caller() when enabled or branch to
> + * NOP when disabled per-function base.
> + */
> +ENTRY(_mcount)
> +	ret
> +ENDPROC(_mcount)

Judging by your comment then, this should never be called. Is that right? If
so, we could add a BUG-equivalent so we know if we missed an mcount during
patching.

> +/*
> + * void ftrace_caller(unsigned long return_address)
> + * @return_address: return address to instrumented function
> + *
> + * This function is a counterpart of _mcount() in 'static' ftrace, and
> + * makes calls to:
> + *     - tracer function to probe instrumented function's entry,
> + *     - ftrace_graph_caller to set up an exit hook
> + */
> +ENTRY(ftrace_caller)
> +	mcount_enter
> +
> +	mcount_get_pc0	x0		//     function's pc
> +	mcount_get_lr	x1		//     function's lr
> +
> +	.global ftrace_call
> +ftrace_call:				// tracer(pc, lr);
> +	nop				// This will be replaced with "bl xxx"
> +					// where xxx can be any kind of tracer.
> +
> +#ifdef CONFIG_FUNCTION_GRAPH_TRACER
> +	.global ftrace_graph_call
> +ftrace_graph_call:			// ftrace_graph_caller();
> +	nop				// If enabled, this will be replaced
> +					// "b ftrace_graph_caller"
> +#endif
> +
> +	mcount_exit
> +ENDPROC(ftrace_caller)
> +#endif /* CONFIG_DYNAMIC_FTRACE */
> +
>  ENTRY(ftrace_stub)
>  	ret
>  ENDPROC(ftrace_stub)
> diff --git a/arch/arm64/kernel/ftrace.c b/arch/arm64/kernel/ftrace.c
> index a559ab8..8c26476 100644
> --- a/arch/arm64/kernel/ftrace.c
> +++ b/arch/arm64/kernel/ftrace.c
> @@ -17,6 +17,89 @@
>  #include <asm/ftrace.h>
>  #include <asm/insn.h>
>  
> +#ifdef CONFIG_DYNAMIC_FTRACE
> +/*
> + * Replace a single instruction, which may be a branch or NOP.
> + * If @validate == true, a replaced instruction is checked against 'old'.
> + */
> +static int ftrace_modify_code(unsigned long pc, unsigned int old,
> +			      unsigned int new, bool validate)
> +{
> +	unsigned int replaced;

u32 is a bit clearer for instructions.

> +	/*
> +	 * Note:
> +	 * Due to modules and __init, code can disappear and change,
> +	 * we need to protect against faulting as well as code changing.
> +	 * We do this by aarch64_insn_*() which use the probe_kernel_*().
> +	 *
> +	 * No lock is held here because all the modifications are run
> +	 * through stop_machine().
> +	 */
> +	if (validate) {
> +		if (aarch64_insn_read((void *)pc, &replaced))
> +			return -EFAULT;
> +
> +		if (replaced != old)
> +			return -EINVAL;
> +	}
> +	if (aarch64_insn_patch_text_nosync((void *)pc, new))
> +		return -EPERM;

I think you're better off propagating the errors here, rather than
overriding them with EFAULT/EINVAL/EPERM.

> +
> +	return 0;
> +}
> +
> +/*
> + * Replace tracer function in ftrace_caller()
> + */
> +int ftrace_update_ftrace_func(ftrace_func_t func)
> +{
> +	unsigned long pc;
> +	unsigned int new;
> +
> +	pc = (unsigned long)&ftrace_call;
> +	new = aarch64_insn_gen_branch_imm(pc, (unsigned long)func, true);
> +
> +	return ftrace_modify_code(pc, 0, new, false);
> +}
> +
> +/*
> + * Turn on the call to ftrace_caller() in instrumented function
> + */
> +int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
> +{
> +	unsigned long pc = rec->ip;
> +	unsigned int old, new;
> +
> +	old = aarch64_insn_gen_nop();
> +	new = aarch64_insn_gen_branch_imm(pc, addr, true);
> +
> +	return ftrace_modify_code(pc, old, new, true);
> +}
> +
> +/*
> + * Turn off the call to ftrace_caller() in instrumented function
> + */
> +int ftrace_make_nop(struct module *mod,
> +		    struct dyn_ftrace *rec, unsigned long addr)
> +{
> +	unsigned long pc = rec->ip;
> +	unsigned int old, new;
> +
> +	old = aarch64_insn_gen_branch_imm(pc, addr, true);
> +	new = aarch64_insn_gen_nop();
> +
> +	return ftrace_modify_code(pc, old, new, true);
> +}
> +
> +int __init ftrace_dyn_arch_init(void *data)
> +{
> +	*(unsigned long *)data = 0;
> +
> +	return 0;
> +}
> +#endif /* CONFIG_DYNAMIC_FTRACE */
> +
>  #ifdef CONFIG_FUNCTION_GRAPH_TRACER
>  /*
>   * function_graph tracer expects ftrace_return_to_handler() to be called
> @@ -61,4 +144,34 @@ void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr,
>  		return;
>  	}
>  }
> +
> +#ifdef CONFIG_DYNAMIC_FTRACE
> +/*
> + * Turn on/off the call to ftrace_graph_caller() in ftrace_caller()
> + * depending on @enable.
> + */
> +static int ftrace_modify_graph_caller(bool enable)
> +{
> +	unsigned long pc = (unsigned long)&ftrace_graph_call;
> +	unsigned int branch, nop, old, new;
> +
> +	branch = aarch64_insn_gen_branch_imm(pc,
> +			(unsigned long)ftrace_graph_caller, false);
> +	nop = aarch64_insn_gen_nop();
> +	old = enable ? nop : branch;
> +	new = enable ? branch : nop;
> +
> +	return ftrace_modify_code(pc, old, new, true);

You could rewrite this as:

	if (enable)
		return ftrace_modify_code(pc, nop, branch, true);
	else
		return ftrace_modify_code(pc, branch, nop, true);

which I find easier to read.

Will

^ permalink raw reply	[flat|nested] 235+ messages in thread

* Re: [PATCH v6 4/7] arm64: Add ftrace support
  2014-03-13 17:08             ` Will Deacon
@ 2014-03-13 18:27               ` Steven Rostedt
  -1 siblings, 0 replies; 235+ messages in thread
From: Steven Rostedt @ 2014-03-13 18:27 UTC (permalink / raw)
  To: Will Deacon
  Cc: AKASHI Takahiro, fweisbec, mingo, Catalin Marinas, tim.bird,
	gkulkarni, dsaxena, arndb, linux-arm-kernel, linaro-kernel,
	linux-kernel

On Thu, 2014-03-13 at 17:08 +0000, Will Deacon wrote:

> > +       /*
> > +        * Note:
> > +        * No protection against faulting at *parent, which may be seen
> > +        * on other archs. It's unlikely on AArch64.
> > +        */
> > +       old = *parent;
> > +       *parent = return_hooker;
> 
> return_hook? People might take it personally otherwise ;)

No, return_hooker is consistent with all the other archs. Hey, it's a
rugby position! Note, which I was when I played. ;-)

> 
> > +       trace.func = self_addr;
> 
> in kernel/ftrace/ftrace.c there's an smb_wmb() between setting up
> tracing_graph_pause and setting the ret_stack with a comment saying:
> 
>     /* Make sure the tasks see the -1 first: */
> 
> Why don't we have a corresponding read-barrier here?

The corresponding rmb is in kernel/trace/trace_function_graph
ftrace_push_return_trace().

-- Steve



^ permalink raw reply	[flat|nested] 235+ messages in thread

* [PATCH v6 4/7] arm64: Add ftrace support
@ 2014-03-13 18:27               ` Steven Rostedt
  0 siblings, 0 replies; 235+ messages in thread
From: Steven Rostedt @ 2014-03-13 18:27 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, 2014-03-13 at 17:08 +0000, Will Deacon wrote:

> > +       /*
> > +        * Note:
> > +        * No protection against faulting at *parent, which may be seen
> > +        * on other archs. It's unlikely on AArch64.
> > +        */
> > +       old = *parent;
> > +       *parent = return_hooker;
> 
> return_hook? People might take it personally otherwise ;)

No, return_hooker is consistent with all the other archs. Hey, it's a
rugby position! Note, which I was when I played. ;-)

> 
> > +       trace.func = self_addr;
> 
> in kernel/ftrace/ftrace.c there's an smb_wmb() between setting up
> tracing_graph_pause and setting the ret_stack with a comment saying:
> 
>     /* Make sure the tasks see the -1 first: */
> 
> Why don't we have a corresponding read-barrier here?

The corresponding rmb is in kernel/trace/trace_function_graph
ftrace_push_return_trace().

-- Steve

^ permalink raw reply	[flat|nested] 235+ messages in thread

* Re: [PATCH v6 5/7] arm64: ftrace: Add dynamic ftrace support
  2014-03-13 18:10             ` Will Deacon
@ 2014-03-13 18:33               ` Steven Rostedt
  -1 siblings, 0 replies; 235+ messages in thread
From: Steven Rostedt @ 2014-03-13 18:33 UTC (permalink / raw)
  To: Will Deacon
  Cc: AKASHI Takahiro, fweisbec, mingo, Catalin Marinas, tim.bird,
	gkulkarni, dsaxena, arndb, linux-arm-kernel, linaro-kernel,
	linux-kernel

On Thu, 2014-03-13 at 18:10 +0000, Will Deacon wrote:
>  
> > +#else /* CONFIG_DYNAMIC_FTRACE */
> > +/*
> > + * _mcount() is used to build the kernel with -pg option, but all the branch
> > + * instructions to _mcount() are replaced to NOP initially at kernel start up,
> > + * and later on, NOP to branch to ftrace_caller() when enabled or branch to
> > + * NOP when disabled per-function base.
> > + */
> > +ENTRY(_mcount)
> > +	ret
> > +ENDPROC(_mcount)
> 
> Judging by your comment then, this should never be called. Is that right? If
> so, we could add a BUG-equivalent so we know if we missed an mcount during
> patching.

Actually, it can be called before the change to nops are done in early
boot. This is done very early, but everything before ftrace_init() in
init/main.c can still call _mcount.


> > +	/*
> > +	 * Note:
> > +	 * Due to modules and __init, code can disappear and change,
> > +	 * we need to protect against faulting as well as code changing.
> > +	 * We do this by aarch64_insn_*() which use the probe_kernel_*().
> > +	 *
> > +	 * No lock is held here because all the modifications are run
> > +	 * through stop_machine().
> > +	 */
> > +	if (validate) {
> > +		if (aarch64_insn_read((void *)pc, &replaced))
> > +			return -EFAULT;
> > +
> > +		if (replaced != old)
> > +			return -EINVAL;
> > +	}
> > +	if (aarch64_insn_patch_text_nosync((void *)pc, new))
> > +		return -EPERM;
> 
> I think you're better off propagating the errors here, rather than
> overriding them with EFAULT/EINVAL/EPERM.

The ftrace generic code expects to see these specific errors. Look at
ftrace_bug() in kernel/trace/ftrace.c.

> 
> > +
> > +	return 0;
> > +}
> > +
> > +/*
> > + * Replace tracer function in ftrace_caller()
> > + */
> > +int ftrace_update_ftrace_func(ftrace_func_t func)
> > +{
> > +	unsigned long pc;
> > +	unsigned int new;
> > +
> > +	pc = (unsigned long)&ftrace_call;
> > +	new = aarch64_insn_gen_branch_imm(pc, (unsigned long)func, true);
> > +
> > +	return ftrace_modify_code(pc, 0, new, false);
> > +}
> > +
> > +/*
> > + * Turn on the call to ftrace_caller() in instrumented function
> > + */
> > +int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
> > +{
> > +	unsigned long pc = rec->ip;
> > +	unsigned int old, new;
> > +
> > +	old = aarch64_insn_gen_nop();
> > +	new = aarch64_insn_gen_branch_imm(pc, addr, true);
> > +
> > +	return ftrace_modify_code(pc, old, new, true);
> > +}
> > +
> > +/*
> > + * Turn off the call to ftrace_caller() in instrumented function
> > + */
> > +int ftrace_make_nop(struct module *mod,
> > +		    struct dyn_ftrace *rec, unsigned long addr)
> > +{
> > +	unsigned long pc = rec->ip;
> > +	unsigned int old, new;
> > +
> > +	old = aarch64_insn_gen_branch_imm(pc, addr, true);
> > +	new = aarch64_insn_gen_nop();
> > +
> > +	return ftrace_modify_code(pc, old, new, true);
> > +}
> > +
> > +int __init ftrace_dyn_arch_init(void *data)
> > +{
> > +	*(unsigned long *)data = 0;
> > +
> > +	return 0;
> > +}
> > +#endif /* CONFIG_DYNAMIC_FTRACE */
> > +
> >  #ifdef CONFIG_FUNCTION_GRAPH_TRACER
> >  /*
> >   * function_graph tracer expects ftrace_return_to_handler() to be called
> > @@ -61,4 +144,34 @@ void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr,
> >  		return;
> >  	}
> >  }
> > +
> > +#ifdef CONFIG_DYNAMIC_FTRACE
> > +/*
> > + * Turn on/off the call to ftrace_graph_caller() in ftrace_caller()
> > + * depending on @enable.
> > + */
> > +static int ftrace_modify_graph_caller(bool enable)
> > +{
> > +	unsigned long pc = (unsigned long)&ftrace_graph_call;
> > +	unsigned int branch, nop, old, new;
> > +
> > +	branch = aarch64_insn_gen_branch_imm(pc,
> > +			(unsigned long)ftrace_graph_caller, false);
> > +	nop = aarch64_insn_gen_nop();
> > +	old = enable ? nop : branch;
> > +	new = enable ? branch : nop;
> > +
> > +	return ftrace_modify_code(pc, old, new, true);
> 
> You could rewrite this as:
> 
> 	if (enable)
> 		return ftrace_modify_code(pc, nop, branch, true);
> 	else
> 		return ftrace_modify_code(pc, branch, nop, true);
> 
> which I find easier to read.

Heh, maybe that could be updated in other archs too. I'll have to think
about that one.

-- Steve



^ permalink raw reply	[flat|nested] 235+ messages in thread

* [PATCH v6 5/7] arm64: ftrace: Add dynamic ftrace support
@ 2014-03-13 18:33               ` Steven Rostedt
  0 siblings, 0 replies; 235+ messages in thread
From: Steven Rostedt @ 2014-03-13 18:33 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, 2014-03-13 at 18:10 +0000, Will Deacon wrote:
>  
> > +#else /* CONFIG_DYNAMIC_FTRACE */
> > +/*
> > + * _mcount() is used to build the kernel with -pg option, but all the branch
> > + * instructions to _mcount() are replaced to NOP initially at kernel start up,
> > + * and later on, NOP to branch to ftrace_caller() when enabled or branch to
> > + * NOP when disabled per-function base.
> > + */
> > +ENTRY(_mcount)
> > +	ret
> > +ENDPROC(_mcount)
> 
> Judging by your comment then, this should never be called. Is that right? If
> so, we could add a BUG-equivalent so we know if we missed an mcount during
> patching.

Actually, it can be called before the change to nops are done in early
boot. This is done very early, but everything before ftrace_init() in
init/main.c can still call _mcount.


> > +	/*
> > +	 * Note:
> > +	 * Due to modules and __init, code can disappear and change,
> > +	 * we need to protect against faulting as well as code changing.
> > +	 * We do this by aarch64_insn_*() which use the probe_kernel_*().
> > +	 *
> > +	 * No lock is held here because all the modifications are run
> > +	 * through stop_machine().
> > +	 */
> > +	if (validate) {
> > +		if (aarch64_insn_read((void *)pc, &replaced))
> > +			return -EFAULT;
> > +
> > +		if (replaced != old)
> > +			return -EINVAL;
> > +	}
> > +	if (aarch64_insn_patch_text_nosync((void *)pc, new))
> > +		return -EPERM;
> 
> I think you're better off propagating the errors here, rather than
> overriding them with EFAULT/EINVAL/EPERM.

The ftrace generic code expects to see these specific errors. Look at
ftrace_bug() in kernel/trace/ftrace.c.

> 
> > +
> > +	return 0;
> > +}
> > +
> > +/*
> > + * Replace tracer function in ftrace_caller()
> > + */
> > +int ftrace_update_ftrace_func(ftrace_func_t func)
> > +{
> > +	unsigned long pc;
> > +	unsigned int new;
> > +
> > +	pc = (unsigned long)&ftrace_call;
> > +	new = aarch64_insn_gen_branch_imm(pc, (unsigned long)func, true);
> > +
> > +	return ftrace_modify_code(pc, 0, new, false);
> > +}
> > +
> > +/*
> > + * Turn on the call to ftrace_caller() in instrumented function
> > + */
> > +int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
> > +{
> > +	unsigned long pc = rec->ip;
> > +	unsigned int old, new;
> > +
> > +	old = aarch64_insn_gen_nop();
> > +	new = aarch64_insn_gen_branch_imm(pc, addr, true);
> > +
> > +	return ftrace_modify_code(pc, old, new, true);
> > +}
> > +
> > +/*
> > + * Turn off the call to ftrace_caller() in instrumented function
> > + */
> > +int ftrace_make_nop(struct module *mod,
> > +		    struct dyn_ftrace *rec, unsigned long addr)
> > +{
> > +	unsigned long pc = rec->ip;
> > +	unsigned int old, new;
> > +
> > +	old = aarch64_insn_gen_branch_imm(pc, addr, true);
> > +	new = aarch64_insn_gen_nop();
> > +
> > +	return ftrace_modify_code(pc, old, new, true);
> > +}
> > +
> > +int __init ftrace_dyn_arch_init(void *data)
> > +{
> > +	*(unsigned long *)data = 0;
> > +
> > +	return 0;
> > +}
> > +#endif /* CONFIG_DYNAMIC_FTRACE */
> > +
> >  #ifdef CONFIG_FUNCTION_GRAPH_TRACER
> >  /*
> >   * function_graph tracer expects ftrace_return_to_handler() to be called
> > @@ -61,4 +144,34 @@ void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr,
> >  		return;
> >  	}
> >  }
> > +
> > +#ifdef CONFIG_DYNAMIC_FTRACE
> > +/*
> > + * Turn on/off the call to ftrace_graph_caller() in ftrace_caller()
> > + * depending on @enable.
> > + */
> > +static int ftrace_modify_graph_caller(bool enable)
> > +{
> > +	unsigned long pc = (unsigned long)&ftrace_graph_call;
> > +	unsigned int branch, nop, old, new;
> > +
> > +	branch = aarch64_insn_gen_branch_imm(pc,
> > +			(unsigned long)ftrace_graph_caller, false);
> > +	nop = aarch64_insn_gen_nop();
> > +	old = enable ? nop : branch;
> > +	new = enable ? branch : nop;
> > +
> > +	return ftrace_modify_code(pc, old, new, true);
> 
> You could rewrite this as:
> 
> 	if (enable)
> 		return ftrace_modify_code(pc, nop, branch, true);
> 	else
> 		return ftrace_modify_code(pc, branch, nop, true);
> 
> which I find easier to read.

Heh, maybe that could be updated in other archs too. I'll have to think
about that one.

-- Steve

^ permalink raw reply	[flat|nested] 235+ messages in thread

* Re: [PATCH v6 4/7] arm64: Add ftrace support
  2014-03-13 18:27               ` Steven Rostedt
@ 2014-03-13 18:37                 ` Will Deacon
  -1 siblings, 0 replies; 235+ messages in thread
From: Will Deacon @ 2014-03-13 18:37 UTC (permalink / raw)
  To: Steven Rostedt
  Cc: AKASHI Takahiro, fweisbec, mingo, Catalin Marinas, tim.bird,
	gkulkarni, dsaxena, arndb, linux-arm-kernel, linaro-kernel,
	linux-kernel

On Thu, Mar 13, 2014 at 06:27:39PM +0000, Steven Rostedt wrote:
> On Thu, 2014-03-13 at 17:08 +0000, Will Deacon wrote:
> 
> > > +       /*
> > > +        * Note:
> > > +        * No protection against faulting at *parent, which may be seen
> > > +        * on other archs. It's unlikely on AArch64.
> > > +        */
> > > +       old = *parent;
> > > +       *parent = return_hooker;
> > 
> > return_hook? People might take it personally otherwise ;)
> 
> No, return_hooker is consistent with all the other archs. Hey, it's a
> rugby position! Note, which I was when I played. ;-)

Hehe, in which case your children will be able to execute that line of
ftrace!

> > 
> > > +       trace.func = self_addr;
> > 
> > in kernel/ftrace/ftrace.c there's an smb_wmb() between setting up
> > tracing_graph_pause and setting the ret_stack with a comment saying:
> > 
> >     /* Make sure the tasks see the -1 first: */
> > 
> > Why don't we have a corresponding read-barrier here?
> 
> The corresponding rmb is in kernel/trace/trace_function_graph
> ftrace_push_return_trace().

Okey doke then, I guess we don't really care about tracing_graph_pause
getting out-of-sync with curr_ret_stack.

Will

^ permalink raw reply	[flat|nested] 235+ messages in thread

* [PATCH v6 4/7] arm64: Add ftrace support
@ 2014-03-13 18:37                 ` Will Deacon
  0 siblings, 0 replies; 235+ messages in thread
From: Will Deacon @ 2014-03-13 18:37 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Mar 13, 2014 at 06:27:39PM +0000, Steven Rostedt wrote:
> On Thu, 2014-03-13 at 17:08 +0000, Will Deacon wrote:
> 
> > > +       /*
> > > +        * Note:
> > > +        * No protection against faulting at *parent, which may be seen
> > > +        * on other archs. It's unlikely on AArch64.
> > > +        */
> > > +       old = *parent;
> > > +       *parent = return_hooker;
> > 
> > return_hook? People might take it personally otherwise ;)
> 
> No, return_hooker is consistent with all the other archs. Hey, it's a
> rugby position! Note, which I was when I played. ;-)

Hehe, in which case your children will be able to execute that line of
ftrace!

> > 
> > > +       trace.func = self_addr;
> > 
> > in kernel/ftrace/ftrace.c there's an smb_wmb() between setting up
> > tracing_graph_pause and setting the ret_stack with a comment saying:
> > 
> >     /* Make sure the tasks see the -1 first: */
> > 
> > Why don't we have a corresponding read-barrier here?
> 
> The corresponding rmb is in kernel/trace/trace_function_graph
> ftrace_push_return_trace().

Okey doke then, I guess we don't really care about tracing_graph_pause
getting out-of-sync with curr_ret_stack.

Will

^ permalink raw reply	[flat|nested] 235+ messages in thread

* Re: [PATCH v6 4/7] arm64: Add ftrace support
  2014-03-13 18:37                 ` Will Deacon
@ 2014-03-13 18:49                   ` Steven Rostedt
  -1 siblings, 0 replies; 235+ messages in thread
From: Steven Rostedt @ 2014-03-13 18:49 UTC (permalink / raw)
  To: Will Deacon
  Cc: AKASHI Takahiro, fweisbec, mingo, Catalin Marinas, tim.bird,
	gkulkarni, dsaxena, arndb, linux-arm-kernel, linaro-kernel,
	linux-kernel

On Thu, 2014-03-13 at 18:37 +0000, Will Deacon wrote:
>  
> > No, return_hooker is consistent with all the other archs. Hey, it's a
> > rugby position! Note, which I was when I played. ;-)
> 
> Hehe, in which case your children will be able to execute that line of
> ftrace!
> 

My kids already know I was :-)

> > > 
> > > > +       trace.func = self_addr;
> > > 
> > > in kernel/ftrace/ftrace.c there's an smb_wmb() between setting up
> > > tracing_graph_pause and setting the ret_stack with a comment saying:
> > > 
> > >     /* Make sure the tasks see the -1 first: */
> > > 
> > > Why don't we have a corresponding read-barrier here?
> > 
> > The corresponding rmb is in kernel/trace/trace_function_graph
> > ftrace_push_return_trace().
> 
> Okey doke then, I guess we don't really care about tracing_graph_pause
> getting out-of-sync with curr_ret_stack.

Yep, the tracing_graph_pause is more to prevent crazy stuff happening
when an interrupt comes in. So it is just local cpu context, and doesn't
have issues with other CPUS. If it takes a bit for the task to see it go
to zero, the worse thing is that you might miss a few tracing functions
until that gets synced. Which will probably happen by the time tracing
is fully activated anyway.

-- Steve



^ permalink raw reply	[flat|nested] 235+ messages in thread

* [PATCH v6 4/7] arm64: Add ftrace support
@ 2014-03-13 18:49                   ` Steven Rostedt
  0 siblings, 0 replies; 235+ messages in thread
From: Steven Rostedt @ 2014-03-13 18:49 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, 2014-03-13 at 18:37 +0000, Will Deacon wrote:
>  
> > No, return_hooker is consistent with all the other archs. Hey, it's a
> > rugby position! Note, which I was when I played. ;-)
> 
> Hehe, in which case your children will be able to execute that line of
> ftrace!
> 

My kids already know I was :-)

> > > 
> > > > +       trace.func = self_addr;
> > > 
> > > in kernel/ftrace/ftrace.c there's an smb_wmb() between setting up
> > > tracing_graph_pause and setting the ret_stack with a comment saying:
> > > 
> > >     /* Make sure the tasks see the -1 first: */
> > > 
> > > Why don't we have a corresponding read-barrier here?
> > 
> > The corresponding rmb is in kernel/trace/trace_function_graph
> > ftrace_push_return_trace().
> 
> Okey doke then, I guess we don't really care about tracing_graph_pause
> getting out-of-sync with curr_ret_stack.

Yep, the tracing_graph_pause is more to prevent crazy stuff happening
when an interrupt comes in. So it is just local cpu context, and doesn't
have issues with other CPUS. If it takes a bit for the task to see it go
to zero, the worse thing is that you might miss a few tracing functions
until that gets synced. Which will probably happen by the time tracing
is fully activated anyway.

-- Steve

^ permalink raw reply	[flat|nested] 235+ messages in thread

* Re: [PATCH v6 6/7] arm64: ftrace: Add CALLER_ADDRx macros
  2014-03-13 15:54             ` Will Deacon
@ 2014-03-14  3:00               ` AKASHI Takahiro
  -1 siblings, 0 replies; 235+ messages in thread
From: AKASHI Takahiro @ 2014-03-14  3:00 UTC (permalink / raw)
  To: Will Deacon
  Cc: rostedt, fweisbec, mingo, Catalin Marinas, tim.bird, gkulkarni,
	dsaxena, arndb, linux-arm-kernel, linaro-kernel, linux-kernel

On 03/14/2014 12:54 AM, Will Deacon wrote:
> On Thu, Mar 13, 2014 at 10:13:49AM +0000, AKASHI Takahiro wrote:
>> CALLER_ADDRx returns caller's address at specified level in call stacks.
>> They are used for several tracers like irqsoff and preemptoff.
>> Strange to say, however, they are refered even without FTRACE.
>>
>> Please note that this implementation assumes that we have frame pointers.
>> (which means kernel should be compiled with -fno-omit-frame-pointer.)
>
> How do you ensure that -fno-omit-frame-pointer is passed?

arm64 selects ARCH_WANT_FRAME_POINTERS, then FRAME_POINTER is on (lib/Kconfig.debug)
and so -fno-omit-frame-pointer is appended (${TOP}/Makefile).
(stacktrace.c also assumes FRAME_POINTER.)

Do you think I should remove the comment above?

>> Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
>> ---
>>   arch/arm64/include/asm/ftrace.h    |   13 ++++++++-
>>   arch/arm64/kernel/Makefile         |    3 +-
>>   arch/arm64/kernel/return_address.c |   55 ++++++++++++++++++++++++++++++++++++
>>   3 files changed, 69 insertions(+), 2 deletions(-)
>>   create mode 100644 arch/arm64/kernel/return_address.c
>>
>> diff --git a/arch/arm64/include/asm/ftrace.h b/arch/arm64/include/asm/ftrace.h
>> index ed5c448..c44c4b1 100644
>> --- a/arch/arm64/include/asm/ftrace.h
>> +++ b/arch/arm64/include/asm/ftrace.h
>> @@ -18,6 +18,7 @@
>>
>>   #ifndef __ASSEMBLY__
>>   extern void _mcount(unsigned long);
>> +extern void *return_address(unsigned int);
>>
>>   struct dyn_arch_ftrace {
>>   	/* No extra data needed for arm64 */
>> @@ -33,6 +34,16 @@ static inline unsigned long ftrace_call_adjust(unsigned long addr)
>>   	 */
>>   	return addr;
>>   }
>> -#endif /* __ASSEMBLY__ */
>> +
>> +#define HAVE_ARCH_CALLER_ADDR
>> +
>> +#define CALLER_ADDR0 ((unsigned long)__builtin_return_address(0))
>> +#define CALLER_ADDR1 ((unsigned long)return_address(1))
>> +#define CALLER_ADDR2 ((unsigned long)return_address(2))
>> +#define CALLER_ADDR3 ((unsigned long)return_address(3))
>> +#define CALLER_ADDR4 ((unsigned long)return_address(4))
>> +#define CALLER_ADDR5 ((unsigned long)return_address(5))
>> +#define CALLER_ADDR6 ((unsigned long)return_address(6))
>
> Could we change the core definitions of these macros (in linux/ftrace.h) to
> use return_address, then provide an overridable version of return_address
> that defaults to __builtin_return_address, instead of copy-pasting this
> sequence?

I think I understand what you mean, and will try to post a separate RFC,
but I also want to hold off this change on this patch since such a change
may raise a small controversy from other archs' maintainers.

>> diff --git a/arch/arm64/kernel/return_address.c b/arch/arm64/kernel/return_address.c
>> new file mode 100644
>> index 0000000..89102a6
>> --- /dev/null
>> +++ b/arch/arm64/kernel/return_address.c
>> @@ -0,0 +1,55 @@
>> +/*
>> + * arch/arm64/kernel/return_address.c
>> + *
>> + * Copyright (C) 2013 Linaro Limited
>> + * Author: AKASHI Takahiro <takahiro.akashi@linaro.org>
>> + *
>> + * 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 <linux/export.h>
>> +#include <linux/ftrace.h>
>> +
>> +#include <asm/stacktrace.h>
>> +
>> +struct return_address_data {
>> +	unsigned int level;
>> +	void *addr;
>> +};
>> +
>> +static int save_return_addr(struct stackframe *frame, void *d)
>> +{
>> +	struct return_address_data *data = d;
>> +
>> +	if (!data->level) {
>> +		data->addr = (void *)frame->pc;
>> +		return 1;
>> +	} else {
>> +		--data->level;
>> +		return 0;
>> +	}
>> +}
>> +
>> +void *return_address(unsigned int level)
>> +{
>> +	struct return_address_data data;
>> +	struct stackframe frame;
>> +	register unsigned long current_sp asm ("sp");
>> +
>> +	data.level = level + 2;
>> +	data.addr = NULL;
>> +
>> +	frame.fp = (unsigned long)__builtin_frame_address(0);
>> +	frame.sp = current_sp;
>> +	frame.pc = (unsigned long)return_address; /* dummy */
>> +
>> +	walk_stackframe(&frame, save_return_addr, &data);
>> +
>> +	if (!data.level)
>> +		return data.addr;
>> +	else
>> +		return NULL;
>> +}
>> +EXPORT_SYMBOL_GPL(return_address);
>
> This whole file is basically copied from arch/arm/, but it's not too much
> code. Ideally the toolchain would have made use of the frame pointer, but it
> looks like it doesn't bother.

I confirmed that __builtin_return_address([123456]) doesn't work
even with -fno-omit-frame-pointer.
Keep this as it is.

-Takahiro AKASHI

> Will
>

^ permalink raw reply	[flat|nested] 235+ messages in thread

* [PATCH v6 6/7] arm64: ftrace: Add CALLER_ADDRx macros
@ 2014-03-14  3:00               ` AKASHI Takahiro
  0 siblings, 0 replies; 235+ messages in thread
From: AKASHI Takahiro @ 2014-03-14  3:00 UTC (permalink / raw)
  To: linux-arm-kernel

On 03/14/2014 12:54 AM, Will Deacon wrote:
> On Thu, Mar 13, 2014 at 10:13:49AM +0000, AKASHI Takahiro wrote:
>> CALLER_ADDRx returns caller's address at specified level in call stacks.
>> They are used for several tracers like irqsoff and preemptoff.
>> Strange to say, however, they are refered even without FTRACE.
>>
>> Please note that this implementation assumes that we have frame pointers.
>> (which means kernel should be compiled with -fno-omit-frame-pointer.)
>
> How do you ensure that -fno-omit-frame-pointer is passed?

arm64 selects ARCH_WANT_FRAME_POINTERS, then FRAME_POINTER is on (lib/Kconfig.debug)
and so -fno-omit-frame-pointer is appended (${TOP}/Makefile).
(stacktrace.c also assumes FRAME_POINTER.)

Do you think I should remove the comment above?

>> Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
>> ---
>>   arch/arm64/include/asm/ftrace.h    |   13 ++++++++-
>>   arch/arm64/kernel/Makefile         |    3 +-
>>   arch/arm64/kernel/return_address.c |   55 ++++++++++++++++++++++++++++++++++++
>>   3 files changed, 69 insertions(+), 2 deletions(-)
>>   create mode 100644 arch/arm64/kernel/return_address.c
>>
>> diff --git a/arch/arm64/include/asm/ftrace.h b/arch/arm64/include/asm/ftrace.h
>> index ed5c448..c44c4b1 100644
>> --- a/arch/arm64/include/asm/ftrace.h
>> +++ b/arch/arm64/include/asm/ftrace.h
>> @@ -18,6 +18,7 @@
>>
>>   #ifndef __ASSEMBLY__
>>   extern void _mcount(unsigned long);
>> +extern void *return_address(unsigned int);
>>
>>   struct dyn_arch_ftrace {
>>   	/* No extra data needed for arm64 */
>> @@ -33,6 +34,16 @@ static inline unsigned long ftrace_call_adjust(unsigned long addr)
>>   	 */
>>   	return addr;
>>   }
>> -#endif /* __ASSEMBLY__ */
>> +
>> +#define HAVE_ARCH_CALLER_ADDR
>> +
>> +#define CALLER_ADDR0 ((unsigned long)__builtin_return_address(0))
>> +#define CALLER_ADDR1 ((unsigned long)return_address(1))
>> +#define CALLER_ADDR2 ((unsigned long)return_address(2))
>> +#define CALLER_ADDR3 ((unsigned long)return_address(3))
>> +#define CALLER_ADDR4 ((unsigned long)return_address(4))
>> +#define CALLER_ADDR5 ((unsigned long)return_address(5))
>> +#define CALLER_ADDR6 ((unsigned long)return_address(6))
>
> Could we change the core definitions of these macros (in linux/ftrace.h) to
> use return_address, then provide an overridable version of return_address
> that defaults to __builtin_return_address, instead of copy-pasting this
> sequence?

I think I understand what you mean, and will try to post a separate RFC,
but I also want to hold off this change on this patch since such a change
may raise a small controversy from other archs' maintainers.

>> diff --git a/arch/arm64/kernel/return_address.c b/arch/arm64/kernel/return_address.c
>> new file mode 100644
>> index 0000000..89102a6
>> --- /dev/null
>> +++ b/arch/arm64/kernel/return_address.c
>> @@ -0,0 +1,55 @@
>> +/*
>> + * arch/arm64/kernel/return_address.c
>> + *
>> + * Copyright (C) 2013 Linaro Limited
>> + * Author: AKASHI Takahiro <takahiro.akashi@linaro.org>
>> + *
>> + * 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 <linux/export.h>
>> +#include <linux/ftrace.h>
>> +
>> +#include <asm/stacktrace.h>
>> +
>> +struct return_address_data {
>> +	unsigned int level;
>> +	void *addr;
>> +};
>> +
>> +static int save_return_addr(struct stackframe *frame, void *d)
>> +{
>> +	struct return_address_data *data = d;
>> +
>> +	if (!data->level) {
>> +		data->addr = (void *)frame->pc;
>> +		return 1;
>> +	} else {
>> +		--data->level;
>> +		return 0;
>> +	}
>> +}
>> +
>> +void *return_address(unsigned int level)
>> +{
>> +	struct return_address_data data;
>> +	struct stackframe frame;
>> +	register unsigned long current_sp asm ("sp");
>> +
>> +	data.level = level + 2;
>> +	data.addr = NULL;
>> +
>> +	frame.fp = (unsigned long)__builtin_frame_address(0);
>> +	frame.sp = current_sp;
>> +	frame.pc = (unsigned long)return_address; /* dummy */
>> +
>> +	walk_stackframe(&frame, save_return_addr, &data);
>> +
>> +	if (!data.level)
>> +		return data.addr;
>> +	else
>> +		return NULL;
>> +}
>> +EXPORT_SYMBOL_GPL(return_address);
>
> This whole file is basically copied from arch/arm/, but it's not too much
> code. Ideally the toolchain would have made use of the frame pointer, but it
> looks like it doesn't bother.

I confirmed that __builtin_return_address([123456]) doesn't work
even with -fno-omit-frame-pointer.
Keep this as it is.

-Takahiro AKASHI

> Will
>

^ permalink raw reply	[flat|nested] 235+ messages in thread

* Re: [PATCH v6 7/7] arm64: ftrace: Add system call tracepoint
  2014-03-13 16:25             ` Will Deacon
@ 2014-03-14  3:50               ` AKASHI Takahiro
  -1 siblings, 0 replies; 235+ messages in thread
From: AKASHI Takahiro @ 2014-03-14  3:50 UTC (permalink / raw)
  To: Will Deacon
  Cc: rostedt, fweisbec, mingo, Catalin Marinas, tim.bird, gkulkarni,
	dsaxena, arndb, linux-arm-kernel, linaro-kernel, linux-kernel

On 03/14/2014 01:25 AM, Will Deacon wrote:
> On Thu, Mar 13, 2014 at 10:13:50AM +0000, AKASHI Takahiro wrote:
>> This patch allows system call entry or exit to be traced as ftrace events,
>> ie. sys_enter_*/sys_exit_*, if CONFIG_FTRACE_SYSCALLS is enabled.
>> Those events appear and can be controlled under
>>      ${sysfs}/tracing/events/syscalls/
>>
>> Please note that we can't trace compat system calls here because
>> AArch32 mode does not share the same syscall table with AArch64.
>> Just define ARCH_TRACE_IGNORE_COMPAT_SYSCALLS in order to avoid unexpected
>> results (bogus syscalls reported or even hang-up).
>>
>> Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
>> ---
>>   arch/arm64/Kconfig               |    1 +
>>   arch/arm64/include/asm/ftrace.h  |   20 ++++++++++++++++
>>   arch/arm64/include/asm/syscall.h |    1 +
>>   arch/arm64/include/asm/unistd.h  |    2 ++
>>   arch/arm64/kernel/ptrace.c       |   48 ++++++++++++++++++++++----------------
>>   5 files changed, 52 insertions(+), 20 deletions(-)
>>
>> diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
>> index 6954959..b1dcdb4 100644
>> --- a/arch/arm64/Kconfig
>> +++ b/arch/arm64/Kconfig
>> @@ -43,6 +43,7 @@ config ARM64
>>   	select HAVE_MEMBLOCK
>>   	select HAVE_PATA_PLATFORM
>>   	select HAVE_PERF_EVENTS
>> +	select HAVE_SYSCALL_TRACEPOINTS
>>   	select IRQ_DOMAIN
>>   	select MODULES_USE_ELF_RELA
>>   	select NO_BOOTMEM
>> diff --git a/arch/arm64/include/asm/ftrace.h b/arch/arm64/include/asm/ftrace.h
>> index c44c4b1..4ef06f1 100644
>> --- a/arch/arm64/include/asm/ftrace.h
>> +++ b/arch/arm64/include/asm/ftrace.h
>> @@ -44,6 +44,26 @@ static inline unsigned long ftrace_call_adjust(unsigned long addr)
>>   #define CALLER_ADDR4 ((unsigned long)return_address(4))
>>   #define CALLER_ADDR5 ((unsigned long)return_address(5))
>>   #define CALLER_ADDR6 ((unsigned long)return_address(6))
>> +
>> +#include <asm/compat.h>
>> +
>> +/*
>> + * Because AArch32 mode does not share the same syscall table with AArch64,
>> + * tracing compat syscalls may result in reporting bogus syscalls or even
>> + * hang-up, so just do not trace them.
>> + * See kernel/trace/trace_syscalls.c
>> + *
>> + * x86 code says:
>> + * If the user realy wants these, then they should use the
>> + * raw syscall tracepoints with filtering.
>
> Fair enough.
>
>> + */
>> +#define ARCH_TRACE_IGNORE_COMPAT_SYSCALLS 1
>
> You don't need the '1' here.

OK.

>> +static inline bool arch_trace_is_compat_syscall(struct pt_regs *regs)
>> +{
>> +        if (is_compat_task())
>> +                return true;
>> +        return false;
>> +}
>
> return is_compat_task();

Fix it.

>>   #endif /* ifndef __ASSEMBLY__ */
>>
>>   #endif /* __ASM_FTRACE_H */
>> diff --git a/arch/arm64/include/asm/syscall.h b/arch/arm64/include/asm/syscall.h
>> index 70ba9d4..383771e 100644
>> --- a/arch/arm64/include/asm/syscall.h
>> +++ b/arch/arm64/include/asm/syscall.h
>> @@ -18,6 +18,7 @@
>>
>>   #include <linux/err.h>
>>
>> +extern const void *sys_call_table[];
>>
>>   static inline int syscall_get_nr(struct task_struct *task,
>>   				 struct pt_regs *regs)
>> diff --git a/arch/arm64/include/asm/unistd.h b/arch/arm64/include/asm/unistd.h
>> index 82ce217..c335479 100644
>> --- a/arch/arm64/include/asm/unistd.h
>> +++ b/arch/arm64/include/asm/unistd.h
>> @@ -28,3 +28,5 @@
>>   #endif
>>   #define __ARCH_WANT_SYS_CLONE
>>   #include <uapi/asm/unistd.h>
>> +
>> +#define NR_syscalls (__NR_syscalls)
>> diff --git a/arch/arm64/kernel/ptrace.c b/arch/arm64/kernel/ptrace.c
>> index 9993a8f..9c52b3e 100644
>> --- a/arch/arm64/kernel/ptrace.c
>> +++ b/arch/arm64/kernel/ptrace.c
>> @@ -41,6 +41,9 @@
>>   #include <asm/traps.h>
>>   #include <asm/system_misc.h>
>>
>> +#define CREATE_TRACE_POINTS
>> +#include <trace/events/syscalls.h>
>> +
>>   /*
>>    * TODO: does not yet catch signals sent when the child dies.
>>    * in exit.c or in signal.c.
>> @@ -1062,29 +1065,31 @@ asmlinkage int syscall_trace_enter(struct pt_regs *regs)
>>   {
>>   	unsigned long saved_reg;
>>
>> -	if (!test_thread_flag(TIF_SYSCALL_TRACE))
>> -		return regs->syscallno;
>> +	if (test_thread_flag(TIF_SYSCALL_TRACE)) {
>> +		/*
>> +		 * A scrach register (ip(r12) on AArch32, x7 on AArch64) is
>> +		 * used to denote syscall entry/exit:
>> +		 *   0 -> entry
>> +		 */
>> +		if (is_compat_task()) {
>
> if (arch_trace_is_compat_syscall())

I don't mind either way, but this part of code comes from the original
syscall_trace() (ie. ptrace stuff), and has nothing to do with ftrace events.
(You know, arch_trace_is_compat_syscall() is currently defined in asm/ftrace.h.)
So I'd like to keep it unchanged unless you really want.

> With those changes:
>
>    Acked-by: Will Deacon <will.deacon@arm.com>

Thank you,
-Takahiro AKASHI

> Will
>

^ permalink raw reply	[flat|nested] 235+ messages in thread

* [PATCH v6 7/7] arm64: ftrace: Add system call tracepoint
@ 2014-03-14  3:50               ` AKASHI Takahiro
  0 siblings, 0 replies; 235+ messages in thread
From: AKASHI Takahiro @ 2014-03-14  3:50 UTC (permalink / raw)
  To: linux-arm-kernel

On 03/14/2014 01:25 AM, Will Deacon wrote:
> On Thu, Mar 13, 2014 at 10:13:50AM +0000, AKASHI Takahiro wrote:
>> This patch allows system call entry or exit to be traced as ftrace events,
>> ie. sys_enter_*/sys_exit_*, if CONFIG_FTRACE_SYSCALLS is enabled.
>> Those events appear and can be controlled under
>>      ${sysfs}/tracing/events/syscalls/
>>
>> Please note that we can't trace compat system calls here because
>> AArch32 mode does not share the same syscall table with AArch64.
>> Just define ARCH_TRACE_IGNORE_COMPAT_SYSCALLS in order to avoid unexpected
>> results (bogus syscalls reported or even hang-up).
>>
>> Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
>> ---
>>   arch/arm64/Kconfig               |    1 +
>>   arch/arm64/include/asm/ftrace.h  |   20 ++++++++++++++++
>>   arch/arm64/include/asm/syscall.h |    1 +
>>   arch/arm64/include/asm/unistd.h  |    2 ++
>>   arch/arm64/kernel/ptrace.c       |   48 ++++++++++++++++++++++----------------
>>   5 files changed, 52 insertions(+), 20 deletions(-)
>>
>> diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
>> index 6954959..b1dcdb4 100644
>> --- a/arch/arm64/Kconfig
>> +++ b/arch/arm64/Kconfig
>> @@ -43,6 +43,7 @@ config ARM64
>>   	select HAVE_MEMBLOCK
>>   	select HAVE_PATA_PLATFORM
>>   	select HAVE_PERF_EVENTS
>> +	select HAVE_SYSCALL_TRACEPOINTS
>>   	select IRQ_DOMAIN
>>   	select MODULES_USE_ELF_RELA
>>   	select NO_BOOTMEM
>> diff --git a/arch/arm64/include/asm/ftrace.h b/arch/arm64/include/asm/ftrace.h
>> index c44c4b1..4ef06f1 100644
>> --- a/arch/arm64/include/asm/ftrace.h
>> +++ b/arch/arm64/include/asm/ftrace.h
>> @@ -44,6 +44,26 @@ static inline unsigned long ftrace_call_adjust(unsigned long addr)
>>   #define CALLER_ADDR4 ((unsigned long)return_address(4))
>>   #define CALLER_ADDR5 ((unsigned long)return_address(5))
>>   #define CALLER_ADDR6 ((unsigned long)return_address(6))
>> +
>> +#include <asm/compat.h>
>> +
>> +/*
>> + * Because AArch32 mode does not share the same syscall table with AArch64,
>> + * tracing compat syscalls may result in reporting bogus syscalls or even
>> + * hang-up, so just do not trace them.
>> + * See kernel/trace/trace_syscalls.c
>> + *
>> + * x86 code says:
>> + * If the user realy wants these, then they should use the
>> + * raw syscall tracepoints with filtering.
>
> Fair enough.
>
>> + */
>> +#define ARCH_TRACE_IGNORE_COMPAT_SYSCALLS 1
>
> You don't need the '1' here.

OK.

>> +static inline bool arch_trace_is_compat_syscall(struct pt_regs *regs)
>> +{
>> +        if (is_compat_task())
>> +                return true;
>> +        return false;
>> +}
>
> return is_compat_task();

Fix it.

>>   #endif /* ifndef __ASSEMBLY__ */
>>
>>   #endif /* __ASM_FTRACE_H */
>> diff --git a/arch/arm64/include/asm/syscall.h b/arch/arm64/include/asm/syscall.h
>> index 70ba9d4..383771e 100644
>> --- a/arch/arm64/include/asm/syscall.h
>> +++ b/arch/arm64/include/asm/syscall.h
>> @@ -18,6 +18,7 @@
>>
>>   #include <linux/err.h>
>>
>> +extern const void *sys_call_table[];
>>
>>   static inline int syscall_get_nr(struct task_struct *task,
>>   				 struct pt_regs *regs)
>> diff --git a/arch/arm64/include/asm/unistd.h b/arch/arm64/include/asm/unistd.h
>> index 82ce217..c335479 100644
>> --- a/arch/arm64/include/asm/unistd.h
>> +++ b/arch/arm64/include/asm/unistd.h
>> @@ -28,3 +28,5 @@
>>   #endif
>>   #define __ARCH_WANT_SYS_CLONE
>>   #include <uapi/asm/unistd.h>
>> +
>> +#define NR_syscalls (__NR_syscalls)
>> diff --git a/arch/arm64/kernel/ptrace.c b/arch/arm64/kernel/ptrace.c
>> index 9993a8f..9c52b3e 100644
>> --- a/arch/arm64/kernel/ptrace.c
>> +++ b/arch/arm64/kernel/ptrace.c
>> @@ -41,6 +41,9 @@
>>   #include <asm/traps.h>
>>   #include <asm/system_misc.h>
>>
>> +#define CREATE_TRACE_POINTS
>> +#include <trace/events/syscalls.h>
>> +
>>   /*
>>    * TODO: does not yet catch signals sent when the child dies.
>>    * in exit.c or in signal.c.
>> @@ -1062,29 +1065,31 @@ asmlinkage int syscall_trace_enter(struct pt_regs *regs)
>>   {
>>   	unsigned long saved_reg;
>>
>> -	if (!test_thread_flag(TIF_SYSCALL_TRACE))
>> -		return regs->syscallno;
>> +	if (test_thread_flag(TIF_SYSCALL_TRACE)) {
>> +		/*
>> +		 * A scrach register (ip(r12) on AArch32, x7 on AArch64) is
>> +		 * used to denote syscall entry/exit:
>> +		 *   0 -> entry
>> +		 */
>> +		if (is_compat_task()) {
>
> if (arch_trace_is_compat_syscall())

I don't mind either way, but this part of code comes from the original
syscall_trace() (ie. ptrace stuff), and has nothing to do with ftrace events.
(You know, arch_trace_is_compat_syscall() is currently defined in asm/ftrace.h.)
So I'd like to keep it unchanged unless you really want.

> With those changes:
>
>    Acked-by: Will Deacon <will.deacon@arm.com>

Thank you,
-Takahiro AKASHI

> Will
>

^ permalink raw reply	[flat|nested] 235+ messages in thread

* Re: [PATCH v6 4/7] arm64: Add ftrace support
  2014-03-13 17:08             ` Will Deacon
@ 2014-03-14  4:45               ` AKASHI Takahiro
  -1 siblings, 0 replies; 235+ messages in thread
From: AKASHI Takahiro @ 2014-03-14  4:45 UTC (permalink / raw)
  To: Will Deacon
  Cc: rostedt, fweisbec, mingo, Catalin Marinas, tim.bird, gkulkarni,
	dsaxena, arndb, linux-arm-kernel, linaro-kernel, linux-kernel

On 03/14/2014 02:08 AM, Will Deacon wrote:
> On Thu, Mar 13, 2014 at 10:13:47AM +0000, AKASHI Takahiro wrote:
>> This patch implements arm64 specific part to support function tracers,
>> such as function (CONFIG_FUNCTION_TRACER), function_graph
>> (CONFIG_FUNCTION_GRAPH_TRACER) and function profiler
>> (CONFIG_FUNCTION_PROFILER).
>>
>> With 'function' tracer, all the functions in the kernel are traced with
>> timestamps in ${sysfs}/tracing/trace. If function_graph tracer is
>> specified, call graph is generated.
>>
>> The kernel must be compiled with -pg option so that _mcount() is inserted
>> at the beginning of functions. This function is called on every function's
>> entry as long as tracing is enabled.
>> In addition, function_graph tracer also needs to be able to probe function's
>> exit. ftrace_graph_caller() & return_to_handler do this by faking link
>> register's value to intercept function's return path.
>>
>> More details on architecture specific requirements are described in
>> Documentation/trace/ftrace-design.txt.
>
> [...]

You seem not to like this statement :-)

>> diff --git a/arch/arm64/kernel/entry-ftrace.S b/arch/arm64/kernel/entry-ftrace.S
>> new file mode 100644
>> index 0000000..0ac31c8
>> --- /dev/null
>> +++ b/arch/arm64/kernel/entry-ftrace.S
>> @@ -0,0 +1,175 @@
>> +/*
>> + * arch/arm64/kernel/entry-ftrace.S
>> + *
>> + * Copyright (C) 2013 Linaro Limited
>> + * Author: AKASHI Takahiro <takahiro.akashi@linaro.org>
>> + *
>> + * 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 <linux/linkage.h>
>> +#include <asm/ftrace.h>
>> +#include <asm/insn.h>
>> +
>> +/*
>> + * Gcc with -pg will put the following code in the beginning of each function:
>> + *      mov x0, x30
>> + *      bl _mcount
>> + *     [function's body ...]
>> + * "bl _mcount" may be replaced to "bl ftrace_caller" or NOP if dynamic
>> + * ftrace is enabled.
>> + *
>> + * Please note that x0 as an argument will not be used here because we can
>> + * get lr(x30) of instrumented function at any time by winding up call stack
>> + * as long as the kernel is compiled without -fomit-frame-pointer.
>> + * (or CONFIG_FRAME_POINTER, this is forced on arm64)
>> + *
>> + * stack layout after mcount_enter in _mcount():
>> + *
>> + * current sp/fp =>  0:+-----+
>> + * in _mcount()               | x29 | -> instrumented function's fp
>> + *                    +-----+
>> + *                    | x30 | -> _mcount()'s lr (= instrumented function's pc)
>> + * old sp      => +16:+-----+
>> + * when instrumented   |     |
>> + * function calls      | ... |
>> + * _mcount()          |     |
>> + *                    |     |
>> + * instrumented => +xx:+--- --+
>> + * function's fp       | x29 | -> parent's fp
>> + *                    +-----+
>> + *                    | x30 | -> instrumented function's lr (= parent's pc)
>> + *                    +-----+
>> + *                    | ... |
>
> I guess it's just the diff that's misaligning your ASCII art here?

Yes, I think so. Misaligned due to "tab"

>> +/*
>> + * void return_to_handler(void)
>> + *
>> + * Run ftrace_return_to_handler() before going back to parent.
>> + * @fp is checked against the value passed by ftrace_graph_caller()
>> + * only when CONFIG_FUNCTION_GRAPH_FP_TEST is enabled.a
>> + */
>> +       .global return_to_handler
>> +return_to_handler:
>
> ENTRY(return_to_handler)

Fix it.

>> +       str     x0, [sp, #-16]!
>> +       mov     x0, x29                 //     parent's fp
>> +       bl      ftrace_return_to_handler// addr = ftrace_return_to_hander(fp);
>> +       mov     x30, x0                 // restore the original return address
>> +       ldr     x0, [sp], #16
>> +       ret
>
> and an ENDPROC here.

Fix it.
But please note that this (return_to_handler) is not a real function.
Declaring it as ENDPROC is not very useful.

>> +#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
>> diff --git a/arch/arm64/kernel/ftrace.c b/arch/arm64/kernel/ftrace.c
>> new file mode 100644
>> index 0000000..a559ab8
>> --- /dev/null
>> +++ b/arch/arm64/kernel/ftrace.c
>> @@ -0,0 +1,64 @@
>> +/*
>> + * arch/arm64/kernel/ftrace.c
>> + *
>> + * Copyright (C) 2013 Linaro Limited
>> + * Author: AKASHI Takahiro <takahiro.akashi@linaro.org>
>> + *
>> + * 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 <linux/ftrace.h>
>> +#include <linux/swab.h>
>> +#include <linux/uaccess.h>
>> +
>> +#include <asm/cacheflush.h>
>> +#include <asm/ftrace.h>
>> +#include <asm/insn.h>
>> +
>> +#ifdef CONFIG_FUNCTION_GRAPH_TRACER
>> +/*
>> + * function_graph tracer expects ftrace_return_to_handler() to be called
>> + * on the way back to parent. For this purpose, this function is called
>> + * in _mcount() or ftrace_caller() to replace return address (*parent) on
>> + * the call stack to return_to_handler.
>> + *
>> + * Note that @frame_pointer is used only for sanity check later.
>> + */
>> +void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr,
>> +                          unsigned long frame_pointer)
>> +{
>> +       unsigned long return_hooker = (unsigned long)&return_to_handler;
>> +       unsigned long old;
>> +       struct ftrace_graph_ent trace;
>> +       int err;
>> +
>> +       if (unlikely(atomic_read(&current->tracing_graph_pause)))
>> +               return;
>> +
>> +       /*
>> +        * Note:
>> +        * No protection against faulting at *parent, which may be seen
>> +        * on other archs. It's unlikely on AArch64.
>> +        */
>> +       old = *parent;
>> +       *parent = return_hooker;
>
> return_hook? People might take it personally otherwise ;)

I didn't know what "(return) hooker" means.
Anyway, leave it as it is after you and Steven's discussion.

>> +       trace.func = self_addr;
>
> in kernel/ftrace/ftrace.c there's an smb_wmb() between setting up
> tracing_graph_pause and setting the ret_stack with a comment saying:
>
>      /* Make sure the tasks see the -1 first: */
>
> Why don't we have a corresponding read-barrier here?

I think Steven answered it.

-Takahiro AKASHI

> Will
>

^ permalink raw reply	[flat|nested] 235+ messages in thread

* [PATCH v6 4/7] arm64: Add ftrace support
@ 2014-03-14  4:45               ` AKASHI Takahiro
  0 siblings, 0 replies; 235+ messages in thread
From: AKASHI Takahiro @ 2014-03-14  4:45 UTC (permalink / raw)
  To: linux-arm-kernel

On 03/14/2014 02:08 AM, Will Deacon wrote:
> On Thu, Mar 13, 2014 at 10:13:47AM +0000, AKASHI Takahiro wrote:
>> This patch implements arm64 specific part to support function tracers,
>> such as function (CONFIG_FUNCTION_TRACER), function_graph
>> (CONFIG_FUNCTION_GRAPH_TRACER) and function profiler
>> (CONFIG_FUNCTION_PROFILER).
>>
>> With 'function' tracer, all the functions in the kernel are traced with
>> timestamps in ${sysfs}/tracing/trace. If function_graph tracer is
>> specified, call graph is generated.
>>
>> The kernel must be compiled with -pg option so that _mcount() is inserted
>> at the beginning of functions. This function is called on every function's
>> entry as long as tracing is enabled.
>> In addition, function_graph tracer also needs to be able to probe function's
>> exit. ftrace_graph_caller() & return_to_handler do this by faking link
>> register's value to intercept function's return path.
>>
>> More details on architecture specific requirements are described in
>> Documentation/trace/ftrace-design.txt.
>
> [...]

You seem not to like this statement :-)

>> diff --git a/arch/arm64/kernel/entry-ftrace.S b/arch/arm64/kernel/entry-ftrace.S
>> new file mode 100644
>> index 0000000..0ac31c8
>> --- /dev/null
>> +++ b/arch/arm64/kernel/entry-ftrace.S
>> @@ -0,0 +1,175 @@
>> +/*
>> + * arch/arm64/kernel/entry-ftrace.S
>> + *
>> + * Copyright (C) 2013 Linaro Limited
>> + * Author: AKASHI Takahiro <takahiro.akashi@linaro.org>
>> + *
>> + * 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 <linux/linkage.h>
>> +#include <asm/ftrace.h>
>> +#include <asm/insn.h>
>> +
>> +/*
>> + * Gcc with -pg will put the following code in the beginning of each function:
>> + *      mov x0, x30
>> + *      bl _mcount
>> + *     [function's body ...]
>> + * "bl _mcount" may be replaced to "bl ftrace_caller" or NOP if dynamic
>> + * ftrace is enabled.
>> + *
>> + * Please note that x0 as an argument will not be used here because we can
>> + * get lr(x30) of instrumented function at any time by winding up call stack
>> + * as long as the kernel is compiled without -fomit-frame-pointer.
>> + * (or CONFIG_FRAME_POINTER, this is forced on arm64)
>> + *
>> + * stack layout after mcount_enter in _mcount():
>> + *
>> + * current sp/fp =>  0:+-----+
>> + * in _mcount()               | x29 | -> instrumented function's fp
>> + *                    +-----+
>> + *                    | x30 | -> _mcount()'s lr (= instrumented function's pc)
>> + * old sp      => +16:+-----+
>> + * when instrumented   |     |
>> + * function calls      | ... |
>> + * _mcount()          |     |
>> + *                    |     |
>> + * instrumented => +xx:+--- --+
>> + * function's fp       | x29 | -> parent's fp
>> + *                    +-----+
>> + *                    | x30 | -> instrumented function's lr (= parent's pc)
>> + *                    +-----+
>> + *                    | ... |
>
> I guess it's just the diff that's misaligning your ASCII art here?

Yes, I think so. Misaligned due to "tab"

>> +/*
>> + * void return_to_handler(void)
>> + *
>> + * Run ftrace_return_to_handler() before going back to parent.
>> + * @fp is checked against the value passed by ftrace_graph_caller()
>> + * only when CONFIG_FUNCTION_GRAPH_FP_TEST is enabled.a
>> + */
>> +       .global return_to_handler
>> +return_to_handler:
>
> ENTRY(return_to_handler)

Fix it.

>> +       str     x0, [sp, #-16]!
>> +       mov     x0, x29                 //     parent's fp
>> +       bl      ftrace_return_to_handler// addr = ftrace_return_to_hander(fp);
>> +       mov     x30, x0                 // restore the original return address
>> +       ldr     x0, [sp], #16
>> +       ret
>
> and an ENDPROC here.

Fix it.
But please note that this (return_to_handler) is not a real function.
Declaring it as ENDPROC is not very useful.

>> +#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
>> diff --git a/arch/arm64/kernel/ftrace.c b/arch/arm64/kernel/ftrace.c
>> new file mode 100644
>> index 0000000..a559ab8
>> --- /dev/null
>> +++ b/arch/arm64/kernel/ftrace.c
>> @@ -0,0 +1,64 @@
>> +/*
>> + * arch/arm64/kernel/ftrace.c
>> + *
>> + * Copyright (C) 2013 Linaro Limited
>> + * Author: AKASHI Takahiro <takahiro.akashi@linaro.org>
>> + *
>> + * 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 <linux/ftrace.h>
>> +#include <linux/swab.h>
>> +#include <linux/uaccess.h>
>> +
>> +#include <asm/cacheflush.h>
>> +#include <asm/ftrace.h>
>> +#include <asm/insn.h>
>> +
>> +#ifdef CONFIG_FUNCTION_GRAPH_TRACER
>> +/*
>> + * function_graph tracer expects ftrace_return_to_handler() to be called
>> + * on the way back to parent. For this purpose, this function is called
>> + * in _mcount() or ftrace_caller() to replace return address (*parent) on
>> + * the call stack to return_to_handler.
>> + *
>> + * Note that @frame_pointer is used only for sanity check later.
>> + */
>> +void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr,
>> +                          unsigned long frame_pointer)
>> +{
>> +       unsigned long return_hooker = (unsigned long)&return_to_handler;
>> +       unsigned long old;
>> +       struct ftrace_graph_ent trace;
>> +       int err;
>> +
>> +       if (unlikely(atomic_read(&current->tracing_graph_pause)))
>> +               return;
>> +
>> +       /*
>> +        * Note:
>> +        * No protection against faulting at *parent, which may be seen
>> +        * on other archs. It's unlikely on AArch64.
>> +        */
>> +       old = *parent;
>> +       *parent = return_hooker;
>
> return_hook? People might take it personally otherwise ;)

I didn't know what "(return) hooker" means.
Anyway, leave it as it is after you and Steven's discussion.

>> +       trace.func = self_addr;
>
> in kernel/ftrace/ftrace.c there's an smb_wmb() between setting up
> tracing_graph_pause and setting the ret_stack with a comment saying:
>
>      /* Make sure the tasks see the -1 first: */
>
> Why don't we have a corresponding read-barrier here?

I think Steven answered it.

-Takahiro AKASHI

> Will
>

^ permalink raw reply	[flat|nested] 235+ messages in thread

* Re: [PATCH v6 6/7] arm64: ftrace: Add CALLER_ADDRx macros
  2014-03-13 18:07               ` Steven Rostedt
@ 2014-03-14  4:55                 ` AKASHI Takahiro
  -1 siblings, 0 replies; 235+ messages in thread
From: AKASHI Takahiro @ 2014-03-14  4:55 UTC (permalink / raw)
  To: Steven Rostedt, Will Deacon
  Cc: fweisbec, mingo, Catalin Marinas, tim.bird, gkulkarni, dsaxena,
	arndb, linux-arm-kernel, linaro-kernel, linux-kernel

On 03/14/2014 03:07 AM, Steven Rostedt wrote:
> On Thu, 2014-03-13 at 15:54 +0000, Will Deacon wrote:
>> On Thu, Mar 13, 2014 at 10:13:49AM +0000, AKASHI Takahiro wrote:
>>> CALLER_ADDRx returns caller's address at specified level in call stacks.
>>> They are used for several tracers like irqsoff and preemptoff.
>>> Strange to say, however, they are refered even without FTRACE.
>>>
>>> Please note that this implementation assumes that we have frame pointers.
>>> (which means kernel should be compiled with -fno-omit-frame-pointer.)
>>
>> How do you ensure that -fno-omit-frame-pointer is passed?
>
> Perhaps -pg does the same thing?
>
>>> +#define HAVE_ARCH_CALLER_ADDR
>>> +
>>> +#define CALLER_ADDR0 ((unsigned long)__builtin_return_address(0))
>>> +#define CALLER_ADDR1 ((unsigned long)return_address(1))
>>> +#define CALLER_ADDR2 ((unsigned long)return_address(2))
>>> +#define CALLER_ADDR3 ((unsigned long)return_address(3))
>>> +#define CALLER_ADDR4 ((unsigned long)return_address(4))
>>> +#define CALLER_ADDR5 ((unsigned long)return_address(5))
>>> +#define CALLER_ADDR6 ((unsigned long)return_address(6))
>>
>> Could we change the core definitions of these macros (in linux/ftrace.h) to
>> use return_address, then provide an overridable version of return_address
>> that defaults to __builtin_return_address, instead of copy-pasting this
>> sequence?
>
> We could add a new macro:
>
> /* All archs should have this, but we define it for consistency */
> #ifndef ftrace_return_address0
> # define ftrace_return_address0  __builtin_return_address(0)
> #endif
> /* Archs may use other ways for ADDR1 and beyond */
> #ifndef ftrace_return_address
> # define ftrace_return_address(n) __builtin_return_address(n)
> #endif
>
> And then have:
>
> #define CALLER_ADDR0 ((unsigned long)ftrace_return_address0)
> #define CALLER_ADDR1 ((unsigned long)ftrace_return_address(1))
> [...]
>
> And then you would only need to redefine ftrace_return_address.

I'm going to create a separate RFC, including fixes for other archs.

-Takahiro AKASHI

> -- Steve
>
>

^ permalink raw reply	[flat|nested] 235+ messages in thread

* [PATCH v6 6/7] arm64: ftrace: Add CALLER_ADDRx macros
@ 2014-03-14  4:55                 ` AKASHI Takahiro
  0 siblings, 0 replies; 235+ messages in thread
From: AKASHI Takahiro @ 2014-03-14  4:55 UTC (permalink / raw)
  To: linux-arm-kernel

On 03/14/2014 03:07 AM, Steven Rostedt wrote:
> On Thu, 2014-03-13 at 15:54 +0000, Will Deacon wrote:
>> On Thu, Mar 13, 2014 at 10:13:49AM +0000, AKASHI Takahiro wrote:
>>> CALLER_ADDRx returns caller's address at specified level in call stacks.
>>> They are used for several tracers like irqsoff and preemptoff.
>>> Strange to say, however, they are refered even without FTRACE.
>>>
>>> Please note that this implementation assumes that we have frame pointers.
>>> (which means kernel should be compiled with -fno-omit-frame-pointer.)
>>
>> How do you ensure that -fno-omit-frame-pointer is passed?
>
> Perhaps -pg does the same thing?
>
>>> +#define HAVE_ARCH_CALLER_ADDR
>>> +
>>> +#define CALLER_ADDR0 ((unsigned long)__builtin_return_address(0))
>>> +#define CALLER_ADDR1 ((unsigned long)return_address(1))
>>> +#define CALLER_ADDR2 ((unsigned long)return_address(2))
>>> +#define CALLER_ADDR3 ((unsigned long)return_address(3))
>>> +#define CALLER_ADDR4 ((unsigned long)return_address(4))
>>> +#define CALLER_ADDR5 ((unsigned long)return_address(5))
>>> +#define CALLER_ADDR6 ((unsigned long)return_address(6))
>>
>> Could we change the core definitions of these macros (in linux/ftrace.h) to
>> use return_address, then provide an overridable version of return_address
>> that defaults to __builtin_return_address, instead of copy-pasting this
>> sequence?
>
> We could add a new macro:
>
> /* All archs should have this, but we define it for consistency */
> #ifndef ftrace_return_address0
> # define ftrace_return_address0  __builtin_return_address(0)
> #endif
> /* Archs may use other ways for ADDR1 and beyond */
> #ifndef ftrace_return_address
> # define ftrace_return_address(n) __builtin_return_address(n)
> #endif
>
> And then have:
>
> #define CALLER_ADDR0 ((unsigned long)ftrace_return_address0)
> #define CALLER_ADDR1 ((unsigned long)ftrace_return_address(1))
> [...]
>
> And then you would only need to redefine ftrace_return_address.

I'm going to create a separate RFC, including fixes for other archs.

-Takahiro AKASHI

> -- Steve
>
>

^ permalink raw reply	[flat|nested] 235+ messages in thread

* Re: [PATCH v6 5/7] arm64: ftrace: Add dynamic ftrace support
  2014-03-13 18:10             ` Will Deacon
@ 2014-03-14  5:26               ` AKASHI Takahiro
  -1 siblings, 0 replies; 235+ messages in thread
From: AKASHI Takahiro @ 2014-03-14  5:26 UTC (permalink / raw)
  To: Will Deacon
  Cc: rostedt, fweisbec, mingo, Catalin Marinas, tim.bird, gkulkarni,
	dsaxena, arndb, linux-arm-kernel, linaro-kernel, linux-kernel

On 03/14/2014 03:10 AM, Will Deacon wrote:
> On Thu, Mar 13, 2014 at 10:13:48AM +0000, AKASHI Takahiro wrote:
>> This patch allows "dynamic ftrace" if CONFIG_DYNAMIC_FTRACE is enabled.
>> Here we can turn on and off tracing dynamically per-function base.
>>
>> On arm64, this is done by patching single branch instruction to _mcount()
>> inserted by gcc -pg option. The branch is replaced to NOP initially at
>> kernel start up, and later on, NOP to branch to ftrace_caller() when
>> enabled or branch to NOP when disabled.
>> Please note that ftrace_caller() is a counterpart of _mcount() in case of
>> 'static' ftrace.
>>
>> More details on architecture specific requirements are described in
>> Documentation/trace/ftrace-design.txt.
>>
>> Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
>> ---
>>   arch/arm64/Kconfig               |    1 +
>>   arch/arm64/include/asm/ftrace.h  |   15 +++++
>>   arch/arm64/kernel/entry-ftrace.S |   43 +++++++++++++++
>>   arch/arm64/kernel/ftrace.c       |  113 ++++++++++++++++++++++++++++++++++++++
>>   4 files changed, 172 insertions(+)
>>
>> diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
>> index 6b3fef6..6954959 100644
>> --- a/arch/arm64/Kconfig
>> +++ b/arch/arm64/Kconfig
>> @@ -33,6 +33,7 @@ config ARM64
>>   	select HAVE_DMA_API_DEBUG
>>   	select HAVE_DMA_ATTRS
>>   	select HAVE_DMA_CONTIGUOUS
>> +	select HAVE_DYNAMIC_FTRACE
>>   	select HAVE_EFFICIENT_UNALIGNED_ACCESS
>>   	select HAVE_FTRACE_MCOUNT_RECORD
>>   	select HAVE_FUNCTION_TRACER
>> diff --git a/arch/arm64/include/asm/ftrace.h b/arch/arm64/include/asm/ftrace.h
>> index 58ea595..ed5c448 100644
>> --- a/arch/arm64/include/asm/ftrace.h
>> +++ b/arch/arm64/include/asm/ftrace.h
>> @@ -18,6 +18,21 @@
>>
>>   #ifndef __ASSEMBLY__
>>   extern void _mcount(unsigned long);
>> +
>> +struct dyn_arch_ftrace {
>> +	/* No extra data needed for arm64 */
>> +};
>> +
>> +extern unsigned long ftrace_graph_call;
>> +
>> +static inline unsigned long ftrace_call_adjust(unsigned long addr)
>> +{
>> +	/*
>> +	 * addr is the address of the mcount call instruction.
>> +	 * recordmcount does the necessary offset calculation.
>> +	 */
>> +	return addr;
>> +}
>
> You could just as easily implement this as a dummy macro, but I guess it
> doesn't matter either way.

FYI, all archs define this as an inline function.
Leave it as it is.

>>   #endif /* __ASSEMBLY__ */
>>
>>   #endif /* __ASM_FTRACE_H */
>> diff --git a/arch/arm64/kernel/entry-ftrace.S b/arch/arm64/kernel/entry-ftrace.S
>> index 0ac31c8..c0fbe10 100644
>> --- a/arch/arm64/kernel/entry-ftrace.S
>> +++ b/arch/arm64/kernel/entry-ftrace.S
>> @@ -86,6 +86,7 @@
>>   	add	\reg, \reg, #8
>>   	.endm
>>
>> +#ifndef CONFIG_DYNAMIC_FTRACE
>>   /*
>>    * void _mcount(unsigned long return_address)
>>    * @return_address: return address to instrumented function
>> @@ -134,6 +135,48 @@ skip_ftrace_call:
>>   #endif /* CONFIG_FUNCTION_GRAPH_TRACER */
>>   ENDPROC(_mcount)
>>
>> +#else /* CONFIG_DYNAMIC_FTRACE */
>> +/*
>> + * _mcount() is used to build the kernel with -pg option, but all the branch
>> + * instructions to _mcount() are replaced to NOP initially at kernel start up,
>> + * and later on, NOP to branch to ftrace_caller() when enabled or branch to
>> + * NOP when disabled per-function base.
>> + */
>> +ENTRY(_mcount)
>> +	ret
>> +ENDPROC(_mcount)
>
> Judging by your comment then, this should never be called. Is that right? If
> so, we could add a BUG-equivalent so we know if we missed an mcount during
> patching.

Steven explained this.

>> +/*
>> + * void ftrace_caller(unsigned long return_address)
>> + * @return_address: return address to instrumented function
>> + *
>> + * This function is a counterpart of _mcount() in 'static' ftrace, and
>> + * makes calls to:
>> + *     - tracer function to probe instrumented function's entry,
>> + *     - ftrace_graph_caller to set up an exit hook
>> + */
>> +ENTRY(ftrace_caller)
>> +	mcount_enter
>> +
>> +	mcount_get_pc0	x0		//     function's pc
>> +	mcount_get_lr	x1		//     function's lr
>> +
>> +	.global ftrace_call
>> +ftrace_call:				// tracer(pc, lr);
>> +	nop				// This will be replaced with "bl xxx"
>> +					// where xxx can be any kind of tracer.
>> +
>> +#ifdef CONFIG_FUNCTION_GRAPH_TRACER
>> +	.global ftrace_graph_call
>> +ftrace_graph_call:			// ftrace_graph_caller();
>> +	nop				// If enabled, this will be replaced
>> +					// "b ftrace_graph_caller"
>> +#endif
>> +
>> +	mcount_exit
>> +ENDPROC(ftrace_caller)
>> +#endif /* CONFIG_DYNAMIC_FTRACE */
>> +
>>   ENTRY(ftrace_stub)
>>   	ret
>>   ENDPROC(ftrace_stub)
>> diff --git a/arch/arm64/kernel/ftrace.c b/arch/arm64/kernel/ftrace.c
>> index a559ab8..8c26476 100644
>> --- a/arch/arm64/kernel/ftrace.c
>> +++ b/arch/arm64/kernel/ftrace.c
>> @@ -17,6 +17,89 @@
>>   #include <asm/ftrace.h>
>>   #include <asm/insn.h>
>>
>> +#ifdef CONFIG_DYNAMIC_FTRACE
>> +/*
>> + * Replace a single instruction, which may be a branch or NOP.
>> + * If @validate == true, a replaced instruction is checked against 'old'.
>> + */
>> +static int ftrace_modify_code(unsigned long pc, unsigned int old,
>> +			      unsigned int new, bool validate)
>> +{
>> +	unsigned int replaced;
>
> u32 is a bit clearer for instructions.

Fix it.

>> +	/*
>> +	 * Note:
>> +	 * Due to modules and __init, code can disappear and change,
>> +	 * we need to protect against faulting as well as code changing.
>> +	 * We do this by aarch64_insn_*() which use the probe_kernel_*().
>> +	 *
>> +	 * No lock is held here because all the modifications are run
>> +	 * through stop_machine().
>> +	 */
>> +	if (validate) {
>> +		if (aarch64_insn_read((void *)pc, &replaced))
>> +			return -EFAULT;
>> +
>> +		if (replaced != old)
>> +			return -EINVAL;
>> +	}
>> +	if (aarch64_insn_patch_text_nosync((void *)pc, new))
>> +		return -EPERM;
>
> I think you're better off propagating the errors here, rather than
> overriding them with EFAULT/EINVAL/EPERM.

Steven explained this.

>> +
>> +	return 0;
>> +}
>> +
>> +/*
>> + * Replace tracer function in ftrace_caller()
>> + */
>> +int ftrace_update_ftrace_func(ftrace_func_t func)
>> +{
>> +	unsigned long pc;
>> +	unsigned int new;
>> +
>> +	pc = (unsigned long)&ftrace_call;
>> +	new = aarch64_insn_gen_branch_imm(pc, (unsigned long)func, true);
>> +
>> +	return ftrace_modify_code(pc, 0, new, false);
>> +}
>> +
>> +/*
>> + * Turn on the call to ftrace_caller() in instrumented function
>> + */
>> +int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
>> +{
>> +	unsigned long pc = rec->ip;
>> +	unsigned int old, new;
>> +
>> +	old = aarch64_insn_gen_nop();
>> +	new = aarch64_insn_gen_branch_imm(pc, addr, true);
>> +
>> +	return ftrace_modify_code(pc, old, new, true);
>> +}
>> +
>> +/*
>> + * Turn off the call to ftrace_caller() in instrumented function
>> + */
>> +int ftrace_make_nop(struct module *mod,
>> +		    struct dyn_ftrace *rec, unsigned long addr)
>> +{
>> +	unsigned long pc = rec->ip;
>> +	unsigned int old, new;
>> +
>> +	old = aarch64_insn_gen_branch_imm(pc, addr, true);
>> +	new = aarch64_insn_gen_nop();
>> +
>> +	return ftrace_modify_code(pc, old, new, true);
>> +}
>> +
>> +int __init ftrace_dyn_arch_init(void *data)
>> +{
>> +	*(unsigned long *)data = 0;
>> +
>> +	return 0;
>> +}
>> +#endif /* CONFIG_DYNAMIC_FTRACE */
>> +
>>   #ifdef CONFIG_FUNCTION_GRAPH_TRACER
>>   /*
>>    * function_graph tracer expects ftrace_return_to_handler() to be called
>> @@ -61,4 +144,34 @@ void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr,
>>   		return;
>>   	}
>>   }
>> +
>> +#ifdef CONFIG_DYNAMIC_FTRACE
>> +/*
>> + * Turn on/off the call to ftrace_graph_caller() in ftrace_caller()
>> + * depending on @enable.
>> + */
>> +static int ftrace_modify_graph_caller(bool enable)
>> +{
>> +	unsigned long pc = (unsigned long)&ftrace_graph_call;
>> +	unsigned int branch, nop, old, new;
>> +
>> +	branch = aarch64_insn_gen_branch_imm(pc,
>> +			(unsigned long)ftrace_graph_caller, false);
>> +	nop = aarch64_insn_gen_nop();
>> +	old = enable ? nop : branch;
>> +	new = enable ? branch : nop;
>> +
>> +	return ftrace_modify_code(pc, old, new, true);
>
> You could rewrite this as:
>
> 	if (enable)
> 		return ftrace_modify_code(pc, nop, branch, true);
> 	else
> 		return ftrace_modify_code(pc, branch, nop, true);
>
> which I find easier to read.

Yep, fix it.

-Takahiro AKASHI

> Will
>

^ permalink raw reply	[flat|nested] 235+ messages in thread

* [PATCH v6 5/7] arm64: ftrace: Add dynamic ftrace support
@ 2014-03-14  5:26               ` AKASHI Takahiro
  0 siblings, 0 replies; 235+ messages in thread
From: AKASHI Takahiro @ 2014-03-14  5:26 UTC (permalink / raw)
  To: linux-arm-kernel

On 03/14/2014 03:10 AM, Will Deacon wrote:
> On Thu, Mar 13, 2014 at 10:13:48AM +0000, AKASHI Takahiro wrote:
>> This patch allows "dynamic ftrace" if CONFIG_DYNAMIC_FTRACE is enabled.
>> Here we can turn on and off tracing dynamically per-function base.
>>
>> On arm64, this is done by patching single branch instruction to _mcount()
>> inserted by gcc -pg option. The branch is replaced to NOP initially at
>> kernel start up, and later on, NOP to branch to ftrace_caller() when
>> enabled or branch to NOP when disabled.
>> Please note that ftrace_caller() is a counterpart of _mcount() in case of
>> 'static' ftrace.
>>
>> More details on architecture specific requirements are described in
>> Documentation/trace/ftrace-design.txt.
>>
>> Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
>> ---
>>   arch/arm64/Kconfig               |    1 +
>>   arch/arm64/include/asm/ftrace.h  |   15 +++++
>>   arch/arm64/kernel/entry-ftrace.S |   43 +++++++++++++++
>>   arch/arm64/kernel/ftrace.c       |  113 ++++++++++++++++++++++++++++++++++++++
>>   4 files changed, 172 insertions(+)
>>
>> diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
>> index 6b3fef6..6954959 100644
>> --- a/arch/arm64/Kconfig
>> +++ b/arch/arm64/Kconfig
>> @@ -33,6 +33,7 @@ config ARM64
>>   	select HAVE_DMA_API_DEBUG
>>   	select HAVE_DMA_ATTRS
>>   	select HAVE_DMA_CONTIGUOUS
>> +	select HAVE_DYNAMIC_FTRACE
>>   	select HAVE_EFFICIENT_UNALIGNED_ACCESS
>>   	select HAVE_FTRACE_MCOUNT_RECORD
>>   	select HAVE_FUNCTION_TRACER
>> diff --git a/arch/arm64/include/asm/ftrace.h b/arch/arm64/include/asm/ftrace.h
>> index 58ea595..ed5c448 100644
>> --- a/arch/arm64/include/asm/ftrace.h
>> +++ b/arch/arm64/include/asm/ftrace.h
>> @@ -18,6 +18,21 @@
>>
>>   #ifndef __ASSEMBLY__
>>   extern void _mcount(unsigned long);
>> +
>> +struct dyn_arch_ftrace {
>> +	/* No extra data needed for arm64 */
>> +};
>> +
>> +extern unsigned long ftrace_graph_call;
>> +
>> +static inline unsigned long ftrace_call_adjust(unsigned long addr)
>> +{
>> +	/*
>> +	 * addr is the address of the mcount call instruction.
>> +	 * recordmcount does the necessary offset calculation.
>> +	 */
>> +	return addr;
>> +}
>
> You could just as easily implement this as a dummy macro, but I guess it
> doesn't matter either way.

FYI, all archs define this as an inline function.
Leave it as it is.

>>   #endif /* __ASSEMBLY__ */
>>
>>   #endif /* __ASM_FTRACE_H */
>> diff --git a/arch/arm64/kernel/entry-ftrace.S b/arch/arm64/kernel/entry-ftrace.S
>> index 0ac31c8..c0fbe10 100644
>> --- a/arch/arm64/kernel/entry-ftrace.S
>> +++ b/arch/arm64/kernel/entry-ftrace.S
>> @@ -86,6 +86,7 @@
>>   	add	\reg, \reg, #8
>>   	.endm
>>
>> +#ifndef CONFIG_DYNAMIC_FTRACE
>>   /*
>>    * void _mcount(unsigned long return_address)
>>    * @return_address: return address to instrumented function
>> @@ -134,6 +135,48 @@ skip_ftrace_call:
>>   #endif /* CONFIG_FUNCTION_GRAPH_TRACER */
>>   ENDPROC(_mcount)
>>
>> +#else /* CONFIG_DYNAMIC_FTRACE */
>> +/*
>> + * _mcount() is used to build the kernel with -pg option, but all the branch
>> + * instructions to _mcount() are replaced to NOP initially at kernel start up,
>> + * and later on, NOP to branch to ftrace_caller() when enabled or branch to
>> + * NOP when disabled per-function base.
>> + */
>> +ENTRY(_mcount)
>> +	ret
>> +ENDPROC(_mcount)
>
> Judging by your comment then, this should never be called. Is that right? If
> so, we could add a BUG-equivalent so we know if we missed an mcount during
> patching.

Steven explained this.

>> +/*
>> + * void ftrace_caller(unsigned long return_address)
>> + * @return_address: return address to instrumented function
>> + *
>> + * This function is a counterpart of _mcount() in 'static' ftrace, and
>> + * makes calls to:
>> + *     - tracer function to probe instrumented function's entry,
>> + *     - ftrace_graph_caller to set up an exit hook
>> + */
>> +ENTRY(ftrace_caller)
>> +	mcount_enter
>> +
>> +	mcount_get_pc0	x0		//     function's pc
>> +	mcount_get_lr	x1		//     function's lr
>> +
>> +	.global ftrace_call
>> +ftrace_call:				// tracer(pc, lr);
>> +	nop				// This will be replaced with "bl xxx"
>> +					// where xxx can be any kind of tracer.
>> +
>> +#ifdef CONFIG_FUNCTION_GRAPH_TRACER
>> +	.global ftrace_graph_call
>> +ftrace_graph_call:			// ftrace_graph_caller();
>> +	nop				// If enabled, this will be replaced
>> +					// "b ftrace_graph_caller"
>> +#endif
>> +
>> +	mcount_exit
>> +ENDPROC(ftrace_caller)
>> +#endif /* CONFIG_DYNAMIC_FTRACE */
>> +
>>   ENTRY(ftrace_stub)
>>   	ret
>>   ENDPROC(ftrace_stub)
>> diff --git a/arch/arm64/kernel/ftrace.c b/arch/arm64/kernel/ftrace.c
>> index a559ab8..8c26476 100644
>> --- a/arch/arm64/kernel/ftrace.c
>> +++ b/arch/arm64/kernel/ftrace.c
>> @@ -17,6 +17,89 @@
>>   #include <asm/ftrace.h>
>>   #include <asm/insn.h>
>>
>> +#ifdef CONFIG_DYNAMIC_FTRACE
>> +/*
>> + * Replace a single instruction, which may be a branch or NOP.
>> + * If @validate == true, a replaced instruction is checked against 'old'.
>> + */
>> +static int ftrace_modify_code(unsigned long pc, unsigned int old,
>> +			      unsigned int new, bool validate)
>> +{
>> +	unsigned int replaced;
>
> u32 is a bit clearer for instructions.

Fix it.

>> +	/*
>> +	 * Note:
>> +	 * Due to modules and __init, code can disappear and change,
>> +	 * we need to protect against faulting as well as code changing.
>> +	 * We do this by aarch64_insn_*() which use the probe_kernel_*().
>> +	 *
>> +	 * No lock is held here because all the modifications are run
>> +	 * through stop_machine().
>> +	 */
>> +	if (validate) {
>> +		if (aarch64_insn_read((void *)pc, &replaced))
>> +			return -EFAULT;
>> +
>> +		if (replaced != old)
>> +			return -EINVAL;
>> +	}
>> +	if (aarch64_insn_patch_text_nosync((void *)pc, new))
>> +		return -EPERM;
>
> I think you're better off propagating the errors here, rather than
> overriding them with EFAULT/EINVAL/EPERM.

Steven explained this.

>> +
>> +	return 0;
>> +}
>> +
>> +/*
>> + * Replace tracer function in ftrace_caller()
>> + */
>> +int ftrace_update_ftrace_func(ftrace_func_t func)
>> +{
>> +	unsigned long pc;
>> +	unsigned int new;
>> +
>> +	pc = (unsigned long)&ftrace_call;
>> +	new = aarch64_insn_gen_branch_imm(pc, (unsigned long)func, true);
>> +
>> +	return ftrace_modify_code(pc, 0, new, false);
>> +}
>> +
>> +/*
>> + * Turn on the call to ftrace_caller() in instrumented function
>> + */
>> +int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
>> +{
>> +	unsigned long pc = rec->ip;
>> +	unsigned int old, new;
>> +
>> +	old = aarch64_insn_gen_nop();
>> +	new = aarch64_insn_gen_branch_imm(pc, addr, true);
>> +
>> +	return ftrace_modify_code(pc, old, new, true);
>> +}
>> +
>> +/*
>> + * Turn off the call to ftrace_caller() in instrumented function
>> + */
>> +int ftrace_make_nop(struct module *mod,
>> +		    struct dyn_ftrace *rec, unsigned long addr)
>> +{
>> +	unsigned long pc = rec->ip;
>> +	unsigned int old, new;
>> +
>> +	old = aarch64_insn_gen_branch_imm(pc, addr, true);
>> +	new = aarch64_insn_gen_nop();
>> +
>> +	return ftrace_modify_code(pc, old, new, true);
>> +}
>> +
>> +int __init ftrace_dyn_arch_init(void *data)
>> +{
>> +	*(unsigned long *)data = 0;
>> +
>> +	return 0;
>> +}
>> +#endif /* CONFIG_DYNAMIC_FTRACE */
>> +
>>   #ifdef CONFIG_FUNCTION_GRAPH_TRACER
>>   /*
>>    * function_graph tracer expects ftrace_return_to_handler() to be called
>> @@ -61,4 +144,34 @@ void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr,
>>   		return;
>>   	}
>>   }
>> +
>> +#ifdef CONFIG_DYNAMIC_FTRACE
>> +/*
>> + * Turn on/off the call to ftrace_graph_caller() in ftrace_caller()
>> + * depending on @enable.
>> + */
>> +static int ftrace_modify_graph_caller(bool enable)
>> +{
>> +	unsigned long pc = (unsigned long)&ftrace_graph_call;
>> +	unsigned int branch, nop, old, new;
>> +
>> +	branch = aarch64_insn_gen_branch_imm(pc,
>> +			(unsigned long)ftrace_graph_caller, false);
>> +	nop = aarch64_insn_gen_nop();
>> +	old = enable ? nop : branch;
>> +	new = enable ? branch : nop;
>> +
>> +	return ftrace_modify_code(pc, old, new, true);
>
> You could rewrite this as:
>
> 	if (enable)
> 		return ftrace_modify_code(pc, nop, branch, true);
> 	else
> 		return ftrace_modify_code(pc, branch, nop, true);
>
> which I find easier to read.

Yep, fix it.

-Takahiro AKASHI

> Will
>

^ permalink raw reply	[flat|nested] 235+ messages in thread

* Re: [PATCH v6 5/7] arm64: ftrace: Add dynamic ftrace support
  2014-03-13 18:33               ` Steven Rostedt
@ 2014-03-14  5:28                 ` AKASHI Takahiro
  -1 siblings, 0 replies; 235+ messages in thread
From: AKASHI Takahiro @ 2014-03-14  5:28 UTC (permalink / raw)
  To: Steven Rostedt, Will Deacon
  Cc: fweisbec, mingo, Catalin Marinas, tim.bird, gkulkarni, dsaxena,
	arndb, linux-arm-kernel, linaro-kernel, linux-kernel

Thank you for you clarification, Steven.

-Takahiro AKASHI

On 03/14/2014 03:33 AM, Steven Rostedt wrote:
> On Thu, 2014-03-13 at 18:10 +0000, Will Deacon wrote:
>>
>>> +#else /* CONFIG_DYNAMIC_FTRACE */
>>> +/*
>>> + * _mcount() is used to build the kernel with -pg option, but all the branch
>>> + * instructions to _mcount() are replaced to NOP initially at kernel start up,
>>> + * and later on, NOP to branch to ftrace_caller() when enabled or branch to
>>> + * NOP when disabled per-function base.
>>> + */
>>> +ENTRY(_mcount)
>>> +	ret
>>> +ENDPROC(_mcount)
>>
>> Judging by your comment then, this should never be called. Is that right? If
>> so, we could add a BUG-equivalent so we know if we missed an mcount during
>> patching.
>
> Actually, it can be called before the change to nops are done in early
> boot. This is done very early, but everything before ftrace_init() in
> init/main.c can still call _mcount.
>
>
>>> +	/*
>>> +	 * Note:
>>> +	 * Due to modules and __init, code can disappear and change,
>>> +	 * we need to protect against faulting as well as code changing.
>>> +	 * We do this by aarch64_insn_*() which use the probe_kernel_*().
>>> +	 *
>>> +	 * No lock is held here because all the modifications are run
>>> +	 * through stop_machine().
>>> +	 */
>>> +	if (validate) {
>>> +		if (aarch64_insn_read((void *)pc, &replaced))
>>> +			return -EFAULT;
>>> +
>>> +		if (replaced != old)
>>> +			return -EINVAL;
>>> +	}
>>> +	if (aarch64_insn_patch_text_nosync((void *)pc, new))
>>> +		return -EPERM;
>>
>> I think you're better off propagating the errors here, rather than
>> overriding them with EFAULT/EINVAL/EPERM.
>
> The ftrace generic code expects to see these specific errors. Look at
> ftrace_bug() in kernel/trace/ftrace.c.
>
>>
>>> +
>>> +	return 0;
>>> +}
>>> +
>>> +/*
>>> + * Replace tracer function in ftrace_caller()
>>> + */
>>> +int ftrace_update_ftrace_func(ftrace_func_t func)
>>> +{
>>> +	unsigned long pc;
>>> +	unsigned int new;
>>> +
>>> +	pc = (unsigned long)&ftrace_call;
>>> +	new = aarch64_insn_gen_branch_imm(pc, (unsigned long)func, true);
>>> +
>>> +	return ftrace_modify_code(pc, 0, new, false);
>>> +}
>>> +
>>> +/*
>>> + * Turn on the call to ftrace_caller() in instrumented function
>>> + */
>>> +int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
>>> +{
>>> +	unsigned long pc = rec->ip;
>>> +	unsigned int old, new;
>>> +
>>> +	old = aarch64_insn_gen_nop();
>>> +	new = aarch64_insn_gen_branch_imm(pc, addr, true);
>>> +
>>> +	return ftrace_modify_code(pc, old, new, true);
>>> +}
>>> +
>>> +/*
>>> + * Turn off the call to ftrace_caller() in instrumented function
>>> + */
>>> +int ftrace_make_nop(struct module *mod,
>>> +		    struct dyn_ftrace *rec, unsigned long addr)
>>> +{
>>> +	unsigned long pc = rec->ip;
>>> +	unsigned int old, new;
>>> +
>>> +	old = aarch64_insn_gen_branch_imm(pc, addr, true);
>>> +	new = aarch64_insn_gen_nop();
>>> +
>>> +	return ftrace_modify_code(pc, old, new, true);
>>> +}
>>> +
>>> +int __init ftrace_dyn_arch_init(void *data)
>>> +{
>>> +	*(unsigned long *)data = 0;
>>> +
>>> +	return 0;
>>> +}
>>> +#endif /* CONFIG_DYNAMIC_FTRACE */
>>> +
>>>   #ifdef CONFIG_FUNCTION_GRAPH_TRACER
>>>   /*
>>>    * function_graph tracer expects ftrace_return_to_handler() to be called
>>> @@ -61,4 +144,34 @@ void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr,
>>>   		return;
>>>   	}
>>>   }
>>> +
>>> +#ifdef CONFIG_DYNAMIC_FTRACE
>>> +/*
>>> + * Turn on/off the call to ftrace_graph_caller() in ftrace_caller()
>>> + * depending on @enable.
>>> + */
>>> +static int ftrace_modify_graph_caller(bool enable)
>>> +{
>>> +	unsigned long pc = (unsigned long)&ftrace_graph_call;
>>> +	unsigned int branch, nop, old, new;
>>> +
>>> +	branch = aarch64_insn_gen_branch_imm(pc,
>>> +			(unsigned long)ftrace_graph_caller, false);
>>> +	nop = aarch64_insn_gen_nop();
>>> +	old = enable ? nop : branch;
>>> +	new = enable ? branch : nop;
>>> +
>>> +	return ftrace_modify_code(pc, old, new, true);
>>
>> You could rewrite this as:
>>
>> 	if (enable)
>> 		return ftrace_modify_code(pc, nop, branch, true);
>> 	else
>> 		return ftrace_modify_code(pc, branch, nop, true);
>>
>> which I find easier to read.
>
> Heh, maybe that could be updated in other archs too. I'll have to think
> about that one.
>
> -- Steve
>
>

^ permalink raw reply	[flat|nested] 235+ messages in thread

* [PATCH v6 5/7] arm64: ftrace: Add dynamic ftrace support
@ 2014-03-14  5:28                 ` AKASHI Takahiro
  0 siblings, 0 replies; 235+ messages in thread
From: AKASHI Takahiro @ 2014-03-14  5:28 UTC (permalink / raw)
  To: linux-arm-kernel

Thank you for you clarification, Steven.

-Takahiro AKASHI

On 03/14/2014 03:33 AM, Steven Rostedt wrote:
> On Thu, 2014-03-13 at 18:10 +0000, Will Deacon wrote:
>>
>>> +#else /* CONFIG_DYNAMIC_FTRACE */
>>> +/*
>>> + * _mcount() is used to build the kernel with -pg option, but all the branch
>>> + * instructions to _mcount() are replaced to NOP initially at kernel start up,
>>> + * and later on, NOP to branch to ftrace_caller() when enabled or branch to
>>> + * NOP when disabled per-function base.
>>> + */
>>> +ENTRY(_mcount)
>>> +	ret
>>> +ENDPROC(_mcount)
>>
>> Judging by your comment then, this should never be called. Is that right? If
>> so, we could add a BUG-equivalent so we know if we missed an mcount during
>> patching.
>
> Actually, it can be called before the change to nops are done in early
> boot. This is done very early, but everything before ftrace_init() in
> init/main.c can still call _mcount.
>
>
>>> +	/*
>>> +	 * Note:
>>> +	 * Due to modules and __init, code can disappear and change,
>>> +	 * we need to protect against faulting as well as code changing.
>>> +	 * We do this by aarch64_insn_*() which use the probe_kernel_*().
>>> +	 *
>>> +	 * No lock is held here because all the modifications are run
>>> +	 * through stop_machine().
>>> +	 */
>>> +	if (validate) {
>>> +		if (aarch64_insn_read((void *)pc, &replaced))
>>> +			return -EFAULT;
>>> +
>>> +		if (replaced != old)
>>> +			return -EINVAL;
>>> +	}
>>> +	if (aarch64_insn_patch_text_nosync((void *)pc, new))
>>> +		return -EPERM;
>>
>> I think you're better off propagating the errors here, rather than
>> overriding them with EFAULT/EINVAL/EPERM.
>
> The ftrace generic code expects to see these specific errors. Look at
> ftrace_bug() in kernel/trace/ftrace.c.
>
>>
>>> +
>>> +	return 0;
>>> +}
>>> +
>>> +/*
>>> + * Replace tracer function in ftrace_caller()
>>> + */
>>> +int ftrace_update_ftrace_func(ftrace_func_t func)
>>> +{
>>> +	unsigned long pc;
>>> +	unsigned int new;
>>> +
>>> +	pc = (unsigned long)&ftrace_call;
>>> +	new = aarch64_insn_gen_branch_imm(pc, (unsigned long)func, true);
>>> +
>>> +	return ftrace_modify_code(pc, 0, new, false);
>>> +}
>>> +
>>> +/*
>>> + * Turn on the call to ftrace_caller() in instrumented function
>>> + */
>>> +int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
>>> +{
>>> +	unsigned long pc = rec->ip;
>>> +	unsigned int old, new;
>>> +
>>> +	old = aarch64_insn_gen_nop();
>>> +	new = aarch64_insn_gen_branch_imm(pc, addr, true);
>>> +
>>> +	return ftrace_modify_code(pc, old, new, true);
>>> +}
>>> +
>>> +/*
>>> + * Turn off the call to ftrace_caller() in instrumented function
>>> + */
>>> +int ftrace_make_nop(struct module *mod,
>>> +		    struct dyn_ftrace *rec, unsigned long addr)
>>> +{
>>> +	unsigned long pc = rec->ip;
>>> +	unsigned int old, new;
>>> +
>>> +	old = aarch64_insn_gen_branch_imm(pc, addr, true);
>>> +	new = aarch64_insn_gen_nop();
>>> +
>>> +	return ftrace_modify_code(pc, old, new, true);
>>> +}
>>> +
>>> +int __init ftrace_dyn_arch_init(void *data)
>>> +{
>>> +	*(unsigned long *)data = 0;
>>> +
>>> +	return 0;
>>> +}
>>> +#endif /* CONFIG_DYNAMIC_FTRACE */
>>> +
>>>   #ifdef CONFIG_FUNCTION_GRAPH_TRACER
>>>   /*
>>>    * function_graph tracer expects ftrace_return_to_handler() to be called
>>> @@ -61,4 +144,34 @@ void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr,
>>>   		return;
>>>   	}
>>>   }
>>> +
>>> +#ifdef CONFIG_DYNAMIC_FTRACE
>>> +/*
>>> + * Turn on/off the call to ftrace_graph_caller() in ftrace_caller()
>>> + * depending on @enable.
>>> + */
>>> +static int ftrace_modify_graph_caller(bool enable)
>>> +{
>>> +	unsigned long pc = (unsigned long)&ftrace_graph_call;
>>> +	unsigned int branch, nop, old, new;
>>> +
>>> +	branch = aarch64_insn_gen_branch_imm(pc,
>>> +			(unsigned long)ftrace_graph_caller, false);
>>> +	nop = aarch64_insn_gen_nop();
>>> +	old = enable ? nop : branch;
>>> +	new = enable ? branch : nop;
>>> +
>>> +	return ftrace_modify_code(pc, old, new, true);
>>
>> You could rewrite this as:
>>
>> 	if (enable)
>> 		return ftrace_modify_code(pc, nop, branch, true);
>> 	else
>> 		return ftrace_modify_code(pc, branch, nop, true);
>>
>> which I find easier to read.
>
> Heh, maybe that could be updated in other archs too. I'll have to think
> about that one.
>
> -- Steve
>
>

^ permalink raw reply	[flat|nested] 235+ messages in thread

* Re: [PATCH v6 4/7] arm64: Add ftrace support
  2014-03-14  4:45               ` AKASHI Takahiro
@ 2014-03-14 10:07                 ` Will Deacon
  -1 siblings, 0 replies; 235+ messages in thread
From: Will Deacon @ 2014-03-14 10:07 UTC (permalink / raw)
  To: AKASHI Takahiro
  Cc: rostedt, fweisbec, mingo, Catalin Marinas, tim.bird, gkulkarni,
	dsaxena, arndb, linux-arm-kernel, linaro-kernel, linux-kernel

On Fri, Mar 14, 2014 at 04:45:13AM +0000, AKASHI Takahiro wrote:
> On 03/14/2014 02:08 AM, Will Deacon wrote:
> > On Thu, Mar 13, 2014 at 10:13:47AM +0000, AKASHI Takahiro wrote:
> >> This patch implements arm64 specific part to support function tracers,
> >> such as function (CONFIG_FUNCTION_TRACER), function_graph
> >> (CONFIG_FUNCTION_GRAPH_TRACER) and function profiler
> >> (CONFIG_FUNCTION_PROFILER).
> >>
> >> With 'function' tracer, all the functions in the kernel are traced with
> >> timestamps in ${sysfs}/tracing/trace. If function_graph tracer is
> >> specified, call graph is generated.
> >>
> >> The kernel must be compiled with -pg option so that _mcount() is inserted
> >> at the beginning of functions. This function is called on every function's
> >> entry as long as tracing is enabled.
> >> In addition, function_graph tracer also needs to be able to probe function's
> >> exit. ftrace_graph_caller() & return_to_handler do this by faking link
> >> register's value to intercept function's return path.
> >>
> >> More details on architecture specific requirements are described in
> >> Documentation/trace/ftrace-design.txt.
> >
> > [...]
> 
> You seem not to like this statement :-)

Huh? I was just using '[...]' to signify that I'd removed a lot of context
(since the code all looked fine there). Otherwise, review emails can get
really long.

> >> +       str     x0, [sp, #-16]!
> >> +       mov     x0, x29                 //     parent's fp
> >> +       bl      ftrace_return_to_handler// addr = ftrace_return_to_hander(fp);
> >> +       mov     x30, x0                 // restore the original return address
> >> +       ldr     x0, [sp], #16
> >> +       ret
> >
> > and an ENDPROC here.
> 
> Fix it.
> But please note that this (return_to_handler) is not a real function.
> Declaring it as ENDPROC is not very useful.

Then use END(...). The opening macro was the main point, since that avoid
the need for an explicit .globl.

Will

^ permalink raw reply	[flat|nested] 235+ messages in thread

* [PATCH v6 4/7] arm64: Add ftrace support
@ 2014-03-14 10:07                 ` Will Deacon
  0 siblings, 0 replies; 235+ messages in thread
From: Will Deacon @ 2014-03-14 10:07 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, Mar 14, 2014 at 04:45:13AM +0000, AKASHI Takahiro wrote:
> On 03/14/2014 02:08 AM, Will Deacon wrote:
> > On Thu, Mar 13, 2014 at 10:13:47AM +0000, AKASHI Takahiro wrote:
> >> This patch implements arm64 specific part to support function tracers,
> >> such as function (CONFIG_FUNCTION_TRACER), function_graph
> >> (CONFIG_FUNCTION_GRAPH_TRACER) and function profiler
> >> (CONFIG_FUNCTION_PROFILER).
> >>
> >> With 'function' tracer, all the functions in the kernel are traced with
> >> timestamps in ${sysfs}/tracing/trace. If function_graph tracer is
> >> specified, call graph is generated.
> >>
> >> The kernel must be compiled with -pg option so that _mcount() is inserted
> >> at the beginning of functions. This function is called on every function's
> >> entry as long as tracing is enabled.
> >> In addition, function_graph tracer also needs to be able to probe function's
> >> exit. ftrace_graph_caller() & return_to_handler do this by faking link
> >> register's value to intercept function's return path.
> >>
> >> More details on architecture specific requirements are described in
> >> Documentation/trace/ftrace-design.txt.
> >
> > [...]
> 
> You seem not to like this statement :-)

Huh? I was just using '[...]' to signify that I'd removed a lot of context
(since the code all looked fine there). Otherwise, review emails can get
really long.

> >> +       str     x0, [sp, #-16]!
> >> +       mov     x0, x29                 //     parent's fp
> >> +       bl      ftrace_return_to_handler// addr = ftrace_return_to_hander(fp);
> >> +       mov     x30, x0                 // restore the original return address
> >> +       ldr     x0, [sp], #16
> >> +       ret
> >
> > and an ENDPROC here.
> 
> Fix it.
> But please note that this (return_to_handler) is not a real function.
> Declaring it as ENDPROC is not very useful.

Then use END(...). The opening macro was the main point, since that avoid
the need for an explicit .globl.

Will

^ permalink raw reply	[flat|nested] 235+ messages in thread

* Re: [PATCH v6 6/7] arm64: ftrace: Add CALLER_ADDRx macros
  2014-03-14  3:00               ` AKASHI Takahiro
@ 2014-03-14 10:09                 ` Will Deacon
  -1 siblings, 0 replies; 235+ messages in thread
From: Will Deacon @ 2014-03-14 10:09 UTC (permalink / raw)
  To: AKASHI Takahiro
  Cc: rostedt, fweisbec, mingo, Catalin Marinas, tim.bird, gkulkarni,
	dsaxena, arndb, linux-arm-kernel, linaro-kernel, linux-kernel

On Fri, Mar 14, 2014 at 03:00:14AM +0000, AKASHI Takahiro wrote:
> On 03/14/2014 12:54 AM, Will Deacon wrote:
> > On Thu, Mar 13, 2014 at 10:13:49AM +0000, AKASHI Takahiro wrote:
> >> CALLER_ADDRx returns caller's address at specified level in call stacks.
> >> They are used for several tracers like irqsoff and preemptoff.
> >> Strange to say, however, they are refered even without FTRACE.
> >>
> >> Please note that this implementation assumes that we have frame pointers.
> >> (which means kernel should be compiled with -fno-omit-frame-pointer.)
> >
> > How do you ensure that -fno-omit-frame-pointer is passed?
> 
> arm64 selects ARCH_WANT_FRAME_POINTERS, then FRAME_POINTER is on (lib/Kconfig.debug)
> and so -fno-omit-frame-pointer is appended (${TOP}/Makefile).
> (stacktrace.c also assumes FRAME_POINTER.)
> 
> Do you think I should remove the comment above?

Yes please, it sounds like everything is taken care of automatically, so
there's no need to scare people in the commit message!

> >> diff --git a/arch/arm64/include/asm/ftrace.h b/arch/arm64/include/asm/ftrace.h
> >> index ed5c448..c44c4b1 100644
> >> --- a/arch/arm64/include/asm/ftrace.h
> >> +++ b/arch/arm64/include/asm/ftrace.h
> >> @@ -18,6 +18,7 @@
> >>
> >>   #ifndef __ASSEMBLY__
> >>   extern void _mcount(unsigned long);
> >> +extern void *return_address(unsigned int);
> >>
> >>   struct dyn_arch_ftrace {
> >>   	/* No extra data needed for arm64 */
> >> @@ -33,6 +34,16 @@ static inline unsigned long ftrace_call_adjust(unsigned long addr)
> >>   	 */
> >>   	return addr;
> >>   }
> >> -#endif /* __ASSEMBLY__ */
> >> +
> >> +#define HAVE_ARCH_CALLER_ADDR
> >> +
> >> +#define CALLER_ADDR0 ((unsigned long)__builtin_return_address(0))
> >> +#define CALLER_ADDR1 ((unsigned long)return_address(1))
> >> +#define CALLER_ADDR2 ((unsigned long)return_address(2))
> >> +#define CALLER_ADDR3 ((unsigned long)return_address(3))
> >> +#define CALLER_ADDR4 ((unsigned long)return_address(4))
> >> +#define CALLER_ADDR5 ((unsigned long)return_address(5))
> >> +#define CALLER_ADDR6 ((unsigned long)return_address(6))
> >
> > Could we change the core definitions of these macros (in linux/ftrace.h) to
> > use return_address, then provide an overridable version of return_address
> > that defaults to __builtin_return_address, instead of copy-pasting this
> > sequence?
> 
> I think I understand what you mean, and will try to post a separate RFC,
> but I also want to hold off this change on this patch since such a change
> may raise a small controversy from other archs' maintainers.

I don't see anything controversial here, but ok. Steve already posted
something you can get started with.

Will

^ permalink raw reply	[flat|nested] 235+ messages in thread

* [PATCH v6 6/7] arm64: ftrace: Add CALLER_ADDRx macros
@ 2014-03-14 10:09                 ` Will Deacon
  0 siblings, 0 replies; 235+ messages in thread
From: Will Deacon @ 2014-03-14 10:09 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, Mar 14, 2014 at 03:00:14AM +0000, AKASHI Takahiro wrote:
> On 03/14/2014 12:54 AM, Will Deacon wrote:
> > On Thu, Mar 13, 2014 at 10:13:49AM +0000, AKASHI Takahiro wrote:
> >> CALLER_ADDRx returns caller's address at specified level in call stacks.
> >> They are used for several tracers like irqsoff and preemptoff.
> >> Strange to say, however, they are refered even without FTRACE.
> >>
> >> Please note that this implementation assumes that we have frame pointers.
> >> (which means kernel should be compiled with -fno-omit-frame-pointer.)
> >
> > How do you ensure that -fno-omit-frame-pointer is passed?
> 
> arm64 selects ARCH_WANT_FRAME_POINTERS, then FRAME_POINTER is on (lib/Kconfig.debug)
> and so -fno-omit-frame-pointer is appended (${TOP}/Makefile).
> (stacktrace.c also assumes FRAME_POINTER.)
> 
> Do you think I should remove the comment above?

Yes please, it sounds like everything is taken care of automatically, so
there's no need to scare people in the commit message!

> >> diff --git a/arch/arm64/include/asm/ftrace.h b/arch/arm64/include/asm/ftrace.h
> >> index ed5c448..c44c4b1 100644
> >> --- a/arch/arm64/include/asm/ftrace.h
> >> +++ b/arch/arm64/include/asm/ftrace.h
> >> @@ -18,6 +18,7 @@
> >>
> >>   #ifndef __ASSEMBLY__
> >>   extern void _mcount(unsigned long);
> >> +extern void *return_address(unsigned int);
> >>
> >>   struct dyn_arch_ftrace {
> >>   	/* No extra data needed for arm64 */
> >> @@ -33,6 +34,16 @@ static inline unsigned long ftrace_call_adjust(unsigned long addr)
> >>   	 */
> >>   	return addr;
> >>   }
> >> -#endif /* __ASSEMBLY__ */
> >> +
> >> +#define HAVE_ARCH_CALLER_ADDR
> >> +
> >> +#define CALLER_ADDR0 ((unsigned long)__builtin_return_address(0))
> >> +#define CALLER_ADDR1 ((unsigned long)return_address(1))
> >> +#define CALLER_ADDR2 ((unsigned long)return_address(2))
> >> +#define CALLER_ADDR3 ((unsigned long)return_address(3))
> >> +#define CALLER_ADDR4 ((unsigned long)return_address(4))
> >> +#define CALLER_ADDR5 ((unsigned long)return_address(5))
> >> +#define CALLER_ADDR6 ((unsigned long)return_address(6))
> >
> > Could we change the core definitions of these macros (in linux/ftrace.h) to
> > use return_address, then provide an overridable version of return_address
> > that defaults to __builtin_return_address, instead of copy-pasting this
> > sequence?
> 
> I think I understand what you mean, and will try to post a separate RFC,
> but I also want to hold off this change on this patch since such a change
> may raise a small controversy from other archs' maintainers.

I don't see anything controversial here, but ok. Steve already posted
something you can get started with.

Will

^ permalink raw reply	[flat|nested] 235+ messages in thread

* Re: [PATCH v6 4/7] arm64: Add ftrace support
  2014-03-14 10:07                 ` Will Deacon
@ 2014-03-14 16:13                   ` AKASHI Takahiro
  -1 siblings, 0 replies; 235+ messages in thread
From: AKASHI Takahiro @ 2014-03-14 16:13 UTC (permalink / raw)
  To: Will Deacon
  Cc: rostedt, fweisbec, mingo, Catalin Marinas, tim.bird, gkulkarni,
	dsaxena, arndb, linux-arm-kernel, linaro-kernel, linux-kernel

On 03/14/2014 07:07 PM, Will Deacon wrote:
> On Fri, Mar 14, 2014 at 04:45:13AM +0000, AKASHI Takahiro wrote:
>> On 03/14/2014 02:08 AM, Will Deacon wrote:
>>> On Thu, Mar 13, 2014 at 10:13:47AM +0000, AKASHI Takahiro wrote:
>>>> This patch implements arm64 specific part to support function tracers,
>>>> such as function (CONFIG_FUNCTION_TRACER), function_graph
>>>> (CONFIG_FUNCTION_GRAPH_TRACER) and function profiler
>>>> (CONFIG_FUNCTION_PROFILER).
>>>>
>>>> With 'function' tracer, all the functions in the kernel are traced with
>>>> timestamps in ${sysfs}/tracing/trace. If function_graph tracer is
>>>> specified, call graph is generated.
>>>>
>>>> The kernel must be compiled with -pg option so that _mcount() is inserted
>>>> at the beginning of functions. This function is called on every function's
>>>> entry as long as tracing is enabled.
>>>> In addition, function_graph tracer also needs to be able to probe function's
>>>> exit. ftrace_graph_caller() & return_to_handler do this by faking link
>>>> register's value to intercept function's return path.
>>>>
>>>> More details on architecture specific requirements are described in
>>>> Documentation/trace/ftrace-design.txt.
>>>
>>> [...]
>>
>> You seem not to like this statement :-)
>
> Huh? I was just using '[...]' to signify that I'd removed a lot of context
> (since the code all looked fine there). Otherwise, review emails can get
> really long.

Please ignore my comment.

>>>> +       str     x0, [sp, #-16]!
>>>> +       mov     x0, x29                 //     parent's fp
>>>> +       bl      ftrace_return_to_handler// addr = ftrace_return_to_hander(fp);
>>>> +       mov     x30, x0                 // restore the original return address
>>>> +       ldr     x0, [sp], #16
>>>> +       ret
>>>
>>> and an ENDPROC here.
>>
>> Fix it.
>> But please note that this (return_to_handler) is not a real function.
>> Declaring it as ENDPROC is not very useful.
>
> Then use END(...). The opening macro was the main point, since that avoid
> the need for an explicit .globl.

Fix it.

-Takahiro AKASHI

> Will
>

^ permalink raw reply	[flat|nested] 235+ messages in thread

* [PATCH v6 4/7] arm64: Add ftrace support
@ 2014-03-14 16:13                   ` AKASHI Takahiro
  0 siblings, 0 replies; 235+ messages in thread
From: AKASHI Takahiro @ 2014-03-14 16:13 UTC (permalink / raw)
  To: linux-arm-kernel

On 03/14/2014 07:07 PM, Will Deacon wrote:
> On Fri, Mar 14, 2014 at 04:45:13AM +0000, AKASHI Takahiro wrote:
>> On 03/14/2014 02:08 AM, Will Deacon wrote:
>>> On Thu, Mar 13, 2014 at 10:13:47AM +0000, AKASHI Takahiro wrote:
>>>> This patch implements arm64 specific part to support function tracers,
>>>> such as function (CONFIG_FUNCTION_TRACER), function_graph
>>>> (CONFIG_FUNCTION_GRAPH_TRACER) and function profiler
>>>> (CONFIG_FUNCTION_PROFILER).
>>>>
>>>> With 'function' tracer, all the functions in the kernel are traced with
>>>> timestamps in ${sysfs}/tracing/trace. If function_graph tracer is
>>>> specified, call graph is generated.
>>>>
>>>> The kernel must be compiled with -pg option so that _mcount() is inserted
>>>> at the beginning of functions. This function is called on every function's
>>>> entry as long as tracing is enabled.
>>>> In addition, function_graph tracer also needs to be able to probe function's
>>>> exit. ftrace_graph_caller() & return_to_handler do this by faking link
>>>> register's value to intercept function's return path.
>>>>
>>>> More details on architecture specific requirements are described in
>>>> Documentation/trace/ftrace-design.txt.
>>>
>>> [...]
>>
>> You seem not to like this statement :-)
>
> Huh? I was just using '[...]' to signify that I'd removed a lot of context
> (since the code all looked fine there). Otherwise, review emails can get
> really long.

Please ignore my comment.

>>>> +       str     x0, [sp, #-16]!
>>>> +       mov     x0, x29                 //     parent's fp
>>>> +       bl      ftrace_return_to_handler// addr = ftrace_return_to_hander(fp);
>>>> +       mov     x30, x0                 // restore the original return address
>>>> +       ldr     x0, [sp], #16
>>>> +       ret
>>>
>>> and an ENDPROC here.
>>
>> Fix it.
>> But please note that this (return_to_handler) is not a real function.
>> Declaring it as ENDPROC is not very useful.
>
> Then use END(...). The opening macro was the main point, since that avoid
> the need for an explicit .globl.

Fix it.

-Takahiro AKASHI

> Will
>

^ permalink raw reply	[flat|nested] 235+ messages in thread

* Re: [PATCH v6 6/7] arm64: ftrace: Add CALLER_ADDRx macros
  2014-03-14 10:09                 ` Will Deacon
@ 2014-03-14 16:15                   ` AKASHI Takahiro
  -1 siblings, 0 replies; 235+ messages in thread
From: AKASHI Takahiro @ 2014-03-14 16:15 UTC (permalink / raw)
  To: Will Deacon
  Cc: rostedt, fweisbec, mingo, Catalin Marinas, tim.bird, gkulkarni,
	dsaxena, arndb, linux-arm-kernel, linaro-kernel, linux-kernel

On 03/14/2014 07:09 PM, Will Deacon wrote:
> On Fri, Mar 14, 2014 at 03:00:14AM +0000, AKASHI Takahiro wrote:
>> On 03/14/2014 12:54 AM, Will Deacon wrote:
>>> On Thu, Mar 13, 2014 at 10:13:49AM +0000, AKASHI Takahiro wrote:
>>>> CALLER_ADDRx returns caller's address at specified level in call stacks.
>>>> They are used for several tracers like irqsoff and preemptoff.
>>>> Strange to say, however, they are refered even without FTRACE.
>>>>
>>>> Please note that this implementation assumes that we have frame pointers.
>>>> (which means kernel should be compiled with -fno-omit-frame-pointer.)
>>>
>>> How do you ensure that -fno-omit-frame-pointer is passed?
>>
>> arm64 selects ARCH_WANT_FRAME_POINTERS, then FRAME_POINTER is on (lib/Kconfig.debug)
>> and so -fno-omit-frame-pointer is appended (${TOP}/Makefile).
>> (stacktrace.c also assumes FRAME_POINTER.)
>>
>> Do you think I should remove the comment above?
>
> Yes please, it sounds like everything is taken care of automatically, so
> there's no need to scare people in the commit message!

OK, I will do so.

Thanks,
-Takahiro AKASHI

>>>> diff --git a/arch/arm64/include/asm/ftrace.h b/arch/arm64/include/asm/ftrace.h
>>>> index ed5c448..c44c4b1 100644
>>>> --- a/arch/arm64/include/asm/ftrace.h
>>>> +++ b/arch/arm64/include/asm/ftrace.h
>>>> @@ -18,6 +18,7 @@
>>>>
>>>>    #ifndef __ASSEMBLY__
>>>>    extern void _mcount(unsigned long);
>>>> +extern void *return_address(unsigned int);
>>>>
>>>>    struct dyn_arch_ftrace {
>>>>    	/* No extra data needed for arm64 */
>>>> @@ -33,6 +34,16 @@ static inline unsigned long ftrace_call_adjust(unsigned long addr)
>>>>    	 */
>>>>    	return addr;
>>>>    }
>>>> -#endif /* __ASSEMBLY__ */
>>>> +
>>>> +#define HAVE_ARCH_CALLER_ADDR
>>>> +
>>>> +#define CALLER_ADDR0 ((unsigned long)__builtin_return_address(0))
>>>> +#define CALLER_ADDR1 ((unsigned long)return_address(1))
>>>> +#define CALLER_ADDR2 ((unsigned long)return_address(2))
>>>> +#define CALLER_ADDR3 ((unsigned long)return_address(3))
>>>> +#define CALLER_ADDR4 ((unsigned long)return_address(4))
>>>> +#define CALLER_ADDR5 ((unsigned long)return_address(5))
>>>> +#define CALLER_ADDR6 ((unsigned long)return_address(6))
>>>
>>> Could we change the core definitions of these macros (in linux/ftrace.h) to
>>> use return_address, then provide an overridable version of return_address
>>> that defaults to __builtin_return_address, instead of copy-pasting this
>>> sequence?
>>
>> I think I understand what you mean, and will try to post a separate RFC,
>> but I also want to hold off this change on this patch since such a change
>> may raise a small controversy from other archs' maintainers.
>
> I don't see anything controversial here, but ok. Steve already posted
> something you can get started with.
>
> Will
>

^ permalink raw reply	[flat|nested] 235+ messages in thread

* [PATCH v6 6/7] arm64: ftrace: Add CALLER_ADDRx macros
@ 2014-03-14 16:15                   ` AKASHI Takahiro
  0 siblings, 0 replies; 235+ messages in thread
From: AKASHI Takahiro @ 2014-03-14 16:15 UTC (permalink / raw)
  To: linux-arm-kernel

On 03/14/2014 07:09 PM, Will Deacon wrote:
> On Fri, Mar 14, 2014 at 03:00:14AM +0000, AKASHI Takahiro wrote:
>> On 03/14/2014 12:54 AM, Will Deacon wrote:
>>> On Thu, Mar 13, 2014 at 10:13:49AM +0000, AKASHI Takahiro wrote:
>>>> CALLER_ADDRx returns caller's address at specified level in call stacks.
>>>> They are used for several tracers like irqsoff and preemptoff.
>>>> Strange to say, however, they are refered even without FTRACE.
>>>>
>>>> Please note that this implementation assumes that we have frame pointers.
>>>> (which means kernel should be compiled with -fno-omit-frame-pointer.)
>>>
>>> How do you ensure that -fno-omit-frame-pointer is passed?
>>
>> arm64 selects ARCH_WANT_FRAME_POINTERS, then FRAME_POINTER is on (lib/Kconfig.debug)
>> and so -fno-omit-frame-pointer is appended (${TOP}/Makefile).
>> (stacktrace.c also assumes FRAME_POINTER.)
>>
>> Do you think I should remove the comment above?
>
> Yes please, it sounds like everything is taken care of automatically, so
> there's no need to scare people in the commit message!

OK, I will do so.

Thanks,
-Takahiro AKASHI

>>>> diff --git a/arch/arm64/include/asm/ftrace.h b/arch/arm64/include/asm/ftrace.h
>>>> index ed5c448..c44c4b1 100644
>>>> --- a/arch/arm64/include/asm/ftrace.h
>>>> +++ b/arch/arm64/include/asm/ftrace.h
>>>> @@ -18,6 +18,7 @@
>>>>
>>>>    #ifndef __ASSEMBLY__
>>>>    extern void _mcount(unsigned long);
>>>> +extern void *return_address(unsigned int);
>>>>
>>>>    struct dyn_arch_ftrace {
>>>>    	/* No extra data needed for arm64 */
>>>> @@ -33,6 +34,16 @@ static inline unsigned long ftrace_call_adjust(unsigned long addr)
>>>>    	 */
>>>>    	return addr;
>>>>    }
>>>> -#endif /* __ASSEMBLY__ */
>>>> +
>>>> +#define HAVE_ARCH_CALLER_ADDR
>>>> +
>>>> +#define CALLER_ADDR0 ((unsigned long)__builtin_return_address(0))
>>>> +#define CALLER_ADDR1 ((unsigned long)return_address(1))
>>>> +#define CALLER_ADDR2 ((unsigned long)return_address(2))
>>>> +#define CALLER_ADDR3 ((unsigned long)return_address(3))
>>>> +#define CALLER_ADDR4 ((unsigned long)return_address(4))
>>>> +#define CALLER_ADDR5 ((unsigned long)return_address(5))
>>>> +#define CALLER_ADDR6 ((unsigned long)return_address(6))
>>>
>>> Could we change the core definitions of these macros (in linux/ftrace.h) to
>>> use return_address, then provide an overridable version of return_address
>>> that defaults to __builtin_return_address, instead of copy-pasting this
>>> sequence?
>>
>> I think I understand what you mean, and will try to post a separate RFC,
>> but I also want to hold off this change on this patch since such a change
>> may raise a small controversy from other archs' maintainers.
>
> I don't see anything controversial here, but ok. Steve already posted
> something you can get started with.
>
> Will
>

^ permalink raw reply	[flat|nested] 235+ messages in thread

* [PATCH v7 0/7] arm64: Add ftrace support
  2014-03-13 10:13         ` AKASHI Takahiro
@ 2014-03-15  5:40           ` AKASHI Takahiro
  -1 siblings, 0 replies; 235+ messages in thread
From: AKASHI Takahiro @ 2014-03-15  5:40 UTC (permalink / raw)
  To: rostedt, fweisbec, mingo, catalin.marinas, will.deacon, tim.bird
  Cc: gkulkarni, dsaxena, arndb, linux-arm-kernel, linaro-kernel,
	linux-kernel, AKASHI Takahiro

This patchset implements a function tracer on arm64.
There was another implementation from Cavium network, but both of us agreed
to use my patchset as future base. He is supposed to review this code, too.

The only issue that I had some concern on was "fault protection" code
in prepare_ftrace_return(). With discussions with Steven and Tim (as author
of arm ftrace), I removed that code since I'm not quite sure about possibility
of "fault" occurrences in this function.

The code is tested on ARMv8 Fast Model with the following tracers & events:
     function tracer with dynamic ftrace
     function graph tracer with dynamic ftrace
     syscall tracepoint (but only for AArch64 tasks)
     irqsoff & preemptirqsoff (which use CALLER_ADDRx)
and also verified with in-kernel tests, FTRACE_SELFTEST, FTRACE_STARTUP_TEST
and EVENT_TRACE_TEST_SYSCALLS.

Prerequisites are:
 * "arm64: make a single hook to syscall_trace() for all syscall features" patch
 * "arm64: split syscall_trace() into separate functions for enter/exit" patch
 * "arm64: Add regs_return_value() in syscall.h" patch
 * "arm64: is_compat_task is defined both in asm/compat.h and
    linux/compat.h" patch

Please be careful:
* Patch [3/7] gets warnings from checkpatch, but they are based on the
  original's coding style.
* Patch [7/7] may conflict with my audit patch because both changes the same
  location in syscall_trace_enter/exit(). I expect the functions are called
  in this order:
  On entry,
     * tracehook_report_syscall(ENTER)
     * trace_sys_enter()
     * audit_syscall_entry()
  On exit,
     * audit_sysscall_exit()
     * trace_sys_exit()
     * tracehook_report_syscall(EXIT) 

Changes from v6 to v7:
* changed to use gpfx variable instead of defining altmcount in recordmcount.c
  [3/7]
* declared return_to_handler using ENTRY/END macros [4/7]
* changed to use u32 instead of int as instruction words, and simplified
  ftrace_modify_graph_caller() [5/7]
* simplified arch_trace_is_compat_call() for readability [7/7]
* added the following patch to prerequisite list,
  "arm64: is_compat_task is defined both in asm/compat.h and linux/compat.h"
  and changed to use linux/compat.h instead of asm/compat.h in asm/ftrace.h
  to avoid compile errors against some files (ie. do_mounts.c and etc) if
  FTRACE & !COMPAT. [7/7]

Changes from v5 to v6:
* changed the order of patches to avoid any bisect error (I have not tried
  though)
* added EM_AARCH64 and R_AARCH64_ABS64 definitions in scripts/recordmcount.c
  just in case elf.h on host machine doesn't have them. [3/7]
* updated a frame pointer (x29) in _mcount() to make it look like a normal
  function [4/7]
* aligned with the patch, "arm64: split syscall_trace() into separate
  functions for enter/exit" [7/7]
* defined ARCH_TRACE_IGNORE_COMPAT_SYSCALLS in order not to trace compat
  syscalls [7/7]

Chnages from v4 to v5:
* improved the description of stack layout [1/7]
* aligned with the change in "arm64: make a single hook to syscall_trace()
  for all syscall features" v3 [5/7]

Changes from v3 to v4:
* removed unnecessary "#ifdef" [1,2/7]
* changed stack depth from 48B to 16B in mcount()/ftrace_caller() (a bug) [1/7]
* changed MCOUNT_INSN_SIZE to AARCH64_INSN_SIZE [1,7/7]
* added a guard againt TIF_SYSCALL_TRACEPOINT [5/7]
* corrected the second argument passed to trace_sys_exit() (a bug) [5/7]
* aligned with the change in "arm64: make a single hook to syscall_trace()
  for all syscall features" v2 [5/7]

Changes from v2 to v3:
* optimized register usages in asm (by not saving x0, x1, and x2)
* removed "fault protection" code in prepare_ftrace_return()
* rewrote ftrace_modify_code() using "hotpatch" interfaces
* revised descriptions in comments

Changes from v1 to v2:
* splitted one patch into some pieces for easier review
  (especially function tracer + dynamic ftrace + CALLER_ADDRx)
* put return_address() in a separate file
* renamed __mcount to _mcount (it was my mistake)
* changed stackframe handling to get parent's frame pointer
* removed ARCH_SUPPORTS_FTRACE_OPS
* switched to "hotpatch" interfaces from Huawai
* revised descriptions in comments

AKASHI Takahiro (7):
  arm64: add __ASSEMBLY__ in asm/insn.h
  arm64: Add 'notrace' attribute to unwind_frame() for ftrace
  ftrace: Add arm64 support to recordmcount
  arm64: Add ftrace support
  arm64: ftrace: Add dynamic ftrace support
  arm64: ftrace: Add CALLER_ADDRx macros
  arm64: ftrace: Add system call tracepoint

 arch/arm64/Kconfig                 |   6 +
 arch/arm64/include/asm/ftrace.h    |  67 ++++++++++++
 arch/arm64/include/asm/insn.h      |   2 +
 arch/arm64/include/asm/syscall.h   |   1 +
 arch/arm64/include/asm/unistd.h    |   2 +
 arch/arm64/kernel/Makefile         |   7 +-
 arch/arm64/kernel/arm64ksyms.c     |   4 +
 arch/arm64/kernel/entry-ftrace.S   | 218 +++++++++++++++++++++++++++++++++++++
 arch/arm64/kernel/ftrace.c         | 178 ++++++++++++++++++++++++++++++
 arch/arm64/kernel/ptrace.c         |   9 ++
 arch/arm64/kernel/return_address.c |  55 ++++++++++
 arch/arm64/kernel/stacktrace.c     |   2 +-
 scripts/recordmcount.c             |   7 ++
 scripts/recordmcount.pl            |   5 +
 14 files changed, 561 insertions(+), 2 deletions(-)
 create mode 100644 arch/arm64/include/asm/ftrace.h
 create mode 100644 arch/arm64/kernel/entry-ftrace.S
 create mode 100644 arch/arm64/kernel/ftrace.c
 create mode 100644 arch/arm64/kernel/return_address.c

-- 
1.8.3.2


^ permalink raw reply	[flat|nested] 235+ messages in thread

* [PATCH v7 0/7] arm64: Add ftrace support
@ 2014-03-15  5:40           ` AKASHI Takahiro
  0 siblings, 0 replies; 235+ messages in thread
From: AKASHI Takahiro @ 2014-03-15  5:40 UTC (permalink / raw)
  To: linux-arm-kernel

This patchset implements a function tracer on arm64.
There was another implementation from Cavium network, but both of us agreed
to use my patchset as future base. He is supposed to review this code, too.

The only issue that I had some concern on was "fault protection" code
in prepare_ftrace_return(). With discussions with Steven and Tim (as author
of arm ftrace), I removed that code since I'm not quite sure about possibility
of "fault" occurrences in this function.

The code is tested on ARMv8 Fast Model with the following tracers & events:
     function tracer with dynamic ftrace
     function graph tracer with dynamic ftrace
     syscall tracepoint (but only for AArch64 tasks)
     irqsoff & preemptirqsoff (which use CALLER_ADDRx)
and also verified with in-kernel tests, FTRACE_SELFTEST, FTRACE_STARTUP_TEST
and EVENT_TRACE_TEST_SYSCALLS.

Prerequisites are:
 * "arm64: make a single hook to syscall_trace() for all syscall features" patch
 * "arm64: split syscall_trace() into separate functions for enter/exit" patch
 * "arm64: Add regs_return_value() in syscall.h" patch
 * "arm64: is_compat_task is defined both in asm/compat.h and
    linux/compat.h" patch

Please be careful:
* Patch [3/7] gets warnings from checkpatch, but they are based on the
  original's coding style.
* Patch [7/7] may conflict with my audit patch because both changes the same
  location in syscall_trace_enter/exit(). I expect the functions are called
  in this order:
  On entry,
     * tracehook_report_syscall(ENTER)
     * trace_sys_enter()
     * audit_syscall_entry()
  On exit,
     * audit_sysscall_exit()
     * trace_sys_exit()
     * tracehook_report_syscall(EXIT) 

Changes from v6 to v7:
* changed to use gpfx variable instead of defining altmcount in recordmcount.c
  [3/7]
* declared return_to_handler using ENTRY/END macros [4/7]
* changed to use u32 instead of int as instruction words, and simplified
  ftrace_modify_graph_caller() [5/7]
* simplified arch_trace_is_compat_call() for readability [7/7]
* added the following patch to prerequisite list,
  "arm64: is_compat_task is defined both in asm/compat.h and linux/compat.h"
  and changed to use linux/compat.h instead of asm/compat.h in asm/ftrace.h
  to avoid compile errors against some files (ie. do_mounts.c and etc) if
  FTRACE & !COMPAT. [7/7]

Changes from v5 to v6:
* changed the order of patches to avoid any bisect error (I have not tried
  though)
* added EM_AARCH64 and R_AARCH64_ABS64 definitions in scripts/recordmcount.c
  just in case elf.h on host machine doesn't have them. [3/7]
* updated a frame pointer (x29) in _mcount() to make it look like a normal
  function [4/7]
* aligned with the patch, "arm64: split syscall_trace() into separate
  functions for enter/exit" [7/7]
* defined ARCH_TRACE_IGNORE_COMPAT_SYSCALLS in order not to trace compat
  syscalls [7/7]

Chnages from v4 to v5:
* improved the description of stack layout [1/7]
* aligned with the change in "arm64: make a single hook to syscall_trace()
  for all syscall features" v3 [5/7]

Changes from v3 to v4:
* removed unnecessary "#ifdef" [1,2/7]
* changed stack depth from 48B to 16B in mcount()/ftrace_caller() (a bug) [1/7]
* changed MCOUNT_INSN_SIZE to AARCH64_INSN_SIZE [1,7/7]
* added a guard againt TIF_SYSCALL_TRACEPOINT [5/7]
* corrected the second argument passed to trace_sys_exit() (a bug) [5/7]
* aligned with the change in "arm64: make a single hook to syscall_trace()
  for all syscall features" v2 [5/7]

Changes from v2 to v3:
* optimized register usages in asm (by not saving x0, x1, and x2)
* removed "fault protection" code in prepare_ftrace_return()
* rewrote ftrace_modify_code() using "hotpatch" interfaces
* revised descriptions in comments

Changes from v1 to v2:
* splitted one patch into some pieces for easier review
  (especially function tracer + dynamic ftrace + CALLER_ADDRx)
* put return_address() in a separate file
* renamed __mcount to _mcount (it was my mistake)
* changed stackframe handling to get parent's frame pointer
* removed ARCH_SUPPORTS_FTRACE_OPS
* switched to "hotpatch" interfaces from Huawai
* revised descriptions in comments

AKASHI Takahiro (7):
  arm64: add __ASSEMBLY__ in asm/insn.h
  arm64: Add 'notrace' attribute to unwind_frame() for ftrace
  ftrace: Add arm64 support to recordmcount
  arm64: Add ftrace support
  arm64: ftrace: Add dynamic ftrace support
  arm64: ftrace: Add CALLER_ADDRx macros
  arm64: ftrace: Add system call tracepoint

 arch/arm64/Kconfig                 |   6 +
 arch/arm64/include/asm/ftrace.h    |  67 ++++++++++++
 arch/arm64/include/asm/insn.h      |   2 +
 arch/arm64/include/asm/syscall.h   |   1 +
 arch/arm64/include/asm/unistd.h    |   2 +
 arch/arm64/kernel/Makefile         |   7 +-
 arch/arm64/kernel/arm64ksyms.c     |   4 +
 arch/arm64/kernel/entry-ftrace.S   | 218 +++++++++++++++++++++++++++++++++++++
 arch/arm64/kernel/ftrace.c         | 178 ++++++++++++++++++++++++++++++
 arch/arm64/kernel/ptrace.c         |   9 ++
 arch/arm64/kernel/return_address.c |  55 ++++++++++
 arch/arm64/kernel/stacktrace.c     |   2 +-
 scripts/recordmcount.c             |   7 ++
 scripts/recordmcount.pl            |   5 +
 14 files changed, 561 insertions(+), 2 deletions(-)
 create mode 100644 arch/arm64/include/asm/ftrace.h
 create mode 100644 arch/arm64/kernel/entry-ftrace.S
 create mode 100644 arch/arm64/kernel/ftrace.c
 create mode 100644 arch/arm64/kernel/return_address.c

-- 
1.8.3.2

^ permalink raw reply	[flat|nested] 235+ messages in thread

* [PATCH v7 1/7] arm64: add __ASSEMBLY__ in asm/insn.h
  2014-03-15  5:40           ` AKASHI Takahiro
@ 2014-03-15  5:40             ` AKASHI Takahiro
  -1 siblings, 0 replies; 235+ messages in thread
From: AKASHI Takahiro @ 2014-03-15  5:40 UTC (permalink / raw)
  To: rostedt, fweisbec, mingo, catalin.marinas, will.deacon, tim.bird
  Cc: gkulkarni, dsaxena, arndb, linux-arm-kernel, linaro-kernel,
	linux-kernel, AKASHI Takahiro

Since insn.h is indirectly included in asm/entry-ftrace.S,
we need to exclude some declarations by __ASSEMBLY__.

Acked-by: Will Deacon <will.deacon@arm.com>
Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
---
 arch/arm64/include/asm/insn.h | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/arch/arm64/include/asm/insn.h b/arch/arm64/include/asm/insn.h
index c44ad39..dc1f73b 100644
--- a/arch/arm64/include/asm/insn.h
+++ b/arch/arm64/include/asm/insn.h
@@ -21,6 +21,7 @@
 /* A64 instructions are always 32 bits. */
 #define	AARCH64_INSN_SIZE		4
 
+#ifndef __ASSEMBLY__
 /*
  * ARM Architecture Reference Manual for ARMv8 Profile-A, Issue A.a
  * Section C3.1 "A64 instruction index by encoding":
@@ -104,5 +105,6 @@ bool aarch64_insn_hotpatch_safe(u32 old_insn, u32 new_insn);
 int aarch64_insn_patch_text_nosync(void *addr, u32 insn);
 int aarch64_insn_patch_text_sync(void *addrs[], u32 insns[], int cnt);
 int aarch64_insn_patch_text(void *addrs[], u32 insns[], int cnt);
+#endif /* __ASSEMBLY__ */
 
 #endif	/* __ASM_INSN_H */
-- 
1.8.3.2


^ permalink raw reply related	[flat|nested] 235+ messages in thread

* [PATCH v7 1/7] arm64: add __ASSEMBLY__ in asm/insn.h
@ 2014-03-15  5:40             ` AKASHI Takahiro
  0 siblings, 0 replies; 235+ messages in thread
From: AKASHI Takahiro @ 2014-03-15  5:40 UTC (permalink / raw)
  To: linux-arm-kernel

Since insn.h is indirectly included in asm/entry-ftrace.S,
we need to exclude some declarations by __ASSEMBLY__.

Acked-by: Will Deacon <will.deacon@arm.com>
Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
---
 arch/arm64/include/asm/insn.h | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/arch/arm64/include/asm/insn.h b/arch/arm64/include/asm/insn.h
index c44ad39..dc1f73b 100644
--- a/arch/arm64/include/asm/insn.h
+++ b/arch/arm64/include/asm/insn.h
@@ -21,6 +21,7 @@
 /* A64 instructions are always 32 bits. */
 #define	AARCH64_INSN_SIZE		4
 
+#ifndef __ASSEMBLY__
 /*
  * ARM Architecture Reference Manual for ARMv8 Profile-A, Issue A.a
  * Section C3.1 "A64 instruction index by encoding":
@@ -104,5 +105,6 @@ bool aarch64_insn_hotpatch_safe(u32 old_insn, u32 new_insn);
 int aarch64_insn_patch_text_nosync(void *addr, u32 insn);
 int aarch64_insn_patch_text_sync(void *addrs[], u32 insns[], int cnt);
 int aarch64_insn_patch_text(void *addrs[], u32 insns[], int cnt);
+#endif /* __ASSEMBLY__ */
 
 #endif	/* __ASM_INSN_H */
-- 
1.8.3.2

^ permalink raw reply related	[flat|nested] 235+ messages in thread

* [PATCH v7 2/7] arm64: Add 'notrace' attribute to unwind_frame() for ftrace
  2014-03-15  5:40           ` AKASHI Takahiro
@ 2014-03-15  5:40             ` AKASHI Takahiro
  -1 siblings, 0 replies; 235+ messages in thread
From: AKASHI Takahiro @ 2014-03-15  5:40 UTC (permalink / raw)
  To: rostedt, fweisbec, mingo, catalin.marinas, will.deacon, tim.bird
  Cc: gkulkarni, dsaxena, arndb, linux-arm-kernel, linaro-kernel,
	linux-kernel, AKASHI Takahiro

walk_stackframe() calls unwind_frame(), and if walk_stackframe() is
"notrace", unwind_frame() should be also "notrace".

Acked-by: Will Deacon <will.deacon@arm.com>
Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
---
 arch/arm64/kernel/stacktrace.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm64/kernel/stacktrace.c b/arch/arm64/kernel/stacktrace.c
index c3b6c63..54122c4 100644
--- a/arch/arm64/kernel/stacktrace.c
+++ b/arch/arm64/kernel/stacktrace.c
@@ -35,7 +35,7 @@
  *	ldp	x29, x30, [sp]
  *	add	sp, sp, #0x10
  */
-int unwind_frame(struct stackframe *frame)
+int notrace unwind_frame(struct stackframe *frame)
 {
 	unsigned long high, low;
 	unsigned long fp = frame->fp;
-- 
1.8.3.2


^ permalink raw reply related	[flat|nested] 235+ messages in thread

* [PATCH v7 2/7] arm64: Add 'notrace' attribute to unwind_frame() for ftrace
@ 2014-03-15  5:40             ` AKASHI Takahiro
  0 siblings, 0 replies; 235+ messages in thread
From: AKASHI Takahiro @ 2014-03-15  5:40 UTC (permalink / raw)
  To: linux-arm-kernel

walk_stackframe() calls unwind_frame(), and if walk_stackframe() is
"notrace", unwind_frame() should be also "notrace".

Acked-by: Will Deacon <will.deacon@arm.com>
Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
---
 arch/arm64/kernel/stacktrace.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm64/kernel/stacktrace.c b/arch/arm64/kernel/stacktrace.c
index c3b6c63..54122c4 100644
--- a/arch/arm64/kernel/stacktrace.c
+++ b/arch/arm64/kernel/stacktrace.c
@@ -35,7 +35,7 @@
  *	ldp	x29, x30, [sp]
  *	add	sp, sp, #0x10
  */
-int unwind_frame(struct stackframe *frame)
+int notrace unwind_frame(struct stackframe *frame)
 {
 	unsigned long high, low;
 	unsigned long fp = frame->fp;
-- 
1.8.3.2

^ permalink raw reply related	[flat|nested] 235+ messages in thread

* [PATCH v7 3/7] ftrace: Add arm64 support to recordmcount
  2014-03-15  5:40           ` AKASHI Takahiro
@ 2014-03-15  5:40             ` AKASHI Takahiro
  -1 siblings, 0 replies; 235+ messages in thread
From: AKASHI Takahiro @ 2014-03-15  5:40 UTC (permalink / raw)
  To: rostedt, fweisbec, mingo, catalin.marinas, will.deacon, tim.bird
  Cc: gkulkarni, dsaxena, arndb, linux-arm-kernel, linaro-kernel,
	linux-kernel, AKASHI Takahiro

Recordmcount utility under scripts is run, after compiling each object,
to find out all the locations of calling _mcount() and put them into
specific seciton named __mcount_loc.
Then linker collects all such information into a table in the kernel image
(between __start_mcount_loc and __stop_mcount_loc) for later use by ftrace.

This patch adds arm64 specific definitions to identify such locations.
There are two types of implementation, C and Perl. On arm64, only C version
is used to build the kernel now that CONFIG_HAVE_C_RECORDMCOUNT is on.
But Perl version is also maintained.

This patch also contains a workaround just in case where a header file,
elf.h, on host machine doesn't have definitions of EM_AARCH64 nor
R_AARCH64_ABS64. Without them, compiling C version of recordmcount will
fail.

Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
---
 arch/arm64/Kconfig      | 2 ++
 scripts/recordmcount.c  | 7 +++++++
 scripts/recordmcount.pl | 5 +++++
 3 files changed, 14 insertions(+)

diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 27bbcfc..340e344 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -27,12 +27,14 @@ config ARM64
 	select HARDIRQS_SW_RESEND
 	select HAVE_ARCH_JUMP_LABEL
 	select HAVE_ARCH_TRACEHOOK
+	select HAVE_C_RECORDMCOUNT
 	select HAVE_DEBUG_BUGVERBOSE
 	select HAVE_DEBUG_KMEMLEAK
 	select HAVE_DMA_API_DEBUG
 	select HAVE_DMA_ATTRS
 	select HAVE_DMA_CONTIGUOUS
 	select HAVE_EFFICIENT_UNALIGNED_ACCESS
+	select HAVE_FTRACE_MCOUNT_RECORD
 	select HAVE_GENERIC_DMA_COHERENT
 	select HAVE_HW_BREAKPOINT if PERF_EVENTS
 	select HAVE_MEMBLOCK
diff --git a/scripts/recordmcount.c b/scripts/recordmcount.c
index 9c22317..e11aa4a 100644
--- a/scripts/recordmcount.c
+++ b/scripts/recordmcount.c
@@ -40,6 +40,11 @@
 #define R_METAG_NONE                     3
 #endif
 
+#ifndef EM_AARCH64
+#define EM_AARCH64	183
+#define R_AARCH64_ABS64	257
+#endif
+
 static int fd_map;	/* File descriptor for file being modified. */
 static int mmap_failed; /* Boolean flag. */
 static void *ehdr_curr; /* current ElfXX_Ehdr *  for resource cleanup */
@@ -347,6 +352,8 @@ do_file(char const *const fname)
 	case EM_ARM:	 reltype = R_ARM_ABS32;
 			 altmcount = "__gnu_mcount_nc";
 			 break;
+	case EM_AARCH64:
+			 reltype = R_AARCH64_ABS64; gpfx = '_'; break;
 	case EM_IA_64:	 reltype = R_IA64_IMM64;   gpfx = '_'; break;
 	case EM_METAG:	 reltype = R_METAG_ADDR32;
 			 altmcount = "_mcount_wrapper";
diff --git a/scripts/recordmcount.pl b/scripts/recordmcount.pl
index 91280b8..397b6b8 100755
--- a/scripts/recordmcount.pl
+++ b/scripts/recordmcount.pl
@@ -279,6 +279,11 @@ if ($arch eq "x86_64") {
     $mcount_regex = "^\\s*([0-9a-fA-F]+):\\s*R_ARM_(CALL|PC24|THM_CALL)" .
 			"\\s+(__gnu_mcount_nc|mcount)\$";
 
+} elsif ($arch eq "arm64") {
+    $alignment = 3;
+    $section_type = '%progbits';
+    $mcount_regex = "^\\s*([0-9a-fA-F]+):\\s*R_AARCH64_CALL26\\s+_mcount\$";
+    $type = ".quad";
 } elsif ($arch eq "ia64") {
     $mcount_regex = "^\\s*([0-9a-fA-F]+):.*\\s_mcount\$";
     $type = "data8";
-- 
1.8.3.2


^ permalink raw reply related	[flat|nested] 235+ messages in thread

* [PATCH v7 3/7] ftrace: Add arm64 support to recordmcount
@ 2014-03-15  5:40             ` AKASHI Takahiro
  0 siblings, 0 replies; 235+ messages in thread
From: AKASHI Takahiro @ 2014-03-15  5:40 UTC (permalink / raw)
  To: linux-arm-kernel

Recordmcount utility under scripts is run, after compiling each object,
to find out all the locations of calling _mcount() and put them into
specific seciton named __mcount_loc.
Then linker collects all such information into a table in the kernel image
(between __start_mcount_loc and __stop_mcount_loc) for later use by ftrace.

This patch adds arm64 specific definitions to identify such locations.
There are two types of implementation, C and Perl. On arm64, only C version
is used to build the kernel now that CONFIG_HAVE_C_RECORDMCOUNT is on.
But Perl version is also maintained.

This patch also contains a workaround just in case where a header file,
elf.h, on host machine doesn't have definitions of EM_AARCH64 nor
R_AARCH64_ABS64. Without them, compiling C version of recordmcount will
fail.

Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
---
 arch/arm64/Kconfig      | 2 ++
 scripts/recordmcount.c  | 7 +++++++
 scripts/recordmcount.pl | 5 +++++
 3 files changed, 14 insertions(+)

diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 27bbcfc..340e344 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -27,12 +27,14 @@ config ARM64
 	select HARDIRQS_SW_RESEND
 	select HAVE_ARCH_JUMP_LABEL
 	select HAVE_ARCH_TRACEHOOK
+	select HAVE_C_RECORDMCOUNT
 	select HAVE_DEBUG_BUGVERBOSE
 	select HAVE_DEBUG_KMEMLEAK
 	select HAVE_DMA_API_DEBUG
 	select HAVE_DMA_ATTRS
 	select HAVE_DMA_CONTIGUOUS
 	select HAVE_EFFICIENT_UNALIGNED_ACCESS
+	select HAVE_FTRACE_MCOUNT_RECORD
 	select HAVE_GENERIC_DMA_COHERENT
 	select HAVE_HW_BREAKPOINT if PERF_EVENTS
 	select HAVE_MEMBLOCK
diff --git a/scripts/recordmcount.c b/scripts/recordmcount.c
index 9c22317..e11aa4a 100644
--- a/scripts/recordmcount.c
+++ b/scripts/recordmcount.c
@@ -40,6 +40,11 @@
 #define R_METAG_NONE                     3
 #endif
 
+#ifndef EM_AARCH64
+#define EM_AARCH64	183
+#define R_AARCH64_ABS64	257
+#endif
+
 static int fd_map;	/* File descriptor for file being modified. */
 static int mmap_failed; /* Boolean flag. */
 static void *ehdr_curr; /* current ElfXX_Ehdr *  for resource cleanup */
@@ -347,6 +352,8 @@ do_file(char const *const fname)
 	case EM_ARM:	 reltype = R_ARM_ABS32;
 			 altmcount = "__gnu_mcount_nc";
 			 break;
+	case EM_AARCH64:
+			 reltype = R_AARCH64_ABS64; gpfx = '_'; break;
 	case EM_IA_64:	 reltype = R_IA64_IMM64;   gpfx = '_'; break;
 	case EM_METAG:	 reltype = R_METAG_ADDR32;
 			 altmcount = "_mcount_wrapper";
diff --git a/scripts/recordmcount.pl b/scripts/recordmcount.pl
index 91280b8..397b6b8 100755
--- a/scripts/recordmcount.pl
+++ b/scripts/recordmcount.pl
@@ -279,6 +279,11 @@ if ($arch eq "x86_64") {
     $mcount_regex = "^\\s*([0-9a-fA-F]+):\\s*R_ARM_(CALL|PC24|THM_CALL)" .
 			"\\s+(__gnu_mcount_nc|mcount)\$";
 
+} elsif ($arch eq "arm64") {
+    $alignment = 3;
+    $section_type = '%progbits';
+    $mcount_regex = "^\\s*([0-9a-fA-F]+):\\s*R_AARCH64_CALL26\\s+_mcount\$";
+    $type = ".quad";
 } elsif ($arch eq "ia64") {
     $mcount_regex = "^\\s*([0-9a-fA-F]+):.*\\s_mcount\$";
     $type = "data8";
-- 
1.8.3.2

^ permalink raw reply related	[flat|nested] 235+ messages in thread

* [PATCH v7 4/7] arm64: Add ftrace support
  2014-03-13 10:13         ` AKASHI Takahiro
@ 2014-03-15  5:45           ` AKASHI Takahiro
  -1 siblings, 0 replies; 235+ messages in thread
From: AKASHI Takahiro @ 2014-03-15  5:45 UTC (permalink / raw)
  To: rostedt, fweisbec, mingo, catalin.marinas, will.deacon, tim.bird
  Cc: gkulkarni, dsaxena, arndb, linux-arm-kernel, linaro-kernel,
	linux-kernel, AKASHI Takahiro

This patch implements arm64 specific part to support function tracers,
such as function (CONFIG_FUNCTION_TRACER), function_graph
(CONFIG_FUNCTION_GRAPH_TRACER) and function profiler
(CONFIG_FUNCTION_PROFILER).

With 'function' tracer, all the functions in the kernel are traced with
timestamps in ${sysfs}/tracing/trace. If function_graph tracer is
specified, call graph is generated.

The kernel must be compiled with -pg option so that _mcount() is inserted
at the beginning of functions. This function is called on every function's
entry as long as tracing is enabled.
In addition, function_graph tracer also needs to be able to probe function's
exit. ftrace_graph_caller() & return_to_handler do this by faking link
register's value to intercept function's return path.

More details on architecture specific requirements are described in
Documentation/trace/ftrace-design.txt.

Reviewed-by: Ganapatrao Kulkarni <ganapatrao.kulkarni@cavium.com>
Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
---
 arch/arm64/Kconfig               |   2 +
 arch/arm64/include/asm/ftrace.h  |  23 +++++
 arch/arm64/kernel/Makefile       |   4 +
 arch/arm64/kernel/arm64ksyms.c   |   4 +
 arch/arm64/kernel/entry-ftrace.S | 175 +++++++++++++++++++++++++++++++++++++++
 arch/arm64/kernel/ftrace.c       |  64 ++++++++++++++
 6 files changed, 272 insertions(+)
 create mode 100644 arch/arm64/include/asm/ftrace.h
 create mode 100644 arch/arm64/kernel/entry-ftrace.S
 create mode 100644 arch/arm64/kernel/ftrace.c

diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 340e344..6b3fef6 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -35,6 +35,8 @@ config ARM64
 	select HAVE_DMA_CONTIGUOUS
 	select HAVE_EFFICIENT_UNALIGNED_ACCESS
 	select HAVE_FTRACE_MCOUNT_RECORD
+	select HAVE_FUNCTION_TRACER
+	select HAVE_FUNCTION_GRAPH_TRACER
 	select HAVE_GENERIC_DMA_COHERENT
 	select HAVE_HW_BREAKPOINT if PERF_EVENTS
 	select HAVE_MEMBLOCK
diff --git a/arch/arm64/include/asm/ftrace.h b/arch/arm64/include/asm/ftrace.h
new file mode 100644
index 0000000..58ea595
--- /dev/null
+++ b/arch/arm64/include/asm/ftrace.h
@@ -0,0 +1,23 @@
+/*
+ * arch/arm64/include/asm/ftrace.h
+ *
+ * Copyright (C) 2013 Linaro Limited
+ * Author: AKASHI Takahiro <takahiro.akashi@linaro.org>
+ *
+ * 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.
+ */
+#ifndef __ASM_FTRACE_H
+#define __ASM_FTRACE_H
+
+#include <asm/insn.h>
+
+#define MCOUNT_ADDR		((unsigned long)_mcount)
+#define MCOUNT_INSN_SIZE	AARCH64_INSN_SIZE
+
+#ifndef __ASSEMBLY__
+extern void _mcount(unsigned long);
+#endif /* __ASSEMBLY__ */
+
+#endif /* __ASM_FTRACE_H */
diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile
index 2d4554b..ac67fd0 100644
--- a/arch/arm64/kernel/Makefile
+++ b/arch/arm64/kernel/Makefile
@@ -5,6 +5,9 @@
 CPPFLAGS_vmlinux.lds	:= -DTEXT_OFFSET=$(TEXT_OFFSET)
 AFLAGS_head.o		:= -DTEXT_OFFSET=$(TEXT_OFFSET)
 
+CFLAGS_REMOVE_ftrace.o = -pg
+CFLAGS_REMOVE_insn.o = -pg
+
 # Object file lists.
 arm64-obj-y		:= cputable.o debug-monitors.o entry.o irq.o fpsimd.o	\
 			   entry-fpsimd.o process.o ptrace.o setup.o signal.o	\
@@ -13,6 +16,7 @@ arm64-obj-y		:= cputable.o debug-monitors.o entry.o irq.o fpsimd.o	\
 
 arm64-obj-$(CONFIG_COMPAT)		+= sys32.o kuser32.o signal32.o 	\
 					   sys_compat.o
+arm64-obj-$(CONFIG_FUNCTION_TRACER)	+= ftrace.o entry-ftrace.o
 arm64-obj-$(CONFIG_MODULES)		+= arm64ksyms.o module.o
 arm64-obj-$(CONFIG_SMP)			+= smp.o smp_spin_table.o
 arm64-obj-$(CONFIG_HW_PERF_EVENTS)	+= perf_event.o
diff --git a/arch/arm64/kernel/arm64ksyms.c b/arch/arm64/kernel/arm64ksyms.c
index 338b568..7f0512f 100644
--- a/arch/arm64/kernel/arm64ksyms.c
+++ b/arch/arm64/kernel/arm64ksyms.c
@@ -56,3 +56,7 @@ EXPORT_SYMBOL(clear_bit);
 EXPORT_SYMBOL(test_and_clear_bit);
 EXPORT_SYMBOL(change_bit);
 EXPORT_SYMBOL(test_and_change_bit);
+
+#ifdef CONFIG_FUNCTION_TRACER
+EXPORT_SYMBOL(_mcount);
+#endif
diff --git a/arch/arm64/kernel/entry-ftrace.S b/arch/arm64/kernel/entry-ftrace.S
new file mode 100644
index 0000000..622846f
--- /dev/null
+++ b/arch/arm64/kernel/entry-ftrace.S
@@ -0,0 +1,175 @@
+/*
+ * arch/arm64/kernel/entry-ftrace.S
+ *
+ * Copyright (C) 2013 Linaro Limited
+ * Author: AKASHI Takahiro <takahiro.akashi@linaro.org>
+ *
+ * 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 <linux/linkage.h>
+#include <asm/ftrace.h>
+#include <asm/insn.h>
+
+/*
+ * Gcc with -pg will put the following code in the beginning of each function:
+ *      mov x0, x30
+ *      bl _mcount
+ *	[function's body ...]
+ * "bl _mcount" may be replaced to "bl ftrace_caller" or NOP if dynamic
+ * ftrace is enabled.
+ *
+ * Please note that x0 as an argument will not be used here because we can
+ * get lr(x30) of instrumented function at any time by winding up call stack
+ * as long as the kernel is compiled without -fomit-frame-pointer.
+ * (or CONFIG_FRAME_POINTER, this is forced on arm64)
+ *
+ * stack layout after mcount_enter in _mcount():
+ *
+ * current sp/fp =>  0:+-----+
+ * in _mcount()	       | x29 | -> instrumented function's fp
+ *		       +-----+
+ *		       | x30 | -> _mcount()'s lr (= instrumented function's pc)
+ * old sp	=> +16:+-----+
+ * when instrumented   |     |
+ * function calls      | ... |
+ * _mcount()	       |     |
+ *		       |     |
+ * instrumented => +xx:+-----+
+ * function's fp       | x29 | -> parent's fp
+ *		       +-----+
+ *		       | x30 | -> instrumented function's lr (= parent's pc)
+ *		       +-----+
+ *		       | ... |
+ */
+
+	.macro mcount_enter
+	stp	x29, x30, [sp, #-16]!
+	mov	x29, sp
+	.endm
+
+	.macro mcount_exit
+	ldp	x29, x30, [sp], #16
+	ret
+	.endm
+
+	.macro mcount_adjust_addr rd, rn
+	sub	\rd, \rn, #AARCH64_INSN_SIZE
+	.endm
+
+	/* for instrumented function's parent */
+	.macro mcount_get_parent_fp reg
+	ldr	\reg, [x29]
+	ldr	\reg, [\reg]
+	.endm
+
+	/* for instrumented function */
+	.macro mcount_get_pc0 reg
+	mcount_adjust_addr	\reg, x30
+	.endm
+
+	.macro mcount_get_pc reg
+	ldr	\reg, [x29, #8]
+	mcount_adjust_addr	\reg, \reg
+	.endm
+
+	.macro mcount_get_lr reg
+	ldr	\reg, [x29]
+	ldr	\reg, [\reg, #8]
+	mcount_adjust_addr	\reg, \reg
+	.endm
+
+	.macro mcount_get_lr_addr reg
+	ldr	\reg, [x29]
+	add	\reg, \reg, #8
+	.endm
+
+/*
+ * void _mcount(unsigned long return_address)
+ * @return_address: return address to instrumented function
+ *
+ * This function makes calls, if enabled, to:
+ *     - tracer function to probe instrumented function's entry,
+ *     - ftrace_graph_caller to set up an exit hook
+ */
+ENTRY(_mcount)
+#ifdef CONFIG_HAVE_FUNCTION_TRACE_MCOUNT_TEST
+	ldr	x0, =ftrace_trace_stop
+	ldr	x0, [x0]		// if ftrace_trace_stop
+	ret				//   return;
+#endif
+	mcount_enter
+
+	ldr	x0, =ftrace_trace_function
+	ldr	x2, [x0]
+	adr	x0, ftrace_stub
+	cmp	x0, x2			// if (ftrace_trace_function
+	b.eq	skip_ftrace_call	//     != ftrace_stub) {
+
+	mcount_get_pc	x0		//       function's pc
+	mcount_get_lr	x1		//       function's lr (= parent's pc)
+	blr	x2			//   (*ftrace_trace_function)(pc, lr);
+
+#ifndef CONFIG_FUNCTION_GRAPH_TRACER
+skip_ftrace_call:			//   return;
+	mcount_exit			// }
+#else
+	mcount_exit			//   return;
+					// }
+skip_ftrace_call:
+	ldr	x1, =ftrace_graph_return
+	ldr	x2, [x1]		//   if ((ftrace_graph_return
+	cmp	x0, x2			//        != ftrace_stub)
+	b.ne	ftrace_graph_caller
+
+	ldr	x1, =ftrace_graph_entry	//     || (ftrace_graph_entry
+	ldr	x2, [x1]		//        != ftrace_graph_entry_stub))
+	ldr	x0, =ftrace_graph_entry_stub
+	cmp	x0, x2
+	b.ne	ftrace_graph_caller	//     ftrace_graph_caller();
+
+	mcount_exit
+#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
+ENDPROC(_mcount)
+
+ENTRY(ftrace_stub)
+	ret
+ENDPROC(ftrace_stub)
+
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+/*
+ * void ftrace_graph_caller(void)
+ *
+ * Called from _mcount() or ftrace_caller() when function_graph tracer is
+ * selected.
+ * This function w/ prepare_ftrace_return() fakes link register's value on
+ * the call stack in order to intercept instrumented function's return path
+ * and run return_to_handler() later on its exit.
+ */
+ENTRY(ftrace_graph_caller)
+	mcount_get_lr_addr	  x0	//     pointer to function's saved lr
+	mcount_get_pc		  x1	//     function's pc
+	mcount_get_parent_fp	  x2	//     parent's fp
+	bl	prepare_ftrace_return	// prepare_ftrace_return(&lr, pc, fp)
+
+	mcount_exit
+ENDPROC(ftrace_graph_caller)
+
+/*
+ * void return_to_handler(void)
+ *
+ * Run ftrace_return_to_handler() before going back to parent.
+ * @fp is checked against the value passed by ftrace_graph_caller()
+ * only when CONFIG_FUNCTION_GRAPH_FP_TEST is enabled.
+ */
+ENTRY(return_to_handler)
+	str	x0, [sp, #-16]!
+	mov	x0, x29			//     parent's fp
+	bl	ftrace_return_to_handler// addr = ftrace_return_to_hander(fp);
+	mov	x30, x0			// restore the original return address
+	ldr	x0, [sp], #16
+	ret
+END(return_to_handler)
+#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
diff --git a/arch/arm64/kernel/ftrace.c b/arch/arm64/kernel/ftrace.c
new file mode 100644
index 0000000..a559ab8
--- /dev/null
+++ b/arch/arm64/kernel/ftrace.c
@@ -0,0 +1,64 @@
+/*
+ * arch/arm64/kernel/ftrace.c
+ *
+ * Copyright (C) 2013 Linaro Limited
+ * Author: AKASHI Takahiro <takahiro.akashi@linaro.org>
+ *
+ * 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 <linux/ftrace.h>
+#include <linux/swab.h>
+#include <linux/uaccess.h>
+
+#include <asm/cacheflush.h>
+#include <asm/ftrace.h>
+#include <asm/insn.h>
+
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+/*
+ * function_graph tracer expects ftrace_return_to_handler() to be called
+ * on the way back to parent. For this purpose, this function is called
+ * in _mcount() or ftrace_caller() to replace return address (*parent) on
+ * the call stack to return_to_handler.
+ *
+ * Note that @frame_pointer is used only for sanity check later.
+ */
+void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr,
+			   unsigned long frame_pointer)
+{
+	unsigned long return_hooker = (unsigned long)&return_to_handler;
+	unsigned long old;
+	struct ftrace_graph_ent trace;
+	int err;
+
+	if (unlikely(atomic_read(&current->tracing_graph_pause)))
+		return;
+
+	/*
+	 * Note:
+	 * No protection against faulting at *parent, which may be seen
+	 * on other archs. It's unlikely on AArch64.
+	 */
+	old = *parent;
+	*parent = return_hooker;
+
+	trace.func = self_addr;
+	trace.depth = current->curr_ret_stack + 1;
+
+	/* Only trace if the calling function expects to */
+	if (!ftrace_graph_entry(&trace)) {
+		*parent = old;
+		return;
+	}
+
+	err = ftrace_push_return_trace(old, self_addr, &trace.depth,
+				       frame_pointer);
+	if (err == -EBUSY) {
+		*parent = old;
+		return;
+	}
+}
+#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
-- 
1.8.3.2


^ permalink raw reply related	[flat|nested] 235+ messages in thread

* [PATCH v7 4/7] arm64: Add ftrace support
@ 2014-03-15  5:45           ` AKASHI Takahiro
  0 siblings, 0 replies; 235+ messages in thread
From: AKASHI Takahiro @ 2014-03-15  5:45 UTC (permalink / raw)
  To: linux-arm-kernel

This patch implements arm64 specific part to support function tracers,
such as function (CONFIG_FUNCTION_TRACER), function_graph
(CONFIG_FUNCTION_GRAPH_TRACER) and function profiler
(CONFIG_FUNCTION_PROFILER).

With 'function' tracer, all the functions in the kernel are traced with
timestamps in ${sysfs}/tracing/trace. If function_graph tracer is
specified, call graph is generated.

The kernel must be compiled with -pg option so that _mcount() is inserted
at the beginning of functions. This function is called on every function's
entry as long as tracing is enabled.
In addition, function_graph tracer also needs to be able to probe function's
exit. ftrace_graph_caller() & return_to_handler do this by faking link
register's value to intercept function's return path.

More details on architecture specific requirements are described in
Documentation/trace/ftrace-design.txt.

Reviewed-by: Ganapatrao Kulkarni <ganapatrao.kulkarni@cavium.com>
Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
---
 arch/arm64/Kconfig               |   2 +
 arch/arm64/include/asm/ftrace.h  |  23 +++++
 arch/arm64/kernel/Makefile       |   4 +
 arch/arm64/kernel/arm64ksyms.c   |   4 +
 arch/arm64/kernel/entry-ftrace.S | 175 +++++++++++++++++++++++++++++++++++++++
 arch/arm64/kernel/ftrace.c       |  64 ++++++++++++++
 6 files changed, 272 insertions(+)
 create mode 100644 arch/arm64/include/asm/ftrace.h
 create mode 100644 arch/arm64/kernel/entry-ftrace.S
 create mode 100644 arch/arm64/kernel/ftrace.c

diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 340e344..6b3fef6 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -35,6 +35,8 @@ config ARM64
 	select HAVE_DMA_CONTIGUOUS
 	select HAVE_EFFICIENT_UNALIGNED_ACCESS
 	select HAVE_FTRACE_MCOUNT_RECORD
+	select HAVE_FUNCTION_TRACER
+	select HAVE_FUNCTION_GRAPH_TRACER
 	select HAVE_GENERIC_DMA_COHERENT
 	select HAVE_HW_BREAKPOINT if PERF_EVENTS
 	select HAVE_MEMBLOCK
diff --git a/arch/arm64/include/asm/ftrace.h b/arch/arm64/include/asm/ftrace.h
new file mode 100644
index 0000000..58ea595
--- /dev/null
+++ b/arch/arm64/include/asm/ftrace.h
@@ -0,0 +1,23 @@
+/*
+ * arch/arm64/include/asm/ftrace.h
+ *
+ * Copyright (C) 2013 Linaro Limited
+ * Author: AKASHI Takahiro <takahiro.akashi@linaro.org>
+ *
+ * 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.
+ */
+#ifndef __ASM_FTRACE_H
+#define __ASM_FTRACE_H
+
+#include <asm/insn.h>
+
+#define MCOUNT_ADDR		((unsigned long)_mcount)
+#define MCOUNT_INSN_SIZE	AARCH64_INSN_SIZE
+
+#ifndef __ASSEMBLY__
+extern void _mcount(unsigned long);
+#endif /* __ASSEMBLY__ */
+
+#endif /* __ASM_FTRACE_H */
diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile
index 2d4554b..ac67fd0 100644
--- a/arch/arm64/kernel/Makefile
+++ b/arch/arm64/kernel/Makefile
@@ -5,6 +5,9 @@
 CPPFLAGS_vmlinux.lds	:= -DTEXT_OFFSET=$(TEXT_OFFSET)
 AFLAGS_head.o		:= -DTEXT_OFFSET=$(TEXT_OFFSET)
 
+CFLAGS_REMOVE_ftrace.o = -pg
+CFLAGS_REMOVE_insn.o = -pg
+
 # Object file lists.
 arm64-obj-y		:= cputable.o debug-monitors.o entry.o irq.o fpsimd.o	\
 			   entry-fpsimd.o process.o ptrace.o setup.o signal.o	\
@@ -13,6 +16,7 @@ arm64-obj-y		:= cputable.o debug-monitors.o entry.o irq.o fpsimd.o	\
 
 arm64-obj-$(CONFIG_COMPAT)		+= sys32.o kuser32.o signal32.o 	\
 					   sys_compat.o
+arm64-obj-$(CONFIG_FUNCTION_TRACER)	+= ftrace.o entry-ftrace.o
 arm64-obj-$(CONFIG_MODULES)		+= arm64ksyms.o module.o
 arm64-obj-$(CONFIG_SMP)			+= smp.o smp_spin_table.o
 arm64-obj-$(CONFIG_HW_PERF_EVENTS)	+= perf_event.o
diff --git a/arch/arm64/kernel/arm64ksyms.c b/arch/arm64/kernel/arm64ksyms.c
index 338b568..7f0512f 100644
--- a/arch/arm64/kernel/arm64ksyms.c
+++ b/arch/arm64/kernel/arm64ksyms.c
@@ -56,3 +56,7 @@ EXPORT_SYMBOL(clear_bit);
 EXPORT_SYMBOL(test_and_clear_bit);
 EXPORT_SYMBOL(change_bit);
 EXPORT_SYMBOL(test_and_change_bit);
+
+#ifdef CONFIG_FUNCTION_TRACER
+EXPORT_SYMBOL(_mcount);
+#endif
diff --git a/arch/arm64/kernel/entry-ftrace.S b/arch/arm64/kernel/entry-ftrace.S
new file mode 100644
index 0000000..622846f
--- /dev/null
+++ b/arch/arm64/kernel/entry-ftrace.S
@@ -0,0 +1,175 @@
+/*
+ * arch/arm64/kernel/entry-ftrace.S
+ *
+ * Copyright (C) 2013 Linaro Limited
+ * Author: AKASHI Takahiro <takahiro.akashi@linaro.org>
+ *
+ * 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 <linux/linkage.h>
+#include <asm/ftrace.h>
+#include <asm/insn.h>
+
+/*
+ * Gcc with -pg will put the following code in the beginning of each function:
+ *      mov x0, x30
+ *      bl _mcount
+ *	[function's body ...]
+ * "bl _mcount" may be replaced to "bl ftrace_caller" or NOP if dynamic
+ * ftrace is enabled.
+ *
+ * Please note that x0 as an argument will not be used here because we can
+ * get lr(x30) of instrumented function at any time by winding up call stack
+ * as long as the kernel is compiled without -fomit-frame-pointer.
+ * (or CONFIG_FRAME_POINTER, this is forced on arm64)
+ *
+ * stack layout after mcount_enter in _mcount():
+ *
+ * current sp/fp =>  0:+-----+
+ * in _mcount()	       | x29 | -> instrumented function's fp
+ *		       +-----+
+ *		       | x30 | -> _mcount()'s lr (= instrumented function's pc)
+ * old sp	=> +16:+-----+
+ * when instrumented   |     |
+ * function calls      | ... |
+ * _mcount()	       |     |
+ *		       |     |
+ * instrumented => +xx:+-----+
+ * function's fp       | x29 | -> parent's fp
+ *		       +-----+
+ *		       | x30 | -> instrumented function's lr (= parent's pc)
+ *		       +-----+
+ *		       | ... |
+ */
+
+	.macro mcount_enter
+	stp	x29, x30, [sp, #-16]!
+	mov	x29, sp
+	.endm
+
+	.macro mcount_exit
+	ldp	x29, x30, [sp], #16
+	ret
+	.endm
+
+	.macro mcount_adjust_addr rd, rn
+	sub	\rd, \rn, #AARCH64_INSN_SIZE
+	.endm
+
+	/* for instrumented function's parent */
+	.macro mcount_get_parent_fp reg
+	ldr	\reg, [x29]
+	ldr	\reg, [\reg]
+	.endm
+
+	/* for instrumented function */
+	.macro mcount_get_pc0 reg
+	mcount_adjust_addr	\reg, x30
+	.endm
+
+	.macro mcount_get_pc reg
+	ldr	\reg, [x29, #8]
+	mcount_adjust_addr	\reg, \reg
+	.endm
+
+	.macro mcount_get_lr reg
+	ldr	\reg, [x29]
+	ldr	\reg, [\reg, #8]
+	mcount_adjust_addr	\reg, \reg
+	.endm
+
+	.macro mcount_get_lr_addr reg
+	ldr	\reg, [x29]
+	add	\reg, \reg, #8
+	.endm
+
+/*
+ * void _mcount(unsigned long return_address)
+ * @return_address: return address to instrumented function
+ *
+ * This function makes calls, if enabled, to:
+ *     - tracer function to probe instrumented function's entry,
+ *     - ftrace_graph_caller to set up an exit hook
+ */
+ENTRY(_mcount)
+#ifdef CONFIG_HAVE_FUNCTION_TRACE_MCOUNT_TEST
+	ldr	x0, =ftrace_trace_stop
+	ldr	x0, [x0]		// if ftrace_trace_stop
+	ret				//   return;
+#endif
+	mcount_enter
+
+	ldr	x0, =ftrace_trace_function
+	ldr	x2, [x0]
+	adr	x0, ftrace_stub
+	cmp	x0, x2			// if (ftrace_trace_function
+	b.eq	skip_ftrace_call	//     != ftrace_stub) {
+
+	mcount_get_pc	x0		//       function's pc
+	mcount_get_lr	x1		//       function's lr (= parent's pc)
+	blr	x2			//   (*ftrace_trace_function)(pc, lr);
+
+#ifndef CONFIG_FUNCTION_GRAPH_TRACER
+skip_ftrace_call:			//   return;
+	mcount_exit			// }
+#else
+	mcount_exit			//   return;
+					// }
+skip_ftrace_call:
+	ldr	x1, =ftrace_graph_return
+	ldr	x2, [x1]		//   if ((ftrace_graph_return
+	cmp	x0, x2			//        != ftrace_stub)
+	b.ne	ftrace_graph_caller
+
+	ldr	x1, =ftrace_graph_entry	//     || (ftrace_graph_entry
+	ldr	x2, [x1]		//        != ftrace_graph_entry_stub))
+	ldr	x0, =ftrace_graph_entry_stub
+	cmp	x0, x2
+	b.ne	ftrace_graph_caller	//     ftrace_graph_caller();
+
+	mcount_exit
+#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
+ENDPROC(_mcount)
+
+ENTRY(ftrace_stub)
+	ret
+ENDPROC(ftrace_stub)
+
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+/*
+ * void ftrace_graph_caller(void)
+ *
+ * Called from _mcount() or ftrace_caller() when function_graph tracer is
+ * selected.
+ * This function w/ prepare_ftrace_return() fakes link register's value on
+ * the call stack in order to intercept instrumented function's return path
+ * and run return_to_handler() later on its exit.
+ */
+ENTRY(ftrace_graph_caller)
+	mcount_get_lr_addr	  x0	//     pointer to function's saved lr
+	mcount_get_pc		  x1	//     function's pc
+	mcount_get_parent_fp	  x2	//     parent's fp
+	bl	prepare_ftrace_return	// prepare_ftrace_return(&lr, pc, fp)
+
+	mcount_exit
+ENDPROC(ftrace_graph_caller)
+
+/*
+ * void return_to_handler(void)
+ *
+ * Run ftrace_return_to_handler() before going back to parent.
+ * @fp is checked against the value passed by ftrace_graph_caller()
+ * only when CONFIG_FUNCTION_GRAPH_FP_TEST is enabled.
+ */
+ENTRY(return_to_handler)
+	str	x0, [sp, #-16]!
+	mov	x0, x29			//     parent's fp
+	bl	ftrace_return_to_handler// addr = ftrace_return_to_hander(fp);
+	mov	x30, x0			// restore the original return address
+	ldr	x0, [sp], #16
+	ret
+END(return_to_handler)
+#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
diff --git a/arch/arm64/kernel/ftrace.c b/arch/arm64/kernel/ftrace.c
new file mode 100644
index 0000000..a559ab8
--- /dev/null
+++ b/arch/arm64/kernel/ftrace.c
@@ -0,0 +1,64 @@
+/*
+ * arch/arm64/kernel/ftrace.c
+ *
+ * Copyright (C) 2013 Linaro Limited
+ * Author: AKASHI Takahiro <takahiro.akashi@linaro.org>
+ *
+ * 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 <linux/ftrace.h>
+#include <linux/swab.h>
+#include <linux/uaccess.h>
+
+#include <asm/cacheflush.h>
+#include <asm/ftrace.h>
+#include <asm/insn.h>
+
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+/*
+ * function_graph tracer expects ftrace_return_to_handler() to be called
+ * on the way back to parent. For this purpose, this function is called
+ * in _mcount() or ftrace_caller() to replace return address (*parent) on
+ * the call stack to return_to_handler.
+ *
+ * Note that @frame_pointer is used only for sanity check later.
+ */
+void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr,
+			   unsigned long frame_pointer)
+{
+	unsigned long return_hooker = (unsigned long)&return_to_handler;
+	unsigned long old;
+	struct ftrace_graph_ent trace;
+	int err;
+
+	if (unlikely(atomic_read(&current->tracing_graph_pause)))
+		return;
+
+	/*
+	 * Note:
+	 * No protection against faulting at *parent, which may be seen
+	 * on other archs. It's unlikely on AArch64.
+	 */
+	old = *parent;
+	*parent = return_hooker;
+
+	trace.func = self_addr;
+	trace.depth = current->curr_ret_stack + 1;
+
+	/* Only trace if the calling function expects to */
+	if (!ftrace_graph_entry(&trace)) {
+		*parent = old;
+		return;
+	}
+
+	err = ftrace_push_return_trace(old, self_addr, &trace.depth,
+				       frame_pointer);
+	if (err == -EBUSY) {
+		*parent = old;
+		return;
+	}
+}
+#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
-- 
1.8.3.2

^ permalink raw reply related	[flat|nested] 235+ messages in thread

* [PATCH v7 5/7] arm64: ftrace: Add dynamic ftrace support
  2014-03-13 10:13         ` AKASHI Takahiro
@ 2014-03-15  5:45           ` AKASHI Takahiro
  -1 siblings, 0 replies; 235+ messages in thread
From: AKASHI Takahiro @ 2014-03-15  5:45 UTC (permalink / raw)
  To: rostedt, fweisbec, mingo, catalin.marinas, will.deacon, tim.bird
  Cc: gkulkarni, dsaxena, arndb, linux-arm-kernel, linaro-kernel,
	linux-kernel, AKASHI Takahiro

This patch allows "dynamic ftrace" if CONFIG_DYNAMIC_FTRACE is enabled.
Here we can turn on and off tracing dynamically per-function base.

On arm64, this is done by patching single branch instruction to _mcount()
inserted by gcc -pg option. The branch is replaced to NOP initially at
kernel start up, and later on, NOP to branch to ftrace_caller() when
enabled or branch to NOP when disabled.
Please note that ftrace_caller() is a counterpart of _mcount() in case of
'static' ftrace.

More details on architecture specific requirements are described in
Documentation/trace/ftrace-design.txt.

Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
---
 arch/arm64/Kconfig               |   1 +
 arch/arm64/include/asm/ftrace.h  |  15 ++++++
 arch/arm64/kernel/entry-ftrace.S |  43 +++++++++++++++
 arch/arm64/kernel/ftrace.c       | 114 +++++++++++++++++++++++++++++++++++++++
 4 files changed, 173 insertions(+)

diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 6b3fef6..6954959 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -33,6 +33,7 @@ config ARM64
 	select HAVE_DMA_API_DEBUG
 	select HAVE_DMA_ATTRS
 	select HAVE_DMA_CONTIGUOUS
+	select HAVE_DYNAMIC_FTRACE
 	select HAVE_EFFICIENT_UNALIGNED_ACCESS
 	select HAVE_FTRACE_MCOUNT_RECORD
 	select HAVE_FUNCTION_TRACER
diff --git a/arch/arm64/include/asm/ftrace.h b/arch/arm64/include/asm/ftrace.h
index 58ea595..ed5c448 100644
--- a/arch/arm64/include/asm/ftrace.h
+++ b/arch/arm64/include/asm/ftrace.h
@@ -18,6 +18,21 @@
 
 #ifndef __ASSEMBLY__
 extern void _mcount(unsigned long);
+
+struct dyn_arch_ftrace {
+	/* No extra data needed for arm64 */
+};
+
+extern unsigned long ftrace_graph_call;
+
+static inline unsigned long ftrace_call_adjust(unsigned long addr)
+{
+	/*
+	 * addr is the address of the mcount call instruction.
+	 * recordmcount does the necessary offset calculation.
+	 */
+	return addr;
+}
 #endif /* __ASSEMBLY__ */
 
 #endif /* __ASM_FTRACE_H */
diff --git a/arch/arm64/kernel/entry-ftrace.S b/arch/arm64/kernel/entry-ftrace.S
index 622846f..d0cad6d 100644
--- a/arch/arm64/kernel/entry-ftrace.S
+++ b/arch/arm64/kernel/entry-ftrace.S
@@ -86,6 +86,7 @@
 	add	\reg, \reg, #8
 	.endm
 
+#ifndef CONFIG_DYNAMIC_FTRACE
 /*
  * void _mcount(unsigned long return_address)
  * @return_address: return address to instrumented function
@@ -134,6 +135,48 @@ skip_ftrace_call:
 #endif /* CONFIG_FUNCTION_GRAPH_TRACER */
 ENDPROC(_mcount)
 
+#else /* CONFIG_DYNAMIC_FTRACE */
+/*
+ * _mcount() is used to build the kernel with -pg option, but all the branch
+ * instructions to _mcount() are replaced to NOP initially at kernel start up,
+ * and later on, NOP to branch to ftrace_caller() when enabled or branch to
+ * NOP when disabled per-function base.
+ */
+ENTRY(_mcount)
+	ret
+ENDPROC(_mcount)
+
+/*
+ * void ftrace_caller(unsigned long return_address)
+ * @return_address: return address to instrumented function
+ *
+ * This function is a counterpart of _mcount() in 'static' ftrace, and
+ * makes calls to:
+ *     - tracer function to probe instrumented function's entry,
+ *     - ftrace_graph_caller to set up an exit hook
+ */
+ENTRY(ftrace_caller)
+	mcount_enter
+
+	mcount_get_pc0	x0		//     function's pc
+	mcount_get_lr	x1		//     function's lr
+
+	.global ftrace_call
+ftrace_call:				// tracer(pc, lr);
+	nop				// This will be replaced with "bl xxx"
+					// where xxx can be any kind of tracer.
+
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+	.global ftrace_graph_call
+ftrace_graph_call:			// ftrace_graph_caller();
+	nop				// If enabled, this will be replaced
+					// "b ftrace_graph_caller"
+#endif
+
+	mcount_exit
+ENDPROC(ftrace_caller)
+#endif /* CONFIG_DYNAMIC_FTRACE */
+
 ENTRY(ftrace_stub)
 	ret
 ENDPROC(ftrace_stub)
diff --git a/arch/arm64/kernel/ftrace.c b/arch/arm64/kernel/ftrace.c
index a559ab8..9f708e7 100644
--- a/arch/arm64/kernel/ftrace.c
+++ b/arch/arm64/kernel/ftrace.c
@@ -17,6 +17,89 @@
 #include <asm/ftrace.h>
 #include <asm/insn.h>
 
+#ifdef CONFIG_DYNAMIC_FTRACE
+/*
+ * Replace a single instruction, which may be a branch or NOP.
+ * If @validate == true, a replaced instruction is checked against 'old'.
+ */
+static int ftrace_modify_code(unsigned long pc, u32 old, u32 new,
+			      bool validate)
+{
+	u32 replaced;
+
+	/*
+	 * Note:
+	 * Due to modules and __init, code can disappear and change,
+	 * we need to protect against faulting as well as code changing.
+	 * We do this by aarch64_insn_*() which use the probe_kernel_*().
+	 *
+	 * No lock is held here because all the modifications are run
+	 * through stop_machine().
+	 */
+	if (validate) {
+		if (aarch64_insn_read((void *)pc, &replaced))
+			return -EFAULT;
+
+		if (replaced != old)
+			return -EINVAL;
+	}
+	if (aarch64_insn_patch_text_nosync((void *)pc, new))
+		return -EPERM;
+
+	return 0;
+}
+
+/*
+ * Replace tracer function in ftrace_caller()
+ */
+int ftrace_update_ftrace_func(ftrace_func_t func)
+{
+	unsigned long pc;
+	u32 new;
+
+	pc = (unsigned long)&ftrace_call;
+	new = aarch64_insn_gen_branch_imm(pc, (unsigned long)func, true);
+
+	return ftrace_modify_code(pc, 0, new, false);
+}
+
+/*
+ * Turn on the call to ftrace_caller() in instrumented function
+ */
+int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
+{
+	unsigned long pc = rec->ip;
+	u32 old, new;
+
+	old = aarch64_insn_gen_nop();
+	new = aarch64_insn_gen_branch_imm(pc, addr, true);
+
+	return ftrace_modify_code(pc, old, new, true);
+}
+
+/*
+ * Turn off the call to ftrace_caller() in instrumented function
+ */
+int ftrace_make_nop(struct module *mod, struct dyn_ftrace *rec,
+		    unsigned long addr)
+{
+	unsigned long pc = rec->ip;
+	u32 old, new;
+
+	old = aarch64_insn_gen_branch_imm(pc, addr, true);
+	new = aarch64_insn_gen_nop();
+
+	return ftrace_modify_code(pc, old, new, true);
+}
+
+int __init ftrace_dyn_arch_init(void *data)
+{
+	*(unsigned long *)data = 0;
+
+	return 0;
+}
+#endif /* CONFIG_DYNAMIC_FTRACE */
+
 #ifdef CONFIG_FUNCTION_GRAPH_TRACER
 /*
  * function_graph tracer expects ftrace_return_to_handler() to be called
@@ -61,4 +144,35 @@ void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr,
 		return;
 	}
 }
+
+#ifdef CONFIG_DYNAMIC_FTRACE
+/*
+ * Turn on/off the call to ftrace_graph_caller() in ftrace_caller()
+ * depending on @enable.
+ */
+static int ftrace_modify_graph_caller(bool enable)
+{
+	unsigned long pc = (unsigned long)&ftrace_graph_call;
+	u32 branch, nop;
+
+	branch = aarch64_insn_gen_branch_imm(pc,
+			(unsigned long)ftrace_graph_caller, false);
+	nop = aarch64_insn_gen_nop();
+
+	if (enable)
+		return ftrace_modify_code(pc, nop, branch, true);
+	else
+		return ftrace_modify_code(pc, branch, nop, true);
+}
+
+int ftrace_enable_ftrace_graph_caller(void)
+{
+	return ftrace_modify_graph_caller(true);
+}
+
+int ftrace_disable_ftrace_graph_caller(void)
+{
+	return ftrace_modify_graph_caller(false);
+}
+#endif /* CONFIG_DYNAMIC_FTRACE */
 #endif /* CONFIG_FUNCTION_GRAPH_TRACER */
-- 
1.8.3.2


^ permalink raw reply related	[flat|nested] 235+ messages in thread

* [PATCH v7 5/7] arm64: ftrace: Add dynamic ftrace support
@ 2014-03-15  5:45           ` AKASHI Takahiro
  0 siblings, 0 replies; 235+ messages in thread
From: AKASHI Takahiro @ 2014-03-15  5:45 UTC (permalink / raw)
  To: linux-arm-kernel

This patch allows "dynamic ftrace" if CONFIG_DYNAMIC_FTRACE is enabled.
Here we can turn on and off tracing dynamically per-function base.

On arm64, this is done by patching single branch instruction to _mcount()
inserted by gcc -pg option. The branch is replaced to NOP initially at
kernel start up, and later on, NOP to branch to ftrace_caller() when
enabled or branch to NOP when disabled.
Please note that ftrace_caller() is a counterpart of _mcount() in case of
'static' ftrace.

More details on architecture specific requirements are described in
Documentation/trace/ftrace-design.txt.

Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
---
 arch/arm64/Kconfig               |   1 +
 arch/arm64/include/asm/ftrace.h  |  15 ++++++
 arch/arm64/kernel/entry-ftrace.S |  43 +++++++++++++++
 arch/arm64/kernel/ftrace.c       | 114 +++++++++++++++++++++++++++++++++++++++
 4 files changed, 173 insertions(+)

diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 6b3fef6..6954959 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -33,6 +33,7 @@ config ARM64
 	select HAVE_DMA_API_DEBUG
 	select HAVE_DMA_ATTRS
 	select HAVE_DMA_CONTIGUOUS
+	select HAVE_DYNAMIC_FTRACE
 	select HAVE_EFFICIENT_UNALIGNED_ACCESS
 	select HAVE_FTRACE_MCOUNT_RECORD
 	select HAVE_FUNCTION_TRACER
diff --git a/arch/arm64/include/asm/ftrace.h b/arch/arm64/include/asm/ftrace.h
index 58ea595..ed5c448 100644
--- a/arch/arm64/include/asm/ftrace.h
+++ b/arch/arm64/include/asm/ftrace.h
@@ -18,6 +18,21 @@
 
 #ifndef __ASSEMBLY__
 extern void _mcount(unsigned long);
+
+struct dyn_arch_ftrace {
+	/* No extra data needed for arm64 */
+};
+
+extern unsigned long ftrace_graph_call;
+
+static inline unsigned long ftrace_call_adjust(unsigned long addr)
+{
+	/*
+	 * addr is the address of the mcount call instruction.
+	 * recordmcount does the necessary offset calculation.
+	 */
+	return addr;
+}
 #endif /* __ASSEMBLY__ */
 
 #endif /* __ASM_FTRACE_H */
diff --git a/arch/arm64/kernel/entry-ftrace.S b/arch/arm64/kernel/entry-ftrace.S
index 622846f..d0cad6d 100644
--- a/arch/arm64/kernel/entry-ftrace.S
+++ b/arch/arm64/kernel/entry-ftrace.S
@@ -86,6 +86,7 @@
 	add	\reg, \reg, #8
 	.endm
 
+#ifndef CONFIG_DYNAMIC_FTRACE
 /*
  * void _mcount(unsigned long return_address)
  * @return_address: return address to instrumented function
@@ -134,6 +135,48 @@ skip_ftrace_call:
 #endif /* CONFIG_FUNCTION_GRAPH_TRACER */
 ENDPROC(_mcount)
 
+#else /* CONFIG_DYNAMIC_FTRACE */
+/*
+ * _mcount() is used to build the kernel with -pg option, but all the branch
+ * instructions to _mcount() are replaced to NOP initially at kernel start up,
+ * and later on, NOP to branch to ftrace_caller() when enabled or branch to
+ * NOP when disabled per-function base.
+ */
+ENTRY(_mcount)
+	ret
+ENDPROC(_mcount)
+
+/*
+ * void ftrace_caller(unsigned long return_address)
+ * @return_address: return address to instrumented function
+ *
+ * This function is a counterpart of _mcount() in 'static' ftrace, and
+ * makes calls to:
+ *     - tracer function to probe instrumented function's entry,
+ *     - ftrace_graph_caller to set up an exit hook
+ */
+ENTRY(ftrace_caller)
+	mcount_enter
+
+	mcount_get_pc0	x0		//     function's pc
+	mcount_get_lr	x1		//     function's lr
+
+	.global ftrace_call
+ftrace_call:				// tracer(pc, lr);
+	nop				// This will be replaced with "bl xxx"
+					// where xxx can be any kind of tracer.
+
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+	.global ftrace_graph_call
+ftrace_graph_call:			// ftrace_graph_caller();
+	nop				// If enabled, this will be replaced
+					// "b ftrace_graph_caller"
+#endif
+
+	mcount_exit
+ENDPROC(ftrace_caller)
+#endif /* CONFIG_DYNAMIC_FTRACE */
+
 ENTRY(ftrace_stub)
 	ret
 ENDPROC(ftrace_stub)
diff --git a/arch/arm64/kernel/ftrace.c b/arch/arm64/kernel/ftrace.c
index a559ab8..9f708e7 100644
--- a/arch/arm64/kernel/ftrace.c
+++ b/arch/arm64/kernel/ftrace.c
@@ -17,6 +17,89 @@
 #include <asm/ftrace.h>
 #include <asm/insn.h>
 
+#ifdef CONFIG_DYNAMIC_FTRACE
+/*
+ * Replace a single instruction, which may be a branch or NOP.
+ * If @validate == true, a replaced instruction is checked against 'old'.
+ */
+static int ftrace_modify_code(unsigned long pc, u32 old, u32 new,
+			      bool validate)
+{
+	u32 replaced;
+
+	/*
+	 * Note:
+	 * Due to modules and __init, code can disappear and change,
+	 * we need to protect against faulting as well as code changing.
+	 * We do this by aarch64_insn_*() which use the probe_kernel_*().
+	 *
+	 * No lock is held here because all the modifications are run
+	 * through stop_machine().
+	 */
+	if (validate) {
+		if (aarch64_insn_read((void *)pc, &replaced))
+			return -EFAULT;
+
+		if (replaced != old)
+			return -EINVAL;
+	}
+	if (aarch64_insn_patch_text_nosync((void *)pc, new))
+		return -EPERM;
+
+	return 0;
+}
+
+/*
+ * Replace tracer function in ftrace_caller()
+ */
+int ftrace_update_ftrace_func(ftrace_func_t func)
+{
+	unsigned long pc;
+	u32 new;
+
+	pc = (unsigned long)&ftrace_call;
+	new = aarch64_insn_gen_branch_imm(pc, (unsigned long)func, true);
+
+	return ftrace_modify_code(pc, 0, new, false);
+}
+
+/*
+ * Turn on the call to ftrace_caller() in instrumented function
+ */
+int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
+{
+	unsigned long pc = rec->ip;
+	u32 old, new;
+
+	old = aarch64_insn_gen_nop();
+	new = aarch64_insn_gen_branch_imm(pc, addr, true);
+
+	return ftrace_modify_code(pc, old, new, true);
+}
+
+/*
+ * Turn off the call to ftrace_caller() in instrumented function
+ */
+int ftrace_make_nop(struct module *mod, struct dyn_ftrace *rec,
+		    unsigned long addr)
+{
+	unsigned long pc = rec->ip;
+	u32 old, new;
+
+	old = aarch64_insn_gen_branch_imm(pc, addr, true);
+	new = aarch64_insn_gen_nop();
+
+	return ftrace_modify_code(pc, old, new, true);
+}
+
+int __init ftrace_dyn_arch_init(void *data)
+{
+	*(unsigned long *)data = 0;
+
+	return 0;
+}
+#endif /* CONFIG_DYNAMIC_FTRACE */
+
 #ifdef CONFIG_FUNCTION_GRAPH_TRACER
 /*
  * function_graph tracer expects ftrace_return_to_handler() to be called
@@ -61,4 +144,35 @@ void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr,
 		return;
 	}
 }
+
+#ifdef CONFIG_DYNAMIC_FTRACE
+/*
+ * Turn on/off the call to ftrace_graph_caller() in ftrace_caller()
+ * depending on @enable.
+ */
+static int ftrace_modify_graph_caller(bool enable)
+{
+	unsigned long pc = (unsigned long)&ftrace_graph_call;
+	u32 branch, nop;
+
+	branch = aarch64_insn_gen_branch_imm(pc,
+			(unsigned long)ftrace_graph_caller, false);
+	nop = aarch64_insn_gen_nop();
+
+	if (enable)
+		return ftrace_modify_code(pc, nop, branch, true);
+	else
+		return ftrace_modify_code(pc, branch, nop, true);
+}
+
+int ftrace_enable_ftrace_graph_caller(void)
+{
+	return ftrace_modify_graph_caller(true);
+}
+
+int ftrace_disable_ftrace_graph_caller(void)
+{
+	return ftrace_modify_graph_caller(false);
+}
+#endif /* CONFIG_DYNAMIC_FTRACE */
 #endif /* CONFIG_FUNCTION_GRAPH_TRACER */
-- 
1.8.3.2

^ permalink raw reply related	[flat|nested] 235+ messages in thread

* [PATCH v7 6/7] arm64: ftrace: Add CALLER_ADDRx macros
  2014-03-13 10:13         ` AKASHI Takahiro
@ 2014-03-15  5:45           ` AKASHI Takahiro
  -1 siblings, 0 replies; 235+ messages in thread
From: AKASHI Takahiro @ 2014-03-15  5:45 UTC (permalink / raw)
  To: rostedt, fweisbec, mingo, catalin.marinas, will.deacon, tim.bird
  Cc: gkulkarni, dsaxena, arndb, linux-arm-kernel, linaro-kernel,
	linux-kernel, AKASHI Takahiro

CALLER_ADDRx returns caller's address at specified level in call stacks.
They are used for several tracers like irqsoff and preemptoff.
Strange to say, however, they are refered even without FTRACE.

Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
---
 arch/arm64/include/asm/ftrace.h    | 13 ++++++++-
 arch/arm64/kernel/Makefile         |  3 ++-
 arch/arm64/kernel/return_address.c | 55 ++++++++++++++++++++++++++++++++++++++
 3 files changed, 69 insertions(+), 2 deletions(-)
 create mode 100644 arch/arm64/kernel/return_address.c

diff --git a/arch/arm64/include/asm/ftrace.h b/arch/arm64/include/asm/ftrace.h
index ed5c448..c44c4b1 100644
--- a/arch/arm64/include/asm/ftrace.h
+++ b/arch/arm64/include/asm/ftrace.h
@@ -18,6 +18,7 @@
 
 #ifndef __ASSEMBLY__
 extern void _mcount(unsigned long);
+extern void *return_address(unsigned int);
 
 struct dyn_arch_ftrace {
 	/* No extra data needed for arm64 */
@@ -33,6 +34,16 @@ static inline unsigned long ftrace_call_adjust(unsigned long addr)
 	 */
 	return addr;
 }
-#endif /* __ASSEMBLY__ */
+
+#define HAVE_ARCH_CALLER_ADDR
+
+#define CALLER_ADDR0 ((unsigned long)__builtin_return_address(0))
+#define CALLER_ADDR1 ((unsigned long)return_address(1))
+#define CALLER_ADDR2 ((unsigned long)return_address(2))
+#define CALLER_ADDR3 ((unsigned long)return_address(3))
+#define CALLER_ADDR4 ((unsigned long)return_address(4))
+#define CALLER_ADDR5 ((unsigned long)return_address(5))
+#define CALLER_ADDR6 ((unsigned long)return_address(6))
+#endif /* ifndef __ASSEMBLY__ */
 
 #endif /* __ASM_FTRACE_H */
diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile
index ac67fd0..b5bfa7f 100644
--- a/arch/arm64/kernel/Makefile
+++ b/arch/arm64/kernel/Makefile
@@ -7,12 +7,13 @@ AFLAGS_head.o		:= -DTEXT_OFFSET=$(TEXT_OFFSET)
 
 CFLAGS_REMOVE_ftrace.o = -pg
 CFLAGS_REMOVE_insn.o = -pg
+CFLAGS_REMOVE_return_address.o = -pg
 
 # Object file lists.
 arm64-obj-y		:= cputable.o debug-monitors.o entry.o irq.o fpsimd.o	\
 			   entry-fpsimd.o process.o ptrace.o setup.o signal.o	\
 			   sys.o stacktrace.o time.o traps.o io.o vdso.o	\
-			   hyp-stub.o psci.o cpu_ops.o insn.o
+			   hyp-stub.o psci.o cpu_ops.o insn.o return_address.o
 
 arm64-obj-$(CONFIG_COMPAT)		+= sys32.o kuser32.o signal32.o 	\
 					   sys_compat.o
diff --git a/arch/arm64/kernel/return_address.c b/arch/arm64/kernel/return_address.c
new file mode 100644
index 0000000..89102a6
--- /dev/null
+++ b/arch/arm64/kernel/return_address.c
@@ -0,0 +1,55 @@
+/*
+ * arch/arm64/kernel/return_address.c
+ *
+ * Copyright (C) 2013 Linaro Limited
+ * Author: AKASHI Takahiro <takahiro.akashi@linaro.org>
+ *
+ * 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 <linux/export.h>
+#include <linux/ftrace.h>
+
+#include <asm/stacktrace.h>
+
+struct return_address_data {
+	unsigned int level;
+	void *addr;
+};
+
+static int save_return_addr(struct stackframe *frame, void *d)
+{
+	struct return_address_data *data = d;
+
+	if (!data->level) {
+		data->addr = (void *)frame->pc;
+		return 1;
+	} else {
+		--data->level;
+		return 0;
+	}
+}
+
+void *return_address(unsigned int level)
+{
+	struct return_address_data data;
+	struct stackframe frame;
+	register unsigned long current_sp asm ("sp");
+
+	data.level = level + 2;
+	data.addr = NULL;
+
+	frame.fp = (unsigned long)__builtin_frame_address(0);
+	frame.sp = current_sp;
+	frame.pc = (unsigned long)return_address; /* dummy */
+
+	walk_stackframe(&frame, save_return_addr, &data);
+
+	if (!data.level)
+		return data.addr;
+	else
+		return NULL;
+}
+EXPORT_SYMBOL_GPL(return_address);
-- 
1.8.3.2


^ permalink raw reply related	[flat|nested] 235+ messages in thread

* [PATCH v7 6/7] arm64: ftrace: Add CALLER_ADDRx macros
@ 2014-03-15  5:45           ` AKASHI Takahiro
  0 siblings, 0 replies; 235+ messages in thread
From: AKASHI Takahiro @ 2014-03-15  5:45 UTC (permalink / raw)
  To: linux-arm-kernel

CALLER_ADDRx returns caller's address at specified level in call stacks.
They are used for several tracers like irqsoff and preemptoff.
Strange to say, however, they are refered even without FTRACE.

Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
---
 arch/arm64/include/asm/ftrace.h    | 13 ++++++++-
 arch/arm64/kernel/Makefile         |  3 ++-
 arch/arm64/kernel/return_address.c | 55 ++++++++++++++++++++++++++++++++++++++
 3 files changed, 69 insertions(+), 2 deletions(-)
 create mode 100644 arch/arm64/kernel/return_address.c

diff --git a/arch/arm64/include/asm/ftrace.h b/arch/arm64/include/asm/ftrace.h
index ed5c448..c44c4b1 100644
--- a/arch/arm64/include/asm/ftrace.h
+++ b/arch/arm64/include/asm/ftrace.h
@@ -18,6 +18,7 @@
 
 #ifndef __ASSEMBLY__
 extern void _mcount(unsigned long);
+extern void *return_address(unsigned int);
 
 struct dyn_arch_ftrace {
 	/* No extra data needed for arm64 */
@@ -33,6 +34,16 @@ static inline unsigned long ftrace_call_adjust(unsigned long addr)
 	 */
 	return addr;
 }
-#endif /* __ASSEMBLY__ */
+
+#define HAVE_ARCH_CALLER_ADDR
+
+#define CALLER_ADDR0 ((unsigned long)__builtin_return_address(0))
+#define CALLER_ADDR1 ((unsigned long)return_address(1))
+#define CALLER_ADDR2 ((unsigned long)return_address(2))
+#define CALLER_ADDR3 ((unsigned long)return_address(3))
+#define CALLER_ADDR4 ((unsigned long)return_address(4))
+#define CALLER_ADDR5 ((unsigned long)return_address(5))
+#define CALLER_ADDR6 ((unsigned long)return_address(6))
+#endif /* ifndef __ASSEMBLY__ */
 
 #endif /* __ASM_FTRACE_H */
diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile
index ac67fd0..b5bfa7f 100644
--- a/arch/arm64/kernel/Makefile
+++ b/arch/arm64/kernel/Makefile
@@ -7,12 +7,13 @@ AFLAGS_head.o		:= -DTEXT_OFFSET=$(TEXT_OFFSET)
 
 CFLAGS_REMOVE_ftrace.o = -pg
 CFLAGS_REMOVE_insn.o = -pg
+CFLAGS_REMOVE_return_address.o = -pg
 
 # Object file lists.
 arm64-obj-y		:= cputable.o debug-monitors.o entry.o irq.o fpsimd.o	\
 			   entry-fpsimd.o process.o ptrace.o setup.o signal.o	\
 			   sys.o stacktrace.o time.o traps.o io.o vdso.o	\
-			   hyp-stub.o psci.o cpu_ops.o insn.o
+			   hyp-stub.o psci.o cpu_ops.o insn.o return_address.o
 
 arm64-obj-$(CONFIG_COMPAT)		+= sys32.o kuser32.o signal32.o 	\
 					   sys_compat.o
diff --git a/arch/arm64/kernel/return_address.c b/arch/arm64/kernel/return_address.c
new file mode 100644
index 0000000..89102a6
--- /dev/null
+++ b/arch/arm64/kernel/return_address.c
@@ -0,0 +1,55 @@
+/*
+ * arch/arm64/kernel/return_address.c
+ *
+ * Copyright (C) 2013 Linaro Limited
+ * Author: AKASHI Takahiro <takahiro.akashi@linaro.org>
+ *
+ * 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 <linux/export.h>
+#include <linux/ftrace.h>
+
+#include <asm/stacktrace.h>
+
+struct return_address_data {
+	unsigned int level;
+	void *addr;
+};
+
+static int save_return_addr(struct stackframe *frame, void *d)
+{
+	struct return_address_data *data = d;
+
+	if (!data->level) {
+		data->addr = (void *)frame->pc;
+		return 1;
+	} else {
+		--data->level;
+		return 0;
+	}
+}
+
+void *return_address(unsigned int level)
+{
+	struct return_address_data data;
+	struct stackframe frame;
+	register unsigned long current_sp asm ("sp");
+
+	data.level = level + 2;
+	data.addr = NULL;
+
+	frame.fp = (unsigned long)__builtin_frame_address(0);
+	frame.sp = current_sp;
+	frame.pc = (unsigned long)return_address; /* dummy */
+
+	walk_stackframe(&frame, save_return_addr, &data);
+
+	if (!data.level)
+		return data.addr;
+	else
+		return NULL;
+}
+EXPORT_SYMBOL_GPL(return_address);
-- 
1.8.3.2

^ permalink raw reply related	[flat|nested] 235+ messages in thread

* [PATCH v7 7/7] arm64: ftrace: Add system call tracepoint
  2014-03-13 10:13         ` AKASHI Takahiro
@ 2014-03-15  5:45           ` AKASHI Takahiro
  -1 siblings, 0 replies; 235+ messages in thread
From: AKASHI Takahiro @ 2014-03-15  5:45 UTC (permalink / raw)
  To: rostedt, fweisbec, mingo, catalin.marinas, will.deacon, tim.bird
  Cc: gkulkarni, dsaxena, arndb, linux-arm-kernel, linaro-kernel,
	linux-kernel, AKASHI Takahiro

This patch allows system call entry or exit to be traced as ftrace events,
ie. sys_enter_*/sys_exit_*, if CONFIG_FTRACE_SYSCALLS is enabled.
Those events appear and can be controlled under
    ${sysfs}/tracing/events/syscalls/

Please note that we can't trace compat system calls here because
AArch32 mode does not share the same syscall table with AArch64.
Just define ARCH_TRACE_IGNORE_COMPAT_SYSCALLS in order to avoid unexpected
results (bogus syscalls reported or even hang-up).

Acked-by: Will Deacon <will.deacon@arm.com>
Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
---
 arch/arm64/Kconfig               |  1 +
 arch/arm64/include/asm/ftrace.h  | 18 ++++++++++++++++++
 arch/arm64/include/asm/syscall.h |  1 +
 arch/arm64/include/asm/unistd.h  |  2 ++
 arch/arm64/kernel/ptrace.c       |  9 +++++++++
 5 files changed, 31 insertions(+)

diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 6954959..b1dcdb4 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -43,6 +43,7 @@ config ARM64
 	select HAVE_MEMBLOCK
 	select HAVE_PATA_PLATFORM
 	select HAVE_PERF_EVENTS
+	select HAVE_SYSCALL_TRACEPOINTS
 	select IRQ_DOMAIN
 	select MODULES_USE_ELF_RELA
 	select NO_BOOTMEM
diff --git a/arch/arm64/include/asm/ftrace.h b/arch/arm64/include/asm/ftrace.h
index c44c4b1..7616255 100644
--- a/arch/arm64/include/asm/ftrace.h
+++ b/arch/arm64/include/asm/ftrace.h
@@ -44,6 +44,24 @@ static inline unsigned long ftrace_call_adjust(unsigned long addr)
 #define CALLER_ADDR4 ((unsigned long)return_address(4))
 #define CALLER_ADDR5 ((unsigned long)return_address(5))
 #define CALLER_ADDR6 ((unsigned long)return_address(6))
+
+#include <linux/compat.h>
+
+/*
+ * Because AArch32 mode does not share the same syscall table with AArch64,
+ * tracing compat syscalls may result in reporting bogus syscalls or even
+ * hang-up, so just do not trace them.
+ * See kernel/trace/trace_syscalls.c
+ *
+ * x86 code says:
+ * If the user realy wants these, then they should use the
+ * raw syscall tracepoints with filtering.
+ */
+#define ARCH_TRACE_IGNORE_COMPAT_SYSCALLS
+static inline bool arch_trace_is_compat_syscall(struct pt_regs *regs)
+{
+	return is_compat_task();
+}
 #endif /* ifndef __ASSEMBLY__ */
 
 #endif /* __ASM_FTRACE_H */
diff --git a/arch/arm64/include/asm/syscall.h b/arch/arm64/include/asm/syscall.h
index 70ba9d4..383771e 100644
--- a/arch/arm64/include/asm/syscall.h
+++ b/arch/arm64/include/asm/syscall.h
@@ -18,6 +18,7 @@
 
 #include <linux/err.h>
 
+extern const void *sys_call_table[];
 
 static inline int syscall_get_nr(struct task_struct *task,
 				 struct pt_regs *regs)
diff --git a/arch/arm64/include/asm/unistd.h b/arch/arm64/include/asm/unistd.h
index 82ce217..c335479 100644
--- a/arch/arm64/include/asm/unistd.h
+++ b/arch/arm64/include/asm/unistd.h
@@ -28,3 +28,5 @@
 #endif
 #define __ARCH_WANT_SYS_CLONE
 #include <uapi/asm/unistd.h>
+
+#define NR_syscalls (__NR_syscalls)
diff --git a/arch/arm64/kernel/ptrace.c b/arch/arm64/kernel/ptrace.c
index c47a3ed..3ee76ed 100644
--- a/arch/arm64/kernel/ptrace.c
+++ b/arch/arm64/kernel/ptrace.c
@@ -42,6 +42,9 @@
 #include <asm/traps.h>
 #include <asm/system_misc.h>
 
+#define CREATE_TRACE_POINTS
+#include <trace/events/syscalls.h>
+
 /*
  * TODO: does not yet catch signals sent when the child dies.
  * in exit.c or in signal.c.
@@ -1091,11 +1094,17 @@ asmlinkage int syscall_trace_enter(struct pt_regs *regs)
 	if (test_thread_flag(TIF_SYSCALL_TRACE))
 		tracehook_report_syscall(regs, PTRACE_SYSCALL_ENTER);
 
+	if (test_thread_flag(TIF_SYSCALL_TRACEPOINT))
+		trace_sys_enter(regs, regs->syscallno);
+
 	return regs->syscallno;
 }
 
 asmlinkage void syscall_trace_exit(struct pt_regs *regs)
 {
+	if (test_thread_flag(TIF_SYSCALL_TRACEPOINT))
+		trace_sys_exit(regs, regs_return_value(regs));
+
 	if (test_thread_flag(TIF_SYSCALL_TRACE))
 		tracehook_report_syscall(regs, PTRACE_SYSCALL_EXIT);
 }
-- 
1.8.3.2


^ permalink raw reply related	[flat|nested] 235+ messages in thread

* [PATCH v7 7/7] arm64: ftrace: Add system call tracepoint
@ 2014-03-15  5:45           ` AKASHI Takahiro
  0 siblings, 0 replies; 235+ messages in thread
From: AKASHI Takahiro @ 2014-03-15  5:45 UTC (permalink / raw)
  To: linux-arm-kernel

This patch allows system call entry or exit to be traced as ftrace events,
ie. sys_enter_*/sys_exit_*, if CONFIG_FTRACE_SYSCALLS is enabled.
Those events appear and can be controlled under
    ${sysfs}/tracing/events/syscalls/

Please note that we can't trace compat system calls here because
AArch32 mode does not share the same syscall table with AArch64.
Just define ARCH_TRACE_IGNORE_COMPAT_SYSCALLS in order to avoid unexpected
results (bogus syscalls reported or even hang-up).

Acked-by: Will Deacon <will.deacon@arm.com>
Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
---
 arch/arm64/Kconfig               |  1 +
 arch/arm64/include/asm/ftrace.h  | 18 ++++++++++++++++++
 arch/arm64/include/asm/syscall.h |  1 +
 arch/arm64/include/asm/unistd.h  |  2 ++
 arch/arm64/kernel/ptrace.c       |  9 +++++++++
 5 files changed, 31 insertions(+)

diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 6954959..b1dcdb4 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -43,6 +43,7 @@ config ARM64
 	select HAVE_MEMBLOCK
 	select HAVE_PATA_PLATFORM
 	select HAVE_PERF_EVENTS
+	select HAVE_SYSCALL_TRACEPOINTS
 	select IRQ_DOMAIN
 	select MODULES_USE_ELF_RELA
 	select NO_BOOTMEM
diff --git a/arch/arm64/include/asm/ftrace.h b/arch/arm64/include/asm/ftrace.h
index c44c4b1..7616255 100644
--- a/arch/arm64/include/asm/ftrace.h
+++ b/arch/arm64/include/asm/ftrace.h
@@ -44,6 +44,24 @@ static inline unsigned long ftrace_call_adjust(unsigned long addr)
 #define CALLER_ADDR4 ((unsigned long)return_address(4))
 #define CALLER_ADDR5 ((unsigned long)return_address(5))
 #define CALLER_ADDR6 ((unsigned long)return_address(6))
+
+#include <linux/compat.h>
+
+/*
+ * Because AArch32 mode does not share the same syscall table with AArch64,
+ * tracing compat syscalls may result in reporting bogus syscalls or even
+ * hang-up, so just do not trace them.
+ * See kernel/trace/trace_syscalls.c
+ *
+ * x86 code says:
+ * If the user realy wants these, then they should use the
+ * raw syscall tracepoints with filtering.
+ */
+#define ARCH_TRACE_IGNORE_COMPAT_SYSCALLS
+static inline bool arch_trace_is_compat_syscall(struct pt_regs *regs)
+{
+	return is_compat_task();
+}
 #endif /* ifndef __ASSEMBLY__ */
 
 #endif /* __ASM_FTRACE_H */
diff --git a/arch/arm64/include/asm/syscall.h b/arch/arm64/include/asm/syscall.h
index 70ba9d4..383771e 100644
--- a/arch/arm64/include/asm/syscall.h
+++ b/arch/arm64/include/asm/syscall.h
@@ -18,6 +18,7 @@
 
 #include <linux/err.h>
 
+extern const void *sys_call_table[];
 
 static inline int syscall_get_nr(struct task_struct *task,
 				 struct pt_regs *regs)
diff --git a/arch/arm64/include/asm/unistd.h b/arch/arm64/include/asm/unistd.h
index 82ce217..c335479 100644
--- a/arch/arm64/include/asm/unistd.h
+++ b/arch/arm64/include/asm/unistd.h
@@ -28,3 +28,5 @@
 #endif
 #define __ARCH_WANT_SYS_CLONE
 #include <uapi/asm/unistd.h>
+
+#define NR_syscalls (__NR_syscalls)
diff --git a/arch/arm64/kernel/ptrace.c b/arch/arm64/kernel/ptrace.c
index c47a3ed..3ee76ed 100644
--- a/arch/arm64/kernel/ptrace.c
+++ b/arch/arm64/kernel/ptrace.c
@@ -42,6 +42,9 @@
 #include <asm/traps.h>
 #include <asm/system_misc.h>
 
+#define CREATE_TRACE_POINTS
+#include <trace/events/syscalls.h>
+
 /*
  * TODO: does not yet catch signals sent when the child dies.
  * in exit.c or in signal.c.
@@ -1091,11 +1094,17 @@ asmlinkage int syscall_trace_enter(struct pt_regs *regs)
 	if (test_thread_flag(TIF_SYSCALL_TRACE))
 		tracehook_report_syscall(regs, PTRACE_SYSCALL_ENTER);
 
+	if (test_thread_flag(TIF_SYSCALL_TRACEPOINT))
+		trace_sys_enter(regs, regs->syscallno);
+
 	return regs->syscallno;
 }
 
 asmlinkage void syscall_trace_exit(struct pt_regs *regs)
 {
+	if (test_thread_flag(TIF_SYSCALL_TRACEPOINT))
+		trace_sys_exit(regs, regs_return_value(regs));
+
 	if (test_thread_flag(TIF_SYSCALL_TRACE))
 		tracehook_report_syscall(regs, PTRACE_SYSCALL_EXIT);
 }
-- 
1.8.3.2

^ permalink raw reply related	[flat|nested] 235+ messages in thread

* Re: [PATCH v7 3/7] ftrace: Add arm64 support to recordmcount
  2014-03-15  5:40             ` AKASHI Takahiro
@ 2014-04-16 13:31               ` Will Deacon
  -1 siblings, 0 replies; 235+ messages in thread
From: Will Deacon @ 2014-04-16 13:31 UTC (permalink / raw)
  To: AKASHI Takahiro
  Cc: rostedt, fweisbec, mingo, Catalin Marinas, tim.bird, gkulkarni,
	dsaxena, arndb, linux-arm-kernel, linaro-kernel, linux-kernel

On Sat, Mar 15, 2014 at 05:40:44AM +0000, AKASHI Takahiro wrote:
> Recordmcount utility under scripts is run, after compiling each object,
> to find out all the locations of calling _mcount() and put them into
> specific seciton named __mcount_loc.
> Then linker collects all such information into a table in the kernel image
> (between __start_mcount_loc and __stop_mcount_loc) for later use by ftrace.
> 
> This patch adds arm64 specific definitions to identify such locations.
> There are two types of implementation, C and Perl. On arm64, only C version
> is used to build the kernel now that CONFIG_HAVE_C_RECORDMCOUNT is on.
> But Perl version is also maintained.
> 
> This patch also contains a workaround just in case where a header file,
> elf.h, on host machine doesn't have definitions of EM_AARCH64 nor
> R_AARCH64_ABS64. Without them, compiling C version of recordmcount will
> fail.
> 
> Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>

  Acked-by: Will Deacon <will.deacon@arm.com>

Will

^ permalink raw reply	[flat|nested] 235+ messages in thread

* [PATCH v7 3/7] ftrace: Add arm64 support to recordmcount
@ 2014-04-16 13:31               ` Will Deacon
  0 siblings, 0 replies; 235+ messages in thread
From: Will Deacon @ 2014-04-16 13:31 UTC (permalink / raw)
  To: linux-arm-kernel

On Sat, Mar 15, 2014 at 05:40:44AM +0000, AKASHI Takahiro wrote:
> Recordmcount utility under scripts is run, after compiling each object,
> to find out all the locations of calling _mcount() and put them into
> specific seciton named __mcount_loc.
> Then linker collects all such information into a table in the kernel image
> (between __start_mcount_loc and __stop_mcount_loc) for later use by ftrace.
> 
> This patch adds arm64 specific definitions to identify such locations.
> There are two types of implementation, C and Perl. On arm64, only C version
> is used to build the kernel now that CONFIG_HAVE_C_RECORDMCOUNT is on.
> But Perl version is also maintained.
> 
> This patch also contains a workaround just in case where a header file,
> elf.h, on host machine doesn't have definitions of EM_AARCH64 nor
> R_AARCH64_ABS64. Without them, compiling C version of recordmcount will
> fail.
> 
> Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>

  Acked-by: Will Deacon <will.deacon@arm.com>

Will

^ permalink raw reply	[flat|nested] 235+ messages in thread

* Re: [PATCH v7 4/7] arm64: Add ftrace support
  2014-03-15  5:45           ` AKASHI Takahiro
@ 2014-04-16 13:45             ` Will Deacon
  -1 siblings, 0 replies; 235+ messages in thread
From: Will Deacon @ 2014-04-16 13:45 UTC (permalink / raw)
  To: AKASHI Takahiro
  Cc: rostedt, fweisbec, mingo, Catalin Marinas, tim.bird, gkulkarni,
	dsaxena, arndb, linux-arm-kernel, linaro-kernel, linux-kernel

On Sat, Mar 15, 2014 at 05:45:50AM +0000, AKASHI Takahiro wrote:
> This patch implements arm64 specific part to support function tracers,
> such as function (CONFIG_FUNCTION_TRACER), function_graph
> (CONFIG_FUNCTION_GRAPH_TRACER) and function profiler
> (CONFIG_FUNCTION_PROFILER).
> 
> With 'function' tracer, all the functions in the kernel are traced with
> timestamps in ${sysfs}/tracing/trace. If function_graph tracer is
> specified, call graph is generated.
> 
> The kernel must be compiled with -pg option so that _mcount() is inserted
> at the beginning of functions. This function is called on every function's
> entry as long as tracing is enabled.
> In addition, function_graph tracer also needs to be able to probe function's
> exit. ftrace_graph_caller() & return_to_handler do this by faking link
> register's value to intercept function's return path.
> 
> More details on architecture specific requirements are described in
> Documentation/trace/ftrace-design.txt.
> 
> Reviewed-by: Ganapatrao Kulkarni <ganapatrao.kulkarni@cavium.com>
> Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>

I'm still slightly suspicious about the alignment of your ASCII art, but:

  Acked-by: Will Deacon <will.deacon@arm.com>

Will

^ permalink raw reply	[flat|nested] 235+ messages in thread

* [PATCH v7 4/7] arm64: Add ftrace support
@ 2014-04-16 13:45             ` Will Deacon
  0 siblings, 0 replies; 235+ messages in thread
From: Will Deacon @ 2014-04-16 13:45 UTC (permalink / raw)
  To: linux-arm-kernel

On Sat, Mar 15, 2014 at 05:45:50AM +0000, AKASHI Takahiro wrote:
> This patch implements arm64 specific part to support function tracers,
> such as function (CONFIG_FUNCTION_TRACER), function_graph
> (CONFIG_FUNCTION_GRAPH_TRACER) and function profiler
> (CONFIG_FUNCTION_PROFILER).
> 
> With 'function' tracer, all the functions in the kernel are traced with
> timestamps in ${sysfs}/tracing/trace. If function_graph tracer is
> specified, call graph is generated.
> 
> The kernel must be compiled with -pg option so that _mcount() is inserted
> at the beginning of functions. This function is called on every function's
> entry as long as tracing is enabled.
> In addition, function_graph tracer also needs to be able to probe function's
> exit. ftrace_graph_caller() & return_to_handler do this by faking link
> register's value to intercept function's return path.
> 
> More details on architecture specific requirements are described in
> Documentation/trace/ftrace-design.txt.
> 
> Reviewed-by: Ganapatrao Kulkarni <ganapatrao.kulkarni@cavium.com>
> Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>

I'm still slightly suspicious about the alignment of your ASCII art, but:

  Acked-by: Will Deacon <will.deacon@arm.com>

Will

^ permalink raw reply	[flat|nested] 235+ messages in thread

* Re: [PATCH v7 5/7] arm64: ftrace: Add dynamic ftrace support
  2014-03-15  5:45           ` AKASHI Takahiro
@ 2014-04-16 13:48             ` Will Deacon
  -1 siblings, 0 replies; 235+ messages in thread
From: Will Deacon @ 2014-04-16 13:48 UTC (permalink / raw)
  To: AKASHI Takahiro
  Cc: rostedt, fweisbec, mingo, Catalin Marinas, tim.bird, gkulkarni,
	dsaxena, arndb, linux-arm-kernel, linaro-kernel, linux-kernel

On Sat, Mar 15, 2014 at 05:45:51AM +0000, AKASHI Takahiro wrote:
> This patch allows "dynamic ftrace" if CONFIG_DYNAMIC_FTRACE is enabled.
> Here we can turn on and off tracing dynamically per-function base.
> 
> On arm64, this is done by patching single branch instruction to _mcount()
> inserted by gcc -pg option. The branch is replaced to NOP initially at
> kernel start up, and later on, NOP to branch to ftrace_caller() when
> enabled or branch to NOP when disabled.
> Please note that ftrace_caller() is a counterpart of _mcount() in case of
> 'static' ftrace.
> 
> More details on architecture specific requirements are described in
> Documentation/trace/ftrace-design.txt.
> 
> Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>

  Acked-by: Will Deacon <will.deacon@arm.com>

Will

^ permalink raw reply	[flat|nested] 235+ messages in thread

* [PATCH v7 5/7] arm64: ftrace: Add dynamic ftrace support
@ 2014-04-16 13:48             ` Will Deacon
  0 siblings, 0 replies; 235+ messages in thread
From: Will Deacon @ 2014-04-16 13:48 UTC (permalink / raw)
  To: linux-arm-kernel

On Sat, Mar 15, 2014 at 05:45:51AM +0000, AKASHI Takahiro wrote:
> This patch allows "dynamic ftrace" if CONFIG_DYNAMIC_FTRACE is enabled.
> Here we can turn on and off tracing dynamically per-function base.
> 
> On arm64, this is done by patching single branch instruction to _mcount()
> inserted by gcc -pg option. The branch is replaced to NOP initially at
> kernel start up, and later on, NOP to branch to ftrace_caller() when
> enabled or branch to NOP when disabled.
> Please note that ftrace_caller() is a counterpart of _mcount() in case of
> 'static' ftrace.
> 
> More details on architecture specific requirements are described in
> Documentation/trace/ftrace-design.txt.
> 
> Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>

  Acked-by: Will Deacon <will.deacon@arm.com>

Will

^ permalink raw reply	[flat|nested] 235+ messages in thread

* Re: [PATCH v7 6/7] arm64: ftrace: Add CALLER_ADDRx macros
  2014-03-15  5:45           ` AKASHI Takahiro
@ 2014-04-16 13:52             ` Will Deacon
  -1 siblings, 0 replies; 235+ messages in thread
From: Will Deacon @ 2014-04-16 13:52 UTC (permalink / raw)
  To: AKASHI Takahiro
  Cc: rostedt, fweisbec, mingo, Catalin Marinas, tim.bird, gkulkarni,
	dsaxena, arndb, linux-arm-kernel, linaro-kernel, linux-kernel

On Sat, Mar 15, 2014 at 05:45:52AM +0000, AKASHI Takahiro wrote:
> CALLER_ADDRx returns caller's address at specified level in call stacks.
> They are used for several tracers like irqsoff and preemptoff.
> Strange to say, however, they are refered even without FTRACE.
> 
> Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
> ---
>  arch/arm64/include/asm/ftrace.h    | 13 ++++++++-
>  arch/arm64/kernel/Makefile         |  3 ++-
>  arch/arm64/kernel/return_address.c | 55 ++++++++++++++++++++++++++++++++++++++
>  3 files changed, 69 insertions(+), 2 deletions(-)
>  create mode 100644 arch/arm64/kernel/return_address.c
> 
> diff --git a/arch/arm64/include/asm/ftrace.h b/arch/arm64/include/asm/ftrace.h
> index ed5c448..c44c4b1 100644
> --- a/arch/arm64/include/asm/ftrace.h
> +++ b/arch/arm64/include/asm/ftrace.h
> @@ -18,6 +18,7 @@
>  
>  #ifndef __ASSEMBLY__
>  extern void _mcount(unsigned long);
> +extern void *return_address(unsigned int);
>  
>  struct dyn_arch_ftrace {
>  	/* No extra data needed for arm64 */
> @@ -33,6 +34,16 @@ static inline unsigned long ftrace_call_adjust(unsigned long addr)
>  	 */
>  	return addr;
>  }
> -#endif /* __ASSEMBLY__ */
> +
> +#define HAVE_ARCH_CALLER_ADDR
> +
> +#define CALLER_ADDR0 ((unsigned long)__builtin_return_address(0))
> +#define CALLER_ADDR1 ((unsigned long)return_address(1))
> +#define CALLER_ADDR2 ((unsigned long)return_address(2))
> +#define CALLER_ADDR3 ((unsigned long)return_address(3))
> +#define CALLER_ADDR4 ((unsigned long)return_address(4))
> +#define CALLER_ADDR5 ((unsigned long)return_address(5))
> +#define CALLER_ADDR6 ((unsigned long)return_address(6))
> +#endif /* ifndef __ASSEMBLY__ */

Hmm, I thought you were going to take a look at reworking the core code for
this, as Steve and I suggested?

  http://lists.infradead.org/pipermail/linux-arm-kernel/2014-March/240239.html

Will

^ permalink raw reply	[flat|nested] 235+ messages in thread

* [PATCH v7 6/7] arm64: ftrace: Add CALLER_ADDRx macros
@ 2014-04-16 13:52             ` Will Deacon
  0 siblings, 0 replies; 235+ messages in thread
From: Will Deacon @ 2014-04-16 13:52 UTC (permalink / raw)
  To: linux-arm-kernel

On Sat, Mar 15, 2014 at 05:45:52AM +0000, AKASHI Takahiro wrote:
> CALLER_ADDRx returns caller's address at specified level in call stacks.
> They are used for several tracers like irqsoff and preemptoff.
> Strange to say, however, they are refered even without FTRACE.
> 
> Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
> ---
>  arch/arm64/include/asm/ftrace.h    | 13 ++++++++-
>  arch/arm64/kernel/Makefile         |  3 ++-
>  arch/arm64/kernel/return_address.c | 55 ++++++++++++++++++++++++++++++++++++++
>  3 files changed, 69 insertions(+), 2 deletions(-)
>  create mode 100644 arch/arm64/kernel/return_address.c
> 
> diff --git a/arch/arm64/include/asm/ftrace.h b/arch/arm64/include/asm/ftrace.h
> index ed5c448..c44c4b1 100644
> --- a/arch/arm64/include/asm/ftrace.h
> +++ b/arch/arm64/include/asm/ftrace.h
> @@ -18,6 +18,7 @@
>  
>  #ifndef __ASSEMBLY__
>  extern void _mcount(unsigned long);
> +extern void *return_address(unsigned int);
>  
>  struct dyn_arch_ftrace {
>  	/* No extra data needed for arm64 */
> @@ -33,6 +34,16 @@ static inline unsigned long ftrace_call_adjust(unsigned long addr)
>  	 */
>  	return addr;
>  }
> -#endif /* __ASSEMBLY__ */
> +
> +#define HAVE_ARCH_CALLER_ADDR
> +
> +#define CALLER_ADDR0 ((unsigned long)__builtin_return_address(0))
> +#define CALLER_ADDR1 ((unsigned long)return_address(1))
> +#define CALLER_ADDR2 ((unsigned long)return_address(2))
> +#define CALLER_ADDR3 ((unsigned long)return_address(3))
> +#define CALLER_ADDR4 ((unsigned long)return_address(4))
> +#define CALLER_ADDR5 ((unsigned long)return_address(5))
> +#define CALLER_ADDR6 ((unsigned long)return_address(6))
> +#endif /* ifndef __ASSEMBLY__ */

Hmm, I thought you were going to take a look at reworking the core code for
this, as Steve and I suggested?

  http://lists.infradead.org/pipermail/linux-arm-kernel/2014-March/240239.html

Will

^ permalink raw reply	[flat|nested] 235+ messages in thread

* Re: [PATCH v7 6/7] arm64: ftrace: Add CALLER_ADDRx macros
  2014-04-16 13:52             ` Will Deacon
@ 2014-04-28 10:41               ` AKASHI Takahiro
  -1 siblings, 0 replies; 235+ messages in thread
From: AKASHI Takahiro @ 2014-04-28 10:41 UTC (permalink / raw)
  To: Will Deacon
  Cc: rostedt, fweisbec, mingo, Catalin Marinas, tim.bird, gkulkarni,
	dsaxena, arndb, linux-arm-kernel, linaro-kernel, linux-kernel

Hi Will,

On 04/16/2014 10:52 PM, Will Deacon wrote:
> On Sat, Mar 15, 2014 at 05:45:52AM +0000, AKASHI Takahiro wrote:
>> CALLER_ADDRx returns caller's address at specified level in call stacks.
>> They are used for several tracers like irqsoff and preemptoff.
>> Strange to say, however, they are refered even without FTRACE.
>>
>> Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
>> ---
>>   arch/arm64/include/asm/ftrace.h    | 13 ++++++++-
>>   arch/arm64/kernel/Makefile         |  3 ++-
>>   arch/arm64/kernel/return_address.c | 55 ++++++++++++++++++++++++++++++++++++++
>>   3 files changed, 69 insertions(+), 2 deletions(-)
>>   create mode 100644 arch/arm64/kernel/return_address.c
>>
>> diff --git a/arch/arm64/include/asm/ftrace.h b/arch/arm64/include/asm/ftrace.h
>> index ed5c448..c44c4b1 100644
>> --- a/arch/arm64/include/asm/ftrace.h
>> +++ b/arch/arm64/include/asm/ftrace.h
>> @@ -18,6 +18,7 @@
>>
>>   #ifndef __ASSEMBLY__
>>   extern void _mcount(unsigned long);
>> +extern void *return_address(unsigned int);
>>
>>   struct dyn_arch_ftrace {
>>   	/* No extra data needed for arm64 */
>> @@ -33,6 +34,16 @@ static inline unsigned long ftrace_call_adjust(unsigned long addr)
>>   	 */
>>   	return addr;
>>   }
>> -#endif /* __ASSEMBLY__ */
>> +
>> +#define HAVE_ARCH_CALLER_ADDR
>> +
>> +#define CALLER_ADDR0 ((unsigned long)__builtin_return_address(0))
>> +#define CALLER_ADDR1 ((unsigned long)return_address(1))
>> +#define CALLER_ADDR2 ((unsigned long)return_address(2))
>> +#define CALLER_ADDR3 ((unsigned long)return_address(3))
>> +#define CALLER_ADDR4 ((unsigned long)return_address(4))
>> +#define CALLER_ADDR5 ((unsigned long)return_address(5))
>> +#define CALLER_ADDR6 ((unsigned long)return_address(6))
>> +#endif /* ifndef __ASSEMBLY__ */
>
> Hmm, I thought you were going to take a look at reworking the core code for
> this, as Steve and I suggested?
>
>    http://lists.infradead.org/pipermail/linux-arm-kernel/2014-March/240239.html

Sorry that I've forgot to submit a new revision with this change.
I will post it soon.

Thanks,
-Takahiro AKASHI

> Will
>

^ permalink raw reply	[flat|nested] 235+ messages in thread

* [PATCH v7 6/7] arm64: ftrace: Add CALLER_ADDRx macros
@ 2014-04-28 10:41               ` AKASHI Takahiro
  0 siblings, 0 replies; 235+ messages in thread
From: AKASHI Takahiro @ 2014-04-28 10:41 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Will,

On 04/16/2014 10:52 PM, Will Deacon wrote:
> On Sat, Mar 15, 2014 at 05:45:52AM +0000, AKASHI Takahiro wrote:
>> CALLER_ADDRx returns caller's address at specified level in call stacks.
>> They are used for several tracers like irqsoff and preemptoff.
>> Strange to say, however, they are refered even without FTRACE.
>>
>> Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
>> ---
>>   arch/arm64/include/asm/ftrace.h    | 13 ++++++++-
>>   arch/arm64/kernel/Makefile         |  3 ++-
>>   arch/arm64/kernel/return_address.c | 55 ++++++++++++++++++++++++++++++++++++++
>>   3 files changed, 69 insertions(+), 2 deletions(-)
>>   create mode 100644 arch/arm64/kernel/return_address.c
>>
>> diff --git a/arch/arm64/include/asm/ftrace.h b/arch/arm64/include/asm/ftrace.h
>> index ed5c448..c44c4b1 100644
>> --- a/arch/arm64/include/asm/ftrace.h
>> +++ b/arch/arm64/include/asm/ftrace.h
>> @@ -18,6 +18,7 @@
>>
>>   #ifndef __ASSEMBLY__
>>   extern void _mcount(unsigned long);
>> +extern void *return_address(unsigned int);
>>
>>   struct dyn_arch_ftrace {
>>   	/* No extra data needed for arm64 */
>> @@ -33,6 +34,16 @@ static inline unsigned long ftrace_call_adjust(unsigned long addr)
>>   	 */
>>   	return addr;
>>   }
>> -#endif /* __ASSEMBLY__ */
>> +
>> +#define HAVE_ARCH_CALLER_ADDR
>> +
>> +#define CALLER_ADDR0 ((unsigned long)__builtin_return_address(0))
>> +#define CALLER_ADDR1 ((unsigned long)return_address(1))
>> +#define CALLER_ADDR2 ((unsigned long)return_address(2))
>> +#define CALLER_ADDR3 ((unsigned long)return_address(3))
>> +#define CALLER_ADDR4 ((unsigned long)return_address(4))
>> +#define CALLER_ADDR5 ((unsigned long)return_address(5))
>> +#define CALLER_ADDR6 ((unsigned long)return_address(6))
>> +#endif /* ifndef __ASSEMBLY__ */
>
> Hmm, I thought you were going to take a look at reworking the core code for
> this, as Steve and I suggested?
>
>    http://lists.infradead.org/pipermail/linux-arm-kernel/2014-March/240239.html

Sorry that I've forgot to submit a new revision with this change.
I will post it soon.

Thanks,
-Takahiro AKASHI

> Will
>

^ permalink raw reply	[flat|nested] 235+ messages in thread

* [PATCH v8 0/8] arm64: Add ftrace support
  2014-03-15  5:40           ` AKASHI Takahiro
@ 2014-04-30  9:54             ` AKASHI Takahiro
  -1 siblings, 0 replies; 235+ messages in thread
From: AKASHI Takahiro @ 2014-04-30  9:54 UTC (permalink / raw)
  To: rostedt, fweisbec, mingo, catalin.marinas, will.deacon, tim.bird
  Cc: gkulkarni, dsaxena, arndb, linux-arm-kernel, linaro-kernel,
	linux-kernel, AKASHI Takahiro

This patchset implements a function tracer on arm64.
There was another implementation from Cavium network, but both of us agreed
to use my patchset as future base. He is supposed to review this code, too.

The only issue that I had some concern on was "fault protection" code
in prepare_ftrace_return(). With discussions with Steven and Tim (as author
of arm ftrace), I removed that code since I'm not quite sure about possibility
of "fault" occurrences in this function.

The code is tested on ARMv8 Fast Model with the following tracers & events:
     function tracer with dynamic ftrace
     function graph tracer with dynamic ftrace
     syscall tracepoint (but only for AArch64 tasks)
     irqsoff & preemptirqsoff (which use CALLER_ADDRx)
and also verified with in-kernel tests, FTRACE_SELFTEST, FTRACE_STARTUP_TEST
and EVENT_TRACE_TEST_SYSCALLS.

Prerequisites are:
 * "arm64: make a single hook to syscall_trace() for all syscall features" patch
 * "arm64: split syscall_trace() into separate functions for enter/exit" patch
 * "arm64: Add regs_return_value() in syscall.h" patch
 * "arm64: is_compat_task is defined both in asm/compat.h and
    linux/compat.h" patch

Please be careful:
* Patch [3/7] gets warnings from checkpatch, but they are based on the
  original's coding style.
* Patch [7/7] may conflict with my audit patch because both changes the same
  location in syscall_trace_enter/exit(). I expect the functions are called
  in this order:
  On entry,
     * tracehook_report_syscall(ENTER)
     * trace_sys_enter()
     * audit_syscall_entry()
  On exit,
     * audit_sysscall_exit()
     * trace_sys_exit()
     * tracehook_report_syscall(EXIT) 

Changes from v7 to v8:
* rebased on 3.15-rc
* untabified the ascii art in entry-ftrace.S [5/8]
* added patch [1/8] in order to make CALLER_ADDRx() macro more generic across
  most architectures [1,7/8]

Changes from v6 to v7:
* changed to use gpfx variable instead of defining altmcount in recordmcount.c
  [3/7]
* declared return_to_handler using ENTRY/END macros [4/7]
* changed to use u32 instead of int as instruction words, and simplified
  ftrace_modify_graph_caller() [5/7]
* simplified arch_trace_is_compat_call() for readability [7/7]
* added the following patch to prerequisite list,
  "arm64: is_compat_task is defined both in asm/compat.h and linux/compat.h"
  and changed to use linux/compat.h instead of asm/compat.h in asm/ftrace.h
  to avoid compile errors against some files (ie. do_mounts.c and etc) if
  FTRACE & !COMPAT. [7/7]

Changes from v5 to v6:
* changed the order of patches to avoid any bisect error (I have not tried
  though)
* added EM_AARCH64 and R_AARCH64_ABS64 definitions in scripts/recordmcount.c
  just in case elf.h on host machine doesn't have them. [3/7]
* updated a frame pointer (x29) in _mcount() to make it look like a normal
  function [4/7]
* aligned with the patch, "arm64: split syscall_trace() into separate
  functions for enter/exit" [7/7]
* defined ARCH_TRACE_IGNORE_COMPAT_SYSCALLS in order not to trace compat
  syscalls [7/7]

Chnages from v4 to v5:
* improved the description of stack layout [1/7]
* aligned with the change in "arm64: make a single hook to syscall_trace()
  for all syscall features" v3 [5/7]

Changes from v3 to v4:
* removed unnecessary "#ifdef" [1,2/7]
* changed stack depth from 48B to 16B in mcount()/ftrace_caller() (a bug) [1/7]
* changed MCOUNT_INSN_SIZE to AARCH64_INSN_SIZE [1,7/7]
* added a guard againt TIF_SYSCALL_TRACEPOINT [5/7]
* corrected the second argument passed to trace_sys_exit() (a bug) [5/7]
* aligned with the change in "arm64: make a single hook to syscall_trace()
  for all syscall features" v2 [5/7]

Changes from v2 to v3:
* optimized register usages in asm (by not saving x0, x1, and x2)
* removed "fault protection" code in prepare_ftrace_return()
* rewrote ftrace_modify_code() using "hotpatch" interfaces
* revised descriptions in comments

Changes from v1 to v2:
* splitted one patch into some pieces for easier review
  (especially function tracer + dynamic ftrace + CALLER_ADDRx)
* put return_address() in a separate file
* renamed __mcount to _mcount (it was my mistake)
* changed stackframe handling to get parent's frame pointer
* removed ARCH_SUPPORTS_FTRACE_OPS
* switched to "hotpatch" interfaces from Huawai
* revised descriptions in comments

AKASHI Takahiro (7):
  arm64: add __ASSEMBLY__ in asm/insn.h
  arm64: Add 'notrace' attribute to unwind_frame() for ftrace
  ftrace: Add arm64 support to recordmcount
  arm64: Add ftrace support
  arm64: ftrace: Add dynamic ftrace support
  arm64: ftrace: Add CALLER_ADDRx macros
  arm64: ftrace: Add system call tracepoint

AKASHI Takahiro (8):
  ftrace: make CALLER_ADDRx macros more generic
  arm64: add __ASSEMBLY__ in asm/insn.h
  arm64: Add 'notrace' attribute to unwind_frame() for ftrace
  ftrace: Add arm64 support to recordmcount
  arm64: Add ftrace support
  arm64: ftrace: Add dynamic ftrace support
  arm64: ftrace: Add CALLER_ADDRx macros
  arm64: ftrace: Add system call tracepoint

 arch/arm/include/asm/ftrace.h      |   10 +-
 arch/arm64/Kconfig                 |    6 +
 arch/arm64/include/asm/ftrace.h    |   59 ++++++++++
 arch/arm64/include/asm/insn.h      |    2 +
 arch/arm64/include/asm/syscall.h   |    1 +
 arch/arm64/include/asm/unistd.h    |    2 +
 arch/arm64/kernel/Makefile         |    7 +-
 arch/arm64/kernel/arm64ksyms.c     |    4 +
 arch/arm64/kernel/entry-ftrace.S   |  218 ++++++++++++++++++++++++++++++++++++
 arch/arm64/kernel/ftrace.c         |  176 +++++++++++++++++++++++++++++
 arch/arm64/kernel/ptrace.c         |    9 ++
 arch/arm64/kernel/return_address.c |   55 +++++++++
 arch/arm64/kernel/stacktrace.c     |    2 +-
 arch/blackfin/include/asm/ftrace.h |   11 +-
 arch/parisc/include/asm/ftrace.h   |   10 +-
 arch/sh/include/asm/ftrace.h       |   10 +-
 arch/xtensa/include/asm/ftrace.h   |   14 +--
 include/linux/ftrace.h             |   34 +++---
 scripts/recordmcount.c             |    7 ++
 scripts/recordmcount.pl            |    5 +
 20 files changed, 577 insertions(+), 65 deletions(-)
 create mode 100644 arch/arm64/include/asm/ftrace.h
 create mode 100644 arch/arm64/kernel/entry-ftrace.S
 create mode 100644 arch/arm64/kernel/ftrace.c
 create mode 100644 arch/arm64/kernel/return_address.c

-- 
1.7.9.5


^ permalink raw reply	[flat|nested] 235+ messages in thread

* [PATCH v8 0/8] arm64: Add ftrace support
@ 2014-04-30  9:54             ` AKASHI Takahiro
  0 siblings, 0 replies; 235+ messages in thread
From: AKASHI Takahiro @ 2014-04-30  9:54 UTC (permalink / raw)
  To: linux-arm-kernel

This patchset implements a function tracer on arm64.
There was another implementation from Cavium network, but both of us agreed
to use my patchset as future base. He is supposed to review this code, too.

The only issue that I had some concern on was "fault protection" code
in prepare_ftrace_return(). With discussions with Steven and Tim (as author
of arm ftrace), I removed that code since I'm not quite sure about possibility
of "fault" occurrences in this function.

The code is tested on ARMv8 Fast Model with the following tracers & events:
     function tracer with dynamic ftrace
     function graph tracer with dynamic ftrace
     syscall tracepoint (but only for AArch64 tasks)
     irqsoff & preemptirqsoff (which use CALLER_ADDRx)
and also verified with in-kernel tests, FTRACE_SELFTEST, FTRACE_STARTUP_TEST
and EVENT_TRACE_TEST_SYSCALLS.

Prerequisites are:
 * "arm64: make a single hook to syscall_trace() for all syscall features" patch
 * "arm64: split syscall_trace() into separate functions for enter/exit" patch
 * "arm64: Add regs_return_value() in syscall.h" patch
 * "arm64: is_compat_task is defined both in asm/compat.h and
    linux/compat.h" patch

Please be careful:
* Patch [3/7] gets warnings from checkpatch, but they are based on the
  original's coding style.
* Patch [7/7] may conflict with my audit patch because both changes the same
  location in syscall_trace_enter/exit(). I expect the functions are called
  in this order:
  On entry,
     * tracehook_report_syscall(ENTER)
     * trace_sys_enter()
     * audit_syscall_entry()
  On exit,
     * audit_sysscall_exit()
     * trace_sys_exit()
     * tracehook_report_syscall(EXIT) 

Changes from v7 to v8:
* rebased on 3.15-rc
* untabified the ascii art in entry-ftrace.S [5/8]
* added patch [1/8] in order to make CALLER_ADDRx() macro more generic across
  most architectures [1,7/8]

Changes from v6 to v7:
* changed to use gpfx variable instead of defining altmcount in recordmcount.c
  [3/7]
* declared return_to_handler using ENTRY/END macros [4/7]
* changed to use u32 instead of int as instruction words, and simplified
  ftrace_modify_graph_caller() [5/7]
* simplified arch_trace_is_compat_call() for readability [7/7]
* added the following patch to prerequisite list,
  "arm64: is_compat_task is defined both in asm/compat.h and linux/compat.h"
  and changed to use linux/compat.h instead of asm/compat.h in asm/ftrace.h
  to avoid compile errors against some files (ie. do_mounts.c and etc) if
  FTRACE & !COMPAT. [7/7]

Changes from v5 to v6:
* changed the order of patches to avoid any bisect error (I have not tried
  though)
* added EM_AARCH64 and R_AARCH64_ABS64 definitions in scripts/recordmcount.c
  just in case elf.h on host machine doesn't have them. [3/7]
* updated a frame pointer (x29) in _mcount() to make it look like a normal
  function [4/7]
* aligned with the patch, "arm64: split syscall_trace() into separate
  functions for enter/exit" [7/7]
* defined ARCH_TRACE_IGNORE_COMPAT_SYSCALLS in order not to trace compat
  syscalls [7/7]

Chnages from v4 to v5:
* improved the description of stack layout [1/7]
* aligned with the change in "arm64: make a single hook to syscall_trace()
  for all syscall features" v3 [5/7]

Changes from v3 to v4:
* removed unnecessary "#ifdef" [1,2/7]
* changed stack depth from 48B to 16B in mcount()/ftrace_caller() (a bug) [1/7]
* changed MCOUNT_INSN_SIZE to AARCH64_INSN_SIZE [1,7/7]
* added a guard againt TIF_SYSCALL_TRACEPOINT [5/7]
* corrected the second argument passed to trace_sys_exit() (a bug) [5/7]
* aligned with the change in "arm64: make a single hook to syscall_trace()
  for all syscall features" v2 [5/7]

Changes from v2 to v3:
* optimized register usages in asm (by not saving x0, x1, and x2)
* removed "fault protection" code in prepare_ftrace_return()
* rewrote ftrace_modify_code() using "hotpatch" interfaces
* revised descriptions in comments

Changes from v1 to v2:
* splitted one patch into some pieces for easier review
  (especially function tracer + dynamic ftrace + CALLER_ADDRx)
* put return_address() in a separate file
* renamed __mcount to _mcount (it was my mistake)
* changed stackframe handling to get parent's frame pointer
* removed ARCH_SUPPORTS_FTRACE_OPS
* switched to "hotpatch" interfaces from Huawai
* revised descriptions in comments

AKASHI Takahiro (7):
  arm64: add __ASSEMBLY__ in asm/insn.h
  arm64: Add 'notrace' attribute to unwind_frame() for ftrace
  ftrace: Add arm64 support to recordmcount
  arm64: Add ftrace support
  arm64: ftrace: Add dynamic ftrace support
  arm64: ftrace: Add CALLER_ADDRx macros
  arm64: ftrace: Add system call tracepoint

AKASHI Takahiro (8):
  ftrace: make CALLER_ADDRx macros more generic
  arm64: add __ASSEMBLY__ in asm/insn.h
  arm64: Add 'notrace' attribute to unwind_frame() for ftrace
  ftrace: Add arm64 support to recordmcount
  arm64: Add ftrace support
  arm64: ftrace: Add dynamic ftrace support
  arm64: ftrace: Add CALLER_ADDRx macros
  arm64: ftrace: Add system call tracepoint

 arch/arm/include/asm/ftrace.h      |   10 +-
 arch/arm64/Kconfig                 |    6 +
 arch/arm64/include/asm/ftrace.h    |   59 ++++++++++
 arch/arm64/include/asm/insn.h      |    2 +
 arch/arm64/include/asm/syscall.h   |    1 +
 arch/arm64/include/asm/unistd.h    |    2 +
 arch/arm64/kernel/Makefile         |    7 +-
 arch/arm64/kernel/arm64ksyms.c     |    4 +
 arch/arm64/kernel/entry-ftrace.S   |  218 ++++++++++++++++++++++++++++++++++++
 arch/arm64/kernel/ftrace.c         |  176 +++++++++++++++++++++++++++++
 arch/arm64/kernel/ptrace.c         |    9 ++
 arch/arm64/kernel/return_address.c |   55 +++++++++
 arch/arm64/kernel/stacktrace.c     |    2 +-
 arch/blackfin/include/asm/ftrace.h |   11 +-
 arch/parisc/include/asm/ftrace.h   |   10 +-
 arch/sh/include/asm/ftrace.h       |   10 +-
 arch/xtensa/include/asm/ftrace.h   |   14 +--
 include/linux/ftrace.h             |   34 +++---
 scripts/recordmcount.c             |    7 ++
 scripts/recordmcount.pl            |    5 +
 20 files changed, 577 insertions(+), 65 deletions(-)
 create mode 100644 arch/arm64/include/asm/ftrace.h
 create mode 100644 arch/arm64/kernel/entry-ftrace.S
 create mode 100644 arch/arm64/kernel/ftrace.c
 create mode 100644 arch/arm64/kernel/return_address.c

-- 
1.7.9.5

^ permalink raw reply	[flat|nested] 235+ messages in thread

* [PATCH v8 1/8] ftrace: make CALLER_ADDRx macros more generic
  2014-04-30  9:54             ` AKASHI Takahiro
@ 2014-04-30  9:54               ` AKASHI Takahiro
  -1 siblings, 0 replies; 235+ messages in thread
From: AKASHI Takahiro @ 2014-04-30  9:54 UTC (permalink / raw)
  To: rostedt, fweisbec, mingo, catalin.marinas, will.deacon, tim.bird
  Cc: gkulkarni, dsaxena, arndb, linux-arm-kernel, linaro-kernel,
	linux-kernel, AKASHI Takahiro

Most archs with HAVE_ARCH_CALLER_ADDR have the almost same definitions
of CALLER_ADDRx(n), and so put them into linux/ftrace.h.

Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
---
 arch/arm/include/asm/ftrace.h      |   10 +---------
 arch/blackfin/include/asm/ftrace.h |   11 +----------
 arch/parisc/include/asm/ftrace.h   |   10 +---------
 arch/sh/include/asm/ftrace.h       |   10 +---------
 arch/xtensa/include/asm/ftrace.h   |   14 ++++----------
 include/linux/ftrace.h             |   34 ++++++++++++++++++----------------
 6 files changed, 26 insertions(+), 63 deletions(-)

diff --git a/arch/arm/include/asm/ftrace.h b/arch/arm/include/asm/ftrace.h
index f89515a..eb577f4 100644
--- a/arch/arm/include/asm/ftrace.h
+++ b/arch/arm/include/asm/ftrace.h
@@ -52,15 +52,7 @@ extern inline void *return_address(unsigned int level)
 
 #endif
 
-#define HAVE_ARCH_CALLER_ADDR
-
-#define CALLER_ADDR0 ((unsigned long)__builtin_return_address(0))
-#define CALLER_ADDR1 ((unsigned long)return_address(1))
-#define CALLER_ADDR2 ((unsigned long)return_address(2))
-#define CALLER_ADDR3 ((unsigned long)return_address(3))
-#define CALLER_ADDR4 ((unsigned long)return_address(4))
-#define CALLER_ADDR5 ((unsigned long)return_address(5))
-#define CALLER_ADDR6 ((unsigned long)return_address(6))
+#define ftrace_return_addr(n) return_address(n)
 
 #endif /* ifndef __ASSEMBLY__ */
 
diff --git a/arch/blackfin/include/asm/ftrace.h b/arch/blackfin/include/asm/ftrace.h
index 8a02950..2f1c3c2 100644
--- a/arch/blackfin/include/asm/ftrace.h
+++ b/arch/blackfin/include/asm/ftrace.h
@@ -66,16 +66,7 @@ extern inline void *return_address(unsigned int level)
 
 #endif /* CONFIG_FRAME_POINTER */
 
-#define HAVE_ARCH_CALLER_ADDR
-
-/* inline function or macro may lead to unexpected result */
-#define CALLER_ADDR0 ((unsigned long)__builtin_return_address(0))
-#define CALLER_ADDR1 ((unsigned long)return_address(1))
-#define CALLER_ADDR2 ((unsigned long)return_address(2))
-#define CALLER_ADDR3 ((unsigned long)return_address(3))
-#define CALLER_ADDR4 ((unsigned long)return_address(4))
-#define CALLER_ADDR5 ((unsigned long)return_address(5))
-#define CALLER_ADDR6 ((unsigned long)return_address(6))
+#define ftrace_return_address(n) return_address(n)
 
 #endif /* __ASSEMBLY__ */
 
diff --git a/arch/parisc/include/asm/ftrace.h b/arch/parisc/include/asm/ftrace.h
index 72c0faf..544ed8e 100644
--- a/arch/parisc/include/asm/ftrace.h
+++ b/arch/parisc/include/asm/ftrace.h
@@ -24,15 +24,7 @@ extern void return_to_handler(void);
 
 extern unsigned long return_address(unsigned int);
 
-#define HAVE_ARCH_CALLER_ADDR
-
-#define CALLER_ADDR0 ((unsigned long)__builtin_return_address(0))
-#define CALLER_ADDR1 return_address(1)
-#define CALLER_ADDR2 return_address(2)
-#define CALLER_ADDR3 return_address(3)
-#define CALLER_ADDR4 return_address(4)
-#define CALLER_ADDR5 return_address(5)
-#define CALLER_ADDR6 return_address(6)
+#define ftrace_return_address(n) return_address(n)
 
 #endif /* __ASSEMBLY__ */
 
diff --git a/arch/sh/include/asm/ftrace.h b/arch/sh/include/asm/ftrace.h
index 13e9966..e79fb6e 100644
--- a/arch/sh/include/asm/ftrace.h
+++ b/arch/sh/include/asm/ftrace.h
@@ -40,15 +40,7 @@ static inline unsigned long ftrace_call_adjust(unsigned long addr)
 /* arch/sh/kernel/return_address.c */
 extern void *return_address(unsigned int);
 
-#define HAVE_ARCH_CALLER_ADDR
-
-#define CALLER_ADDR0 ((unsigned long)__builtin_return_address(0))
-#define CALLER_ADDR1 ((unsigned long)return_address(1))
-#define CALLER_ADDR2 ((unsigned long)return_address(2))
-#define CALLER_ADDR3 ((unsigned long)return_address(3))
-#define CALLER_ADDR4 ((unsigned long)return_address(4))
-#define CALLER_ADDR5 ((unsigned long)return_address(5))
-#define CALLER_ADDR6 ((unsigned long)return_address(6))
+#define ftrace_return_address(n) return_address(n)
 
 #endif /* __ASSEMBLY__ */
 
diff --git a/arch/xtensa/include/asm/ftrace.h b/arch/xtensa/include/asm/ftrace.h
index 736b9d2..6c6d9a9 100644
--- a/arch/xtensa/include/asm/ftrace.h
+++ b/arch/xtensa/include/asm/ftrace.h
@@ -12,24 +12,18 @@
 
 #include <asm/processor.h>
 
-#define HAVE_ARCH_CALLER_ADDR
 #ifndef __ASSEMBLY__
-#define CALLER_ADDR0 ({ unsigned long a0, a1; \
+#define ftrace_return_address0 ({ unsigned long a0, a1; \
 		__asm__ __volatile__ ( \
 			"mov %0, a0\n" \
 			"mov %1, a1\n" \
 			: "=r"(a0), "=r"(a1)); \
 		MAKE_PC_FROM_RA(a0, a1); })
+
 #ifdef CONFIG_FRAME_POINTER
 extern unsigned long return_address(unsigned level);
-#define CALLER_ADDR1 return_address(1)
-#define CALLER_ADDR2 return_address(2)
-#define CALLER_ADDR3 return_address(3)
-#else /* CONFIG_FRAME_POINTER */
-#define CALLER_ADDR1 (0)
-#define CALLER_ADDR2 (0)
-#define CALLER_ADDR3 (0)
-#endif /* CONFIG_FRAME_POINTER */
+#define ftrace_return_address(n) return_address(n)
+#endif
 #endif /* __ASSEMBLY__ */
 
 #ifdef CONFIG_FUNCTION_TRACER
diff --git a/include/linux/ftrace.h b/include/linux/ftrace.h
index 9212b01..18f1ae7 100644
--- a/include/linux/ftrace.h
+++ b/include/linux/ftrace.h
@@ -614,25 +614,27 @@ static inline void __ftrace_enabled_restore(int enabled)
 #endif
 }
 
-#ifndef HAVE_ARCH_CALLER_ADDR
+/* All archs should have this, but we define it for consistency */
+#ifndef ftrace_return_address0
+# define ftrace_return_address0 __builtin_return_address(0)
+#endif
+
+/* Archs may use other ways for ADDR1 and beyond */
+#ifndef ftrace_return_address
 # ifdef CONFIG_FRAME_POINTER
-#  define CALLER_ADDR0 ((unsigned long)__builtin_return_address(0))
-#  define CALLER_ADDR1 ((unsigned long)__builtin_return_address(1))
-#  define CALLER_ADDR2 ((unsigned long)__builtin_return_address(2))
-#  define CALLER_ADDR3 ((unsigned long)__builtin_return_address(3))
-#  define CALLER_ADDR4 ((unsigned long)__builtin_return_address(4))
-#  define CALLER_ADDR5 ((unsigned long)__builtin_return_address(5))
-#  define CALLER_ADDR6 ((unsigned long)__builtin_return_address(6))
+#  define ftrace_return_address(n) __builtin_return_address(n)
 # else
-#  define CALLER_ADDR0 ((unsigned long)__builtin_return_address(0))
-#  define CALLER_ADDR1 0UL
-#  define CALLER_ADDR2 0UL
-#  define CALLER_ADDR3 0UL
-#  define CALLER_ADDR4 0UL
-#  define CALLER_ADDR5 0UL
-#  define CALLER_ADDR6 0UL
+#  define ftrace_return_address(n) 0UL
 # endif
-#endif /* ifndef HAVE_ARCH_CALLER_ADDR */
+#endif
+
+#define CALLER_ADDR0 ((unsigned long)ftrace_return_address0)
+#define CALLER_ADDR1 ((unsigned long)ftrace_return_address(1))
+#define CALLER_ADDR2 ((unsigned long)ftrace_return_address(2))
+#define CALLER_ADDR3 ((unsigned long)ftrace_return_address(3))
+#define CALLER_ADDR4 ((unsigned long)ftrace_return_address(4))
+#define CALLER_ADDR5 ((unsigned long)ftrace_return_address(5))
+#define CALLER_ADDR6 ((unsigned long)ftrace_return_address(6))
 
 #ifdef CONFIG_IRQSOFF_TRACER
   extern void time_hardirqs_on(unsigned long a0, unsigned long a1);
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 235+ messages in thread

* [PATCH v8 1/8] ftrace: make CALLER_ADDRx macros more generic
@ 2014-04-30  9:54               ` AKASHI Takahiro
  0 siblings, 0 replies; 235+ messages in thread
From: AKASHI Takahiro @ 2014-04-30  9:54 UTC (permalink / raw)
  To: linux-arm-kernel

Most archs with HAVE_ARCH_CALLER_ADDR have the almost same definitions
of CALLER_ADDRx(n), and so put them into linux/ftrace.h.

Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
---
 arch/arm/include/asm/ftrace.h      |   10 +---------
 arch/blackfin/include/asm/ftrace.h |   11 +----------
 arch/parisc/include/asm/ftrace.h   |   10 +---------
 arch/sh/include/asm/ftrace.h       |   10 +---------
 arch/xtensa/include/asm/ftrace.h   |   14 ++++----------
 include/linux/ftrace.h             |   34 ++++++++++++++++++----------------
 6 files changed, 26 insertions(+), 63 deletions(-)

diff --git a/arch/arm/include/asm/ftrace.h b/arch/arm/include/asm/ftrace.h
index f89515a..eb577f4 100644
--- a/arch/arm/include/asm/ftrace.h
+++ b/arch/arm/include/asm/ftrace.h
@@ -52,15 +52,7 @@ extern inline void *return_address(unsigned int level)
 
 #endif
 
-#define HAVE_ARCH_CALLER_ADDR
-
-#define CALLER_ADDR0 ((unsigned long)__builtin_return_address(0))
-#define CALLER_ADDR1 ((unsigned long)return_address(1))
-#define CALLER_ADDR2 ((unsigned long)return_address(2))
-#define CALLER_ADDR3 ((unsigned long)return_address(3))
-#define CALLER_ADDR4 ((unsigned long)return_address(4))
-#define CALLER_ADDR5 ((unsigned long)return_address(5))
-#define CALLER_ADDR6 ((unsigned long)return_address(6))
+#define ftrace_return_addr(n) return_address(n)
 
 #endif /* ifndef __ASSEMBLY__ */
 
diff --git a/arch/blackfin/include/asm/ftrace.h b/arch/blackfin/include/asm/ftrace.h
index 8a02950..2f1c3c2 100644
--- a/arch/blackfin/include/asm/ftrace.h
+++ b/arch/blackfin/include/asm/ftrace.h
@@ -66,16 +66,7 @@ extern inline void *return_address(unsigned int level)
 
 #endif /* CONFIG_FRAME_POINTER */
 
-#define HAVE_ARCH_CALLER_ADDR
-
-/* inline function or macro may lead to unexpected result */
-#define CALLER_ADDR0 ((unsigned long)__builtin_return_address(0))
-#define CALLER_ADDR1 ((unsigned long)return_address(1))
-#define CALLER_ADDR2 ((unsigned long)return_address(2))
-#define CALLER_ADDR3 ((unsigned long)return_address(3))
-#define CALLER_ADDR4 ((unsigned long)return_address(4))
-#define CALLER_ADDR5 ((unsigned long)return_address(5))
-#define CALLER_ADDR6 ((unsigned long)return_address(6))
+#define ftrace_return_address(n) return_address(n)
 
 #endif /* __ASSEMBLY__ */
 
diff --git a/arch/parisc/include/asm/ftrace.h b/arch/parisc/include/asm/ftrace.h
index 72c0faf..544ed8e 100644
--- a/arch/parisc/include/asm/ftrace.h
+++ b/arch/parisc/include/asm/ftrace.h
@@ -24,15 +24,7 @@ extern void return_to_handler(void);
 
 extern unsigned long return_address(unsigned int);
 
-#define HAVE_ARCH_CALLER_ADDR
-
-#define CALLER_ADDR0 ((unsigned long)__builtin_return_address(0))
-#define CALLER_ADDR1 return_address(1)
-#define CALLER_ADDR2 return_address(2)
-#define CALLER_ADDR3 return_address(3)
-#define CALLER_ADDR4 return_address(4)
-#define CALLER_ADDR5 return_address(5)
-#define CALLER_ADDR6 return_address(6)
+#define ftrace_return_address(n) return_address(n)
 
 #endif /* __ASSEMBLY__ */
 
diff --git a/arch/sh/include/asm/ftrace.h b/arch/sh/include/asm/ftrace.h
index 13e9966..e79fb6e 100644
--- a/arch/sh/include/asm/ftrace.h
+++ b/arch/sh/include/asm/ftrace.h
@@ -40,15 +40,7 @@ static inline unsigned long ftrace_call_adjust(unsigned long addr)
 /* arch/sh/kernel/return_address.c */
 extern void *return_address(unsigned int);
 
-#define HAVE_ARCH_CALLER_ADDR
-
-#define CALLER_ADDR0 ((unsigned long)__builtin_return_address(0))
-#define CALLER_ADDR1 ((unsigned long)return_address(1))
-#define CALLER_ADDR2 ((unsigned long)return_address(2))
-#define CALLER_ADDR3 ((unsigned long)return_address(3))
-#define CALLER_ADDR4 ((unsigned long)return_address(4))
-#define CALLER_ADDR5 ((unsigned long)return_address(5))
-#define CALLER_ADDR6 ((unsigned long)return_address(6))
+#define ftrace_return_address(n) return_address(n)
 
 #endif /* __ASSEMBLY__ */
 
diff --git a/arch/xtensa/include/asm/ftrace.h b/arch/xtensa/include/asm/ftrace.h
index 736b9d2..6c6d9a9 100644
--- a/arch/xtensa/include/asm/ftrace.h
+++ b/arch/xtensa/include/asm/ftrace.h
@@ -12,24 +12,18 @@
 
 #include <asm/processor.h>
 
-#define HAVE_ARCH_CALLER_ADDR
 #ifndef __ASSEMBLY__
-#define CALLER_ADDR0 ({ unsigned long a0, a1; \
+#define ftrace_return_address0 ({ unsigned long a0, a1; \
 		__asm__ __volatile__ ( \
 			"mov %0, a0\n" \
 			"mov %1, a1\n" \
 			: "=r"(a0), "=r"(a1)); \
 		MAKE_PC_FROM_RA(a0, a1); })
+
 #ifdef CONFIG_FRAME_POINTER
 extern unsigned long return_address(unsigned level);
-#define CALLER_ADDR1 return_address(1)
-#define CALLER_ADDR2 return_address(2)
-#define CALLER_ADDR3 return_address(3)
-#else /* CONFIG_FRAME_POINTER */
-#define CALLER_ADDR1 (0)
-#define CALLER_ADDR2 (0)
-#define CALLER_ADDR3 (0)
-#endif /* CONFIG_FRAME_POINTER */
+#define ftrace_return_address(n) return_address(n)
+#endif
 #endif /* __ASSEMBLY__ */
 
 #ifdef CONFIG_FUNCTION_TRACER
diff --git a/include/linux/ftrace.h b/include/linux/ftrace.h
index 9212b01..18f1ae7 100644
--- a/include/linux/ftrace.h
+++ b/include/linux/ftrace.h
@@ -614,25 +614,27 @@ static inline void __ftrace_enabled_restore(int enabled)
 #endif
 }
 
-#ifndef HAVE_ARCH_CALLER_ADDR
+/* All archs should have this, but we define it for consistency */
+#ifndef ftrace_return_address0
+# define ftrace_return_address0 __builtin_return_address(0)
+#endif
+
+/* Archs may use other ways for ADDR1 and beyond */
+#ifndef ftrace_return_address
 # ifdef CONFIG_FRAME_POINTER
-#  define CALLER_ADDR0 ((unsigned long)__builtin_return_address(0))
-#  define CALLER_ADDR1 ((unsigned long)__builtin_return_address(1))
-#  define CALLER_ADDR2 ((unsigned long)__builtin_return_address(2))
-#  define CALLER_ADDR3 ((unsigned long)__builtin_return_address(3))
-#  define CALLER_ADDR4 ((unsigned long)__builtin_return_address(4))
-#  define CALLER_ADDR5 ((unsigned long)__builtin_return_address(5))
-#  define CALLER_ADDR6 ((unsigned long)__builtin_return_address(6))
+#  define ftrace_return_address(n) __builtin_return_address(n)
 # else
-#  define CALLER_ADDR0 ((unsigned long)__builtin_return_address(0))
-#  define CALLER_ADDR1 0UL
-#  define CALLER_ADDR2 0UL
-#  define CALLER_ADDR3 0UL
-#  define CALLER_ADDR4 0UL
-#  define CALLER_ADDR5 0UL
-#  define CALLER_ADDR6 0UL
+#  define ftrace_return_address(n) 0UL
 # endif
-#endif /* ifndef HAVE_ARCH_CALLER_ADDR */
+#endif
+
+#define CALLER_ADDR0 ((unsigned long)ftrace_return_address0)
+#define CALLER_ADDR1 ((unsigned long)ftrace_return_address(1))
+#define CALLER_ADDR2 ((unsigned long)ftrace_return_address(2))
+#define CALLER_ADDR3 ((unsigned long)ftrace_return_address(3))
+#define CALLER_ADDR4 ((unsigned long)ftrace_return_address(4))
+#define CALLER_ADDR5 ((unsigned long)ftrace_return_address(5))
+#define CALLER_ADDR6 ((unsigned long)ftrace_return_address(6))
 
 #ifdef CONFIG_IRQSOFF_TRACER
   extern void time_hardirqs_on(unsigned long a0, unsigned long a1);
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 235+ messages in thread

* [PATCH v8 2/8] arm64: add __ASSEMBLY__ in asm/insn.h
  2014-04-30  9:54             ` AKASHI Takahiro
@ 2014-04-30  9:54               ` AKASHI Takahiro
  -1 siblings, 0 replies; 235+ messages in thread
From: AKASHI Takahiro @ 2014-04-30  9:54 UTC (permalink / raw)
  To: rostedt, fweisbec, mingo, catalin.marinas, will.deacon, tim.bird
  Cc: gkulkarni, dsaxena, arndb, linux-arm-kernel, linaro-kernel,
	linux-kernel, AKASHI Takahiro

Since insn.h is indirectly included in asm/entry-ftrace.S,
we need to exclude some declarations by __ASSEMBLY__.

Acked-by: Will Deacon <will.deacon@arm.com>
Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
---
 arch/arm64/include/asm/insn.h |    2 ++
 1 file changed, 2 insertions(+)

diff --git a/arch/arm64/include/asm/insn.h b/arch/arm64/include/asm/insn.h
index c44ad39..dc1f73b 100644
--- a/arch/arm64/include/asm/insn.h
+++ b/arch/arm64/include/asm/insn.h
@@ -21,6 +21,7 @@
 /* A64 instructions are always 32 bits. */
 #define	AARCH64_INSN_SIZE		4
 
+#ifndef __ASSEMBLY__
 /*
  * ARM Architecture Reference Manual for ARMv8 Profile-A, Issue A.a
  * Section C3.1 "A64 instruction index by encoding":
@@ -104,5 +105,6 @@ bool aarch64_insn_hotpatch_safe(u32 old_insn, u32 new_insn);
 int aarch64_insn_patch_text_nosync(void *addr, u32 insn);
 int aarch64_insn_patch_text_sync(void *addrs[], u32 insns[], int cnt);
 int aarch64_insn_patch_text(void *addrs[], u32 insns[], int cnt);
+#endif /* __ASSEMBLY__ */
 
 #endif	/* __ASM_INSN_H */
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 235+ messages in thread

* [PATCH v8 2/8] arm64: add __ASSEMBLY__ in asm/insn.h
@ 2014-04-30  9:54               ` AKASHI Takahiro
  0 siblings, 0 replies; 235+ messages in thread
From: AKASHI Takahiro @ 2014-04-30  9:54 UTC (permalink / raw)
  To: linux-arm-kernel

Since insn.h is indirectly included in asm/entry-ftrace.S,
we need to exclude some declarations by __ASSEMBLY__.

Acked-by: Will Deacon <will.deacon@arm.com>
Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
---
 arch/arm64/include/asm/insn.h |    2 ++
 1 file changed, 2 insertions(+)

diff --git a/arch/arm64/include/asm/insn.h b/arch/arm64/include/asm/insn.h
index c44ad39..dc1f73b 100644
--- a/arch/arm64/include/asm/insn.h
+++ b/arch/arm64/include/asm/insn.h
@@ -21,6 +21,7 @@
 /* A64 instructions are always 32 bits. */
 #define	AARCH64_INSN_SIZE		4
 
+#ifndef __ASSEMBLY__
 /*
  * ARM Architecture Reference Manual for ARMv8 Profile-A, Issue A.a
  * Section C3.1 "A64 instruction index by encoding":
@@ -104,5 +105,6 @@ bool aarch64_insn_hotpatch_safe(u32 old_insn, u32 new_insn);
 int aarch64_insn_patch_text_nosync(void *addr, u32 insn);
 int aarch64_insn_patch_text_sync(void *addrs[], u32 insns[], int cnt);
 int aarch64_insn_patch_text(void *addrs[], u32 insns[], int cnt);
+#endif /* __ASSEMBLY__ */
 
 #endif	/* __ASM_INSN_H */
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 235+ messages in thread

* [PATCH v8 3/8] arm64: Add 'notrace' attribute to unwind_frame() for ftrace
  2014-04-30  9:54             ` AKASHI Takahiro
@ 2014-04-30  9:54               ` AKASHI Takahiro
  -1 siblings, 0 replies; 235+ messages in thread
From: AKASHI Takahiro @ 2014-04-30  9:54 UTC (permalink / raw)
  To: rostedt, fweisbec, mingo, catalin.marinas, will.deacon, tim.bird
  Cc: gkulkarni, dsaxena, arndb, linux-arm-kernel, linaro-kernel,
	linux-kernel, AKASHI Takahiro

walk_stackframe() calls unwind_frame(), and if walk_stackframe() is
"notrace", unwind_frame() should be also "notrace".

Acked-by: Will Deacon <will.deacon@arm.com>
Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
---
 arch/arm64/kernel/stacktrace.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm64/kernel/stacktrace.c b/arch/arm64/kernel/stacktrace.c
index 38f0558..55437ba 100644
--- a/arch/arm64/kernel/stacktrace.c
+++ b/arch/arm64/kernel/stacktrace.c
@@ -35,7 +35,7 @@
  *	ldp	x29, x30, [sp]
  *	add	sp, sp, #0x10
  */
-int unwind_frame(struct stackframe *frame)
+int notrace unwind_frame(struct stackframe *frame)
 {
 	unsigned long high, low;
 	unsigned long fp = frame->fp;
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 235+ messages in thread

* [PATCH v8 3/8] arm64: Add 'notrace' attribute to unwind_frame() for ftrace
@ 2014-04-30  9:54               ` AKASHI Takahiro
  0 siblings, 0 replies; 235+ messages in thread
From: AKASHI Takahiro @ 2014-04-30  9:54 UTC (permalink / raw)
  To: linux-arm-kernel

walk_stackframe() calls unwind_frame(), and if walk_stackframe() is
"notrace", unwind_frame() should be also "notrace".

Acked-by: Will Deacon <will.deacon@arm.com>
Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
---
 arch/arm64/kernel/stacktrace.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm64/kernel/stacktrace.c b/arch/arm64/kernel/stacktrace.c
index 38f0558..55437ba 100644
--- a/arch/arm64/kernel/stacktrace.c
+++ b/arch/arm64/kernel/stacktrace.c
@@ -35,7 +35,7 @@
  *	ldp	x29, x30, [sp]
  *	add	sp, sp, #0x10
  */
-int unwind_frame(struct stackframe *frame)
+int notrace unwind_frame(struct stackframe *frame)
 {
 	unsigned long high, low;
 	unsigned long fp = frame->fp;
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 235+ messages in thread

* [PATCH v8 4/8] ftrace: Add arm64 support to recordmcount
  2014-04-30  9:54             ` AKASHI Takahiro
@ 2014-04-30  9:54               ` AKASHI Takahiro
  -1 siblings, 0 replies; 235+ messages in thread
From: AKASHI Takahiro @ 2014-04-30  9:54 UTC (permalink / raw)
  To: rostedt, fweisbec, mingo, catalin.marinas, will.deacon, tim.bird
  Cc: gkulkarni, dsaxena, arndb, linux-arm-kernel, linaro-kernel,
	linux-kernel, AKASHI Takahiro

Recordmcount utility under scripts is run, after compiling each object,
to find out all the locations of calling _mcount() and put them into
specific seciton named __mcount_loc.
Then linker collects all such information into a table in the kernel image
(between __start_mcount_loc and __stop_mcount_loc) for later use by ftrace.

This patch adds arm64 specific definitions to identify such locations.
There are two types of implementation, C and Perl. On arm64, only C version
is used to build the kernel now that CONFIG_HAVE_C_RECORDMCOUNT is on.
But Perl version is also maintained.

This patch also contains a workaround just in case where a header file,
elf.h, on host machine doesn't have definitions of EM_AARCH64 nor
R_AARCH64_ABS64. Without them, compiling C version of recordmcount will
fail.

Acked-by: Will Deacon <will.deacon@arm.com>
Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
---
 arch/arm64/Kconfig      |    2 ++
 scripts/recordmcount.c  |    7 +++++++
 scripts/recordmcount.pl |    5 +++++
 3 files changed, 14 insertions(+)

diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index e6e4d37..f467285 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -30,12 +30,14 @@ config ARM64
 	select HAVE_ARCH_JUMP_LABEL
 	select HAVE_ARCH_KGDB
 	select HAVE_ARCH_TRACEHOOK
+	select HAVE_C_RECORDMCOUNT
 	select HAVE_DEBUG_BUGVERBOSE
 	select HAVE_DEBUG_KMEMLEAK
 	select HAVE_DMA_API_DEBUG
 	select HAVE_DMA_ATTRS
 	select HAVE_DMA_CONTIGUOUS
 	select HAVE_EFFICIENT_UNALIGNED_ACCESS
+	select HAVE_FTRACE_MCOUNT_RECORD
 	select HAVE_GENERIC_DMA_COHERENT
 	select HAVE_HW_BREAKPOINT if PERF_EVENTS
 	select HAVE_MEMBLOCK
diff --git a/scripts/recordmcount.c b/scripts/recordmcount.c
index 9c22317..e11aa4a 100644
--- a/scripts/recordmcount.c
+++ b/scripts/recordmcount.c
@@ -40,6 +40,11 @@
 #define R_METAG_NONE                     3
 #endif
 
+#ifndef EM_AARCH64
+#define EM_AARCH64	183
+#define R_AARCH64_ABS64	257
+#endif
+
 static int fd_map;	/* File descriptor for file being modified. */
 static int mmap_failed; /* Boolean flag. */
 static void *ehdr_curr; /* current ElfXX_Ehdr *  for resource cleanup */
@@ -347,6 +352,8 @@ do_file(char const *const fname)
 	case EM_ARM:	 reltype = R_ARM_ABS32;
 			 altmcount = "__gnu_mcount_nc";
 			 break;
+	case EM_AARCH64:
+			 reltype = R_AARCH64_ABS64; gpfx = '_'; break;
 	case EM_IA_64:	 reltype = R_IA64_IMM64;   gpfx = '_'; break;
 	case EM_METAG:	 reltype = R_METAG_ADDR32;
 			 altmcount = "_mcount_wrapper";
diff --git a/scripts/recordmcount.pl b/scripts/recordmcount.pl
index 91280b8..397b6b8 100755
--- a/scripts/recordmcount.pl
+++ b/scripts/recordmcount.pl
@@ -279,6 +279,11 @@ if ($arch eq "x86_64") {
     $mcount_regex = "^\\s*([0-9a-fA-F]+):\\s*R_ARM_(CALL|PC24|THM_CALL)" .
 			"\\s+(__gnu_mcount_nc|mcount)\$";
 
+} elsif ($arch eq "arm64") {
+    $alignment = 3;
+    $section_type = '%progbits';
+    $mcount_regex = "^\\s*([0-9a-fA-F]+):\\s*R_AARCH64_CALL26\\s+_mcount\$";
+    $type = ".quad";
 } elsif ($arch eq "ia64") {
     $mcount_regex = "^\\s*([0-9a-fA-F]+):.*\\s_mcount\$";
     $type = "data8";
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 235+ messages in thread

* [PATCH v8 4/8] ftrace: Add arm64 support to recordmcount
@ 2014-04-30  9:54               ` AKASHI Takahiro
  0 siblings, 0 replies; 235+ messages in thread
From: AKASHI Takahiro @ 2014-04-30  9:54 UTC (permalink / raw)
  To: linux-arm-kernel

Recordmcount utility under scripts is run, after compiling each object,
to find out all the locations of calling _mcount() and put them into
specific seciton named __mcount_loc.
Then linker collects all such information into a table in the kernel image
(between __start_mcount_loc and __stop_mcount_loc) for later use by ftrace.

This patch adds arm64 specific definitions to identify such locations.
There are two types of implementation, C and Perl. On arm64, only C version
is used to build the kernel now that CONFIG_HAVE_C_RECORDMCOUNT is on.
But Perl version is also maintained.

This patch also contains a workaround just in case where a header file,
elf.h, on host machine doesn't have definitions of EM_AARCH64 nor
R_AARCH64_ABS64. Without them, compiling C version of recordmcount will
fail.

Acked-by: Will Deacon <will.deacon@arm.com>
Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
---
 arch/arm64/Kconfig      |    2 ++
 scripts/recordmcount.c  |    7 +++++++
 scripts/recordmcount.pl |    5 +++++
 3 files changed, 14 insertions(+)

diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index e6e4d37..f467285 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -30,12 +30,14 @@ config ARM64
 	select HAVE_ARCH_JUMP_LABEL
 	select HAVE_ARCH_KGDB
 	select HAVE_ARCH_TRACEHOOK
+	select HAVE_C_RECORDMCOUNT
 	select HAVE_DEBUG_BUGVERBOSE
 	select HAVE_DEBUG_KMEMLEAK
 	select HAVE_DMA_API_DEBUG
 	select HAVE_DMA_ATTRS
 	select HAVE_DMA_CONTIGUOUS
 	select HAVE_EFFICIENT_UNALIGNED_ACCESS
+	select HAVE_FTRACE_MCOUNT_RECORD
 	select HAVE_GENERIC_DMA_COHERENT
 	select HAVE_HW_BREAKPOINT if PERF_EVENTS
 	select HAVE_MEMBLOCK
diff --git a/scripts/recordmcount.c b/scripts/recordmcount.c
index 9c22317..e11aa4a 100644
--- a/scripts/recordmcount.c
+++ b/scripts/recordmcount.c
@@ -40,6 +40,11 @@
 #define R_METAG_NONE                     3
 #endif
 
+#ifndef EM_AARCH64
+#define EM_AARCH64	183
+#define R_AARCH64_ABS64	257
+#endif
+
 static int fd_map;	/* File descriptor for file being modified. */
 static int mmap_failed; /* Boolean flag. */
 static void *ehdr_curr; /* current ElfXX_Ehdr *  for resource cleanup */
@@ -347,6 +352,8 @@ do_file(char const *const fname)
 	case EM_ARM:	 reltype = R_ARM_ABS32;
 			 altmcount = "__gnu_mcount_nc";
 			 break;
+	case EM_AARCH64:
+			 reltype = R_AARCH64_ABS64; gpfx = '_'; break;
 	case EM_IA_64:	 reltype = R_IA64_IMM64;   gpfx = '_'; break;
 	case EM_METAG:	 reltype = R_METAG_ADDR32;
 			 altmcount = "_mcount_wrapper";
diff --git a/scripts/recordmcount.pl b/scripts/recordmcount.pl
index 91280b8..397b6b8 100755
--- a/scripts/recordmcount.pl
+++ b/scripts/recordmcount.pl
@@ -279,6 +279,11 @@ if ($arch eq "x86_64") {
     $mcount_regex = "^\\s*([0-9a-fA-F]+):\\s*R_ARM_(CALL|PC24|THM_CALL)" .
 			"\\s+(__gnu_mcount_nc|mcount)\$";
 
+} elsif ($arch eq "arm64") {
+    $alignment = 3;
+    $section_type = '%progbits';
+    $mcount_regex = "^\\s*([0-9a-fA-F]+):\\s*R_AARCH64_CALL26\\s+_mcount\$";
+    $type = ".quad";
 } elsif ($arch eq "ia64") {
     $mcount_regex = "^\\s*([0-9a-fA-F]+):.*\\s_mcount\$";
     $type = "data8";
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 235+ messages in thread

* [PATCH v8 5/8] arm64: Add ftrace support
  2014-04-30  9:54             ` AKASHI Takahiro
@ 2014-04-30  9:54               ` AKASHI Takahiro
  -1 siblings, 0 replies; 235+ messages in thread
From: AKASHI Takahiro @ 2014-04-30  9:54 UTC (permalink / raw)
  To: rostedt, fweisbec, mingo, catalin.marinas, will.deacon, tim.bird
  Cc: gkulkarni, dsaxena, arndb, linux-arm-kernel, linaro-kernel,
	linux-kernel, AKASHI Takahiro

This patch implements arm64 specific part to support function tracers,
such as function (CONFIG_FUNCTION_TRACER), function_graph
(CONFIG_FUNCTION_GRAPH_TRACER) and function profiler
(CONFIG_FUNCTION_PROFILER).

With 'function' tracer, all the functions in the kernel are traced with
timestamps in ${sysfs}/tracing/trace. If function_graph tracer is
specified, call graph is generated.

The kernel must be compiled with -pg option so that _mcount() is inserted
at the beginning of functions. This function is called on every function's
entry as long as tracing is enabled.
In addition, function_graph tracer also needs to be able to probe function's
exit. ftrace_graph_caller() & return_to_handler do this by faking link
register's value to intercept function's return path.

More details on architecture specific requirements are described in
Documentation/trace/ftrace-design.txt.

Reviewed-by: Ganapatrao Kulkarni <ganapatrao.kulkarni@cavium.com>
Acked-by: Will Deacon <will.deacon@arm.com>
Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
---
 arch/arm64/Kconfig               |    2 +
 arch/arm64/include/asm/ftrace.h  |   23 +++++
 arch/arm64/kernel/Makefile       |    4 +
 arch/arm64/kernel/arm64ksyms.c   |    4 +
 arch/arm64/kernel/entry-ftrace.S |  175 ++++++++++++++++++++++++++++++++++++++
 arch/arm64/kernel/ftrace.c       |   64 ++++++++++++++
 6 files changed, 272 insertions(+)
 create mode 100644 arch/arm64/include/asm/ftrace.h
 create mode 100644 arch/arm64/kernel/entry-ftrace.S
 create mode 100644 arch/arm64/kernel/ftrace.c

diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index f467285..856007e 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -38,6 +38,8 @@ config ARM64
 	select HAVE_DMA_CONTIGUOUS
 	select HAVE_EFFICIENT_UNALIGNED_ACCESS
 	select HAVE_FTRACE_MCOUNT_RECORD
+	select HAVE_FUNCTION_TRACER
+	select HAVE_FUNCTION_GRAPH_TRACER
 	select HAVE_GENERIC_DMA_COHERENT
 	select HAVE_HW_BREAKPOINT if PERF_EVENTS
 	select HAVE_MEMBLOCK
diff --git a/arch/arm64/include/asm/ftrace.h b/arch/arm64/include/asm/ftrace.h
new file mode 100644
index 0000000..58ea595
--- /dev/null
+++ b/arch/arm64/include/asm/ftrace.h
@@ -0,0 +1,23 @@
+/*
+ * arch/arm64/include/asm/ftrace.h
+ *
+ * Copyright (C) 2013 Linaro Limited
+ * Author: AKASHI Takahiro <takahiro.akashi@linaro.org>
+ *
+ * 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.
+ */
+#ifndef __ASM_FTRACE_H
+#define __ASM_FTRACE_H
+
+#include <asm/insn.h>
+
+#define MCOUNT_ADDR		((unsigned long)_mcount)
+#define MCOUNT_INSN_SIZE	AARCH64_INSN_SIZE
+
+#ifndef __ASSEMBLY__
+extern void _mcount(unsigned long);
+#endif /* __ASSEMBLY__ */
+
+#endif /* __ASM_FTRACE_H */
diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile
index 7d811d9..1ebcb4c 100644
--- a/arch/arm64/kernel/Makefile
+++ b/arch/arm64/kernel/Makefile
@@ -5,6 +5,9 @@
 CPPFLAGS_vmlinux.lds	:= -DTEXT_OFFSET=$(TEXT_OFFSET)
 AFLAGS_head.o		:= -DTEXT_OFFSET=$(TEXT_OFFSET)
 
+CFLAGS_REMOVE_ftrace.o = -pg
+CFLAGS_REMOVE_insn.o = -pg
+
 # Object file lists.
 arm64-obj-y		:= cputable.o debug-monitors.o entry.o irq.o fpsimd.o	\
 			   entry-fpsimd.o process.o ptrace.o setup.o signal.o	\
@@ -13,6 +16,7 @@ arm64-obj-y		:= cputable.o debug-monitors.o entry.o irq.o fpsimd.o	\
 
 arm64-obj-$(CONFIG_COMPAT)		+= sys32.o kuser32.o signal32.o 	\
 					   sys_compat.o
+arm64-obj-$(CONFIG_FUNCTION_TRACER)	+= ftrace.o entry-ftrace.o
 arm64-obj-$(CONFIG_MODULES)		+= arm64ksyms.o module.o
 arm64-obj-$(CONFIG_SMP)			+= smp.o smp_spin_table.o topology.o
 arm64-obj-$(CONFIG_PERF_EVENTS)		+= perf_regs.o
diff --git a/arch/arm64/kernel/arm64ksyms.c b/arch/arm64/kernel/arm64ksyms.c
index 338b568..7f0512f 100644
--- a/arch/arm64/kernel/arm64ksyms.c
+++ b/arch/arm64/kernel/arm64ksyms.c
@@ -56,3 +56,7 @@ EXPORT_SYMBOL(clear_bit);
 EXPORT_SYMBOL(test_and_clear_bit);
 EXPORT_SYMBOL(change_bit);
 EXPORT_SYMBOL(test_and_change_bit);
+
+#ifdef CONFIG_FUNCTION_TRACER
+EXPORT_SYMBOL(_mcount);
+#endif
diff --git a/arch/arm64/kernel/entry-ftrace.S b/arch/arm64/kernel/entry-ftrace.S
new file mode 100644
index 0000000..b2d8c45
--- /dev/null
+++ b/arch/arm64/kernel/entry-ftrace.S
@@ -0,0 +1,175 @@
+/*
+ * arch/arm64/kernel/entry-ftrace.S
+ *
+ * Copyright (C) 2013 Linaro Limited
+ * Author: AKASHI Takahiro <takahiro.akashi@linaro.org>
+ *
+ * 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 <linux/linkage.h>
+#include <asm/ftrace.h>
+#include <asm/insn.h>
+
+/*
+ * Gcc with -pg will put the following code in the beginning of each function:
+ *      mov x0, x30
+ *      bl _mcount
+ *	[function's body ...]
+ * "bl _mcount" may be replaced to "bl ftrace_caller" or NOP if dynamic
+ * ftrace is enabled.
+ *
+ * Please note that x0 as an argument will not be used here because we can
+ * get lr(x30) of instrumented function at any time by winding up call stack
+ * as long as the kernel is compiled without -fomit-frame-pointer.
+ * (or CONFIG_FRAME_POINTER, this is forced on arm64)
+ *
+ * stack layout after mcount_enter in _mcount():
+ *
+ * current sp/fp =>  0:+-----+
+ * in _mcount()        | x29 | -> instrumented function's fp
+ *                     +-----+
+ *                     | x30 | -> _mcount()'s lr (= instrumented function's pc)
+ * old sp       => +16:+-----+
+ * when instrumented   |     |
+ * function calls      | ... |
+ * _mcount()           |     |
+ *                     |     |
+ * instrumented => +xx:+-----+
+ * function's fp       | x29 | -> parent's fp
+ *                     +-----+
+ *                     | x30 | -> instrumented function's lr (= parent's pc)
+ *                     +-----+
+ *                     | ... |
+ */
+
+	.macro mcount_enter
+	stp	x29, x30, [sp, #-16]!
+	mov	x29, sp
+	.endm
+
+	.macro mcount_exit
+	ldp	x29, x30, [sp], #16
+	ret
+	.endm
+
+	.macro mcount_adjust_addr rd, rn
+	sub	\rd, \rn, #AARCH64_INSN_SIZE
+	.endm
+
+	/* for instrumented function's parent */
+	.macro mcount_get_parent_fp reg
+	ldr	\reg, [x29]
+	ldr	\reg, [\reg]
+	.endm
+
+	/* for instrumented function */
+	.macro mcount_get_pc0 reg
+	mcount_adjust_addr	\reg, x30
+	.endm
+
+	.macro mcount_get_pc reg
+	ldr	\reg, [x29, #8]
+	mcount_adjust_addr	\reg, \reg
+	.endm
+
+	.macro mcount_get_lr reg
+	ldr	\reg, [x29]
+	ldr	\reg, [\reg, #8]
+	mcount_adjust_addr	\reg, \reg
+	.endm
+
+	.macro mcount_get_lr_addr reg
+	ldr	\reg, [x29]
+	add	\reg, \reg, #8
+	.endm
+
+/*
+ * void _mcount(unsigned long return_address)
+ * @return_address: return address to instrumented function
+ *
+ * This function makes calls, if enabled, to:
+ *     - tracer function to probe instrumented function's entry,
+ *     - ftrace_graph_caller to set up an exit hook
+ */
+ENTRY(_mcount)
+#ifdef CONFIG_HAVE_FUNCTION_TRACE_MCOUNT_TEST
+	ldr	x0, =ftrace_trace_stop
+	ldr	x0, [x0]		// if ftrace_trace_stop
+	ret				//   return;
+#endif
+	mcount_enter
+
+	ldr	x0, =ftrace_trace_function
+	ldr	x2, [x0]
+	adr	x0, ftrace_stub
+	cmp	x0, x2			// if (ftrace_trace_function
+	b.eq	skip_ftrace_call	//     != ftrace_stub) {
+
+	mcount_get_pc	x0		//       function's pc
+	mcount_get_lr	x1		//       function's lr (= parent's pc)
+	blr	x2			//   (*ftrace_trace_function)(pc, lr);
+
+#ifndef CONFIG_FUNCTION_GRAPH_TRACER
+skip_ftrace_call:			//   return;
+	mcount_exit			// }
+#else
+	mcount_exit			//   return;
+					// }
+skip_ftrace_call:
+	ldr	x1, =ftrace_graph_return
+	ldr	x2, [x1]		//   if ((ftrace_graph_return
+	cmp	x0, x2			//        != ftrace_stub)
+	b.ne	ftrace_graph_caller
+
+	ldr	x1, =ftrace_graph_entry	//     || (ftrace_graph_entry
+	ldr	x2, [x1]		//        != ftrace_graph_entry_stub))
+	ldr	x0, =ftrace_graph_entry_stub
+	cmp	x0, x2
+	b.ne	ftrace_graph_caller	//     ftrace_graph_caller();
+
+	mcount_exit
+#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
+ENDPROC(_mcount)
+
+ENTRY(ftrace_stub)
+	ret
+ENDPROC(ftrace_stub)
+
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+/*
+ * void ftrace_graph_caller(void)
+ *
+ * Called from _mcount() or ftrace_caller() when function_graph tracer is
+ * selected.
+ * This function w/ prepare_ftrace_return() fakes link register's value on
+ * the call stack in order to intercept instrumented function's return path
+ * and run return_to_handler() later on its exit.
+ */
+ENTRY(ftrace_graph_caller)
+	mcount_get_lr_addr	  x0	//     pointer to function's saved lr
+	mcount_get_pc		  x1	//     function's pc
+	mcount_get_parent_fp	  x2	//     parent's fp
+	bl	prepare_ftrace_return	// prepare_ftrace_return(&lr, pc, fp)
+
+	mcount_exit
+ENDPROC(ftrace_graph_caller)
+
+/*
+ * void return_to_handler(void)
+ *
+ * Run ftrace_return_to_handler() before going back to parent.
+ * @fp is checked against the value passed by ftrace_graph_caller()
+ * only when CONFIG_FUNCTION_GRAPH_FP_TEST is enabled.
+ */
+ENTRY(return_to_handler)
+	str	x0, [sp, #-16]!
+	mov	x0, x29			//     parent's fp
+	bl	ftrace_return_to_handler// addr = ftrace_return_to_hander(fp);
+	mov	x30, x0			// restore the original return address
+	ldr	x0, [sp], #16
+	ret
+END(return_to_handler)
+#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
diff --git a/arch/arm64/kernel/ftrace.c b/arch/arm64/kernel/ftrace.c
new file mode 100644
index 0000000..a559ab8
--- /dev/null
+++ b/arch/arm64/kernel/ftrace.c
@@ -0,0 +1,64 @@
+/*
+ * arch/arm64/kernel/ftrace.c
+ *
+ * Copyright (C) 2013 Linaro Limited
+ * Author: AKASHI Takahiro <takahiro.akashi@linaro.org>
+ *
+ * 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 <linux/ftrace.h>
+#include <linux/swab.h>
+#include <linux/uaccess.h>
+
+#include <asm/cacheflush.h>
+#include <asm/ftrace.h>
+#include <asm/insn.h>
+
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+/*
+ * function_graph tracer expects ftrace_return_to_handler() to be called
+ * on the way back to parent. For this purpose, this function is called
+ * in _mcount() or ftrace_caller() to replace return address (*parent) on
+ * the call stack to return_to_handler.
+ *
+ * Note that @frame_pointer is used only for sanity check later.
+ */
+void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr,
+			   unsigned long frame_pointer)
+{
+	unsigned long return_hooker = (unsigned long)&return_to_handler;
+	unsigned long old;
+	struct ftrace_graph_ent trace;
+	int err;
+
+	if (unlikely(atomic_read(&current->tracing_graph_pause)))
+		return;
+
+	/*
+	 * Note:
+	 * No protection against faulting at *parent, which may be seen
+	 * on other archs. It's unlikely on AArch64.
+	 */
+	old = *parent;
+	*parent = return_hooker;
+
+	trace.func = self_addr;
+	trace.depth = current->curr_ret_stack + 1;
+
+	/* Only trace if the calling function expects to */
+	if (!ftrace_graph_entry(&trace)) {
+		*parent = old;
+		return;
+	}
+
+	err = ftrace_push_return_trace(old, self_addr, &trace.depth,
+				       frame_pointer);
+	if (err == -EBUSY) {
+		*parent = old;
+		return;
+	}
+}
+#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 235+ messages in thread

* [PATCH v8 5/8] arm64: Add ftrace support
@ 2014-04-30  9:54               ` AKASHI Takahiro
  0 siblings, 0 replies; 235+ messages in thread
From: AKASHI Takahiro @ 2014-04-30  9:54 UTC (permalink / raw)
  To: linux-arm-kernel

This patch implements arm64 specific part to support function tracers,
such as function (CONFIG_FUNCTION_TRACER), function_graph
(CONFIG_FUNCTION_GRAPH_TRACER) and function profiler
(CONFIG_FUNCTION_PROFILER).

With 'function' tracer, all the functions in the kernel are traced with
timestamps in ${sysfs}/tracing/trace. If function_graph tracer is
specified, call graph is generated.

The kernel must be compiled with -pg option so that _mcount() is inserted
at the beginning of functions. This function is called on every function's
entry as long as tracing is enabled.
In addition, function_graph tracer also needs to be able to probe function's
exit. ftrace_graph_caller() & return_to_handler do this by faking link
register's value to intercept function's return path.

More details on architecture specific requirements are described in
Documentation/trace/ftrace-design.txt.

Reviewed-by: Ganapatrao Kulkarni <ganapatrao.kulkarni@cavium.com>
Acked-by: Will Deacon <will.deacon@arm.com>
Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
---
 arch/arm64/Kconfig               |    2 +
 arch/arm64/include/asm/ftrace.h  |   23 +++++
 arch/arm64/kernel/Makefile       |    4 +
 arch/arm64/kernel/arm64ksyms.c   |    4 +
 arch/arm64/kernel/entry-ftrace.S |  175 ++++++++++++++++++++++++++++++++++++++
 arch/arm64/kernel/ftrace.c       |   64 ++++++++++++++
 6 files changed, 272 insertions(+)
 create mode 100644 arch/arm64/include/asm/ftrace.h
 create mode 100644 arch/arm64/kernel/entry-ftrace.S
 create mode 100644 arch/arm64/kernel/ftrace.c

diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index f467285..856007e 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -38,6 +38,8 @@ config ARM64
 	select HAVE_DMA_CONTIGUOUS
 	select HAVE_EFFICIENT_UNALIGNED_ACCESS
 	select HAVE_FTRACE_MCOUNT_RECORD
+	select HAVE_FUNCTION_TRACER
+	select HAVE_FUNCTION_GRAPH_TRACER
 	select HAVE_GENERIC_DMA_COHERENT
 	select HAVE_HW_BREAKPOINT if PERF_EVENTS
 	select HAVE_MEMBLOCK
diff --git a/arch/arm64/include/asm/ftrace.h b/arch/arm64/include/asm/ftrace.h
new file mode 100644
index 0000000..58ea595
--- /dev/null
+++ b/arch/arm64/include/asm/ftrace.h
@@ -0,0 +1,23 @@
+/*
+ * arch/arm64/include/asm/ftrace.h
+ *
+ * Copyright (C) 2013 Linaro Limited
+ * Author: AKASHI Takahiro <takahiro.akashi@linaro.org>
+ *
+ * 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.
+ */
+#ifndef __ASM_FTRACE_H
+#define __ASM_FTRACE_H
+
+#include <asm/insn.h>
+
+#define MCOUNT_ADDR		((unsigned long)_mcount)
+#define MCOUNT_INSN_SIZE	AARCH64_INSN_SIZE
+
+#ifndef __ASSEMBLY__
+extern void _mcount(unsigned long);
+#endif /* __ASSEMBLY__ */
+
+#endif /* __ASM_FTRACE_H */
diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile
index 7d811d9..1ebcb4c 100644
--- a/arch/arm64/kernel/Makefile
+++ b/arch/arm64/kernel/Makefile
@@ -5,6 +5,9 @@
 CPPFLAGS_vmlinux.lds	:= -DTEXT_OFFSET=$(TEXT_OFFSET)
 AFLAGS_head.o		:= -DTEXT_OFFSET=$(TEXT_OFFSET)
 
+CFLAGS_REMOVE_ftrace.o = -pg
+CFLAGS_REMOVE_insn.o = -pg
+
 # Object file lists.
 arm64-obj-y		:= cputable.o debug-monitors.o entry.o irq.o fpsimd.o	\
 			   entry-fpsimd.o process.o ptrace.o setup.o signal.o	\
@@ -13,6 +16,7 @@ arm64-obj-y		:= cputable.o debug-monitors.o entry.o irq.o fpsimd.o	\
 
 arm64-obj-$(CONFIG_COMPAT)		+= sys32.o kuser32.o signal32.o 	\
 					   sys_compat.o
+arm64-obj-$(CONFIG_FUNCTION_TRACER)	+= ftrace.o entry-ftrace.o
 arm64-obj-$(CONFIG_MODULES)		+= arm64ksyms.o module.o
 arm64-obj-$(CONFIG_SMP)			+= smp.o smp_spin_table.o topology.o
 arm64-obj-$(CONFIG_PERF_EVENTS)		+= perf_regs.o
diff --git a/arch/arm64/kernel/arm64ksyms.c b/arch/arm64/kernel/arm64ksyms.c
index 338b568..7f0512f 100644
--- a/arch/arm64/kernel/arm64ksyms.c
+++ b/arch/arm64/kernel/arm64ksyms.c
@@ -56,3 +56,7 @@ EXPORT_SYMBOL(clear_bit);
 EXPORT_SYMBOL(test_and_clear_bit);
 EXPORT_SYMBOL(change_bit);
 EXPORT_SYMBOL(test_and_change_bit);
+
+#ifdef CONFIG_FUNCTION_TRACER
+EXPORT_SYMBOL(_mcount);
+#endif
diff --git a/arch/arm64/kernel/entry-ftrace.S b/arch/arm64/kernel/entry-ftrace.S
new file mode 100644
index 0000000..b2d8c45
--- /dev/null
+++ b/arch/arm64/kernel/entry-ftrace.S
@@ -0,0 +1,175 @@
+/*
+ * arch/arm64/kernel/entry-ftrace.S
+ *
+ * Copyright (C) 2013 Linaro Limited
+ * Author: AKASHI Takahiro <takahiro.akashi@linaro.org>
+ *
+ * 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 <linux/linkage.h>
+#include <asm/ftrace.h>
+#include <asm/insn.h>
+
+/*
+ * Gcc with -pg will put the following code in the beginning of each function:
+ *      mov x0, x30
+ *      bl _mcount
+ *	[function's body ...]
+ * "bl _mcount" may be replaced to "bl ftrace_caller" or NOP if dynamic
+ * ftrace is enabled.
+ *
+ * Please note that x0 as an argument will not be used here because we can
+ * get lr(x30) of instrumented function at any time by winding up call stack
+ * as long as the kernel is compiled without -fomit-frame-pointer.
+ * (or CONFIG_FRAME_POINTER, this is forced on arm64)
+ *
+ * stack layout after mcount_enter in _mcount():
+ *
+ * current sp/fp =>  0:+-----+
+ * in _mcount()        | x29 | -> instrumented function's fp
+ *                     +-----+
+ *                     | x30 | -> _mcount()'s lr (= instrumented function's pc)
+ * old sp       => +16:+-----+
+ * when instrumented   |     |
+ * function calls      | ... |
+ * _mcount()           |     |
+ *                     |     |
+ * instrumented => +xx:+-----+
+ * function's fp       | x29 | -> parent's fp
+ *                     +-----+
+ *                     | x30 | -> instrumented function's lr (= parent's pc)
+ *                     +-----+
+ *                     | ... |
+ */
+
+	.macro mcount_enter
+	stp	x29, x30, [sp, #-16]!
+	mov	x29, sp
+	.endm
+
+	.macro mcount_exit
+	ldp	x29, x30, [sp], #16
+	ret
+	.endm
+
+	.macro mcount_adjust_addr rd, rn
+	sub	\rd, \rn, #AARCH64_INSN_SIZE
+	.endm
+
+	/* for instrumented function's parent */
+	.macro mcount_get_parent_fp reg
+	ldr	\reg, [x29]
+	ldr	\reg, [\reg]
+	.endm
+
+	/* for instrumented function */
+	.macro mcount_get_pc0 reg
+	mcount_adjust_addr	\reg, x30
+	.endm
+
+	.macro mcount_get_pc reg
+	ldr	\reg, [x29, #8]
+	mcount_adjust_addr	\reg, \reg
+	.endm
+
+	.macro mcount_get_lr reg
+	ldr	\reg, [x29]
+	ldr	\reg, [\reg, #8]
+	mcount_adjust_addr	\reg, \reg
+	.endm
+
+	.macro mcount_get_lr_addr reg
+	ldr	\reg, [x29]
+	add	\reg, \reg, #8
+	.endm
+
+/*
+ * void _mcount(unsigned long return_address)
+ * @return_address: return address to instrumented function
+ *
+ * This function makes calls, if enabled, to:
+ *     - tracer function to probe instrumented function's entry,
+ *     - ftrace_graph_caller to set up an exit hook
+ */
+ENTRY(_mcount)
+#ifdef CONFIG_HAVE_FUNCTION_TRACE_MCOUNT_TEST
+	ldr	x0, =ftrace_trace_stop
+	ldr	x0, [x0]		// if ftrace_trace_stop
+	ret				//   return;
+#endif
+	mcount_enter
+
+	ldr	x0, =ftrace_trace_function
+	ldr	x2, [x0]
+	adr	x0, ftrace_stub
+	cmp	x0, x2			// if (ftrace_trace_function
+	b.eq	skip_ftrace_call	//     != ftrace_stub) {
+
+	mcount_get_pc	x0		//       function's pc
+	mcount_get_lr	x1		//       function's lr (= parent's pc)
+	blr	x2			//   (*ftrace_trace_function)(pc, lr);
+
+#ifndef CONFIG_FUNCTION_GRAPH_TRACER
+skip_ftrace_call:			//   return;
+	mcount_exit			// }
+#else
+	mcount_exit			//   return;
+					// }
+skip_ftrace_call:
+	ldr	x1, =ftrace_graph_return
+	ldr	x2, [x1]		//   if ((ftrace_graph_return
+	cmp	x0, x2			//        != ftrace_stub)
+	b.ne	ftrace_graph_caller
+
+	ldr	x1, =ftrace_graph_entry	//     || (ftrace_graph_entry
+	ldr	x2, [x1]		//        != ftrace_graph_entry_stub))
+	ldr	x0, =ftrace_graph_entry_stub
+	cmp	x0, x2
+	b.ne	ftrace_graph_caller	//     ftrace_graph_caller();
+
+	mcount_exit
+#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
+ENDPROC(_mcount)
+
+ENTRY(ftrace_stub)
+	ret
+ENDPROC(ftrace_stub)
+
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+/*
+ * void ftrace_graph_caller(void)
+ *
+ * Called from _mcount() or ftrace_caller() when function_graph tracer is
+ * selected.
+ * This function w/ prepare_ftrace_return() fakes link register's value on
+ * the call stack in order to intercept instrumented function's return path
+ * and run return_to_handler() later on its exit.
+ */
+ENTRY(ftrace_graph_caller)
+	mcount_get_lr_addr	  x0	//     pointer to function's saved lr
+	mcount_get_pc		  x1	//     function's pc
+	mcount_get_parent_fp	  x2	//     parent's fp
+	bl	prepare_ftrace_return	// prepare_ftrace_return(&lr, pc, fp)
+
+	mcount_exit
+ENDPROC(ftrace_graph_caller)
+
+/*
+ * void return_to_handler(void)
+ *
+ * Run ftrace_return_to_handler() before going back to parent.
+ * @fp is checked against the value passed by ftrace_graph_caller()
+ * only when CONFIG_FUNCTION_GRAPH_FP_TEST is enabled.
+ */
+ENTRY(return_to_handler)
+	str	x0, [sp, #-16]!
+	mov	x0, x29			//     parent's fp
+	bl	ftrace_return_to_handler// addr = ftrace_return_to_hander(fp);
+	mov	x30, x0			// restore the original return address
+	ldr	x0, [sp], #16
+	ret
+END(return_to_handler)
+#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
diff --git a/arch/arm64/kernel/ftrace.c b/arch/arm64/kernel/ftrace.c
new file mode 100644
index 0000000..a559ab8
--- /dev/null
+++ b/arch/arm64/kernel/ftrace.c
@@ -0,0 +1,64 @@
+/*
+ * arch/arm64/kernel/ftrace.c
+ *
+ * Copyright (C) 2013 Linaro Limited
+ * Author: AKASHI Takahiro <takahiro.akashi@linaro.org>
+ *
+ * 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 <linux/ftrace.h>
+#include <linux/swab.h>
+#include <linux/uaccess.h>
+
+#include <asm/cacheflush.h>
+#include <asm/ftrace.h>
+#include <asm/insn.h>
+
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+/*
+ * function_graph tracer expects ftrace_return_to_handler() to be called
+ * on the way back to parent. For this purpose, this function is called
+ * in _mcount() or ftrace_caller() to replace return address (*parent) on
+ * the call stack to return_to_handler.
+ *
+ * Note that @frame_pointer is used only for sanity check later.
+ */
+void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr,
+			   unsigned long frame_pointer)
+{
+	unsigned long return_hooker = (unsigned long)&return_to_handler;
+	unsigned long old;
+	struct ftrace_graph_ent trace;
+	int err;
+
+	if (unlikely(atomic_read(&current->tracing_graph_pause)))
+		return;
+
+	/*
+	 * Note:
+	 * No protection against faulting at *parent, which may be seen
+	 * on other archs. It's unlikely on AArch64.
+	 */
+	old = *parent;
+	*parent = return_hooker;
+
+	trace.func = self_addr;
+	trace.depth = current->curr_ret_stack + 1;
+
+	/* Only trace if the calling function expects to */
+	if (!ftrace_graph_entry(&trace)) {
+		*parent = old;
+		return;
+	}
+
+	err = ftrace_push_return_trace(old, self_addr, &trace.depth,
+				       frame_pointer);
+	if (err == -EBUSY) {
+		*parent = old;
+		return;
+	}
+}
+#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 235+ messages in thread

* [PATCH v8 6/8] arm64: ftrace: Add dynamic ftrace support
  2014-04-30  9:54             ` AKASHI Takahiro
@ 2014-04-30  9:54               ` AKASHI Takahiro
  -1 siblings, 0 replies; 235+ messages in thread
From: AKASHI Takahiro @ 2014-04-30  9:54 UTC (permalink / raw)
  To: rostedt, fweisbec, mingo, catalin.marinas, will.deacon, tim.bird
  Cc: gkulkarni, dsaxena, arndb, linux-arm-kernel, linaro-kernel,
	linux-kernel, AKASHI Takahiro

This patch allows "dynamic ftrace" if CONFIG_DYNAMIC_FTRACE is enabled.
Here we can turn on and off tracing dynamically per-function base.

On arm64, this is done by patching single branch instruction to _mcount()
inserted by gcc -pg option. The branch is replaced to NOP initially at
kernel start up, and later on, NOP to branch to ftrace_caller() when
enabled or branch to NOP when disabled.
Please note that ftrace_caller() is a counterpart of _mcount() in case of
'static' ftrace.

More details on architecture specific requirements are described in
Documentation/trace/ftrace-design.txt.

Acked-by: Will Deacon <will.deacon@arm.com>
Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
---
 arch/arm64/Kconfig               |    1 +
 arch/arm64/include/asm/ftrace.h  |   15 +++++
 arch/arm64/kernel/entry-ftrace.S |   43 +++++++++++++++
 arch/arm64/kernel/ftrace.c       |  112 ++++++++++++++++++++++++++++++++++++++
 4 files changed, 171 insertions(+)

diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 856007e..438a4ea 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -36,6 +36,7 @@ config ARM64
 	select HAVE_DMA_API_DEBUG
 	select HAVE_DMA_ATTRS
 	select HAVE_DMA_CONTIGUOUS
+	select HAVE_DYNAMIC_FTRACE
 	select HAVE_EFFICIENT_UNALIGNED_ACCESS
 	select HAVE_FTRACE_MCOUNT_RECORD
 	select HAVE_FUNCTION_TRACER
diff --git a/arch/arm64/include/asm/ftrace.h b/arch/arm64/include/asm/ftrace.h
index 58ea595..ed5c448 100644
--- a/arch/arm64/include/asm/ftrace.h
+++ b/arch/arm64/include/asm/ftrace.h
@@ -18,6 +18,21 @@
 
 #ifndef __ASSEMBLY__
 extern void _mcount(unsigned long);
+
+struct dyn_arch_ftrace {
+	/* No extra data needed for arm64 */
+};
+
+extern unsigned long ftrace_graph_call;
+
+static inline unsigned long ftrace_call_adjust(unsigned long addr)
+{
+	/*
+	 * addr is the address of the mcount call instruction.
+	 * recordmcount does the necessary offset calculation.
+	 */
+	return addr;
+}
 #endif /* __ASSEMBLY__ */
 
 #endif /* __ASM_FTRACE_H */
diff --git a/arch/arm64/kernel/entry-ftrace.S b/arch/arm64/kernel/entry-ftrace.S
index b2d8c45..b051871 100644
--- a/arch/arm64/kernel/entry-ftrace.S
+++ b/arch/arm64/kernel/entry-ftrace.S
@@ -86,6 +86,7 @@
 	add	\reg, \reg, #8
 	.endm
 
+#ifndef CONFIG_DYNAMIC_FTRACE
 /*
  * void _mcount(unsigned long return_address)
  * @return_address: return address to instrumented function
@@ -134,6 +135,48 @@ skip_ftrace_call:
 #endif /* CONFIG_FUNCTION_GRAPH_TRACER */
 ENDPROC(_mcount)
 
+#else /* CONFIG_DYNAMIC_FTRACE */
+/*
+ * _mcount() is used to build the kernel with -pg option, but all the branch
+ * instructions to _mcount() are replaced to NOP initially at kernel start up,
+ * and later on, NOP to branch to ftrace_caller() when enabled or branch to
+ * NOP when disabled per-function base.
+ */
+ENTRY(_mcount)
+	ret
+ENDPROC(_mcount)
+
+/*
+ * void ftrace_caller(unsigned long return_address)
+ * @return_address: return address to instrumented function
+ *
+ * This function is a counterpart of _mcount() in 'static' ftrace, and
+ * makes calls to:
+ *     - tracer function to probe instrumented function's entry,
+ *     - ftrace_graph_caller to set up an exit hook
+ */
+ENTRY(ftrace_caller)
+	mcount_enter
+
+	mcount_get_pc0	x0		//     function's pc
+	mcount_get_lr	x1		//     function's lr
+
+	.global ftrace_call
+ftrace_call:				// tracer(pc, lr);
+	nop				// This will be replaced with "bl xxx"
+					// where xxx can be any kind of tracer.
+
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+	.global ftrace_graph_call
+ftrace_graph_call:			// ftrace_graph_caller();
+	nop				// If enabled, this will be replaced
+					// "b ftrace_graph_caller"
+#endif
+
+	mcount_exit
+ENDPROC(ftrace_caller)
+#endif /* CONFIG_DYNAMIC_FTRACE */
+
 ENTRY(ftrace_stub)
 	ret
 ENDPROC(ftrace_stub)
diff --git a/arch/arm64/kernel/ftrace.c b/arch/arm64/kernel/ftrace.c
index a559ab8..7924d73 100644
--- a/arch/arm64/kernel/ftrace.c
+++ b/arch/arm64/kernel/ftrace.c
@@ -17,6 +17,87 @@
 #include <asm/ftrace.h>
 #include <asm/insn.h>
 
+#ifdef CONFIG_DYNAMIC_FTRACE
+/*
+ * Replace a single instruction, which may be a branch or NOP.
+ * If @validate == true, a replaced instruction is checked against 'old'.
+ */
+static int ftrace_modify_code(unsigned long pc, u32 old, u32 new,
+			      bool validate)
+{
+	u32 replaced;
+
+	/*
+	 * Note:
+	 * Due to modules and __init, code can disappear and change,
+	 * we need to protect against faulting as well as code changing.
+	 * We do this by aarch64_insn_*() which use the probe_kernel_*().
+	 *
+	 * No lock is held here because all the modifications are run
+	 * through stop_machine().
+	 */
+	if (validate) {
+		if (aarch64_insn_read((void *)pc, &replaced))
+			return -EFAULT;
+
+		if (replaced != old)
+			return -EINVAL;
+	}
+	if (aarch64_insn_patch_text_nosync((void *)pc, new))
+		return -EPERM;
+
+	return 0;
+}
+
+/*
+ * Replace tracer function in ftrace_caller()
+ */
+int ftrace_update_ftrace_func(ftrace_func_t func)
+{
+	unsigned long pc;
+	u32 new;
+
+	pc = (unsigned long)&ftrace_call;
+	new = aarch64_insn_gen_branch_imm(pc, (unsigned long)func, true);
+
+	return ftrace_modify_code(pc, 0, new, false);
+}
+
+/*
+ * Turn on the call to ftrace_caller() in instrumented function
+ */
+int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
+{
+	unsigned long pc = rec->ip;
+	u32 old, new;
+
+	old = aarch64_insn_gen_nop();
+	new = aarch64_insn_gen_branch_imm(pc, addr, true);
+
+	return ftrace_modify_code(pc, old, new, true);
+}
+
+/*
+ * Turn off the call to ftrace_caller() in instrumented function
+ */
+int ftrace_make_nop(struct module *mod, struct dyn_ftrace *rec,
+		    unsigned long addr)
+{
+	unsigned long pc = rec->ip;
+	u32 old, new;
+
+	old = aarch64_insn_gen_branch_imm(pc, addr, true);
+	new = aarch64_insn_gen_nop();
+
+	return ftrace_modify_code(pc, old, new, true);
+}
+
+int __init ftrace_dyn_arch_init(void)
+{
+	return 0;
+}
+#endif /* CONFIG_DYNAMIC_FTRACE */
+
 #ifdef CONFIG_FUNCTION_GRAPH_TRACER
 /*
  * function_graph tracer expects ftrace_return_to_handler() to be called
@@ -61,4 +142,35 @@ void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr,
 		return;
 	}
 }
+
+#ifdef CONFIG_DYNAMIC_FTRACE
+/*
+ * Turn on/off the call to ftrace_graph_caller() in ftrace_caller()
+ * depending on @enable.
+ */
+static int ftrace_modify_graph_caller(bool enable)
+{
+	unsigned long pc = (unsigned long)&ftrace_graph_call;
+	u32 branch, nop;
+
+	branch = aarch64_insn_gen_branch_imm(pc,
+			(unsigned long)ftrace_graph_caller, false);
+	nop = aarch64_insn_gen_nop();
+
+	if (enable)
+		return ftrace_modify_code(pc, nop, branch, true);
+	else
+		return ftrace_modify_code(pc, branch, nop, true);
+}
+
+int ftrace_enable_ftrace_graph_caller(void)
+{
+	return ftrace_modify_graph_caller(true);
+}
+
+int ftrace_disable_ftrace_graph_caller(void)
+{
+	return ftrace_modify_graph_caller(false);
+}
+#endif /* CONFIG_DYNAMIC_FTRACE */
 #endif /* CONFIG_FUNCTION_GRAPH_TRACER */
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 235+ messages in thread

* [PATCH v8 6/8] arm64: ftrace: Add dynamic ftrace support
@ 2014-04-30  9:54               ` AKASHI Takahiro
  0 siblings, 0 replies; 235+ messages in thread
From: AKASHI Takahiro @ 2014-04-30  9:54 UTC (permalink / raw)
  To: linux-arm-kernel

This patch allows "dynamic ftrace" if CONFIG_DYNAMIC_FTRACE is enabled.
Here we can turn on and off tracing dynamically per-function base.

On arm64, this is done by patching single branch instruction to _mcount()
inserted by gcc -pg option. The branch is replaced to NOP initially at
kernel start up, and later on, NOP to branch to ftrace_caller() when
enabled or branch to NOP when disabled.
Please note that ftrace_caller() is a counterpart of _mcount() in case of
'static' ftrace.

More details on architecture specific requirements are described in
Documentation/trace/ftrace-design.txt.

Acked-by: Will Deacon <will.deacon@arm.com>
Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
---
 arch/arm64/Kconfig               |    1 +
 arch/arm64/include/asm/ftrace.h  |   15 +++++
 arch/arm64/kernel/entry-ftrace.S |   43 +++++++++++++++
 arch/arm64/kernel/ftrace.c       |  112 ++++++++++++++++++++++++++++++++++++++
 4 files changed, 171 insertions(+)

diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 856007e..438a4ea 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -36,6 +36,7 @@ config ARM64
 	select HAVE_DMA_API_DEBUG
 	select HAVE_DMA_ATTRS
 	select HAVE_DMA_CONTIGUOUS
+	select HAVE_DYNAMIC_FTRACE
 	select HAVE_EFFICIENT_UNALIGNED_ACCESS
 	select HAVE_FTRACE_MCOUNT_RECORD
 	select HAVE_FUNCTION_TRACER
diff --git a/arch/arm64/include/asm/ftrace.h b/arch/arm64/include/asm/ftrace.h
index 58ea595..ed5c448 100644
--- a/arch/arm64/include/asm/ftrace.h
+++ b/arch/arm64/include/asm/ftrace.h
@@ -18,6 +18,21 @@
 
 #ifndef __ASSEMBLY__
 extern void _mcount(unsigned long);
+
+struct dyn_arch_ftrace {
+	/* No extra data needed for arm64 */
+};
+
+extern unsigned long ftrace_graph_call;
+
+static inline unsigned long ftrace_call_adjust(unsigned long addr)
+{
+	/*
+	 * addr is the address of the mcount call instruction.
+	 * recordmcount does the necessary offset calculation.
+	 */
+	return addr;
+}
 #endif /* __ASSEMBLY__ */
 
 #endif /* __ASM_FTRACE_H */
diff --git a/arch/arm64/kernel/entry-ftrace.S b/arch/arm64/kernel/entry-ftrace.S
index b2d8c45..b051871 100644
--- a/arch/arm64/kernel/entry-ftrace.S
+++ b/arch/arm64/kernel/entry-ftrace.S
@@ -86,6 +86,7 @@
 	add	\reg, \reg, #8
 	.endm
 
+#ifndef CONFIG_DYNAMIC_FTRACE
 /*
  * void _mcount(unsigned long return_address)
  * @return_address: return address to instrumented function
@@ -134,6 +135,48 @@ skip_ftrace_call:
 #endif /* CONFIG_FUNCTION_GRAPH_TRACER */
 ENDPROC(_mcount)
 
+#else /* CONFIG_DYNAMIC_FTRACE */
+/*
+ * _mcount() is used to build the kernel with -pg option, but all the branch
+ * instructions to _mcount() are replaced to NOP initially at kernel start up,
+ * and later on, NOP to branch to ftrace_caller() when enabled or branch to
+ * NOP when disabled per-function base.
+ */
+ENTRY(_mcount)
+	ret
+ENDPROC(_mcount)
+
+/*
+ * void ftrace_caller(unsigned long return_address)
+ * @return_address: return address to instrumented function
+ *
+ * This function is a counterpart of _mcount() in 'static' ftrace, and
+ * makes calls to:
+ *     - tracer function to probe instrumented function's entry,
+ *     - ftrace_graph_caller to set up an exit hook
+ */
+ENTRY(ftrace_caller)
+	mcount_enter
+
+	mcount_get_pc0	x0		//     function's pc
+	mcount_get_lr	x1		//     function's lr
+
+	.global ftrace_call
+ftrace_call:				// tracer(pc, lr);
+	nop				// This will be replaced with "bl xxx"
+					// where xxx can be any kind of tracer.
+
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+	.global ftrace_graph_call
+ftrace_graph_call:			// ftrace_graph_caller();
+	nop				// If enabled, this will be replaced
+					// "b ftrace_graph_caller"
+#endif
+
+	mcount_exit
+ENDPROC(ftrace_caller)
+#endif /* CONFIG_DYNAMIC_FTRACE */
+
 ENTRY(ftrace_stub)
 	ret
 ENDPROC(ftrace_stub)
diff --git a/arch/arm64/kernel/ftrace.c b/arch/arm64/kernel/ftrace.c
index a559ab8..7924d73 100644
--- a/arch/arm64/kernel/ftrace.c
+++ b/arch/arm64/kernel/ftrace.c
@@ -17,6 +17,87 @@
 #include <asm/ftrace.h>
 #include <asm/insn.h>
 
+#ifdef CONFIG_DYNAMIC_FTRACE
+/*
+ * Replace a single instruction, which may be a branch or NOP.
+ * If @validate == true, a replaced instruction is checked against 'old'.
+ */
+static int ftrace_modify_code(unsigned long pc, u32 old, u32 new,
+			      bool validate)
+{
+	u32 replaced;
+
+	/*
+	 * Note:
+	 * Due to modules and __init, code can disappear and change,
+	 * we need to protect against faulting as well as code changing.
+	 * We do this by aarch64_insn_*() which use the probe_kernel_*().
+	 *
+	 * No lock is held here because all the modifications are run
+	 * through stop_machine().
+	 */
+	if (validate) {
+		if (aarch64_insn_read((void *)pc, &replaced))
+			return -EFAULT;
+
+		if (replaced != old)
+			return -EINVAL;
+	}
+	if (aarch64_insn_patch_text_nosync((void *)pc, new))
+		return -EPERM;
+
+	return 0;
+}
+
+/*
+ * Replace tracer function in ftrace_caller()
+ */
+int ftrace_update_ftrace_func(ftrace_func_t func)
+{
+	unsigned long pc;
+	u32 new;
+
+	pc = (unsigned long)&ftrace_call;
+	new = aarch64_insn_gen_branch_imm(pc, (unsigned long)func, true);
+
+	return ftrace_modify_code(pc, 0, new, false);
+}
+
+/*
+ * Turn on the call to ftrace_caller() in instrumented function
+ */
+int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
+{
+	unsigned long pc = rec->ip;
+	u32 old, new;
+
+	old = aarch64_insn_gen_nop();
+	new = aarch64_insn_gen_branch_imm(pc, addr, true);
+
+	return ftrace_modify_code(pc, old, new, true);
+}
+
+/*
+ * Turn off the call to ftrace_caller() in instrumented function
+ */
+int ftrace_make_nop(struct module *mod, struct dyn_ftrace *rec,
+		    unsigned long addr)
+{
+	unsigned long pc = rec->ip;
+	u32 old, new;
+
+	old = aarch64_insn_gen_branch_imm(pc, addr, true);
+	new = aarch64_insn_gen_nop();
+
+	return ftrace_modify_code(pc, old, new, true);
+}
+
+int __init ftrace_dyn_arch_init(void)
+{
+	return 0;
+}
+#endif /* CONFIG_DYNAMIC_FTRACE */
+
 #ifdef CONFIG_FUNCTION_GRAPH_TRACER
 /*
  * function_graph tracer expects ftrace_return_to_handler() to be called
@@ -61,4 +142,35 @@ void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr,
 		return;
 	}
 }
+
+#ifdef CONFIG_DYNAMIC_FTRACE
+/*
+ * Turn on/off the call to ftrace_graph_caller() in ftrace_caller()
+ * depending on @enable.
+ */
+static int ftrace_modify_graph_caller(bool enable)
+{
+	unsigned long pc = (unsigned long)&ftrace_graph_call;
+	u32 branch, nop;
+
+	branch = aarch64_insn_gen_branch_imm(pc,
+			(unsigned long)ftrace_graph_caller, false);
+	nop = aarch64_insn_gen_nop();
+
+	if (enable)
+		return ftrace_modify_code(pc, nop, branch, true);
+	else
+		return ftrace_modify_code(pc, branch, nop, true);
+}
+
+int ftrace_enable_ftrace_graph_caller(void)
+{
+	return ftrace_modify_graph_caller(true);
+}
+
+int ftrace_disable_ftrace_graph_caller(void)
+{
+	return ftrace_modify_graph_caller(false);
+}
+#endif /* CONFIG_DYNAMIC_FTRACE */
 #endif /* CONFIG_FUNCTION_GRAPH_TRACER */
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 235+ messages in thread

* [PATCH v8 7/8] arm64: ftrace: Add CALLER_ADDRx macros
  2014-04-30  9:54             ` AKASHI Takahiro
@ 2014-04-30  9:54               ` AKASHI Takahiro
  -1 siblings, 0 replies; 235+ messages in thread
From: AKASHI Takahiro @ 2014-04-30  9:54 UTC (permalink / raw)
  To: rostedt, fweisbec, mingo, catalin.marinas, will.deacon, tim.bird
  Cc: gkulkarni, dsaxena, arndb, linux-arm-kernel, linaro-kernel,
	linux-kernel, AKASHI Takahiro

CALLER_ADDRx returns caller's address at specified level in call stacks.
They are used for several tracers like irqsoff and preemptoff.
Strange to say, however, they are refered even without FTRACE.

Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
---
 arch/arm64/include/asm/ftrace.h    |    5 +++-
 arch/arm64/kernel/Makefile         |    3 +-
 arch/arm64/kernel/return_address.c |   55 ++++++++++++++++++++++++++++++++++++
 3 files changed, 61 insertions(+), 2 deletions(-)
 create mode 100644 arch/arm64/kernel/return_address.c

diff --git a/arch/arm64/include/asm/ftrace.h b/arch/arm64/include/asm/ftrace.h
index ed5c448..41e8670 100644
--- a/arch/arm64/include/asm/ftrace.h
+++ b/arch/arm64/include/asm/ftrace.h
@@ -18,6 +18,7 @@
 
 #ifndef __ASSEMBLY__
 extern void _mcount(unsigned long);
+extern void *return_address(unsigned int);
 
 struct dyn_arch_ftrace {
 	/* No extra data needed for arm64 */
@@ -33,6 +34,8 @@ static inline unsigned long ftrace_call_adjust(unsigned long addr)
 	 */
 	return addr;
 }
-#endif /* __ASSEMBLY__ */
+
+#define ftrace_return_address(n) return_address(n)
+#endif /* ifndef __ASSEMBLY__ */
 
 #endif /* __ASM_FTRACE_H */
diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile
index 1ebcb4c..1f4d891 100644
--- a/arch/arm64/kernel/Makefile
+++ b/arch/arm64/kernel/Makefile
@@ -7,12 +7,13 @@ AFLAGS_head.o		:= -DTEXT_OFFSET=$(TEXT_OFFSET)
 
 CFLAGS_REMOVE_ftrace.o = -pg
 CFLAGS_REMOVE_insn.o = -pg
+CFLAGS_REMOVE_return_address.o = -pg
 
 # Object file lists.
 arm64-obj-y		:= cputable.o debug-monitors.o entry.o irq.o fpsimd.o	\
 			   entry-fpsimd.o process.o ptrace.o setup.o signal.o	\
 			   sys.o stacktrace.o time.o traps.o io.o vdso.o	\
-			   hyp-stub.o psci.o cpu_ops.o insn.o
+			   hyp-stub.o psci.o cpu_ops.o insn.o return_address.o
 
 arm64-obj-$(CONFIG_COMPAT)		+= sys32.o kuser32.o signal32.o 	\
 					   sys_compat.o
diff --git a/arch/arm64/kernel/return_address.c b/arch/arm64/kernel/return_address.c
new file mode 100644
index 0000000..89102a6
--- /dev/null
+++ b/arch/arm64/kernel/return_address.c
@@ -0,0 +1,55 @@
+/*
+ * arch/arm64/kernel/return_address.c
+ *
+ * Copyright (C) 2013 Linaro Limited
+ * Author: AKASHI Takahiro <takahiro.akashi@linaro.org>
+ *
+ * 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 <linux/export.h>
+#include <linux/ftrace.h>
+
+#include <asm/stacktrace.h>
+
+struct return_address_data {
+	unsigned int level;
+	void *addr;
+};
+
+static int save_return_addr(struct stackframe *frame, void *d)
+{
+	struct return_address_data *data = d;
+
+	if (!data->level) {
+		data->addr = (void *)frame->pc;
+		return 1;
+	} else {
+		--data->level;
+		return 0;
+	}
+}
+
+void *return_address(unsigned int level)
+{
+	struct return_address_data data;
+	struct stackframe frame;
+	register unsigned long current_sp asm ("sp");
+
+	data.level = level + 2;
+	data.addr = NULL;
+
+	frame.fp = (unsigned long)__builtin_frame_address(0);
+	frame.sp = current_sp;
+	frame.pc = (unsigned long)return_address; /* dummy */
+
+	walk_stackframe(&frame, save_return_addr, &data);
+
+	if (!data.level)
+		return data.addr;
+	else
+		return NULL;
+}
+EXPORT_SYMBOL_GPL(return_address);
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 235+ messages in thread

* [PATCH v8 7/8] arm64: ftrace: Add CALLER_ADDRx macros
@ 2014-04-30  9:54               ` AKASHI Takahiro
  0 siblings, 0 replies; 235+ messages in thread
From: AKASHI Takahiro @ 2014-04-30  9:54 UTC (permalink / raw)
  To: linux-arm-kernel

CALLER_ADDRx returns caller's address at specified level in call stacks.
They are used for several tracers like irqsoff and preemptoff.
Strange to say, however, they are refered even without FTRACE.

Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
---
 arch/arm64/include/asm/ftrace.h    |    5 +++-
 arch/arm64/kernel/Makefile         |    3 +-
 arch/arm64/kernel/return_address.c |   55 ++++++++++++++++++++++++++++++++++++
 3 files changed, 61 insertions(+), 2 deletions(-)
 create mode 100644 arch/arm64/kernel/return_address.c

diff --git a/arch/arm64/include/asm/ftrace.h b/arch/arm64/include/asm/ftrace.h
index ed5c448..41e8670 100644
--- a/arch/arm64/include/asm/ftrace.h
+++ b/arch/arm64/include/asm/ftrace.h
@@ -18,6 +18,7 @@
 
 #ifndef __ASSEMBLY__
 extern void _mcount(unsigned long);
+extern void *return_address(unsigned int);
 
 struct dyn_arch_ftrace {
 	/* No extra data needed for arm64 */
@@ -33,6 +34,8 @@ static inline unsigned long ftrace_call_adjust(unsigned long addr)
 	 */
 	return addr;
 }
-#endif /* __ASSEMBLY__ */
+
+#define ftrace_return_address(n) return_address(n)
+#endif /* ifndef __ASSEMBLY__ */
 
 #endif /* __ASM_FTRACE_H */
diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile
index 1ebcb4c..1f4d891 100644
--- a/arch/arm64/kernel/Makefile
+++ b/arch/arm64/kernel/Makefile
@@ -7,12 +7,13 @@ AFLAGS_head.o		:= -DTEXT_OFFSET=$(TEXT_OFFSET)
 
 CFLAGS_REMOVE_ftrace.o = -pg
 CFLAGS_REMOVE_insn.o = -pg
+CFLAGS_REMOVE_return_address.o = -pg
 
 # Object file lists.
 arm64-obj-y		:= cputable.o debug-monitors.o entry.o irq.o fpsimd.o	\
 			   entry-fpsimd.o process.o ptrace.o setup.o signal.o	\
 			   sys.o stacktrace.o time.o traps.o io.o vdso.o	\
-			   hyp-stub.o psci.o cpu_ops.o insn.o
+			   hyp-stub.o psci.o cpu_ops.o insn.o return_address.o
 
 arm64-obj-$(CONFIG_COMPAT)		+= sys32.o kuser32.o signal32.o 	\
 					   sys_compat.o
diff --git a/arch/arm64/kernel/return_address.c b/arch/arm64/kernel/return_address.c
new file mode 100644
index 0000000..89102a6
--- /dev/null
+++ b/arch/arm64/kernel/return_address.c
@@ -0,0 +1,55 @@
+/*
+ * arch/arm64/kernel/return_address.c
+ *
+ * Copyright (C) 2013 Linaro Limited
+ * Author: AKASHI Takahiro <takahiro.akashi@linaro.org>
+ *
+ * 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 <linux/export.h>
+#include <linux/ftrace.h>
+
+#include <asm/stacktrace.h>
+
+struct return_address_data {
+	unsigned int level;
+	void *addr;
+};
+
+static int save_return_addr(struct stackframe *frame, void *d)
+{
+	struct return_address_data *data = d;
+
+	if (!data->level) {
+		data->addr = (void *)frame->pc;
+		return 1;
+	} else {
+		--data->level;
+		return 0;
+	}
+}
+
+void *return_address(unsigned int level)
+{
+	struct return_address_data data;
+	struct stackframe frame;
+	register unsigned long current_sp asm ("sp");
+
+	data.level = level + 2;
+	data.addr = NULL;
+
+	frame.fp = (unsigned long)__builtin_frame_address(0);
+	frame.sp = current_sp;
+	frame.pc = (unsigned long)return_address; /* dummy */
+
+	walk_stackframe(&frame, save_return_addr, &data);
+
+	if (!data.level)
+		return data.addr;
+	else
+		return NULL;
+}
+EXPORT_SYMBOL_GPL(return_address);
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 235+ messages in thread

* [PATCH v8 8/8] arm64: ftrace: Add system call tracepoint
  2014-04-30  9:54             ` AKASHI Takahiro
@ 2014-04-30  9:54               ` AKASHI Takahiro
  -1 siblings, 0 replies; 235+ messages in thread
From: AKASHI Takahiro @ 2014-04-30  9:54 UTC (permalink / raw)
  To: rostedt, fweisbec, mingo, catalin.marinas, will.deacon, tim.bird
  Cc: gkulkarni, dsaxena, arndb, linux-arm-kernel, linaro-kernel,
	linux-kernel, AKASHI Takahiro

This patch allows system call entry or exit to be traced as ftrace events,
ie. sys_enter_*/sys_exit_*, if CONFIG_FTRACE_SYSCALLS is enabled.
Those events appear and can be controlled under
    ${sysfs}/tracing/events/syscalls/

Please note that we can't trace compat system calls here because
AArch32 mode does not share the same syscall table with AArch64.
Just define ARCH_TRACE_IGNORE_COMPAT_SYSCALLS in order to avoid unexpected
results (bogus syscalls reported or even hang-up).

Acked-by: Will Deacon <will.deacon@arm.com>
Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
---
 arch/arm64/Kconfig               |    1 +
 arch/arm64/include/asm/ftrace.h  |   18 ++++++++++++++++++
 arch/arm64/include/asm/syscall.h |    1 +
 arch/arm64/include/asm/unistd.h  |    2 ++
 arch/arm64/kernel/ptrace.c       |    9 +++++++++
 5 files changed, 31 insertions(+)

diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 438a4ea..0e9b8ce 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -48,6 +48,7 @@ config ARM64
 	select HAVE_PERF_EVENTS
 	select HAVE_PERF_REGS
 	select HAVE_PERF_USER_STACK_DUMP
+	select HAVE_SYSCALL_TRACEPOINTS
 	select IRQ_DOMAIN
 	select MODULES_USE_ELF_RELA
 	select NO_BOOTMEM
diff --git a/arch/arm64/include/asm/ftrace.h b/arch/arm64/include/asm/ftrace.h
index 41e8670..c5534fa 100644
--- a/arch/arm64/include/asm/ftrace.h
+++ b/arch/arm64/include/asm/ftrace.h
@@ -17,6 +17,8 @@
 #define MCOUNT_INSN_SIZE	AARCH64_INSN_SIZE
 
 #ifndef __ASSEMBLY__
+#include <linux/compat.h>
+
 extern void _mcount(unsigned long);
 extern void *return_address(unsigned int);
 
@@ -36,6 +38,22 @@ static inline unsigned long ftrace_call_adjust(unsigned long addr)
 }
 
 #define ftrace_return_address(n) return_address(n)
+
+/*
+ * Because AArch32 mode does not share the same syscall table with AArch64,
+ * tracing compat syscalls may result in reporting bogus syscalls or even
+ * hang-up, so just do not trace them.
+ * See kernel/trace/trace_syscalls.c
+ *
+ * x86 code says:
+ * If the user realy wants these, then they should use the
+ * raw syscall tracepoints with filtering.
+ */
+#define ARCH_TRACE_IGNORE_COMPAT_SYSCALLS
+static inline bool arch_trace_is_compat_syscall(struct pt_regs *regs)
+{
+	return is_compat_task();
+}
 #endif /* ifndef __ASSEMBLY__ */
 
 #endif /* __ASM_FTRACE_H */
diff --git a/arch/arm64/include/asm/syscall.h b/arch/arm64/include/asm/syscall.h
index 70ba9d4..383771e 100644
--- a/arch/arm64/include/asm/syscall.h
+++ b/arch/arm64/include/asm/syscall.h
@@ -18,6 +18,7 @@
 
 #include <linux/err.h>
 
+extern const void *sys_call_table[];
 
 static inline int syscall_get_nr(struct task_struct *task,
 				 struct pt_regs *regs)
diff --git a/arch/arm64/include/asm/unistd.h b/arch/arm64/include/asm/unistd.h
index a4654c6..e5f47df 100644
--- a/arch/arm64/include/asm/unistd.h
+++ b/arch/arm64/include/asm/unistd.h
@@ -29,3 +29,5 @@
 #endif
 #define __ARCH_WANT_SYS_CLONE
 #include <uapi/asm/unistd.h>
+
+#define NR_syscalls (__NR_syscalls)
diff --git a/arch/arm64/kernel/ptrace.c b/arch/arm64/kernel/ptrace.c
index 4b58e81..0bf1955 100644
--- a/arch/arm64/kernel/ptrace.c
+++ b/arch/arm64/kernel/ptrace.c
@@ -42,6 +42,9 @@
 #include <asm/traps.h>
 #include <asm/system_misc.h>
 
+#define CREATE_TRACE_POINTS
+#include <trace/events/syscalls.h>
+
 /*
  * TODO: does not yet catch signals sent when the child dies.
  * in exit.c or in signal.c.
@@ -1091,11 +1094,17 @@ asmlinkage int syscall_trace_enter(struct pt_regs *regs)
 	if (test_thread_flag(TIF_SYSCALL_TRACE))
 		tracehook_report_syscall(regs, PTRACE_SYSCALL_ENTER);
 
+	if (test_thread_flag(TIF_SYSCALL_TRACEPOINT))
+		trace_sys_enter(regs, regs->syscallno);
+
 	return regs->syscallno;
 }
 
 asmlinkage void syscall_trace_exit(struct pt_regs *regs)
 {
+	if (test_thread_flag(TIF_SYSCALL_TRACEPOINT))
+		trace_sys_exit(regs, regs_return_value(regs));
+
 	if (test_thread_flag(TIF_SYSCALL_TRACE))
 		tracehook_report_syscall(regs, PTRACE_SYSCALL_EXIT);
 }
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 235+ messages in thread

* [PATCH v8 8/8] arm64: ftrace: Add system call tracepoint
@ 2014-04-30  9:54               ` AKASHI Takahiro
  0 siblings, 0 replies; 235+ messages in thread
From: AKASHI Takahiro @ 2014-04-30  9:54 UTC (permalink / raw)
  To: linux-arm-kernel

This patch allows system call entry or exit to be traced as ftrace events,
ie. sys_enter_*/sys_exit_*, if CONFIG_FTRACE_SYSCALLS is enabled.
Those events appear and can be controlled under
    ${sysfs}/tracing/events/syscalls/

Please note that we can't trace compat system calls here because
AArch32 mode does not share the same syscall table with AArch64.
Just define ARCH_TRACE_IGNORE_COMPAT_SYSCALLS in order to avoid unexpected
results (bogus syscalls reported or even hang-up).

Acked-by: Will Deacon <will.deacon@arm.com>
Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
---
 arch/arm64/Kconfig               |    1 +
 arch/arm64/include/asm/ftrace.h  |   18 ++++++++++++++++++
 arch/arm64/include/asm/syscall.h |    1 +
 arch/arm64/include/asm/unistd.h  |    2 ++
 arch/arm64/kernel/ptrace.c       |    9 +++++++++
 5 files changed, 31 insertions(+)

diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 438a4ea..0e9b8ce 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -48,6 +48,7 @@ config ARM64
 	select HAVE_PERF_EVENTS
 	select HAVE_PERF_REGS
 	select HAVE_PERF_USER_STACK_DUMP
+	select HAVE_SYSCALL_TRACEPOINTS
 	select IRQ_DOMAIN
 	select MODULES_USE_ELF_RELA
 	select NO_BOOTMEM
diff --git a/arch/arm64/include/asm/ftrace.h b/arch/arm64/include/asm/ftrace.h
index 41e8670..c5534fa 100644
--- a/arch/arm64/include/asm/ftrace.h
+++ b/arch/arm64/include/asm/ftrace.h
@@ -17,6 +17,8 @@
 #define MCOUNT_INSN_SIZE	AARCH64_INSN_SIZE
 
 #ifndef __ASSEMBLY__
+#include <linux/compat.h>
+
 extern void _mcount(unsigned long);
 extern void *return_address(unsigned int);
 
@@ -36,6 +38,22 @@ static inline unsigned long ftrace_call_adjust(unsigned long addr)
 }
 
 #define ftrace_return_address(n) return_address(n)
+
+/*
+ * Because AArch32 mode does not share the same syscall table with AArch64,
+ * tracing compat syscalls may result in reporting bogus syscalls or even
+ * hang-up, so just do not trace them.
+ * See kernel/trace/trace_syscalls.c
+ *
+ * x86 code says:
+ * If the user realy wants these, then they should use the
+ * raw syscall tracepoints with filtering.
+ */
+#define ARCH_TRACE_IGNORE_COMPAT_SYSCALLS
+static inline bool arch_trace_is_compat_syscall(struct pt_regs *regs)
+{
+	return is_compat_task();
+}
 #endif /* ifndef __ASSEMBLY__ */
 
 #endif /* __ASM_FTRACE_H */
diff --git a/arch/arm64/include/asm/syscall.h b/arch/arm64/include/asm/syscall.h
index 70ba9d4..383771e 100644
--- a/arch/arm64/include/asm/syscall.h
+++ b/arch/arm64/include/asm/syscall.h
@@ -18,6 +18,7 @@
 
 #include <linux/err.h>
 
+extern const void *sys_call_table[];
 
 static inline int syscall_get_nr(struct task_struct *task,
 				 struct pt_regs *regs)
diff --git a/arch/arm64/include/asm/unistd.h b/arch/arm64/include/asm/unistd.h
index a4654c6..e5f47df 100644
--- a/arch/arm64/include/asm/unistd.h
+++ b/arch/arm64/include/asm/unistd.h
@@ -29,3 +29,5 @@
 #endif
 #define __ARCH_WANT_SYS_CLONE
 #include <uapi/asm/unistd.h>
+
+#define NR_syscalls (__NR_syscalls)
diff --git a/arch/arm64/kernel/ptrace.c b/arch/arm64/kernel/ptrace.c
index 4b58e81..0bf1955 100644
--- a/arch/arm64/kernel/ptrace.c
+++ b/arch/arm64/kernel/ptrace.c
@@ -42,6 +42,9 @@
 #include <asm/traps.h>
 #include <asm/system_misc.h>
 
+#define CREATE_TRACE_POINTS
+#include <trace/events/syscalls.h>
+
 /*
  * TODO: does not yet catch signals sent when the child dies.
  * in exit.c or in signal.c.
@@ -1091,11 +1094,17 @@ asmlinkage int syscall_trace_enter(struct pt_regs *regs)
 	if (test_thread_flag(TIF_SYSCALL_TRACE))
 		tracehook_report_syscall(regs, PTRACE_SYSCALL_ENTER);
 
+	if (test_thread_flag(TIF_SYSCALL_TRACEPOINT))
+		trace_sys_enter(regs, regs->syscallno);
+
 	return regs->syscallno;
 }
 
 asmlinkage void syscall_trace_exit(struct pt_regs *regs)
 {
+	if (test_thread_flag(TIF_SYSCALL_TRACEPOINT))
+		trace_sys_exit(regs, regs_return_value(regs));
+
 	if (test_thread_flag(TIF_SYSCALL_TRACE))
 		tracehook_report_syscall(regs, PTRACE_SYSCALL_EXIT);
 }
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 235+ messages in thread

* Re: [PATCH v8 1/8] ftrace: make CALLER_ADDRx macros more generic
  2014-04-30  9:54               ` AKASHI Takahiro
@ 2014-05-02 18:13                 ` Will Deacon
  -1 siblings, 0 replies; 235+ messages in thread
From: Will Deacon @ 2014-05-02 18:13 UTC (permalink / raw)
  To: AKASHI Takahiro
  Cc: rostedt, fweisbec, mingo, Catalin Marinas, tim.bird, gkulkarni,
	dsaxena, arndb, linux-arm-kernel, linaro-kernel, linux-kernel

Hi Akashi,

On Wed, Apr 30, 2014 at 10:54:29AM +0100, AKASHI Takahiro wrote:
> Most archs with HAVE_ARCH_CALLER_ADDR have the almost same definitions
> of CALLER_ADDRx(n), and so put them into linux/ftrace.h.
> 
> Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
> ---
>  arch/arm/include/asm/ftrace.h      |   10 +---------
>  arch/blackfin/include/asm/ftrace.h |   11 +----------
>  arch/parisc/include/asm/ftrace.h   |   10 +---------
>  arch/sh/include/asm/ftrace.h       |   10 +---------
>  arch/xtensa/include/asm/ftrace.h   |   14 ++++----------
>  include/linux/ftrace.h             |   34 ++++++++++++++++++----------------
>  6 files changed, 26 insertions(+), 63 deletions(-)

This one looks a bit too widespread to be merged via the arm64 tree. I
wonder if the ftrace maintainers would consider taking it as a cleanup?

Will

> diff --git a/arch/arm/include/asm/ftrace.h b/arch/arm/include/asm/ftrace.h
> index f89515a..eb577f4 100644
> --- a/arch/arm/include/asm/ftrace.h
> +++ b/arch/arm/include/asm/ftrace.h
> @@ -52,15 +52,7 @@ extern inline void *return_address(unsigned int level)
>  
>  #endif
>  
> -#define HAVE_ARCH_CALLER_ADDR
> -
> -#define CALLER_ADDR0 ((unsigned long)__builtin_return_address(0))
> -#define CALLER_ADDR1 ((unsigned long)return_address(1))
> -#define CALLER_ADDR2 ((unsigned long)return_address(2))
> -#define CALLER_ADDR3 ((unsigned long)return_address(3))
> -#define CALLER_ADDR4 ((unsigned long)return_address(4))
> -#define CALLER_ADDR5 ((unsigned long)return_address(5))
> -#define CALLER_ADDR6 ((unsigned long)return_address(6))
> +#define ftrace_return_addr(n) return_address(n)
>  
>  #endif /* ifndef __ASSEMBLY__ */
>  
> diff --git a/arch/blackfin/include/asm/ftrace.h b/arch/blackfin/include/asm/ftrace.h
> index 8a02950..2f1c3c2 100644
> --- a/arch/blackfin/include/asm/ftrace.h
> +++ b/arch/blackfin/include/asm/ftrace.h
> @@ -66,16 +66,7 @@ extern inline void *return_address(unsigned int level)
>  
>  #endif /* CONFIG_FRAME_POINTER */
>  
> -#define HAVE_ARCH_CALLER_ADDR
> -
> -/* inline function or macro may lead to unexpected result */
> -#define CALLER_ADDR0 ((unsigned long)__builtin_return_address(0))
> -#define CALLER_ADDR1 ((unsigned long)return_address(1))
> -#define CALLER_ADDR2 ((unsigned long)return_address(2))
> -#define CALLER_ADDR3 ((unsigned long)return_address(3))
> -#define CALLER_ADDR4 ((unsigned long)return_address(4))
> -#define CALLER_ADDR5 ((unsigned long)return_address(5))
> -#define CALLER_ADDR6 ((unsigned long)return_address(6))
> +#define ftrace_return_address(n) return_address(n)
>  
>  #endif /* __ASSEMBLY__ */
>  
> diff --git a/arch/parisc/include/asm/ftrace.h b/arch/parisc/include/asm/ftrace.h
> index 72c0faf..544ed8e 100644
> --- a/arch/parisc/include/asm/ftrace.h
> +++ b/arch/parisc/include/asm/ftrace.h
> @@ -24,15 +24,7 @@ extern void return_to_handler(void);
>  
>  extern unsigned long return_address(unsigned int);
>  
> -#define HAVE_ARCH_CALLER_ADDR
> -
> -#define CALLER_ADDR0 ((unsigned long)__builtin_return_address(0))
> -#define CALLER_ADDR1 return_address(1)
> -#define CALLER_ADDR2 return_address(2)
> -#define CALLER_ADDR3 return_address(3)
> -#define CALLER_ADDR4 return_address(4)
> -#define CALLER_ADDR5 return_address(5)
> -#define CALLER_ADDR6 return_address(6)
> +#define ftrace_return_address(n) return_address(n)
>  
>  #endif /* __ASSEMBLY__ */
>  
> diff --git a/arch/sh/include/asm/ftrace.h b/arch/sh/include/asm/ftrace.h
> index 13e9966..e79fb6e 100644
> --- a/arch/sh/include/asm/ftrace.h
> +++ b/arch/sh/include/asm/ftrace.h
> @@ -40,15 +40,7 @@ static inline unsigned long ftrace_call_adjust(unsigned long addr)
>  /* arch/sh/kernel/return_address.c */
>  extern void *return_address(unsigned int);
>  
> -#define HAVE_ARCH_CALLER_ADDR
> -
> -#define CALLER_ADDR0 ((unsigned long)__builtin_return_address(0))
> -#define CALLER_ADDR1 ((unsigned long)return_address(1))
> -#define CALLER_ADDR2 ((unsigned long)return_address(2))
> -#define CALLER_ADDR3 ((unsigned long)return_address(3))
> -#define CALLER_ADDR4 ((unsigned long)return_address(4))
> -#define CALLER_ADDR5 ((unsigned long)return_address(5))
> -#define CALLER_ADDR6 ((unsigned long)return_address(6))
> +#define ftrace_return_address(n) return_address(n)
>  
>  #endif /* __ASSEMBLY__ */
>  
> diff --git a/arch/xtensa/include/asm/ftrace.h b/arch/xtensa/include/asm/ftrace.h
> index 736b9d2..6c6d9a9 100644
> --- a/arch/xtensa/include/asm/ftrace.h
> +++ b/arch/xtensa/include/asm/ftrace.h
> @@ -12,24 +12,18 @@
>  
>  #include <asm/processor.h>
>  
> -#define HAVE_ARCH_CALLER_ADDR
>  #ifndef __ASSEMBLY__
> -#define CALLER_ADDR0 ({ unsigned long a0, a1; \
> +#define ftrace_return_address0 ({ unsigned long a0, a1; \
>  		__asm__ __volatile__ ( \
>  			"mov %0, a0\n" \
>  			"mov %1, a1\n" \
>  			: "=r"(a0), "=r"(a1)); \
>  		MAKE_PC_FROM_RA(a0, a1); })
> +
>  #ifdef CONFIG_FRAME_POINTER
>  extern unsigned long return_address(unsigned level);
> -#define CALLER_ADDR1 return_address(1)
> -#define CALLER_ADDR2 return_address(2)
> -#define CALLER_ADDR3 return_address(3)
> -#else /* CONFIG_FRAME_POINTER */
> -#define CALLER_ADDR1 (0)
> -#define CALLER_ADDR2 (0)
> -#define CALLER_ADDR3 (0)
> -#endif /* CONFIG_FRAME_POINTER */
> +#define ftrace_return_address(n) return_address(n)
> +#endif
>  #endif /* __ASSEMBLY__ */
>  
>  #ifdef CONFIG_FUNCTION_TRACER
> diff --git a/include/linux/ftrace.h b/include/linux/ftrace.h
> index 9212b01..18f1ae7 100644
> --- a/include/linux/ftrace.h
> +++ b/include/linux/ftrace.h
> @@ -614,25 +614,27 @@ static inline void __ftrace_enabled_restore(int enabled)
>  #endif
>  }
>  
> -#ifndef HAVE_ARCH_CALLER_ADDR
> +/* All archs should have this, but we define it for consistency */
> +#ifndef ftrace_return_address0
> +# define ftrace_return_address0 __builtin_return_address(0)
> +#endif
> +
> +/* Archs may use other ways for ADDR1 and beyond */
> +#ifndef ftrace_return_address
>  # ifdef CONFIG_FRAME_POINTER
> -#  define CALLER_ADDR0 ((unsigned long)__builtin_return_address(0))
> -#  define CALLER_ADDR1 ((unsigned long)__builtin_return_address(1))
> -#  define CALLER_ADDR2 ((unsigned long)__builtin_return_address(2))
> -#  define CALLER_ADDR3 ((unsigned long)__builtin_return_address(3))
> -#  define CALLER_ADDR4 ((unsigned long)__builtin_return_address(4))
> -#  define CALLER_ADDR5 ((unsigned long)__builtin_return_address(5))
> -#  define CALLER_ADDR6 ((unsigned long)__builtin_return_address(6))
> +#  define ftrace_return_address(n) __builtin_return_address(n)
>  # else
> -#  define CALLER_ADDR0 ((unsigned long)__builtin_return_address(0))
> -#  define CALLER_ADDR1 0UL
> -#  define CALLER_ADDR2 0UL
> -#  define CALLER_ADDR3 0UL
> -#  define CALLER_ADDR4 0UL
> -#  define CALLER_ADDR5 0UL
> -#  define CALLER_ADDR6 0UL
> +#  define ftrace_return_address(n) 0UL
>  # endif
> -#endif /* ifndef HAVE_ARCH_CALLER_ADDR */
> +#endif
> +
> +#define CALLER_ADDR0 ((unsigned long)ftrace_return_address0)
> +#define CALLER_ADDR1 ((unsigned long)ftrace_return_address(1))
> +#define CALLER_ADDR2 ((unsigned long)ftrace_return_address(2))
> +#define CALLER_ADDR3 ((unsigned long)ftrace_return_address(3))
> +#define CALLER_ADDR4 ((unsigned long)ftrace_return_address(4))
> +#define CALLER_ADDR5 ((unsigned long)ftrace_return_address(5))
> +#define CALLER_ADDR6 ((unsigned long)ftrace_return_address(6))
>  
>  #ifdef CONFIG_IRQSOFF_TRACER
>    extern void time_hardirqs_on(unsigned long a0, unsigned long a1);
> -- 
> 1.7.9.5
> 
> 

^ permalink raw reply	[flat|nested] 235+ messages in thread

* [PATCH v8 1/8] ftrace: make CALLER_ADDRx macros more generic
@ 2014-05-02 18:13                 ` Will Deacon
  0 siblings, 0 replies; 235+ messages in thread
From: Will Deacon @ 2014-05-02 18:13 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Akashi,

On Wed, Apr 30, 2014 at 10:54:29AM +0100, AKASHI Takahiro wrote:
> Most archs with HAVE_ARCH_CALLER_ADDR have the almost same definitions
> of CALLER_ADDRx(n), and so put them into linux/ftrace.h.
> 
> Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
> ---
>  arch/arm/include/asm/ftrace.h      |   10 +---------
>  arch/blackfin/include/asm/ftrace.h |   11 +----------
>  arch/parisc/include/asm/ftrace.h   |   10 +---------
>  arch/sh/include/asm/ftrace.h       |   10 +---------
>  arch/xtensa/include/asm/ftrace.h   |   14 ++++----------
>  include/linux/ftrace.h             |   34 ++++++++++++++++++----------------
>  6 files changed, 26 insertions(+), 63 deletions(-)

This one looks a bit too widespread to be merged via the arm64 tree. I
wonder if the ftrace maintainers would consider taking it as a cleanup?

Will

> diff --git a/arch/arm/include/asm/ftrace.h b/arch/arm/include/asm/ftrace.h
> index f89515a..eb577f4 100644
> --- a/arch/arm/include/asm/ftrace.h
> +++ b/arch/arm/include/asm/ftrace.h
> @@ -52,15 +52,7 @@ extern inline void *return_address(unsigned int level)
>  
>  #endif
>  
> -#define HAVE_ARCH_CALLER_ADDR
> -
> -#define CALLER_ADDR0 ((unsigned long)__builtin_return_address(0))
> -#define CALLER_ADDR1 ((unsigned long)return_address(1))
> -#define CALLER_ADDR2 ((unsigned long)return_address(2))
> -#define CALLER_ADDR3 ((unsigned long)return_address(3))
> -#define CALLER_ADDR4 ((unsigned long)return_address(4))
> -#define CALLER_ADDR5 ((unsigned long)return_address(5))
> -#define CALLER_ADDR6 ((unsigned long)return_address(6))
> +#define ftrace_return_addr(n) return_address(n)
>  
>  #endif /* ifndef __ASSEMBLY__ */
>  
> diff --git a/arch/blackfin/include/asm/ftrace.h b/arch/blackfin/include/asm/ftrace.h
> index 8a02950..2f1c3c2 100644
> --- a/arch/blackfin/include/asm/ftrace.h
> +++ b/arch/blackfin/include/asm/ftrace.h
> @@ -66,16 +66,7 @@ extern inline void *return_address(unsigned int level)
>  
>  #endif /* CONFIG_FRAME_POINTER */
>  
> -#define HAVE_ARCH_CALLER_ADDR
> -
> -/* inline function or macro may lead to unexpected result */
> -#define CALLER_ADDR0 ((unsigned long)__builtin_return_address(0))
> -#define CALLER_ADDR1 ((unsigned long)return_address(1))
> -#define CALLER_ADDR2 ((unsigned long)return_address(2))
> -#define CALLER_ADDR3 ((unsigned long)return_address(3))
> -#define CALLER_ADDR4 ((unsigned long)return_address(4))
> -#define CALLER_ADDR5 ((unsigned long)return_address(5))
> -#define CALLER_ADDR6 ((unsigned long)return_address(6))
> +#define ftrace_return_address(n) return_address(n)
>  
>  #endif /* __ASSEMBLY__ */
>  
> diff --git a/arch/parisc/include/asm/ftrace.h b/arch/parisc/include/asm/ftrace.h
> index 72c0faf..544ed8e 100644
> --- a/arch/parisc/include/asm/ftrace.h
> +++ b/arch/parisc/include/asm/ftrace.h
> @@ -24,15 +24,7 @@ extern void return_to_handler(void);
>  
>  extern unsigned long return_address(unsigned int);
>  
> -#define HAVE_ARCH_CALLER_ADDR
> -
> -#define CALLER_ADDR0 ((unsigned long)__builtin_return_address(0))
> -#define CALLER_ADDR1 return_address(1)
> -#define CALLER_ADDR2 return_address(2)
> -#define CALLER_ADDR3 return_address(3)
> -#define CALLER_ADDR4 return_address(4)
> -#define CALLER_ADDR5 return_address(5)
> -#define CALLER_ADDR6 return_address(6)
> +#define ftrace_return_address(n) return_address(n)
>  
>  #endif /* __ASSEMBLY__ */
>  
> diff --git a/arch/sh/include/asm/ftrace.h b/arch/sh/include/asm/ftrace.h
> index 13e9966..e79fb6e 100644
> --- a/arch/sh/include/asm/ftrace.h
> +++ b/arch/sh/include/asm/ftrace.h
> @@ -40,15 +40,7 @@ static inline unsigned long ftrace_call_adjust(unsigned long addr)
>  /* arch/sh/kernel/return_address.c */
>  extern void *return_address(unsigned int);
>  
> -#define HAVE_ARCH_CALLER_ADDR
> -
> -#define CALLER_ADDR0 ((unsigned long)__builtin_return_address(0))
> -#define CALLER_ADDR1 ((unsigned long)return_address(1))
> -#define CALLER_ADDR2 ((unsigned long)return_address(2))
> -#define CALLER_ADDR3 ((unsigned long)return_address(3))
> -#define CALLER_ADDR4 ((unsigned long)return_address(4))
> -#define CALLER_ADDR5 ((unsigned long)return_address(5))
> -#define CALLER_ADDR6 ((unsigned long)return_address(6))
> +#define ftrace_return_address(n) return_address(n)
>  
>  #endif /* __ASSEMBLY__ */
>  
> diff --git a/arch/xtensa/include/asm/ftrace.h b/arch/xtensa/include/asm/ftrace.h
> index 736b9d2..6c6d9a9 100644
> --- a/arch/xtensa/include/asm/ftrace.h
> +++ b/arch/xtensa/include/asm/ftrace.h
> @@ -12,24 +12,18 @@
>  
>  #include <asm/processor.h>
>  
> -#define HAVE_ARCH_CALLER_ADDR
>  #ifndef __ASSEMBLY__
> -#define CALLER_ADDR0 ({ unsigned long a0, a1; \
> +#define ftrace_return_address0 ({ unsigned long a0, a1; \
>  		__asm__ __volatile__ ( \
>  			"mov %0, a0\n" \
>  			"mov %1, a1\n" \
>  			: "=r"(a0), "=r"(a1)); \
>  		MAKE_PC_FROM_RA(a0, a1); })
> +
>  #ifdef CONFIG_FRAME_POINTER
>  extern unsigned long return_address(unsigned level);
> -#define CALLER_ADDR1 return_address(1)
> -#define CALLER_ADDR2 return_address(2)
> -#define CALLER_ADDR3 return_address(3)
> -#else /* CONFIG_FRAME_POINTER */
> -#define CALLER_ADDR1 (0)
> -#define CALLER_ADDR2 (0)
> -#define CALLER_ADDR3 (0)
> -#endif /* CONFIG_FRAME_POINTER */
> +#define ftrace_return_address(n) return_address(n)
> +#endif
>  #endif /* __ASSEMBLY__ */
>  
>  #ifdef CONFIG_FUNCTION_TRACER
> diff --git a/include/linux/ftrace.h b/include/linux/ftrace.h
> index 9212b01..18f1ae7 100644
> --- a/include/linux/ftrace.h
> +++ b/include/linux/ftrace.h
> @@ -614,25 +614,27 @@ static inline void __ftrace_enabled_restore(int enabled)
>  #endif
>  }
>  
> -#ifndef HAVE_ARCH_CALLER_ADDR
> +/* All archs should have this, but we define it for consistency */
> +#ifndef ftrace_return_address0
> +# define ftrace_return_address0 __builtin_return_address(0)
> +#endif
> +
> +/* Archs may use other ways for ADDR1 and beyond */
> +#ifndef ftrace_return_address
>  # ifdef CONFIG_FRAME_POINTER
> -#  define CALLER_ADDR0 ((unsigned long)__builtin_return_address(0))
> -#  define CALLER_ADDR1 ((unsigned long)__builtin_return_address(1))
> -#  define CALLER_ADDR2 ((unsigned long)__builtin_return_address(2))
> -#  define CALLER_ADDR3 ((unsigned long)__builtin_return_address(3))
> -#  define CALLER_ADDR4 ((unsigned long)__builtin_return_address(4))
> -#  define CALLER_ADDR5 ((unsigned long)__builtin_return_address(5))
> -#  define CALLER_ADDR6 ((unsigned long)__builtin_return_address(6))
> +#  define ftrace_return_address(n) __builtin_return_address(n)
>  # else
> -#  define CALLER_ADDR0 ((unsigned long)__builtin_return_address(0))
> -#  define CALLER_ADDR1 0UL
> -#  define CALLER_ADDR2 0UL
> -#  define CALLER_ADDR3 0UL
> -#  define CALLER_ADDR4 0UL
> -#  define CALLER_ADDR5 0UL
> -#  define CALLER_ADDR6 0UL
> +#  define ftrace_return_address(n) 0UL
>  # endif
> -#endif /* ifndef HAVE_ARCH_CALLER_ADDR */
> +#endif
> +
> +#define CALLER_ADDR0 ((unsigned long)ftrace_return_address0)
> +#define CALLER_ADDR1 ((unsigned long)ftrace_return_address(1))
> +#define CALLER_ADDR2 ((unsigned long)ftrace_return_address(2))
> +#define CALLER_ADDR3 ((unsigned long)ftrace_return_address(3))
> +#define CALLER_ADDR4 ((unsigned long)ftrace_return_address(4))
> +#define CALLER_ADDR5 ((unsigned long)ftrace_return_address(5))
> +#define CALLER_ADDR6 ((unsigned long)ftrace_return_address(6))
>  
>  #ifdef CONFIG_IRQSOFF_TRACER
>    extern void time_hardirqs_on(unsigned long a0, unsigned long a1);
> -- 
> 1.7.9.5
> 
> 

^ permalink raw reply	[flat|nested] 235+ messages in thread

* Re: [PATCH v8 1/8] ftrace: make CALLER_ADDRx macros more generic
  2014-05-02 18:13                 ` Will Deacon
@ 2014-05-02 19:02                   ` Steven Rostedt
  -1 siblings, 0 replies; 235+ messages in thread
From: Steven Rostedt @ 2014-05-02 19:02 UTC (permalink / raw)
  To: Will Deacon
  Cc: AKASHI Takahiro, fweisbec, mingo, Catalin Marinas, tim.bird,
	gkulkarni, dsaxena, arndb, linux-arm-kernel, linaro-kernel,
	linux-kernel

On Fri, 2 May 2014 19:13:48 +0100
Will Deacon <will.deacon@arm.com> wrote:

> Hi Akashi,
> 
> On Wed, Apr 30, 2014 at 10:54:29AM +0100, AKASHI Takahiro wrote:
> > Most archs with HAVE_ARCH_CALLER_ADDR have the almost same definitions
> > of CALLER_ADDRx(n), and so put them into linux/ftrace.h.
> > 
> > Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
> > ---
> >  arch/arm/include/asm/ftrace.h      |   10 +---------
> >  arch/blackfin/include/asm/ftrace.h |   11 +----------
> >  arch/parisc/include/asm/ftrace.h   |   10 +---------
> >  arch/sh/include/asm/ftrace.h       |   10 +---------
> >  arch/xtensa/include/asm/ftrace.h   |   14 ++++----------
> >  include/linux/ftrace.h             |   34 ++++++++++++++++++----------------
> >  6 files changed, 26 insertions(+), 63 deletions(-)
> 
> This one looks a bit too widespread to be merged via the arm64 tree. I
> wonder if the ftrace maintainers would consider taking it as a cleanup?
> 

I actually was the one to recommend this approach. But I have some
small comments to the patch. I'll reply directly to the patch with them.

-- Steve

^ permalink raw reply	[flat|nested] 235+ messages in thread

* [PATCH v8 1/8] ftrace: make CALLER_ADDRx macros more generic
@ 2014-05-02 19:02                   ` Steven Rostedt
  0 siblings, 0 replies; 235+ messages in thread
From: Steven Rostedt @ 2014-05-02 19:02 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, 2 May 2014 19:13:48 +0100
Will Deacon <will.deacon@arm.com> wrote:

> Hi Akashi,
> 
> On Wed, Apr 30, 2014 at 10:54:29AM +0100, AKASHI Takahiro wrote:
> > Most archs with HAVE_ARCH_CALLER_ADDR have the almost same definitions
> > of CALLER_ADDRx(n), and so put them into linux/ftrace.h.
> > 
> > Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
> > ---
> >  arch/arm/include/asm/ftrace.h      |   10 +---------
> >  arch/blackfin/include/asm/ftrace.h |   11 +----------
> >  arch/parisc/include/asm/ftrace.h   |   10 +---------
> >  arch/sh/include/asm/ftrace.h       |   10 +---------
> >  arch/xtensa/include/asm/ftrace.h   |   14 ++++----------
> >  include/linux/ftrace.h             |   34 ++++++++++++++++++----------------
> >  6 files changed, 26 insertions(+), 63 deletions(-)
> 
> This one looks a bit too widespread to be merged via the arm64 tree. I
> wonder if the ftrace maintainers would consider taking it as a cleanup?
> 

I actually was the one to recommend this approach. But I have some
small comments to the patch. I'll reply directly to the patch with them.

-- Steve

^ permalink raw reply	[flat|nested] 235+ messages in thread

* Re: [PATCH v8 1/8] ftrace: make CALLER_ADDRx macros more generic
  2014-05-02 18:13                 ` Will Deacon
@ 2014-05-02 19:03                   ` Steven Rostedt
  -1 siblings, 0 replies; 235+ messages in thread
From: Steven Rostedt @ 2014-05-02 19:03 UTC (permalink / raw)
  To: Will Deacon
  Cc: AKASHI Takahiro, fweisbec, mingo, Catalin Marinas, tim.bird,
	gkulkarni, dsaxena, arndb, linux-arm-kernel, linaro-kernel,
	linux-kernel

On Fri, 2 May 2014 19:13:48 +0100
Will Deacon <will.deacon@arm.com> wrote:

> This one looks a bit too widespread to be merged via the arm64 tree. I
> wonder if the ftrace maintainers would consider taking it as a cleanup?

Oh, and I can take the patch if you feel uncomfortable with taking
something so spread out. As it deals with ftrace I probably can get
away with a cross the board arch change to it.

-- Steve

^ permalink raw reply	[flat|nested] 235+ messages in thread

* [PATCH v8 1/8] ftrace: make CALLER_ADDRx macros more generic
@ 2014-05-02 19:03                   ` Steven Rostedt
  0 siblings, 0 replies; 235+ messages in thread
From: Steven Rostedt @ 2014-05-02 19:03 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, 2 May 2014 19:13:48 +0100
Will Deacon <will.deacon@arm.com> wrote:

> This one looks a bit too widespread to be merged via the arm64 tree. I
> wonder if the ftrace maintainers would consider taking it as a cleanup?

Oh, and I can take the patch if you feel uncomfortable with taking
something so spread out. As it deals with ftrace I probably can get
away with a cross the board arch change to it.

-- Steve

^ permalink raw reply	[flat|nested] 235+ messages in thread

* Re: [PATCH v8 1/8] ftrace: make CALLER_ADDRx macros more generic
  2014-04-30  9:54               ` AKASHI Takahiro
@ 2014-05-02 19:19                 ` Steven Rostedt
  -1 siblings, 0 replies; 235+ messages in thread
From: Steven Rostedt @ 2014-05-02 19:19 UTC (permalink / raw)
  To: AKASHI Takahiro
  Cc: fweisbec, mingo, catalin.marinas, will.deacon, tim.bird,
	gkulkarni, dsaxena, arndb, linux-arm-kernel, linaro-kernel,
	linux-kernel

On Wed, 30 Apr 2014 18:54:29 +0900
AKASHI Takahiro <takahiro.akashi@linaro.org> wrote:

> Most archs with HAVE_ARCH_CALLER_ADDR have the almost same definitions
> of CALLER_ADDRx(n), and so put them into linux/ftrace.h.

Please add a bit more to the change log. Like what you did. Something
like:

----
Most archs with HAVE_ARCH_CALLER_ADDR have pretty much the same
definitions of CALLER_ADDRx(n). Instead of duplicating the code for all
the archs, define a ftrace_return_address0() and
ftrace_return_address(n) that can be overwritten by the archs if they
need to do something different. Instead of 7 macros in every arch, we
now only have at most 2 (and actually only 1 as
ftrace_return_address0() should be the same for all archs).

The CALLER_ADDRx(n) will now be defined in linux/ftrace.h and use the
ftrace_return_address*(n?) macros. This removes a lot of the duplicate
code.
-----

Use that if you want :-)


> 
> Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
> ---
>  arch/arm/include/asm/ftrace.h      |   10 +---------
>  arch/blackfin/include/asm/ftrace.h |   11 +----------
>  arch/parisc/include/asm/ftrace.h   |   10 +---------
>  arch/sh/include/asm/ftrace.h       |   10 +---------
>  arch/xtensa/include/asm/ftrace.h   |   14 ++++----------
>  include/linux/ftrace.h             |   34 ++++++++++++++++++----------------
>  6 files changed, 26 insertions(+), 63 deletions(-)
> 
> diff --git a/arch/arm/include/asm/ftrace.h b/arch/arm/include/asm/ftrace.h
> index f89515a..eb577f4 100644
> --- a/arch/arm/include/asm/ftrace.h
> +++ b/arch/arm/include/asm/ftrace.h
> @@ -52,15 +52,7 @@ extern inline void *return_address(unsigned int level)
>  
>  #endif
>  
> -#define HAVE_ARCH_CALLER_ADDR
> -
> -#define CALLER_ADDR0 ((unsigned long)__builtin_return_address(0))
> -#define CALLER_ADDR1 ((unsigned long)return_address(1))
> -#define CALLER_ADDR2 ((unsigned long)return_address(2))
> -#define CALLER_ADDR3 ((unsigned long)return_address(3))
> -#define CALLER_ADDR4 ((unsigned long)return_address(4))
> -#define CALLER_ADDR5 ((unsigned long)return_address(5))
> -#define CALLER_ADDR6 ((unsigned long)return_address(6))
> +#define ftrace_return_addr(n) return_address(n)
>  
>  #endif /* ifndef __ASSEMBLY__ */
>  
> diff --git a/arch/blackfin/include/asm/ftrace.h b/arch/blackfin/include/asm/ftrace.h
> index 8a02950..2f1c3c2 100644
> --- a/arch/blackfin/include/asm/ftrace.h
> +++ b/arch/blackfin/include/asm/ftrace.h
> @@ -66,16 +66,7 @@ extern inline void *return_address(unsigned int level)
>  
>  #endif /* CONFIG_FRAME_POINTER */
>  
> -#define HAVE_ARCH_CALLER_ADDR
> -
> -/* inline function or macro may lead to unexpected result */
> -#define CALLER_ADDR0 ((unsigned long)__builtin_return_address(0))
> -#define CALLER_ADDR1 ((unsigned long)return_address(1))
> -#define CALLER_ADDR2 ((unsigned long)return_address(2))
> -#define CALLER_ADDR3 ((unsigned long)return_address(3))
> -#define CALLER_ADDR4 ((unsigned long)return_address(4))
> -#define CALLER_ADDR5 ((unsigned long)return_address(5))
> -#define CALLER_ADDR6 ((unsigned long)return_address(6))
> +#define ftrace_return_address(n) return_address(n)
>  
>  #endif /* __ASSEMBLY__ */
>  
> diff --git a/arch/parisc/include/asm/ftrace.h b/arch/parisc/include/asm/ftrace.h
> index 72c0faf..544ed8e 100644
> --- a/arch/parisc/include/asm/ftrace.h
> +++ b/arch/parisc/include/asm/ftrace.h
> @@ -24,15 +24,7 @@ extern void return_to_handler(void);
>  
>  extern unsigned long return_address(unsigned int);
>  
> -#define HAVE_ARCH_CALLER_ADDR
> -
> -#define CALLER_ADDR0 ((unsigned long)__builtin_return_address(0))
> -#define CALLER_ADDR1 return_address(1)
> -#define CALLER_ADDR2 return_address(2)
> -#define CALLER_ADDR3 return_address(3)
> -#define CALLER_ADDR4 return_address(4)
> -#define CALLER_ADDR5 return_address(5)
> -#define CALLER_ADDR6 return_address(6)
> +#define ftrace_return_address(n) return_address(n)
>  
>  #endif /* __ASSEMBLY__ */
>  
> diff --git a/arch/sh/include/asm/ftrace.h b/arch/sh/include/asm/ftrace.h
> index 13e9966..e79fb6e 100644
> --- a/arch/sh/include/asm/ftrace.h
> +++ b/arch/sh/include/asm/ftrace.h
> @@ -40,15 +40,7 @@ static inline unsigned long ftrace_call_adjust(unsigned long addr)
>  /* arch/sh/kernel/return_address.c */
>  extern void *return_address(unsigned int);
>  
> -#define HAVE_ARCH_CALLER_ADDR
> -
> -#define CALLER_ADDR0 ((unsigned long)__builtin_return_address(0))
> -#define CALLER_ADDR1 ((unsigned long)return_address(1))
> -#define CALLER_ADDR2 ((unsigned long)return_address(2))
> -#define CALLER_ADDR3 ((unsigned long)return_address(3))
> -#define CALLER_ADDR4 ((unsigned long)return_address(4))
> -#define CALLER_ADDR5 ((unsigned long)return_address(5))
> -#define CALLER_ADDR6 ((unsigned long)return_address(6))
> +#define ftrace_return_address(n) return_address(n)
>  
>  #endif /* __ASSEMBLY__ */
>  
> diff --git a/arch/xtensa/include/asm/ftrace.h b/arch/xtensa/include/asm/ftrace.h
> index 736b9d2..6c6d9a9 100644
> --- a/arch/xtensa/include/asm/ftrace.h
> +++ b/arch/xtensa/include/asm/ftrace.h
> @@ -12,24 +12,18 @@
>  
>  #include <asm/processor.h>
>  
> -#define HAVE_ARCH_CALLER_ADDR
>  #ifndef __ASSEMBLY__
> -#define CALLER_ADDR0 ({ unsigned long a0, a1; \
> +#define ftrace_return_address0 ({ unsigned long a0, a1; \
>  		__asm__ __volatile__ ( \
>  			"mov %0, a0\n" \
>  			"mov %1, a1\n" \
>  			: "=r"(a0), "=r"(a1)); \
>  		MAKE_PC_FROM_RA(a0, a1); })
> +
>  #ifdef CONFIG_FRAME_POINTER
>  extern unsigned long return_address(unsigned level);
> -#define CALLER_ADDR1 return_address(1)
> -#define CALLER_ADDR2 return_address(2)
> -#define CALLER_ADDR3 return_address(3)
> -#else /* CONFIG_FRAME_POINTER */
> -#define CALLER_ADDR1 (0)
> -#define CALLER_ADDR2 (0)
> -#define CALLER_ADDR3 (0)
> -#endif /* CONFIG_FRAME_POINTER */
> +#define ftrace_return_address(n) return_address(n)

I would add a comment here that states:

/*
 * #else !CONFIG_FRAME_POINTER
 *
 * Define CALLER_ADDRn (n > 0) to 0 is the default in linux/ftrace.h if
 * ftrace_return_address(n) and CONFIG_FRAME_POINTER are not defined.
 */

Otherwise it looks like you are missing the #else statement.

> +#endif
>  #endif /* __ASSEMBLY__ */
>  
>  #ifdef CONFIG_FUNCTION_TRACER
> diff --git a/include/linux/ftrace.h b/include/linux/ftrace.h
> index 9212b01..18f1ae7 100644
> --- a/include/linux/ftrace.h
> +++ b/include/linux/ftrace.h
> @@ -614,25 +614,27 @@ static inline void __ftrace_enabled_restore(int enabled)
>  #endif
>  }
>  
> -#ifndef HAVE_ARCH_CALLER_ADDR
> +/* All archs should have this, but we define it for consistency */

The comment is a little confusing. I think it may be better stated as:

/*
 * All archs should be able to use __builtin_return_address(0) but
 * we allow them to redefine it for consistency.
 */

> +#ifndef ftrace_return_address0
> +# define ftrace_return_address0 __builtin_return_address(0)
> +#endif
> +
> +/* Archs may use other ways for ADDR1 and beyond */

How about:

/* Not all archs can use __builtin_return_address(n) where n > 0 */

> +#ifndef ftrace_return_address
>  # ifdef CONFIG_FRAME_POINTER
> -#  define CALLER_ADDR0 ((unsigned long)__builtin_return_address(0))
> -#  define CALLER_ADDR1 ((unsigned long)__builtin_return_address(1))
> -#  define CALLER_ADDR2 ((unsigned long)__builtin_return_address(2))
> -#  define CALLER_ADDR3 ((unsigned long)__builtin_return_address(3))
> -#  define CALLER_ADDR4 ((unsigned long)__builtin_return_address(4))
> -#  define CALLER_ADDR5 ((unsigned long)__builtin_return_address(5))
> -#  define CALLER_ADDR6 ((unsigned long)__builtin_return_address(6))
> +#  define ftrace_return_address(n) __builtin_return_address(n)
>  # else
> -#  define CALLER_ADDR0 ((unsigned long)__builtin_return_address(0))
> -#  define CALLER_ADDR1 0UL
> -#  define CALLER_ADDR2 0UL
> -#  define CALLER_ADDR3 0UL
> -#  define CALLER_ADDR4 0UL
> -#  define CALLER_ADDR5 0UL
> -#  define CALLER_ADDR6 0UL
> +#  define ftrace_return_address(n) 0UL
>  # endif
> -#endif /* ifndef HAVE_ARCH_CALLER_ADDR */
> +#endif
> +
> +#define CALLER_ADDR0 ((unsigned long)ftrace_return_address0)
> +#define CALLER_ADDR1 ((unsigned long)ftrace_return_address(1))
> +#define CALLER_ADDR2 ((unsigned long)ftrace_return_address(2))
> +#define CALLER_ADDR3 ((unsigned long)ftrace_return_address(3))
> +#define CALLER_ADDR4 ((unsigned long)ftrace_return_address(4))
> +#define CALLER_ADDR5 ((unsigned long)ftrace_return_address(5))
> +#define CALLER_ADDR6 ((unsigned long)ftrace_return_address(6))

Other than that, it looks good. You can send me the patch and I'll add
it to my 3.16 queue.

Feel free to reply to this email with a v9. When I pull patches into
git, it adds the link to the thread for the patch in LKML. To keep this
entire thread, just reply to it.

Thanks!

-- Steve

>  
>  #ifdef CONFIG_IRQSOFF_TRACER
>    extern void time_hardirqs_on(unsigned long a0, unsigned long a1);


^ permalink raw reply	[flat|nested] 235+ messages in thread

* [PATCH v8 1/8] ftrace: make CALLER_ADDRx macros more generic
@ 2014-05-02 19:19                 ` Steven Rostedt
  0 siblings, 0 replies; 235+ messages in thread
From: Steven Rostedt @ 2014-05-02 19:19 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, 30 Apr 2014 18:54:29 +0900
AKASHI Takahiro <takahiro.akashi@linaro.org> wrote:

> Most archs with HAVE_ARCH_CALLER_ADDR have the almost same definitions
> of CALLER_ADDRx(n), and so put them into linux/ftrace.h.

Please add a bit more to the change log. Like what you did. Something
like:

----
Most archs with HAVE_ARCH_CALLER_ADDR have pretty much the same
definitions of CALLER_ADDRx(n). Instead of duplicating the code for all
the archs, define a ftrace_return_address0() and
ftrace_return_address(n) that can be overwritten by the archs if they
need to do something different. Instead of 7 macros in every arch, we
now only have at most 2 (and actually only 1 as
ftrace_return_address0() should be the same for all archs).

The CALLER_ADDRx(n) will now be defined in linux/ftrace.h and use the
ftrace_return_address*(n?) macros. This removes a lot of the duplicate
code.
-----

Use that if you want :-)


> 
> Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
> ---
>  arch/arm/include/asm/ftrace.h      |   10 +---------
>  arch/blackfin/include/asm/ftrace.h |   11 +----------
>  arch/parisc/include/asm/ftrace.h   |   10 +---------
>  arch/sh/include/asm/ftrace.h       |   10 +---------
>  arch/xtensa/include/asm/ftrace.h   |   14 ++++----------
>  include/linux/ftrace.h             |   34 ++++++++++++++++++----------------
>  6 files changed, 26 insertions(+), 63 deletions(-)
> 
> diff --git a/arch/arm/include/asm/ftrace.h b/arch/arm/include/asm/ftrace.h
> index f89515a..eb577f4 100644
> --- a/arch/arm/include/asm/ftrace.h
> +++ b/arch/arm/include/asm/ftrace.h
> @@ -52,15 +52,7 @@ extern inline void *return_address(unsigned int level)
>  
>  #endif
>  
> -#define HAVE_ARCH_CALLER_ADDR
> -
> -#define CALLER_ADDR0 ((unsigned long)__builtin_return_address(0))
> -#define CALLER_ADDR1 ((unsigned long)return_address(1))
> -#define CALLER_ADDR2 ((unsigned long)return_address(2))
> -#define CALLER_ADDR3 ((unsigned long)return_address(3))
> -#define CALLER_ADDR4 ((unsigned long)return_address(4))
> -#define CALLER_ADDR5 ((unsigned long)return_address(5))
> -#define CALLER_ADDR6 ((unsigned long)return_address(6))
> +#define ftrace_return_addr(n) return_address(n)
>  
>  #endif /* ifndef __ASSEMBLY__ */
>  
> diff --git a/arch/blackfin/include/asm/ftrace.h b/arch/blackfin/include/asm/ftrace.h
> index 8a02950..2f1c3c2 100644
> --- a/arch/blackfin/include/asm/ftrace.h
> +++ b/arch/blackfin/include/asm/ftrace.h
> @@ -66,16 +66,7 @@ extern inline void *return_address(unsigned int level)
>  
>  #endif /* CONFIG_FRAME_POINTER */
>  
> -#define HAVE_ARCH_CALLER_ADDR
> -
> -/* inline function or macro may lead to unexpected result */
> -#define CALLER_ADDR0 ((unsigned long)__builtin_return_address(0))
> -#define CALLER_ADDR1 ((unsigned long)return_address(1))
> -#define CALLER_ADDR2 ((unsigned long)return_address(2))
> -#define CALLER_ADDR3 ((unsigned long)return_address(3))
> -#define CALLER_ADDR4 ((unsigned long)return_address(4))
> -#define CALLER_ADDR5 ((unsigned long)return_address(5))
> -#define CALLER_ADDR6 ((unsigned long)return_address(6))
> +#define ftrace_return_address(n) return_address(n)
>  
>  #endif /* __ASSEMBLY__ */
>  
> diff --git a/arch/parisc/include/asm/ftrace.h b/arch/parisc/include/asm/ftrace.h
> index 72c0faf..544ed8e 100644
> --- a/arch/parisc/include/asm/ftrace.h
> +++ b/arch/parisc/include/asm/ftrace.h
> @@ -24,15 +24,7 @@ extern void return_to_handler(void);
>  
>  extern unsigned long return_address(unsigned int);
>  
> -#define HAVE_ARCH_CALLER_ADDR
> -
> -#define CALLER_ADDR0 ((unsigned long)__builtin_return_address(0))
> -#define CALLER_ADDR1 return_address(1)
> -#define CALLER_ADDR2 return_address(2)
> -#define CALLER_ADDR3 return_address(3)
> -#define CALLER_ADDR4 return_address(4)
> -#define CALLER_ADDR5 return_address(5)
> -#define CALLER_ADDR6 return_address(6)
> +#define ftrace_return_address(n) return_address(n)
>  
>  #endif /* __ASSEMBLY__ */
>  
> diff --git a/arch/sh/include/asm/ftrace.h b/arch/sh/include/asm/ftrace.h
> index 13e9966..e79fb6e 100644
> --- a/arch/sh/include/asm/ftrace.h
> +++ b/arch/sh/include/asm/ftrace.h
> @@ -40,15 +40,7 @@ static inline unsigned long ftrace_call_adjust(unsigned long addr)
>  /* arch/sh/kernel/return_address.c */
>  extern void *return_address(unsigned int);
>  
> -#define HAVE_ARCH_CALLER_ADDR
> -
> -#define CALLER_ADDR0 ((unsigned long)__builtin_return_address(0))
> -#define CALLER_ADDR1 ((unsigned long)return_address(1))
> -#define CALLER_ADDR2 ((unsigned long)return_address(2))
> -#define CALLER_ADDR3 ((unsigned long)return_address(3))
> -#define CALLER_ADDR4 ((unsigned long)return_address(4))
> -#define CALLER_ADDR5 ((unsigned long)return_address(5))
> -#define CALLER_ADDR6 ((unsigned long)return_address(6))
> +#define ftrace_return_address(n) return_address(n)
>  
>  #endif /* __ASSEMBLY__ */
>  
> diff --git a/arch/xtensa/include/asm/ftrace.h b/arch/xtensa/include/asm/ftrace.h
> index 736b9d2..6c6d9a9 100644
> --- a/arch/xtensa/include/asm/ftrace.h
> +++ b/arch/xtensa/include/asm/ftrace.h
> @@ -12,24 +12,18 @@
>  
>  #include <asm/processor.h>
>  
> -#define HAVE_ARCH_CALLER_ADDR
>  #ifndef __ASSEMBLY__
> -#define CALLER_ADDR0 ({ unsigned long a0, a1; \
> +#define ftrace_return_address0 ({ unsigned long a0, a1; \
>  		__asm__ __volatile__ ( \
>  			"mov %0, a0\n" \
>  			"mov %1, a1\n" \
>  			: "=r"(a0), "=r"(a1)); \
>  		MAKE_PC_FROM_RA(a0, a1); })
> +
>  #ifdef CONFIG_FRAME_POINTER
>  extern unsigned long return_address(unsigned level);
> -#define CALLER_ADDR1 return_address(1)
> -#define CALLER_ADDR2 return_address(2)
> -#define CALLER_ADDR3 return_address(3)
> -#else /* CONFIG_FRAME_POINTER */
> -#define CALLER_ADDR1 (0)
> -#define CALLER_ADDR2 (0)
> -#define CALLER_ADDR3 (0)
> -#endif /* CONFIG_FRAME_POINTER */
> +#define ftrace_return_address(n) return_address(n)

I would add a comment here that states:

/*
 * #else !CONFIG_FRAME_POINTER
 *
 * Define CALLER_ADDRn (n > 0) to 0 is the default in linux/ftrace.h if
 * ftrace_return_address(n) and CONFIG_FRAME_POINTER are not defined.
 */

Otherwise it looks like you are missing the #else statement.

> +#endif
>  #endif /* __ASSEMBLY__ */
>  
>  #ifdef CONFIG_FUNCTION_TRACER
> diff --git a/include/linux/ftrace.h b/include/linux/ftrace.h
> index 9212b01..18f1ae7 100644
> --- a/include/linux/ftrace.h
> +++ b/include/linux/ftrace.h
> @@ -614,25 +614,27 @@ static inline void __ftrace_enabled_restore(int enabled)
>  #endif
>  }
>  
> -#ifndef HAVE_ARCH_CALLER_ADDR
> +/* All archs should have this, but we define it for consistency */

The comment is a little confusing. I think it may be better stated as:

/*
 * All archs should be able to use __builtin_return_address(0) but
 * we allow them to redefine it for consistency.
 */

> +#ifndef ftrace_return_address0
> +# define ftrace_return_address0 __builtin_return_address(0)
> +#endif
> +
> +/* Archs may use other ways for ADDR1 and beyond */

How about:

/* Not all archs can use __builtin_return_address(n) where n > 0 */

> +#ifndef ftrace_return_address
>  # ifdef CONFIG_FRAME_POINTER
> -#  define CALLER_ADDR0 ((unsigned long)__builtin_return_address(0))
> -#  define CALLER_ADDR1 ((unsigned long)__builtin_return_address(1))
> -#  define CALLER_ADDR2 ((unsigned long)__builtin_return_address(2))
> -#  define CALLER_ADDR3 ((unsigned long)__builtin_return_address(3))
> -#  define CALLER_ADDR4 ((unsigned long)__builtin_return_address(4))
> -#  define CALLER_ADDR5 ((unsigned long)__builtin_return_address(5))
> -#  define CALLER_ADDR6 ((unsigned long)__builtin_return_address(6))
> +#  define ftrace_return_address(n) __builtin_return_address(n)
>  # else
> -#  define CALLER_ADDR0 ((unsigned long)__builtin_return_address(0))
> -#  define CALLER_ADDR1 0UL
> -#  define CALLER_ADDR2 0UL
> -#  define CALLER_ADDR3 0UL
> -#  define CALLER_ADDR4 0UL
> -#  define CALLER_ADDR5 0UL
> -#  define CALLER_ADDR6 0UL
> +#  define ftrace_return_address(n) 0UL
>  # endif
> -#endif /* ifndef HAVE_ARCH_CALLER_ADDR */
> +#endif
> +
> +#define CALLER_ADDR0 ((unsigned long)ftrace_return_address0)
> +#define CALLER_ADDR1 ((unsigned long)ftrace_return_address(1))
> +#define CALLER_ADDR2 ((unsigned long)ftrace_return_address(2))
> +#define CALLER_ADDR3 ((unsigned long)ftrace_return_address(3))
> +#define CALLER_ADDR4 ((unsigned long)ftrace_return_address(4))
> +#define CALLER_ADDR5 ((unsigned long)ftrace_return_address(5))
> +#define CALLER_ADDR6 ((unsigned long)ftrace_return_address(6))

Other than that, it looks good. You can send me the patch and I'll add
it to my 3.16 queue.

Feel free to reply to this email with a v9. When I pull patches into
git, it adds the link to the thread for the patch in LKML. To keep this
entire thread, just reply to it.

Thanks!

-- Steve

>  
>  #ifdef CONFIG_IRQSOFF_TRACER
>    extern void time_hardirqs_on(unsigned long a0, unsigned long a1);

^ permalink raw reply	[flat|nested] 235+ messages in thread

* Re: [PATCH v8 1/8] ftrace: make CALLER_ADDRx macros more generic
  2014-05-02 19:19                 ` Steven Rostedt
@ 2014-05-12 15:58                   ` Will Deacon
  -1 siblings, 0 replies; 235+ messages in thread
From: Will Deacon @ 2014-05-12 15:58 UTC (permalink / raw)
  To: Steven Rostedt
  Cc: AKASHI Takahiro, fweisbec, mingo, Catalin Marinas, tim.bird,
	gkulkarni, dsaxena, arndb, linux-arm-kernel, linaro-kernel,
	linux-kernel

Hi guys,

On Fri, May 02, 2014 at 08:19:57PM +0100, Steven Rostedt wrote:
> On Wed, 30 Apr 2014 18:54:29 +0900
> AKASHI Takahiro <takahiro.akashi@linaro.org> wrote:
> 
> > Most archs with HAVE_ARCH_CALLER_ADDR have the almost same definitions
> > of CALLER_ADDRx(n), and so put them into linux/ftrace.h.
> 
> Please add a bit more to the change log. Like what you did. Something
> like:
> 
> ----
> Most archs with HAVE_ARCH_CALLER_ADDR have pretty much the same
> definitions of CALLER_ADDRx(n). Instead of duplicating the code for all
> the archs, define a ftrace_return_address0() and
> ftrace_return_address(n) that can be overwritten by the archs if they
> need to do something different. Instead of 7 macros in every arch, we
> now only have at most 2 (and actually only 1 as
> ftrace_return_address0() should be the same for all archs).
> 
> The CALLER_ADDRx(n) will now be defined in linux/ftrace.h and use the
> ftrace_return_address*(n?) macros. This removes a lot of the duplicate
> code.
> -----
> 
> Use that if you want :-)

Akashi: did you get around to posting a new version of this patch? We can't
take your arm64 patches until you get the core stuff merged...

Will

^ permalink raw reply	[flat|nested] 235+ messages in thread

* [PATCH v8 1/8] ftrace: make CALLER_ADDRx macros more generic
@ 2014-05-12 15:58                   ` Will Deacon
  0 siblings, 0 replies; 235+ messages in thread
From: Will Deacon @ 2014-05-12 15:58 UTC (permalink / raw)
  To: linux-arm-kernel

Hi guys,

On Fri, May 02, 2014 at 08:19:57PM +0100, Steven Rostedt wrote:
> On Wed, 30 Apr 2014 18:54:29 +0900
> AKASHI Takahiro <takahiro.akashi@linaro.org> wrote:
> 
> > Most archs with HAVE_ARCH_CALLER_ADDR have the almost same definitions
> > of CALLER_ADDRx(n), and so put them into linux/ftrace.h.
> 
> Please add a bit more to the change log. Like what you did. Something
> like:
> 
> ----
> Most archs with HAVE_ARCH_CALLER_ADDR have pretty much the same
> definitions of CALLER_ADDRx(n). Instead of duplicating the code for all
> the archs, define a ftrace_return_address0() and
> ftrace_return_address(n) that can be overwritten by the archs if they
> need to do something different. Instead of 7 macros in every arch, we
> now only have at most 2 (and actually only 1 as
> ftrace_return_address0() should be the same for all archs).
> 
> The CALLER_ADDRx(n) will now be defined in linux/ftrace.h and use the
> ftrace_return_address*(n?) macros. This removes a lot of the duplicate
> code.
> -----
> 
> Use that if you want :-)

Akashi: did you get around to posting a new version of this patch? We can't
take your arm64 patches until you get the core stuff merged...

Will

^ permalink raw reply	[flat|nested] 235+ messages in thread

* Re: [PATCH v8 1/8] ftrace: make CALLER_ADDRx macros more generic
  2014-05-12 15:58                   ` Will Deacon
@ 2014-05-12 16:05                     ` Steven Rostedt
  -1 siblings, 0 replies; 235+ messages in thread
From: Steven Rostedt @ 2014-05-12 16:05 UTC (permalink / raw)
  To: Will Deacon
  Cc: AKASHI Takahiro, fweisbec, mingo, Catalin Marinas, tim.bird,
	gkulkarni, dsaxena, arndb, linux-arm-kernel, linaro-kernel,
	linux-kernel

On Mon, 12 May 2014 16:58:11 +0100
Will Deacon <will.deacon@arm.com> wrote:

> Akashi: did you get around to posting a new version of this patch? We can't
> take your arm64 patches until you get the core stuff merged...

I haven't seen any patches yet.

What I can also do is to create a separate branch based on mainline,
and just apply this change to the core. Then you could pull that branch
with a note to Linus that it is also in my tree with the common
ancestor.

If he pulls your work first, he'll only get that change from my tree,
and if he pulls mine first it doesn't matter as all the changes will be
there.

This is something he said at Kernel Summit that was normal procedure if
there's a change in one tree that another tree is dependent on.

-- Steve


^ permalink raw reply	[flat|nested] 235+ messages in thread

* [PATCH v8 1/8] ftrace: make CALLER_ADDRx macros more generic
@ 2014-05-12 16:05                     ` Steven Rostedt
  0 siblings, 0 replies; 235+ messages in thread
From: Steven Rostedt @ 2014-05-12 16:05 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, 12 May 2014 16:58:11 +0100
Will Deacon <will.deacon@arm.com> wrote:

> Akashi: did you get around to posting a new version of this patch? We can't
> take your arm64 patches until you get the core stuff merged...

I haven't seen any patches yet.

What I can also do is to create a separate branch based on mainline,
and just apply this change to the core. Then you could pull that branch
with a note to Linus that it is also in my tree with the common
ancestor.

If he pulls your work first, he'll only get that change from my tree,
and if he pulls mine first it doesn't matter as all the changes will be
there.

This is something he said at Kernel Summit that was normal procedure if
there's a change in one tree that another tree is dependent on.

-- Steve

^ permalink raw reply	[flat|nested] 235+ messages in thread

* Re: [PATCH v8 1/8] ftrace: make CALLER_ADDRx macros more generic
  2014-05-12 16:05                     ` Steven Rostedt
@ 2014-05-12 16:12                       ` Will Deacon
  -1 siblings, 0 replies; 235+ messages in thread
From: Will Deacon @ 2014-05-12 16:12 UTC (permalink / raw)
  To: Steven Rostedt
  Cc: AKASHI Takahiro, fweisbec, mingo, Catalin Marinas, tim.bird,
	gkulkarni, dsaxena, arndb, linux-arm-kernel, linaro-kernel,
	linux-kernel

Hey Steve,

On Mon, May 12, 2014 at 05:05:35PM +0100, Steven Rostedt wrote:
> On Mon, 12 May 2014 16:58:11 +0100
> Will Deacon <will.deacon@arm.com> wrote:
> 
> > Akashi: did you get around to posting a new version of this patch? We can't
> > take your arm64 patches until you get the core stuff merged...
> 
> I haven't seen any patches yet.
> 
> What I can also do is to create a separate branch based on mainline,
> and just apply this change to the core. Then you could pull that branch
> with a note to Linus that it is also in my tree with the common
> ancestor.
> 
> If he pulls your work first, he'll only get that change from my tree,
> and if he pulls mine first it doesn't matter as all the changes will be
> there.
> 
> This is something he said at Kernel Summit that was normal procedure if
> there's a change in one tree that another tree is dependent on.

That sounds great, and nicely solves the dependency between our trees for
3.16 at the same time.

If you point us at the branch and promise not to rebase it, that would be
fantastic.

Cheers,

Will

^ permalink raw reply	[flat|nested] 235+ messages in thread

* [PATCH v8 1/8] ftrace: make CALLER_ADDRx macros more generic
@ 2014-05-12 16:12                       ` Will Deacon
  0 siblings, 0 replies; 235+ messages in thread
From: Will Deacon @ 2014-05-12 16:12 UTC (permalink / raw)
  To: linux-arm-kernel

Hey Steve,

On Mon, May 12, 2014 at 05:05:35PM +0100, Steven Rostedt wrote:
> On Mon, 12 May 2014 16:58:11 +0100
> Will Deacon <will.deacon@arm.com> wrote:
> 
> > Akashi: did you get around to posting a new version of this patch? We can't
> > take your arm64 patches until you get the core stuff merged...
> 
> I haven't seen any patches yet.
> 
> What I can also do is to create a separate branch based on mainline,
> and just apply this change to the core. Then you could pull that branch
> with a note to Linus that it is also in my tree with the common
> ancestor.
> 
> If he pulls your work first, he'll only get that change from my tree,
> and if he pulls mine first it doesn't matter as all the changes will be
> there.
> 
> This is something he said at Kernel Summit that was normal procedure if
> there's a change in one tree that another tree is dependent on.

That sounds great, and nicely solves the dependency between our trees for
3.16 at the same time.

If you point us at the branch and promise not to rebase it, that would be
fantastic.

Cheers,

Will

^ permalink raw reply	[flat|nested] 235+ messages in thread

* Re: [PATCH v8 1/8] ftrace: make CALLER_ADDRx macros more generic
  2014-05-12 16:12                       ` Will Deacon
@ 2014-05-12 17:23                         ` Steven Rostedt
  -1 siblings, 0 replies; 235+ messages in thread
From: Steven Rostedt @ 2014-05-12 17:23 UTC (permalink / raw)
  To: Will Deacon
  Cc: AKASHI Takahiro, fweisbec, mingo, Catalin Marinas, tim.bird,
	gkulkarni, dsaxena, arndb, linux-arm-kernel, linaro-kernel,
	linux-kernel

On Mon, 12 May 2014 17:12:46 +0100
Will Deacon <will.deacon@arm.com> wrote:


> If you point us at the branch and promise not to rebase it, that would be
> fantastic.

I will when I get the patch(es) :-) and run it through all my tests.

-- Steve


^ permalink raw reply	[flat|nested] 235+ messages in thread

* [PATCH v8 1/8] ftrace: make CALLER_ADDRx macros more generic
@ 2014-05-12 17:23                         ` Steven Rostedt
  0 siblings, 0 replies; 235+ messages in thread
From: Steven Rostedt @ 2014-05-12 17:23 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, 12 May 2014 17:12:46 +0100
Will Deacon <will.deacon@arm.com> wrote:


> If you point us at the branch and promise not to rebase it, that would be
> fantastic.

I will when I get the patch(es) :-) and run it through all my tests.

-- Steve

^ permalink raw reply	[flat|nested] 235+ messages in thread

* Re: [PATCH v8 1/8] ftrace: make CALLER_ADDRx macros more generic
  2014-05-02 19:19                 ` Steven Rostedt
@ 2014-05-20 11:29                   ` AKASHI Takahiro
  -1 siblings, 0 replies; 235+ messages in thread
From: AKASHI Takahiro @ 2014-05-20 11:29 UTC (permalink / raw)
  To: Steven Rostedt
  Cc: fweisbec, mingo, catalin.marinas, will.deacon, tim.bird,
	gkulkarni, dsaxena, arndb, linux-arm-kernel, linaro-kernel,
	linux-kernel

Hi Will, Steven,

So sorry, I completely missed this message thread. I will submit a new patch (replacement of [1/8])
in the following e-mail.

-Takahiro AKASHI

On 05/03/2014 04:19 AM, Steven Rostedt wrote:
> On Wed, 30 Apr 2014 18:54:29 +0900
> AKASHI Takahiro <takahiro.akashi@linaro.org> wrote:
>
>> Most archs with HAVE_ARCH_CALLER_ADDR have the almost same definitions
>> of CALLER_ADDRx(n), and so put them into linux/ftrace.h.
>
> Please add a bit more to the change log. Like what you did. Something
> like:
>
> ----
> Most archs with HAVE_ARCH_CALLER_ADDR have pretty much the same
> definitions of CALLER_ADDRx(n). Instead of duplicating the code for all
> the archs, define a ftrace_return_address0() and
> ftrace_return_address(n) that can be overwritten by the archs if they
> need to do something different. Instead of 7 macros in every arch, we
> now only have at most 2 (and actually only 1 as
> ftrace_return_address0() should be the same for all archs).
>
> The CALLER_ADDRx(n) will now be defined in linux/ftrace.h and use the
> ftrace_return_address*(n?) macros. This removes a lot of the duplicate
> code.
> -----
>
> Use that if you want :-)
>
>
>>
>> Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
>> ---
>>   arch/arm/include/asm/ftrace.h      |   10 +---------
>>   arch/blackfin/include/asm/ftrace.h |   11 +----------
>>   arch/parisc/include/asm/ftrace.h   |   10 +---------
>>   arch/sh/include/asm/ftrace.h       |   10 +---------
>>   arch/xtensa/include/asm/ftrace.h   |   14 ++++----------
>>   include/linux/ftrace.h             |   34 ++++++++++++++++++----------------
>>   6 files changed, 26 insertions(+), 63 deletions(-)
>>
>> diff --git a/arch/arm/include/asm/ftrace.h b/arch/arm/include/asm/ftrace.h
>> index f89515a..eb577f4 100644
>> --- a/arch/arm/include/asm/ftrace.h
>> +++ b/arch/arm/include/asm/ftrace.h
>> @@ -52,15 +52,7 @@ extern inline void *return_address(unsigned int level)
>>
>>   #endif
>>
>> -#define HAVE_ARCH_CALLER_ADDR
>> -
>> -#define CALLER_ADDR0 ((unsigned long)__builtin_return_address(0))
>> -#define CALLER_ADDR1 ((unsigned long)return_address(1))
>> -#define CALLER_ADDR2 ((unsigned long)return_address(2))
>> -#define CALLER_ADDR3 ((unsigned long)return_address(3))
>> -#define CALLER_ADDR4 ((unsigned long)return_address(4))
>> -#define CALLER_ADDR5 ((unsigned long)return_address(5))
>> -#define CALLER_ADDR6 ((unsigned long)return_address(6))
>> +#define ftrace_return_addr(n) return_address(n)
>>
>>   #endif /* ifndef __ASSEMBLY__ */
>>
>> diff --git a/arch/blackfin/include/asm/ftrace.h b/arch/blackfin/include/asm/ftrace.h
>> index 8a02950..2f1c3c2 100644
>> --- a/arch/blackfin/include/asm/ftrace.h
>> +++ b/arch/blackfin/include/asm/ftrace.h
>> @@ -66,16 +66,7 @@ extern inline void *return_address(unsigned int level)
>>
>>   #endif /* CONFIG_FRAME_POINTER */
>>
>> -#define HAVE_ARCH_CALLER_ADDR
>> -
>> -/* inline function or macro may lead to unexpected result */
>> -#define CALLER_ADDR0 ((unsigned long)__builtin_return_address(0))
>> -#define CALLER_ADDR1 ((unsigned long)return_address(1))
>> -#define CALLER_ADDR2 ((unsigned long)return_address(2))
>> -#define CALLER_ADDR3 ((unsigned long)return_address(3))
>> -#define CALLER_ADDR4 ((unsigned long)return_address(4))
>> -#define CALLER_ADDR5 ((unsigned long)return_address(5))
>> -#define CALLER_ADDR6 ((unsigned long)return_address(6))
>> +#define ftrace_return_address(n) return_address(n)
>>
>>   #endif /* __ASSEMBLY__ */
>>
>> diff --git a/arch/parisc/include/asm/ftrace.h b/arch/parisc/include/asm/ftrace.h
>> index 72c0faf..544ed8e 100644
>> --- a/arch/parisc/include/asm/ftrace.h
>> +++ b/arch/parisc/include/asm/ftrace.h
>> @@ -24,15 +24,7 @@ extern void return_to_handler(void);
>>
>>   extern unsigned long return_address(unsigned int);
>>
>> -#define HAVE_ARCH_CALLER_ADDR
>> -
>> -#define CALLER_ADDR0 ((unsigned long)__builtin_return_address(0))
>> -#define CALLER_ADDR1 return_address(1)
>> -#define CALLER_ADDR2 return_address(2)
>> -#define CALLER_ADDR3 return_address(3)
>> -#define CALLER_ADDR4 return_address(4)
>> -#define CALLER_ADDR5 return_address(5)
>> -#define CALLER_ADDR6 return_address(6)
>> +#define ftrace_return_address(n) return_address(n)
>>
>>   #endif /* __ASSEMBLY__ */
>>
>> diff --git a/arch/sh/include/asm/ftrace.h b/arch/sh/include/asm/ftrace.h
>> index 13e9966..e79fb6e 100644
>> --- a/arch/sh/include/asm/ftrace.h
>> +++ b/arch/sh/include/asm/ftrace.h
>> @@ -40,15 +40,7 @@ static inline unsigned long ftrace_call_adjust(unsigned long addr)
>>   /* arch/sh/kernel/return_address.c */
>>   extern void *return_address(unsigned int);
>>
>> -#define HAVE_ARCH_CALLER_ADDR
>> -
>> -#define CALLER_ADDR0 ((unsigned long)__builtin_return_address(0))
>> -#define CALLER_ADDR1 ((unsigned long)return_address(1))
>> -#define CALLER_ADDR2 ((unsigned long)return_address(2))
>> -#define CALLER_ADDR3 ((unsigned long)return_address(3))
>> -#define CALLER_ADDR4 ((unsigned long)return_address(4))
>> -#define CALLER_ADDR5 ((unsigned long)return_address(5))
>> -#define CALLER_ADDR6 ((unsigned long)return_address(6))
>> +#define ftrace_return_address(n) return_address(n)
>>
>>   #endif /* __ASSEMBLY__ */
>>
>> diff --git a/arch/xtensa/include/asm/ftrace.h b/arch/xtensa/include/asm/ftrace.h
>> index 736b9d2..6c6d9a9 100644
>> --- a/arch/xtensa/include/asm/ftrace.h
>> +++ b/arch/xtensa/include/asm/ftrace.h
>> @@ -12,24 +12,18 @@
>>
>>   #include <asm/processor.h>
>>
>> -#define HAVE_ARCH_CALLER_ADDR
>>   #ifndef __ASSEMBLY__
>> -#define CALLER_ADDR0 ({ unsigned long a0, a1; \
>> +#define ftrace_return_address0 ({ unsigned long a0, a1; \
>>   		__asm__ __volatile__ ( \
>>   			"mov %0, a0\n" \
>>   			"mov %1, a1\n" \
>>   			: "=r"(a0), "=r"(a1)); \
>>   		MAKE_PC_FROM_RA(a0, a1); })
>> +
>>   #ifdef CONFIG_FRAME_POINTER
>>   extern unsigned long return_address(unsigned level);
>> -#define CALLER_ADDR1 return_address(1)
>> -#define CALLER_ADDR2 return_address(2)
>> -#define CALLER_ADDR3 return_address(3)
>> -#else /* CONFIG_FRAME_POINTER */
>> -#define CALLER_ADDR1 (0)
>> -#define CALLER_ADDR2 (0)
>> -#define CALLER_ADDR3 (0)
>> -#endif /* CONFIG_FRAME_POINTER */
>> +#define ftrace_return_address(n) return_address(n)
>
> I would add a comment here that states:
>
> /*
>   * #else !CONFIG_FRAME_POINTER
>   *
>   * Define CALLER_ADDRn (n > 0) to 0 is the default in linux/ftrace.h if
>   * ftrace_return_address(n) and CONFIG_FRAME_POINTER are not defined.
>   */
>
> Otherwise it looks like you are missing the #else statement.
>
>> +#endif
>>   #endif /* __ASSEMBLY__ */
>>
>>   #ifdef CONFIG_FUNCTION_TRACER
>> diff --git a/include/linux/ftrace.h b/include/linux/ftrace.h
>> index 9212b01..18f1ae7 100644
>> --- a/include/linux/ftrace.h
>> +++ b/include/linux/ftrace.h
>> @@ -614,25 +614,27 @@ static inline void __ftrace_enabled_restore(int enabled)
>>   #endif
>>   }
>>
>> -#ifndef HAVE_ARCH_CALLER_ADDR
>> +/* All archs should have this, but we define it for consistency */
>
> The comment is a little confusing. I think it may be better stated as:
>
> /*
>   * All archs should be able to use __builtin_return_address(0) but
>   * we allow them to redefine it for consistency.
>   */
>
>> +#ifndef ftrace_return_address0
>> +# define ftrace_return_address0 __builtin_return_address(0)
>> +#endif
>> +
>> +/* Archs may use other ways for ADDR1 and beyond */
>
> How about:
>
> /* Not all archs can use __builtin_return_address(n) where n > 0 */
>
>> +#ifndef ftrace_return_address
>>   # ifdef CONFIG_FRAME_POINTER
>> -#  define CALLER_ADDR0 ((unsigned long)__builtin_return_address(0))
>> -#  define CALLER_ADDR1 ((unsigned long)__builtin_return_address(1))
>> -#  define CALLER_ADDR2 ((unsigned long)__builtin_return_address(2))
>> -#  define CALLER_ADDR3 ((unsigned long)__builtin_return_address(3))
>> -#  define CALLER_ADDR4 ((unsigned long)__builtin_return_address(4))
>> -#  define CALLER_ADDR5 ((unsigned long)__builtin_return_address(5))
>> -#  define CALLER_ADDR6 ((unsigned long)__builtin_return_address(6))
>> +#  define ftrace_return_address(n) __builtin_return_address(n)
>>   # else
>> -#  define CALLER_ADDR0 ((unsigned long)__builtin_return_address(0))
>> -#  define CALLER_ADDR1 0UL
>> -#  define CALLER_ADDR2 0UL
>> -#  define CALLER_ADDR3 0UL
>> -#  define CALLER_ADDR4 0UL
>> -#  define CALLER_ADDR5 0UL
>> -#  define CALLER_ADDR6 0UL
>> +#  define ftrace_return_address(n) 0UL
>>   # endif
>> -#endif /* ifndef HAVE_ARCH_CALLER_ADDR */
>> +#endif
>> +
>> +#define CALLER_ADDR0 ((unsigned long)ftrace_return_address0)
>> +#define CALLER_ADDR1 ((unsigned long)ftrace_return_address(1))
>> +#define CALLER_ADDR2 ((unsigned long)ftrace_return_address(2))
>> +#define CALLER_ADDR3 ((unsigned long)ftrace_return_address(3))
>> +#define CALLER_ADDR4 ((unsigned long)ftrace_return_address(4))
>> +#define CALLER_ADDR5 ((unsigned long)ftrace_return_address(5))
>> +#define CALLER_ADDR6 ((unsigned long)ftrace_return_address(6))
>
> Other than that, it looks good. You can send me the patch and I'll add
> it to my 3.16 queue.
>
> Feel free to reply to this email with a v9. When I pull patches into
> git, it adds the link to the thread for the patch in LKML. To keep this
> entire thread, just reply to it.
>
> Thanks!
>
> -- Steve
>
>>
>>   #ifdef CONFIG_IRQSOFF_TRACER
>>     extern void time_hardirqs_on(unsigned long a0, unsigned long a1);
>

^ permalink raw reply	[flat|nested] 235+ messages in thread

* [PATCH v8 1/8] ftrace: make CALLER_ADDRx macros more generic
@ 2014-05-20 11:29                   ` AKASHI Takahiro
  0 siblings, 0 replies; 235+ messages in thread
From: AKASHI Takahiro @ 2014-05-20 11:29 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Will, Steven,

So sorry, I completely missed this message thread. I will submit a new patch (replacement of [1/8])
in the following e-mail.

-Takahiro AKASHI

On 05/03/2014 04:19 AM, Steven Rostedt wrote:
> On Wed, 30 Apr 2014 18:54:29 +0900
> AKASHI Takahiro <takahiro.akashi@linaro.org> wrote:
>
>> Most archs with HAVE_ARCH_CALLER_ADDR have the almost same definitions
>> of CALLER_ADDRx(n), and so put them into linux/ftrace.h.
>
> Please add a bit more to the change log. Like what you did. Something
> like:
>
> ----
> Most archs with HAVE_ARCH_CALLER_ADDR have pretty much the same
> definitions of CALLER_ADDRx(n). Instead of duplicating the code for all
> the archs, define a ftrace_return_address0() and
> ftrace_return_address(n) that can be overwritten by the archs if they
> need to do something different. Instead of 7 macros in every arch, we
> now only have at most 2 (and actually only 1 as
> ftrace_return_address0() should be the same for all archs).
>
> The CALLER_ADDRx(n) will now be defined in linux/ftrace.h and use the
> ftrace_return_address*(n?) macros. This removes a lot of the duplicate
> code.
> -----
>
> Use that if you want :-)
>
>
>>
>> Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
>> ---
>>   arch/arm/include/asm/ftrace.h      |   10 +---------
>>   arch/blackfin/include/asm/ftrace.h |   11 +----------
>>   arch/parisc/include/asm/ftrace.h   |   10 +---------
>>   arch/sh/include/asm/ftrace.h       |   10 +---------
>>   arch/xtensa/include/asm/ftrace.h   |   14 ++++----------
>>   include/linux/ftrace.h             |   34 ++++++++++++++++++----------------
>>   6 files changed, 26 insertions(+), 63 deletions(-)
>>
>> diff --git a/arch/arm/include/asm/ftrace.h b/arch/arm/include/asm/ftrace.h
>> index f89515a..eb577f4 100644
>> --- a/arch/arm/include/asm/ftrace.h
>> +++ b/arch/arm/include/asm/ftrace.h
>> @@ -52,15 +52,7 @@ extern inline void *return_address(unsigned int level)
>>
>>   #endif
>>
>> -#define HAVE_ARCH_CALLER_ADDR
>> -
>> -#define CALLER_ADDR0 ((unsigned long)__builtin_return_address(0))
>> -#define CALLER_ADDR1 ((unsigned long)return_address(1))
>> -#define CALLER_ADDR2 ((unsigned long)return_address(2))
>> -#define CALLER_ADDR3 ((unsigned long)return_address(3))
>> -#define CALLER_ADDR4 ((unsigned long)return_address(4))
>> -#define CALLER_ADDR5 ((unsigned long)return_address(5))
>> -#define CALLER_ADDR6 ((unsigned long)return_address(6))
>> +#define ftrace_return_addr(n) return_address(n)
>>
>>   #endif /* ifndef __ASSEMBLY__ */
>>
>> diff --git a/arch/blackfin/include/asm/ftrace.h b/arch/blackfin/include/asm/ftrace.h
>> index 8a02950..2f1c3c2 100644
>> --- a/arch/blackfin/include/asm/ftrace.h
>> +++ b/arch/blackfin/include/asm/ftrace.h
>> @@ -66,16 +66,7 @@ extern inline void *return_address(unsigned int level)
>>
>>   #endif /* CONFIG_FRAME_POINTER */
>>
>> -#define HAVE_ARCH_CALLER_ADDR
>> -
>> -/* inline function or macro may lead to unexpected result */
>> -#define CALLER_ADDR0 ((unsigned long)__builtin_return_address(0))
>> -#define CALLER_ADDR1 ((unsigned long)return_address(1))
>> -#define CALLER_ADDR2 ((unsigned long)return_address(2))
>> -#define CALLER_ADDR3 ((unsigned long)return_address(3))
>> -#define CALLER_ADDR4 ((unsigned long)return_address(4))
>> -#define CALLER_ADDR5 ((unsigned long)return_address(5))
>> -#define CALLER_ADDR6 ((unsigned long)return_address(6))
>> +#define ftrace_return_address(n) return_address(n)
>>
>>   #endif /* __ASSEMBLY__ */
>>
>> diff --git a/arch/parisc/include/asm/ftrace.h b/arch/parisc/include/asm/ftrace.h
>> index 72c0faf..544ed8e 100644
>> --- a/arch/parisc/include/asm/ftrace.h
>> +++ b/arch/parisc/include/asm/ftrace.h
>> @@ -24,15 +24,7 @@ extern void return_to_handler(void);
>>
>>   extern unsigned long return_address(unsigned int);
>>
>> -#define HAVE_ARCH_CALLER_ADDR
>> -
>> -#define CALLER_ADDR0 ((unsigned long)__builtin_return_address(0))
>> -#define CALLER_ADDR1 return_address(1)
>> -#define CALLER_ADDR2 return_address(2)
>> -#define CALLER_ADDR3 return_address(3)
>> -#define CALLER_ADDR4 return_address(4)
>> -#define CALLER_ADDR5 return_address(5)
>> -#define CALLER_ADDR6 return_address(6)
>> +#define ftrace_return_address(n) return_address(n)
>>
>>   #endif /* __ASSEMBLY__ */
>>
>> diff --git a/arch/sh/include/asm/ftrace.h b/arch/sh/include/asm/ftrace.h
>> index 13e9966..e79fb6e 100644
>> --- a/arch/sh/include/asm/ftrace.h
>> +++ b/arch/sh/include/asm/ftrace.h
>> @@ -40,15 +40,7 @@ static inline unsigned long ftrace_call_adjust(unsigned long addr)
>>   /* arch/sh/kernel/return_address.c */
>>   extern void *return_address(unsigned int);
>>
>> -#define HAVE_ARCH_CALLER_ADDR
>> -
>> -#define CALLER_ADDR0 ((unsigned long)__builtin_return_address(0))
>> -#define CALLER_ADDR1 ((unsigned long)return_address(1))
>> -#define CALLER_ADDR2 ((unsigned long)return_address(2))
>> -#define CALLER_ADDR3 ((unsigned long)return_address(3))
>> -#define CALLER_ADDR4 ((unsigned long)return_address(4))
>> -#define CALLER_ADDR5 ((unsigned long)return_address(5))
>> -#define CALLER_ADDR6 ((unsigned long)return_address(6))
>> +#define ftrace_return_address(n) return_address(n)
>>
>>   #endif /* __ASSEMBLY__ */
>>
>> diff --git a/arch/xtensa/include/asm/ftrace.h b/arch/xtensa/include/asm/ftrace.h
>> index 736b9d2..6c6d9a9 100644
>> --- a/arch/xtensa/include/asm/ftrace.h
>> +++ b/arch/xtensa/include/asm/ftrace.h
>> @@ -12,24 +12,18 @@
>>
>>   #include <asm/processor.h>
>>
>> -#define HAVE_ARCH_CALLER_ADDR
>>   #ifndef __ASSEMBLY__
>> -#define CALLER_ADDR0 ({ unsigned long a0, a1; \
>> +#define ftrace_return_address0 ({ unsigned long a0, a1; \
>>   		__asm__ __volatile__ ( \
>>   			"mov %0, a0\n" \
>>   			"mov %1, a1\n" \
>>   			: "=r"(a0), "=r"(a1)); \
>>   		MAKE_PC_FROM_RA(a0, a1); })
>> +
>>   #ifdef CONFIG_FRAME_POINTER
>>   extern unsigned long return_address(unsigned level);
>> -#define CALLER_ADDR1 return_address(1)
>> -#define CALLER_ADDR2 return_address(2)
>> -#define CALLER_ADDR3 return_address(3)
>> -#else /* CONFIG_FRAME_POINTER */
>> -#define CALLER_ADDR1 (0)
>> -#define CALLER_ADDR2 (0)
>> -#define CALLER_ADDR3 (0)
>> -#endif /* CONFIG_FRAME_POINTER */
>> +#define ftrace_return_address(n) return_address(n)
>
> I would add a comment here that states:
>
> /*
>   * #else !CONFIG_FRAME_POINTER
>   *
>   * Define CALLER_ADDRn (n > 0) to 0 is the default in linux/ftrace.h if
>   * ftrace_return_address(n) and CONFIG_FRAME_POINTER are not defined.
>   */
>
> Otherwise it looks like you are missing the #else statement.
>
>> +#endif
>>   #endif /* __ASSEMBLY__ */
>>
>>   #ifdef CONFIG_FUNCTION_TRACER
>> diff --git a/include/linux/ftrace.h b/include/linux/ftrace.h
>> index 9212b01..18f1ae7 100644
>> --- a/include/linux/ftrace.h
>> +++ b/include/linux/ftrace.h
>> @@ -614,25 +614,27 @@ static inline void __ftrace_enabled_restore(int enabled)
>>   #endif
>>   }
>>
>> -#ifndef HAVE_ARCH_CALLER_ADDR
>> +/* All archs should have this, but we define it for consistency */
>
> The comment is a little confusing. I think it may be better stated as:
>
> /*
>   * All archs should be able to use __builtin_return_address(0) but
>   * we allow them to redefine it for consistency.
>   */
>
>> +#ifndef ftrace_return_address0
>> +# define ftrace_return_address0 __builtin_return_address(0)
>> +#endif
>> +
>> +/* Archs may use other ways for ADDR1 and beyond */
>
> How about:
>
> /* Not all archs can use __builtin_return_address(n) where n > 0 */
>
>> +#ifndef ftrace_return_address
>>   # ifdef CONFIG_FRAME_POINTER
>> -#  define CALLER_ADDR0 ((unsigned long)__builtin_return_address(0))
>> -#  define CALLER_ADDR1 ((unsigned long)__builtin_return_address(1))
>> -#  define CALLER_ADDR2 ((unsigned long)__builtin_return_address(2))
>> -#  define CALLER_ADDR3 ((unsigned long)__builtin_return_address(3))
>> -#  define CALLER_ADDR4 ((unsigned long)__builtin_return_address(4))
>> -#  define CALLER_ADDR5 ((unsigned long)__builtin_return_address(5))
>> -#  define CALLER_ADDR6 ((unsigned long)__builtin_return_address(6))
>> +#  define ftrace_return_address(n) __builtin_return_address(n)
>>   # else
>> -#  define CALLER_ADDR0 ((unsigned long)__builtin_return_address(0))
>> -#  define CALLER_ADDR1 0UL
>> -#  define CALLER_ADDR2 0UL
>> -#  define CALLER_ADDR3 0UL
>> -#  define CALLER_ADDR4 0UL
>> -#  define CALLER_ADDR5 0UL
>> -#  define CALLER_ADDR6 0UL
>> +#  define ftrace_return_address(n) 0UL
>>   # endif
>> -#endif /* ifndef HAVE_ARCH_CALLER_ADDR */
>> +#endif
>> +
>> +#define CALLER_ADDR0 ((unsigned long)ftrace_return_address0)
>> +#define CALLER_ADDR1 ((unsigned long)ftrace_return_address(1))
>> +#define CALLER_ADDR2 ((unsigned long)ftrace_return_address(2))
>> +#define CALLER_ADDR3 ((unsigned long)ftrace_return_address(3))
>> +#define CALLER_ADDR4 ((unsigned long)ftrace_return_address(4))
>> +#define CALLER_ADDR5 ((unsigned long)ftrace_return_address(5))
>> +#define CALLER_ADDR6 ((unsigned long)ftrace_return_address(6))
>
> Other than that, it looks good. You can send me the patch and I'll add
> it to my 3.16 queue.
>
> Feel free to reply to this email with a v9. When I pull patches into
> git, it adds the link to the thread for the patch in LKML. To keep this
> entire thread, just reply to it.
>
> Thanks!
>
> -- Steve
>
>>
>>   #ifdef CONFIG_IRQSOFF_TRACER
>>     extern void time_hardirqs_on(unsigned long a0, unsigned long a1);
>

^ permalink raw reply	[flat|nested] 235+ messages in thread

* [PATCH v8_1] ftrace: make CALLER_ADDRx macros more generic
  2014-04-30  9:54               ` AKASHI Takahiro
@ 2014-05-20 11:31                 ` AKASHI Takahiro
  -1 siblings, 0 replies; 235+ messages in thread
From: AKASHI Takahiro @ 2014-05-20 11:31 UTC (permalink / raw)
  To: rostedt, fweisbec, mingo, catalin.marinas, will.deacon, tim.bird
  Cc: gkulkarni, dsaxena, arndb, linux-arm-kernel, linaro-kernel,
	linux-kernel, AKASHI Takahiro

Most archs with HAVE_ARCH_CALLER_ADDR have pretty much the same
definitions of CALLER_ADDRx(n). Instead of duplicating the code for all
the archs, define a ftrace_return_address0() and
ftrace_return_address(n) that can be overwritten by the archs if they
need to do something different. Instead of 7 macros in every arch, we
now only have at most 2 (and actually only 1 as
ftrace_return_address0() should be the same for all archs).

The CALLER_ADDRx(n) will now be defined in linux/ftrace.h and use the
ftrace_return_address*(n?) macros. This removes a lot of the duplicate
code.

Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
---
 arch/arm/include/asm/ftrace.h      |   10 +---------
 arch/blackfin/include/asm/ftrace.h |   11 +----------
 arch/parisc/include/asm/ftrace.h   |   10 +---------
 arch/sh/include/asm/ftrace.h       |   10 +---------
 arch/xtensa/include/asm/ftrace.h   |   14 ++++----------
 include/linux/ftrace.h             |   34 ++++++++++++++++++----------------
 6 files changed, 26 insertions(+), 63 deletions(-)

diff --git a/arch/arm/include/asm/ftrace.h b/arch/arm/include/asm/ftrace.h
index f89515a..eb577f4 100644
--- a/arch/arm/include/asm/ftrace.h
+++ b/arch/arm/include/asm/ftrace.h
@@ -52,15 +52,7 @@ extern inline void *return_address(unsigned int level)
 
 #endif
 
-#define HAVE_ARCH_CALLER_ADDR
-
-#define CALLER_ADDR0 ((unsigned long)__builtin_return_address(0))
-#define CALLER_ADDR1 ((unsigned long)return_address(1))
-#define CALLER_ADDR2 ((unsigned long)return_address(2))
-#define CALLER_ADDR3 ((unsigned long)return_address(3))
-#define CALLER_ADDR4 ((unsigned long)return_address(4))
-#define CALLER_ADDR5 ((unsigned long)return_address(5))
-#define CALLER_ADDR6 ((unsigned long)return_address(6))
+#define ftrace_return_addr(n) return_address(n)
 
 #endif /* ifndef __ASSEMBLY__ */
 
diff --git a/arch/blackfin/include/asm/ftrace.h b/arch/blackfin/include/asm/ftrace.h
index 8a02950..2f1c3c2 100644
--- a/arch/blackfin/include/asm/ftrace.h
+++ b/arch/blackfin/include/asm/ftrace.h
@@ -66,16 +66,7 @@ extern inline void *return_address(unsigned int level)
 
 #endif /* CONFIG_FRAME_POINTER */
 
-#define HAVE_ARCH_CALLER_ADDR
-
-/* inline function or macro may lead to unexpected result */
-#define CALLER_ADDR0 ((unsigned long)__builtin_return_address(0))
-#define CALLER_ADDR1 ((unsigned long)return_address(1))
-#define CALLER_ADDR2 ((unsigned long)return_address(2))
-#define CALLER_ADDR3 ((unsigned long)return_address(3))
-#define CALLER_ADDR4 ((unsigned long)return_address(4))
-#define CALLER_ADDR5 ((unsigned long)return_address(5))
-#define CALLER_ADDR6 ((unsigned long)return_address(6))
+#define ftrace_return_address(n) return_address(n)
 
 #endif /* __ASSEMBLY__ */
 
diff --git a/arch/parisc/include/asm/ftrace.h b/arch/parisc/include/asm/ftrace.h
index 72c0faf..544ed8e 100644
--- a/arch/parisc/include/asm/ftrace.h
+++ b/arch/parisc/include/asm/ftrace.h
@@ -24,15 +24,7 @@ extern void return_to_handler(void);
 
 extern unsigned long return_address(unsigned int);
 
-#define HAVE_ARCH_CALLER_ADDR
-
-#define CALLER_ADDR0 ((unsigned long)__builtin_return_address(0))
-#define CALLER_ADDR1 return_address(1)
-#define CALLER_ADDR2 return_address(2)
-#define CALLER_ADDR3 return_address(3)
-#define CALLER_ADDR4 return_address(4)
-#define CALLER_ADDR5 return_address(5)
-#define CALLER_ADDR6 return_address(6)
+#define ftrace_return_address(n) return_address(n)
 
 #endif /* __ASSEMBLY__ */
 
diff --git a/arch/sh/include/asm/ftrace.h b/arch/sh/include/asm/ftrace.h
index 13e9966..e79fb6e 100644
--- a/arch/sh/include/asm/ftrace.h
+++ b/arch/sh/include/asm/ftrace.h
@@ -40,15 +40,7 @@ static inline unsigned long ftrace_call_adjust(unsigned long addr)
 /* arch/sh/kernel/return_address.c */
 extern void *return_address(unsigned int);
 
-#define HAVE_ARCH_CALLER_ADDR
-
-#define CALLER_ADDR0 ((unsigned long)__builtin_return_address(0))
-#define CALLER_ADDR1 ((unsigned long)return_address(1))
-#define CALLER_ADDR2 ((unsigned long)return_address(2))
-#define CALLER_ADDR3 ((unsigned long)return_address(3))
-#define CALLER_ADDR4 ((unsigned long)return_address(4))
-#define CALLER_ADDR5 ((unsigned long)return_address(5))
-#define CALLER_ADDR6 ((unsigned long)return_address(6))
+#define ftrace_return_address(n) return_address(n)
 
 #endif /* __ASSEMBLY__ */
 
diff --git a/arch/xtensa/include/asm/ftrace.h b/arch/xtensa/include/asm/ftrace.h
index 736b9d2..6c6d9a9 100644
--- a/arch/xtensa/include/asm/ftrace.h
+++ b/arch/xtensa/include/asm/ftrace.h
@@ -12,24 +12,18 @@
 
 #include <asm/processor.h>
 
-#define HAVE_ARCH_CALLER_ADDR
 #ifndef __ASSEMBLY__
-#define CALLER_ADDR0 ({ unsigned long a0, a1; \
+#define ftrace_return_address0 ({ unsigned long a0, a1; \
 		__asm__ __volatile__ ( \
 			"mov %0, a0\n" \
 			"mov %1, a1\n" \
 			: "=r"(a0), "=r"(a1)); \
 		MAKE_PC_FROM_RA(a0, a1); })
+
 #ifdef CONFIG_FRAME_POINTER
 extern unsigned long return_address(unsigned level);
-#define CALLER_ADDR1 return_address(1)
-#define CALLER_ADDR2 return_address(2)
-#define CALLER_ADDR3 return_address(3)
-#else /* CONFIG_FRAME_POINTER */
-#define CALLER_ADDR1 (0)
-#define CALLER_ADDR2 (0)
-#define CALLER_ADDR3 (0)
-#endif /* CONFIG_FRAME_POINTER */
+#define ftrace_return_address(n) return_address(n)
+#endif
 #endif /* __ASSEMBLY__ */
 
 #ifdef CONFIG_FUNCTION_TRACER
diff --git a/include/linux/ftrace.h b/include/linux/ftrace.h
index 9212b01..18f1ae7 100644
--- a/include/linux/ftrace.h
+++ b/include/linux/ftrace.h
@@ -614,25 +614,27 @@ static inline void __ftrace_enabled_restore(int enabled)
 #endif
 }
 
-#ifndef HAVE_ARCH_CALLER_ADDR
+/* All archs should have this, but we define it for consistency */
+#ifndef ftrace_return_address0
+# define ftrace_return_address0 __builtin_return_address(0)
+#endif
+
+/* Archs may use other ways for ADDR1 and beyond */
+#ifndef ftrace_return_address
 # ifdef CONFIG_FRAME_POINTER
-#  define CALLER_ADDR0 ((unsigned long)__builtin_return_address(0))
-#  define CALLER_ADDR1 ((unsigned long)__builtin_return_address(1))
-#  define CALLER_ADDR2 ((unsigned long)__builtin_return_address(2))
-#  define CALLER_ADDR3 ((unsigned long)__builtin_return_address(3))
-#  define CALLER_ADDR4 ((unsigned long)__builtin_return_address(4))
-#  define CALLER_ADDR5 ((unsigned long)__builtin_return_address(5))
-#  define CALLER_ADDR6 ((unsigned long)__builtin_return_address(6))
+#  define ftrace_return_address(n) __builtin_return_address(n)
 # else
-#  define CALLER_ADDR0 ((unsigned long)__builtin_return_address(0))
-#  define CALLER_ADDR1 0UL
-#  define CALLER_ADDR2 0UL
-#  define CALLER_ADDR3 0UL
-#  define CALLER_ADDR4 0UL
-#  define CALLER_ADDR5 0UL
-#  define CALLER_ADDR6 0UL
+#  define ftrace_return_address(n) 0UL
 # endif
-#endif /* ifndef HAVE_ARCH_CALLER_ADDR */
+#endif
+
+#define CALLER_ADDR0 ((unsigned long)ftrace_return_address0)
+#define CALLER_ADDR1 ((unsigned long)ftrace_return_address(1))
+#define CALLER_ADDR2 ((unsigned long)ftrace_return_address(2))
+#define CALLER_ADDR3 ((unsigned long)ftrace_return_address(3))
+#define CALLER_ADDR4 ((unsigned long)ftrace_return_address(4))
+#define CALLER_ADDR5 ((unsigned long)ftrace_return_address(5))
+#define CALLER_ADDR6 ((unsigned long)ftrace_return_address(6))
 
 #ifdef CONFIG_IRQSOFF_TRACER
   extern void time_hardirqs_on(unsigned long a0, unsigned long a1);
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 235+ messages in thread

* [PATCH v8_1] ftrace: make CALLER_ADDRx macros more generic
@ 2014-05-20 11:31                 ` AKASHI Takahiro
  0 siblings, 0 replies; 235+ messages in thread
From: AKASHI Takahiro @ 2014-05-20 11:31 UTC (permalink / raw)
  To: linux-arm-kernel

Most archs with HAVE_ARCH_CALLER_ADDR have pretty much the same
definitions of CALLER_ADDRx(n). Instead of duplicating the code for all
the archs, define a ftrace_return_address0() and
ftrace_return_address(n) that can be overwritten by the archs if they
need to do something different. Instead of 7 macros in every arch, we
now only have at most 2 (and actually only 1 as
ftrace_return_address0() should be the same for all archs).

The CALLER_ADDRx(n) will now be defined in linux/ftrace.h and use the
ftrace_return_address*(n?) macros. This removes a lot of the duplicate
code.

Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
---
 arch/arm/include/asm/ftrace.h      |   10 +---------
 arch/blackfin/include/asm/ftrace.h |   11 +----------
 arch/parisc/include/asm/ftrace.h   |   10 +---------
 arch/sh/include/asm/ftrace.h       |   10 +---------
 arch/xtensa/include/asm/ftrace.h   |   14 ++++----------
 include/linux/ftrace.h             |   34 ++++++++++++++++++----------------
 6 files changed, 26 insertions(+), 63 deletions(-)

diff --git a/arch/arm/include/asm/ftrace.h b/arch/arm/include/asm/ftrace.h
index f89515a..eb577f4 100644
--- a/arch/arm/include/asm/ftrace.h
+++ b/arch/arm/include/asm/ftrace.h
@@ -52,15 +52,7 @@ extern inline void *return_address(unsigned int level)
 
 #endif
 
-#define HAVE_ARCH_CALLER_ADDR
-
-#define CALLER_ADDR0 ((unsigned long)__builtin_return_address(0))
-#define CALLER_ADDR1 ((unsigned long)return_address(1))
-#define CALLER_ADDR2 ((unsigned long)return_address(2))
-#define CALLER_ADDR3 ((unsigned long)return_address(3))
-#define CALLER_ADDR4 ((unsigned long)return_address(4))
-#define CALLER_ADDR5 ((unsigned long)return_address(5))
-#define CALLER_ADDR6 ((unsigned long)return_address(6))
+#define ftrace_return_addr(n) return_address(n)
 
 #endif /* ifndef __ASSEMBLY__ */
 
diff --git a/arch/blackfin/include/asm/ftrace.h b/arch/blackfin/include/asm/ftrace.h
index 8a02950..2f1c3c2 100644
--- a/arch/blackfin/include/asm/ftrace.h
+++ b/arch/blackfin/include/asm/ftrace.h
@@ -66,16 +66,7 @@ extern inline void *return_address(unsigned int level)
 
 #endif /* CONFIG_FRAME_POINTER */
 
-#define HAVE_ARCH_CALLER_ADDR
-
-/* inline function or macro may lead to unexpected result */
-#define CALLER_ADDR0 ((unsigned long)__builtin_return_address(0))
-#define CALLER_ADDR1 ((unsigned long)return_address(1))
-#define CALLER_ADDR2 ((unsigned long)return_address(2))
-#define CALLER_ADDR3 ((unsigned long)return_address(3))
-#define CALLER_ADDR4 ((unsigned long)return_address(4))
-#define CALLER_ADDR5 ((unsigned long)return_address(5))
-#define CALLER_ADDR6 ((unsigned long)return_address(6))
+#define ftrace_return_address(n) return_address(n)
 
 #endif /* __ASSEMBLY__ */
 
diff --git a/arch/parisc/include/asm/ftrace.h b/arch/parisc/include/asm/ftrace.h
index 72c0faf..544ed8e 100644
--- a/arch/parisc/include/asm/ftrace.h
+++ b/arch/parisc/include/asm/ftrace.h
@@ -24,15 +24,7 @@ extern void return_to_handler(void);
 
 extern unsigned long return_address(unsigned int);
 
-#define HAVE_ARCH_CALLER_ADDR
-
-#define CALLER_ADDR0 ((unsigned long)__builtin_return_address(0))
-#define CALLER_ADDR1 return_address(1)
-#define CALLER_ADDR2 return_address(2)
-#define CALLER_ADDR3 return_address(3)
-#define CALLER_ADDR4 return_address(4)
-#define CALLER_ADDR5 return_address(5)
-#define CALLER_ADDR6 return_address(6)
+#define ftrace_return_address(n) return_address(n)
 
 #endif /* __ASSEMBLY__ */
 
diff --git a/arch/sh/include/asm/ftrace.h b/arch/sh/include/asm/ftrace.h
index 13e9966..e79fb6e 100644
--- a/arch/sh/include/asm/ftrace.h
+++ b/arch/sh/include/asm/ftrace.h
@@ -40,15 +40,7 @@ static inline unsigned long ftrace_call_adjust(unsigned long addr)
 /* arch/sh/kernel/return_address.c */
 extern void *return_address(unsigned int);
 
-#define HAVE_ARCH_CALLER_ADDR
-
-#define CALLER_ADDR0 ((unsigned long)__builtin_return_address(0))
-#define CALLER_ADDR1 ((unsigned long)return_address(1))
-#define CALLER_ADDR2 ((unsigned long)return_address(2))
-#define CALLER_ADDR3 ((unsigned long)return_address(3))
-#define CALLER_ADDR4 ((unsigned long)return_address(4))
-#define CALLER_ADDR5 ((unsigned long)return_address(5))
-#define CALLER_ADDR6 ((unsigned long)return_address(6))
+#define ftrace_return_address(n) return_address(n)
 
 #endif /* __ASSEMBLY__ */
 
diff --git a/arch/xtensa/include/asm/ftrace.h b/arch/xtensa/include/asm/ftrace.h
index 736b9d2..6c6d9a9 100644
--- a/arch/xtensa/include/asm/ftrace.h
+++ b/arch/xtensa/include/asm/ftrace.h
@@ -12,24 +12,18 @@
 
 #include <asm/processor.h>
 
-#define HAVE_ARCH_CALLER_ADDR
 #ifndef __ASSEMBLY__
-#define CALLER_ADDR0 ({ unsigned long a0, a1; \
+#define ftrace_return_address0 ({ unsigned long a0, a1; \
 		__asm__ __volatile__ ( \
 			"mov %0, a0\n" \
 			"mov %1, a1\n" \
 			: "=r"(a0), "=r"(a1)); \
 		MAKE_PC_FROM_RA(a0, a1); })
+
 #ifdef CONFIG_FRAME_POINTER
 extern unsigned long return_address(unsigned level);
-#define CALLER_ADDR1 return_address(1)
-#define CALLER_ADDR2 return_address(2)
-#define CALLER_ADDR3 return_address(3)
-#else /* CONFIG_FRAME_POINTER */
-#define CALLER_ADDR1 (0)
-#define CALLER_ADDR2 (0)
-#define CALLER_ADDR3 (0)
-#endif /* CONFIG_FRAME_POINTER */
+#define ftrace_return_address(n) return_address(n)
+#endif
 #endif /* __ASSEMBLY__ */
 
 #ifdef CONFIG_FUNCTION_TRACER
diff --git a/include/linux/ftrace.h b/include/linux/ftrace.h
index 9212b01..18f1ae7 100644
--- a/include/linux/ftrace.h
+++ b/include/linux/ftrace.h
@@ -614,25 +614,27 @@ static inline void __ftrace_enabled_restore(int enabled)
 #endif
 }
 
-#ifndef HAVE_ARCH_CALLER_ADDR
+/* All archs should have this, but we define it for consistency */
+#ifndef ftrace_return_address0
+# define ftrace_return_address0 __builtin_return_address(0)
+#endif
+
+/* Archs may use other ways for ADDR1 and beyond */
+#ifndef ftrace_return_address
 # ifdef CONFIG_FRAME_POINTER
-#  define CALLER_ADDR0 ((unsigned long)__builtin_return_address(0))
-#  define CALLER_ADDR1 ((unsigned long)__builtin_return_address(1))
-#  define CALLER_ADDR2 ((unsigned long)__builtin_return_address(2))
-#  define CALLER_ADDR3 ((unsigned long)__builtin_return_address(3))
-#  define CALLER_ADDR4 ((unsigned long)__builtin_return_address(4))
-#  define CALLER_ADDR5 ((unsigned long)__builtin_return_address(5))
-#  define CALLER_ADDR6 ((unsigned long)__builtin_return_address(6))
+#  define ftrace_return_address(n) __builtin_return_address(n)
 # else
-#  define CALLER_ADDR0 ((unsigned long)__builtin_return_address(0))
-#  define CALLER_ADDR1 0UL
-#  define CALLER_ADDR2 0UL
-#  define CALLER_ADDR3 0UL
-#  define CALLER_ADDR4 0UL
-#  define CALLER_ADDR5 0UL
-#  define CALLER_ADDR6 0UL
+#  define ftrace_return_address(n) 0UL
 # endif
-#endif /* ifndef HAVE_ARCH_CALLER_ADDR */
+#endif
+
+#define CALLER_ADDR0 ((unsigned long)ftrace_return_address0)
+#define CALLER_ADDR1 ((unsigned long)ftrace_return_address(1))
+#define CALLER_ADDR2 ((unsigned long)ftrace_return_address(2))
+#define CALLER_ADDR3 ((unsigned long)ftrace_return_address(3))
+#define CALLER_ADDR4 ((unsigned long)ftrace_return_address(4))
+#define CALLER_ADDR5 ((unsigned long)ftrace_return_address(5))
+#define CALLER_ADDR6 ((unsigned long)ftrace_return_address(6))
 
 #ifdef CONFIG_IRQSOFF_TRACER
   extern void time_hardirqs_on(unsigned long a0, unsigned long a1);
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 235+ messages in thread

* [for-next][PATCH] ftrace: Make CALLER_ADDRx macros more generic
  2014-04-28 10:41               ` AKASHI Takahiro
@ 2014-05-27 13:10                 ` Steven Rostedt
  -1 siblings, 0 replies; 235+ messages in thread
From: Steven Rostedt @ 2014-05-27 13:10 UTC (permalink / raw)
  To: AKASHI Takahiro
  Cc: Will Deacon, fweisbec, mingo, Catalin Marinas, tim.bird,
	gkulkarni, dsaxena, arndb, linux-arm-kernel, linaro-kernel,
	linux-kernel

Will,

I made a separate branch called ftrace/arm64 as shown below. You can
pull that branch to base the rest of Akashi-san's patches on top of it.
The branch is based on top of v3.15-rc5.

-- Steve


  git://git.kernel.org/pub/scm/linux/kernel/git/rostedt/linux-trace.git
ftrace/arm64

Head SHA1: eed542d6962ba33a689b4007a389f466e407bd74


AKASHI Takahiro (1):
      ftrace: Make CALLER_ADDRx macros more generic

----
 arch/arm/include/asm/ftrace.h      | 10 +---------
 arch/blackfin/include/asm/ftrace.h | 11 +----------
 arch/parisc/include/asm/ftrace.h   | 10 +---------
 arch/sh/include/asm/ftrace.h       | 10 +---------
 arch/xtensa/include/asm/ftrace.h   | 14 ++++----------
 include/linux/ftrace.h             | 34 ++++++++++++++++++----------------
 6 files changed, 26 insertions(+), 63 deletions(-)
---------------------------
commit eed542d6962ba33a689b4007a389f466e407bd74
Author: AKASHI Takahiro <takahiro.akashi@linaro.org>
Date:   Tue May 20 20:31:04 2014 +0900

    ftrace: Make CALLER_ADDRx macros more generic
    
    Most archs with HAVE_ARCH_CALLER_ADDR have pretty much the same
    definitions of CALLER_ADDRx(n). Instead of duplicating the code for all
    the archs, define a ftrace_return_address0() and
    ftrace_return_address(n) that can be overwritten by the archs if they
    need to do something different. Instead of 7 macros in every arch, we
    now only have at most 2 (and actually only 1 as
    ftrace_return_address0() should be the same for all archs).
    
    The CALLER_ADDRx(n) will now be defined in linux/ftrace.h and use the
    ftrace_return_address*(n?) macros. This removes a lot of the duplicate
    code.
    
    Link: http://lkml.kernel.org/p/1400585464-30333-1-git-send-email-takahiro.akashi@linaro.org
    
    Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
    Signed-off-by: Steven Rostedt <rostedt@goodmis.org>

diff --git a/arch/arm/include/asm/ftrace.h b/arch/arm/include/asm/ftrace.h
index f89515adac60..eb577f4f5f70 100644
--- a/arch/arm/include/asm/ftrace.h
+++ b/arch/arm/include/asm/ftrace.h
@@ -52,15 +52,7 @@ extern inline void *return_address(unsigned int level)
 
 #endif
 
-#define HAVE_ARCH_CALLER_ADDR
-
-#define CALLER_ADDR0 ((unsigned long)__builtin_return_address(0))
-#define CALLER_ADDR1 ((unsigned long)return_address(1))
-#define CALLER_ADDR2 ((unsigned long)return_address(2))
-#define CALLER_ADDR3 ((unsigned long)return_address(3))
-#define CALLER_ADDR4 ((unsigned long)return_address(4))
-#define CALLER_ADDR5 ((unsigned long)return_address(5))
-#define CALLER_ADDR6 ((unsigned long)return_address(6))
+#define ftrace_return_addr(n) return_address(n)
 
 #endif /* ifndef __ASSEMBLY__ */
 
diff --git a/arch/blackfin/include/asm/ftrace.h b/arch/blackfin/include/asm/ftrace.h
index 8a029505d7b7..2f1c3c2657ad 100644
--- a/arch/blackfin/include/asm/ftrace.h
+++ b/arch/blackfin/include/asm/ftrace.h
@@ -66,16 +66,7 @@ extern inline void *return_address(unsigned int level)
 
 #endif /* CONFIG_FRAME_POINTER */
 
-#define HAVE_ARCH_CALLER_ADDR
-
-/* inline function or macro may lead to unexpected result */
-#define CALLER_ADDR0 ((unsigned long)__builtin_return_address(0))
-#define CALLER_ADDR1 ((unsigned long)return_address(1))
-#define CALLER_ADDR2 ((unsigned long)return_address(2))
-#define CALLER_ADDR3 ((unsigned long)return_address(3))
-#define CALLER_ADDR4 ((unsigned long)return_address(4))
-#define CALLER_ADDR5 ((unsigned long)return_address(5))
-#define CALLER_ADDR6 ((unsigned long)return_address(6))
+#define ftrace_return_address(n) return_address(n)
 
 #endif /* __ASSEMBLY__ */
 
diff --git a/arch/parisc/include/asm/ftrace.h b/arch/parisc/include/asm/ftrace.h
index 72c0fafaa039..544ed8ef87eb 100644
--- a/arch/parisc/include/asm/ftrace.h
+++ b/arch/parisc/include/asm/ftrace.h
@@ -24,15 +24,7 @@ extern void return_to_handler(void);
 
 extern unsigned long return_address(unsigned int);
 
-#define HAVE_ARCH_CALLER_ADDR
-
-#define CALLER_ADDR0 ((unsigned long)__builtin_return_address(0))
-#define CALLER_ADDR1 return_address(1)
-#define CALLER_ADDR2 return_address(2)
-#define CALLER_ADDR3 return_address(3)
-#define CALLER_ADDR4 return_address(4)
-#define CALLER_ADDR5 return_address(5)
-#define CALLER_ADDR6 return_address(6)
+#define ftrace_return_address(n) return_address(n)
 
 #endif /* __ASSEMBLY__ */
 
diff --git a/arch/sh/include/asm/ftrace.h b/arch/sh/include/asm/ftrace.h
index 13e9966464c2..e79fb6ebaa42 100644
--- a/arch/sh/include/asm/ftrace.h
+++ b/arch/sh/include/asm/ftrace.h
@@ -40,15 +40,7 @@ static inline unsigned long ftrace_call_adjust(unsigned long addr)
 /* arch/sh/kernel/return_address.c */
 extern void *return_address(unsigned int);
 
-#define HAVE_ARCH_CALLER_ADDR
-
-#define CALLER_ADDR0 ((unsigned long)__builtin_return_address(0))
-#define CALLER_ADDR1 ((unsigned long)return_address(1))
-#define CALLER_ADDR2 ((unsigned long)return_address(2))
-#define CALLER_ADDR3 ((unsigned long)return_address(3))
-#define CALLER_ADDR4 ((unsigned long)return_address(4))
-#define CALLER_ADDR5 ((unsigned long)return_address(5))
-#define CALLER_ADDR6 ((unsigned long)return_address(6))
+#define ftrace_return_address(n) return_address(n)
 
 #endif /* __ASSEMBLY__ */
 
diff --git a/arch/xtensa/include/asm/ftrace.h b/arch/xtensa/include/asm/ftrace.h
index 736b9d214d80..6c6d9a9f185f 100644
--- a/arch/xtensa/include/asm/ftrace.h
+++ b/arch/xtensa/include/asm/ftrace.h
@@ -12,24 +12,18 @@
 
 #include <asm/processor.h>
 
-#define HAVE_ARCH_CALLER_ADDR
 #ifndef __ASSEMBLY__
-#define CALLER_ADDR0 ({ unsigned long a0, a1; \
+#define ftrace_return_address0 ({ unsigned long a0, a1; \
 		__asm__ __volatile__ ( \
 			"mov %0, a0\n" \
 			"mov %1, a1\n" \
 			: "=r"(a0), "=r"(a1)); \
 		MAKE_PC_FROM_RA(a0, a1); })
+
 #ifdef CONFIG_FRAME_POINTER
 extern unsigned long return_address(unsigned level);
-#define CALLER_ADDR1 return_address(1)
-#define CALLER_ADDR2 return_address(2)
-#define CALLER_ADDR3 return_address(3)
-#else /* CONFIG_FRAME_POINTER */
-#define CALLER_ADDR1 (0)
-#define CALLER_ADDR2 (0)
-#define CALLER_ADDR3 (0)
-#endif /* CONFIG_FRAME_POINTER */
+#define ftrace_return_address(n) return_address(n)
+#endif
 #endif /* __ASSEMBLY__ */
 
 #ifdef CONFIG_FUNCTION_TRACER
diff --git a/include/linux/ftrace.h b/include/linux/ftrace.h
index ae9504b4b67d..2018751cad9e 100644
--- a/include/linux/ftrace.h
+++ b/include/linux/ftrace.h
@@ -616,25 +616,27 @@ static inline void __ftrace_enabled_restore(int enabled)
 #endif
 }
 
-#ifndef HAVE_ARCH_CALLER_ADDR
+/* All archs should have this, but we define it for consistency */
+#ifndef ftrace_return_address0
+# define ftrace_return_address0 __builtin_return_address(0)
+#endif
+
+/* Archs may use other ways for ADDR1 and beyond */
+#ifndef ftrace_return_address
 # ifdef CONFIG_FRAME_POINTER
-#  define CALLER_ADDR0 ((unsigned long)__builtin_return_address(0))
-#  define CALLER_ADDR1 ((unsigned long)__builtin_return_address(1))
-#  define CALLER_ADDR2 ((unsigned long)__builtin_return_address(2))
-#  define CALLER_ADDR3 ((unsigned long)__builtin_return_address(3))
-#  define CALLER_ADDR4 ((unsigned long)__builtin_return_address(4))
-#  define CALLER_ADDR5 ((unsigned long)__builtin_return_address(5))
-#  define CALLER_ADDR6 ((unsigned long)__builtin_return_address(6))
+#  define ftrace_return_address(n) __builtin_return_address(n)
 # else
-#  define CALLER_ADDR0 ((unsigned long)__builtin_return_address(0))
-#  define CALLER_ADDR1 0UL
-#  define CALLER_ADDR2 0UL
-#  define CALLER_ADDR3 0UL
-#  define CALLER_ADDR4 0UL
-#  define CALLER_ADDR5 0UL
-#  define CALLER_ADDR6 0UL
+#  define ftrace_return_address(n) 0UL
 # endif
-#endif /* ifndef HAVE_ARCH_CALLER_ADDR */
+#endif
+
+#define CALLER_ADDR0 ((unsigned long)ftrace_return_address0)
+#define CALLER_ADDR1 ((unsigned long)ftrace_return_address(1))
+#define CALLER_ADDR2 ((unsigned long)ftrace_return_address(2))
+#define CALLER_ADDR3 ((unsigned long)ftrace_return_address(3))
+#define CALLER_ADDR4 ((unsigned long)ftrace_return_address(4))
+#define CALLER_ADDR5 ((unsigned long)ftrace_return_address(5))
+#define CALLER_ADDR6 ((unsigned long)ftrace_return_address(6))
 
 #ifdef CONFIG_IRQSOFF_TRACER
   extern void time_hardirqs_on(unsigned long a0, unsigned long a1);


^ permalink raw reply related	[flat|nested] 235+ messages in thread

* [for-next][PATCH] ftrace: Make CALLER_ADDRx macros more generic
@ 2014-05-27 13:10                 ` Steven Rostedt
  0 siblings, 0 replies; 235+ messages in thread
From: Steven Rostedt @ 2014-05-27 13:10 UTC (permalink / raw)
  To: linux-arm-kernel

Will,

I made a separate branch called ftrace/arm64 as shown below. You can
pull that branch to base the rest of Akashi-san's patches on top of it.
The branch is based on top of v3.15-rc5.

-- Steve


  git://git.kernel.org/pub/scm/linux/kernel/git/rostedt/linux-trace.git
ftrace/arm64

Head SHA1: eed542d6962ba33a689b4007a389f466e407bd74


AKASHI Takahiro (1):
      ftrace: Make CALLER_ADDRx macros more generic

----
 arch/arm/include/asm/ftrace.h      | 10 +---------
 arch/blackfin/include/asm/ftrace.h | 11 +----------
 arch/parisc/include/asm/ftrace.h   | 10 +---------
 arch/sh/include/asm/ftrace.h       | 10 +---------
 arch/xtensa/include/asm/ftrace.h   | 14 ++++----------
 include/linux/ftrace.h             | 34 ++++++++++++++++++----------------
 6 files changed, 26 insertions(+), 63 deletions(-)
---------------------------
commit eed542d6962ba33a689b4007a389f466e407bd74
Author: AKASHI Takahiro <takahiro.akashi@linaro.org>
Date:   Tue May 20 20:31:04 2014 +0900

    ftrace: Make CALLER_ADDRx macros more generic
    
    Most archs with HAVE_ARCH_CALLER_ADDR have pretty much the same
    definitions of CALLER_ADDRx(n). Instead of duplicating the code for all
    the archs, define a ftrace_return_address0() and
    ftrace_return_address(n) that can be overwritten by the archs if they
    need to do something different. Instead of 7 macros in every arch, we
    now only have at most 2 (and actually only 1 as
    ftrace_return_address0() should be the same for all archs).
    
    The CALLER_ADDRx(n) will now be defined in linux/ftrace.h and use the
    ftrace_return_address*(n?) macros. This removes a lot of the duplicate
    code.
    
    Link: http://lkml.kernel.org/p/1400585464-30333-1-git-send-email-takahiro.akashi at linaro.org
    
    Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
    Signed-off-by: Steven Rostedt <rostedt@goodmis.org>

diff --git a/arch/arm/include/asm/ftrace.h b/arch/arm/include/asm/ftrace.h
index f89515adac60..eb577f4f5f70 100644
--- a/arch/arm/include/asm/ftrace.h
+++ b/arch/arm/include/asm/ftrace.h
@@ -52,15 +52,7 @@ extern inline void *return_address(unsigned int level)
 
 #endif
 
-#define HAVE_ARCH_CALLER_ADDR
-
-#define CALLER_ADDR0 ((unsigned long)__builtin_return_address(0))
-#define CALLER_ADDR1 ((unsigned long)return_address(1))
-#define CALLER_ADDR2 ((unsigned long)return_address(2))
-#define CALLER_ADDR3 ((unsigned long)return_address(3))
-#define CALLER_ADDR4 ((unsigned long)return_address(4))
-#define CALLER_ADDR5 ((unsigned long)return_address(5))
-#define CALLER_ADDR6 ((unsigned long)return_address(6))
+#define ftrace_return_addr(n) return_address(n)
 
 #endif /* ifndef __ASSEMBLY__ */
 
diff --git a/arch/blackfin/include/asm/ftrace.h b/arch/blackfin/include/asm/ftrace.h
index 8a029505d7b7..2f1c3c2657ad 100644
--- a/arch/blackfin/include/asm/ftrace.h
+++ b/arch/blackfin/include/asm/ftrace.h
@@ -66,16 +66,7 @@ extern inline void *return_address(unsigned int level)
 
 #endif /* CONFIG_FRAME_POINTER */
 
-#define HAVE_ARCH_CALLER_ADDR
-
-/* inline function or macro may lead to unexpected result */
-#define CALLER_ADDR0 ((unsigned long)__builtin_return_address(0))
-#define CALLER_ADDR1 ((unsigned long)return_address(1))
-#define CALLER_ADDR2 ((unsigned long)return_address(2))
-#define CALLER_ADDR3 ((unsigned long)return_address(3))
-#define CALLER_ADDR4 ((unsigned long)return_address(4))
-#define CALLER_ADDR5 ((unsigned long)return_address(5))
-#define CALLER_ADDR6 ((unsigned long)return_address(6))
+#define ftrace_return_address(n) return_address(n)
 
 #endif /* __ASSEMBLY__ */
 
diff --git a/arch/parisc/include/asm/ftrace.h b/arch/parisc/include/asm/ftrace.h
index 72c0fafaa039..544ed8ef87eb 100644
--- a/arch/parisc/include/asm/ftrace.h
+++ b/arch/parisc/include/asm/ftrace.h
@@ -24,15 +24,7 @@ extern void return_to_handler(void);
 
 extern unsigned long return_address(unsigned int);
 
-#define HAVE_ARCH_CALLER_ADDR
-
-#define CALLER_ADDR0 ((unsigned long)__builtin_return_address(0))
-#define CALLER_ADDR1 return_address(1)
-#define CALLER_ADDR2 return_address(2)
-#define CALLER_ADDR3 return_address(3)
-#define CALLER_ADDR4 return_address(4)
-#define CALLER_ADDR5 return_address(5)
-#define CALLER_ADDR6 return_address(6)
+#define ftrace_return_address(n) return_address(n)
 
 #endif /* __ASSEMBLY__ */
 
diff --git a/arch/sh/include/asm/ftrace.h b/arch/sh/include/asm/ftrace.h
index 13e9966464c2..e79fb6ebaa42 100644
--- a/arch/sh/include/asm/ftrace.h
+++ b/arch/sh/include/asm/ftrace.h
@@ -40,15 +40,7 @@ static inline unsigned long ftrace_call_adjust(unsigned long addr)
 /* arch/sh/kernel/return_address.c */
 extern void *return_address(unsigned int);
 
-#define HAVE_ARCH_CALLER_ADDR
-
-#define CALLER_ADDR0 ((unsigned long)__builtin_return_address(0))
-#define CALLER_ADDR1 ((unsigned long)return_address(1))
-#define CALLER_ADDR2 ((unsigned long)return_address(2))
-#define CALLER_ADDR3 ((unsigned long)return_address(3))
-#define CALLER_ADDR4 ((unsigned long)return_address(4))
-#define CALLER_ADDR5 ((unsigned long)return_address(5))
-#define CALLER_ADDR6 ((unsigned long)return_address(6))
+#define ftrace_return_address(n) return_address(n)
 
 #endif /* __ASSEMBLY__ */
 
diff --git a/arch/xtensa/include/asm/ftrace.h b/arch/xtensa/include/asm/ftrace.h
index 736b9d214d80..6c6d9a9f185f 100644
--- a/arch/xtensa/include/asm/ftrace.h
+++ b/arch/xtensa/include/asm/ftrace.h
@@ -12,24 +12,18 @@
 
 #include <asm/processor.h>
 
-#define HAVE_ARCH_CALLER_ADDR
 #ifndef __ASSEMBLY__
-#define CALLER_ADDR0 ({ unsigned long a0, a1; \
+#define ftrace_return_address0 ({ unsigned long a0, a1; \
 		__asm__ __volatile__ ( \
 			"mov %0, a0\n" \
 			"mov %1, a1\n" \
 			: "=r"(a0), "=r"(a1)); \
 		MAKE_PC_FROM_RA(a0, a1); })
+
 #ifdef CONFIG_FRAME_POINTER
 extern unsigned long return_address(unsigned level);
-#define CALLER_ADDR1 return_address(1)
-#define CALLER_ADDR2 return_address(2)
-#define CALLER_ADDR3 return_address(3)
-#else /* CONFIG_FRAME_POINTER */
-#define CALLER_ADDR1 (0)
-#define CALLER_ADDR2 (0)
-#define CALLER_ADDR3 (0)
-#endif /* CONFIG_FRAME_POINTER */
+#define ftrace_return_address(n) return_address(n)
+#endif
 #endif /* __ASSEMBLY__ */
 
 #ifdef CONFIG_FUNCTION_TRACER
diff --git a/include/linux/ftrace.h b/include/linux/ftrace.h
index ae9504b4b67d..2018751cad9e 100644
--- a/include/linux/ftrace.h
+++ b/include/linux/ftrace.h
@@ -616,25 +616,27 @@ static inline void __ftrace_enabled_restore(int enabled)
 #endif
 }
 
-#ifndef HAVE_ARCH_CALLER_ADDR
+/* All archs should have this, but we define it for consistency */
+#ifndef ftrace_return_address0
+# define ftrace_return_address0 __builtin_return_address(0)
+#endif
+
+/* Archs may use other ways for ADDR1 and beyond */
+#ifndef ftrace_return_address
 # ifdef CONFIG_FRAME_POINTER
-#  define CALLER_ADDR0 ((unsigned long)__builtin_return_address(0))
-#  define CALLER_ADDR1 ((unsigned long)__builtin_return_address(1))
-#  define CALLER_ADDR2 ((unsigned long)__builtin_return_address(2))
-#  define CALLER_ADDR3 ((unsigned long)__builtin_return_address(3))
-#  define CALLER_ADDR4 ((unsigned long)__builtin_return_address(4))
-#  define CALLER_ADDR5 ((unsigned long)__builtin_return_address(5))
-#  define CALLER_ADDR6 ((unsigned long)__builtin_return_address(6))
+#  define ftrace_return_address(n) __builtin_return_address(n)
 # else
-#  define CALLER_ADDR0 ((unsigned long)__builtin_return_address(0))
-#  define CALLER_ADDR1 0UL
-#  define CALLER_ADDR2 0UL
-#  define CALLER_ADDR3 0UL
-#  define CALLER_ADDR4 0UL
-#  define CALLER_ADDR5 0UL
-#  define CALLER_ADDR6 0UL
+#  define ftrace_return_address(n) 0UL
 # endif
-#endif /* ifndef HAVE_ARCH_CALLER_ADDR */
+#endif
+
+#define CALLER_ADDR0 ((unsigned long)ftrace_return_address0)
+#define CALLER_ADDR1 ((unsigned long)ftrace_return_address(1))
+#define CALLER_ADDR2 ((unsigned long)ftrace_return_address(2))
+#define CALLER_ADDR3 ((unsigned long)ftrace_return_address(3))
+#define CALLER_ADDR4 ((unsigned long)ftrace_return_address(4))
+#define CALLER_ADDR5 ((unsigned long)ftrace_return_address(5))
+#define CALLER_ADDR6 ((unsigned long)ftrace_return_address(6))
 
 #ifdef CONFIG_IRQSOFF_TRACER
   extern void time_hardirqs_on(unsigned long a0, unsigned long a1);

^ permalink raw reply related	[flat|nested] 235+ messages in thread

* Re: [for-next][PATCH] ftrace: Make CALLER_ADDRx macros more generic
  2014-05-27 13:10                 ` Steven Rostedt
@ 2014-05-27 18:49                   ` Will Deacon
  -1 siblings, 0 replies; 235+ messages in thread
From: Will Deacon @ 2014-05-27 18:49 UTC (permalink / raw)
  To: Steven Rostedt
  Cc: AKASHI Takahiro, fweisbec, mingo, Catalin Marinas, tim.bird,
	gkulkarni, dsaxena, arndb, linux-arm-kernel, linaro-kernel,
	linux-kernel

On Tue, May 27, 2014 at 02:10:19PM +0100, Steven Rostedt wrote:
> Will,
> 
> I made a separate branch called ftrace/arm64 as shown below. You can
> pull that branch to base the rest of Akashi-san's patches on top of it.
> The branch is based on top of v3.15-rc5.

Thanks Steve, I'll pull that in.

Akashi: please can you re-send your series, based on the branch below and
including the acks/reviewed-by tags you got for v6 of the patches?

Cheers,

Will

>   git://git.kernel.org/pub/scm/linux/kernel/git/rostedt/linux-trace.git
> ftrace/arm64
> 
> Head SHA1: eed542d6962ba33a689b4007a389f466e407bd74

^ permalink raw reply	[flat|nested] 235+ messages in thread

* [for-next][PATCH] ftrace: Make CALLER_ADDRx macros more generic
@ 2014-05-27 18:49                   ` Will Deacon
  0 siblings, 0 replies; 235+ messages in thread
From: Will Deacon @ 2014-05-27 18:49 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, May 27, 2014 at 02:10:19PM +0100, Steven Rostedt wrote:
> Will,
> 
> I made a separate branch called ftrace/arm64 as shown below. You can
> pull that branch to base the rest of Akashi-san's patches on top of it.
> The branch is based on top of v3.15-rc5.

Thanks Steve, I'll pull that in.

Akashi: please can you re-send your series, based on the branch below and
including the acks/reviewed-by tags you got for v6 of the patches?

Cheers,

Will

>   git://git.kernel.org/pub/scm/linux/kernel/git/rostedt/linux-trace.git
> ftrace/arm64
> 
> Head SHA1: eed542d6962ba33a689b4007a389f466e407bd74

^ permalink raw reply	[flat|nested] 235+ messages in thread

* Re: [PATCH v8 5/8] arm64: Add ftrace support
  2014-04-30  9:54               ` AKASHI Takahiro
@ 2014-05-28 20:19                 ` Mark Brown
  -1 siblings, 0 replies; 235+ messages in thread
From: Mark Brown @ 2014-05-28 20:19 UTC (permalink / raw)
  To: AKASHI Takahiro
  Cc: rostedt, fweisbec, mingo, catalin.marinas, will.deacon, tim.bird,
	linaro-kernel, arndb, linux-kernel, dsaxena, gkulkarni,
	linux-arm-kernel

[-- Attachment #1: Type: text/plain, Size: 680 bytes --]

On Wed, Apr 30, 2014 at 06:54:33PM +0900, AKASHI Takahiro wrote:

> +/*
> + * arch/arm64/kernel/entry-ftrace.S
> + *
> + * Copyright (C) 2013 Linaro Limited
> + * Author: AKASHI Takahiro <takahiro.akashi@linaro.org>
> + *
> + * 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 <linux/linkage.h>
> +#include <asm/ftrace.h>
> +#include <asm/insn.h>

asm/insn.h contains a bunch of C stuff which won't build without
__ASSEMBLY__ guards unless I'm missing something (I'm working with a
non-mainline tree so I might be).

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

^ permalink raw reply	[flat|nested] 235+ messages in thread

* [PATCH v8 5/8] arm64: Add ftrace support
@ 2014-05-28 20:19                 ` Mark Brown
  0 siblings, 0 replies; 235+ messages in thread
From: Mark Brown @ 2014-05-28 20:19 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, Apr 30, 2014 at 06:54:33PM +0900, AKASHI Takahiro wrote:

> +/*
> + * arch/arm64/kernel/entry-ftrace.S
> + *
> + * Copyright (C) 2013 Linaro Limited
> + * Author: AKASHI Takahiro <takahiro.akashi@linaro.org>
> + *
> + * 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 <linux/linkage.h>
> +#include <asm/ftrace.h>
> +#include <asm/insn.h>

asm/insn.h contains a bunch of C stuff which won't build without
__ASSEMBLY__ guards unless I'm missing something (I'm working with a
non-mainline tree so I might be).
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20140528/d1863090/attachment.sig>

^ permalink raw reply	[flat|nested] 235+ messages in thread

* Re: [for-next][PATCH] ftrace: Make CALLER_ADDRx macros more generic
  2014-05-27 18:49                   ` Will Deacon
@ 2014-05-29  5:27                     ` AKASHI Takahiro
  -1 siblings, 0 replies; 235+ messages in thread
From: AKASHI Takahiro @ 2014-05-29  5:27 UTC (permalink / raw)
  To: Will Deacon, Steven Rostedt
  Cc: fweisbec, mingo, Catalin Marinas, tim.bird, gkulkarni, dsaxena,
	arndb, linux-arm-kernel, linaro-kernel, linux-kernel

Hi Will

On 05/28/2014 03:49 AM, Will Deacon wrote:
> On Tue, May 27, 2014 at 02:10:19PM +0100, Steven Rostedt wrote:
>> Will,
>>
>> I made a separate branch called ftrace/arm64 as shown below. You can
>> pull that branch to base the rest of Akashi-san's patches on top of it.
>> The branch is based on top of v3.15-rc5.
>
> Thanks Steve, I'll pull that in.
>
> Akashi: please can you re-send your series, based on the branch below and
> including the acks/reviewed-by tags you got for v6 of the patches?

Sorry again to have missed your e-mail :-)
I'm sure that you can successfully apply all my patch series, without any
modification, from:
     v6 arm64: prerequisites for audit and ftrace
     v8 arm64: Add ftrace support
except for the patch, "[v8 1/8] ftrace: make CALLER_ADDRx macros more generic,"
which was replaced by a new version and already appears in Steven's repo.

Thank you,
-Takahiro AKASHI

> Cheers,
>
> Will
>
>>    git://git.kernel.org/pub/scm/linux/kernel/git/rostedt/linux-trace.git
>> ftrace/arm64
>>
>> Head SHA1: eed542d6962ba33a689b4007a389f466e407bd74

^ permalink raw reply	[flat|nested] 235+ messages in thread

* [for-next][PATCH] ftrace: Make CALLER_ADDRx macros more generic
@ 2014-05-29  5:27                     ` AKASHI Takahiro
  0 siblings, 0 replies; 235+ messages in thread
From: AKASHI Takahiro @ 2014-05-29  5:27 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Will

On 05/28/2014 03:49 AM, Will Deacon wrote:
> On Tue, May 27, 2014 at 02:10:19PM +0100, Steven Rostedt wrote:
>> Will,
>>
>> I made a separate branch called ftrace/arm64 as shown below. You can
>> pull that branch to base the rest of Akashi-san's patches on top of it.
>> The branch is based on top of v3.15-rc5.
>
> Thanks Steve, I'll pull that in.
>
> Akashi: please can you re-send your series, based on the branch below and
> including the acks/reviewed-by tags you got for v6 of the patches?

Sorry again to have missed your e-mail :-)
I'm sure that you can successfully apply all my patch series, without any
modification, from:
     v6 arm64: prerequisites for audit and ftrace
     v8 arm64: Add ftrace support
except for the patch, "[v8 1/8] ftrace: make CALLER_ADDRx macros more generic,"
which was replaced by a new version and already appears in Steven's repo.

Thank you,
-Takahiro AKASHI

> Cheers,
>
> Will
>
>>    git://git.kernel.org/pub/scm/linux/kernel/git/rostedt/linux-trace.git
>> ftrace/arm64
>>
>> Head SHA1: eed542d6962ba33a689b4007a389f466e407bd74

^ permalink raw reply	[flat|nested] 235+ messages in thread

* Re: [PATCH v8 5/8] arm64: Add ftrace support
  2014-05-28 20:19                 ` Mark Brown
@ 2014-05-29  8:07                   ` Will Deacon
  -1 siblings, 0 replies; 235+ messages in thread
From: Will Deacon @ 2014-05-29  8:07 UTC (permalink / raw)
  To: Mark Brown
  Cc: AKASHI Takahiro, rostedt, fweisbec, mingo, Catalin Marinas,
	tim.bird, linaro-kernel, arndb, linux-kernel, dsaxena, gkulkarni,
	linux-arm-kernel

On Wed, May 28, 2014 at 09:19:55PM +0100, Mark Brown wrote:
> On Wed, Apr 30, 2014 at 06:54:33PM +0900, AKASHI Takahiro wrote:
> 
> > +/*
> > + * arch/arm64/kernel/entry-ftrace.S
> > + *
> > + * Copyright (C) 2013 Linaro Limited
> > + * Author: AKASHI Takahiro <takahiro.akashi@linaro.org>
> > + *
> > + * 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 <linux/linkage.h>
> > +#include <asm/ftrace.h>
> > +#include <asm/insn.h>
> 
> asm/insn.h contains a bunch of C stuff which won't build without
> __ASSEMBLY__ guards unless I'm missing something (I'm working with a
> non-mainline tree so I might be).

The guards are added earlier in this series.

Will

^ permalink raw reply	[flat|nested] 235+ messages in thread

* [PATCH v8 5/8] arm64: Add ftrace support
@ 2014-05-29  8:07                   ` Will Deacon
  0 siblings, 0 replies; 235+ messages in thread
From: Will Deacon @ 2014-05-29  8:07 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, May 28, 2014 at 09:19:55PM +0100, Mark Brown wrote:
> On Wed, Apr 30, 2014 at 06:54:33PM +0900, AKASHI Takahiro wrote:
> 
> > +/*
> > + * arch/arm64/kernel/entry-ftrace.S
> > + *
> > + * Copyright (C) 2013 Linaro Limited
> > + * Author: AKASHI Takahiro <takahiro.akashi@linaro.org>
> > + *
> > + * 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 <linux/linkage.h>
> > +#include <asm/ftrace.h>
> > +#include <asm/insn.h>
> 
> asm/insn.h contains a bunch of C stuff which won't build without
> __ASSEMBLY__ guards unless I'm missing something (I'm working with a
> non-mainline tree so I might be).

The guards are added earlier in this series.

Will

^ permalink raw reply	[flat|nested] 235+ messages in thread

* Re: [for-next][PATCH] ftrace: Make CALLER_ADDRx macros more generic
  2014-05-29  5:27                     ` AKASHI Takahiro
@ 2014-05-29  8:10                       ` Will Deacon
  -1 siblings, 0 replies; 235+ messages in thread
From: Will Deacon @ 2014-05-29  8:10 UTC (permalink / raw)
  To: AKASHI Takahiro
  Cc: Steven Rostedt, fweisbec, mingo, Catalin Marinas, tim.bird,
	gkulkarni, dsaxena, arndb, linux-arm-kernel, linaro-kernel,
	linux-kernel

On Thu, May 29, 2014 at 06:27:31AM +0100, AKASHI Takahiro wrote:
> Hi Will

Hi Akashi,

> On 05/28/2014 03:49 AM, Will Deacon wrote:
> > On Tue, May 27, 2014 at 02:10:19PM +0100, Steven Rostedt wrote:
> >> Will,
> >>
> >> I made a separate branch called ftrace/arm64 as shown below. You can
> >> pull that branch to base the rest of Akashi-san's patches on top of it.
> >> The branch is based on top of v3.15-rc5.
> >
> > Thanks Steve, I'll pull that in.
> >
> > Akashi: please can you re-send your series, based on the branch below and
> > including the acks/reviewed-by tags you got for v6 of the patches?
> 
> Sorry again to have missed your e-mail :-)

You should fix your filters!

> I'm sure that you can successfully apply all my patch series, without any
> modification, from:
>      v6 arm64: prerequisites for audit and ftrace
>      v8 arm64: Add ftrace support
> except for the patch, "[v8 1/8] ftrace: make CALLER_ADDRx macros more generic,"
> which was replaced by a new version and already appears in Steven's repo.

Yeah, you're right, I've managed to pick patches 2-8 from that posting --
thanks.

Will

^ permalink raw reply	[flat|nested] 235+ messages in thread

* [for-next][PATCH] ftrace: Make CALLER_ADDRx macros more generic
@ 2014-05-29  8:10                       ` Will Deacon
  0 siblings, 0 replies; 235+ messages in thread
From: Will Deacon @ 2014-05-29  8:10 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, May 29, 2014 at 06:27:31AM +0100, AKASHI Takahiro wrote:
> Hi Will

Hi Akashi,

> On 05/28/2014 03:49 AM, Will Deacon wrote:
> > On Tue, May 27, 2014 at 02:10:19PM +0100, Steven Rostedt wrote:
> >> Will,
> >>
> >> I made a separate branch called ftrace/arm64 as shown below. You can
> >> pull that branch to base the rest of Akashi-san's patches on top of it.
> >> The branch is based on top of v3.15-rc5.
> >
> > Thanks Steve, I'll pull that in.
> >
> > Akashi: please can you re-send your series, based on the branch below and
> > including the acks/reviewed-by tags you got for v6 of the patches?
> 
> Sorry again to have missed your e-mail :-)

You should fix your filters!

> I'm sure that you can successfully apply all my patch series, without any
> modification, from:
>      v6 arm64: prerequisites for audit and ftrace
>      v8 arm64: Add ftrace support
> except for the patch, "[v8 1/8] ftrace: make CALLER_ADDRx macros more generic,"
> which was replaced by a new version and already appears in Steven's repo.

Yeah, you're right, I've managed to pick patches 2-8 from that posting --
thanks.

Will

^ permalink raw reply	[flat|nested] 235+ messages in thread

* Re: [PATCH v8 5/8] arm64: Add ftrace support
  2014-05-29  8:07                   ` Will Deacon
@ 2014-05-29  9:47                     ` Mark Brown
  -1 siblings, 0 replies; 235+ messages in thread
From: Mark Brown @ 2014-05-29  9:47 UTC (permalink / raw)
  To: Will Deacon
  Cc: AKASHI Takahiro, rostedt, fweisbec, mingo, Catalin Marinas,
	tim.bird, linaro-kernel, arndb, linux-kernel, dsaxena, gkulkarni,
	linux-arm-kernel

[-- Attachment #1: Type: text/plain, Size: 657 bytes --]

On Thu, May 29, 2014 at 09:07:05AM +0100, Will Deacon wrote:
> On Wed, May 28, 2014 at 09:19:55PM +0100, Mark Brown wrote:
> > On Wed, Apr 30, 2014 at 06:54:33PM +0900, AKASHI Takahiro wrote:

> > > +#include <linux/linkage.h>
> > > +#include <asm/ftrace.h>
> > > +#include <asm/insn.h>

> > asm/insn.h contains a bunch of C stuff which won't build without
> > __ASSEMBLY__ guards unless I'm missing something (I'm working with a
> > non-mainline tree so I might be).

> The guards are added earlier in this series.

Yeah, I discussed with Akashi-san later - the guard patch didn't
actually make it onto the list properly, neither of us has a copy
locally.

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

^ permalink raw reply	[flat|nested] 235+ messages in thread

* [PATCH v8 5/8] arm64: Add ftrace support
@ 2014-05-29  9:47                     ` Mark Brown
  0 siblings, 0 replies; 235+ messages in thread
From: Mark Brown @ 2014-05-29  9:47 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, May 29, 2014 at 09:07:05AM +0100, Will Deacon wrote:
> On Wed, May 28, 2014 at 09:19:55PM +0100, Mark Brown wrote:
> > On Wed, Apr 30, 2014 at 06:54:33PM +0900, AKASHI Takahiro wrote:

> > > +#include <linux/linkage.h>
> > > +#include <asm/ftrace.h>
> > > +#include <asm/insn.h>

> > asm/insn.h contains a bunch of C stuff which won't build without
> > __ASSEMBLY__ guards unless I'm missing something (I'm working with a
> > non-mainline tree so I might be).

> The guards are added earlier in this series.

Yeah, I discussed with Akashi-san later - the guard patch didn't
actually make it onto the list properly, neither of us has a copy
locally.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20140529/92d8ef66/attachment-0001.sig>

^ permalink raw reply	[flat|nested] 235+ messages in thread

* Re: [PATCH v8 1/8] ftrace: make CALLER_ADDRx macros more generic
  2014-04-30  9:54               ` AKASHI Takahiro
  (?)
@ 2014-06-11 12:34                 ` Geert Uytterhoeven
  -1 siblings, 0 replies; 235+ messages in thread
From: Geert Uytterhoeven @ 2014-06-11 12:34 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, Apr 30, 2014 at 11:54 AM, AKASHI Takahiro
<takahiro.akashi@linaro.org> wrote:
> Most archs with HAVE_ARCH_CALLER_ADDR have the almost same definitions
> of CALLER_ADDRx(n), and so put them into linux/ftrace.h.
>
> Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>

On arm (at least shmobile_defconfig and versatile_defconfig) with gcc 4.6.3:

kernel/sched/core.c: In function 'get_parent_ip':
kernel/sched/core.c:2520:10: warning: unsupported argument to
'__builtin_return_address' [enabled by default]
kernel/sched/core.c:2522:11: warning: unsupported argument to
'__builtin_return_address' [enabled by default]

With gcc 4.9.0:

kernel/sched/core.c: In function 'get_parent_ip':
include/linux/ftrace.h:627:36: warning: unsupported argument to
'__builtin_return_address'
 #  define ftrace_return_address(n) __builtin_return_address(n)
                                    ^
include/linux/ftrace.h:635:38: note: in expansion of macro
'ftrace_return_address'
 #define CALLER_ADDR2 ((unsigned long)ftrace_return_address(2))
                                      ^
kernel/sched/core.c:2520:10: note: in expansion of macro 'CALLER_ADDR2'
   addr = CALLER_ADDR2;
          ^
include/linux/ftrace.h:627:36: warning: unsupported argument to
'__builtin_return_address'
 #  define ftrace_return_address(n) __builtin_return_address(n)
                                    ^
include/linux/ftrace.h:636:38: note: in expansion of macro
'ftrace_return_address'
 #define CALLER_ADDR3 ((unsigned long)ftrace_return_address(3))
                                      ^
kernel/sched/core.c:2522:11: note: in expansion of macro 'CALLER_ADDR3'
    addr = CALLER_ADDR3;
           ^

Gr{oetje,eeting}s,

                        Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
                                -- Linus Torvalds

^ permalink raw reply	[flat|nested] 235+ messages in thread

* Re: [PATCH v8 1/8] ftrace: make CALLER_ADDRx macros more generic
@ 2014-06-11 12:34                 ` Geert Uytterhoeven
  0 siblings, 0 replies; 235+ messages in thread
From: Geert Uytterhoeven @ 2014-06-11 12:34 UTC (permalink / raw)
  To: AKASHI Takahiro
  Cc: Steven Rostedt, Frédéric Weisbecker, Ingo Molnar,
	Catalin Marinas, Will Deacon, tim.bird, gkulkarni, dsaxena,
	arndb, linux-arm-kernel, linaro-kernel, linux-kernel,
	Linux-sh list

On Wed, Apr 30, 2014 at 11:54 AM, AKASHI Takahiro
<takahiro.akashi@linaro.org> wrote:
> Most archs with HAVE_ARCH_CALLER_ADDR have the almost same definitions
> of CALLER_ADDRx(n), and so put them into linux/ftrace.h.
>
> Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>

On arm (at least shmobile_defconfig and versatile_defconfig) with gcc 4.6.3:

kernel/sched/core.c: In function 'get_parent_ip':
kernel/sched/core.c:2520:10: warning: unsupported argument to
'__builtin_return_address' [enabled by default]
kernel/sched/core.c:2522:11: warning: unsupported argument to
'__builtin_return_address' [enabled by default]

With gcc 4.9.0:

kernel/sched/core.c: In function 'get_parent_ip':
include/linux/ftrace.h:627:36: warning: unsupported argument to
'__builtin_return_address'
 #  define ftrace_return_address(n) __builtin_return_address(n)
                                    ^
include/linux/ftrace.h:635:38: note: in expansion of macro
'ftrace_return_address'
 #define CALLER_ADDR2 ((unsigned long)ftrace_return_address(2))
                                      ^
kernel/sched/core.c:2520:10: note: in expansion of macro 'CALLER_ADDR2'
   addr = CALLER_ADDR2;
          ^
include/linux/ftrace.h:627:36: warning: unsupported argument to
'__builtin_return_address'
 #  define ftrace_return_address(n) __builtin_return_address(n)
                                    ^
include/linux/ftrace.h:636:38: note: in expansion of macro
'ftrace_return_address'
 #define CALLER_ADDR3 ((unsigned long)ftrace_return_address(3))
                                      ^
kernel/sched/core.c:2522:11: note: in expansion of macro 'CALLER_ADDR3'
    addr = CALLER_ADDR3;
           ^

Gr{oetje,eeting}s,

                        Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
                                -- Linus Torvalds

^ permalink raw reply	[flat|nested] 235+ messages in thread

* [PATCH v8 1/8] ftrace: make CALLER_ADDRx macros more generic
@ 2014-06-11 12:34                 ` Geert Uytterhoeven
  0 siblings, 0 replies; 235+ messages in thread
From: Geert Uytterhoeven @ 2014-06-11 12:34 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, Apr 30, 2014 at 11:54 AM, AKASHI Takahiro
<takahiro.akashi@linaro.org> wrote:
> Most archs with HAVE_ARCH_CALLER_ADDR have the almost same definitions
> of CALLER_ADDRx(n), and so put them into linux/ftrace.h.
>
> Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>

On arm (at least shmobile_defconfig and versatile_defconfig) with gcc 4.6.3:

kernel/sched/core.c: In function 'get_parent_ip':
kernel/sched/core.c:2520:10: warning: unsupported argument to
'__builtin_return_address' [enabled by default]
kernel/sched/core.c:2522:11: warning: unsupported argument to
'__builtin_return_address' [enabled by default]

With gcc 4.9.0:

kernel/sched/core.c: In function 'get_parent_ip':
include/linux/ftrace.h:627:36: warning: unsupported argument to
'__builtin_return_address'
 #  define ftrace_return_address(n) __builtin_return_address(n)
                                    ^
include/linux/ftrace.h:635:38: note: in expansion of macro
'ftrace_return_address'
 #define CALLER_ADDR2 ((unsigned long)ftrace_return_address(2))
                                      ^
kernel/sched/core.c:2520:10: note: in expansion of macro 'CALLER_ADDR2'
   addr = CALLER_ADDR2;
          ^
include/linux/ftrace.h:627:36: warning: unsupported argument to
'__builtin_return_address'
 #  define ftrace_return_address(n) __builtin_return_address(n)
                                    ^
include/linux/ftrace.h:636:38: note: in expansion of macro
'ftrace_return_address'
 #define CALLER_ADDR3 ((unsigned long)ftrace_return_address(3))
                                      ^
kernel/sched/core.c:2522:11: note: in expansion of macro 'CALLER_ADDR3'
    addr = CALLER_ADDR3;
           ^

Gr{oetje,eeting}s,

                        Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert at linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
                                -- Linus Torvalds

^ permalink raw reply	[flat|nested] 235+ messages in thread

* [PATCH] arm/ftrace: Fix function_return_addr() to function_return_address()
  2014-06-11 12:34                 ` Geert Uytterhoeven
  (?)
@ 2014-06-11 13:23                   ` Steven Rostedt
  -1 siblings, 0 replies; 235+ messages in thread
From: Steven Rostedt @ 2014-06-11 13:23 UTC (permalink / raw)
  To: linux-arm-kernel

The clean up of CALLER_ADDR*() functions required the archs to either
use the default __builtin_return_address(X) (where X > 0) or override
it with something the arch can use. To override it, the arch would
define function_return_address(x).

The arm architecture requires this to be redefined but instead of
defining function_return_address(x) it defined function_return_addr(x).

Reported-by: Geert Uytterhoeven <geert@linux-m68k.org>
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
----
diff --git a/arch/arm/include/asm/ftrace.h b/arch/arm/include/asm/ftrace.h
index eb577f4..39eb16b 100644
--- a/arch/arm/include/asm/ftrace.h
+++ b/arch/arm/include/asm/ftrace.h
@@ -52,7 +52,7 @@ extern inline void *return_address(unsigned int level)
 
 #endif
 
-#define ftrace_return_addr(n) return_address(n)
+#define ftrace_return_address(n) return_address(n)
 
 #endif /* ifndef __ASSEMBLY__ */
 

^ permalink raw reply related	[flat|nested] 235+ messages in thread

* [PATCH] arm/ftrace: Fix function_return_addr() to function_return_address()
@ 2014-06-11 13:23                   ` Steven Rostedt
  0 siblings, 0 replies; 235+ messages in thread
From: Steven Rostedt @ 2014-06-11 13:23 UTC (permalink / raw)
  To: Will Deacon
  Cc: Geert Uytterhoeven, AKASHI Takahiro,
	Frédéric Weisbecker, Ingo Molnar, Catalin Marinas,
	tim.bird, gkulkarni, dsaxena, arndb, linux-arm-kernel,
	linaro-kernel, linux-kernel, Linux-sh list

The clean up of CALLER_ADDR*() functions required the archs to either
use the default __builtin_return_address(X) (where X > 0) or override
it with something the arch can use. To override it, the arch would
define function_return_address(x).

The arm architecture requires this to be redefined but instead of
defining function_return_address(x) it defined function_return_addr(x).

Reported-by: Geert Uytterhoeven <geert@linux-m68k.org>
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
----
diff --git a/arch/arm/include/asm/ftrace.h b/arch/arm/include/asm/ftrace.h
index eb577f4..39eb16b 100644
--- a/arch/arm/include/asm/ftrace.h
+++ b/arch/arm/include/asm/ftrace.h
@@ -52,7 +52,7 @@ extern inline void *return_address(unsigned int level)
 
 #endif
 
-#define ftrace_return_addr(n) return_address(n)
+#define ftrace_return_address(n) return_address(n)
 
 #endif /* ifndef __ASSEMBLY__ */
 

^ permalink raw reply related	[flat|nested] 235+ messages in thread

* [PATCH] arm/ftrace: Fix function_return_addr() to function_return_address()
@ 2014-06-11 13:23                   ` Steven Rostedt
  0 siblings, 0 replies; 235+ messages in thread
From: Steven Rostedt @ 2014-06-11 13:23 UTC (permalink / raw)
  To: linux-arm-kernel

The clean up of CALLER_ADDR*() functions required the archs to either
use the default __builtin_return_address(X) (where X > 0) or override
it with something the arch can use. To override it, the arch would
define function_return_address(x).

The arm architecture requires this to be redefined but instead of
defining function_return_address(x) it defined function_return_addr(x).

Reported-by: Geert Uytterhoeven <geert@linux-m68k.org>
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
----
diff --git a/arch/arm/include/asm/ftrace.h b/arch/arm/include/asm/ftrace.h
index eb577f4..39eb16b 100644
--- a/arch/arm/include/asm/ftrace.h
+++ b/arch/arm/include/asm/ftrace.h
@@ -52,7 +52,7 @@ extern inline void *return_address(unsigned int level)
 
 #endif
 
-#define ftrace_return_addr(n) return_address(n)
+#define ftrace_return_address(n) return_address(n)
 
 #endif /* ifndef __ASSEMBLY__ */
 

^ permalink raw reply related	[flat|nested] 235+ messages in thread

* Re: [PATCH] arm/ftrace: Fix function_return_addr() to function_return_address()
  2014-06-11 13:23                   ` Steven Rostedt
  (?)
@ 2014-06-11 13:38                     ` Geert Uytterhoeven
  -1 siblings, 0 replies; 235+ messages in thread
From: Geert Uytterhoeven @ 2014-06-11 13:38 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Steven,

On Wed, Jun 11, 2014 at 3:23 PM, Steven Rostedt <rostedt@goodmis.org> wrote:
> The clean up of CALLER_ADDR*() functions required the archs to either
> use the default __builtin_return_address(X) (where X > 0) or override
> it with something the arch can use. To override it, the arch would
> define function_return_address(x).

ftrace_return_address(x)

> The arm architecture requires this to be redefined but instead of
> defining function_return_address(x) it defined function_return_addr(x).

ftrace_return_address(x) ... ftrace_return_address(x)

> Reported-by: Geert Uytterhoeven <geert@linux-m68k.org>
> Signed-off-by: Steven Rostedt <rostedt@goodmis.org>

Nevertheless, your patch kills the warnings. Thanks!

Tested-by: Geert Uytterhoeven <geert@linux-m68k.org>

> ----
> diff --git a/arch/arm/include/asm/ftrace.h b/arch/arm/include/asm/ftrace.h
> index eb577f4..39eb16b 100644
> --- a/arch/arm/include/asm/ftrace.h
> +++ b/arch/arm/include/asm/ftrace.h
> @@ -52,7 +52,7 @@ extern inline void *return_address(unsigned int level)
>
>  #endif
>
> -#define ftrace_return_addr(n) return_address(n)
> +#define ftrace_return_address(n) return_address(n)
>
>  #endif /* ifndef __ASSEMBLY__ */

Gr{oetje,eeting}s,

                        Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
                                -- Linus Torvalds

^ permalink raw reply	[flat|nested] 235+ messages in thread

* Re: [PATCH] arm/ftrace: Fix function_return_addr() to function_return_address()
@ 2014-06-11 13:38                     ` Geert Uytterhoeven
  0 siblings, 0 replies; 235+ messages in thread
From: Geert Uytterhoeven @ 2014-06-11 13:38 UTC (permalink / raw)
  To: Steven Rostedt
  Cc: Will Deacon, AKASHI Takahiro, Frédéric Weisbecker,
	Ingo Molnar, Catalin Marinas, Tim Bird, gkulkarni, Deepak Saxena,
	arndb, linux-arm-kernel, linaro-kernel, linux-kernel,
	Linux-sh list

Hi Steven,

On Wed, Jun 11, 2014 at 3:23 PM, Steven Rostedt <rostedt@goodmis.org> wrote:
> The clean up of CALLER_ADDR*() functions required the archs to either
> use the default __builtin_return_address(X) (where X > 0) or override
> it with something the arch can use. To override it, the arch would
> define function_return_address(x).

ftrace_return_address(x)

> The arm architecture requires this to be redefined but instead of
> defining function_return_address(x) it defined function_return_addr(x).

ftrace_return_address(x) ... ftrace_return_address(x)

> Reported-by: Geert Uytterhoeven <geert@linux-m68k.org>
> Signed-off-by: Steven Rostedt <rostedt@goodmis.org>

Nevertheless, your patch kills the warnings. Thanks!

Tested-by: Geert Uytterhoeven <geert@linux-m68k.org>

> ----
> diff --git a/arch/arm/include/asm/ftrace.h b/arch/arm/include/asm/ftrace.h
> index eb577f4..39eb16b 100644
> --- a/arch/arm/include/asm/ftrace.h
> +++ b/arch/arm/include/asm/ftrace.h
> @@ -52,7 +52,7 @@ extern inline void *return_address(unsigned int level)
>
>  #endif
>
> -#define ftrace_return_addr(n) return_address(n)
> +#define ftrace_return_address(n) return_address(n)
>
>  #endif /* ifndef __ASSEMBLY__ */

Gr{oetje,eeting}s,

                        Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
                                -- Linus Torvalds

^ permalink raw reply	[flat|nested] 235+ messages in thread

* [PATCH] arm/ftrace: Fix function_return_addr() to function_return_address()
@ 2014-06-11 13:38                     ` Geert Uytterhoeven
  0 siblings, 0 replies; 235+ messages in thread
From: Geert Uytterhoeven @ 2014-06-11 13:38 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Steven,

On Wed, Jun 11, 2014 at 3:23 PM, Steven Rostedt <rostedt@goodmis.org> wrote:
> The clean up of CALLER_ADDR*() functions required the archs to either
> use the default __builtin_return_address(X) (where X > 0) or override
> it with something the arch can use. To override it, the arch would
> define function_return_address(x).

ftrace_return_address(x)

> The arm architecture requires this to be redefined but instead of
> defining function_return_address(x) it defined function_return_addr(x).

ftrace_return_address(x) ... ftrace_return_address(x)

> Reported-by: Geert Uytterhoeven <geert@linux-m68k.org>
> Signed-off-by: Steven Rostedt <rostedt@goodmis.org>

Nevertheless, your patch kills the warnings. Thanks!

Tested-by: Geert Uytterhoeven <geert@linux-m68k.org>

> ----
> diff --git a/arch/arm/include/asm/ftrace.h b/arch/arm/include/asm/ftrace.h
> index eb577f4..39eb16b 100644
> --- a/arch/arm/include/asm/ftrace.h
> +++ b/arch/arm/include/asm/ftrace.h
> @@ -52,7 +52,7 @@ extern inline void *return_address(unsigned int level)
>
>  #endif
>
> -#define ftrace_return_addr(n) return_address(n)
> +#define ftrace_return_address(n) return_address(n)
>
>  #endif /* ifndef __ASSEMBLY__ */

Gr{oetje,eeting}s,

                        Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert at linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
                                -- Linus Torvalds

^ permalink raw reply	[flat|nested] 235+ messages in thread

* Re: [PATCH] arm/ftrace: Fix function_return_addr() to function_return_address()
  2014-06-11 13:38                     ` Geert Uytterhoeven
  (?)
@ 2014-06-11 13:44                       ` Steven Rostedt
  -1 siblings, 0 replies; 235+ messages in thread
From: Steven Rostedt @ 2014-06-11 13:44 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, 11 Jun 2014 15:38:49 +0200
Geert Uytterhoeven <geert@linux-m68k.org> wrote:

> Hi Steven,
> 
> On Wed, Jun 11, 2014 at 3:23 PM, Steven Rostedt <rostedt@goodmis.org> wrote:
> > The clean up of CALLER_ADDR*() functions required the archs to either
> > use the default __builtin_return_address(X) (where X > 0) or override
> > it with something the arch can use. To override it, the arch would
> > define function_return_address(x).
> 
> ftrace_return_address(x)
> 
> > The arm architecture requires this to be redefined but instead of
> > defining function_return_address(x) it defined function_return_addr(x).
> 
> ftrace_return_address(x) ... ftrace_return_address(x)

As long as I got the patch part right ;-)

Will, please update the change log with the correct name. Including the
subject. Thanks!

-- Steve

> 
> > Reported-by: Geert Uytterhoeven <geert@linux-m68k.org>
> > Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
> 
> Nevertheless, your patch kills the warnings. Thanks!
> 
> Tested-by: Geert Uytterhoeven <geert@linux-m68k.org>
> 
> > ----
> > diff --git a/arch/arm/include/asm/ftrace.h b/arch/arm/include/asm/ftrace.h
> > index eb577f4..39eb16b 100644
> > --- a/arch/arm/include/asm/ftrace.h
> > +++ b/arch/arm/include/asm/ftrace.h
> > @@ -52,7 +52,7 @@ extern inline void *return_address(unsigned int level)
> >
> >  #endif
> >
> > -#define ftrace_return_addr(n) return_address(n)
> > +#define ftrace_return_address(n) return_address(n)
> >
> >  #endif /* ifndef __ASSEMBLY__ */
> 
> Gr{oetje,eeting}s,
> 
>                         Geert
> 
> --
> Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org
> 
> In personal conversations with technical people, I call myself a hacker. But
> when I'm talking to journalists I just say "programmer" or something like that.
>                                 -- Linus Torvalds


^ permalink raw reply	[flat|nested] 235+ messages in thread

* Re: [PATCH] arm/ftrace: Fix function_return_addr() to function_return_address()
@ 2014-06-11 13:44                       ` Steven Rostedt
  0 siblings, 0 replies; 235+ messages in thread
From: Steven Rostedt @ 2014-06-11 13:44 UTC (permalink / raw)
  To: Geert Uytterhoeven
  Cc: Will Deacon, AKASHI Takahiro, Frédéric Weisbecker,
	Ingo Molnar, Catalin Marinas, Tim Bird, gkulkarni, Deepak Saxena,
	arndb, linux-arm-kernel, linaro-kernel, linux-kernel,
	Linux-sh list

On Wed, 11 Jun 2014 15:38:49 +0200
Geert Uytterhoeven <geert@linux-m68k.org> wrote:

> Hi Steven,
> 
> On Wed, Jun 11, 2014 at 3:23 PM, Steven Rostedt <rostedt@goodmis.org> wrote:
> > The clean up of CALLER_ADDR*() functions required the archs to either
> > use the default __builtin_return_address(X) (where X > 0) or override
> > it with something the arch can use. To override it, the arch would
> > define function_return_address(x).
> 
> ftrace_return_address(x)
> 
> > The arm architecture requires this to be redefined but instead of
> > defining function_return_address(x) it defined function_return_addr(x).
> 
> ftrace_return_address(x) ... ftrace_return_address(x)

As long as I got the patch part right ;-)

Will, please update the change log with the correct name. Including the
subject. Thanks!

-- Steve

> 
> > Reported-by: Geert Uytterhoeven <geert@linux-m68k.org>
> > Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
> 
> Nevertheless, your patch kills the warnings. Thanks!
> 
> Tested-by: Geert Uytterhoeven <geert@linux-m68k.org>
> 
> > ----
> > diff --git a/arch/arm/include/asm/ftrace.h b/arch/arm/include/asm/ftrace.h
> > index eb577f4..39eb16b 100644
> > --- a/arch/arm/include/asm/ftrace.h
> > +++ b/arch/arm/include/asm/ftrace.h
> > @@ -52,7 +52,7 @@ extern inline void *return_address(unsigned int level)
> >
> >  #endif
> >
> > -#define ftrace_return_addr(n) return_address(n)
> > +#define ftrace_return_address(n) return_address(n)
> >
> >  #endif /* ifndef __ASSEMBLY__ */
> 
> Gr{oetje,eeting}s,
> 
>                         Geert
> 
> --
> Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org
> 
> In personal conversations with technical people, I call myself a hacker. But
> when I'm talking to journalists I just say "programmer" or something like that.
>                                 -- Linus Torvalds


^ permalink raw reply	[flat|nested] 235+ messages in thread

* [PATCH] arm/ftrace: Fix function_return_addr() to function_return_address()
@ 2014-06-11 13:44                       ` Steven Rostedt
  0 siblings, 0 replies; 235+ messages in thread
From: Steven Rostedt @ 2014-06-11 13:44 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, 11 Jun 2014 15:38:49 +0200
Geert Uytterhoeven <geert@linux-m68k.org> wrote:

> Hi Steven,
> 
> On Wed, Jun 11, 2014 at 3:23 PM, Steven Rostedt <rostedt@goodmis.org> wrote:
> > The clean up of CALLER_ADDR*() functions required the archs to either
> > use the default __builtin_return_address(X) (where X > 0) or override
> > it with something the arch can use. To override it, the arch would
> > define function_return_address(x).
> 
> ftrace_return_address(x)
> 
> > The arm architecture requires this to be redefined but instead of
> > defining function_return_address(x) it defined function_return_addr(x).
> 
> ftrace_return_address(x) ... ftrace_return_address(x)

As long as I got the patch part right ;-)

Will, please update the change log with the correct name. Including the
subject. Thanks!

-- Steve

> 
> > Reported-by: Geert Uytterhoeven <geert@linux-m68k.org>
> > Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
> 
> Nevertheless, your patch kills the warnings. Thanks!
> 
> Tested-by: Geert Uytterhoeven <geert@linux-m68k.org>
> 
> > ----
> > diff --git a/arch/arm/include/asm/ftrace.h b/arch/arm/include/asm/ftrace.h
> > index eb577f4..39eb16b 100644
> > --- a/arch/arm/include/asm/ftrace.h
> > +++ b/arch/arm/include/asm/ftrace.h
> > @@ -52,7 +52,7 @@ extern inline void *return_address(unsigned int level)
> >
> >  #endif
> >
> > -#define ftrace_return_addr(n) return_address(n)
> > +#define ftrace_return_address(n) return_address(n)
> >
> >  #endif /* ifndef __ASSEMBLY__ */
> 
> Gr{oetje,eeting}s,
> 
>                         Geert
> 
> --
> Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert at linux-m68k.org
> 
> In personal conversations with technical people, I call myself a hacker. But
> when I'm talking to journalists I just say "programmer" or something like that.
>                                 -- Linus Torvalds

^ permalink raw reply	[flat|nested] 235+ messages in thread

end of thread, other threads:[~2014-06-11 13:44 UTC | newest]

Thread overview: 235+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-10-24  7:08 [PATCH v2 0/6] arm64: Add ftrace support AKASHI Takahiro
2013-10-24  7:08 ` [PATCH v2 1/6] " AKASHI Takahiro
2013-10-24  7:08 ` [PATCH v2 2/6] arm64: ftrace: Add dynamic " AKASHI Takahiro
2013-10-24  7:08 ` [PATCH v2 3/6] arm64: ftrace: Add CALLER_ADDRx macros AKASHI Takahiro
2013-10-24  7:08 ` [PATCH v2 4/6] ftrace: Add arm64 support to recordmcount AKASHI Takahiro
2013-10-24  7:08 ` [PATCH v2 5/6] arm64: ftrace: Add system call tracepoint AKASHI Takahiro
2013-10-24  7:08 ` [PATCH v2 6/6] arm64: Add 'notrace' attribute to unwind_frame() for ftrace AKASHI Takahiro
2014-02-07 10:18 ` [PATCH v3 0/6] arm64: Add ftrace support AKASHI Takahiro
2014-02-07 10:18   ` AKASHI Takahiro
2014-02-07 10:18   ` [PATCH v3 1/6] " AKASHI Takahiro
2014-02-07 10:18     ` AKASHI Takahiro
2014-02-10 15:03     ` Arnd Bergmann
2014-02-10 15:03       ` Arnd Bergmann
2014-02-10 15:19       ` Steven Rostedt
2014-02-10 15:19         ` Steven Rostedt
     [not found]       ` <CAB5YjtCr2KL_q1FF8kO_VKe+feg7f9qFRKtwf3xj2h0ENwuB5g@mail.gmail.com>
2014-02-12 11:03         ` Arnd Bergmann
2014-02-12 11:03           ` Arnd Bergmann
2014-02-17 18:12     ` Will Deacon
2014-02-17 18:12       ` Will Deacon
2014-02-19 10:46       ` AKASHI Takahiro
2014-02-19 10:46         ` AKASHI Takahiro
2014-02-07 10:18   ` [PATCH v3 2/6] arm64: ftrace: Add dynamic " AKASHI Takahiro
2014-02-07 10:18     ` AKASHI Takahiro
2014-02-07 10:18   ` [PATCH v3 3/6] arm64: ftrace: Add CALLER_ADDRx macros AKASHI Takahiro
2014-02-07 10:18     ` AKASHI Takahiro
2014-02-07 10:18   ` [PATCH v3 4/6] ftrace: Add arm64 support to recordmcount AKASHI Takahiro
2014-02-07 10:18     ` AKASHI Takahiro
2014-02-07 10:18   ` [PATCH v3 5/6] arm64: ftrace: Add system call tracepoint AKASHI Takahiro
2014-02-07 10:18     ` AKASHI Takahiro
2014-02-17 19:29     ` Will Deacon
2014-02-17 19:29       ` Will Deacon
2014-02-19 10:48       ` AKASHI Takahiro
2014-02-19 10:48         ` AKASHI Takahiro
2014-02-07 10:18   ` [PATCH v3 6/6] arm64: Add 'notrace' attribute to unwind_frame() for ftrace AKASHI Takahiro
2014-02-07 10:18     ` AKASHI Takahiro
2014-02-10 14:21   ` [PATCH v3 0/6] arm64: Add ftrace support Kulkarni, Ganapatrao
2014-02-10 14:21     ` Kulkarni, Ganapatrao
2014-02-25  9:23   ` [PATCH v4 0/7] " AKASHI Takahiro
2014-02-25  9:23     ` AKASHI Takahiro
2014-02-25  9:23     ` [PATCH v4 1/7] " AKASHI Takahiro
2014-02-25  9:23       ` AKASHI Takahiro
2014-02-25 15:38       ` Kulkarni, Ganapatrao
2014-02-25 15:38         ` Kulkarni, Ganapatrao
2014-02-28  5:06         ` AKASHI Takahiro
2014-02-28  5:06           ` AKASHI Takahiro
2014-02-25  9:23     ` [PATCH v4 2/7] arm64: ftrace: Add dynamic " AKASHI Takahiro
2014-02-25  9:23       ` AKASHI Takahiro
2014-02-25  9:23     ` [PATCH v4 3/7] arm64: ftrace: Add CALLER_ADDRx macros AKASHI Takahiro
2014-02-25  9:23       ` AKASHI Takahiro
2014-02-25  9:23     ` [PATCH v4 4/7] ftrace: Add arm64 support to recordmcount AKASHI Takahiro
2014-02-25  9:23       ` AKASHI Takahiro
2014-02-25  9:23     ` [PATCH v4 5/7] arm64: ftrace: Add system call tracepoint AKASHI Takahiro
2014-02-25  9:23       ` AKASHI Takahiro
2014-02-25  9:23     ` [PATCH v4 6/7] arm64: Add 'notrace' attribute to unwind_frame() for ftrace AKASHI Takahiro
2014-02-25  9:23       ` AKASHI Takahiro
2014-02-25  9:23     ` [PATCH v4 7/7] arm64: add __ASSEMBLY__ in asm/insn.h AKASHI Takahiro
2014-02-25  9:23       ` AKASHI Takahiro
2014-02-28  5:18     ` [PATCH v5 0/7] arm64: Add ftrace support AKASHI Takahiro
2014-02-28  5:18       ` AKASHI Takahiro
2014-02-28  5:18       ` [PATCH v5 1/7] " AKASHI Takahiro
2014-02-28  5:18         ` AKASHI Takahiro
2014-02-28  5:18       ` [PATCH v5 2/7] arm64: ftrace: Add dynamic " AKASHI Takahiro
2014-02-28  5:18         ` AKASHI Takahiro
2014-02-28  5:18       ` [PATCH v5 3/7] arm64: ftrace: Add CALLER_ADDRx macros AKASHI Takahiro
2014-02-28  5:18         ` AKASHI Takahiro
2014-02-28  5:18       ` [PATCH v5 4/7] ftrace: Add arm64 support to recordmcount AKASHI Takahiro
2014-02-28  5:18         ` AKASHI Takahiro
2014-02-28  5:18       ` [PATCH v5 5/7] arm64: ftrace: Add system call tracepoint AKASHI Takahiro
2014-02-28  5:18         ` AKASHI Takahiro
2014-02-28  5:18       ` [PATCH v5 6/7] arm64: Add 'notrace' attribute to unwind_frame() for ftrace AKASHI Takahiro
2014-02-28  5:18         ` AKASHI Takahiro
2014-02-28  5:18       ` [PATCH v5 7/7] arm64: add __ASSEMBLY__ in asm/insn.h AKASHI Takahiro
2014-02-28  5:18         ` AKASHI Takahiro
2014-03-11 14:35       ` [PATCH v5 0/7] arm64: Add ftrace support Will Deacon
2014-03-11 14:35         ` Will Deacon
2014-03-12  1:47         ` AKASHI Takahiro
2014-03-12  1:47           ` AKASHI Takahiro
2014-03-12  1:58           ` Steven Rostedt
2014-03-12  1:58             ` Steven Rostedt
2014-03-12  2:02           ` Steven Rostedt
2014-03-12  2:02             ` Steven Rostedt
2014-03-13 10:13       ` [PATCH v6 " AKASHI Takahiro
2014-03-13 10:13         ` AKASHI Takahiro
2014-03-13 10:13         ` [PATCH v6 1/7] arm64: add __ASSEMBLY__ in asm/insn.h AKASHI Takahiro
2014-03-13 10:13           ` AKASHI Takahiro
2014-03-13 12:19           ` Will Deacon
2014-03-13 12:19             ` Will Deacon
2014-03-13 10:13         ` [PATCH v6 2/7] arm64: Add 'notrace' attribute to unwind_frame() for ftrace AKASHI Takahiro
2014-03-13 10:13           ` AKASHI Takahiro
2014-03-13 12:19           ` Will Deacon
2014-03-13 12:19             ` Will Deacon
2014-03-13 10:13         ` [PATCH v6 3/7] ftrace: Add arm64 support to recordmcount AKASHI Takahiro
2014-03-13 10:13           ` AKASHI Takahiro
2014-03-13 12:38           ` Will Deacon
2014-03-13 12:38             ` Will Deacon
2014-03-13 14:57             ` AKASHI Takahiro
2014-03-13 14:57               ` AKASHI Takahiro
2014-03-13 16:05               ` Will Deacon
2014-03-13 16:05                 ` Will Deacon
2014-03-13 10:13         ` [PATCH v6 4/7] arm64: Add ftrace support AKASHI Takahiro
2014-03-13 10:13           ` AKASHI Takahiro
2014-03-13 17:08           ` Will Deacon
2014-03-13 17:08             ` Will Deacon
2014-03-13 18:27             ` Steven Rostedt
2014-03-13 18:27               ` Steven Rostedt
2014-03-13 18:37               ` Will Deacon
2014-03-13 18:37                 ` Will Deacon
2014-03-13 18:49                 ` Steven Rostedt
2014-03-13 18:49                   ` Steven Rostedt
2014-03-14  4:45             ` AKASHI Takahiro
2014-03-14  4:45               ` AKASHI Takahiro
2014-03-14 10:07               ` Will Deacon
2014-03-14 10:07                 ` Will Deacon
2014-03-14 16:13                 ` AKASHI Takahiro
2014-03-14 16:13                   ` AKASHI Takahiro
2014-03-13 10:13         ` [PATCH v6 5/7] arm64: ftrace: Add dynamic " AKASHI Takahiro
2014-03-13 10:13           ` AKASHI Takahiro
2014-03-13 18:10           ` Will Deacon
2014-03-13 18:10             ` Will Deacon
2014-03-13 18:33             ` Steven Rostedt
2014-03-13 18:33               ` Steven Rostedt
2014-03-14  5:28               ` AKASHI Takahiro
2014-03-14  5:28                 ` AKASHI Takahiro
2014-03-14  5:26             ` AKASHI Takahiro
2014-03-14  5:26               ` AKASHI Takahiro
2014-03-13 10:13         ` [PATCH v6 6/7] arm64: ftrace: Add CALLER_ADDRx macros AKASHI Takahiro
2014-03-13 10:13           ` AKASHI Takahiro
2014-03-13 15:54           ` Will Deacon
2014-03-13 15:54             ` Will Deacon
2014-03-13 18:07             ` Steven Rostedt
2014-03-13 18:07               ` Steven Rostedt
2014-03-14  4:55               ` AKASHI Takahiro
2014-03-14  4:55                 ` AKASHI Takahiro
2014-03-14  3:00             ` AKASHI Takahiro
2014-03-14  3:00               ` AKASHI Takahiro
2014-03-14 10:09               ` Will Deacon
2014-03-14 10:09                 ` Will Deacon
2014-03-14 16:15                 ` AKASHI Takahiro
2014-03-14 16:15                   ` AKASHI Takahiro
2014-03-13 10:13         ` [PATCH v6 7/7] arm64: ftrace: Add system call tracepoint AKASHI Takahiro
2014-03-13 10:13           ` AKASHI Takahiro
2014-03-13 16:25           ` Will Deacon
2014-03-13 16:25             ` Will Deacon
2014-03-14  3:50             ` AKASHI Takahiro
2014-03-14  3:50               ` AKASHI Takahiro
2014-03-15  5:40         ` [PATCH v7 0/7] arm64: Add ftrace support AKASHI Takahiro
2014-03-15  5:40           ` AKASHI Takahiro
2014-03-15  5:40           ` [PATCH v7 1/7] arm64: add __ASSEMBLY__ in asm/insn.h AKASHI Takahiro
2014-03-15  5:40             ` AKASHI Takahiro
2014-03-15  5:40           ` [PATCH v7 2/7] arm64: Add 'notrace' attribute to unwind_frame() for ftrace AKASHI Takahiro
2014-03-15  5:40             ` AKASHI Takahiro
2014-03-15  5:40           ` [PATCH v7 3/7] ftrace: Add arm64 support to recordmcount AKASHI Takahiro
2014-03-15  5:40             ` AKASHI Takahiro
2014-04-16 13:31             ` Will Deacon
2014-04-16 13:31               ` Will Deacon
2014-04-30  9:54           ` [PATCH v8 0/8] arm64: Add ftrace support AKASHI Takahiro
2014-04-30  9:54             ` AKASHI Takahiro
2014-04-30  9:54             ` [PATCH v8 1/8] ftrace: make CALLER_ADDRx macros more generic AKASHI Takahiro
2014-04-30  9:54               ` AKASHI Takahiro
2014-05-02 18:13               ` Will Deacon
2014-05-02 18:13                 ` Will Deacon
2014-05-02 19:02                 ` Steven Rostedt
2014-05-02 19:02                   ` Steven Rostedt
2014-05-02 19:03                 ` Steven Rostedt
2014-05-02 19:03                   ` Steven Rostedt
2014-05-02 19:19               ` Steven Rostedt
2014-05-02 19:19                 ` Steven Rostedt
2014-05-12 15:58                 ` Will Deacon
2014-05-12 15:58                   ` Will Deacon
2014-05-12 16:05                   ` Steven Rostedt
2014-05-12 16:05                     ` Steven Rostedt
2014-05-12 16:12                     ` Will Deacon
2014-05-12 16:12                       ` Will Deacon
2014-05-12 17:23                       ` Steven Rostedt
2014-05-12 17:23                         ` Steven Rostedt
2014-05-20 11:29                 ` AKASHI Takahiro
2014-05-20 11:29                   ` AKASHI Takahiro
2014-05-20 11:31               ` [PATCH v8_1] " AKASHI Takahiro
2014-05-20 11:31                 ` AKASHI Takahiro
2014-06-11 12:34               ` [PATCH v8 1/8] " Geert Uytterhoeven
2014-06-11 12:34                 ` Geert Uytterhoeven
2014-06-11 12:34                 ` Geert Uytterhoeven
2014-06-11 13:23                 ` [PATCH] arm/ftrace: Fix function_return_addr() to function_return_address() Steven Rostedt
2014-06-11 13:23                   ` Steven Rostedt
2014-06-11 13:23                   ` Steven Rostedt
2014-06-11 13:38                   ` Geert Uytterhoeven
2014-06-11 13:38                     ` Geert Uytterhoeven
2014-06-11 13:38                     ` Geert Uytterhoeven
2014-06-11 13:44                     ` Steven Rostedt
2014-06-11 13:44                       ` Steven Rostedt
2014-06-11 13:44                       ` Steven Rostedt
2014-04-30  9:54             ` [PATCH v8 2/8] arm64: add __ASSEMBLY__ in asm/insn.h AKASHI Takahiro
2014-04-30  9:54               ` AKASHI Takahiro
2014-04-30  9:54             ` [PATCH v8 3/8] arm64: Add 'notrace' attribute to unwind_frame() for ftrace AKASHI Takahiro
2014-04-30  9:54               ` AKASHI Takahiro
2014-04-30  9:54             ` [PATCH v8 4/8] ftrace: Add arm64 support to recordmcount AKASHI Takahiro
2014-04-30  9:54               ` AKASHI Takahiro
2014-04-30  9:54             ` [PATCH v8 5/8] arm64: Add ftrace support AKASHI Takahiro
2014-04-30  9:54               ` AKASHI Takahiro
2014-05-28 20:19               ` Mark Brown
2014-05-28 20:19                 ` Mark Brown
2014-05-29  8:07                 ` Will Deacon
2014-05-29  8:07                   ` Will Deacon
2014-05-29  9:47                   ` Mark Brown
2014-05-29  9:47                     ` Mark Brown
2014-04-30  9:54             ` [PATCH v8 6/8] arm64: ftrace: Add dynamic " AKASHI Takahiro
2014-04-30  9:54               ` AKASHI Takahiro
2014-04-30  9:54             ` [PATCH v8 7/8] arm64: ftrace: Add CALLER_ADDRx macros AKASHI Takahiro
2014-04-30  9:54               ` AKASHI Takahiro
2014-04-30  9:54             ` [PATCH v8 8/8] arm64: ftrace: Add system call tracepoint AKASHI Takahiro
2014-04-30  9:54               ` AKASHI Takahiro
2014-03-15  5:45         ` [PATCH v7 4/7] arm64: Add ftrace support AKASHI Takahiro
2014-03-15  5:45           ` AKASHI Takahiro
2014-04-16 13:45           ` Will Deacon
2014-04-16 13:45             ` Will Deacon
2014-03-15  5:45         ` [PATCH v7 5/7] arm64: ftrace: Add dynamic " AKASHI Takahiro
2014-03-15  5:45           ` AKASHI Takahiro
2014-04-16 13:48           ` Will Deacon
2014-04-16 13:48             ` Will Deacon
2014-03-15  5:45         ` [PATCH v7 6/7] arm64: ftrace: Add CALLER_ADDRx macros AKASHI Takahiro
2014-03-15  5:45           ` AKASHI Takahiro
2014-04-16 13:52           ` Will Deacon
2014-04-16 13:52             ` Will Deacon
2014-04-28 10:41             ` AKASHI Takahiro
2014-04-28 10:41               ` AKASHI Takahiro
2014-05-27 13:10               ` [for-next][PATCH] ftrace: Make CALLER_ADDRx macros more generic Steven Rostedt
2014-05-27 13:10                 ` Steven Rostedt
2014-05-27 18:49                 ` Will Deacon
2014-05-27 18:49                   ` Will Deacon
2014-05-29  5:27                   ` AKASHI Takahiro
2014-05-29  5:27                     ` AKASHI Takahiro
2014-05-29  8:10                     ` Will Deacon
2014-05-29  8:10                       ` Will Deacon
2014-03-15  5:45         ` [PATCH v7 7/7] arm64: ftrace: Add system call tracepoint AKASHI Takahiro
2014-03-15  5:45           ` AKASHI Takahiro

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.