1 /* SPDX-License-Identifier: GPL-2.0 */ 2 /* 3 * Copyright (C) 2020-2022 Loongson Technology Corporation Limited 4 */ 5 #ifndef _ASM_STACKTRACE_H 6 #define _ASM_STACKTRACE_H 7 8 #include <asm/asm.h> 9 #include <asm/ptrace.h> 10 #include <asm/loongarch.h> 11 #include <asm/unwind_hints.h> 12 #include <linux/stringify.h> 13 14 enum stack_type { 15 STACK_TYPE_UNKNOWN, 16 STACK_TYPE_IRQ, 17 STACK_TYPE_TASK, 18 }; 19 20 struct stack_info { 21 enum stack_type type; 22 unsigned long begin, end, next_sp; 23 }; 24 25 struct stack_frame { 26 unsigned long fp; 27 unsigned long ra; 28 }; 29 30 bool in_irq_stack(unsigned long stack, struct stack_info *info); 31 bool in_task_stack(unsigned long stack, struct task_struct *task, struct stack_info *info); 32 int get_stack_info(unsigned long stack, struct task_struct *task, struct stack_info *info); 33 34 static __always_inline bool on_thread_stack(void) 35 { 36 return !(((unsigned long)(current->stack) ^ current_stack_pointer) & ~(THREAD_SIZE - 1)); 37 } 38 39 #define STR_LONG_L __stringify(LONG_L) 40 #define STR_LONG_S __stringify(LONG_S) 41 #define STR_LONGSIZE __stringify(LONGSIZE) 42 43 #define STORE_ONE_REG(r) \ 44 STR_LONG_S " $r" __stringify(r)", %1, "STR_LONGSIZE"*"__stringify(r)"\n\t" 45 46 #define CSRRD_ONE_REG(reg) \ 47 __stringify(csrrd) " %0, "__stringify(reg)"\n\t" 48 49 static __always_inline void prepare_frametrace(struct pt_regs *regs) 50 { 51 __asm__ __volatile__( 52 UNWIND_HINT_SAVE 53 /* Save $ra */ 54 STORE_ONE_REG(1) 55 /* Use $ra to save PC */ 56 "pcaddi $ra, 0\n\t" 57 STR_LONG_S " $ra, %0\n\t" 58 /* Restore $ra */ 59 STR_LONG_L " $ra, %1, "STR_LONGSIZE"\n\t" 60 STORE_ONE_REG(2) 61 STORE_ONE_REG(3) 62 STORE_ONE_REG(4) 63 STORE_ONE_REG(5) 64 STORE_ONE_REG(6) 65 STORE_ONE_REG(7) 66 STORE_ONE_REG(8) 67 STORE_ONE_REG(9) 68 STORE_ONE_REG(10) 69 STORE_ONE_REG(11) 70 STORE_ONE_REG(12) 71 STORE_ONE_REG(13) 72 STORE_ONE_REG(14) 73 STORE_ONE_REG(15) 74 STORE_ONE_REG(16) 75 STORE_ONE_REG(17) 76 STORE_ONE_REG(18) 77 STORE_ONE_REG(19) 78 STORE_ONE_REG(20) 79 STORE_ONE_REG(21) 80 STORE_ONE_REG(22) 81 STORE_ONE_REG(23) 82 STORE_ONE_REG(24) 83 STORE_ONE_REG(25) 84 STORE_ONE_REG(26) 85 STORE_ONE_REG(27) 86 STORE_ONE_REG(28) 87 STORE_ONE_REG(29) 88 STORE_ONE_REG(30) 89 STORE_ONE_REG(31) 90 UNWIND_HINT_RESTORE 91 : "=m" (regs->csr_era) 92 : "r" (regs->regs) 93 : "memory"); 94 __asm__ __volatile__(CSRRD_ONE_REG(LOONGARCH_CSR_BADV) : "=r" (regs->csr_badvaddr)); 95 __asm__ __volatile__(CSRRD_ONE_REG(LOONGARCH_CSR_CRMD) : "=r" (regs->csr_crmd)); 96 __asm__ __volatile__(CSRRD_ONE_REG(LOONGARCH_CSR_PRMD) : "=r" (regs->csr_prmd)); 97 __asm__ __volatile__(CSRRD_ONE_REG(LOONGARCH_CSR_EUEN) : "=r" (regs->csr_euen)); 98 __asm__ __volatile__(CSRRD_ONE_REG(LOONGARCH_CSR_ECFG) : "=r" (regs->csr_ecfg)); 99 __asm__ __volatile__(CSRRD_ONE_REG(LOONGARCH_CSR_ESTAT) : "=r" (regs->csr_estat)); 100 } 101 102 #endif /* _ASM_STACKTRACE_H */ 103