frame.h 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. /* SPDX-License-Identifier: GPL-2.0 */
  2. #ifndef _ASM_X86_FRAME_H
  3. #define _ASM_X86_FRAME_H
  4. #include <asm/asm.h>
  5. /*
  6. * These are stack frame creation macros. They should be used by every
  7. * callable non-leaf asm function to make kernel stack traces more reliable.
  8. */
  9. #ifdef CONFIG_FRAME_POINTER
  10. #ifdef __ASSEMBLY__
  11. .macro FRAME_BEGIN
  12. push %_ASM_BP
  13. _ASM_MOV %_ASM_SP, %_ASM_BP
  14. .endm
  15. .macro FRAME_END
  16. pop %_ASM_BP
  17. .endm
  18. #ifdef CONFIG_X86_64
  19. /*
  20. * This is a sneaky trick to help the unwinder find pt_regs on the stack. The
  21. * frame pointer is replaced with an encoded pointer to pt_regs. The encoding
  22. * is just setting the LSB, which makes it an invalid stack address and is also
  23. * a signal to the unwinder that it's a pt_regs pointer in disguise.
  24. *
  25. * NOTE: This macro must be used *after* PUSH_AND_CLEAR_REGS because it corrupts
  26. * the original rbp.
  27. */
  28. .macro ENCODE_FRAME_POINTER ptregs_offset=0
  29. leaq 1+\ptregs_offset(%rsp), %rbp
  30. .endm
  31. #else /* !CONFIG_X86_64 */
  32. /*
  33. * This is a sneaky trick to help the unwinder find pt_regs on the stack. The
  34. * frame pointer is replaced with an encoded pointer to pt_regs. The encoding
  35. * is just clearing the MSB, which makes it an invalid stack address and is also
  36. * a signal to the unwinder that it's a pt_regs pointer in disguise.
  37. *
  38. * NOTE: This macro must be used *after* SAVE_ALL because it corrupts the
  39. * original ebp.
  40. */
  41. .macro ENCODE_FRAME_POINTER
  42. mov %esp, %ebp
  43. andl $0x7fffffff, %ebp
  44. .endm
  45. #endif /* CONFIG_X86_64 */
  46. #else /* !__ASSEMBLY__ */
  47. #define FRAME_BEGIN \
  48. "push %" _ASM_BP "\n" \
  49. _ASM_MOV "%" _ASM_SP ", %" _ASM_BP "\n"
  50. #define FRAME_END "pop %" _ASM_BP "\n"
  51. #ifdef CONFIG_X86_64
  52. #define ENCODE_FRAME_POINTER \
  53. "lea 1(%rsp), %rbp\n\t"
  54. static inline unsigned long encode_frame_pointer(struct pt_regs *regs)
  55. {
  56. return (unsigned long)regs + 1;
  57. }
  58. #else /* !CONFIG_X86_64 */
  59. #define ENCODE_FRAME_POINTER \
  60. "movl %esp, %ebp\n\t" \
  61. "andl $0x7fffffff, %ebp\n\t"
  62. static inline unsigned long encode_frame_pointer(struct pt_regs *regs)
  63. {
  64. return (unsigned long)regs & 0x7fffffff;
  65. }
  66. #endif /* CONFIG_X86_64 */
  67. #endif /* __ASSEMBLY__ */
  68. #define FRAME_OFFSET __ASM_SEL(4, 8)
  69. #else /* !CONFIG_FRAME_POINTER */
  70. #ifdef __ASSEMBLY__
  71. .macro ENCODE_FRAME_POINTER ptregs_offset=0
  72. .endm
  73. #else /* !__ASSEMBLY */
  74. #define ENCODE_FRAME_POINTER
  75. static inline unsigned long encode_frame_pointer(struct pt_regs *regs)
  76. {
  77. return 0;
  78. }
  79. #endif
  80. #define FRAME_BEGIN
  81. #define FRAME_END
  82. #define FRAME_OFFSET 0
  83. #endif /* CONFIG_FRAME_POINTER */
  84. #endif /* _ASM_X86_FRAME_H */