xref: /linux-6.15/arch/arm64/include/asm/stacktrace.h (revision 7ea55715)
1caab277bSThomas Gleixner /* SPDX-License-Identifier: GPL-2.0-only */
260ffc30dSCatalin Marinas /*
360ffc30dSCatalin Marinas  * Copyright (C) 2012 ARM Ltd.
460ffc30dSCatalin Marinas  */
560ffc30dSCatalin Marinas #ifndef __ASM_STACKTRACE_H
660ffc30dSCatalin Marinas #define __ASM_STACKTRACE_H
760ffc30dSCatalin Marinas 
8f60ad4edSMark Rutland #include <linux/percpu.h>
9f60ad4edSMark Rutland #include <linux/sched.h>
10f60ad4edSMark Rutland #include <linux/sched/task_stack.h>
11cd9bc2c9SMasami Hiramatsu #include <linux/llist.h>
12f60ad4edSMark Rutland 
13f60ad4edSMark Rutland #include <asm/memory.h>
14f51e7146SKalesh Singh #include <asm/pointer_auth.h>
15f60ad4edSMark Rutland #include <asm/ptrace.h>
16f5df2696SJames Morse #include <asm/sdei.h>
17fe13f95bSAKASHI Takahiro 
186bf212c8SKalesh Singh #include <asm/stacktrace/common.h>
198a1ccfbcSLaura Abbott 
20c7689837SDmitry Safonov extern void dump_backtrace(struct pt_regs *regs, struct task_struct *tsk,
21c7689837SDmitry Safonov 			   const char *loglvl);
2260ffc30dSCatalin Marinas 
23f60fe78fSMark Rutland DECLARE_PER_CPU(unsigned long *, irq_stack_ptr);
24f60ad4edSMark Rutland 
stackinfo_get_irq(void)25d1f684e4SMark Rutland static inline struct stack_info stackinfo_get_irq(void)
26bd4298c7SYunfeng Ye {
27bd4298c7SYunfeng Ye 	unsigned long low = (unsigned long)raw_cpu_read(irq_stack_ptr);
28bd4298c7SYunfeng Ye 	unsigned long high = low + IRQ_STACK_SIZE;
29bd4298c7SYunfeng Ye 
30d1f684e4SMark Rutland 	return (struct stack_info) {
31d1f684e4SMark Rutland 		.low = low,
32d1f684e4SMark Rutland 		.high = high,
33d1f684e4SMark Rutland 	};
348a1ccfbcSLaura Abbott }
358a1ccfbcSLaura Abbott 
on_irq_stack(unsigned long sp,unsigned long size)36d1f684e4SMark Rutland static inline bool on_irq_stack(unsigned long sp, unsigned long size)
37d1f684e4SMark Rutland {
38d1f684e4SMark Rutland 	struct stack_info info = stackinfo_get_irq();
39d1f684e4SMark Rutland 	return stackinfo_on_stack(&info, sp, size);
40d1f684e4SMark Rutland }
41d1f684e4SMark Rutland 
stackinfo_get_task(const struct task_struct * tsk)42d1f684e4SMark Rutland static inline struct stack_info stackinfo_get_task(const struct task_struct *tsk)
43f60ad4edSMark Rutland {
44f60ad4edSMark Rutland 	unsigned long low = (unsigned long)task_stack_page(tsk);
45f60ad4edSMark Rutland 	unsigned long high = low + THREAD_SIZE;
46f60ad4edSMark Rutland 
47d1f684e4SMark Rutland 	return (struct stack_info) {
48d1f684e4SMark Rutland 		.low = low,
49d1f684e4SMark Rutland 		.high = high,
50d1f684e4SMark Rutland 	};
51d1f684e4SMark Rutland }
52d1f684e4SMark Rutland 
on_task_stack(const struct task_struct * tsk,unsigned long sp,unsigned long size)53d1f684e4SMark Rutland static inline bool on_task_stack(const struct task_struct *tsk,
54d1f684e4SMark Rutland 				 unsigned long sp, unsigned long size)
55d1f684e4SMark Rutland {
56d1f684e4SMark Rutland 	struct stack_info info = stackinfo_get_task(tsk);
57d1f684e4SMark Rutland 	return stackinfo_on_stack(&info, sp, size);
58f60ad4edSMark Rutland }
59f60ad4edSMark Rutland 
604585a934SMark Rutland #define on_thread_stack()	(on_task_stack(current, current_stack_pointer, 1))
614585a934SMark Rutland 
62872d8327SMark Rutland #ifdef CONFIG_VMAP_STACK
63872d8327SMark Rutland DECLARE_PER_CPU(unsigned long [OVERFLOW_STACK_SIZE/sizeof(long)], overflow_stack);
64872d8327SMark Rutland 
stackinfo_get_overflow(void)65d1f684e4SMark Rutland static inline struct stack_info stackinfo_get_overflow(void)
66872d8327SMark Rutland {
67872d8327SMark Rutland 	unsigned long low = (unsigned long)raw_cpu_ptr(overflow_stack);
68872d8327SMark Rutland 	unsigned long high = low + OVERFLOW_STACK_SIZE;
69872d8327SMark Rutland 
70d1f684e4SMark Rutland 	return (struct stack_info) {
71d1f684e4SMark Rutland 		.low = low,
72d1f684e4SMark Rutland 		.high = high,
73d1f684e4SMark Rutland 	};
74872d8327SMark Rutland }
75872d8327SMark Rutland #else
76d1f684e4SMark Rutland #define stackinfo_get_overflow()	stackinfo_get_unknown()
7775758d51SMark Rutland #endif
7875758d51SMark Rutland 
7975758d51SMark Rutland #if defined(CONFIG_ARM_SDE_INTERFACE) && defined(CONFIG_VMAP_STACK)
8075758d51SMark Rutland DECLARE_PER_CPU(unsigned long *, sdei_stack_normal_ptr);
8175758d51SMark Rutland DECLARE_PER_CPU(unsigned long *, sdei_stack_critical_ptr);
8275758d51SMark Rutland 
stackinfo_get_sdei_normal(void)83d1f684e4SMark Rutland static inline struct stack_info stackinfo_get_sdei_normal(void)
8475758d51SMark Rutland {
8575758d51SMark Rutland 	unsigned long low = (unsigned long)raw_cpu_read(sdei_stack_normal_ptr);
8675758d51SMark Rutland 	unsigned long high = low + SDEI_STACK_SIZE;
8775758d51SMark Rutland 
88d1f684e4SMark Rutland 	return (struct stack_info) {
89d1f684e4SMark Rutland 		.low = low,
90d1f684e4SMark Rutland 		.high = high,
91d1f684e4SMark Rutland 	};
9275758d51SMark Rutland }
9375758d51SMark Rutland 
stackinfo_get_sdei_critical(void)94d1f684e4SMark Rutland static inline struct stack_info stackinfo_get_sdei_critical(void)
9575758d51SMark Rutland {
9675758d51SMark Rutland 	unsigned long low = (unsigned long)raw_cpu_read(sdei_stack_critical_ptr);
9775758d51SMark Rutland 	unsigned long high = low + SDEI_STACK_SIZE;
9875758d51SMark Rutland 
99d1f684e4SMark Rutland 	return (struct stack_info) {
100d1f684e4SMark Rutland 		.low = low,
101d1f684e4SMark Rutland 		.high = high,
102d1f684e4SMark Rutland 	};
10375758d51SMark Rutland }
10475758d51SMark Rutland #else
105d1f684e4SMark Rutland #define stackinfo_get_sdei_normal()	stackinfo_get_unknown()
106d1f684e4SMark Rutland #define stackinfo_get_sdei_critical()	stackinfo_get_unknown()
107872d8327SMark Rutland #endif
108872d8327SMark Rutland 
109*7ea55715SArd Biesheuvel #ifdef CONFIG_EFI
110*7ea55715SArd Biesheuvel extern u64 *efi_rt_stack_top;
111*7ea55715SArd Biesheuvel 
stackinfo_get_efi(void)112*7ea55715SArd Biesheuvel static inline struct stack_info stackinfo_get_efi(void)
113*7ea55715SArd Biesheuvel {
114*7ea55715SArd Biesheuvel 	unsigned long high = (u64)efi_rt_stack_top;
115*7ea55715SArd Biesheuvel 	unsigned long low = high - THREAD_SIZE;
116*7ea55715SArd Biesheuvel 
117*7ea55715SArd Biesheuvel 	return (struct stack_info) {
118*7ea55715SArd Biesheuvel 		.low = low,
119*7ea55715SArd Biesheuvel 		.high = high,
120*7ea55715SArd Biesheuvel 	};
121*7ea55715SArd Biesheuvel }
122*7ea55715SArd Biesheuvel #endif
123*7ea55715SArd Biesheuvel 
12460ffc30dSCatalin Marinas #endif	/* __ASM_STACKTRACE_H */
125