diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-12-12 15:22:13 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-12-12 15:22:13 -0500 |
commit | 9977d9b379cb77e0f67bd6f4563618106e58e11d (patch) | |
tree | 0191accfddf578edb52c69c933d64521e3dce297 /arch/parisc | |
parent | cf4af01221579a4e895f43dbfc47598fbfc5a731 (diff) | |
parent | 541880d9a2c7871f6370071d55aa6662d329c51e (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/Kconfig | 3 | ||||
-rw-r--r-- | arch/parisc/include/asm/processor.h | 1 | ||||
-rw-r--r-- | arch/parisc/include/asm/signal.h | 2 | ||||
-rw-r--r-- | arch/parisc/include/asm/unistd.h | 4 | ||||
-rw-r--r-- | arch/parisc/kernel/entry.S | 241 | ||||
-rw-r--r-- | arch/parisc/kernel/process.c | 142 | ||||
-rw-r--r-- | arch/parisc/kernel/sys_parisc32.c | 22 | ||||
-rw-r--r-- | arch/parisc/kernel/syscall_table.S | 2 |
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. */ |
328 | extern void release_thread(struct task_struct *); | 328 | extern void release_thread(struct task_struct *); |
329 | extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags); | ||
330 | 329 | ||
331 | extern void map_hpux_gateway_page(struct task_struct *tsk, struct mm_struct *mm); | 330 | extern 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 | ||
724 | ENTRY(__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 | ||
757 | ENDPROC(__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 | ||
766 | ENTRY(ret_from_kernel_thread) | 716 | ENTRY(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 | ||
793 | ENDPROC(ret_from_kernel_thread) | ||
794 | |||
795 | .import sys_execve, code | ||
796 | ENTRY(__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 |
816 | ENDPROC(__execve) | 732 | ENDPROC(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 | ||
1775 | ENTRY(sys_fork_wrapper) | 1691 | .macro fork_like name |
1692 | ENTRY(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) | 1699 | ENDPROC(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 | ||
1799 | wrapper_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 */ | 1702 | fork_like clone |
1809 | ldi __NR_fork,%r20 | 1703 | fork_like fork |
1810 | bv %r0(%r2) | 1704 | fork_like vfork |
1811 | STREG %r20,PT_GR20(%r1) | ||
1812 | ENDPROC(sys_fork_wrapper) | ||
1813 | 1705 | ||
1814 | /* Set the return value for the child */ | 1706 | /* Set the return value for the child */ |
1815 | ENTRY(child_return) | 1707 | ENTRY(child_return) |
1816 | BL schedule_tail, %r2 | 1708 | BL schedule_tail, %r2 |
1817 | nop | 1709 | nop |
1710 | finish_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 |
1823 | ENDPROC(child_return) | 1719 | ENDPROC(child_return) |
1824 | 1720 | ||
1825 | |||
1826 | ENTRY(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 | ||
1847 | ENDPROC(sys_clone_wrapper) | ||
1848 | |||
1849 | |||
1850 | ENTRY(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 | ||
1871 | ENDPROC(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 | |||
1903 | error_\execve: | ||
1904 | bv %r0(%r19) | ||
1905 | nop | ||
1906 | .endm | ||
1907 | |||
1908 | .import sys_execve | ||
1909 | ENTRY(sys_execve_wrapper) | ||
1910 | execve_wrapper sys_execve | ||
1911 | ENDPROC(sys_execve_wrapper) | ||
1912 | |||
1913 | #ifdef CONFIG_64BIT | ||
1914 | .import sys32_execve | ||
1915 | ENTRY(sys32_execve_wrapper) | ||
1916 | execve_wrapper sys32_execve | ||
1917 | ENDPROC(sys32_execve_wrapper) | ||
1918 | #endif | ||
1919 | |||
1920 | ENTRY(sys_rt_sigreturn_wrapper) | 1721 | ENTRY(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; | |||
165 | EXPORT_SYMBOL(pm_power_off); | 166 | EXPORT_SYMBOL(pm_power_off); |
166 | 167 | ||
167 | /* | 168 | /* |
168 | * Create a kernel thread | ||
169 | */ | ||
170 | |||
171 | extern pid_t __kernel_thread(int (*fn)(void *), void *arg, unsigned long flags); | ||
172 | pid_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 | } | ||
182 | EXPORT_SYMBOL(kernel_thread); | ||
183 | |||
184 | /* | ||
185 | * Free current thread data structures etc.. | 169 | * Free current thread data structures etc.. |
186 | */ | 170 | */ |
187 | void exit_thread(void) | 171 | void 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). */ | ||
223 | int | ||
224 | sys_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 | |||
251 | int | ||
252 | sys_vfork(struct pt_regs *regs) | ||
253 | { | ||
254 | return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->gr[30], regs, 0, NULL, NULL); | ||
255 | } | ||
256 | |||
257 | int | 205 | int |
258 | copy_thread(unsigned long clone_flags, unsigned long usp, | 206 | copy_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 | |||
342 | asmlinkage 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); | ||
356 | out: | ||
357 | |||
358 | return error; | ||
359 | } | ||
360 | |||
361 | extern int __execve(const char *filename, | ||
362 | const char *const argv[], | ||
363 | const char *const envp[], struct task_struct *task); | ||
364 | int 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 | |||
371 | unsigned long | 275 | unsigned long |
372 | get_wchan(struct task_struct *p) | 276 | get_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 | |||
60 | asmlinkage 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); | ||
73 | out: | ||
74 | |||
75 | return error; | ||
76 | } | ||
77 | |||
78 | asmlinkage long sys32_unimplemented(int r26, int r25, int r24, int r23, | 56 | asmlinkage 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) |