unwind.h 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. /* SPDX-License-Identifier: GPL-2.0 */
  2. #ifndef _ASM_X86_UNWIND_H
  3. #define _ASM_X86_UNWIND_H
  4. #include <linux/sched.h>
  5. #include <linux/ftrace.h>
  6. #include <asm/ptrace.h>
  7. #include <asm/stacktrace.h>
  8. #define IRET_FRAME_OFFSET (offsetof(struct pt_regs, ip))
  9. #define IRET_FRAME_SIZE (sizeof(struct pt_regs) - IRET_FRAME_OFFSET)
  10. struct unwind_state {
  11. struct stack_info stack_info;
  12. unsigned long stack_mask;
  13. struct task_struct *task;
  14. int graph_idx;
  15. bool error;
  16. #if defined(CONFIG_UNWINDER_ORC)
  17. bool signal, full_regs;
  18. unsigned long sp, bp, ip;
  19. struct pt_regs *regs;
  20. #elif defined(CONFIG_UNWINDER_FRAME_POINTER)
  21. bool got_irq;
  22. unsigned long *bp, *orig_sp, ip;
  23. struct pt_regs *regs;
  24. #else
  25. unsigned long *sp;
  26. #endif
  27. };
  28. void __unwind_start(struct unwind_state *state, struct task_struct *task,
  29. struct pt_regs *regs, unsigned long *first_frame);
  30. bool unwind_next_frame(struct unwind_state *state);
  31. unsigned long unwind_get_return_address(struct unwind_state *state);
  32. unsigned long *unwind_get_return_address_ptr(struct unwind_state *state);
  33. static inline bool unwind_done(struct unwind_state *state)
  34. {
  35. return state->stack_info.type == STACK_TYPE_UNKNOWN;
  36. }
  37. static inline bool unwind_error(struct unwind_state *state)
  38. {
  39. return state->error;
  40. }
  41. static inline
  42. void unwind_start(struct unwind_state *state, struct task_struct *task,
  43. struct pt_regs *regs, unsigned long *first_frame)
  44. {
  45. first_frame = first_frame ? : get_stack_pointer(task, regs);
  46. __unwind_start(state, task, regs, first_frame);
  47. }
  48. #if defined(CONFIG_UNWINDER_ORC) || defined(CONFIG_UNWINDER_FRAME_POINTER)
  49. /*
  50. * WARNING: The entire pt_regs may not be safe to dereference. In some cases,
  51. * only the iret frame registers are accessible. Use with caution!
  52. */
  53. static inline struct pt_regs *unwind_get_entry_regs(struct unwind_state *state)
  54. {
  55. if (unwind_done(state))
  56. return NULL;
  57. return state->regs;
  58. }
  59. #else
  60. static inline struct pt_regs *unwind_get_entry_regs(struct unwind_state *state)
  61. {
  62. return NULL;
  63. }
  64. #endif
  65. #ifdef CONFIG_UNWINDER_ORC
  66. void unwind_init(void);
  67. void unwind_module_init(struct module *mod, void *orc_ip, size_t orc_ip_size,
  68. void *orc, size_t orc_size);
  69. #else
  70. static inline void unwind_init(void) {}
  71. static inline
  72. void unwind_module_init(struct module *mod, void *orc_ip, size_t orc_ip_size,
  73. void *orc, size_t orc_size) {}
  74. #endif
  75. /*
  76. * This disables KASAN checking when reading a value from another task's stack,
  77. * since the other task could be running on another CPU and could have poisoned
  78. * the stack in the meantime.
  79. */
  80. #define READ_ONCE_TASK_STACK(task, x) \
  81. ({ \
  82. unsigned long val; \
  83. if (task == current) \
  84. val = READ_ONCE(x); \
  85. else \
  86. val = READ_ONCE_NOCHECK(x); \
  87. val; \
  88. })
  89. static inline bool task_on_another_cpu(struct task_struct *task)
  90. {
  91. #ifdef CONFIG_SMP
  92. return task != current && task->on_cpu;
  93. #else
  94. return false;
  95. #endif
  96. }
  97. #endif /* _ASM_X86_UNWIND_H */