* [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
* 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
* [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
* 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
* [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
* 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 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
* [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(¤t->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(¤t->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 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(¤t->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(¤t->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 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 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 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(¤t->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(¤t->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 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 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
* [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
* 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 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 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 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
* [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
* 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 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 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 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 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 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 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 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 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
* [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
* 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
* [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
* 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
* 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
* 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
* [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
* 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] 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: 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
* 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
* [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
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
* 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
* [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
* 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 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(¤t->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(¤t->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 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: [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: [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
* [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
* [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(¤t->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(¤t->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
* 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
* [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
* 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
* [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
* 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
* [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: [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: [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
* [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