diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2012-10-05 18:55:57 -0400 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2012-10-14 19:36:37 -0400 |
commit | ff0ab8af9c3f36e7b6f716c3b9e8811a4202eec6 (patch) | |
tree | 78f5dba557a1f91b868fa0118516562b6cd28244 /arch/parisc | |
parent | 7f1f311ac7b7b9c779fd207a20369f7fa3a61ba6 (diff) |
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: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'arch/parisc')
-rw-r--r-- | arch/parisc/kernel/entry.S | 86 | ||||
-rw-r--r-- | arch/parisc/kernel/process.c | 28 |
2 files changed, 27 insertions, 87 deletions
diff --git a/arch/parisc/kernel/entry.S b/arch/parisc/kernel/entry.S index 7d22e97347b7..47fb6ddcf12e 100644 --- a/arch/parisc/kernel/entry.S +++ b/arch/parisc/kernel/entry.S | |||
@@ -719,7 +719,7 @@ ENTRY(ret_from_kernel_thread) | |||
719 | BL schedule_tail, %r2 | 719 | BL schedule_tail, %r2 |
720 | nop | 720 | nop |
721 | 721 | ||
722 | LDREG TI_TASK-THREAD_SZ_ALGN(%r30), %r1 | 722 | LDREG TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30), %r1 |
723 | LDREG TASK_PT_GR25(%r1), %r26 | 723 | LDREG TASK_PT_GR25(%r1), %r26 |
724 | #ifdef CONFIG_64BIT | 724 | #ifdef CONFIG_64BIT |
725 | LDREG TASK_PT_GR27(%r1), %r27 | 725 | LDREG TASK_PT_GR27(%r1), %r27 |
@@ -743,9 +743,8 @@ ENDPROC(ret_from_kernel_thread) | |||
743 | 743 | ||
744 | ENTRY(ret_from_kernel_execve) | 744 | ENTRY(ret_from_kernel_execve) |
745 | mfctl %cr30, %r1 | 745 | mfctl %cr30, %r1 |
746 | ldo THREAD_SZ_ALGN(%r1), %r30 | 746 | b syscall_exit /* forward */ |
747 | b intr_return /* forward */ | 747 | ldo THREAD_SZ_ALGN+FRAME_SIZE(%r1), %r30 |
748 | copy %r26,%r16 /* pt_regs into r16 */ | ||
749 | ENDPROC(ret_from_kernel_execve) | 748 | ENDPROC(ret_from_kernel_execve) |
750 | 749 | ||
751 | 750 | ||
@@ -1709,39 +1708,13 @@ ENTRY(sys_fork_wrapper) | |||
1709 | LDREG TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30), %r1 | 1708 | LDREG TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30), %r1 |
1710 | ldo TASK_REGS(%r1),%r1 | 1709 | ldo TASK_REGS(%r1),%r1 |
1711 | reg_save %r1 | 1710 | reg_save %r1 |
1712 | mfctl %cr27, %r3 | 1711 | mfctl %cr27, %r28 |
1713 | STREG %r3, PT_CR27(%r1) | 1712 | STREG %r28, PT_CR27(%r1) |
1714 | |||
1715 | STREG %r2,-RP_OFFSET(%r30) | ||
1716 | ldo FRAME_SIZE(%r30),%r30 | ||
1717 | #ifdef CONFIG_64BIT | ||
1718 | ldo -16(%r30),%r29 /* Reference param save area */ | ||
1719 | #endif | ||
1720 | |||
1721 | /* These are call-clobbered registers and therefore | ||
1722 | also syscall-clobbered (we hope). */ | ||
1723 | STREG %r2,PT_GR19(%r1) /* save for child */ | ||
1724 | STREG %r30,PT_GR21(%r1) | ||
1725 | 1713 | ||
1726 | LDREG PT_GR30(%r1),%r25 | 1714 | LDREG PT_GR30(%r1),%r25 |
1727 | copy %r1,%r24 | 1715 | copy %r1,%r24 |
1728 | BL sys_clone,%r2 | 1716 | b sys_clone |
1729 | ldi SIGCHLD,%r26 | 1717 | ldi SIGCHLD,%r26 |
1730 | |||
1731 | LDREG -RP_OFFSET-FRAME_SIZE(%r30),%r2 | ||
1732 | wrapper_exit: | ||
1733 | ldo -FRAME_SIZE(%r30),%r30 /* get the stackframe */ | ||
1734 | LDREG TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1 | ||
1735 | ldo TASK_REGS(%r1),%r1 /* get pt regs */ | ||
1736 | |||
1737 | LDREG PT_CR27(%r1), %r3 | ||
1738 | mtctl %r3, %cr27 | ||
1739 | reg_restore %r1 | ||
1740 | |||
1741 | /* strace expects syscall # to be preserved in r20 */ | ||
1742 | ldi __NR_fork,%r20 | ||
1743 | bv %r0(%r2) | ||
1744 | STREG %r20,PT_GR20(%r1) | ||
1745 | ENDPROC(sys_fork_wrapper) | 1718 | ENDPROC(sys_fork_wrapper) |
1746 | 1719 | ||
1747 | /* Set the return value for the child */ | 1720 | /* Set the return value for the child */ |
@@ -1749,9 +1722,13 @@ ENTRY(child_return) | |||
1749 | BL schedule_tail, %r2 | 1722 | BL schedule_tail, %r2 |
1750 | nop | 1723 | nop |
1751 | 1724 | ||
1752 | LDREG TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE-FRAME_SIZE(%r30), %r1 | 1725 | LDREG TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30), %r1 |
1753 | LDREG TASK_PT_GR19(%r1),%r2 | 1726 | ldo TASK_REGS(%r1),%r1 /* get pt regs */ |
1754 | b wrapper_exit | 1727 | |
1728 | LDREG PT_CR27(%r1), %r3 | ||
1729 | mtctl %r3, %cr27 | ||
1730 | reg_restore %r1 | ||
1731 | b syscall_exit | ||
1755 | copy %r0,%r28 | 1732 | copy %r0,%r28 |
1756 | ENDPROC(child_return) | 1733 | ENDPROC(child_return) |
1757 | 1734 | ||
@@ -1760,23 +1737,10 @@ ENTRY(sys_clone_wrapper) | |||
1760 | LDREG TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1 | 1737 | LDREG TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1 |
1761 | ldo TASK_REGS(%r1),%r1 /* get pt regs */ | 1738 | ldo TASK_REGS(%r1),%r1 /* get pt regs */ |
1762 | reg_save %r1 | 1739 | reg_save %r1 |
1763 | mfctl %cr27, %r3 | 1740 | mfctl %cr27, %r28 |
1764 | STREG %r3, PT_CR27(%r1) | 1741 | STREG %r28, PT_CR27(%r1) |
1765 | 1742 | b sys_clone | |
1766 | STREG %r2,-RP_OFFSET(%r30) | ||
1767 | ldo FRAME_SIZE(%r30),%r30 | ||
1768 | #ifdef CONFIG_64BIT | ||
1769 | ldo -16(%r30),%r29 /* Reference param save area */ | ||
1770 | #endif | ||
1771 | |||
1772 | /* WARNING - Clobbers r19 and r21, userspace must save these! */ | ||
1773 | STREG %r2,PT_GR19(%r1) /* save for child */ | ||
1774 | STREG %r30,PT_GR21(%r1) | ||
1775 | BL sys_clone,%r2 | ||
1776 | copy %r1,%r24 | 1743 | copy %r1,%r24 |
1777 | |||
1778 | b wrapper_exit | ||
1779 | LDREG -RP_OFFSET-FRAME_SIZE(%r30),%r2 | ||
1780 | ENDPROC(sys_clone_wrapper) | 1744 | ENDPROC(sys_clone_wrapper) |
1781 | 1745 | ||
1782 | 1746 | ||
@@ -1784,23 +1748,11 @@ ENTRY(sys_vfork_wrapper) | |||
1784 | LDREG TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1 | 1748 | LDREG TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1 |
1785 | ldo TASK_REGS(%r1),%r1 /* get pt regs */ | 1749 | ldo TASK_REGS(%r1),%r1 /* get pt regs */ |
1786 | reg_save %r1 | 1750 | reg_save %r1 |
1787 | mfctl %cr27, %r3 | 1751 | mfctl %cr27, %r28 |
1788 | STREG %r3, PT_CR27(%r1) | 1752 | STREG %r28, PT_CR27(%r1) |
1789 | |||
1790 | STREG %r2,-RP_OFFSET(%r30) | ||
1791 | ldo FRAME_SIZE(%r30),%r30 | ||
1792 | #ifdef CONFIG_64BIT | ||
1793 | ldo -16(%r30),%r29 /* Reference param save area */ | ||
1794 | #endif | ||
1795 | 1753 | ||
1796 | STREG %r2,PT_GR19(%r1) /* save for child */ | 1754 | b sys_vfork |
1797 | STREG %r30,PT_GR21(%r1) | ||
1798 | |||
1799 | BL sys_vfork,%r2 | ||
1800 | copy %r1,%r26 | 1755 | copy %r1,%r26 |
1801 | |||
1802 | b wrapper_exit | ||
1803 | LDREG -RP_OFFSET-FRAME_SIZE(%r30),%r2 | ||
1804 | ENDPROC(sys_vfork_wrapper) | 1756 | ENDPROC(sys_vfork_wrapper) |
1805 | 1757 | ||
1806 | 1758 | ||
diff --git a/arch/parisc/kernel/process.c b/arch/parisc/kernel/process.c index 44e8534c52e9..38db36f64307 100644 --- a/arch/parisc/kernel/process.c +++ b/arch/parisc/kernel/process.c | |||
@@ -52,6 +52,7 @@ | |||
52 | 52 | ||
53 | #include <asm/io.h> | 53 | #include <asm/io.h> |
54 | #include <asm/asm-offsets.h> | 54 | #include <asm/asm-offsets.h> |
55 | #include <asm/assembly.h> | ||
55 | #include <asm/pdc.h> | 56 | #include <asm/pdc.h> |
56 | #include <asm/pdc_chassis.h> | 57 | #include <asm/pdc_chassis.h> |
57 | #include <asm/pgalloc.h> | 58 | #include <asm/pgalloc.h> |
@@ -253,14 +254,16 @@ copy_thread(unsigned long clone_flags, unsigned long usp, | |||
253 | #ifdef CONFIG_HPUX | 254 | #ifdef CONFIG_HPUX |
254 | extern void * const hpux_child_return; | 255 | extern void * const hpux_child_return; |
255 | #endif | 256 | #endif |
256 | 257 | if (unlikely(p->flags & PF_KTHREAD)) { | |
257 | if (unlikely((p->flags & PF_KTHREAD) && usp != 0)) { | ||
258 | memset(cregs, 0, sizeof(struct pt_regs)); | 258 | memset(cregs, 0, sizeof(struct pt_regs)); |
259 | if (!usp) /* idle thread */ | ||
260 | return 0; | ||
261 | |||
259 | /* kernel thread */ | 262 | /* kernel thread */ |
260 | cregs->ksp = (unsigned long)stack + THREAD_SZ_ALGN; | ||
261 | /* Must exit via ret_from_kernel_thread in order | 263 | /* Must exit via ret_from_kernel_thread in order |
262 | * to call schedule_tail() | 264 | * to call schedule_tail() |
263 | */ | 265 | */ |
266 | cregs->ksp = (unsigned long)stack + THREAD_SZ_ALGN + FRAME_SIZE; | ||
264 | cregs->kpc = (unsigned long) &ret_from_kernel_thread; | 267 | cregs->kpc = (unsigned long) &ret_from_kernel_thread; |
265 | /* | 268 | /* |
266 | * Copy function and argument to be called from | 269 | * Copy function and argument to be called from |
@@ -275,22 +278,8 @@ copy_thread(unsigned long clone_flags, unsigned long usp, | |||
275 | cregs->gr[25] = arg; | 278 | cregs->gr[25] = arg; |
276 | } else { | 279 | } else { |
277 | /* user thread */ | 280 | /* user thread */ |
278 | /* | ||
279 | * Note that the fork wrappers are responsible | ||
280 | * for setting gr[21]. | ||
281 | */ | ||
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 | |||
290 | /* Use same stack depth as parent */ | ||
291 | cregs->ksp = (unsigned long)stack | ||
292 | + (pregs->gr[21] & (THREAD_SIZE - 1)); | ||
293 | cregs->gr[30] = usp; | 281 | cregs->gr[30] = usp; |
282 | cregs->ksp = (unsigned long)stack + THREAD_SZ_ALGN + FRAME_SIZE; | ||
294 | if (personality(p->personality) == PER_HPUX) { | 283 | if (personality(p->personality) == PER_HPUX) { |
295 | #ifdef CONFIG_HPUX | 284 | #ifdef CONFIG_HPUX |
296 | cregs->kpc = (unsigned long) &hpux_child_return; | 285 | cregs->kpc = (unsigned long) &hpux_child_return; |
@@ -302,8 +291,7 @@ copy_thread(unsigned long clone_flags, unsigned long usp, | |||
302 | } | 291 | } |
303 | /* Setup thread TLS area from the 4th parameter in clone */ | 292 | /* Setup thread TLS area from the 4th parameter in clone */ |
304 | if (clone_flags & CLONE_SETTLS) | 293 | if (clone_flags & CLONE_SETTLS) |
305 | cregs->cr27 = pregs->gr[23]; | 294 | cregs->cr27 = pregs->gr[23]; |
306 | |||
307 | } | 295 | } |
308 | 296 | ||
309 | return 0; | 297 | return 0; |