diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2022-08-12 19:44:23 +0300 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2022-08-12 19:44:23 +0300 |
commit | 999324f58c41262f5b64d04b7ac54e8f79b019fd (patch) | |
tree | 4aa403e5485bef11d1187428adcf20e67fa212f9 /arch/loongarch/kernel/stacktrace.c | |
parent | f7cdaeeab8caf8e42fc176cdb272944e036ad998 (diff) | |
parent | 715355922212a3be8bfe5a94b5707a045ac6bf00 (diff) | |
download | linux-999324f58c41262f5b64d04b7ac54e8f79b019fd.tar.xz |
Merge tag 'loongarch-5.20' of git://git.kernel.org/pub/scm/linux/kernel/git/chenhuacai/linux-loongson
Pull LoongArch updates from Huacai Chen:
- Optimise getcpu() with vDSO
- PCI enablement on top of pci & irqchip changes
- Stack unwinder and stack trace support
- Some bug fixes and build error fixes
- Update the default config file
* tag 'loongarch-5.20' of git://git.kernel.org/pub/scm/linux/kernel/git/chenhuacai/linux-loongson:
docs/zh_CN/LoongArch: Add I14 description
docs/LoongArch: Add I14 description
LoongArch: Update Loongson-3 default config file
LoongArch: Add USER_STACKTRACE support
LoongArch: Add STACKTRACE support
LoongArch: Add prologue unwinder support
LoongArch: Add guess unwinder support
LoongArch: Add vDSO syscall __vdso_getcpu()
LoongArch: Add PCI controller support
LoongArch: Parse MADT to get multi-processor information
LoongArch: Jump to the link address before enable PG
LoongArch: Requires __force attributes for any casts
LoongArch: Fix unsigned comparison with less than zero
LoongArch: Adjust arch/loongarch/Kconfig
LoongArch: cpuinfo: Fix a warning for CONFIG_CPUMASK_OFFSTACK
Diffstat (limited to 'arch/loongarch/kernel/stacktrace.c')
-rw-r--r-- | arch/loongarch/kernel/stacktrace.c | 78 |
1 files changed, 78 insertions, 0 deletions
diff --git a/arch/loongarch/kernel/stacktrace.c b/arch/loongarch/kernel/stacktrace.c new file mode 100644 index 000000000000..3a690f96f00c --- /dev/null +++ b/arch/loongarch/kernel/stacktrace.c @@ -0,0 +1,78 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Stack trace management functions + * + * Copyright (C) 2022 Loongson Technology Corporation Limited + */ +#include <linux/sched.h> +#include <linux/stacktrace.h> +#include <linux/uaccess.h> + +#include <asm/stacktrace.h> +#include <asm/unwind.h> + +void arch_stack_walk(stack_trace_consume_fn consume_entry, void *cookie, + struct task_struct *task, struct pt_regs *regs) +{ + unsigned long addr; + struct pt_regs dummyregs; + struct unwind_state state; + + regs = &dummyregs; + + if (task == current) { + regs->regs[3] = (unsigned long)__builtin_frame_address(0); + regs->csr_era = (unsigned long)__builtin_return_address(0); + } else { + regs->regs[3] = thread_saved_fp(task); + regs->csr_era = thread_saved_ra(task); + } + + regs->regs[1] = 0; + for (unwind_start(&state, task, regs); + !unwind_done(&state); unwind_next_frame(&state)) { + addr = unwind_get_return_address(&state); + if (!addr || !consume_entry(cookie, addr)) + break; + } +} + +static int +copy_stack_frame(unsigned long fp, struct stack_frame *frame) +{ + int ret = 1; + unsigned long err; + unsigned long __user *user_frame_tail; + + user_frame_tail = (unsigned long *)(fp - sizeof(struct stack_frame)); + if (!access_ok(user_frame_tail, sizeof(*frame))) + return 0; + + pagefault_disable(); + err = (__copy_from_user_inatomic(frame, user_frame_tail, sizeof(*frame))); + if (err || (unsigned long)user_frame_tail >= frame->fp) + ret = 0; + pagefault_enable(); + + return ret; +} + +void arch_stack_walk_user(stack_trace_consume_fn consume_entry, void *cookie, + const struct pt_regs *regs) +{ + unsigned long fp = regs->regs[22]; + + while (fp && !((unsigned long)fp & 0xf)) { + struct stack_frame frame; + + frame.fp = 0; + frame.ra = 0; + if (!copy_stack_frame(fp, &frame)) + break; + if (!frame.ra) + break; + if (!consume_entry(cookie, frame.ra)) + break; + fp = frame.fp; + } +} |