aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/kernel/process.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/kernel/process.c')
-rw-r--r--arch/arm/kernel/process.c23
1 files changed, 14 insertions, 9 deletions
diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c
index 090ac9459da1..43557a1eb610 100644
--- a/arch/arm/kernel/process.c
+++ b/arch/arm/kernel/process.c
@@ -358,17 +358,21 @@ EXPORT_SYMBOL(dump_fpu);
358 358
359/* 359/*
360 * Shuffle the argument into the correct register before calling the 360 * Shuffle the argument into the correct register before calling the
361 * thread function. r1 is the thread argument, r2 is the pointer to 361 * thread function. r4 is the thread argument, r5 is the pointer to
362 * the thread function, and r3 points to the exit function. 362 * the thread function, and r6 points to the exit function.
363 */ 363 */
364extern void kernel_thread_helper(void); 364extern void kernel_thread_helper(void);
365asm( ".pushsection .text\n" 365asm( ".pushsection .text\n"
366" .align\n" 366" .align\n"
367" .type kernel_thread_helper, #function\n" 367" .type kernel_thread_helper, #function\n"
368"kernel_thread_helper:\n" 368"kernel_thread_helper:\n"
369" mov r0, r1\n" 369#ifdef CONFIG_TRACE_IRQFLAGS
370" mov lr, r3\n" 370" bl trace_hardirqs_on\n"
371" mov pc, r2\n" 371#endif
372" msr cpsr_c, r7\n"
373" mov r0, r4\n"
374" mov lr, r6\n"
375" mov pc, r5\n"
372" .size kernel_thread_helper, . - kernel_thread_helper\n" 376" .size kernel_thread_helper, . - kernel_thread_helper\n"
373" .popsection"); 377" .popsection");
374 378
@@ -398,11 +402,12 @@ pid_t kernel_thread(int (*fn)(void *), void *arg, unsigned long flags)
398 402
399 memset(&regs, 0, sizeof(regs)); 403 memset(&regs, 0, sizeof(regs));
400 404
401 regs.ARM_r1 = (unsigned long)arg; 405 regs.ARM_r4 = (unsigned long)arg;
402 regs.ARM_r2 = (unsigned long)fn; 406 regs.ARM_r5 = (unsigned long)fn;
403 regs.ARM_r3 = (unsigned long)kernel_thread_exit; 407 regs.ARM_r6 = (unsigned long)kernel_thread_exit;
408 regs.ARM_r7 = SVC_MODE | PSR_ENDSTATE | PSR_ISETSTATE;
404 regs.ARM_pc = (unsigned long)kernel_thread_helper; 409 regs.ARM_pc = (unsigned long)kernel_thread_helper;
405 regs.ARM_cpsr = SVC_MODE | PSR_ENDSTATE | PSR_ISETSTATE; 410 regs.ARM_cpsr = regs.ARM_r7 | PSR_I_BIT;
406 411
407 return do_fork(flags|CLONE_VM|CLONE_UNTRACED, 0, &regs, 0, NULL, NULL); 412 return do_fork(flags|CLONE_VM|CLONE_UNTRACED, 0, &regs, 0, NULL, NULL);
408} 413}