Back to home page

OSCL-LXR

 
 

    


0001 /* SPDX-License-Identifier: GPL-2.0 */
0002 #ifndef _ASM_X86_FRAME_H
0003 #define _ASM_X86_FRAME_H
0004 
0005 #include <asm/asm.h>
0006 
0007 /*
0008  * These are stack frame creation macros.  They should be used by every
0009  * callable non-leaf asm function to make kernel stack traces more reliable.
0010  */
0011 
0012 #ifdef CONFIG_FRAME_POINTER
0013 
0014 #ifdef __ASSEMBLY__
0015 
0016 .macro FRAME_BEGIN
0017     push %_ASM_BP
0018     _ASM_MOV %_ASM_SP, %_ASM_BP
0019 .endm
0020 
0021 .macro FRAME_END
0022     pop %_ASM_BP
0023 .endm
0024 
0025 #ifdef CONFIG_X86_64
0026 /*
0027  * This is a sneaky trick to help the unwinder find pt_regs on the stack.  The
0028  * frame pointer is replaced with an encoded pointer to pt_regs.  The encoding
0029  * is just setting the LSB, which makes it an invalid stack address and is also
0030  * a signal to the unwinder that it's a pt_regs pointer in disguise.
0031  *
0032  * NOTE: This macro must be used *after* PUSH_AND_CLEAR_REGS because it corrupts
0033  * the original rbp.
0034  */
0035 .macro ENCODE_FRAME_POINTER ptregs_offset=0
0036     leaq 1+\ptregs_offset(%rsp), %rbp
0037 .endm
0038 #else /* !CONFIG_X86_64 */
0039 /*
0040  * This is a sneaky trick to help the unwinder find pt_regs on the stack.  The
0041  * frame pointer is replaced with an encoded pointer to pt_regs.  The encoding
0042  * is just clearing the MSB, which makes it an invalid stack address and is also
0043  * a signal to the unwinder that it's a pt_regs pointer in disguise.
0044  *
0045  * NOTE: This macro must be used *after* SAVE_ALL because it corrupts the
0046  * original ebp.
0047  */
0048 .macro ENCODE_FRAME_POINTER
0049     mov %esp, %ebp
0050     andl $0x7fffffff, %ebp
0051 .endm
0052 #endif /* CONFIG_X86_64 */
0053 
0054 #else /* !__ASSEMBLY__ */
0055 
0056 #define FRAME_BEGIN             \
0057     "push %" _ASM_BP "\n"           \
0058     _ASM_MOV "%" _ASM_SP ", %" _ASM_BP "\n"
0059 
0060 #define FRAME_END "pop %" _ASM_BP "\n"
0061 
0062 #ifdef CONFIG_X86_64
0063 
0064 #define ENCODE_FRAME_POINTER            \
0065     "lea 1(%rsp), %rbp\n\t"
0066 
0067 static inline unsigned long encode_frame_pointer(struct pt_regs *regs)
0068 {
0069     return (unsigned long)regs + 1;
0070 }
0071 
0072 #else /* !CONFIG_X86_64 */
0073 
0074 #define ENCODE_FRAME_POINTER            \
0075     "movl %esp, %ebp\n\t"           \
0076     "andl $0x7fffffff, %ebp\n\t"
0077 
0078 static inline unsigned long encode_frame_pointer(struct pt_regs *regs)
0079 {
0080     return (unsigned long)regs & 0x7fffffff;
0081 }
0082 
0083 #endif /* CONFIG_X86_64 */
0084 
0085 #endif /* __ASSEMBLY__ */
0086 
0087 #define FRAME_OFFSET __ASM_SEL(4, 8)
0088 
0089 #else /* !CONFIG_FRAME_POINTER */
0090 
0091 #ifdef __ASSEMBLY__
0092 
0093 .macro ENCODE_FRAME_POINTER ptregs_offset=0
0094 .endm
0095 
0096 #else /* !__ASSEMBLY */
0097 
0098 #define ENCODE_FRAME_POINTER
0099 
0100 static inline unsigned long encode_frame_pointer(struct pt_regs *regs)
0101 {
0102     return 0;
0103 }
0104 
0105 #endif
0106 
0107 #define FRAME_BEGIN
0108 #define FRAME_END
0109 #define FRAME_OFFSET 0
0110 
0111 #endif /* CONFIG_FRAME_POINTER */
0112 
0113 #endif /* _ASM_X86_FRAME_H */