summaryrefslogtreecommitdiffstats
path: root/arch/s390/kernel/dumpstack.c
diff options
context:
space:
mode:
authorHeiko Carstens <heiko.carstens@de.ibm.com>2016-05-02 14:38:29 +0200
committerMartin Schwidefsky <schwidefsky@de.ibm.com>2016-05-04 16:29:45 +0200
commit5606330627ab680f5e6b7549d14ec3ffdae58c15 (patch)
tree5766fa5aa8375263757f24819219175ccf8cfaa5 /arch/s390/kernel/dumpstack.c
parents390/cpum_sf: Remove superfluous SMP function call (diff)
downloadlinux-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.c24
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);