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