From 09427698b379dbb6b7ffdc61e648f4542c45dd6e Mon Sep 17 00:00:00 2001 From: Bruno Mauricio Date: Wed, 22 Nov 2023 15:59:41 +0000 Subject: [PATCH 1/2] ARCv2: Support ftrace and function graph tracer Added support for both FTRACE and FUNCTION_GRAPH_TRACER (GCC > 14) in ARCv2 Signed-off-by: Bruno Mauricio --- arch/arc/Kconfig | 2 + arch/arc/kernel/Makefile | 10 +++++ arch/arc/kernel/ftrace.c | 31 +++++++++++++ arch/arc/kernel/mcount.S | 94 ++++++++++++++++++++++++++++++++++++++++ 4 files changed, 137 insertions(+) create mode 100644 arch/arc/kernel/ftrace.c create mode 100644 arch/arc/kernel/mcount.S diff --git a/arch/arc/Kconfig b/arch/arc/Kconfig index 6ede84ff987835..4bfbe8f7da29cc 100644 --- a/arch/arc/Kconfig +++ b/arch/arc/Kconfig @@ -32,6 +32,8 @@ config ARC select HAVE_ARCH_TRANSPARENT_HUGEPAGE if ARC_MMU_V4 select HAVE_DEBUG_STACKOVERFLOW select HAVE_DEBUG_KMEMLEAK + select HAVE_FUNCTION_TRACER if ISA_ARCV2 + select HAVE_FUNCTION_GRAPH_TRACER if (ISA_ARCV2 && GCC_VERSION >= 140000) select HAVE_FUTEX_CMPXCHG if FUTEX select HAVE_IOREMAP_PROT if !(ISA_ARCV3 && !64BIT) select HAVE_KERNEL_GZIP diff --git a/arch/arc/kernel/Makefile b/arch/arc/kernel/Makefile index c16243d8749586..6c097d25cf9586 100644 --- a/arch/arc/kernel/Makefile +++ b/arch/arc/kernel/Makefile @@ -7,6 +7,16 @@ obj-y := arcksyms.o setup.o irq.o reset.o ptrace.o process.o devtree.o obj-y += signal.o traps.o sys.o troubleshoot.o stacktrace.o disasm.o obj-y += ctx_sw_asm.o +ifdef CONFIG_FTRACE +# ftrace can't be traced (infinite loop) +CFLAGS_REMOVE_ftrace.o = -pg +CFLAGS_REMOVE_mcount.o = -pg + +obj-$(CONFIG_FUNCTION_TRACER) += mcount.o +obj-$(CONFIG_FUNCTION_GRAPH_TRACER) += ftrace.o + +endif + ifdef CONFIG_ISA_ARCOMPACT obj-y += intc-compact.o else diff --git a/arch/arc/kernel/ftrace.c b/arch/arc/kernel/ftrace.c new file mode 100644 index 00000000000000..c93a1fbcb04b06 --- /dev/null +++ b/arch/arc/kernel/ftrace.c @@ -0,0 +1,31 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Function tracing support for ARC + * + * Copyright (C) 2023 Synopsys, Inc. (www.synopsys.com) + */ + +#include + +#ifdef CONFIG_FUNCTION_GRAPH_TRACER + +/* + * Setup return hook in traced routine + * Function copied from riscv + */ +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; + + if (unlikely(atomic_read(¤t->tracing_graph_pause))) + return; + + old = *parent; + + if (!function_graph_enter(old, self_addr, frame_pointer, parent)) + *parent = return_hooker; +} + +#endif /* CONFIG_FUNCTION_GRAPH_TRACER */ diff --git a/arch/arc/kernel/mcount.S b/arch/arc/kernel/mcount.S new file mode 100644 index 00000000000000..c78899cd0cc4d3 --- /dev/null +++ b/arch/arc/kernel/mcount.S @@ -0,0 +1,94 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Function tracing support for ARC + * + * Copyright (C) 2023 Synopsys, Inc. (www.synopsys.com) + */ + +#include +#include + +; ftrace placeholder, just return to caller +ENTRY(ftrace_stub) + j_s [blink] +ENDPROC(ftrace_stub) + +.macro SAVE_ABI + push blink +.endm + +.macro LOAD_ABI + pop blink +.endm + +.macro SAVE_ABI_RET + push r0 + push r1 +.endm + +.macro LOAD_ABI_RET + pop r1 + pop r0 +.endm + +; r0 has the frompc (targets parent ip) +; blink has the selfpc (target ip) +ENTRY(_mcount) + +#ifdef CONFIG_FUNCTION_GRAPH_TRACER + + ; *ftrace_graph_return != ftrace_stub + ld r3, [ftrace_graph_return] + brne r3, @ftrace_stub, @do_ftrace_graph_caller + ; *ftrace_graph_entry != *ftrace_graph_entry_stub + ld r3, [ftrace_graph_entry] + brne r3, @ftrace_graph_entry_stub, @do_ftrace_graph_caller + +#endif + + ; *ftrace_trace_function != ftrace_stub + ld r2, [ftrace_trace_function] + brne r2, @ftrace_stub, @do_trace + ; Return + j_s [blink] + +ENDPROC(_mcount) + +#ifdef CONFIG_FUNCTION_GRAPH_TRACER + +; Return to the actual caller +ENTRY(return_to_handler) + ; Save return value (if any) from handled routine + SAVE_ABI_RET + ; Will return true blink on r0 + jl ftrace_return_to_handler + mov r2, r0 + LOAD_ABI_RET + j [r2] + +ENDPROC(return_to_handler) + +do_ftrace_graph_caller: + ; ABI does not allow us to infer blink location + ; ARC GCC port inserts into r1 the delta between the pushed blink and + ; the sp at call time + ; We perform calculation before any push (sp change) happens + add r0, r1, sp + SAVE_ABI + sub r0, r0, 4 + mov r1, blink + jl prepare_ftrace_return + LOAD_ABI + j_s [blink] +#endif + +do_trace: + SAVE_ABI + mov r1, r0 + mov r0, blink + jl [r2] + ; load ABI state and jump to blink (in stack) + LOAD_ABI + j_s [blink] + +EXPORT_SYMBOL(_mcount) From cba6505416ee028a6707c37cda22f6acf79e9d36 Mon Sep 17 00:00:00 2001 From: Bruno Mauricio Date: Wed, 22 Nov 2023 16:32:53 +0000 Subject: [PATCH 2/2] ARCv3: Support ftrace and function graph tracer Signed-off-by: Bruno Mauricio --- arch/arc/Kconfig | 4 +-- arch/arc/Makefile | 6 +++++ arch/arc/kernel/mcount.S | 58 ++++++++++++++++++++++++++-------------- 3 files changed, 46 insertions(+), 22 deletions(-) diff --git a/arch/arc/Kconfig b/arch/arc/Kconfig index 4bfbe8f7da29cc..02e3b7e4807680 100644 --- a/arch/arc/Kconfig +++ b/arch/arc/Kconfig @@ -32,8 +32,8 @@ config ARC select HAVE_ARCH_TRANSPARENT_HUGEPAGE if ARC_MMU_V4 select HAVE_DEBUG_STACKOVERFLOW select HAVE_DEBUG_KMEMLEAK - select HAVE_FUNCTION_TRACER if ISA_ARCV2 - select HAVE_FUNCTION_GRAPH_TRACER if (ISA_ARCV2 && GCC_VERSION >= 140000) + select HAVE_FUNCTION_TRACER if (ISA_ARCV2 || ISA_ARCV3) + select HAVE_FUNCTION_GRAPH_TRACER if ISA_ARCV3 || (ISA_ARCV2 && GCC_VERSION >= 140000) select HAVE_FUTEX_CMPXCHG if FUTEX select HAVE_IOREMAP_PROT if !(ISA_ARCV3 && !64BIT) select HAVE_KERNEL_GZIP diff --git a/arch/arc/Makefile b/arch/arc/Makefile index 03dd4ba4dc2b6f..1a809ff65e6d22 100644 --- a/arch/arc/Makefile +++ b/arch/arc/Makefile @@ -19,6 +19,12 @@ endif endif endif +ifdef CONFIG_FTRACE +ifdef CONFIG_ISA_ARCV3 +cflags-y += -fno-omit-frame-pointer +endif +endif + ifdef CONFIG_ISA_ARCV3 ifdef CONFIG_64BIT UTS_MACHINE := arc64 diff --git a/arch/arc/kernel/mcount.S b/arch/arc/kernel/mcount.S index c78899cd0cc4d3..20ab11b0dacdc4 100644 --- a/arch/arc/kernel/mcount.S +++ b/arch/arc/kernel/mcount.S @@ -7,6 +7,7 @@ #include #include +#include ; ftrace placeholder, just return to caller ENTRY(ftrace_stub) @@ -14,21 +15,23 @@ ENTRY(ftrace_stub) ENDPROC(ftrace_stub) .macro SAVE_ABI - push blink + PUSHR blink + PUSHR fp .endm .macro LOAD_ABI - pop blink + POPR fp + POPR blink .endm .macro SAVE_ABI_RET - push r0 - push r1 + PUSHR r0 + PUSHR r1 .endm .macro LOAD_ABI_RET - pop r1 - pop r0 + POPR r1 + POPR r0 .endm ; r0 has the frompc (targets parent ip) @@ -38,17 +41,23 @@ ENTRY(_mcount) #ifdef CONFIG_FUNCTION_GRAPH_TRACER ; *ftrace_graph_return != ftrace_stub - ld r3, [ftrace_graph_return] - brne r3, @ftrace_stub, @do_ftrace_graph_caller + MOVA r3, ftrace_graph_return + LDR r3, r3 + MOVA r4, @ftrace_stub + brne r3, r4, @do_ftrace_graph_caller ; *ftrace_graph_entry != *ftrace_graph_entry_stub - ld r3, [ftrace_graph_entry] - brne r3, @ftrace_graph_entry_stub, @do_ftrace_graph_caller + MOVA r3, @ftrace_graph_entry + LDR r3, r3 + MOVA r4, @ftrace_graph_entry_stub + brne r3, r4, @do_ftrace_graph_caller #endif ; *ftrace_trace_function != ftrace_stub - ld r2, [ftrace_trace_function] - brne r2, @ftrace_stub, @do_trace + MOVA r2, ftrace_trace_function + LDR r2, r2 + MOVA r3, @ftrace_stub + brne r2, r3, @do_trace ; Return j_s [blink] @@ -61,31 +70,40 @@ ENTRY(return_to_handler) ; Save return value (if any) from handled routine SAVE_ABI_RET ; Will return true blink on r0 - jl ftrace_return_to_handler - mov r2, r0 + MOVA r0, @ftrace_return_to_handler + jl [r0] + MOVR r2, r0 LOAD_ABI_RET j [r2] ENDPROC(return_to_handler) do_ftrace_graph_caller: + +#ifndef CONFIG_ISA_ARCV3 ; ABI does not allow us to infer blink location ; ARC GCC port inserts into r1 the delta between the pushed blink and ; the sp at call time ; We perform calculation before any push (sp change) happens - add r0, r1, sp + ADDR r0, r1, sp + SAVE_ABI + SUBR r0, r0, REGSZASM +#else SAVE_ABI - sub r0, r0, 4 - mov r1, blink - jl prepare_ftrace_return + ADDR r0, fp, REGSZASM +#endif + + MOVR r1, blink + MOVA r2, @prepare_ftrace_return + jl [r2] LOAD_ABI j_s [blink] #endif do_trace: SAVE_ABI - mov r1, r0 - mov r0, blink + MOVR r1, r0 + MOVR r0, blink jl [r2] ; load ABI state and jump to blink (in stack) LOAD_ABI