summaryrefslogtreecommitdiffstats
path: root/arch/s390/kernel/dumpstack.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/s390/kernel/dumpstack.c')
-rw-r--r--arch/s390/kernel/dumpstack.c36
1 files changed, 28 insertions, 8 deletions
diff --git a/arch/s390/kernel/dumpstack.c b/arch/s390/kernel/dumpstack.c
index 1b6081c0aff9..6693383bc01b 100644
--- a/arch/s390/kernel/dumpstack.c
+++ b/arch/s390/kernel/dumpstack.c
@@ -78,17 +78,37 @@ void dump_trace(dump_trace_func_t func, void *data, struct task_struct *task,
sp = __dump_trace(func, data, sp,
S390_lowcore.async_stack + frame_size - ASYNC_SIZE,
S390_lowcore.async_stack + frame_size);
- if (task)
- __dump_trace(func, data, sp,
- (unsigned long)task_stack_page(task),
- (unsigned long)task_stack_page(task) + THREAD_SIZE);
- else
- __dump_trace(func, data, sp,
- S390_lowcore.thread_info,
- S390_lowcore.thread_info + THREAD_SIZE);
+ task = task ?: current;
+ __dump_trace(func, data, sp,
+ (unsigned long)task_stack_page(task),
+ (unsigned long)task_stack_page(task) + THREAD_SIZE);
}
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);
OpenPOWER on IntegriCloud