CALLER_ADDRx returns caller's address at specified level in call stacks. They are used for several tracers like irqsoff and preemptoff. do_vint irqentry_exit trace_hardirqs_on tracer_hardirqs_on(CALLER_ADDR0, CALLER_ADDR1) Signed-off-by: Qing Zhang <zhangqing@xxxxxxxxxxx> --- arch/loongarch/include/asm/ftrace.h | 2 ++ arch/loongarch/include/asm/processor.h | 2 -- arch/loongarch/kernel/Makefile | 4 +-- arch/loongarch/kernel/return_address.c | 45 ++++++++++++++++++++++++++ 4 files changed, 49 insertions(+), 4 deletions(-) create mode 100644 arch/loongarch/kernel/return_address.c diff --git a/arch/loongarch/include/asm/ftrace.h b/arch/loongarch/include/asm/ftrace.h index f96adef0e4a5..6afc9fc712f4 100644 --- a/arch/loongarch/include/asm/ftrace.h +++ b/arch/loongarch/include/asm/ftrace.h @@ -16,6 +16,8 @@ #define MCOUNT_INSN_SIZE 4 /* sizeof mcount call */ #ifndef __ASSEMBLY__ +extern void *return_address(unsigned int); +#define ftrace_return_address(n) return_address(n) #ifndef CONFIG_DYNAMIC_FTRACE extern void _mcount(void); #define mcount _mcount diff --git a/arch/loongarch/include/asm/processor.h b/arch/loongarch/include/asm/processor.h index 1c4b4308378d..5eb45e55f3c7 100644 --- a/arch/loongarch/include/asm/processor.h +++ b/arch/loongarch/include/asm/processor.h @@ -201,8 +201,6 @@ unsigned long __get_wchan(struct task_struct *p); #define KSTK_EUEN(tsk) (task_pt_regs(tsk)->csr_euen) #define KSTK_ECFG(tsk) (task_pt_regs(tsk)->csr_ecfg) -#define return_address() ({__asm__ __volatile__("":::"$1"); __builtin_return_address(0);}) - #ifdef CONFIG_CPU_HAS_PREFETCH #define ARCH_HAS_PREFETCH diff --git a/arch/loongarch/kernel/Makefile b/arch/loongarch/kernel/Makefile index a73599619466..9a3df7c1f6e8 100644 --- a/arch/loongarch/kernel/Makefile +++ b/arch/loongarch/kernel/Makefile @@ -6,8 +6,8 @@ extra-y := head.o vmlinux.lds obj-y += cpu-probe.o cacheinfo.o env.o setup.o entry.o genex.o \ - traps.o irq.o idle.o process.o dma.o mem.o io.o reset.o switch.o \ - elf.o syscall.o signal.o time.o topology.o inst.o ptrace.o vdso.o + traps.o irq.o idle.o process.o dma.o mem.o io.o reset.o return_address.o \ + switch.o elf.o syscall.o signal.o time.o topology.o inst.o ptrace.o vdso.o obj-$(CONFIG_ACPI) += acpi.o obj-$(CONFIG_EFI) += efi.o diff --git a/arch/loongarch/kernel/return_address.c b/arch/loongarch/kernel/return_address.c new file mode 100644 index 000000000000..ed8121dd2b0f --- /dev/null +++ b/arch/loongarch/kernel/return_address.c @@ -0,0 +1,45 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2022 Loongson Technology Corporation Limited + */ + +#include <linux/export.h> +#include <linux/ftrace.h> +#include <linux/kprobes.h> +#include <linux/stacktrace.h> + +struct return_address_data { + unsigned int level; + void *addr; +}; + +static bool save_return_addr(void *d, unsigned long pc) +{ + struct return_address_data *data = d; + + if (!data->level) { + data->addr = (void *)pc; + return false; + } else { + --data->level; + return true; + } +} +NOKPROBE_SYMBOL(save_return_addr); + +void *return_address(unsigned int level) +{ + struct return_address_data data; + + data.level = level + 2; + data.addr = NULL; + + arch_stack_walk(save_return_addr, &data, current, NULL); + + if (!data.level) + return data.addr; + else + return NULL; +} +EXPORT_SYMBOL_GPL(return_address); +NOKPROBE_SYMBOL(return_address); -- 2.36.1