diff --git a/arch/s390/include/asm/ftrace.h b/arch/s390/include/asm/ftrace.h index 836c56290499..64053d9ac3f2 100644 --- a/arch/s390/include/asm/ftrace.h +++ b/arch/s390/include/asm/ftrace.h @@ -12,7 +12,9 @@ #ifndef __ASSEMBLY__ -#define ftrace_return_address(n) __builtin_return_address(n) +unsigned long return_address(int depth); + +#define ftrace_return_address(n) return_address(n) void _mcount(void); void ftrace_caller(void); diff --git a/arch/s390/kernel/dumpstack.c b/arch/s390/kernel/dumpstack.c index 1b6081c0aff9..69f9908ac44c 100644 --- a/arch/s390/kernel/dumpstack.c +++ b/arch/s390/kernel/dumpstack.c @@ -89,6 +89,30 @@ void dump_trace(dump_trace_func_t func, void *data, struct task_struct *task, } EXPORT_SYMBOL_GPL(dump_trace); +struct return_address_data { + unsigned long address; + int depth; +}; + +static int __return_address(void *data, unsigned long address) +{ + struct return_address_data *rd = data; + + if (rd->depth--) + return 0; + rd->address = address; + return 1; +} + +unsigned long return_address(int depth) +{ + struct return_address_data rd = { .depth = depth + 2 }; + + dump_trace(__return_address, &rd, NULL, current_stack_pointer()); + return rd.address; +} +EXPORT_SYMBOL_GPL(return_address); + static int show_address(void *data, unsigned long address) { printk("([<%016lx>] %pSR)\n", address, (void *)address);