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 Ravnborgstatic 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 Ravnborgstatic 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. Millerstatic 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. Millerstatic 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