* [PATCH 0/1] Add the basic static ftrace support
@ 2025-09-09 3:12 ChenMiao
2025-09-09 3:12 ` [PATCH 1/1] openrisc: " ChenMiao
0 siblings, 1 reply; 2+ messages in thread
From: ChenMiao @ 2025-09-09 3:12 UTC (permalink / raw)
To: Linux Kernel, Linux OpenRISC, Stafford Horne; +Cc: chenmiao
From: chenmiao <chenmiao.ku@gmail.com>
Hello erverone,
This patch contains basic ftrace support for OR1K platform.
Specifically, function tracer (HAVE_FUNCTION_TRACER), function graph
tracer (HAVE_FUNCTION_GRAPH_TRACER), and a frame pointer test
(HAVE_FUNCTION_GRAPH_FP_TEST) are implemented following the
instructions in Documentation/trace/ftrace-design.txt.
Below, I briefly explain why FTRACE_GRAPH was not enabled.
During testing, it was found that when fgraph is used with static ftrace,
it calls the ftrace_startup_subops function. This function is used by
register_ftrace_graph and always returns the EINVAL value in the case of
static ftrace. So, we disable the fgraph. *If re-initialization is attempted,
it may lead to severe consequences*, leading to the following issues:
[ 76.040000] ------------[ cut here ]------------
[ 76.040000] WARNING: CPU: 0 PID: 140 at kernel/trace/fgraph.c:1328 register_ftrace_graph+0x750/0x7e4
[ 76.040000] function graph ops registered again
[ 76.040000] Modules linked in:
[ 76.040000] CPU: 0 UID: 0 PID: 140 Comm: bash Not tainted 6.17.0-rc3-00014-gda230ee3ff1c #1 NONE
[ 76.040000] Call trace:
[ 76.040000] [<0b43fbe5>] dump_stack_lvl+0x8c/0xc4
[ 76.040000] [<d2655aeb>] ? register_ftrace_graph+0x750/0x7e4
[ 76.040000] [<22405ca2>] dump_stack+0x1c/0x2c
[ 76.040000] [<04b97f00>] __warn+0xcc/0x1ac
[ 76.040000] [<d2655aeb>] ? register_ftrace_graph+0x750/0x7e4
[ 76.040000] [<34636c77>] warn_slowpath_fmt+0x1e8/0x1f0
[ 76.040000] [<d2655aeb>] register_ftrace_graph+0x750/0x7e4
[ 76.040000] [<94bcf66b>] ? do_ftrace_graph_caller+0x2c/0x40
[ 76.040000] [<863d51d0>] ? _raw_spin_unlock_irqrestore+0x3c/0x50
[ 76.040000] [<5e3d7fcf>] graph_trace_init+0x60/0xa0
[ 76.040000] [<239e8587>] tracing_set_tracer+0x180/0x29c
[ 76.040000] [<0bedd84e>] ? mutex_unlock+0x24/0x80
[ 76.040000] [<21c17ace>] tracing_set_trace_write+0xa4/0x118
[ 76.040000] [<0d244535>] vfs_write+0x108/0x5ac
[ 76.040000] [<94bcf66b>] ? do_ftrace_graph_caller+0x2c/0x40
[ 76.040000] [<c15d06f8>] ? fdget_pos+0x20/0x210
[ 76.040000] [<bc6b8897>] ksys_write+0x94/0x150
[ 76.040000] [<06a3d204>] sys_write+0x38/0x4c
[ 76.040000] [<2cd910fd>] ? _syscall_return+0x0/0x4
[ 76.040000] ---[ end trace 0000000000000000 ]---
Thanks,
Chen Miao
chenmiao (1):
openrisc: Add the basic static ftrace support
arch/openrisc/Kconfig | 1 +
arch/openrisc/configs/or1ksim_defconfig | 2 +-
arch/openrisc/configs/virt_defconfig | 1 +
arch/openrisc/include/asm/ftrace.h | 29 ++++
arch/openrisc/kernel/Makefile | 7 +
arch/openrisc/kernel/entry-ftrace.S | 185 ++++++++++++++++++++++++
arch/openrisc/kernel/ftrace.c | 35 +++++
7 files changed, 259 insertions(+), 1 deletion(-)
create mode 100644 arch/openrisc/include/asm/ftrace.h
create mode 100644 arch/openrisc/kernel/entry-ftrace.S
create mode 100644 arch/openrisc/kernel/ftrace.c
--
2.45.2
^ permalink raw reply [flat|nested] 2+ messages in thread
* [PATCH 1/1] openrisc: Add the basic static ftrace support
2025-09-09 3:12 [PATCH 0/1] Add the basic static ftrace support ChenMiao
@ 2025-09-09 3:12 ` ChenMiao
0 siblings, 0 replies; 2+ messages in thread
From: ChenMiao @ 2025-09-09 3:12 UTC (permalink / raw)
To: Linux Kernel, Linux OpenRISC, Stafford Horne; +Cc: chenmiao
From: chenmiao <chenmiao.ku@gmail.com>
This patch contains basic ftrace support for OR1K platform.
Specifically, function tracer (HAVE_FUNCTION_TRACER), function graph
tracer (HAVE_FUNCTION_GRAPH_TRACER), and a frame pointer test
(HAVE_FUNCTION_GRAPH_FP_TEST) are implemented following the
instructions in Documentation/trace/ftrace-design.txt.
Note that the functions in both ftrace.c and setup.c should not be
hooked with the compiler's -pg option: to prevent infinite self-
referencing for the former, and to ignore early setup stuff for the
latter.
Currently, dynamic ftrace has not been implemented yet. Directly
porting the existing dynamic ftrace would require significant effort.
If we want to minimally support dynamic ftrace, some APIs have changed,
making it temporarily unsuccessful to port.
By enabling the built-in kselftest option and some necessary configs,
you can refer to the detailed steps provided in the link below for testing.
Link: https://github.com/ChenMiaoi/GSoC-2025-Final-Report/tree/main/tests/ftrace-test
Test Environment:
- Hardware: QEMU emulated OR1K
- Kernel Version: 6.17.0-rc3-dirty
- Configs: CONFIG_FTRACE=y,CONFIG_FUNCTION_TRACER=y,
CONFIG_RING_BUFFER_BENCHMARK=y,CONFIG_FTRACE_SELFTEST=y,
CONFIG_FTRACE_STARTUP_TEST=y,CONFIG_EVENT_TRACE_STARTUP_TEST=y,
CONFIG_EVENT_TRACE_TEST_SYSCALLS=y,CONFIG_TIMER_TRACER=y,
CONFIG_OSNOISE_TRACER=y,CONFIG_TRACER_MAX_TRACE=y,
CONFIG_TRACE_EVENT_INJECT=y
- Toolchain: or1k-none-linux-musl-gcc 15.1.0
Test Result:
cat trace
tracer: function
entries-in-buffer/entries-written: 72039/30671200 #P:1
_-----=> irqs-off/BH-disabled
/ _----=> need-resched
| / _---=> hardirq/softirq
|| / _--=> preempt-depth
||| / _-=> migrate-disable
|||| / delay
TASK-PID CPU# ||||| TIMESTAMP FUNCTIO
| | | ||||| | |
bash-142 [000] ..... 290.910000: ksys_read <-sys_read
bash-142 [000] ..... 290.910000: fdget_pos <-ksys_read
bash-142 [000] ..... 290.910000: vfs_read <-ksys_read
bash-142 [000] ..... 290.910000: sys_pselect6 <-_syscall_return
bash-142 [000] ..... 290.910000: get_timespec64 <-sys_pselect6
bash-142 [000] ..... 290.910000: poll_select_set_timeout <-sys_pselect6
bash-142 [000] ..... 290.910000: set_user_sigmask <-sys_pselect6
bash-142 [000] ..... 290.910000: core_sys_select <-sys_pselect6
This change combines techniques from:
- commit 819e50e25d0c ("arm64: Add ftrace support")
- commit 10626c32e382 ("riscv/ftrace: Add basic support")
Signed-off-by: chenmiao <chenmiao.ku@gmail.com>
---
arch/openrisc/Kconfig | 1 +
arch/openrisc/configs/or1ksim_defconfig | 2 +-
arch/openrisc/configs/virt_defconfig | 1 +
arch/openrisc/include/asm/ftrace.h | 29 ++++
arch/openrisc/kernel/Makefile | 7 +
arch/openrisc/kernel/entry-ftrace.S | 185 ++++++++++++++++++++++++
arch/openrisc/kernel/ftrace.c | 35 +++++
7 files changed, 259 insertions(+), 1 deletion(-)
create mode 100644 arch/openrisc/include/asm/ftrace.h
create mode 100644 arch/openrisc/kernel/entry-ftrace.S
create mode 100644 arch/openrisc/kernel/ftrace.c
diff --git a/arch/openrisc/Kconfig b/arch/openrisc/Kconfig
index 9156635dd264..a274e95a84cb 100644
--- a/arch/openrisc/Kconfig
+++ b/arch/openrisc/Kconfig
@@ -26,6 +26,7 @@ config OPENRISC
select GENERIC_CPU_DEVICES
select HAVE_ARCH_JUMP_LABEL
select HAVE_ARCH_JUMP_LABEL_RELATIVE
+ select HAVE_FUNCTION_TRACER
select HAVE_PCI
select HAVE_UID16
select HAVE_PAGE_SIZE_8KB
diff --git a/arch/openrisc/configs/or1ksim_defconfig b/arch/openrisc/configs/or1ksim_defconfig
index 769705ac24d5..12a2e31e6363 100644
--- a/arch/openrisc/configs/or1ksim_defconfig
+++ b/arch/openrisc/configs/or1ksim_defconfig
@@ -7,7 +7,6 @@ CONFIG_EXPERT=y
# CONFIG_TIMERFD is not set
# CONFIG_EVENTFD is not set
# CONFIG_AIO is not set
-# CONFIG_KALLSYMS is not set
CONFIG_BUILTIN_DTB_NAME="or1ksim"
CONFIG_HZ_100=y
CONFIG_JUMP_LABEL=y
@@ -49,3 +48,4 @@ CONFIG_SERIAL_OF_PLATFORM=y
# CONFIG_DNOTIFY is not set
CONFIG_TMPFS=y
CONFIG_NFS_FS=y
+CONFIG_STACK_TRACER=y
diff --git a/arch/openrisc/configs/virt_defconfig b/arch/openrisc/configs/virt_defconfig
index a93a3e1e4f87..08cfcdd60033 100644
--- a/arch/openrisc/configs/virt_defconfig
+++ b/arch/openrisc/configs/virt_defconfig
@@ -106,3 +106,4 @@ CONFIG_UNICODE=y
CONFIG_PRINTK_TIME=y
CONFIG_DYNAMIC_DEBUG=y
CONFIG_FTRACE=y
+CONFIG_STACK_TRACER=y
diff --git a/arch/openrisc/include/asm/ftrace.h b/arch/openrisc/include/asm/ftrace.h
new file mode 100644
index 000000000000..d7691a351ee7
--- /dev/null
+++ b/arch/openrisc/include/asm/ftrace.h
@@ -0,0 +1,29 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright (C) 2017 Andes Technology Corporation
+ * Copyright (C) 2025 Chen Miao
+ */
+
+#include "linux/export.h"
+#include <asm/insn-def.h>
+
+#ifndef __ASM_OPENRISC_FTRACE_H
+#define __ASM_OPENRISC_FTRACE_H
+
+#if defined(CONFIG_FUNCTION_GRAPH_TRACER) && defined(CONFIG_FRAME_POINTER)
+#define HAVE_FUNCTION_GRAPH_FP_TEST
+#endif
+
+#define MCOUNT_ADDR ((unsigned long)_mcount)
+#define MCOUNT_INSN_SIZE OPENRISC_INSN_SIZE
+
+#ifndef __ASSEMBLER__
+extern void _mcount(void);
+
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+extern void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr,
+ unsigned long frame_pointer);
+#endif /* ifdef CONFIG_FUNCTION_GRAPH_TRACER */
+
+#endif /* __ASSEMBLER__ */
+
+#endif /* __ASM_OPENRISC_FTRACE_H */
diff --git a/arch/openrisc/kernel/Makefile b/arch/openrisc/kernel/Makefile
index 19e0eb94f2eb..9a4ef72380ed 100644
--- a/arch/openrisc/kernel/Makefile
+++ b/arch/openrisc/kernel/Makefile
@@ -3,12 +3,19 @@
# Makefile for the linux kernel.
#
+ifdef CONFIG_FTRACE
+CFLAGS_REMOVE_ftrace.o = -pg
+CFLAGS_REMOVE_setup.o = -pg
+endif
+
always-$(KBUILD_BUILTIN) := vmlinux.lds
obj-y := head.o setup.o or32_ksyms.o process.o dma.o \
traps.o time.o irq.o entry.o ptrace.o signal.o \
sys_call_table.o unwinder.o cacheinfo.o
+obj-$(CONFIG_FUNCTION_TRACER) += entry-ftrace.o
+obj-$(CONFIG_FUNCTION_GRAPH_TRACER) += ftrace.o
obj-$(CONFIG_JUMP_LABEL) += jump_label.o
obj-$(CONFIG_SMP) += smp.o sync-timer.o
obj-$(CONFIG_STACKTRACE) += stacktrace.o
diff --git a/arch/openrisc/kernel/entry-ftrace.S b/arch/openrisc/kernel/entry-ftrace.S
new file mode 100644
index 000000000000..27acbbfe40f6
--- /dev/null
+++ b/arch/openrisc/kernel/entry-ftrace.S
@@ -0,0 +1,185 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright (C) 2017 Andes Technology Corporation
+ * Copyright (C) 2025 Chen Miao
+ */
+
+#include <linux/init.h>
+#include <linux/linkage.h>
+#include <linux/cfi_types.h>
+#include <asm/ftrace.h>
+
+ .text
+
+ .macro SAVE_ABI_STATE
+ l.addi r1, r1, -8 /* Allocate 8 bytes stack space */
+ l.sw 0(r1), r2 /* Save frame pointer (r2) */
+ l.sw 4(r1), r9 /* Save return address (r9) */
+ l.addi r2, r1, 8 /* Set new frame pointer */
+ .endm
+
+ .macro SAVE_RET_ABI_STATE
+ l.addi r1, r1, -16
+ l.sw 0(r1), r2
+ l.sw 4(r1), r9
+ l.sw 8(r1), r11 /* Save function return value (r11) */
+ l.sw 12(r1), r3
+ l.addi r2, r1, 16
+ .endm
+
+ .macro RESTORE_ABI_STATE
+ l.lwz r9, 4(r1) /* Restore return address (r9) */
+ l.lwz r2, 0(r1) /* Restore frame pointer (r2) */
+ l.addi r1, r1, 8 /* Free stack space */
+ .endm
+
+ .macro RESTORE_RET_ABI_STATE
+ l.lwz r3, 12(r1)
+ l.lwz r11, 8(r1) /* Restore function return value (r11) */
+ l.lwz r9, 4(r1)
+ l.lwz r2, 0(r1)
+ l.addi r1, r1, 16
+ .endm
+
+ .macro LOAD_FUNCTION reg func
+ l.movhi \reg, hi(\func)
+ l.ori \reg, \reg, lo(\func)
+ l.lwz \reg, 0(\reg)
+ .endm
+
+/*
+ * void ftrace_stub(void)
+ * {
+ * return;
+ * }
+ */
+SYM_TYPED_FUNC_START(ftrace_stub)
+ l.jr r9
+ l.nop
+SYM_FUNC_END(ftrace_stub)
+
+#if CONFIG_FUNCTION_GRAPH_TRACER
+SYM_TYPED_FUNC_START(return_to_handler)
+ /*
+ * void return_to_handler(void)
+ * {
+ * save all state needed by the API
+ * void (*original_return_point)(void) = ftrace_return_to_handler();
+ * restore all state needed by the ABI
+ *
+ * original_return_point();
+ * }
+ */
+#ifdef HAVE_FUNCTION_GRAPH_FP_TEST
+ l.or r27, r2, r2
+#endif
+ SAVE_RET_ABI_STATE
+#ifdef HAVE_FUNCTION_GRAPH_FP_TEST
+ l.or r3, r27, r27
+#endif
+
+ LOAD_FUNCTION r17 ftrace_return_to_handler
+ l.jalr r17
+ l.nop
+
+ l.or r19, r0, r11
+
+ RESTORE_RET_ABI_STATE
+
+ l.jalr r19
+ l.nop
+SYM_FUNC_END(return_to_handler)
+#endif
+
+SYM_TYPED_FUNC_START(_mcount)
+ /*
+ * void mcount(void)
+ * {
+ * if (ftrace_trace_function != ftrace_stub)
+ * goto do_trace;
+ * return;
+ */
+ LOAD_FUNCTION r15, ftrace_stub
+
+#if CONFIG_FUNCTION_GRAPH_TRACER
+ /*
+ * extern void (*ftrace_graph_return)(...);
+ * extern void (*ftrace_graph_entry)(...);
+ * if (ftrace_graph_return != ftrace_stub ||
+ * ftrace_graph_entry != ftrace_graph_entry_stub)
+ * ftrace_graph_caller();
+ */
+ LOAD_FUNCTION r17, ftrace_graph_return
+ l.sfne r17, r15
+ l.bf do_ftrace_graph_caller
+ l.nop
+
+ LOAD_FUNCTION r19, ftrace_graph_entry
+ LOAD_FUNCTION r21, ftrace_graph_entry_stub
+ l.sfne r21, r19
+ l.bf do_ftrace_graph_caller
+ l.nop
+#endif
+
+ LOAD_FUNCTION r29, ftrace_trace_function
+ l.sfne r29, r15
+ l.bf do_trace
+ l.nop
+
+ l.jr r9
+ l.nop
+
+#if CONFIG_FUNCTION_GRAPH_TRACER
+ /*
+ * void ftrace_graph_caller(void)
+ * {
+ * save all state needed by the ABI
+ * unsigned long *frompc = &...;
+ * unsigned long selfpc = <return address> - MCOUNT_INSN_SIZE;
+ * passing frame pointer up is optional -- see below
+ * prepare_ftrace_return(frompc, selfpc, frame_pointer);
+ * restore all state needed by the ABI
+ * }
+ */
+do_ftrace_graph_caller:
+ l.addi r3, r2, -4
+ l.or r4, r1, r1
+#ifdef HAVE_FUNCTION_GRAPH_FP_TEST
+ l.lwz r5, -8(r2)
+#endif
+ SAVE_ABI_STATE
+
+ /*
+ * DO NOT USE LOAD_FUNCTION r23 prepare_ftrace_return instead of bare asm
+ * because the prepare_ftrace_return's address already store in the r23,
+ * if use l.lwz r23, 0(r23), it will load the first insn of r23.
+ */
+ l.movhi r23, hi(prepare_ftrace_return)
+ l.ori r23, r23, lo(prepare_ftrace_return)
+ l.jalr r23
+ l.nop
+
+ RESTORE_ABI_STATE
+
+ l.jr r9
+ l.nop
+#endif
+
+ /*
+ * do_trace:
+ * save all need ABI state
+ * ftrace_trace_function(ra_to_caller, ra_to_caller_of_caller);
+ * restore ABI state
+ */
+do_trace:
+ l.lwz r4, -4(r2)
+ l.or r3, r9, r9
+
+ SAVE_ABI_STATE
+ l.jalr r29
+ l.nop
+ RESTORE_ABI_STATE
+
+ l.jr r9
+ l.nop
+SYM_FUNC_END(_mcount)
+EXPORT_SYMBOL(_mcount)
diff --git a/arch/openrisc/kernel/ftrace.c b/arch/openrisc/kernel/ftrace.c
new file mode 100644
index 000000000000..2b92bd580230
--- /dev/null
+++ b/arch/openrisc/kernel/ftrace.c
@@ -0,0 +1,35 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2013 Linaro Limited
+ * Author: AKASHI Takahiro <takahiro.akashi@linaro.org>
+ * Copyright (C) 2017 Andes Technology Corporation
+ * Copyright (C) 2025 Chen Miao
+ */
+
+#include <linux/ftrace.h>
+
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+/*
+ * Most of this function is copied from arm64. However, the main porting work
+ * referred to RISC-V.
+ */
+void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr,
+ unsigned long frame_pointer)
+{
+ return;
+ unsigned long return_hooker = (unsigned long)&return_to_handler;
+ unsigned long old;
+
+ if (unlikely(atomic_read(¤t->tracing_graph_pause)))
+ return;
+
+ /*
+ * We don't suffer access faults, so no extra fault-recovery assembly
+ * is needed here.
+ */
+ old = *parent;
+
+ if (!function_graph_enter(old, self_addr, frame_pointer, parent))
+ *parent = return_hooker;
+}
+#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
--
2.45.2
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2025-09-09 3:12 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2025-09-09 3:12 [PATCH 0/1] Add the basic static ftrace support ChenMiao
2025-09-09 3:12 ` [PATCH 1/1] openrisc: " ChenMiao
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®