Skip to content

Commit

Permalink
parisc: optimizations in copy_thread() and friends
Browse files Browse the repository at this point in the history
* 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: Al Viro <viro@zeniv.linux.org.uk>
  • Loading branch information
Al Viro committed Oct 14, 2012
1 parent 7f1f311 commit ff0ab8a
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 87 deletions.
86 changes: 19 additions & 67 deletions arch/parisc/kernel/entry.S
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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)


Expand Down Expand Up @@ -1709,49 +1708,27 @@ 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 */
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)

Expand All @@ -1760,47 +1737,22 @@ 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)


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)


Expand Down
28 changes: 8 additions & 20 deletions arch/parisc/kernel/process.c
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down Expand Up @@ -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
Expand All @@ -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;
Expand All @@ -302,8 +291,7 @@ 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];

cregs->cr27 = pregs->gr[23];
}

return 0;
Expand Down

0 comments on commit ff0ab8a

Please sign in to comment.