Support ftrace on NDS32 architecture
cover Support ftrace on NDS32 architecture
This patch set implements the ftrace function and function graph tracer on NDS32 architecture. We try to use C code to do everything, so we don't need to separate the implementation to assembly code and C code, we just need one ftrace.c file.
In mcount function, we use the prologue/epilogue which generated by compiler to help us to save/restore the status. On the other hand, we use naked attribute of gcc to avoid to generate the prologue/epilogue when we don't need it(such as ftrace_stub and return_to_handler).
We pass the following tests:
1. FTRACE_STARTUP_TEST: PASS
2. tools/testing/selftests/ftrace/:
# of passed: 28 # of failed: 1 # of unresolved: 0 # of untested: 0 # of unsupported: 38 # of xfailed: 0 # of undefined(test bug): 0
The failed case is func-filter-glob.tc.
When setting the '*aw*lock' to the set_ftrace_filter in this test case, we got the error because we have no these functions such as _raw_spin_lock, _raw_spin_trylock and so on in our kernel.
Zong Li (6):
nds32/ftrace: Support static function tracer nds32/ftrace: Support static function graph tracer nds32/ftrace: Add RECORD_MCOUNT support
nds32/ftrace: Support dynamic function tracer nds32/ftrace: Support dynamic function graph tracer nds32/stack: Get real return address by using ftrace_graph_ret_addr
arch/nds32/Kconfig | 4 + arch/nds32/Makefile | 4 + arch/nds32/include/asm/ftrace.h | 46 +++++++ arch/nds32/kernel/Makefile | 6 + arch/nds32/kernel/ftrace.c | 297 ++++++++++++++++++++++++++++++++++++++++ arch/nds32/kernel/stacktrace.c | 4 + arch/nds32/kernel/traps.c | 30 +--- scripts/recordmcount.pl | 3 + 8 files changed, 370 insertions(+), 24 deletions(-) create mode 100644 arch/nds32/include/asm/ftrace.h create mode 100644 arch/nds32/kernel/ftrace.c
Signature · 1 line
2.7.4
PATCH 1/6 nds32/ftrace: Support static function tracer
This patch support the static function tracer. On nds32 ABI, we need to always push return address to stack for __builtin_return_address can work correctly, otherwise, it will get the wrong value of $lp at leaf function.
--- arch/nds32/Kconfig | 1 + arch/nds32/Makefile | 4 ++++ arch/nds32/include/asm/ftrace.h | 20 ++++++++++++++++++++ arch/nds32/kernel/Makefile | 6 ++++++ arch/nds32/kernel/ftrace.c | 28 ++++++++++++++++++++++++++++ 5 files changed, 59 insertions(+) create mode 100644 arch/nds32/include/asm/ftrace.h create mode 100644 arch/nds32/kernel/ftrace.c
arch/nds32/Kconfig +1 -0
@@ -40,6 +40,7 @@ config NDS32 select NO_IOPORT_MAP select RTC_LIB select THREAD_INFO_IN_TASK + select HAVE_FUNCTION_TRACER help Andes(nds32) Linux support.
arch/nds32/Makefile +4 -0
@@ -5,6 +5,10 @@ KBUILD_DEFCONFIG := defconfig comma = , +ifdef CONFIG_FUNCTION_TRACER +arch-y += -malways-save-lp -mno-relax +endif + KBUILD_CFLAGS += $(call cc-option, -mno-sched-prolog-epilog) KBUILD_CFLAGS += -mcmodel=large
arch/nds32/include/asm/ftrace.h new file +20 -0
@@ -0,0 +1,20 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +#ifndef __ASM_NDS32_FTRACE_H +#define __ASM_NDS32_FTRACE_H + +#ifdef CONFIG_FUNCTION_TRACER + +#define HAVE_FUNCTION_GRAPH_FP_TEST + +#define MCOUNT_ADDR ((unsigned long)(_mcount)) +/* mcount call is composed of three instructions: +* sethi + ori + jral +*/ +#define MCOUNT_INSN_SIZE 12 + +extern void _mcount (unsigned long parent_ip); + +#endif /* CONFIG_FUNCTION_TRACER */ + +#endif /* __ASM_NDS32_FTRACE_H */
arch/nds32/kernel/Makefile +6 -0
@@ -21,3 +21,9 @@ extra-y := head.o vmlinux.lds obj-y += vdso/ + +obj-$(CONFIG_FUNCTION_TRACER) += ftrace.o + +ifdef CONFIG_FUNCTION_TRACER +CFLAGS_REMOVE_ftrace.o = $(CC_FLAGS_FTRACE) +endif
arch/nds32/kernel/ftrace.c new file +28 -0
@@ -0,0 +1,28 @@ +// SPDX-License-Identifier: GPL-2.0 + +#include <linux/ftrace.h> +#include <linux/uaccess.h> +#include <asm/cacheflush.h> + +extern void (*ftrace_trace_function)(unsigned long ,unsigned long , +struct ftrace_ops *,struct pt_regs *); + +noinline void __naked ftrace_stub(unsigned long ip, unsigned long parent_ip, +struct ftrace_ops *op,struct pt_regs *regs) +{ + __asm__ ("" );/* avoid to optimize as pure function */ +} + +noinline void _mcount(unsigned long parent_ip) +{ +/* save all state by the compiler prologue */ + +unsigned long ip = (unsigned long )__builtin_return_address (0 ); + +if (ftrace_trace_function != ftrace_stub) +ftrace_trace_function (ip -MCOUNT_INSN_SIZE , parent_ip, +NULL ,NULL ); + +/* restore all state by the compiler epilogue */ +} +EXPORT_SYMBOL (_mcount);
Signature · 1 line
2.7.4
Steven Rostedt
maintainerRe: [PATCH 1/6] nds32/ftrace: Support static function tracer
Quoted 96 lines · On Wed, 15 Aug 2018 17:35:18 +0800 Zong Li <[email protected]> wrote:
This patch support the static function tracer. On nds32 ABI, we need to always push return address to stack for
__builtin_return_addresscan work correctly, otherwise, it will get the wrong value of $lp at leaf function.Signed-off-by Zong Li <[email protected]>--- arch/nds32/Kconfig | 1 + arch/nds32/Makefile | 4 ++++ arch/nds32/include/asm/ftrace.h | 20 ++++++++++++++++++++ arch/nds32/kernel/Makefile | 6 ++++++ arch/nds32/kernel/ftrace.c | 28 ++++++++++++++++++++++++++++ 5 files changed, 59 insertions(+) create mode 100644 arch/nds32/include/asm/ftrace.h create mode 100644 arch/nds32/kernel/ftrace.carch/nds32/Kconfig +1
-0@@ -40,6 +40,7 @@ config NDS32 select NO_IOPORT_MAP select RTC_LIB select THREAD_INFO_IN_TASK + select HAVE_FUNCTION_TRACER help Andes(nds32) Linux support.arch/nds32/Makefile +4
-0@@ -5,6 +5,10 @@ KBUILD_DEFCONFIG := defconfig comma = , +ifdef CONFIG_FUNCTION_TRACER +arch-y += -malways-save-lp -mno-relax +endif + KBUILD_CFLAGS += $(call cc-option, -mno-sched-prolog-epilog) KBUILD_CFLAGS += -mcmodel=largearch/nds32/include/asm/ftrace.h new file +20
-0@@ -0,0 +1,20 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +#ifndef __ASM_NDS32_FTRACE_H +#define __ASM_NDS32_FTRACE_H + +#ifdef CONFIG_FUNCTION_TRACER + +#define HAVE_FUNCTION_GRAPH_FP_TEST + +#define MCOUNT_ADDR ((unsigned long)(_mcount)) +/* mcount call is composed of three instructions: +* sethi + ori + jral +*/ +#define MCOUNT_INSN_SIZE 12 + +extern void _mcount (unsigned long parent_ip); + +#endif /* CONFIG_FUNCTION_TRACER */ + +#endif /* __ASM_NDS32_FTRACE_H */ arch/nds32/kernel/Makefile +6
-0@@ -21,3 +21,9 @@ extra-y := head.o vmlinux.lds obj-y += vdso/ + +obj-$(CONFIG_FUNCTION_TRACER) += ftrace.o + +ifdef CONFIG_FUNCTION_TRACER +CFLAGS_REMOVE_ftrace.o = $(CC_FLAGS_FTRACE) +endifarch/nds32/kernel/ftrace.c new file +7
-0@@ -0,0 +1,28 @@ +// SPDX-License-Identifier: GPL-2.0 + +#include <linux/ftrace.h> +#include <linux/uaccess.h> +#include <asm/cacheflush.h> + +extern void (*ftrace_trace_function)(unsigned long, unsigned long,
arch/nds32/kernel/ftrace.c line 17
Quoted 10 lines
arch/nds32/kernel/ftrace.c new file +10
-0+ struct ftrace_ops*, struct pt_regs*); + +noinline void __naked ftrace_stub(unsigned long ip, unsigned long parent_ip, +struct ftrace_ops *op,struct pt_regs *regs) +{ + __asm__ ("" );/* avoid to optimize as pure function */ +} + +noinline void _mcount(unsigned long parent_ip) +{
Wow! The NDS32 arch allows for _mcount to be a C function! That's nice :-)
-- Steve
Quoted 11 lines
arch/nds32/kernel/ftrace.c new file +11
-0+/* save all state by the compiler prologue */ + +unsigned long ip = (unsigned long )__builtin_return_address (0 ); + +if (ftrace_trace_function != ftrace_stub) +ftrace_trace_function (ip -MCOUNT_INSN_SIZE , parent_ip, +NULL ,NULL ); + +/* restore all state by the compiler epilogue */ +} +EXPORT_SYMBOL (_mcount);
PATCH 2/6 nds32/ftrace: Support static function graph tracer
In reply to Zong LiThis patch contains implementation of static function graph tracer.
--- arch/nds32/Kconfig | 1 + arch/nds32/kernel/ftrace.c | 69 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 70 insertions(+)
arch/nds32/Kconfig +1 -0
@@ -41,6 +41,7 @@ config NDS32 select RTC_LIB select THREAD_INFO_IN_TASK select HAVE_FUNCTION_TRACER + select HAVE_FUNCTION_GRAPH_TRACER help Andes(nds32) Linux support.
arch/nds32/kernel/ftrace.c +69 -0
81 lines not on this page · raw message
Signature · 1 line
2.7.4
PATCH 3/6 nds32/ftrace: Add RECORD_MCOUNT support
In reply to Zong LiRecognize NDS32 object files in recordmcount.pl.
--- arch/nds32/Kconfig | 1 + scripts/recordmcount.pl | 3 +++ 2 files changed, 4 insertions(+)
arch/nds32/Kconfig +1 -0
@@ -42,6 +42,7 @@ config NDS32 select THREAD_INFO_IN_TASK select HAVE_FUNCTION_TRACER select HAVE_FUNCTION_GRAPH_TRACER + select HAVE_FTRACE_MCOUNT_RECORD help Andes(nds32) Linux support.
scripts/recordmcount.pl +3 -0
@@ -389,6 +389,9 @@ if ($arch eq "x86_64") { $mcount_regex = "^\\s*([0-9a-fA-F]+):\\sR_RISCV_CALL\\s_mcount\$"; $type = ".quad"; $alignment = 2; +} elsif ($arch eq "nds32") { + $mcount_regex = "^\\s*([0-9a-fA-F]+):\\s*R_NDS32_HI20_RELA\\s+_mcount\$"; + $alignment = 2; } else { die "Arch $arch is not supported with CONFIG_FTRACE_MCOUNT_RECORD"; }
Signature · 1 line
2.7.4
PATCH 4/6 nds32/ftrace: Support dynamic function tracer
In reply to Zong LiThis patch contains the implementation of dynamic function tracer. The mcount call is composed of three instructions, so there are three nop for enough placeholder.
--- arch/nds32/Kconfig | 1 + arch/nds32/include/asm/ftrace.h | 26 +++++++ arch/nds32/kernel/ftrace.c | 164 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 191 insertions(+)
arch/nds32/Kconfig +1 -0
@@ -43,6 +43,7 @@ config NDS32 select HAVE_FUNCTION_TRACER select HAVE_FUNCTION_GRAPH_TRACER select HAVE_FTRACE_MCOUNT_RECORD + select HAVE_DYNAMIC_FTRACE help Andes(nds32) Linux support.
arch/nds32/include/asm/ftrace.h +26 -0
@@ -15,6 +15,32 @@extern void _mcount (unsigned long parent_ip); +#ifdef CONFIG_DYNAMIC_FTRACE + +#define FTRACE_ADDR ((unsigned long)_ftrace_caller) + +#ifdef __NDS32_EL__ +#define INSN_NOP 0x09000040 +#define INSN_SIZE (insn) (((insn & 0x00000080) == 0) ? 4 : 2) +#define IS_SETHI (insn) ((insn & 0x000000fe) == 0x00000046) +#define ENDIAN_CONVERT (insn) be32_to_cpu(insn) +#else /* __NDS32_EB__ */ +#define INSN_NOP 0x40000009 +#define INSN_SIZE (insn) (((insn & 0x80000000) == 0) ? 4 : 2) +#define IS_SETHI (insn) ((insn & 0xfe000000) == 0x46000000) +#define ENDIAN_CONVERT (insn) (insn) +#endif + +extern void _ftrace_caller (unsigned long parent_ip); +static inline unsigned long ftrace_call_adjust (unsigned long addr) +{ +return addr; +} +struct dyn_arch_ftrace { +}; + +#endif /* CONFIG_DYNAMIC_FTRACE */ +#endif /* CONFIG_FUNCTION_TRACER */ #endif /* __ASM_NDS32_FTRACE_H */
arch/nds32/kernel/ftrace.c +164 -0
180 lines not on this page · raw message
Signature · 1 line
2.7.4
PATCH 5/6 nds32/ftrace: Support dynamic function graph tracer
In reply to Zong LiThis patch contains the implementation of dynamic function graph tracer.
--- arch/nds32/kernel/ftrace.c | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+)
arch/nds32/kernel/ftrace.c +36 -0
@@ -74,6 +74,14 @@ void _ftrace_caller(unsigned long parent_ip)"nop \n\t" "nop \n\t"); +#ifdef CONFIG_FUNCTION_GRAPH_TRACER +/* a placeholder for the call to ftrace_graph_caller */ + __asm__ __volatile__ ( +"ftrace_graph_call: \n\t" +"nop \n\t" +"nop \n\t" +"nop \n\t" ); +#endif /* restore all state needed by the compiler epilogue */ }
@@ -258,4 +266,32 @@ void __naked return_to_handler(void) "lmw.bim $r0,[$sp],$r1,#0x0 \n\t"); } +#ifdef CONFIG_DYNAMIC_FTRACE +extern unsigned long ftrace_graph_call; + +static int ftrace_modify_graph_caller (bool enable) +{ +unsigned long pc = (unsigned long )&ftrace_graph_call; +unsigned long nop_insn[3 ] = {INSN_NOP ,INSN_NOP ,INSN_NOP }; +unsigned long call_insn[3 ] = {INSN_NOP ,INSN_NOP ,INSN_NOP }; + +ftrace_gen_call_insn (call_insn, (unsigned long )ftrace_graph_caller); + +if (enable) +return ftrace_modify_code (pc, nop_insn, call_insn, true); +else +return ftrace_modify_code (pc, call_insn, nop_insn, 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 */
Signature · 1 line
2.7.4
PATCH 6/6 nds32/stack: Get real return address by using ftrace_graph_ret_addr
In reply to Zong LiFunction graph tracer has modified the return address to 'return_to_handler' on stack, and provide the 'ftrace_graph_ret_addr' to get the real return address.
--- arch/nds32/kernel/stacktrace.c | 4 ++++ arch/nds32/kernel/traps.c | 30 ++++++------------------------ 2 files changed, 10 insertions(+), 24 deletions(-)
arch/nds32/kernel/stacktrace.c +4 -0
@@ -4,6 +4,7 @@#include <linux/sched/debug.h> #include <linux/sched/task_stack.h> #include <linux/stacktrace.h> +#include <linux/ftrace.h> void save_stack_trace (struct stack_trace *trace) {
@@ -16,6 +17,7 @@ void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace)unsigned long *fpn;int skip = trace->skip;int savesched; +int graph_idx =0 ;if (tsk == current) { __asm__ __volatile__("\tori\t%0, $fp, #0\n" :"=r" (fpn));
@@ -33,6 +35,8 @@ void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace) fpp = fpn[FP_OFFSET ];if (!__kernel_text_address (lpp))break ; +else + lpp =ftrace_graph_ret_addr (tsk, &graph_idx, lpp,NULL );if (savesched || !in_sched_functions (lpp)) {if (skip) {
arch/nds32/kernel/traps.c +6 -24
@@ -8,6 +8,7 @@#include <linux/kdebug.h> #include <linux/sched/task_stack.h> #include <linux/uaccess.h> +#include <linux/ftrace.h> #include <asm/proc-fns.h> #include <asm/unistd.h>
@@ -94,28 +95,6 @@ static void dump_instr(struct pt_regs *regs)set_fs (fs); } -#ifdef CONFIG_FUNCTION_GRAPH_TRACER -#include <linux/ftrace.h> -static void -get_real_ret_addr (unsigned long *addr,struct task_struct *tsk,int *graph) -{ -if (*addr == (unsigned long )return_to_handler) { -int index = tsk->curr_ret_stack; - -if (tsk->ret_stack && index >= *graph) { - index -= *graph; - *addr = tsk->ret_stack[index].ret; - (*graph)++; - } - } -} -#else -static inline void -get_real_ret_addr (unsigned long *addr,struct task_struct *tsk,int *graph) -{ -} -#endif -#define LOOP_TIMES (100)static void __dump (struct task_struct *tsk,unsigned long *base_reg) {
@@ -126,7 +105,8 @@ static void __dump(struct task_struct *tsk, unsigned long *base_reg)while (!kstack_end (base_reg)) { ret_addr = *base_reg++;if (__kernel_text_address (ret_addr)) { -get_real_ret_addr (&ret_addr, tsk, &graph); + ret_addr =ftrace_graph_ret_addr ( + tsk, &graph, ret_addr,NULL );print_ip_sym (ret_addr); }if (--cnt <0 )
@@ -145,7 +125,9 @@ static void __dump(struct task_struct *tsk, unsigned long *base_reg) next_fp = base_reg[FP_OFFSET ];#endif if (__kernel_text_address (ret_addr)) { -get_real_ret_addr (&ret_addr, tsk, &graph); + + ret_addr =ftrace_graph_ret_addr ( + tsk, &graph, ret_addr,NULL );print_ip_sym (ret_addr); }if (--cnt <0 )
Signature · 1 line
2.7.4
Zong Li <[email protected]> 於 2018年8月15日 週三 下午5:35寫道:
Quoted 37 lines
This patch set implements the ftrace function and function graph tracer on NDS32 architecture. We try to use C code to do everything, so we don't need to separate the implementation to assembly code and C code, we just need one
ftrace.cfile.In mcount function, we use the prologue/epilogue which generated by compiler to help us to save/restore the status. On the other hand, we use naked attribute of gcc to avoid to generate the prologue/epilogue when we don't need
it(such as ftrace_stub and return_to_handler).We pass the following tests:
1.
FTRACE_STARTUP_TEST: PASS2.
tools/testing/selftests/ftrace/:# of passed: 28 # of failed: 1 # of unresolved: 0 # of untested: 0 # of unsupported: 38 # of xfailed: 0 # of undefined(test bug): 0The failed case is func-filter-glob.tc.
When setting the '*aw*lock' to theset_ftrace_filterin this test case, we got the error because we have no these functions such as_raw_spin_lock,_raw_spin_trylockand so on in our kernel.Zong Li (6):
nds32/ftrace: Support static function tracer nds32/ftrace: Support static function graph tracer nds32/ftrace: AddRECORD_MCOUNTsupport
nds32/ftrace: Support dynamic function tracer nds32/ftrace: Support dynamic function graph tracer nds32/stack: Get real return address by usingftrace_graph_ret_addr
Quoted 11 lines
arch/nds32/Kconfig | 4 + arch/nds32/Makefile | 4 + arch/nds32/include/asm/ftrace.h | 46 +++++++ arch/nds32/kernel/Makefile | 6 + arch/nds32/kernel/ftrace.c | 297 ++++++++++++++++++++++++++++++++++++++++ arch/nds32/kernel/stacktrace.c | 4 + arch/nds32/kernel/traps.c | 30 +--- scripts/recordmcount.pl | 3 + 8 files changed, 370 insertions(+), 24 deletions(-) create mode 100644 arch/nds32/include/asm/ftrace.h create mode 100644 arch/nds32/kernel/ftrace.c