|
@@ -176,6 +176,22 @@
|
|
SET_KERNEL_GS %edx
|
|
SET_KERNEL_GS %edx
|
|
.endm
|
|
.endm
|
|
|
|
|
|
|
|
+/*
|
|
|
|
+ * This is a sneaky trick to help the unwinder find pt_regs on the stack. The
|
|
|
|
+ * frame pointer is replaced with an encoded pointer to pt_regs. The encoding
|
|
|
|
+ * is just setting the LSB, which makes it an invalid stack address and is also
|
|
|
|
+ * a signal to the unwinder that it's a pt_regs pointer in disguise.
|
|
|
|
+ *
|
|
|
|
+ * NOTE: This macro must be used *after* SAVE_ALL because it corrupts the
|
|
|
|
+ * original rbp.
|
|
|
|
+ */
|
|
|
|
+.macro ENCODE_FRAME_POINTER
|
|
|
|
+#ifdef CONFIG_FRAME_POINTER
|
|
|
|
+ mov %esp, %ebp
|
|
|
|
+ orl $0x1, %ebp
|
|
|
|
+#endif
|
|
|
|
+.endm
|
|
|
|
+
|
|
.macro RESTORE_INT_REGS
|
|
.macro RESTORE_INT_REGS
|
|
popl %ebx
|
|
popl %ebx
|
|
popl %ecx
|
|
popl %ecx
|
|
@@ -641,6 +657,7 @@ common_interrupt:
|
|
ASM_CLAC
|
|
ASM_CLAC
|
|
addl $-0x80, (%esp) /* Adjust vector into the [-256, -1] range */
|
|
addl $-0x80, (%esp) /* Adjust vector into the [-256, -1] range */
|
|
SAVE_ALL
|
|
SAVE_ALL
|
|
|
|
+ ENCODE_FRAME_POINTER
|
|
TRACE_IRQS_OFF
|
|
TRACE_IRQS_OFF
|
|
movl %esp, %eax
|
|
movl %esp, %eax
|
|
call do_IRQ
|
|
call do_IRQ
|
|
@@ -652,6 +669,7 @@ ENTRY(name) \
|
|
ASM_CLAC; \
|
|
ASM_CLAC; \
|
|
pushl $~(nr); \
|
|
pushl $~(nr); \
|
|
SAVE_ALL; \
|
|
SAVE_ALL; \
|
|
|
|
+ ENCODE_FRAME_POINTER; \
|
|
TRACE_IRQS_OFF \
|
|
TRACE_IRQS_OFF \
|
|
movl %esp, %eax; \
|
|
movl %esp, %eax; \
|
|
call fn; \
|
|
call fn; \
|
|
@@ -786,6 +804,7 @@ END(spurious_interrupt_bug)
|
|
ENTRY(xen_hypervisor_callback)
|
|
ENTRY(xen_hypervisor_callback)
|
|
pushl $-1 /* orig_ax = -1 => not a system call */
|
|
pushl $-1 /* orig_ax = -1 => not a system call */
|
|
SAVE_ALL
|
|
SAVE_ALL
|
|
|
|
+ ENCODE_FRAME_POINTER
|
|
TRACE_IRQS_OFF
|
|
TRACE_IRQS_OFF
|
|
|
|
|
|
/*
|
|
/*
|
|
@@ -840,6 +859,7 @@ ENTRY(xen_failsafe_callback)
|
|
jmp iret_exc
|
|
jmp iret_exc
|
|
5: pushl $-1 /* orig_ax = -1 => not a system call */
|
|
5: pushl $-1 /* orig_ax = -1 => not a system call */
|
|
SAVE_ALL
|
|
SAVE_ALL
|
|
|
|
+ ENCODE_FRAME_POINTER
|
|
jmp ret_from_exception
|
|
jmp ret_from_exception
|
|
|
|
|
|
.section .fixup, "ax"
|
|
.section .fixup, "ax"
|
|
@@ -1067,6 +1087,7 @@ common_exception:
|
|
pushl %edx
|
|
pushl %edx
|
|
pushl %ecx
|
|
pushl %ecx
|
|
pushl %ebx
|
|
pushl %ebx
|
|
|
|
+ ENCODE_FRAME_POINTER
|
|
cld
|
|
cld
|
|
movl $(__KERNEL_PERCPU), %ecx
|
|
movl $(__KERNEL_PERCPU), %ecx
|
|
movl %ecx, %fs
|
|
movl %ecx, %fs
|
|
@@ -1099,6 +1120,7 @@ ENTRY(debug)
|
|
ASM_CLAC
|
|
ASM_CLAC
|
|
pushl $-1 # mark this as an int
|
|
pushl $-1 # mark this as an int
|
|
SAVE_ALL
|
|
SAVE_ALL
|
|
|
|
+ ENCODE_FRAME_POINTER
|
|
xorl %edx, %edx # error code 0
|
|
xorl %edx, %edx # error code 0
|
|
movl %esp, %eax # pt_regs pointer
|
|
movl %esp, %eax # pt_regs pointer
|
|
|
|
|
|
@@ -1114,11 +1136,11 @@ ENTRY(debug)
|
|
|
|
|
|
.Ldebug_from_sysenter_stack:
|
|
.Ldebug_from_sysenter_stack:
|
|
/* We're on the SYSENTER stack. Switch off. */
|
|
/* We're on the SYSENTER stack. Switch off. */
|
|
- movl %esp, %ebp
|
|
|
|
|
|
+ movl %esp, %ebx
|
|
movl PER_CPU_VAR(cpu_current_top_of_stack), %esp
|
|
movl PER_CPU_VAR(cpu_current_top_of_stack), %esp
|
|
TRACE_IRQS_OFF
|
|
TRACE_IRQS_OFF
|
|
call do_debug
|
|
call do_debug
|
|
- movl %ebp, %esp
|
|
|
|
|
|
+ movl %ebx, %esp
|
|
jmp ret_from_exception
|
|
jmp ret_from_exception
|
|
END(debug)
|
|
END(debug)
|
|
|
|
|
|
@@ -1141,6 +1163,7 @@ ENTRY(nmi)
|
|
|
|
|
|
pushl %eax # pt_regs->orig_ax
|
|
pushl %eax # pt_regs->orig_ax
|
|
SAVE_ALL
|
|
SAVE_ALL
|
|
|
|
+ ENCODE_FRAME_POINTER
|
|
xorl %edx, %edx # zero error code
|
|
xorl %edx, %edx # zero error code
|
|
movl %esp, %eax # pt_regs pointer
|
|
movl %esp, %eax # pt_regs pointer
|
|
|
|
|
|
@@ -1159,10 +1182,10 @@ ENTRY(nmi)
|
|
* We're on the SYSENTER stack. Switch off. No one (not even debug)
|
|
* We're on the SYSENTER stack. Switch off. No one (not even debug)
|
|
* is using the thread stack right now, so it's safe for us to use it.
|
|
* is using the thread stack right now, so it's safe for us to use it.
|
|
*/
|
|
*/
|
|
- movl %esp, %ebp
|
|
|
|
|
|
+ movl %esp, %ebx
|
|
movl PER_CPU_VAR(cpu_current_top_of_stack), %esp
|
|
movl PER_CPU_VAR(cpu_current_top_of_stack), %esp
|
|
call do_nmi
|
|
call do_nmi
|
|
- movl %ebp, %esp
|
|
|
|
|
|
+ movl %ebx, %esp
|
|
jmp .Lrestore_all_notrace
|
|
jmp .Lrestore_all_notrace
|
|
|
|
|
|
#ifdef CONFIG_X86_ESPFIX32
|
|
#ifdef CONFIG_X86_ESPFIX32
|
|
@@ -1179,6 +1202,7 @@ ENTRY(nmi)
|
|
.endr
|
|
.endr
|
|
pushl %eax
|
|
pushl %eax
|
|
SAVE_ALL
|
|
SAVE_ALL
|
|
|
|
+ ENCODE_FRAME_POINTER
|
|
FIXUP_ESPFIX_STACK # %eax == %esp
|
|
FIXUP_ESPFIX_STACK # %eax == %esp
|
|
xorl %edx, %edx # zero error code
|
|
xorl %edx, %edx # zero error code
|
|
call do_nmi
|
|
call do_nmi
|
|
@@ -1192,6 +1216,7 @@ ENTRY(int3)
|
|
ASM_CLAC
|
|
ASM_CLAC
|
|
pushl $-1 # mark this as an int
|
|
pushl $-1 # mark this as an int
|
|
SAVE_ALL
|
|
SAVE_ALL
|
|
|
|
+ ENCODE_FRAME_POINTER
|
|
TRACE_IRQS_OFF
|
|
TRACE_IRQS_OFF
|
|
xorl %edx, %edx # zero error code
|
|
xorl %edx, %edx # zero error code
|
|
movl %esp, %eax # pt_regs pointer
|
|
movl %esp, %eax # pt_regs pointer
|