Skip to content

Commit 6803413

Browse files
zongboxpalmer-dabbelt
authored andcommitted
riscv: add CALLER_ADDRx support
CALLER_ADDRx returns caller's address at specified level, they are used for several tracers. These macros eventually use __builtin_return_address(n) to get the caller's address if arch doesn't define their own implementation. In RISC-V, __builtin_return_address(n) only works when n == 0, we need to walk the stack frame to get the caller's address at specified level. data.level started from 'level + 3' due to the call flow of getting caller's address in RISC-V implementation. If we don't have additional three iteration, the level is corresponding to follows: callsite -> return_address -> arch_stack_walk -> walk_stackframe | | | | level 3 level 2 level 1 level 0 Fixes: 10626c3 ("riscv/ftrace: Add basic support") Cc: stable@vger.kernel.org Reviewed-by: Alexandre Ghiti <alexghiti@rivosinc.com> Signed-off-by: Zong Li <zong.li@sifive.com> Link: https://lore.kernel.org/r/20240202015102.26251-1-zong.li@sifive.com Signed-off-by: Palmer Dabbelt <palmer@rivosinc.com>
1 parent 4af2414 commit 6803413

3 files changed

Lines changed: 55 additions & 0 deletions

File tree

arch/riscv/include/asm/ftrace.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,11 @@
2525

2626
#define ARCH_SUPPORTS_FTRACE_OPS 1
2727
#ifndef __ASSEMBLY__
28+
29+
extern void *return_address(unsigned int level);
30+
31+
#define ftrace_return_address(n) return_address(n)
32+
2833
void MCOUNT_NAME(void);
2934
static inline unsigned long ftrace_call_adjust(unsigned long addr)
3035
{

arch/riscv/kernel/Makefile

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ ifdef CONFIG_FTRACE
77
CFLAGS_REMOVE_ftrace.o = $(CC_FLAGS_FTRACE)
88
CFLAGS_REMOVE_patch.o = $(CC_FLAGS_FTRACE)
99
CFLAGS_REMOVE_sbi.o = $(CC_FLAGS_FTRACE)
10+
CFLAGS_REMOVE_return_address.o = $(CC_FLAGS_FTRACE)
1011
endif
1112
CFLAGS_syscall_table.o += $(call cc-option,-Wno-override-init,)
1213
CFLAGS_compat_syscall_table.o += $(call cc-option,-Wno-override-init,)
@@ -46,6 +47,7 @@ obj-y += irq.o
4647
obj-y += process.o
4748
obj-y += ptrace.o
4849
obj-y += reset.o
50+
obj-y += return_address.o
4951
obj-y += setup.o
5052
obj-y += signal.o
5153
obj-y += syscall_table.o

arch/riscv/kernel/return_address.c

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
// SPDX-License-Identifier: GPL-2.0-only
2+
/*
3+
* This code come from arch/arm64/kernel/return_address.c
4+
*
5+
* Copyright (C) 2023 SiFive.
6+
*/
7+
8+
#include <linux/export.h>
9+
#include <linux/kprobes.h>
10+
#include <linux/stacktrace.h>
11+
12+
struct return_address_data {
13+
unsigned int level;
14+
void *addr;
15+
};
16+
17+
static bool save_return_addr(void *d, unsigned long pc)
18+
{
19+
struct return_address_data *data = d;
20+
21+
if (!data->level) {
22+
data->addr = (void *)pc;
23+
return false;
24+
}
25+
26+
--data->level;
27+
28+
return true;
29+
}
30+
NOKPROBE_SYMBOL(save_return_addr);
31+
32+
noinline void *return_address(unsigned int level)
33+
{
34+
struct return_address_data data;
35+
36+
data.level = level + 3;
37+
data.addr = NULL;
38+
39+
arch_stack_walk(save_return_addr, &data, current, NULL);
40+
41+
if (!data.level)
42+
return data.addr;
43+
else
44+
return NULL;
45+
46+
}
47+
EXPORT_SYMBOL_GPL(return_address);
48+
NOKPROBE_SYMBOL(return_address);

0 commit comments

Comments
 (0)