|
@@ -351,17 +351,21 @@ EXPORT_SYMBOL(dump_fpu);
|
|
|
|
|
|
/*
|
|
|
* Shuffle the argument into the correct register before calling the
|
|
|
- * thread function. r1 is the thread argument, r2 is the pointer to
|
|
|
- * the thread function, and r3 points to the exit function.
|
|
|
+ * thread function. r4 is the thread argument, r5 is the pointer to
|
|
|
+ * the thread function, and r6 points to the exit function.
|
|
|
*/
|
|
|
extern void kernel_thread_helper(void);
|
|
|
asm( ".pushsection .text\n"
|
|
|
" .align\n"
|
|
|
" .type kernel_thread_helper, #function\n"
|
|
|
"kernel_thread_helper:\n"
|
|
|
-" mov r0, r1\n"
|
|
|
-" mov lr, r3\n"
|
|
|
-" mov pc, r2\n"
|
|
|
+#ifdef CONFIG_TRACE_IRQFLAGS
|
|
|
+" bl trace_hardirqs_on\n"
|
|
|
+#endif
|
|
|
+" msr cpsr_c, r7\n"
|
|
|
+" mov r0, r4\n"
|
|
|
+" mov lr, r6\n"
|
|
|
+" mov pc, r5\n"
|
|
|
" .size kernel_thread_helper, . - kernel_thread_helper\n"
|
|
|
" .popsection");
|
|
|
|
|
@@ -391,11 +395,12 @@ pid_t kernel_thread(int (*fn)(void *), void *arg, unsigned long flags)
|
|
|
|
|
|
memset(®s, 0, sizeof(regs));
|
|
|
|
|
|
- regs.ARM_r1 = (unsigned long)arg;
|
|
|
- regs.ARM_r2 = (unsigned long)fn;
|
|
|
- regs.ARM_r3 = (unsigned long)kernel_thread_exit;
|
|
|
+ regs.ARM_r4 = (unsigned long)arg;
|
|
|
+ regs.ARM_r5 = (unsigned long)fn;
|
|
|
+ regs.ARM_r6 = (unsigned long)kernel_thread_exit;
|
|
|
+ regs.ARM_r7 = SVC_MODE | PSR_ENDSTATE | PSR_ISETSTATE;
|
|
|
regs.ARM_pc = (unsigned long)kernel_thread_helper;
|
|
|
- regs.ARM_cpsr = SVC_MODE | PSR_ENDSTATE | PSR_ISETSTATE;
|
|
|
+ regs.ARM_cpsr = regs.ARM_r7 | PSR_I_BIT;
|
|
|
|
|
|
return do_fork(flags|CLONE_VM|CLONE_UNTRACED, 0, ®s, 0, NULL, NULL);
|
|
|
}
|