diff options
Diffstat (limited to 'arch/arm/kernel/process.c')
-rw-r--r-- | arch/arm/kernel/process.c | 23 |
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 | */ |
357 | extern void kernel_thread_helper(void); | 357 | extern void kernel_thread_helper(void); |
358 | asm( ".pushsection .text\n" | 358 | asm( ".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(®s, 0, sizeof(regs)); | 396 | memset(®s, 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, ®s, 0, NULL, NULL); | 405 | return do_fork(flags|CLONE_VM|CLONE_UNTRACED, 0, ®s, 0, NULL, NULL); |
401 | } | 406 | } |