aboutsummaryrefslogtreecommitdiffstats
path: root/arch/parisc/kernel
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2012-10-03 23:28:08 -0400
committerAl Viro <viro@zeniv.linux.org.uk>2012-10-14 19:36:30 -0400
commita44e060fc523c379341e35a981c09c3953cf4ba4 (patch)
treef32db182b2f746acd95cd7dbb8794352a8f98eb4 /arch/parisc/kernel
parentddffeb8c4d0331609ef2581d84de4d763607bd37 (diff)
parisc: switch to generic kernel_thread()
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'arch/parisc/kernel')
-rw-r--r--arch/parisc/kernel/entry.S53
-rw-r--r--arch/parisc/kernel/process.c53
2 files changed, 17 insertions, 89 deletions
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
724ENTRY(__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
757ENDPROC(__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
766ENTRY(ret_from_kernel_thread) 716ENTRY(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;
165EXPORT_SYMBOL(pm_power_off); 165EXPORT_SYMBOL(pm_power_off);
166 166
167/* 167/*
168 * Create a kernel thread
169 */
170
171extern pid_t __kernel_thread(int (*fn)(void *), void *arg, unsigned long flags);
172pid_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}
182EXPORT_SYMBOL(kernel_thread);
183
184/*
185 * Free current thread data structures etc.. 168 * Free current thread data structures etc..
186 */ 169 */
187void exit_thread(void) 170void exit_thread(void)
@@ -256,8 +239,8 @@ sys_vfork(struct pt_regs *regs)
256 239
257int 240int
258copy_thread(unsigned long clone_flags, unsigned long usp, 241copy_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));