1 /* SPDX-License-Identifier: GPL-2.0-only */ 2 /* 3 * Copyright (C) 2012 ARM Ltd. 4 */ 5 #ifndef __ASM_STACKTRACE_H 6 #define __ASM_STACKTRACE_H 7 8 #include <linux/percpu.h> 9 #include <linux/sched.h> 10 #include <linux/sched/task_stack.h> 11 #include <linux/llist.h> 12 13 #include <asm/memory.h> 14 #include <asm/ptrace.h> 15 #include <asm/sdei.h> 16 17 #include <asm/stacktrace/common.h> 18 19 extern void dump_backtrace(struct pt_regs *regs, struct task_struct *tsk, 20 const char *loglvl); 21 22 DECLARE_PER_CPU(unsigned long *, irq_stack_ptr); 23 24 static inline bool on_irq_stack(unsigned long sp, unsigned long size, 25 struct stack_info *info) 26 { 27 unsigned long low = (unsigned long)raw_cpu_read(irq_stack_ptr); 28 unsigned long high = low + IRQ_STACK_SIZE; 29 30 return on_stack(sp, size, low, high, STACK_TYPE_IRQ, info); 31 } 32 33 static inline bool on_task_stack(const struct task_struct *tsk, 34 unsigned long sp, unsigned long size, 35 struct stack_info *info) 36 { 37 unsigned long low = (unsigned long)task_stack_page(tsk); 38 unsigned long high = low + THREAD_SIZE; 39 40 return on_stack(sp, size, low, high, STACK_TYPE_TASK, info); 41 } 42 43 #ifdef CONFIG_VMAP_STACK 44 DECLARE_PER_CPU(unsigned long [OVERFLOW_STACK_SIZE/sizeof(long)], overflow_stack); 45 46 static inline bool on_overflow_stack(unsigned long sp, unsigned long size, 47 struct stack_info *info) 48 { 49 unsigned long low = (unsigned long)raw_cpu_ptr(overflow_stack); 50 unsigned long high = low + OVERFLOW_STACK_SIZE; 51 52 return on_stack(sp, size, low, high, STACK_TYPE_OVERFLOW, info); 53 } 54 #else 55 static inline bool on_overflow_stack(unsigned long sp, unsigned long size, 56 struct stack_info *info) { return false; } 57 #endif 58 59 60 /* 61 * We can only safely access per-cpu stacks from current in a non-preemptible 62 * context. 63 */ 64 static inline bool on_accessible_stack(const struct task_struct *tsk, 65 unsigned long sp, unsigned long size, 66 struct stack_info *info) 67 { 68 if (info) 69 info->type = STACK_TYPE_UNKNOWN; 70 71 if (on_task_stack(tsk, sp, size, info)) 72 return true; 73 if (tsk != current || preemptible()) 74 return false; 75 if (on_irq_stack(sp, size, info)) 76 return true; 77 if (on_overflow_stack(sp, size, info)) 78 return true; 79 if (on_sdei_stack(sp, size, info)) 80 return true; 81 82 return false; 83 } 84 85 #endif /* __ASM_STACKTRACE_H */ 86