^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) * OpenRISC unwinder.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * Reusable arch specific api for unwinding stacks.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Copyright (C) 2017 Stafford Horne <shorne@gmail.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * This file is licensed under the terms of the GNU General Public License
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * version 2. This program is licensed "as is" without any warranty of any
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * kind, whether express or implied.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/sched/task_stack.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <asm/unwinder.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #ifdef CONFIG_FRAME_POINTER
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) struct or1k_frameinfo {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) unsigned long *fp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) unsigned long ra;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) unsigned long top;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) * Verify a frameinfo structure. The return address should be a valid text
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) * address. The frame pointer may be null if its the last frame, otherwise
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) * the frame pointer should point to a location in the stack after the the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) * top of the next frame up.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) static inline int or1k_frameinfo_valid(struct or1k_frameinfo *frameinfo)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) return (frameinfo->fp == NULL ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) (!kstack_end(frameinfo->fp) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) frameinfo->fp > &frameinfo->top)) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) __kernel_text_address(frameinfo->ra);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) * Create a stack trace doing scanning which is frame pointer aware. We can
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) * get reliable stack traces by matching the previously found frame
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) * pointer with the top of the stack address every time we find a valid
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) * or1k_frameinfo.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) * Ideally the stack parameter will be passed as FP, but it can not be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) * guaranteed. Therefore we scan each address looking for the first sign
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) * of a return address.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) * The OpenRISC stack frame looks something like the following. The
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) * location SP is held in r1 and location FP is held in r2 when frame pointers
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) * enabled.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) * SP -> (top of stack)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) * - (callee saved registers)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) * - (local variables)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) * FP-8 -> previous FP \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) * FP-4 -> return address |- or1k_frameinfo
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) * FP -> (previous top of stack) /
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) void unwind_stack(void *data, unsigned long *stack,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) void (*trace)(void *data, unsigned long addr, int reliable))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) unsigned long *next_fp = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) struct or1k_frameinfo *frameinfo = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) int reliable = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) while (!kstack_end(stack)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) frameinfo = container_of(stack,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) struct or1k_frameinfo,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) top);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) if (__kernel_text_address(frameinfo->ra)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) if (or1k_frameinfo_valid(frameinfo) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) (next_fp == NULL ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) next_fp == &frameinfo->top)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) reliable = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) next_fp = frameinfo->fp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) reliable = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) trace(data, frameinfo->ra, reliable);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) stack++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) #else /* CONFIG_FRAME_POINTER */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) * Create a stack trace by doing a simple scan treating all text addresses
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) * as return addresses.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) void unwind_stack(void *data, unsigned long *stack,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) void (*trace)(void *data, unsigned long addr, int reliable))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) unsigned long addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) while (!kstack_end(stack)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) addr = *stack++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) if (__kernel_text_address(addr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) trace(data, addr, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) #endif /* CONFIG_FRAME_POINTER */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105)