[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;
}