diff options
author | Heiko Carstens <heiko.carstens@de.ibm.com> | 2016-05-02 14:38:29 +0200 |
---|---|---|
committer | Martin Schwidefsky <schwidefsky@de.ibm.com> | 2016-05-04 16:29:45 +0200 |
commit | 5606330627ab680f5e6b7549d14ec3ffdae58c15 (patch) | |
tree | 5766fa5aa8375263757f24819219175ccf8cfaa5 /arch/s390/kernel/dumpstack.c | |
parent | s390/cpum_sf: Remove superfluous SMP function call (diff) | |
download | linux-5606330627ab680f5e6b7549d14ec3ffdae58c15.tar.xz linux-5606330627ab680f5e6b7549d14ec3ffdae58c15.zip |
s390/dumpstack: implement and use return_address()
Implement return_address() and use it instead of __builtin_return_address(n).
__builtin_return_address(n) is not guaranteed to work for n > 0,
therefore implement a private return_address() function which walks
the stack frames and returns the proper return address.
This way we get also rid of a compile warning which gcc 6.1 emits and
look like all other architectures.
Signed-off-by: Heiko Carstens <heiko.carstens@de.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Diffstat (limited to 'arch/s390/kernel/dumpstack.c')
-rw-r--r-- | arch/s390/kernel/dumpstack.c | 24 |
1 files changed, 24 insertions, 0 deletions
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); |