Commit ff0ab8af authored by Al Viro's avatar Al Viro
Browse files

parisc: optimizations in copy_thread() and friends



* in user thread case the registers had been copied as part of task_struct
already; no need to do it in copy_thread().
* no need to store kernel stack pointer into regs->r21; we know its offset
anyway.
* no need to clobber r3 in sys_fork_wrapper and friends - r28 will do just
as well and *it* will be overwritten anyway.
* no need to mess with storing the return address for child - it should just
use syscall_exit.
* no need to bother with separate stack frame for sys_clone() - just branch
there and be done with that.
* no need to bother with wrapper_exit - we need it only on the child_return,
so let's just do it there.
* use the same ksp for kernel threads and userland ones, while we are at it,
and let ret_from_kernel_execve() go through the normal syscall_exit.  More
straightforward is better here...

[fixes from jejb folded]

Signed-off-by: default avatarAl Viro <viro@zeniv.linux.org.uk>
parent 7f1f311a
Loading
Loading
Loading
Loading
+19 −67
Original line number Diff line number Diff line
@@ -719,7 +719,7 @@ ENTRY(ret_from_kernel_thread)
	BL	schedule_tail, %r2
	nop

	LDREG	TI_TASK-THREAD_SZ_ALGN(%r30), %r1
	LDREG	TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30), %r1
	LDREG	TASK_PT_GR25(%r1), %r26
#ifdef CONFIG_64BIT
	LDREG	TASK_PT_GR27(%r1), %r27
@@ -743,9 +743,8 @@ ENDPROC(ret_from_kernel_thread)

ENTRY(ret_from_kernel_execve)
	mfctl   %cr30, %r1
	ldo	THREAD_SZ_ALGN(%r1), %r30
	b	intr_return	/* forward */
	copy	%r26,%r16	/* pt_regs into r16 */
	b	syscall_exit	/* forward */
	ldo	THREAD_SZ_ALGN+FRAME_SIZE(%r1), %r30
ENDPROC(ret_from_kernel_execve)


@@ -1709,39 +1708,13 @@ ENTRY(sys_fork_wrapper)
	LDREG	TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30), %r1
	ldo	TASK_REGS(%r1),%r1
	reg_save %r1
	mfctl	%cr27, %r3
	STREG	%r3, PT_CR27(%r1)

	STREG	%r2,-RP_OFFSET(%r30)
	ldo	FRAME_SIZE(%r30),%r30
#ifdef CONFIG_64BIT
	ldo	-16(%r30),%r29		/* Reference param save area */
#endif

	/* These are call-clobbered registers and therefore
	   also syscall-clobbered (we hope). */
	STREG	%r2,PT_GR19(%r1)	/* save for child */
	STREG	%r30,PT_GR21(%r1)
	mfctl	%cr27, %r28
	STREG	%r28, PT_CR27(%r1)

	LDREG	PT_GR30(%r1),%r25
	copy	%r1,%r24
	BL	sys_clone,%r2
	b	sys_clone
	ldi	SIGCHLD,%r26

	LDREG	-RP_OFFSET-FRAME_SIZE(%r30),%r2
wrapper_exit:
	ldo	-FRAME_SIZE(%r30),%r30		/* get the stackframe */
	LDREG	TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1
	ldo	TASK_REGS(%r1),%r1	 /* get pt regs */

	LDREG	PT_CR27(%r1), %r3
	mtctl	%r3, %cr27
	reg_restore %r1

	/* strace expects syscall # to be preserved in r20 */
	ldi	__NR_fork,%r20
	bv %r0(%r2)
	STREG	%r20,PT_GR20(%r1)
ENDPROC(sys_fork_wrapper)

	/* Set the return value for the child */
@@ -1749,9 +1722,13 @@ ENTRY(child_return)
	BL	schedule_tail, %r2
	nop

	LDREG	TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE-FRAME_SIZE(%r30), %r1
	LDREG	TASK_PT_GR19(%r1),%r2
	b	wrapper_exit
	LDREG	TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30), %r1
	ldo	TASK_REGS(%r1),%r1	 /* get pt regs */

	LDREG	PT_CR27(%r1), %r3
	mtctl	%r3, %cr27
	reg_restore %r1
	b	syscall_exit
	copy	%r0,%r28
ENDPROC(child_return)

@@ -1760,23 +1737,10 @@ ENTRY(sys_clone_wrapper)
	LDREG	TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1
	ldo	TASK_REGS(%r1),%r1	/* get pt regs */
	reg_save %r1
	mfctl	%cr27, %r3
	STREG	%r3, PT_CR27(%r1)

	STREG	%r2,-RP_OFFSET(%r30)
	ldo	FRAME_SIZE(%r30),%r30
#ifdef CONFIG_64BIT
	ldo	-16(%r30),%r29		/* Reference param save area */
#endif

	/* WARNING - Clobbers r19 and r21, userspace must save these! */
	STREG	%r2,PT_GR19(%r1)	/* save for child */
	STREG	%r30,PT_GR21(%r1)
	BL	sys_clone,%r2
	mfctl	%cr27, %r28
	STREG	%r28, PT_CR27(%r1)
	b	sys_clone
	copy	%r1,%r24

	b	wrapper_exit
	LDREG	-RP_OFFSET-FRAME_SIZE(%r30),%r2
ENDPROC(sys_clone_wrapper)


@@ -1784,23 +1748,11 @@ ENTRY(sys_vfork_wrapper)
	LDREG	TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1
	ldo	TASK_REGS(%r1),%r1	/* get pt regs */
	reg_save %r1
	mfctl	%cr27, %r3
	STREG	%r3, PT_CR27(%r1)

	STREG	%r2,-RP_OFFSET(%r30)
	ldo	FRAME_SIZE(%r30),%r30
#ifdef CONFIG_64BIT
	ldo	-16(%r30),%r29		/* Reference param save area */
#endif
	mfctl	%cr27, %r28
	STREG	%r28, PT_CR27(%r1)

	STREG	%r2,PT_GR19(%r1)	/* save for child */
	STREG	%r30,PT_GR21(%r1)

	BL	sys_vfork,%r2
	b	sys_vfork
	copy	%r1,%r26

	b	wrapper_exit
	LDREG	-RP_OFFSET-FRAME_SIZE(%r30),%r2
ENDPROC(sys_vfork_wrapper)

	
+8 −20
Original line number Diff line number Diff line
@@ -52,6 +52,7 @@

#include <asm/io.h>
#include <asm/asm-offsets.h>
#include <asm/assembly.h>
#include <asm/pdc.h>
#include <asm/pdc_chassis.h>
#include <asm/pgalloc.h>
@@ -253,14 +254,16 @@ copy_thread(unsigned long clone_flags, unsigned long usp,
#ifdef CONFIG_HPUX
	extern void * const hpux_child_return;
#endif

	if (unlikely((p->flags & PF_KTHREAD) && usp != 0)) {
	if (unlikely(p->flags & PF_KTHREAD)) {
		memset(cregs, 0, sizeof(struct pt_regs));
		if (!usp) /* idle thread */
			return 0;

		/* kernel thread */
		cregs->ksp = (unsigned long)stack + THREAD_SZ_ALGN;
		/* Must exit via ret_from_kernel_thread in order
		 * to call schedule_tail()
		 */
		cregs->ksp = (unsigned long)stack + THREAD_SZ_ALGN + FRAME_SIZE;
		cregs->kpc = (unsigned long) &ret_from_kernel_thread;
		/*
		 * Copy function and argument to be called from
@@ -275,22 +278,8 @@ copy_thread(unsigned long clone_flags, unsigned long usp,
		cregs->gr[25] = arg;
	} else {
		/* user thread */
		/*
		 * Note that the fork wrappers are responsible
		 * for setting gr[21].
		 */

		*cregs = *pregs;

		/* Set the return value for the child.  Note that this is not
		   actually restored by the syscall exit path, but we put it
		   here for consistency in case of signals. */
		cregs->gr[28] = 0; /* child */

		/* Use same stack depth as parent */
		cregs->ksp = (unsigned long)stack
			+ (pregs->gr[21] & (THREAD_SIZE - 1));
		cregs->gr[30] = usp;
		cregs->ksp = (unsigned long)stack + THREAD_SZ_ALGN + FRAME_SIZE;
		if (personality(p->personality) == PER_HPUX) {
#ifdef CONFIG_HPUX
			cregs->kpc = (unsigned long) &hpux_child_return;
@@ -303,7 +292,6 @@ copy_thread(unsigned long clone_flags, unsigned long usp,
		/* Setup thread TLS area from the 4th parameter in clone */
		if (clone_flags & CLONE_SETTLS)
			cregs->cr27 = pregs->gr[23];
	
	}

	return 0;