[parisc-linux-cvs] fork tidyups

Matthew Wilcox willy@ldl.fc.hp.com
Mon, 19 Feb 2001 19:21:33 -0700


 * Allocate some stack before we call schedule_tail.

 * Add a call to schedule_tail in child_return.  (I think we should be
   returning through ret_from_kernel_thread, but I haven't got that to
   work right yet.)

 * Return to child_return from copy_thread instead of storing the address
   of child_return in sys_*_wrapper.

 * Tidy up copy_thread as pb suggested.

 * Change sys_*_wrapper to use gr21 for the stack instead of gr20.  gr21
   was previously used for the return address.

 * sys_vfork_wrapper was missing a `save return address for child'
   instruction.

Index: arch/parisc/kernel/entry.S
===================================================================
RCS file: /home/cvs/parisc/linux/arch/parisc/kernel/entry.S,v
retrieving revision 1.70
diff -u -p -r1.70 entry.S
--- entry.S	2001/02/16 03:00:39	1.70
+++ entry.S	2001/02/20 02:08:40
@@ -508,9 +508,10 @@ ret_from_kernel_thread:
 
 	/* Call schedule_tail first though */
 	
-	bl	schedule_tail, %r2
-	nop
+	b,l	schedule_tail, %r2
+	ldo	64(%r30), %r30
 
+	ldo	-64(%r30), %r30
 	LDREG	TASK_PT_GR26-TASK_SZ_ALGN(%r30), %r1
 	LDREG	TASK_PT_GR25-TASK_SZ_ALGN(%r30), %r26
 	ble	0(%sr7, %r1)
@@ -1752,6 +1753,7 @@ tlb_fault:
 	.endm
 
 	.export sys_fork_wrapper
+	.export child_return
 sys_fork_wrapper:
 	ldo	TASK_REGS-TASK_SZ_ALGN-FRAME_SIZE(%r30),%r1	/* get pt regs */
 	reg_save %r1
@@ -1765,10 +1767,7 @@ sys_fork_wrapper:
 	/* These are call-clobbered registers and therefore
 	   also syscall-clobbered (we hope). */
 	STREG	%r2,PT_GR19(%r1)	/* save for child */
-	STREG	%r30,PT_GR20(%r1)
-	ldil    L%child_return,%r3
-	ldo     R%child_return(%r3),%r3
-	STREG	%r3,PT_GR21(%r1)	/* save for child */
+	STREG	%r30,PT_GR21(%r1)
 
 	LDREG	PT_GR30(%r1),%r25
 	copy	%r1,%r24
@@ -1787,6 +1786,10 @@ wrapper_exit:
 
 	/* Set the return value for the child */
 child_return:
+	b,l	schedule_tail, %r2
+	ldo	64(%r30), %r30
+
+	ldo	-64(%r30), %r30
 	LDREG	TASK_PT_GR19-TASK_SZ_ALGN-FRAME_SIZE-FRAME_SIZE(%r30),%r2
 	b	wrapper_exit
 	copy	%r0,%r28
@@ -1804,10 +1807,7 @@ sys_clone_wrapper:
 #endif
 
 	STREG	%r2,PT_GR19(%r1)	/* save for child */
-	STREG	%r30,PT_GR20(%r1)
-	ldil	L%child_return,%r3
-	ldo	R%child_return(%r3),%r3
-	STREG	%r3,PT_GR21(%r1)	/* save for child */
+	STREG	%r30,PT_GR21(%r1)
 
 	bl	sys_clone,%r2
 	copy	%r1,%r24
@@ -1826,10 +1826,8 @@ sys_vfork_wrapper:
 	ldo	-16(%r30),%r29		/* Reference param save area */
 #endif
 
-	STREG	%r30,PT_GR20(%r1)
-	ldil	L%child_return,%r3
-	ldo	R%child_return(%r3),%r3
-	STREG	%r3,PT_GR21(%r1)	/* save for child */
+	STREG	%r2,PT_GR19(%r1)	/* save for child */
+	STREG	%r30,PT_GR21(%r1)
 
 	bl	sys_vfork,%r2
 	copy	%r1,%r26
Index: arch/parisc/kernel/process.c
===================================================================
RCS file: /home/cvs/parisc/linux/arch/parisc/kernel/process.c,v
retrieving revision 1.30
diff -u -p -r1.30 process.c
--- process.c	2001/02/16 03:03:54	1.30
+++ process.c	2001/02/20 02:08:40
@@ -36,16 +36,6 @@
 #include <asm/gsc.h>
 #include <asm/processor.h>
 
-#ifdef __LP64__
-/* The 64-bit code should work equally well in 32-bit land but I didn't
- * want to take the time to confirm that.  -PB
- */
-extern unsigned int ret_from_kernel_thread;
-#else
-asmlinkage void ret_from_kernel_thread(void) __asm__("ret_from_kernel_thread");
-#endif
-
-
 int hlt_counter=0;
 
 /*
@@ -228,6 +218,11 @@ copy_thread(int nr, unsigned long clone_
 	    struct task_struct * p, struct pt_regs * pregs)
 {
 	struct pt_regs * cregs = &(p->thread.regs);
+	
+	/* We have to use void * instead of a function pointer, because
+	 * function pointers aren't a pointer to the function on 64-bit */
+	extern void *ret_from_kernel_thread;
+	extern void *child_return;
 
 	*cregs = *pregs;
 
@@ -236,6 +231,11 @@ copy_thread(int nr, unsigned long clone_
            here for consistency in case of signals. */
 	cregs->gr[28] = 0; /* child */
 
+	/* Must exit via ret_from_kernel_thread in order to call
+	 * schedule_tail()
+	 */
+	cregs->kpc = (unsigned long) &ret_from_kernel_thread;
+
 	/*
 	 * We need to differentiate between a user fork and a
 	 * kernel fork. We can't use user_mode, because the
@@ -244,34 +244,25 @@ copy_thread(int nr, unsigned long clone_
 	 * in zero for usp.
 	 */
 	if (usp == 0) {
-		/* Kernel Thread */
-		unsigned long ksp = (((unsigned long)(p)) + TASK_SZ_ALGN);
-		cregs->ksp = ksp;	    /* always return to kernel */
-#ifdef __LP64__
-		cregs->kpc = (unsigned long) &ret_from_kernel_thread;
-#else
-		cregs->kpc = (unsigned long) ret_from_kernel_thread;
-#endif
-
+		/* kernel thread */
+		cregs->ksp = (((unsigned long)(p)) + TASK_SZ_ALGN);
 		/*
 		 * Copy function and argument to be called from
 		 * ret_from_kernel_thread.
 		 */
 		cregs->gr[26] = pregs->gr[26];
 		cregs->gr[25] = pregs->gr[25];
-
 	} else {
-		/* User Thread:
-		 *
-		 * Use same stack depth as parent when in wrapper
-		 *
+		/* user thread */
+		/*
 		 * Note that the fork wrappers are responsible
-		 * for setting gr[20] and gr[21].
+		 * for setting gr[21].
 		 */
 
+		/* Use same stack depth as parent */
 		cregs->ksp = ((unsigned long)(p))
-			+ (pregs->gr[20] & (INIT_TASK_SIZE - 1));
-		cregs->kpc = pregs->gr[21];
+			+ (pregs->gr[21] & (INIT_TASK_SIZE - 1));
+		cregs->kpc = &child_return;
 		cregs->gr[30] = usp;
 	}