|
@@ -45,6 +45,7 @@
|
|
|
#include <asm/asm.h>
|
|
|
#include <asm/smap.h>
|
|
|
#include <asm/export.h>
|
|
|
+#include <asm/frame.h>
|
|
|
|
|
|
.section .entry.text, "ax"
|
|
|
|
|
@@ -237,6 +238,23 @@ ENTRY(__switch_to_asm)
|
|
|
jmp __switch_to
|
|
|
END(__switch_to_asm)
|
|
|
|
|
|
+/*
|
|
|
+ * The unwinder expects the last frame on the stack to always be at the same
|
|
|
+ * offset from the end of the page, which allows it to validate the stack.
|
|
|
+ * Calling schedule_tail() directly would break that convention because its an
|
|
|
+ * asmlinkage function so its argument has to be pushed on the stack. This
|
|
|
+ * wrapper creates a proper "end of stack" frame header before the call.
|
|
|
+ */
|
|
|
+ENTRY(schedule_tail_wrapper)
|
|
|
+ FRAME_BEGIN
|
|
|
+
|
|
|
+ pushl %eax
|
|
|
+ call schedule_tail
|
|
|
+ popl %eax
|
|
|
+
|
|
|
+ FRAME_END
|
|
|
+ ret
|
|
|
+ENDPROC(schedule_tail_wrapper)
|
|
|
/*
|
|
|
* A newly forked process directly context switches into this address.
|
|
|
*
|
|
@@ -245,9 +263,7 @@ END(__switch_to_asm)
|
|
|
* edi: kernel thread arg
|
|
|
*/
|
|
|
ENTRY(ret_from_fork)
|
|
|
- pushl %eax
|
|
|
- call schedule_tail
|
|
|
- popl %eax
|
|
|
+ call schedule_tail_wrapper
|
|
|
|
|
|
testl %ebx, %ebx
|
|
|
jnz 1f /* kernel threads are uncommon */
|