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 acf5e6fdb6dc..a4a9cc88bec7 100644
--- a/arch/arm/kernel/process.c
+++ b/arch/arm/kernel/process.c
@@ -351,17 +351,21 @@ EXPORT_SYMBOL(dump_fpu);
351 351
352/* 352/*
353 * Shuffle the argument into the correct register before calling the 353 * Shuffle the argument into the correct register before calling the
354 * thread function. r1 is the thread argument, r2 is the pointer to 354 * thread function. r4 is the thread argument, r5 is the pointer to
355 * the thread function, and r3 points to the exit function. 355 * the thread function, and r6 points to the exit function.
356 */ 356 */
357extern void kernel_thread_helper(void); 357extern void kernel_thread_helper(void);
358asm( ".pushsection .text\n" 358asm( ".pushsection .text\n"
359" .align\n" 359" .align\n"
360" .type kernel_thread_helper, #function\n" 360" .type kernel_thread_helper, #function\n"
361"kernel_thread_helper:\n" 361"kernel_thread_helper:\n"
362" mov r0, r1\n" 362#ifdef CONFIG_TRACE_IRQFLAGS
363" mov lr, r3\n" 363" bl trace_hardirqs_on\n"
364" mov pc, r2\n" 364#endif
365" msr cpsr_c, r7\n"
366" mov r0, r4\n"
367" mov lr, r6\n"
368" mov pc, r5\n"
365" .size kernel_thread_helper, . - kernel_thread_helper\n" 369" .size kernel_thread_helper, . - kernel_thread_helper\n"
366" .popsection"); 370" .popsection");
367 371
@@ -391,11 +395,12 @@ pid_t kernel_thread(int (*fn)(void *), void *arg, unsigned long flags)
391 395
392 memset(&regs, 0, sizeof(regs)); 396 memset(&regs, 0, sizeof(regs));
393 397
394 regs.ARM_r1 = (unsigned long)arg; 398 regs.ARM_r4 = (unsigned long)arg;
395 regs.ARM_r2 = (unsigned long)fn; 399 regs.ARM_r5 = (unsigned long)fn;
396 regs.ARM_r3 = (unsigned long)kernel_thread_exit; 400 regs.ARM_r6 = (unsigned long)kernel_thread_exit;
401 regs.ARM_r7 = SVC_MODE | PSR_ENDSTATE | PSR_ISETSTATE;
397 regs.ARM_pc = (unsigned long)kernel_thread_helper; 402 regs.ARM_pc = (unsigned long)kernel_thread_helper;
398 regs.ARM_cpsr = SVC_MODE | PSR_ENDSTATE | PSR_ISETSTATE; 403 regs.ARM_cpsr = regs.ARM_r7 | PSR_I_BIT;
399 404
400 return do_fork(flags|CLONE_VM|CLONE_UNTRACED, 0, &regs, 0, NULL, NULL); 405 return do_fork(flags|CLONE_VM|CLONE_UNTRACED, 0, &regs, 0, NULL, NULL);
401} 406}