aboutsummaryrefslogtreecommitdiffstats
path: root/arch/parisc
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-12-12 15:22:13 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2012-12-12 15:22:13 -0500
commit9977d9b379cb77e0f67bd6f4563618106e58e11d (patch)
tree0191accfddf578edb52c69c933d64521e3dce297 /arch/parisc
parentcf4af01221579a4e895f43dbfc47598fbfc5a731 (diff)
parent541880d9a2c7871f6370071d55aa6662d329c51e (diff)
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/signal
Pull big execve/kernel_thread/fork unification series from Al Viro: "All architectures are converted to new model. Quite a bit of that stuff is actually shared with architecture trees; in such cases it's literally shared branch pulled by both, not a cherry-pick. A lot of ugliness and black magic is gone (-3KLoC total in this one): - kernel_thread()/kernel_execve()/sys_execve() redesign. We don't do syscalls from kernel anymore for either kernel_thread() or kernel_execve(): kernel_thread() is essentially clone(2) with callback run before we return to userland, the callbacks either never return or do successful do_execve() before returning. kernel_execve() is a wrapper for do_execve() - it doesn't need to do transition to user mode anymore. As a result kernel_thread() and kernel_execve() are arch-independent now - they live in kernel/fork.c and fs/exec.c resp. sys_execve() is also in fs/exec.c and it's completely architecture-independent. - daemonize() is gone, along with its parts in fs/*.c - struct pt_regs * is no longer passed to do_fork/copy_process/ copy_thread/do_execve/search_binary_handler/->load_binary/do_coredump. - sys_fork()/sys_vfork()/sys_clone() unified; some architectures still need wrappers (ones with callee-saved registers not saved in pt_regs on syscall entry), but the main part of those suckers is in kernel/fork.c now." * 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/signal: (113 commits) do_coredump(): get rid of pt_regs argument print_fatal_signal(): get rid of pt_regs argument ptrace_signal(): get rid of unused arguments get rid of ptrace_signal_deliver() arguments new helper: signal_pt_regs() unify default ptrace_signal_deliver flagday: kill pt_regs argument of do_fork() death to idle_regs() don't pass regs to copy_process() flagday: don't pass regs to copy_thread() bfin: switch to generic vfork, get rid of pointless wrappers xtensa: switch to generic clone() openrisc: switch to use of generic fork and clone unicore32: switch to generic clone(2) score: switch to generic fork/vfork/clone c6x: sanitize copy_thread(), get rid of clone(2) wrapper, switch to generic clone() take sys_fork/sys_vfork/sys_clone prototypes to linux/syscalls.h mn10300: switch to generic fork/vfork/clone h8300: switch to generic fork/vfork/clone tile: switch to generic clone() ... Conflicts: arch/microblaze/include/asm/Kbuild
Diffstat (limited to 'arch/parisc')
-rw-r--r--arch/parisc/Kconfig3
-rw-r--r--arch/parisc/include/asm/processor.h1
-rw-r--r--arch/parisc/include/asm/signal.h2
-rw-r--r--arch/parisc/include/asm/unistd.h4
-rw-r--r--arch/parisc/kernel/entry.S241
-rw-r--r--arch/parisc/kernel/process.c142
-rw-r--r--arch/parisc/kernel/sys_parisc32.c22
-rw-r--r--arch/parisc/kernel/syscall_table.S2
8 files changed, 52 insertions, 365 deletions
diff --git a/arch/parisc/Kconfig b/arch/parisc/Kconfig
index 11def45b98c5..e688a2be30f6 100644
--- a/arch/parisc/Kconfig
+++ b/arch/parisc/Kconfig
@@ -22,6 +22,9 @@ config PARISC
22 select GENERIC_STRNCPY_FROM_USER 22 select GENERIC_STRNCPY_FROM_USER
23 select HAVE_MOD_ARCH_SPECIFIC 23 select HAVE_MOD_ARCH_SPECIFIC
24 select MODULES_USE_ELF_RELA 24 select MODULES_USE_ELF_RELA
25 select GENERIC_KERNEL_THREAD
26 select GENERIC_KERNEL_EXECVE
27 select CLONE_BACKWARDS
25 28
26 help 29 help
27 The PA-RISC microprocessor is designed by Hewlett-Packard and used 30 The PA-RISC microprocessor is designed by Hewlett-Packard and used
diff --git a/arch/parisc/include/asm/processor.h b/arch/parisc/include/asm/processor.h
index 0e8b7b8ce8a2..09b54a57a48d 100644
--- a/arch/parisc/include/asm/processor.h
+++ b/arch/parisc/include/asm/processor.h
@@ -326,7 +326,6 @@ struct mm_struct;
326 326
327/* Free all resources held by a thread. */ 327/* Free all resources held by a thread. */
328extern void release_thread(struct task_struct *); 328extern void release_thread(struct task_struct *);
329extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags);
330 329
331extern void map_hpux_gateway_page(struct task_struct *tsk, struct mm_struct *mm); 330extern void map_hpux_gateway_page(struct task_struct *tsk, struct mm_struct *mm);
332 331
diff --git a/arch/parisc/include/asm/signal.h b/arch/parisc/include/asm/signal.h
index 21abf4fc169a..0fdb3c835952 100644
--- a/arch/parisc/include/asm/signal.h
+++ b/arch/parisc/include/asm/signal.h
@@ -34,8 +34,6 @@ struct k_sigaction {
34 struct sigaction sa; 34 struct sigaction sa;
35}; 35};
36 36
37#define ptrace_signal_deliver(regs, cookie) do { } while (0)
38
39#include <asm/sigcontext.h> 37#include <asm/sigcontext.h>
40 38
41#endif /* !__ASSEMBLY */ 39#endif /* !__ASSEMBLY */
diff --git a/arch/parisc/include/asm/unistd.h b/arch/parisc/include/asm/unistd.h
index 541639c3f607..1efef41659c9 100644
--- a/arch/parisc/include/asm/unistd.h
+++ b/arch/parisc/include/asm/unistd.h
@@ -163,6 +163,10 @@ type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5) \
163#define __ARCH_WANT_SYS_RT_SIGACTION 163#define __ARCH_WANT_SYS_RT_SIGACTION
164#define __ARCH_WANT_SYS_RT_SIGSUSPEND 164#define __ARCH_WANT_SYS_RT_SIGSUSPEND
165#define __ARCH_WANT_COMPAT_SYS_RT_SIGSUSPEND 165#define __ARCH_WANT_COMPAT_SYS_RT_SIGSUSPEND
166#define __ARCH_WANT_SYS_EXECVE
167#define __ARCH_WANT_SYS_FORK
168#define __ARCH_WANT_SYS_VFORK
169#define __ARCH_WANT_SYS_CLONE
166 170
167#endif /* __ASSEMBLY__ */ 171#endif /* __ASSEMBLY__ */
168 172
diff --git a/arch/parisc/kernel/entry.S b/arch/parisc/kernel/entry.S
index 18670a078849..bfb44247d7a7 100644
--- a/arch/parisc/kernel/entry.S
+++ b/arch/parisc/kernel/entry.S
@@ -708,59 +708,9 @@ ENTRY(end_fault_vector)
708 .import do_cpu_irq_mask,code 708 .import do_cpu_irq_mask,code
709 709
710 /* 710 /*
711 * r26 = function to be called
712 * r25 = argument to pass in
713 * r24 = flags for do_fork()
714 *
715 * Kernel threads don't ever return, so they don't need
716 * a true register context. We just save away the arguments
717 * for copy_thread/ret_ to properly set up the child.
718 */
719
720#define CLONE_VM 0x100 /* Must agree with <linux/sched.h> */
721#define CLONE_UNTRACED 0x00800000
722
723 .import do_fork
724ENTRY(__kernel_thread)
725 STREG %r2, -RP_OFFSET(%r30)
726
727 copy %r30, %r1
728 ldo PT_SZ_ALGN(%r30),%r30
729#ifdef CONFIG_64BIT
730 /* Yo, function pointers in wide mode are little structs... -PB */
731 ldd 24(%r26), %r2
732 STREG %r2, PT_GR27(%r1) /* Store childs %dp */
733 ldd 16(%r26), %r26
734
735 STREG %r22, PT_GR22(%r1) /* save r22 (arg5) */
736 copy %r0, %r22 /* user_tid */
737#endif
738 STREG %r26, PT_GR26(%r1) /* Store function & argument for child */
739 STREG %r25, PT_GR25(%r1)
740 ldil L%CLONE_UNTRACED, %r26
741 ldo CLONE_VM(%r26), %r26 /* Force CLONE_VM since only init_mm */
742 or %r26, %r24, %r26 /* will have kernel mappings. */
743 ldi 1, %r25 /* stack_start, signals kernel thread */
744 stw %r0, -52(%r30) /* user_tid */
745#ifdef CONFIG_64BIT
746 ldo -16(%r30),%r29 /* Reference param save area */
747#endif
748 BL do_fork, %r2
749 copy %r1, %r24 /* pt_regs */
750
751 /* Parent Returns here */
752
753 LDREG -PT_SZ_ALGN-RP_OFFSET(%r30), %r2
754 ldo -PT_SZ_ALGN(%r30), %r30
755 bv %r0(%r2)
756 nop
757ENDPROC(__kernel_thread)
758
759 /*
760 * Child Returns here 711 * Child Returns here
761 * 712 *
762 * copy_thread moved args from temp save area set up above 713 * copy_thread moved args into task save area.
763 * into task save area.
764 */ 714 */
765 715
766ENTRY(ret_from_kernel_thread) 716ENTRY(ret_from_kernel_thread)
@@ -769,51 +719,17 @@ ENTRY(ret_from_kernel_thread)
769 BL schedule_tail, %r2 719 BL schedule_tail, %r2
770 nop 720 nop
771 721
772 LDREG TI_TASK-THREAD_SZ_ALGN(%r30), %r1 722 LDREG TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30), %r1
773 LDREG TASK_PT_GR25(%r1), %r26 723 LDREG TASK_PT_GR25(%r1), %r26
774#ifdef CONFIG_64BIT 724#ifdef CONFIG_64BIT
775 LDREG TASK_PT_GR27(%r1), %r27 725 LDREG TASK_PT_GR27(%r1), %r27
776 LDREG TASK_PT_GR22(%r1), %r22
777#endif 726#endif
778 LDREG TASK_PT_GR26(%r1), %r1 727 LDREG TASK_PT_GR26(%r1), %r1
779 ble 0(%sr7, %r1) 728 ble 0(%sr7, %r1)
780 copy %r31, %r2 729 copy %r31, %r2
781 730 b finish_child_return
782#ifdef CONFIG_64BIT
783 ldo -16(%r30),%r29 /* Reference param save area */
784 loadgp /* Thread could have been in a module */
785#endif
786#ifndef CONFIG_64BIT
787 b sys_exit
788#else
789 load32 sys_exit, %r1
790 bv %r0(%r1)
791#endif
792 ldi 0, %r26
793ENDPROC(ret_from_kernel_thread)
794
795 .import sys_execve, code
796ENTRY(__execve)
797 copy %r2, %r15
798 copy %r30, %r16
799 ldo PT_SZ_ALGN(%r30), %r30
800 STREG %r26, PT_GR26(%r16)
801 STREG %r25, PT_GR25(%r16)
802 STREG %r24, PT_GR24(%r16)
803#ifdef CONFIG_64BIT
804 ldo -16(%r30),%r29 /* Reference param save area */
805#endif
806 BL sys_execve, %r2
807 copy %r16, %r26
808
809 cmpib,=,n 0,%r28,intr_return /* forward */
810
811 /* yes, this will trap and die. */
812 copy %r15, %r2
813 copy %r16, %r30
814 bv %r0(%r2)
815 nop 731 nop
816ENDPROC(__execve) 732ENDPROC(ret_from_kernel_thread)
817 733
818 734
819 /* 735 /*
@@ -1772,151 +1688,36 @@ dtlb_fault:
1772 LDREG PT_GR18(\regs),%r18 1688 LDREG PT_GR18(\regs),%r18
1773 .endm 1689 .endm
1774 1690
1775ENTRY(sys_fork_wrapper) 1691 .macro fork_like name
1692ENTRY(sys_\name\()_wrapper)
1776 LDREG TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30), %r1 1693 LDREG TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30), %r1
1777 ldo TASK_REGS(%r1),%r1 1694 ldo TASK_REGS(%r1),%r1
1778 reg_save %r1 1695 reg_save %r1
1779 mfctl %cr27, %r3 1696 mfctl %cr27, %r28
1780 STREG %r3, PT_CR27(%r1) 1697 b sys_\name
1781 1698 STREG %r28, PT_CR27(%r1)
1782 STREG %r2,-RP_OFFSET(%r30) 1699ENDPROC(sys_\name\()_wrapper)
1783 ldo FRAME_SIZE(%r30),%r30 1700 .endm
1784#ifdef CONFIG_64BIT
1785 ldo -16(%r30),%r29 /* Reference param save area */
1786#endif
1787
1788 /* These are call-clobbered registers and therefore
1789 also syscall-clobbered (we hope). */
1790 STREG %r2,PT_GR19(%r1) /* save for child */
1791 STREG %r30,PT_GR21(%r1)
1792
1793 LDREG PT_GR30(%r1),%r25
1794 copy %r1,%r24
1795 BL sys_clone,%r2
1796 ldi SIGCHLD,%r26
1797
1798 LDREG -RP_OFFSET-FRAME_SIZE(%r30),%r2
1799wrapper_exit:
1800 ldo -FRAME_SIZE(%r30),%r30 /* get the stackframe */
1801 LDREG TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1
1802 ldo TASK_REGS(%r1),%r1 /* get pt regs */
1803
1804 LDREG PT_CR27(%r1), %r3
1805 mtctl %r3, %cr27
1806 reg_restore %r1
1807 1701
1808 /* strace expects syscall # to be preserved in r20 */ 1702fork_like clone
1809 ldi __NR_fork,%r20 1703fork_like fork
1810 bv %r0(%r2) 1704fork_like vfork
1811 STREG %r20,PT_GR20(%r1)
1812ENDPROC(sys_fork_wrapper)
1813 1705
1814 /* Set the return value for the child */ 1706 /* Set the return value for the child */
1815ENTRY(child_return) 1707ENTRY(child_return)
1816 BL schedule_tail, %r2 1708 BL schedule_tail, %r2
1817 nop 1709 nop
1710finish_child_return:
1711 LDREG TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30), %r1
1712 ldo TASK_REGS(%r1),%r1 /* get pt regs */
1818 1713
1819 LDREG TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE-FRAME_SIZE(%r30), %r1 1714 LDREG PT_CR27(%r1), %r3
1820 LDREG TASK_PT_GR19(%r1),%r2 1715 mtctl %r3, %cr27
1821 b wrapper_exit 1716 reg_restore %r1
1717 b syscall_exit
1822 copy %r0,%r28 1718 copy %r0,%r28
1823ENDPROC(child_return) 1719ENDPROC(child_return)
1824 1720
1825
1826ENTRY(sys_clone_wrapper)
1827 LDREG TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1
1828 ldo TASK_REGS(%r1),%r1 /* get pt regs */
1829 reg_save %r1
1830 mfctl %cr27, %r3
1831 STREG %r3, PT_CR27(%r1)
1832
1833 STREG %r2,-RP_OFFSET(%r30)
1834 ldo FRAME_SIZE(%r30),%r30
1835#ifdef CONFIG_64BIT
1836 ldo -16(%r30),%r29 /* Reference param save area */
1837#endif
1838
1839 /* WARNING - Clobbers r19 and r21, userspace must save these! */
1840 STREG %r2,PT_GR19(%r1) /* save for child */
1841 STREG %r30,PT_GR21(%r1)
1842 BL sys_clone,%r2
1843 copy %r1,%r24
1844
1845 b wrapper_exit
1846 LDREG -RP_OFFSET-FRAME_SIZE(%r30),%r2
1847ENDPROC(sys_clone_wrapper)
1848
1849
1850ENTRY(sys_vfork_wrapper)
1851 LDREG TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1
1852 ldo TASK_REGS(%r1),%r1 /* get pt regs */
1853 reg_save %r1
1854 mfctl %cr27, %r3
1855 STREG %r3, PT_CR27(%r1)
1856
1857 STREG %r2,-RP_OFFSET(%r30)
1858 ldo FRAME_SIZE(%r30),%r30
1859#ifdef CONFIG_64BIT
1860 ldo -16(%r30),%r29 /* Reference param save area */
1861#endif
1862
1863 STREG %r2,PT_GR19(%r1) /* save for child */
1864 STREG %r30,PT_GR21(%r1)
1865
1866 BL sys_vfork,%r2
1867 copy %r1,%r26
1868
1869 b wrapper_exit
1870 LDREG -RP_OFFSET-FRAME_SIZE(%r30),%r2
1871ENDPROC(sys_vfork_wrapper)
1872
1873
1874 .macro execve_wrapper execve
1875 LDREG TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1
1876 ldo TASK_REGS(%r1),%r1 /* get pt regs */
1877
1878 /*
1879 * Do we need to save/restore r3-r18 here?
1880 * I don't think so. why would new thread need old
1881 * threads registers?
1882 */
1883
1884 /* %arg0 - %arg3 are already saved for us. */
1885
1886 STREG %r2,-RP_OFFSET(%r30)
1887 ldo FRAME_SIZE(%r30),%r30
1888#ifdef CONFIG_64BIT
1889 ldo -16(%r30),%r29 /* Reference param save area */
1890#endif
1891 BL \execve,%r2
1892 copy %r1,%arg0
1893
1894 ldo -FRAME_SIZE(%r30),%r30
1895 LDREG -RP_OFFSET(%r30),%r2
1896
1897 /* If exec succeeded we need to load the args */
1898
1899 ldo -1024(%r0),%r1
1900 cmpb,>>= %r28,%r1,error_\execve
1901 copy %r2,%r19
1902
1903error_\execve:
1904 bv %r0(%r19)
1905 nop
1906 .endm
1907
1908 .import sys_execve
1909ENTRY(sys_execve_wrapper)
1910 execve_wrapper sys_execve
1911ENDPROC(sys_execve_wrapper)
1912
1913#ifdef CONFIG_64BIT
1914 .import sys32_execve
1915ENTRY(sys32_execve_wrapper)
1916 execve_wrapper sys32_execve
1917ENDPROC(sys32_execve_wrapper)
1918#endif
1919
1920ENTRY(sys_rt_sigreturn_wrapper) 1721ENTRY(sys_rt_sigreturn_wrapper)
1921 LDREG TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r26 1722 LDREG TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r26
1922 ldo TASK_REGS(%r26),%r26 /* get pt regs */ 1723 ldo TASK_REGS(%r26),%r26 /* get pt regs */
diff --git a/arch/parisc/kernel/process.c b/arch/parisc/kernel/process.c
index cbc37216bf90..d13507246c5d 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>
@@ -165,23 +166,6 @@ void (*pm_power_off)(void) = machine_power_off;
165EXPORT_SYMBOL(pm_power_off); 166EXPORT_SYMBOL(pm_power_off);
166 167
167/* 168/*
168 * Create a kernel thread
169 */
170
171extern pid_t __kernel_thread(int (*fn)(void *), void *arg, unsigned long flags);
172pid_t kernel_thread(int (*fn)(void *), void *arg, unsigned long flags)
173{
174
175 /*
176 * FIXME: Once we are sure we don't need any debug here,
177 * kernel_thread can become a #define.
178 */
179
180 return __kernel_thread(fn, arg, flags);
181}
182EXPORT_SYMBOL(kernel_thread);
183
184/*
185 * Free current thread data structures etc.. 169 * Free current thread data structures etc..
186 */ 170 */
187void exit_thread(void) 171void exit_thread(void)
@@ -218,48 +202,11 @@ int dump_task_fpu (struct task_struct *tsk, elf_fpregset_t *r)
218 return 1; 202 return 1;
219} 203}
220 204
221/* Note that "fork()" is implemented in terms of clone, with
222 parameters (SIGCHLD, regs->gr[30], regs). */
223int
224sys_clone(unsigned long clone_flags, unsigned long usp,
225 struct pt_regs *regs)
226{
227 /* Arugments from userspace are:
228 r26 = Clone flags.
229 r25 = Child stack.
230 r24 = parent_tidptr.
231 r23 = Is the TLS storage descriptor
232 r22 = child_tidptr
233
234 However, these last 3 args are only examined
235 if the proper flags are set. */
236 int __user *parent_tidptr = (int __user *)regs->gr[24];
237 int __user *child_tidptr = (int __user *)regs->gr[22];
238
239 /* usp must be word aligned. This also prevents users from
240 * passing in the value 1 (which is the signal for a special
241 * return for a kernel thread) */
242 usp = ALIGN(usp, 4);
243
244 /* A zero value for usp means use the current stack */
245 if (usp == 0)
246 usp = regs->gr[30];
247
248 return do_fork(clone_flags, usp, regs, 0, parent_tidptr, child_tidptr);
249}
250
251int
252sys_vfork(struct pt_regs *regs)
253{
254 return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->gr[30], regs, 0, NULL, NULL);
255}
256
257int 205int
258copy_thread(unsigned long clone_flags, unsigned long usp, 206copy_thread(unsigned long clone_flags, unsigned long usp,
259 unsigned long unused, /* in ia64 this is "user_stack_size" */ 207 unsigned long arg, struct task_struct *p)
260 struct task_struct * p, struct pt_regs * pregs)
261{ 208{
262 struct pt_regs * cregs = &(p->thread.regs); 209 struct pt_regs *cregs = &(p->thread.regs);
263 void *stack = task_stack_page(p); 210 void *stack = task_stack_page(p);
264 211
265 /* We have to use void * instead of a function pointer, because 212 /* We have to use void * instead of a function pointer, because
@@ -270,48 +217,39 @@ copy_thread(unsigned long clone_flags, unsigned long usp,
270#ifdef CONFIG_HPUX 217#ifdef CONFIG_HPUX
271 extern void * const hpux_child_return; 218 extern void * const hpux_child_return;
272#endif 219#endif
220 if (unlikely(p->flags & PF_KTHREAD)) {
221 memset(cregs, 0, sizeof(struct pt_regs));
222 if (!usp) /* idle thread */
223 return 0;
273 224
274 *cregs = *pregs;
275
276 /* Set the return value for the child. Note that this is not
277 actually restored by the syscall exit path, but we put it
278 here for consistency in case of signals. */
279 cregs->gr[28] = 0; /* child */
280
281 /*
282 * We need to differentiate between a user fork and a
283 * kernel fork. We can't use user_mode, because the
284 * the syscall path doesn't save iaoq. Right now
285 * We rely on the fact that kernel_thread passes
286 * in zero for usp.
287 */
288 if (usp == 1) {
289 /* kernel thread */ 225 /* kernel thread */
290 cregs->ksp = (unsigned long)stack + THREAD_SZ_ALGN;
291 /* Must exit via ret_from_kernel_thread in order 226 /* Must exit via ret_from_kernel_thread in order
292 * to call schedule_tail() 227 * to call schedule_tail()
293 */ 228 */
229 cregs->ksp = (unsigned long)stack + THREAD_SZ_ALGN + FRAME_SIZE;
294 cregs->kpc = (unsigned long) &ret_from_kernel_thread; 230 cregs->kpc = (unsigned long) &ret_from_kernel_thread;
295 /* 231 /*
296 * Copy function and argument to be called from 232 * Copy function and argument to be called from
297 * ret_from_kernel_thread. 233 * ret_from_kernel_thread.
298 */ 234 */
299#ifdef CONFIG_64BIT 235#ifdef CONFIG_64BIT
300 cregs->gr[27] = pregs->gr[27]; 236 cregs->gr[27] = ((unsigned long *)usp)[3];
237 cregs->gr[26] = ((unsigned long *)usp)[2];
238#else
239 cregs->gr[26] = usp;
301#endif 240#endif
302 cregs->gr[26] = pregs->gr[26]; 241 cregs->gr[25] = arg;
303 cregs->gr[25] = pregs->gr[25];
304 } else { 242 } else {
305 /* user thread */ 243 /* user thread */
306 /* 244 /* usp must be word aligned. This also prevents users from
307 * Note that the fork wrappers are responsible 245 * passing in the value 1 (which is the signal for a special
308 * for setting gr[21]. 246 * return for a kernel thread) */
309 */ 247 if (usp) {
310 248 usp = ALIGN(usp, 4);
311 /* Use same stack depth as parent */ 249 if (likely(usp))
312 cregs->ksp = (unsigned long)stack 250 cregs->gr[30] = usp;
313 + (pregs->gr[21] & (THREAD_SIZE - 1)); 251 }
314 cregs->gr[30] = usp; 252 cregs->ksp = (unsigned long)stack + THREAD_SZ_ALGN + FRAME_SIZE;
315 if (personality(p->personality) == PER_HPUX) { 253 if (personality(p->personality) == PER_HPUX) {
316#ifdef CONFIG_HPUX 254#ifdef CONFIG_HPUX
317 cregs->kpc = (unsigned long) &hpux_child_return; 255 cregs->kpc = (unsigned long) &hpux_child_return;
@@ -323,8 +261,7 @@ copy_thread(unsigned long clone_flags, unsigned long usp,
323 } 261 }
324 /* Setup thread TLS area from the 4th parameter in clone */ 262 /* Setup thread TLS area from the 4th parameter in clone */
325 if (clone_flags & CLONE_SETTLS) 263 if (clone_flags & CLONE_SETTLS)
326 cregs->cr27 = pregs->gr[23]; 264 cregs->cr27 = cregs->gr[23];
327
328 } 265 }
329 266
330 return 0; 267 return 0;
@@ -335,39 +272,6 @@ unsigned long thread_saved_pc(struct task_struct *t)
335 return t->thread.regs.kpc; 272 return t->thread.regs.kpc;
336} 273}
337 274
338/*
339 * sys_execve() executes a new program.
340 */
341
342asmlinkage int sys_execve(struct pt_regs *regs)
343{
344 int error;
345 struct filename *filename;
346
347 filename = getname((const char __user *) regs->gr[26]);
348 error = PTR_ERR(filename);
349 if (IS_ERR(filename))
350 goto out;
351 error = do_execve(filename->name,
352 (const char __user *const __user *) regs->gr[25],
353 (const char __user *const __user *) regs->gr[24],
354 regs);
355 putname(filename);
356out:
357
358 return error;
359}
360
361extern int __execve(const char *filename,
362 const char *const argv[],
363 const char *const envp[], struct task_struct *task);
364int kernel_execve(const char *filename,
365 const char *const argv[],
366 const char *const envp[])
367{
368 return __execve(filename, argv, envp, current);
369}
370
371unsigned long 275unsigned long
372get_wchan(struct task_struct *p) 276get_wchan(struct task_struct *p)
373{ 277{
diff --git a/arch/parisc/kernel/sys_parisc32.c b/arch/parisc/kernel/sys_parisc32.c
index bf5b93a885d3..9cfdaa19ab63 100644
--- a/arch/parisc/kernel/sys_parisc32.c
+++ b/arch/parisc/kernel/sys_parisc32.c
@@ -53,28 +53,6 @@
53#define DBG(x) 53#define DBG(x)
54#endif 54#endif
55 55
56/*
57 * sys32_execve() executes a new program.
58 */
59
60asmlinkage int sys32_execve(struct pt_regs *regs)
61{
62 int error;
63 struct filename *filename;
64
65 DBG(("sys32_execve(%p) r26 = 0x%lx\n", regs, regs->gr[26]));
66 filename = getname((const char __user *) regs->gr[26]);
67 error = PTR_ERR(filename);
68 if (IS_ERR(filename))
69 goto out;
70 error = compat_do_execve(filename->name, compat_ptr(regs->gr[25]),
71 compat_ptr(regs->gr[24]), regs);
72 putname(filename);
73out:
74
75 return error;
76}
77
78asmlinkage long sys32_unimplemented(int r26, int r25, int r24, int r23, 56asmlinkage long sys32_unimplemented(int r26, int r25, int r24, int r23,
79 int r22, int r21, int r20) 57 int r22, int r21, int r20)
80{ 58{
diff --git a/arch/parisc/kernel/syscall_table.S b/arch/parisc/kernel/syscall_table.S
index cbf5d59d5d6a..54d950b067b7 100644
--- a/arch/parisc/kernel/syscall_table.S
+++ b/arch/parisc/kernel/syscall_table.S
@@ -66,7 +66,7 @@
66 ENTRY_SAME(creat) 66 ENTRY_SAME(creat)
67 ENTRY_SAME(link) 67 ENTRY_SAME(link)
68 ENTRY_SAME(unlink) /* 10 */ 68 ENTRY_SAME(unlink) /* 10 */
69 ENTRY_DIFF(execve_wrapper) 69 ENTRY_COMP(execve)
70 ENTRY_SAME(chdir) 70 ENTRY_SAME(chdir)
71 /* See comments in kernel/time.c!!! Maybe we don't need this? */ 71 /* See comments in kernel/time.c!!! Maybe we don't need this? */
72 ENTRY_COMP(time) 72 ENTRY_COMP(time)