diff options
| author | Al Viro <viro@zeniv.linux.org.uk> | 2012-10-03 23:28:08 -0400 |
|---|---|---|
| committer | Al Viro <viro@zeniv.linux.org.uk> | 2012-10-14 19:36:30 -0400 |
| commit | a44e060fc523c379341e35a981c09c3953cf4ba4 (patch) | |
| tree | f32db182b2f746acd95cd7dbb8794352a8f98eb4 | |
| parent | ddffeb8c4d0331609ef2581d84de4d763607bd37 (diff) | |
parisc: switch to generic kernel_thread()
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
| -rw-r--r-- | arch/parisc/Kconfig | 1 | ||||
| -rw-r--r-- | arch/parisc/kernel/entry.S | 53 | ||||
| -rw-r--r-- | arch/parisc/kernel/process.c | 53 |
3 files changed, 18 insertions, 89 deletions
diff --git a/arch/parisc/Kconfig b/arch/parisc/Kconfig index 11def45b98c5..c779da7cd96b 100644 --- a/arch/parisc/Kconfig +++ b/arch/parisc/Kconfig | |||
| @@ -22,6 +22,7 @@ config PARISC | |||
| 22 | select GENERIC_STRNCPY_FROM_USER | 22 | select GENERIC_STRNCPY_FROM_USER |
| 23 | select HAVE_MOD_ARCH_SPECIFIC | 23 | select HAVE_MOD_ARCH_SPECIFIC |
| 24 | select MODULES_USE_ELF_RELA | 24 | select MODULES_USE_ELF_RELA |
| 25 | select GENERIC_KERNEL_THREAD | ||
| 25 | 26 | ||
| 26 | help | 27 | help |
| 27 | The PA-RISC microprocessor is designed by Hewlett-Packard and used | 28 | The PA-RISC microprocessor is designed by Hewlett-Packard and used |
diff --git a/arch/parisc/kernel/entry.S b/arch/parisc/kernel/entry.S index 18670a078849..18d05e7373b5 100644 --- a/arch/parisc/kernel/entry.S +++ b/arch/parisc/kernel/entry.S | |||
| @@ -708,59 +708,9 @@ ENTRY(end_fault_vector) | |||
| 708 | .import do_cpu_irq_mask,code | 708 | .import do_cpu_irq_mask,code |
| 709 | 709 | ||
| 710 | /* | 710 | /* |
| 711 | * r26 = function to be called | ||
| 712 | * r25 = argument to pass in | ||
| 713 | * r24 = flags for do_fork() | ||
| 714 | * | ||
| 715 | * Kernel threads don't ever return, so they don't need | ||
| 716 | * a true register context. We just save away the arguments | ||
| 717 | * for copy_thread/ret_ to properly set up the child. | ||
| 718 | */ | ||
| 719 | |||
| 720 | #define CLONE_VM 0x100 /* Must agree with <linux/sched.h> */ | ||
| 721 | #define CLONE_UNTRACED 0x00800000 | ||
| 722 | |||
| 723 | .import do_fork | ||
| 724 | ENTRY(__kernel_thread) | ||
| 725 | STREG %r2, -RP_OFFSET(%r30) | ||
| 726 | |||
| 727 | copy %r30, %r1 | ||
| 728 | ldo PT_SZ_ALGN(%r30),%r30 | ||
| 729 | #ifdef CONFIG_64BIT | ||
| 730 | /* Yo, function pointers in wide mode are little structs... -PB */ | ||
| 731 | ldd 24(%r26), %r2 | ||
| 732 | STREG %r2, PT_GR27(%r1) /* Store childs %dp */ | ||
| 733 | ldd 16(%r26), %r26 | ||
| 734 | |||
| 735 | STREG %r22, PT_GR22(%r1) /* save r22 (arg5) */ | ||
| 736 | copy %r0, %r22 /* user_tid */ | ||
| 737 | #endif | ||
| 738 | STREG %r26, PT_GR26(%r1) /* Store function & argument for child */ | ||
| 739 | STREG %r25, PT_GR25(%r1) | ||
| 740 | ldil L%CLONE_UNTRACED, %r26 | ||
| 741 | ldo CLONE_VM(%r26), %r26 /* Force CLONE_VM since only init_mm */ | ||
| 742 | or %r26, %r24, %r26 /* will have kernel mappings. */ | ||
| 743 | ldi 1, %r25 /* stack_start, signals kernel thread */ | ||
| 744 | stw %r0, -52(%r30) /* user_tid */ | ||
| 745 | #ifdef CONFIG_64BIT | ||
| 746 | ldo -16(%r30),%r29 /* Reference param save area */ | ||
| 747 | #endif | ||
| 748 | BL do_fork, %r2 | ||
| 749 | copy %r1, %r24 /* pt_regs */ | ||
| 750 | |||
| 751 | /* Parent Returns here */ | ||
| 752 | |||
| 753 | LDREG -PT_SZ_ALGN-RP_OFFSET(%r30), %r2 | ||
| 754 | ldo -PT_SZ_ALGN(%r30), %r30 | ||
| 755 | bv %r0(%r2) | ||
| 756 | nop | ||
| 757 | ENDPROC(__kernel_thread) | ||
| 758 | |||
| 759 | /* | ||
| 760 | * Child Returns here | 711 | * Child Returns here |
| 761 | * | 712 | * |
| 762 | * copy_thread moved args from temp save area set up above | 713 | * copy_thread moved args into task save area. |
| 763 | * into task save area. | ||
| 764 | */ | 714 | */ |
| 765 | 715 | ||
| 766 | ENTRY(ret_from_kernel_thread) | 716 | ENTRY(ret_from_kernel_thread) |
| @@ -773,7 +723,6 @@ ENTRY(ret_from_kernel_thread) | |||
| 773 | LDREG TASK_PT_GR25(%r1), %r26 | 723 | LDREG TASK_PT_GR25(%r1), %r26 |
| 774 | #ifdef CONFIG_64BIT | 724 | #ifdef CONFIG_64BIT |
| 775 | LDREG TASK_PT_GR27(%r1), %r27 | 725 | LDREG TASK_PT_GR27(%r1), %r27 |
| 776 | LDREG TASK_PT_GR22(%r1), %r22 | ||
| 777 | #endif | 726 | #endif |
| 778 | LDREG TASK_PT_GR26(%r1), %r1 | 727 | LDREG TASK_PT_GR26(%r1), %r1 |
| 779 | ble 0(%sr7, %r1) | 728 | ble 0(%sr7, %r1) |
diff --git a/arch/parisc/kernel/process.c b/arch/parisc/kernel/process.c index cbc37216bf90..b7b4126774e0 100644 --- a/arch/parisc/kernel/process.c +++ b/arch/parisc/kernel/process.c | |||
| @@ -165,23 +165,6 @@ void (*pm_power_off)(void) = machine_power_off; | |||
| 165 | EXPORT_SYMBOL(pm_power_off); | 165 | EXPORT_SYMBOL(pm_power_off); |
| 166 | 166 | ||
| 167 | /* | 167 | /* |
| 168 | * Create a kernel thread | ||
| 169 | */ | ||
| 170 | |||
| 171 | extern pid_t __kernel_thread(int (*fn)(void *), void *arg, unsigned long flags); | ||
| 172 | pid_t kernel_thread(int (*fn)(void *), void *arg, unsigned long flags) | ||
| 173 | { | ||
| 174 | |||
| 175 | /* | ||
| 176 | * FIXME: Once we are sure we don't need any debug here, | ||
| 177 | * kernel_thread can become a #define. | ||
| 178 | */ | ||
| 179 | |||
| 180 | return __kernel_thread(fn, arg, flags); | ||
| 181 | } | ||
| 182 | EXPORT_SYMBOL(kernel_thread); | ||
| 183 | |||
| 184 | /* | ||
| 185 | * Free current thread data structures etc.. | 168 | * Free current thread data structures etc.. |
| 186 | */ | 169 | */ |
| 187 | void exit_thread(void) | 170 | void exit_thread(void) |
| @@ -256,8 +239,8 @@ sys_vfork(struct pt_regs *regs) | |||
| 256 | 239 | ||
| 257 | int | 240 | int |
| 258 | copy_thread(unsigned long clone_flags, unsigned long usp, | 241 | copy_thread(unsigned long clone_flags, unsigned long usp, |
| 259 | unsigned long unused, /* in ia64 this is "user_stack_size" */ | 242 | unsigned long arg, |
| 260 | struct task_struct * p, struct pt_regs * pregs) | 243 | struct task_struct *p, struct pt_regs *pregs) |
| 261 | { | 244 | { |
| 262 | struct pt_regs * cregs = &(p->thread.regs); | 245 | struct pt_regs * cregs = &(p->thread.regs); |
| 263 | void *stack = task_stack_page(p); | 246 | void *stack = task_stack_page(p); |
| @@ -271,21 +254,8 @@ copy_thread(unsigned long clone_flags, unsigned long usp, | |||
| 271 | extern void * const hpux_child_return; | 254 | extern void * const hpux_child_return; |
| 272 | #endif | 255 | #endif |
| 273 | 256 | ||
| 274 | *cregs = *pregs; | 257 | if (unlikely((p->flags & PF_KTHREAD) && usp != 0)) { |
| 275 | 258 | memset(cregs, 0, sizeof(struct pt_regs)); | |
| 276 | /* Set the return value for the child. Note that this is not | ||
| 277 | actually restored by the syscall exit path, but we put it | ||
| 278 | here for consistency in case of signals. */ | ||
| 279 | cregs->gr[28] = 0; /* child */ | ||
| 280 | |||
| 281 | /* | ||
| 282 | * We need to differentiate between a user fork and a | ||
| 283 | * kernel fork. We can't use user_mode, because the | ||
| 284 | * the syscall path doesn't save iaoq. Right now | ||
| 285 | * We rely on the fact that kernel_thread passes | ||
| 286 | * in zero for usp. | ||
| 287 | */ | ||
| 288 | if (usp == 1) { | ||
| 289 | /* kernel thread */ | 259 | /* kernel thread */ |
| 290 | cregs->ksp = (unsigned long)stack + THREAD_SZ_ALGN; | 260 | cregs->ksp = (unsigned long)stack + THREAD_SZ_ALGN; |
| 291 | /* Must exit via ret_from_kernel_thread in order | 261 | /* Must exit via ret_from_kernel_thread in order |
| @@ -297,10 +267,12 @@ copy_thread(unsigned long clone_flags, unsigned long usp, | |||
| 297 | * ret_from_kernel_thread. | 267 | * ret_from_kernel_thread. |
| 298 | */ | 268 | */ |
| 299 | #ifdef CONFIG_64BIT | 269 | #ifdef CONFIG_64BIT |
| 300 | cregs->gr[27] = pregs->gr[27]; | 270 | cregs->gr[27] = ((unsigned long *)usp)[3]; |
| 271 | cregs->gr[26] = ((unsigned long *)usp)[2]; | ||
| 272 | #else | ||
| 273 | cregs->gr[26] = usp; | ||
| 301 | #endif | 274 | #endif |
| 302 | cregs->gr[26] = pregs->gr[26]; | 275 | cregs->gr[25] = arg; |
| 303 | cregs->gr[25] = pregs->gr[25]; | ||
| 304 | } else { | 276 | } else { |
| 305 | /* user thread */ | 277 | /* user thread */ |
| 306 | /* | 278 | /* |
| @@ -308,6 +280,13 @@ copy_thread(unsigned long clone_flags, unsigned long usp, | |||
| 308 | * for setting gr[21]. | 280 | * for setting gr[21]. |
| 309 | */ | 281 | */ |
| 310 | 282 | ||
| 283 | *cregs = *pregs; | ||
| 284 | |||
| 285 | /* Set the return value for the child. Note that this is not | ||
| 286 | actually restored by the syscall exit path, but we put it | ||
| 287 | here for consistency in case of signals. */ | ||
| 288 | cregs->gr[28] = 0; /* child */ | ||
| 289 | |||
| 311 | /* Use same stack depth as parent */ | 290 | /* Use same stack depth as parent */ |
| 312 | cregs->ksp = (unsigned long)stack | 291 | cregs->ksp = (unsigned long)stack |
| 313 | + (pregs->gr[21] & (THREAD_SIZE - 1)); | 292 | + (pregs->gr[21] & (THREAD_SIZE - 1)); |
