diff --git a/arch/arc/Kconfig b/arch/arc/Kconfig index 6ede84ff987835..498d94c2e02c1a 100644 --- a/arch/arc/Kconfig +++ b/arch/arc/Kconfig @@ -38,6 +38,8 @@ config ARC select HAVE_KERNEL_LZMA select HAVE_KPROBES select HAVE_KRETPROBES + select HAVE_FUNCTION_TRACER if ISA_ARCV3 + select HAVE_FUNCTION_GRAPH_TRACER if ISA_ARCV3 select HAVE_MOD_ARCH_SPECIFIC select HAVE_PERF_EVENTS select HANDLE_DOMAIN_IRQ diff --git a/arch/arc/Makefile b/arch/arc/Makefile index 03dd4ba4dc2b6f..c2351c45a90051 100644 --- a/arch/arc/Makefile +++ b/arch/arc/Makefile @@ -61,6 +61,10 @@ cflags-$(CONFIG_64BIT) += -mcmodel=large cflags-$(CONFIG_ARC_HAS_LL128) += -m128 endif +ifdef CONFIG_FTRACE +cflags-y += -fno-omit-frame-pointer +endif + cflags-y += -Wa,-I$(srctree)/arch/arc/include ifdef CONFIG_ARC_CURR_IN_REG diff --git a/arch/arc/kernel/Makefile b/arch/arc/kernel/Makefile index c16243d8749586..44a90f3382bdbf 100644 --- a/arch/arc/kernel/Makefile +++ b/arch/arc/kernel/Makefile @@ -13,6 +13,23 @@ else obj-y += intc-arcv2.o endif +ifdef CONFIG_FTRACE + +# Currently ftrace only works on arcv3 due to ABI +ifdef CONFIG_ISA_ARCV3 + +# ftrace cant 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 + +endif + obj-$(CONFIG_ISA_ARCOMPACT) += entry-compact.o obj-$(CONFIG_ISA_ARCV2) += entry-arcv2.o obj-$(CONFIG_ISA_ARCV3) += entry-arcv3.o diff --git a/arch/arc/kernel/ftrace.c b/arch/arc/kernel/ftrace.c new file mode 100644 index 00000000000000..e62595b123319f --- /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..ebd9f6f9d9dc97 --- /dev/null +++ b/arch/arc/kernel/mcount.S @@ -0,0 +1,119 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Function tracing support for ARC + * + * Copyright (C) 2023 Synopsys, Inc. (www.synopsys.com) + */ + + +#include +#include +#include +#include + +.text +; ftrace placeholder, just return to caller +ENTRY(ftrace_stub) + j_s [blink] +ENDPROC(ftrace_stub) + +; save ABI necessary registers +.macro SAVE_ABI + PUSHR blink + PUSHR fp +.endm + +.macro LOAD_ABI + POPR fp + POPR blink +.endm + +.macro SAVE_ABI_RET + PUSHR r0 + PUSHR r1 + PUSHR blink +.endm + +.macro LOAD_ABI_RET + POPR blink + POPR r1 + POPR r0 +.endm + +#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 + MOVA r0, @ftrace_return_to_handler + jl [r0] + + MOVR r2, r0 + + LOAD_ABI_RET + + j [r2] + +ENDPROC(return_to_handler) +#endif + +; 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 + MOVA r3, ftrace_graph_return + LD64 r3, r3 + MOVA r4, @ftrace_stub + brne r3, r4, @do_ftrace_graph_caller + + ; *ftrace_graph_entry != *ftrace_graph_entry_stub + MOVA r3, @ftrace_graph_entry + LD64 r3, r3 + MOVA r4, @ftrace_graph_entry_stub + brne r3, r4, @do_ftrace_graph_caller + +#endif + + ; *ftrace_trace_function != ftrace_stub + MOVA r2, ftrace_trace_function + LD64 r2, r2 + + MOVA r3, @ftrace_stub + brne r2, r3, @do_trace + + ; Return + j_s [blink] + +ENDPROC(_mcount) + +#ifdef CONFIG_FUNCTION_GRAPH_TRACER +do_ftrace_graph_caller: + +SAVE_ABI + + ADDR r0, fp, 8 + MOVR r1, blink + + MOVA r2, @prepare_ftrace_return + jl [r2] + +LOAD_ABI + + j_s [blink] +#endif + +do_trace: +SAVE_ABI + MOVR r1, r0 + MOVR r0, blink + + jl [r2] + +LOAD_ABI + j_s [blink]