kstack.h 2.2 KB

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