xref: /linux/arch/sparc/kernel/kstack.h (revision 498495dba268b20e8eadd7fe93c140c68b6cc9d2)
1*b2441318SGreg Kroah-Hartman /* SPDX-License-Identifier: GPL-2.0 */
2a88b5ba8SSam Ravnborg #ifndef _KSTACK_H
3a88b5ba8SSam Ravnborg #define _KSTACK_H
4a88b5ba8SSam Ravnborg 
5a88b5ba8SSam Ravnborg #include <linux/thread_info.h>
6a88b5ba8SSam Ravnborg #include <linux/sched.h>
7a88b5ba8SSam Ravnborg #include <asm/ptrace.h>
8a88b5ba8SSam Ravnborg #include <asm/irq.h>
9a88b5ba8SSam Ravnborg 
10a88b5ba8SSam Ravnborg /* SP must be STACK_BIAS adjusted already.  */
kstack_valid(struct thread_info * tp,unsigned long sp)11a88b5ba8SSam Ravnborg static inline bool kstack_valid(struct thread_info *tp, unsigned long sp)
12a88b5ba8SSam Ravnborg {
13a88b5ba8SSam Ravnborg 	unsigned long base = (unsigned long) tp;
14a88b5ba8SSam Ravnborg 
15232486e1SDavid S. Miller 	/* Stack pointer must be 16-byte aligned.  */
16232486e1SDavid S. Miller 	if (sp & (16UL - 1))
17232486e1SDavid S. Miller 		return false;
18232486e1SDavid S. Miller 
19a88b5ba8SSam Ravnborg 	if (sp >= (base + sizeof(struct thread_info)) &&
20a88b5ba8SSam Ravnborg 	    sp <= (base + THREAD_SIZE - sizeof(struct sparc_stackf)))
21a88b5ba8SSam Ravnborg 		return true;
22a88b5ba8SSam Ravnborg 
23a88b5ba8SSam Ravnborg 	if (hardirq_stack[tp->cpu]) {
24a88b5ba8SSam Ravnborg 		base = (unsigned long) hardirq_stack[tp->cpu];
25a88b5ba8SSam Ravnborg 		if (sp >= base &&
26a88b5ba8SSam Ravnborg 		    sp <= (base + THREAD_SIZE - sizeof(struct sparc_stackf)))
27a88b5ba8SSam Ravnborg 			return true;
28a88b5ba8SSam Ravnborg 		base = (unsigned long) softirq_stack[tp->cpu];
29a88b5ba8SSam Ravnborg 		if (sp >= base &&
30a88b5ba8SSam Ravnborg 		    sp <= (base + THREAD_SIZE - sizeof(struct sparc_stackf)))
31a88b5ba8SSam Ravnborg 			return true;
32a88b5ba8SSam Ravnborg 	}
33a88b5ba8SSam Ravnborg 	return false;
34a88b5ba8SSam Ravnborg }
35a88b5ba8SSam Ravnborg 
36a88b5ba8SSam Ravnborg /* Does "regs" point to a valid pt_regs trap frame?  */
kstack_is_trap_frame(struct thread_info * tp,struct pt_regs * regs)37a88b5ba8SSam Ravnborg static inline bool kstack_is_trap_frame(struct thread_info *tp, struct pt_regs *regs)
38a88b5ba8SSam Ravnborg {
39a88b5ba8SSam Ravnborg 	unsigned long base = (unsigned long) tp;
40a88b5ba8SSam Ravnborg 	unsigned long addr = (unsigned long) regs;
41a88b5ba8SSam Ravnborg 
42a88b5ba8SSam Ravnborg 	if (addr >= base &&
43a88b5ba8SSam Ravnborg 	    addr <= (base + THREAD_SIZE - sizeof(*regs)))
44a88b5ba8SSam Ravnborg 		goto check_magic;
45a88b5ba8SSam Ravnborg 
46a88b5ba8SSam Ravnborg 	if (hardirq_stack[tp->cpu]) {
47a88b5ba8SSam Ravnborg 		base = (unsigned long) hardirq_stack[tp->cpu];
48a88b5ba8SSam Ravnborg 		if (addr >= base &&
49a88b5ba8SSam Ravnborg 		    addr <= (base + THREAD_SIZE - sizeof(*regs)))
50a88b5ba8SSam Ravnborg 			goto check_magic;
51a88b5ba8SSam Ravnborg 		base = (unsigned long) softirq_stack[tp->cpu];
52a88b5ba8SSam Ravnborg 		if (addr >= base &&
53a88b5ba8SSam Ravnborg 		    addr <= (base + THREAD_SIZE - sizeof(*regs)))
54a88b5ba8SSam Ravnborg 			goto check_magic;
55a88b5ba8SSam Ravnborg 	}
56a88b5ba8SSam Ravnborg 	return false;
57a88b5ba8SSam Ravnborg 
58a88b5ba8SSam Ravnborg check_magic:
59a88b5ba8SSam Ravnborg 	if ((regs->magic & ~0x1ff) == PT_REGS_MAGIC)
60a88b5ba8SSam Ravnborg 		return true;
61a88b5ba8SSam Ravnborg 	return false;
62a88b5ba8SSam Ravnborg 
63a88b5ba8SSam Ravnborg }
64a88b5ba8SSam Ravnborg 
set_hardirq_stack(void)65ec687886SDavid S. Miller static inline __attribute__((always_inline)) void *set_hardirq_stack(void)
66ec687886SDavid S. Miller {
67ec687886SDavid S. Miller 	void *orig_sp, *sp = hardirq_stack[smp_processor_id()];
68ec687886SDavid S. Miller 
69ec687886SDavid S. Miller 	__asm__ __volatile__("mov %%sp, %0" : "=r" (orig_sp));
70ec687886SDavid S. Miller 	if (orig_sp < sp ||
71ec687886SDavid S. Miller 	    orig_sp > (sp + THREAD_SIZE)) {
72ec687886SDavid S. Miller 		sp += THREAD_SIZE - 192 - STACK_BIAS;
73ec687886SDavid S. Miller 		__asm__ __volatile__("mov %0, %%sp" : : "r" (sp));
74ec687886SDavid S. Miller 	}
75ec687886SDavid S. Miller 
76ec687886SDavid S. Miller 	return orig_sp;
77ec687886SDavid S. Miller }
78ec687886SDavid S. Miller 
restore_hardirq_stack(void * orig_sp)79ec687886SDavid S. Miller static inline __attribute__((always_inline)) void restore_hardirq_stack(void *orig_sp)
80ec687886SDavid S. Miller {
81ec687886SDavid S. Miller 	__asm__ __volatile__("mov %0, %%sp" : : "r" (orig_sp));
82ec687886SDavid S. Miller }
83ec687886SDavid S. Miller 
84a88b5ba8SSam Ravnborg #endif /* _KSTACK_H */
85