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