diff options
Diffstat (limited to 'arch/s390/kernel/stacktrace.c')
-rw-r--r-- | arch/s390/kernel/stacktrace.c | 75 |
1 files changed, 75 insertions, 0 deletions
diff --git a/arch/s390/kernel/stacktrace.c b/arch/s390/kernel/stacktrace.c new file mode 100644 index 000000000..460dcfba7 --- /dev/null +++ b/arch/s390/kernel/stacktrace.c @@ -0,0 +1,75 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Stack trace management functions + * + * Copyright IBM Corp. 2006 + * Author(s): Heiko Carstens <heiko.carstens@de.ibm.com> + */ + +#include <linux/sched.h> +#include <linux/sched/debug.h> +#include <linux/stacktrace.h> +#include <linux/kallsyms.h> +#include <linux/export.h> + +static int __save_address(void *data, unsigned long address, int nosched) +{ + struct stack_trace *trace = data; + + if (nosched && in_sched_functions(address)) + return 0; + if (trace->skip > 0) { + trace->skip--; + return 0; + } + if (trace->nr_entries < trace->max_entries) { + trace->entries[trace->nr_entries++] = address; + return 0; + } + return 1; +} + +static int save_address(void *data, unsigned long address, int reliable) +{ + return __save_address(data, address, 0); +} + +static int save_address_nosched(void *data, unsigned long address, int reliable) +{ + return __save_address(data, address, 1); +} + +void save_stack_trace(struct stack_trace *trace) +{ + unsigned long sp; + + sp = current_stack_pointer(); + dump_trace(save_address, trace, NULL, sp); + if (trace->nr_entries < trace->max_entries) + trace->entries[trace->nr_entries++] = ULONG_MAX; +} +EXPORT_SYMBOL_GPL(save_stack_trace); + +void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace) +{ + unsigned long sp; + + sp = tsk->thread.ksp; + if (tsk == current) + sp = current_stack_pointer(); + dump_trace(save_address_nosched, trace, tsk, sp); + if (trace->nr_entries < trace->max_entries) + trace->entries[trace->nr_entries++] = ULONG_MAX; +} +EXPORT_SYMBOL_GPL(save_stack_trace_tsk); + +void save_stack_trace_regs(struct pt_regs *regs, struct stack_trace *trace) +{ + unsigned long sp; + + sp = kernel_stack_pointer(regs); + dump_trace(save_address, trace, NULL, sp); + if (trace->nr_entries < trace->max_entries) + trace->entries[trace->nr_entries++] = ULONG_MAX; +} +EXPORT_SYMBOL_GPL(save_stack_trace_regs); |