aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/x86/entry/entry_32.S4
-rw-r--r--arch/x86/kernel/unwind_frame.c12
2 files changed, 14 insertions, 2 deletions
diff --git a/arch/x86/entry/entry_32.S b/arch/x86/entry/entry_32.S
index 8a13d468635a..50e0d2bc4528 100644
--- a/arch/x86/entry/entry_32.S
+++ b/arch/x86/entry/entry_32.S
@@ -176,7 +176,7 @@
176/* 176/*
177 * This is a sneaky trick to help the unwinder find pt_regs on the stack. The 177 * This is a sneaky trick to help the unwinder find pt_regs on the stack. The
178 * frame pointer is replaced with an encoded pointer to pt_regs. The encoding 178 * frame pointer is replaced with an encoded pointer to pt_regs. The encoding
179 * is just setting the LSB, which makes it an invalid stack address and is also 179 * is just clearing the MSB, which makes it an invalid stack address and is also
180 * a signal to the unwinder that it's a pt_regs pointer in disguise. 180 * a signal to the unwinder that it's a pt_regs pointer in disguise.
181 * 181 *
182 * NOTE: This macro must be used *after* SAVE_ALL because it corrupts the 182 * NOTE: This macro must be used *after* SAVE_ALL because it corrupts the
@@ -185,7 +185,7 @@
185.macro ENCODE_FRAME_POINTER 185.macro ENCODE_FRAME_POINTER
186#ifdef CONFIG_FRAME_POINTER 186#ifdef CONFIG_FRAME_POINTER
187 mov %esp, %ebp 187 mov %esp, %ebp
188 orl $0x1, %ebp 188 andl $0x7fffffff, %ebp
189#endif 189#endif
190.endm 190.endm
191 191
diff --git a/arch/x86/kernel/unwind_frame.c b/arch/x86/kernel/unwind_frame.c
index d05637726c10..4949bbc95f75 100644
--- a/arch/x86/kernel/unwind_frame.c
+++ b/arch/x86/kernel/unwind_frame.c
@@ -174,6 +174,7 @@ static bool is_last_task_frame(struct unwind_state *state)
174 * This determines if the frame pointer actually contains an encoded pointer to 174 * This determines if the frame pointer actually contains an encoded pointer to
175 * pt_regs on the stack. See ENCODE_FRAME_POINTER. 175 * pt_regs on the stack. See ENCODE_FRAME_POINTER.
176 */ 176 */
177#ifdef CONFIG_X86_64
177static struct pt_regs *decode_frame_pointer(unsigned long *bp) 178static struct pt_regs *decode_frame_pointer(unsigned long *bp)
178{ 179{
179 unsigned long regs = (unsigned long)bp; 180 unsigned long regs = (unsigned long)bp;
@@ -183,6 +184,17 @@ static struct pt_regs *decode_frame_pointer(unsigned long *bp)
183 184
184 return (struct pt_regs *)(regs & ~0x1); 185 return (struct pt_regs *)(regs & ~0x1);
185} 186}
187#else
188static struct pt_regs *decode_frame_pointer(unsigned long *bp)
189{
190 unsigned long regs = (unsigned long)bp;
191
192 if (regs & 0x80000000)
193 return NULL;
194
195 return (struct pt_regs *)(regs | 0x80000000);
196}
197#endif
186 198
187#ifdef CONFIG_X86_32 199#ifdef CONFIG_X86_32
188#define KERNEL_REGS_SIZE (sizeof(struct pt_regs) - 2*sizeof(long)) 200#define KERNEL_REGS_SIZE (sizeof(struct pt_regs) - 2*sizeof(long))