aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sparc
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/sparc
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/sparc')
-rw-r--r--arch/sparc/Kconfig2
-rw-r--r--arch/sparc/include/asm/processor_32.h1
-rw-r--r--arch/sparc/include/asm/processor_64.h11
-rw-r--r--arch/sparc/include/asm/ptrace.h10
-rw-r--r--arch/sparc/include/asm/signal.h2
-rw-r--r--arch/sparc/include/asm/switch_to_64.h2
-rw-r--r--arch/sparc/include/asm/syscalls.h2
-rw-r--r--arch/sparc/include/asm/thread_info_64.h25
-rw-r--r--arch/sparc/include/asm/uaccess_64.h4
-rw-r--r--arch/sparc/include/asm/unistd.h1
-rw-r--r--arch/sparc/kernel/entry.S51
-rw-r--r--arch/sparc/kernel/etrap_64.S8
-rw-r--r--arch/sparc/kernel/process_32.c158
-rw-r--r--arch/sparc/kernel/process_64.c148
-rw-r--r--arch/sparc/kernel/sys_sparc32.c36
-rw-r--r--arch/sparc/kernel/sys_sparc_32.c24
-rw-r--r--arch/sparc/kernel/sys_sparc_64.c22
-rw-r--r--arch/sparc/kernel/syscalls.S30
-rw-r--r--arch/sparc/kernel/systbls_64.S2
-rw-r--r--arch/sparc/kernel/traps_64.c4
-rw-r--r--arch/sparc/mm/init_64.c2
21 files changed, 160 insertions, 385 deletions
diff --git a/arch/sparc/Kconfig b/arch/sparc/Kconfig
index 9f2edb5c5551..0c7d365fa402 100644
--- a/arch/sparc/Kconfig
+++ b/arch/sparc/Kconfig
@@ -41,6 +41,8 @@ config SPARC
41 select GENERIC_STRNCPY_FROM_USER 41 select GENERIC_STRNCPY_FROM_USER
42 select GENERIC_STRNLEN_USER 42 select GENERIC_STRNLEN_USER
43 select MODULES_USE_ELF_RELA 43 select MODULES_USE_ELF_RELA
44 select GENERIC_KERNEL_THREAD
45 select GENERIC_KERNEL_EXECVE
44 46
45config SPARC32 47config SPARC32
46 def_bool !64BIT 48 def_bool !64BIT
diff --git a/arch/sparc/include/asm/processor_32.h b/arch/sparc/include/asm/processor_32.h
index f74ac9ee33a8..c1e01914fd98 100644
--- a/arch/sparc/include/asm/processor_32.h
+++ b/arch/sparc/include/asm/processor_32.h
@@ -106,7 +106,6 @@ static inline void start_thread(struct pt_regs * regs, unsigned long pc,
106 106
107/* Free all resources held by a thread. */ 107/* Free all resources held by a thread. */
108#define release_thread(tsk) do { } while(0) 108#define release_thread(tsk) do { } while(0)
109extern pid_t kernel_thread(int (*fn)(void *), void * arg, unsigned long flags);
110 109
111extern unsigned long get_wchan(struct task_struct *); 110extern unsigned long get_wchan(struct task_struct *);
112 111
diff --git a/arch/sparc/include/asm/processor_64.h b/arch/sparc/include/asm/processor_64.h
index 721e25f0e2ea..cce72ce4c334 100644
--- a/arch/sparc/include/asm/processor_64.h
+++ b/arch/sparc/include/asm/processor_64.h
@@ -94,6 +94,7 @@ struct thread_struct {
94#ifndef __ASSEMBLY__ 94#ifndef __ASSEMBLY__
95 95
96#include <linux/types.h> 96#include <linux/types.h>
97#include <asm/fpumacro.h>
97 98
98/* Return saved PC of a blocked thread. */ 99/* Return saved PC of a blocked thread. */
99struct task_struct; 100struct task_struct;
@@ -143,6 +144,10 @@ do { \
143 : \ 144 : \
144 : "r" (regs), "r" (sp - sizeof(struct reg_window) - STACK_BIAS), \ 145 : "r" (regs), "r" (sp - sizeof(struct reg_window) - STACK_BIAS), \
145 "i" ((const unsigned long)(&((struct pt_regs *)0)->u_regs[0]))); \ 146 "i" ((const unsigned long)(&((struct pt_regs *)0)->u_regs[0]))); \
147 fprs_write(0); \
148 current_thread_info()->xfsr[0] = 0; \
149 current_thread_info()->fpsaved[0] = 0; \
150 regs->tstate &= ~TSTATE_PEF; \
146} while (0) 151} while (0)
147 152
148#define start_thread32(regs, pc, sp) \ 153#define start_thread32(regs, pc, sp) \
@@ -183,13 +188,15 @@ do { \
183 : \ 188 : \
184 : "r" (regs), "r" (sp - sizeof(struct reg_window32)), \ 189 : "r" (regs), "r" (sp - sizeof(struct reg_window32)), \
185 "i" ((const unsigned long)(&((struct pt_regs *)0)->u_regs[0]))); \ 190 "i" ((const unsigned long)(&((struct pt_regs *)0)->u_regs[0]))); \
191 fprs_write(0); \
192 current_thread_info()->xfsr[0] = 0; \
193 current_thread_info()->fpsaved[0] = 0; \
194 regs->tstate &= ~TSTATE_PEF; \
186} while (0) 195} while (0)
187 196
188/* Free all resources held by a thread. */ 197/* Free all resources held by a thread. */
189#define release_thread(tsk) do { } while (0) 198#define release_thread(tsk) do { } while (0)
190 199
191extern pid_t kernel_thread(int (*fn)(void *), void * arg, unsigned long flags);
192
193extern unsigned long get_wchan(struct task_struct *task); 200extern unsigned long get_wchan(struct task_struct *task);
194 201
195#define task_pt_regs(tsk) (task_thread_info(tsk)->kregs) 202#define task_pt_regs(tsk) (task_thread_info(tsk)->kregs)
diff --git a/arch/sparc/include/asm/ptrace.h b/arch/sparc/include/asm/ptrace.h
index da43bdc62294..bdfafd7af46f 100644
--- a/arch/sparc/include/asm/ptrace.h
+++ b/arch/sparc/include/asm/ptrace.h
@@ -32,6 +32,9 @@ static inline bool pt_regs_clear_syscall(struct pt_regs *regs)
32#define arch_ptrace_stop(exit_code, info) \ 32#define arch_ptrace_stop(exit_code, info) \
33 synchronize_user_stack() 33 synchronize_user_stack()
34 34
35#define current_pt_regs() \
36 ((struct pt_regs *)((unsigned long)current_thread_info() + THREAD_SIZE) - 1)
37
35struct global_reg_snapshot { 38struct global_reg_snapshot {
36 unsigned long tstate; 39 unsigned long tstate;
37 unsigned long tpc; 40 unsigned long tpc;
@@ -55,9 +58,7 @@ union global_cpu_snapshot {
55 58
56extern union global_cpu_snapshot global_cpu_snapshot[NR_CPUS]; 59extern union global_cpu_snapshot global_cpu_snapshot[NR_CPUS];
57 60
58#define force_successful_syscall_return() \ 61#define force_successful_syscall_return() set_thread_noerror(1)
59do { current_thread_info()->syscall_noerror = 1; \
60} while (0)
61#define user_mode(regs) (!((regs)->tstate & TSTATE_PRIV)) 62#define user_mode(regs) (!((regs)->tstate & TSTATE_PRIV))
62#define instruction_pointer(regs) ((regs)->tpc) 63#define instruction_pointer(regs) ((regs)->tpc)
63#define instruction_pointer_set(regs, val) ((regs)->tpc = (val)) 64#define instruction_pointer_set(regs, val) ((regs)->tpc = (val))
@@ -100,6 +101,9 @@ static inline bool pt_regs_clear_syscall(struct pt_regs *regs)
100#define arch_ptrace_stop(exit_code, info) \ 101#define arch_ptrace_stop(exit_code, info) \
101 synchronize_user_stack() 102 synchronize_user_stack()
102 103
104#define current_pt_regs() \
105 ((struct pt_regs *)((unsigned long)current_thread_info() + THREAD_SIZE) - 1)
106
103#define user_mode(regs) (!((regs)->psr & PSR_PS)) 107#define user_mode(regs) (!((regs)->psr & PSR_PS))
104#define instruction_pointer(regs) ((regs)->pc) 108#define instruction_pointer(regs) ((regs)->pc)
105#define user_stack_pointer(regs) ((regs)->u_regs[UREG_FP]) 109#define user_stack_pointer(regs) ((regs)->u_regs[UREG_FP])
diff --git a/arch/sparc/include/asm/signal.h b/arch/sparc/include/asm/signal.h
index d243c2ae02d2..77b85850d543 100644
--- a/arch/sparc/include/asm/signal.h
+++ b/arch/sparc/include/asm/signal.h
@@ -26,7 +26,5 @@ struct k_sigaction {
26 void __user *ka_restorer; 26 void __user *ka_restorer;
27}; 27};
28 28
29#define ptrace_signal_deliver(regs, cookie) do { } while (0)
30
31#endif /* !(__ASSEMBLY__) */ 29#endif /* !(__ASSEMBLY__) */
32#endif /* !(__SPARC_SIGNAL_H) */ 30#endif /* !(__SPARC_SIGNAL_H) */
diff --git a/arch/sparc/include/asm/switch_to_64.h b/arch/sparc/include/asm/switch_to_64.h
index 7923c4a2be38..cad36f56fa03 100644
--- a/arch/sparc/include/asm/switch_to_64.h
+++ b/arch/sparc/include/asm/switch_to_64.h
@@ -23,7 +23,7 @@ do { flush_tlb_pending(); \
23 /* If you are tempted to conditionalize the following */ \ 23 /* If you are tempted to conditionalize the following */ \
24 /* so that ASI is only written if it changes, think again. */ \ 24 /* so that ASI is only written if it changes, think again. */ \
25 __asm__ __volatile__("wr %%g0, %0, %%asi" \ 25 __asm__ __volatile__("wr %%g0, %0, %%asi" \
26 : : "r" (__thread_flag_byte_ptr(task_thread_info(next))[TI_FLAG_BYTE_CURRENT_DS]));\ 26 : : "r" (task_thread_info(next)->current_ds));\
27 trap_block[current_thread_info()->cpu].thread = \ 27 trap_block[current_thread_info()->cpu].thread = \
28 task_thread_info(next); \ 28 task_thread_info(next); \
29 __asm__ __volatile__( \ 29 __asm__ __volatile__( \
diff --git a/arch/sparc/include/asm/syscalls.h b/arch/sparc/include/asm/syscalls.h
index 45a43f637a14..bf8972adea17 100644
--- a/arch/sparc/include/asm/syscalls.h
+++ b/arch/sparc/include/asm/syscalls.h
@@ -8,6 +8,4 @@ extern asmlinkage long sparc_do_fork(unsigned long clone_flags,
8 struct pt_regs *regs, 8 struct pt_regs *regs,
9 unsigned long stack_size); 9 unsigned long stack_size);
10 10
11extern asmlinkage int sparc_execve(struct pt_regs *regs);
12
13#endif /* _SPARC64_SYSCALLS_H */ 11#endif /* _SPARC64_SYSCALLS_H */
diff --git a/arch/sparc/include/asm/thread_info_64.h b/arch/sparc/include/asm/thread_info_64.h
index a3fe4dcc0aa6..269bd92313df 100644
--- a/arch/sparc/include/asm/thread_info_64.h
+++ b/arch/sparc/include/asm/thread_info_64.h
@@ -14,12 +14,12 @@
14#define TI_FLAG_FAULT_CODE_SHIFT 56 14#define TI_FLAG_FAULT_CODE_SHIFT 56
15#define TI_FLAG_BYTE_WSTATE 1 15#define TI_FLAG_BYTE_WSTATE 1
16#define TI_FLAG_WSTATE_SHIFT 48 16#define TI_FLAG_WSTATE_SHIFT 48
17#define TI_FLAG_BYTE_CWP 2 17#define TI_FLAG_BYTE_NOERROR 2
18#define TI_FLAG_CWP_SHIFT 40 18#define TI_FLAG_BYTE_NOERROR_SHIFT 40
19#define TI_FLAG_BYTE_CURRENT_DS 3 19#define TI_FLAG_BYTE_FPDEPTH 3
20#define TI_FLAG_CURRENT_DS_SHIFT 32 20#define TI_FLAG_FPDEPTH_SHIFT 32
21#define TI_FLAG_BYTE_FPDEPTH 4 21#define TI_FLAG_BYTE_CWP 4
22#define TI_FLAG_FPDEPTH_SHIFT 24 22#define TI_FLAG_CWP_SHIFT 24
23#define TI_FLAG_BYTE_WSAVED 5 23#define TI_FLAG_BYTE_WSAVED 5
24#define TI_FLAG_WSAVED_SHIFT 16 24#define TI_FLAG_WSAVED_SHIFT 16
25 25
@@ -47,7 +47,7 @@ struct thread_info {
47 struct exec_domain *exec_domain; 47 struct exec_domain *exec_domain;
48 int preempt_count; /* 0 => preemptable, <0 => BUG */ 48 int preempt_count; /* 0 => preemptable, <0 => BUG */
49 __u8 new_child; 49 __u8 new_child;
50 __u8 syscall_noerror; 50 __u8 current_ds;
51 __u16 cpu; 51 __u16 cpu;
52 52
53 unsigned long *utraps; 53 unsigned long *utraps;
@@ -74,9 +74,9 @@ struct thread_info {
74#define TI_FAULT_CODE (TI_FLAGS + TI_FLAG_BYTE_FAULT_CODE) 74#define TI_FAULT_CODE (TI_FLAGS + TI_FLAG_BYTE_FAULT_CODE)
75#define TI_WSTATE (TI_FLAGS + TI_FLAG_BYTE_WSTATE) 75#define TI_WSTATE (TI_FLAGS + TI_FLAG_BYTE_WSTATE)
76#define TI_CWP (TI_FLAGS + TI_FLAG_BYTE_CWP) 76#define TI_CWP (TI_FLAGS + TI_FLAG_BYTE_CWP)
77#define TI_CURRENT_DS (TI_FLAGS + TI_FLAG_BYTE_CURRENT_DS)
78#define TI_FPDEPTH (TI_FLAGS + TI_FLAG_BYTE_FPDEPTH) 77#define TI_FPDEPTH (TI_FLAGS + TI_FLAG_BYTE_FPDEPTH)
79#define TI_WSAVED (TI_FLAGS + TI_FLAG_BYTE_WSAVED) 78#define TI_WSAVED (TI_FLAGS + TI_FLAG_BYTE_WSAVED)
79#define TI_SYS_NOERROR (TI_FLAGS + TI_FLAG_BYTE_NOERROR)
80#define TI_FPSAVED 0x00000010 80#define TI_FPSAVED 0x00000010
81#define TI_KSP 0x00000018 81#define TI_KSP 0x00000018
82#define TI_FAULT_ADDR 0x00000020 82#define TI_FAULT_ADDR 0x00000020
@@ -84,7 +84,7 @@ struct thread_info {
84#define TI_EXEC_DOMAIN 0x00000030 84#define TI_EXEC_DOMAIN 0x00000030
85#define TI_PRE_COUNT 0x00000038 85#define TI_PRE_COUNT 0x00000038
86#define TI_NEW_CHILD 0x0000003c 86#define TI_NEW_CHILD 0x0000003c
87#define TI_SYS_NOERROR 0x0000003d 87#define TI_CURRENT_DS 0x0000003d
88#define TI_CPU 0x0000003e 88#define TI_CPU 0x0000003e
89#define TI_UTRAPS 0x00000040 89#define TI_UTRAPS 0x00000040
90#define TI_REG_WINDOW 0x00000048 90#define TI_REG_WINDOW 0x00000048
@@ -121,7 +121,7 @@ struct thread_info {
121#define INIT_THREAD_INFO(tsk) \ 121#define INIT_THREAD_INFO(tsk) \
122{ \ 122{ \
123 .task = &tsk, \ 123 .task = &tsk, \
124 .flags = ((unsigned long)ASI_P) << TI_FLAG_CURRENT_DS_SHIFT, \ 124 .current_ds = ASI_P, \
125 .exec_domain = &default_exec_domain, \ 125 .exec_domain = &default_exec_domain, \
126 .preempt_count = INIT_PREEMPT_COUNT, \ 126 .preempt_count = INIT_PREEMPT_COUNT, \
127 .restart_block = { \ 127 .restart_block = { \
@@ -153,13 +153,12 @@ register struct thread_info *current_thread_info_reg asm("g6");
153#define set_thread_wstate(val) (__cur_thread_flag_byte_ptr[TI_FLAG_BYTE_WSTATE] = (val)) 153#define set_thread_wstate(val) (__cur_thread_flag_byte_ptr[TI_FLAG_BYTE_WSTATE] = (val))
154#define get_thread_cwp() (__cur_thread_flag_byte_ptr[TI_FLAG_BYTE_CWP]) 154#define get_thread_cwp() (__cur_thread_flag_byte_ptr[TI_FLAG_BYTE_CWP])
155#define set_thread_cwp(val) (__cur_thread_flag_byte_ptr[TI_FLAG_BYTE_CWP] = (val)) 155#define set_thread_cwp(val) (__cur_thread_flag_byte_ptr[TI_FLAG_BYTE_CWP] = (val))
156#define get_thread_current_ds() (__cur_thread_flag_byte_ptr[TI_FLAG_BYTE_CURRENT_DS]) 156#define get_thread_noerror() (__cur_thread_flag_byte_ptr[TI_FLAG_BYTE_NOERROR])
157#define set_thread_current_ds(val) (__cur_thread_flag_byte_ptr[TI_FLAG_BYTE_CURRENT_DS] = (val)) 157#define set_thread_noerror(val) (__cur_thread_flag_byte_ptr[TI_FLAG_BYTE_NOERROR] = (val))
158#define get_thread_fpdepth() (__cur_thread_flag_byte_ptr[TI_FLAG_BYTE_FPDEPTH]) 158#define get_thread_fpdepth() (__cur_thread_flag_byte_ptr[TI_FLAG_BYTE_FPDEPTH])
159#define set_thread_fpdepth(val) (__cur_thread_flag_byte_ptr[TI_FLAG_BYTE_FPDEPTH] = (val)) 159#define set_thread_fpdepth(val) (__cur_thread_flag_byte_ptr[TI_FLAG_BYTE_FPDEPTH] = (val))
160#define get_thread_wsaved() (__cur_thread_flag_byte_ptr[TI_FLAG_BYTE_WSAVED]) 160#define get_thread_wsaved() (__cur_thread_flag_byte_ptr[TI_FLAG_BYTE_WSAVED])
161#define set_thread_wsaved(val) (__cur_thread_flag_byte_ptr[TI_FLAG_BYTE_WSAVED] = (val)) 161#define set_thread_wsaved(val) (__cur_thread_flag_byte_ptr[TI_FLAG_BYTE_WSAVED] = (val))
162
163#endif /* !(__ASSEMBLY__) */ 162#endif /* !(__ASSEMBLY__) */
164 163
165/* 164/*
diff --git a/arch/sparc/include/asm/uaccess_64.h b/arch/sparc/include/asm/uaccess_64.h
index 73083e1d38d9..e562d3caee57 100644
--- a/arch/sparc/include/asm/uaccess_64.h
+++ b/arch/sparc/include/asm/uaccess_64.h
@@ -38,14 +38,14 @@
38#define VERIFY_READ 0 38#define VERIFY_READ 0
39#define VERIFY_WRITE 1 39#define VERIFY_WRITE 1
40 40
41#define get_fs() ((mm_segment_t) { get_thread_current_ds() }) 41#define get_fs() ((mm_segment_t){(current_thread_info()->current_ds)})
42#define get_ds() (KERNEL_DS) 42#define get_ds() (KERNEL_DS)
43 43
44#define segment_eq(a,b) ((a).seg == (b).seg) 44#define segment_eq(a,b) ((a).seg == (b).seg)
45 45
46#define set_fs(val) \ 46#define set_fs(val) \
47do { \ 47do { \
48 set_thread_current_ds((val).seg); \ 48 current_thread_info()->current_ds =(val).seg; \
49 __asm__ __volatile__ ("wr %%g0, %0, %%asi" : : "r" ((val).seg)); \ 49 __asm__ __volatile__ ("wr %%g0, %0, %%asi" : : "r" ((val).seg)); \
50} while(0) 50} while(0)
51 51
diff --git a/arch/sparc/include/asm/unistd.h b/arch/sparc/include/asm/unistd.h
index 0ecea6ed943e..c3e5d8b64171 100644
--- a/arch/sparc/include/asm/unistd.h
+++ b/arch/sparc/include/asm/unistd.h
@@ -46,6 +46,7 @@
46#define __ARCH_WANT_COMPAT_SYS_RT_SIGSUSPEND 46#define __ARCH_WANT_COMPAT_SYS_RT_SIGSUSPEND
47#define __ARCH_WANT_COMPAT_SYS_SENDFILE 47#define __ARCH_WANT_COMPAT_SYS_SENDFILE
48#endif 48#endif
49#define __ARCH_WANT_SYS_EXECVE
49 50
50/* 51/*
51 * "Conditional" syscalls 52 * "Conditional" syscalls
diff --git a/arch/sparc/kernel/entry.S b/arch/sparc/kernel/entry.S
index dcaa1cf0de40..21fd1a8f47d2 100644
--- a/arch/sparc/kernel/entry.S
+++ b/arch/sparc/kernel/entry.S
@@ -806,23 +806,10 @@ sys_nis_syscall:
806 call c_sys_nis_syscall 806 call c_sys_nis_syscall
807 mov %l5, %o7 807 mov %l5, %o7
808 808
809 .align 4
810 .globl sys_execve
811sys_execve:
812 mov %o7, %l5
813 add %sp, STACKFRAME_SZ, %o0 ! pt_regs *regs arg
814 call sparc_execve
815 mov %l5, %o7
816
817 .globl sunos_execv
818sunos_execv: 809sunos_execv:
819 st %g0, [%sp + STACKFRAME_SZ + PT_I2] 810 .globl sunos_execv
820 811 b sys_execve
821 call sparc_execve 812 clr %i2
822 add %sp, STACKFRAME_SZ, %o0
823
824 b ret_sys_call
825 ld [%sp + STACKFRAME_SZ + PT_I0], %o0
826 813
827 .align 4 814 .align 4
828 .globl sys_sparc_pipe 815 .globl sys_sparc_pipe
@@ -959,17 +946,9 @@ flush_patch_four:
959 .align 4 946 .align 4
960linux_sparc_ni_syscall: 947linux_sparc_ni_syscall:
961 sethi %hi(sys_ni_syscall), %l7 948 sethi %hi(sys_ni_syscall), %l7
962 b syscall_is_too_hard 949 b do_syscall
963 or %l7, %lo(sys_ni_syscall), %l7 950 or %l7, %lo(sys_ni_syscall), %l7
964 951
965linux_fast_syscall:
966 andn %l7, 3, %l7
967 mov %i0, %o0
968 mov %i1, %o1
969 mov %i2, %o2
970 jmpl %l7 + %g0, %g0
971 mov %i3, %o3
972
973linux_syscall_trace: 952linux_syscall_trace:
974 add %sp, STACKFRAME_SZ, %o0 953 add %sp, STACKFRAME_SZ, %o0
975 call syscall_trace 954 call syscall_trace
@@ -991,6 +970,23 @@ ret_from_fork:
991 b ret_sys_call 970 b ret_sys_call
992 ld [%sp + STACKFRAME_SZ + PT_I0], %o0 971 ld [%sp + STACKFRAME_SZ + PT_I0], %o0
993 972
973 .globl ret_from_kernel_thread
974ret_from_kernel_thread:
975 call schedule_tail
976 ld [%g3 + TI_TASK], %o0
977 ld [%sp + STACKFRAME_SZ + PT_G1], %l0
978 call %l0
979 ld [%sp + STACKFRAME_SZ + PT_G2], %o0
980 rd %psr, %l1
981 ld [%sp + STACKFRAME_SZ + PT_PSR], %l0
982 andn %l0, PSR_CWP, %l0
983 nop
984 and %l1, PSR_CWP, %l1
985 or %l0, %l1, %l0
986 st %l0, [%sp + STACKFRAME_SZ + PT_PSR]
987 b ret_sys_call
988 mov 0, %o0
989
994 /* Linux native system calls enter here... */ 990 /* Linux native system calls enter here... */
995 .align 4 991 .align 4
996 .globl linux_sparc_syscall 992 .globl linux_sparc_syscall
@@ -1002,11 +998,8 @@ linux_sparc_syscall:
1002 bgeu linux_sparc_ni_syscall 998 bgeu linux_sparc_ni_syscall
1003 sll %g1, 2, %l4 999 sll %g1, 2, %l4
1004 ld [%l7 + %l4], %l7 1000 ld [%l7 + %l4], %l7
1005 andcc %l7, 1, %g0
1006 bne linux_fast_syscall
1007 /* Just do first insn from SAVE_ALL in the delay slot */
1008 1001
1009syscall_is_too_hard: 1002do_syscall:
1010 SAVE_ALL_HEAD 1003 SAVE_ALL_HEAD
1011 rd %wim, %l3 1004 rd %wim, %l3
1012 1005
diff --git a/arch/sparc/kernel/etrap_64.S b/arch/sparc/kernel/etrap_64.S
index 786b185e6e3f..1276ca2567ba 100644
--- a/arch/sparc/kernel/etrap_64.S
+++ b/arch/sparc/kernel/etrap_64.S
@@ -92,8 +92,10 @@ etrap_save: save %g2, -STACK_BIAS, %sp
92 rdpr %wstate, %g2 92 rdpr %wstate, %g2
93 wrpr %g0, 0, %canrestore 93 wrpr %g0, 0, %canrestore
94 sll %g2, 3, %g2 94 sll %g2, 3, %g2
95
96 /* Set TI_SYS_FPDEPTH to 1 and clear TI_SYS_NOERROR. */
95 mov 1, %l5 97 mov 1, %l5
96 stb %l5, [%l6 + TI_FPDEPTH] 98 sth %l5, [%l6 + TI_SYS_NOERROR]
97 99
98 wrpr %g3, 0, %otherwin 100 wrpr %g3, 0, %otherwin
99 wrpr %g2, 0, %wstate 101 wrpr %g2, 0, %wstate
@@ -152,7 +154,9 @@ etrap_save: save %g2, -STACK_BIAS, %sp
152 add %l6, TI_FPSAVED + 1, %l4 154 add %l6, TI_FPSAVED + 1, %l4
153 srl %l5, 1, %l3 155 srl %l5, 1, %l3
154 add %l5, 2, %l5 156 add %l5, 2, %l5
155 stb %l5, [%l6 + TI_FPDEPTH] 157
158 /* Set TI_SYS_FPDEPTH to %l5 and clear TI_SYS_NOERROR. */
159 sth %l5, [%l6 + TI_SYS_NOERROR]
156 ba,pt %xcc, 2b 160 ba,pt %xcc, 2b
157 stb %g0, [%l4 + %l3] 161 stb %g0, [%l4 + %l3]
158 nop 162 nop
diff --git a/arch/sparc/kernel/process_32.c b/arch/sparc/kernel/process_32.c
index 487bffb36f5e..be8e862badaf 100644
--- a/arch/sparc/kernel/process_32.c
+++ b/arch/sparc/kernel/process_32.c
@@ -286,8 +286,7 @@ asmlinkage int sparc_do_fork(unsigned long clone_flags,
286 parent_tid_ptr = regs->u_regs[UREG_I2]; 286 parent_tid_ptr = regs->u_regs[UREG_I2];
287 child_tid_ptr = regs->u_regs[UREG_I4]; 287 child_tid_ptr = regs->u_regs[UREG_I4];
288 288
289 ret = do_fork(clone_flags, stack_start, 289 ret = do_fork(clone_flags, stack_start, stack_size,
290 regs, stack_size,
291 (int __user *) parent_tid_ptr, 290 (int __user *) parent_tid_ptr,
292 (int __user *) child_tid_ptr); 291 (int __user *) child_tid_ptr);
293 292
@@ -316,13 +315,13 @@ asmlinkage int sparc_do_fork(unsigned long clone_flags,
316 * XXX See comment above sys_vfork in sparc64. todo. 315 * XXX See comment above sys_vfork in sparc64. todo.
317 */ 316 */
318extern void ret_from_fork(void); 317extern void ret_from_fork(void);
318extern void ret_from_kernel_thread(void);
319 319
320int copy_thread(unsigned long clone_flags, unsigned long sp, 320int copy_thread(unsigned long clone_flags, unsigned long sp,
321 unsigned long unused, 321 unsigned long arg, struct task_struct *p)
322 struct task_struct *p, struct pt_regs *regs)
323{ 322{
324 struct thread_info *ti = task_thread_info(p); 323 struct thread_info *ti = task_thread_info(p);
325 struct pt_regs *childregs; 324 struct pt_regs *childregs, *regs = current_pt_regs();
326 char *new_stack; 325 char *new_stack;
327 326
328#ifndef CONFIG_SMP 327#ifndef CONFIG_SMP
@@ -336,16 +335,13 @@ int copy_thread(unsigned long clone_flags, unsigned long sp,
336 } 335 }
337 336
338 /* 337 /*
339 * p->thread_info new_stack childregs 338 * p->thread_info new_stack childregs stack bottom
340 * ! ! ! {if(PSR_PS) } 339 * ! ! ! !
341 * V V (stk.fr.) V (pt_regs) { (stk.fr.) } 340 * V V (stk.fr.) V (pt_regs) V
342 * +----- - - - - - ------+===========+============={+==========}+ 341 * +----- - - - - - ------+===========+=============+
343 */ 342 */
344 new_stack = task_stack_page(p) + THREAD_SIZE; 343 new_stack = task_stack_page(p) + THREAD_SIZE;
345 if (regs->psr & PSR_PS)
346 new_stack -= STACKFRAME_SZ;
347 new_stack -= STACKFRAME_SZ + TRACEREG_SZ; 344 new_stack -= STACKFRAME_SZ + TRACEREG_SZ;
348 memcpy(new_stack, (char *)regs - STACKFRAME_SZ, STACKFRAME_SZ + TRACEREG_SZ);
349 childregs = (struct pt_regs *) (new_stack + STACKFRAME_SZ); 345 childregs = (struct pt_regs *) (new_stack + STACKFRAME_SZ);
350 346
351 /* 347 /*
@@ -356,55 +352,58 @@ int copy_thread(unsigned long clone_flags, unsigned long sp,
356 * Thus, kpsr|=PSR_PIL. 352 * Thus, kpsr|=PSR_PIL.
357 */ 353 */
358 ti->ksp = (unsigned long) new_stack; 354 ti->ksp = (unsigned long) new_stack;
355 p->thread.kregs = childregs;
356
357 if (unlikely(p->flags & PF_KTHREAD)) {
358 extern int nwindows;
359 unsigned long psr;
360 memset(new_stack, 0, STACKFRAME_SZ + TRACEREG_SZ);
361 p->thread.flags |= SPARC_FLAG_KTHREAD;
362 p->thread.current_ds = KERNEL_DS;
363 ti->kpc = (((unsigned long) ret_from_kernel_thread) - 0x8);
364 childregs->u_regs[UREG_G1] = sp; /* function */
365 childregs->u_regs[UREG_G2] = arg;
366 psr = childregs->psr = get_psr();
367 ti->kpsr = psr | PSR_PIL;
368 ti->kwim = 1 << (((psr & PSR_CWP) + 1) % nwindows);
369 return 0;
370 }
371 memcpy(new_stack, (char *)regs - STACKFRAME_SZ, STACKFRAME_SZ + TRACEREG_SZ);
372 childregs->u_regs[UREG_FP] = sp;
373 p->thread.flags &= ~SPARC_FLAG_KTHREAD;
374 p->thread.current_ds = USER_DS;
359 ti->kpc = (((unsigned long) ret_from_fork) - 0x8); 375 ti->kpc = (((unsigned long) ret_from_fork) - 0x8);
360 ti->kpsr = current->thread.fork_kpsr | PSR_PIL; 376 ti->kpsr = current->thread.fork_kpsr | PSR_PIL;
361 ti->kwim = current->thread.fork_kwim; 377 ti->kwim = current->thread.fork_kwim;
362 378
363 if(regs->psr & PSR_PS) { 379 if (sp != regs->u_regs[UREG_FP]) {
364 extern struct pt_regs fake_swapper_regs; 380 struct sparc_stackf __user *childstack;
381 struct sparc_stackf __user *parentstack;
365 382
366 p->thread.kregs = &fake_swapper_regs; 383 /*
367 new_stack += STACKFRAME_SZ + TRACEREG_SZ; 384 * This is a clone() call with supplied user stack.
368 childregs->u_regs[UREG_FP] = (unsigned long) new_stack; 385 * Set some valid stack frames to give to the child.
369 p->thread.flags |= SPARC_FLAG_KTHREAD; 386 */
370 p->thread.current_ds = KERNEL_DS; 387 childstack = (struct sparc_stackf __user *)
371 memcpy(new_stack, (void *)regs->u_regs[UREG_FP], STACKFRAME_SZ); 388 (sp & ~0xfUL);
372 childregs->u_regs[UREG_G6] = (unsigned long) ti; 389 parentstack = (struct sparc_stackf __user *)
373 } else { 390 regs->u_regs[UREG_FP];
374 p->thread.kregs = childregs;
375 childregs->u_regs[UREG_FP] = sp;
376 p->thread.flags &= ~SPARC_FLAG_KTHREAD;
377 p->thread.current_ds = USER_DS;
378
379 if (sp != regs->u_regs[UREG_FP]) {
380 struct sparc_stackf __user *childstack;
381 struct sparc_stackf __user *parentstack;
382
383 /*
384 * This is a clone() call with supplied user stack.
385 * Set some valid stack frames to give to the child.
386 */
387 childstack = (struct sparc_stackf __user *)
388 (sp & ~0xfUL);
389 parentstack = (struct sparc_stackf __user *)
390 regs->u_regs[UREG_FP];
391 391
392#if 0 392#if 0
393 printk("clone: parent stack:\n"); 393 printk("clone: parent stack:\n");
394 show_stackframe(parentstack); 394 show_stackframe(parentstack);
395#endif 395#endif
396 396
397 childstack = clone_stackframe(childstack, parentstack); 397 childstack = clone_stackframe(childstack, parentstack);
398 if (!childstack) 398 if (!childstack)
399 return -EFAULT; 399 return -EFAULT;
400 400
401#if 0 401#if 0
402 printk("clone: child stack:\n"); 402 printk("clone: child stack:\n");
403 show_stackframe(childstack); 403 show_stackframe(childstack);
404#endif 404#endif
405 405
406 childregs->u_regs[UREG_FP] = (unsigned long)childstack; 406 childregs->u_regs[UREG_FP] = (unsigned long)childstack;
407 }
408 } 407 }
409 408
410#ifdef CONFIG_SMP 409#ifdef CONFIG_SMP
@@ -475,69 +474,6 @@ int dump_fpu (struct pt_regs * regs, elf_fpregset_t * fpregs)
475 return 1; 474 return 1;
476} 475}
477 476
478/*
479 * sparc_execve() executes a new program after the asm stub has set
480 * things up for us. This should basically do what I want it to.
481 */
482asmlinkage int sparc_execve(struct pt_regs *regs)
483{
484 int error, base = 0;
485 struct filename *filename;
486
487 /* Check for indirect call. */
488 if(regs->u_regs[UREG_G1] == 0)
489 base = 1;
490
491 filename = getname((char __user *)regs->u_regs[base + UREG_I0]);
492 error = PTR_ERR(filename);
493 if(IS_ERR(filename))
494 goto out;
495 error = do_execve(filename->name,
496 (const char __user *const __user *)
497 regs->u_regs[base + UREG_I1],
498 (const char __user *const __user *)
499 regs->u_regs[base + UREG_I2],
500 regs);
501 putname(filename);
502out:
503 return error;
504}
505
506/*
507 * This is the mechanism for creating a new kernel thread.
508 *
509 * NOTE! Only a kernel-only process(ie the swapper or direct descendants
510 * who haven't done an "execve()") should use this: it will work within
511 * a system call from a "real" process, but the process memory space will
512 * not be freed until both the parent and the child have exited.
513 */
514pid_t kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
515{
516 long retval;
517
518 __asm__ __volatile__("mov %4, %%g2\n\t" /* Set aside fn ptr... */
519 "mov %5, %%g3\n\t" /* and arg. */
520 "mov %1, %%g1\n\t"
521 "mov %2, %%o0\n\t" /* Clone flags. */
522 "mov 0, %%o1\n\t" /* usp arg == 0 */
523 "t 0x10\n\t" /* Linux/Sparc clone(). */
524 "cmp %%o1, 0\n\t"
525 "be 1f\n\t" /* The parent, just return. */
526 " nop\n\t" /* Delay slot. */
527 "jmpl %%g2, %%o7\n\t" /* Call the function. */
528 " mov %%g3, %%o0\n\t" /* Get back the arg in delay. */
529 "mov %3, %%g1\n\t"
530 "t 0x10\n\t" /* Linux/Sparc exit(). */
531 /* Notreached by child. */
532 "1: mov %%o0, %0\n\t" :
533 "=r" (retval) :
534 "i" (__NR_clone), "r" (flags | CLONE_VM | CLONE_UNTRACED),
535 "i" (__NR_exit), "r" (fn), "r" (arg) :
536 "g1", "g2", "g3", "o0", "o1", "memory", "cc");
537 return retval;
538}
539EXPORT_SYMBOL(kernel_thread);
540
541unsigned long get_wchan(struct task_struct *task) 477unsigned long get_wchan(struct task_struct *task)
542{ 478{
543 unsigned long pc, fp, bias = 0; 479 unsigned long pc, fp, bias = 0;
diff --git a/arch/sparc/kernel/process_64.c b/arch/sparc/kernel/process_64.c
index c6e0c2910043..cdb80b2adbe0 100644
--- a/arch/sparc/kernel/process_64.c
+++ b/arch/sparc/kernel/process_64.c
@@ -601,8 +601,7 @@ asmlinkage long sparc_do_fork(unsigned long clone_flags,
601 child_tid_ptr = (int __user *) regs->u_regs[UREG_I4]; 601 child_tid_ptr = (int __user *) regs->u_regs[UREG_I4];
602 } 602 }
603 603
604 ret = do_fork(clone_flags, stack_start, 604 ret = do_fork(clone_flags, stack_start, stack_size,
605 regs, stack_size,
606 parent_tid_ptr, child_tid_ptr); 605 parent_tid_ptr, child_tid_ptr);
607 606
608 /* If we get an error and potentially restart the system 607 /* If we get an error and potentially restart the system
@@ -622,64 +621,55 @@ asmlinkage long sparc_do_fork(unsigned long clone_flags,
622 * Child --> %o0 == parents pid, %o1 == 1 621 * Child --> %o0 == parents pid, %o1 == 1
623 */ 622 */
624int copy_thread(unsigned long clone_flags, unsigned long sp, 623int copy_thread(unsigned long clone_flags, unsigned long sp,
625 unsigned long unused, 624 unsigned long arg, struct task_struct *p)
626 struct task_struct *p, struct pt_regs *regs)
627{ 625{
628 struct thread_info *t = task_thread_info(p); 626 struct thread_info *t = task_thread_info(p);
627 struct pt_regs *regs = current_pt_regs();
629 struct sparc_stackf *parent_sf; 628 struct sparc_stackf *parent_sf;
630 unsigned long child_stack_sz; 629 unsigned long child_stack_sz;
631 char *child_trap_frame; 630 char *child_trap_frame;
632 int kernel_thread;
633
634 kernel_thread = (regs->tstate & TSTATE_PRIV) ? 1 : 0;
635 parent_sf = ((struct sparc_stackf *) regs) - 1;
636 631
637 /* Calculate offset to stack_frame & pt_regs */ 632 /* Calculate offset to stack_frame & pt_regs */
638 child_stack_sz = ((STACKFRAME_SZ + TRACEREG_SZ) + 633 child_stack_sz = (STACKFRAME_SZ + TRACEREG_SZ);
639 (kernel_thread ? STACKFRAME_SZ : 0));
640 child_trap_frame = (task_stack_page(p) + 634 child_trap_frame = (task_stack_page(p) +
641 (THREAD_SIZE - child_stack_sz)); 635 (THREAD_SIZE - child_stack_sz));
642 memcpy(child_trap_frame, parent_sf, child_stack_sz);
643 636
644 t->flags = (t->flags & ~((0xffUL << TI_FLAG_CWP_SHIFT) |
645 (0xffUL << TI_FLAG_CURRENT_DS_SHIFT))) |
646 (((regs->tstate + 1) & TSTATE_CWP) << TI_FLAG_CWP_SHIFT);
647 t->new_child = 1; 637 t->new_child = 1;
648 t->ksp = ((unsigned long) child_trap_frame) - STACK_BIAS; 638 t->ksp = ((unsigned long) child_trap_frame) - STACK_BIAS;
649 t->kregs = (struct pt_regs *) (child_trap_frame + 639 t->kregs = (struct pt_regs *) (child_trap_frame +
650 sizeof(struct sparc_stackf)); 640 sizeof(struct sparc_stackf));
651 t->fpsaved[0] = 0; 641 t->fpsaved[0] = 0;
652 642
653 if (kernel_thread) { 643 if (unlikely(p->flags & PF_KTHREAD)) {
654 struct sparc_stackf *child_sf = (struct sparc_stackf *) 644 memset(child_trap_frame, 0, child_stack_sz);
655 (child_trap_frame + (STACKFRAME_SZ + TRACEREG_SZ)); 645 __thread_flag_byte_ptr(t)[TI_FLAG_BYTE_CWP] =
656 646 (current_pt_regs()->tstate + 1) & TSTATE_CWP;
657 /* Zero terminate the stack backtrace. */ 647 t->current_ds = ASI_P;
658 child_sf->fp = NULL; 648 t->kregs->u_regs[UREG_G1] = sp; /* function */
659 t->kregs->u_regs[UREG_FP] = 649 t->kregs->u_regs[UREG_G2] = arg;
660 ((unsigned long) child_sf) - STACK_BIAS; 650 return 0;
651 }
661 652
662 t->flags |= ((long)ASI_P << TI_FLAG_CURRENT_DS_SHIFT); 653 parent_sf = ((struct sparc_stackf *) regs) - 1;
663 t->kregs->u_regs[UREG_G6] = (unsigned long) t; 654 memcpy(child_trap_frame, parent_sf, child_stack_sz);
664 t->kregs->u_regs[UREG_G4] = (unsigned long) t->task; 655 if (t->flags & _TIF_32BIT) {
665 } else { 656 sp &= 0x00000000ffffffffUL;
666 if (t->flags & _TIF_32BIT) { 657 regs->u_regs[UREG_FP] &= 0x00000000ffffffffUL;
667 sp &= 0x00000000ffffffffUL;
668 regs->u_regs[UREG_FP] &= 0x00000000ffffffffUL;
669 }
670 t->kregs->u_regs[UREG_FP] = sp;
671 t->flags |= ((long)ASI_AIUS << TI_FLAG_CURRENT_DS_SHIFT);
672 if (sp != regs->u_regs[UREG_FP]) {
673 unsigned long csp;
674
675 csp = clone_stackframe(sp, regs->u_regs[UREG_FP]);
676 if (!csp)
677 return -EFAULT;
678 t->kregs->u_regs[UREG_FP] = csp;
679 }
680 if (t->utraps)
681 t->utraps[0]++;
682 } 658 }
659 t->kregs->u_regs[UREG_FP] = sp;
660 __thread_flag_byte_ptr(t)[TI_FLAG_BYTE_CWP] =
661 (regs->tstate + 1) & TSTATE_CWP;
662 t->current_ds = ASI_AIUS;
663 if (sp != regs->u_regs[UREG_FP]) {
664 unsigned long csp;
665
666 csp = clone_stackframe(sp, regs->u_regs[UREG_FP]);
667 if (!csp)
668 return -EFAULT;
669 t->kregs->u_regs[UREG_FP] = csp;
670 }
671 if (t->utraps)
672 t->utraps[0]++;
683 673
684 /* Set the return value for the child. */ 674 /* Set the return value for the child. */
685 t->kregs->u_regs[UREG_I0] = current->pid; 675 t->kregs->u_regs[UREG_I0] = current->pid;
@@ -694,45 +684,6 @@ int copy_thread(unsigned long clone_flags, unsigned long sp,
694 return 0; 684 return 0;
695} 685}
696 686
697/*
698 * This is the mechanism for creating a new kernel thread.
699 *
700 * NOTE! Only a kernel-only process(ie the swapper or direct descendants
701 * who haven't done an "execve()") should use this: it will work within
702 * a system call from a "real" process, but the process memory space will
703 * not be freed until both the parent and the child have exited.
704 */
705pid_t kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
706{
707 long retval;
708
709 /* If the parent runs before fn(arg) is called by the child,
710 * the input registers of this function can be clobbered.
711 * So we stash 'fn' and 'arg' into global registers which
712 * will not be modified by the parent.
713 */
714 __asm__ __volatile__("mov %4, %%g2\n\t" /* Save FN into global */
715 "mov %5, %%g3\n\t" /* Save ARG into global */
716 "mov %1, %%g1\n\t" /* Clone syscall nr. */
717 "mov %2, %%o0\n\t" /* Clone flags. */
718 "mov 0, %%o1\n\t" /* usp arg == 0 */
719 "t 0x6d\n\t" /* Linux/Sparc clone(). */
720 "brz,a,pn %%o1, 1f\n\t" /* Parent, just return. */
721 " mov %%o0, %0\n\t"
722 "jmpl %%g2, %%o7\n\t" /* Call the function. */
723 " mov %%g3, %%o0\n\t" /* Set arg in delay. */
724 "mov %3, %%g1\n\t"
725 "t 0x6d\n\t" /* Linux/Sparc exit(). */
726 /* Notreached by child. */
727 "1:" :
728 "=r" (retval) :
729 "i" (__NR_clone), "r" (flags | CLONE_VM | CLONE_UNTRACED),
730 "i" (__NR_exit), "r" (fn), "r" (arg) :
731 "g1", "g2", "g3", "o0", "o1", "memory", "cc");
732 return retval;
733}
734EXPORT_SYMBOL(kernel_thread);
735
736typedef struct { 687typedef struct {
737 union { 688 union {
738 unsigned int pr_regs[32]; 689 unsigned int pr_regs[32];
@@ -799,41 +750,6 @@ int dump_fpu (struct pt_regs * regs, elf_fpregset_t * fpregs)
799} 750}
800EXPORT_SYMBOL(dump_fpu); 751EXPORT_SYMBOL(dump_fpu);
801 752
802/*
803 * sparc_execve() executes a new program after the asm stub has set
804 * things up for us. This should basically do what I want it to.
805 */
806asmlinkage int sparc_execve(struct pt_regs *regs)
807{
808 int error, base = 0;
809 struct filename *filename;
810
811 /* User register window flush is done by entry.S */
812
813 /* Check for indirect call. */
814 if (regs->u_regs[UREG_G1] == 0)
815 base = 1;
816
817 filename = getname((char __user *)regs->u_regs[base + UREG_I0]);
818 error = PTR_ERR(filename);
819 if (IS_ERR(filename))
820 goto out;
821 error = do_execve(filename->name,
822 (const char __user *const __user *)
823 regs->u_regs[base + UREG_I1],
824 (const char __user *const __user *)
825 regs->u_regs[base + UREG_I2], regs);
826 putname(filename);
827 if (!error) {
828 fprs_write(0);
829 current_thread_info()->xfsr[0] = 0;
830 current_thread_info()->fpsaved[0] = 0;
831 regs->tstate &= ~TSTATE_PEF;
832 }
833out:
834 return error;
835}
836
837unsigned long get_wchan(struct task_struct *task) 753unsigned long get_wchan(struct task_struct *task)
838{ 754{
839 unsigned long pc, fp, bias = 0; 755 unsigned long pc, fp, bias = 0;
diff --git a/arch/sparc/kernel/sys_sparc32.c b/arch/sparc/kernel/sys_sparc32.c
index c3239811a1b5..03c7e929ec34 100644
--- a/arch/sparc/kernel/sys_sparc32.c
+++ b/arch/sparc/kernel/sys_sparc32.c
@@ -396,42 +396,6 @@ asmlinkage long compat_sys_rt_sigaction(int sig,
396 return ret; 396 return ret;
397} 397}
398 398
399/*
400 * sparc32_execve() executes a new program after the asm stub has set
401 * things up for us. This should basically do what I want it to.
402 */
403asmlinkage long sparc32_execve(struct pt_regs *regs)
404{
405 int error, base = 0;
406 struct filename *filename;
407
408 /* User register window flush is done by entry.S */
409
410 /* Check for indirect call. */
411 if ((u32)regs->u_regs[UREG_G1] == 0)
412 base = 1;
413
414 filename = getname(compat_ptr(regs->u_regs[base + UREG_I0]));
415 error = PTR_ERR(filename);
416 if (IS_ERR(filename))
417 goto out;
418
419 error = compat_do_execve(filename->name,
420 compat_ptr(regs->u_regs[base + UREG_I1]),
421 compat_ptr(regs->u_regs[base + UREG_I2]), regs);
422
423 putname(filename);
424
425 if (!error) {
426 fprs_write(0);
427 current_thread_info()->xfsr[0] = 0;
428 current_thread_info()->fpsaved[0] = 0;
429 regs->tstate &= ~TSTATE_PEF;
430 }
431out:
432 return error;
433}
434
435#ifdef CONFIG_MODULES 399#ifdef CONFIG_MODULES
436 400
437asmlinkage long sys32_init_module(void __user *umod, u32 len, 401asmlinkage long sys32_init_module(void __user *umod, u32 len,
diff --git a/arch/sparc/kernel/sys_sparc_32.c b/arch/sparc/kernel/sys_sparc_32.c
index 57277c830151..2da0bdcae52f 100644
--- a/arch/sparc/kernel/sys_sparc_32.c
+++ b/arch/sparc/kernel/sys_sparc_32.c
@@ -249,27 +249,3 @@ out:
249 up_read(&uts_sem); 249 up_read(&uts_sem);
250 return err; 250 return err;
251} 251}
252
253/*
254 * Do a system call from kernel instead of calling sys_execve so we
255 * end up with proper pt_regs.
256 */
257int kernel_execve(const char *filename,
258 const char *const argv[],
259 const char *const envp[])
260{
261 long __res;
262 register long __g1 __asm__ ("g1") = __NR_execve;
263 register long __o0 __asm__ ("o0") = (long)(filename);
264 register long __o1 __asm__ ("o1") = (long)(argv);
265 register long __o2 __asm__ ("o2") = (long)(envp);
266 asm volatile ("t 0x10\n\t"
267 "bcc 1f\n\t"
268 "mov %%o0, %0\n\t"
269 "sub %%g0, %%o0, %0\n\t"
270 "1:\n\t"
271 : "=r" (__res), "=&r" (__o0)
272 : "1" (__o0), "r" (__o1), "r" (__o2), "r" (__g1)
273 : "cc");
274 return __res;
275}
diff --git a/arch/sparc/kernel/sys_sparc_64.c b/arch/sparc/kernel/sys_sparc_64.c
index 97309c0ec533..708bc29d36a8 100644
--- a/arch/sparc/kernel/sys_sparc_64.c
+++ b/arch/sparc/kernel/sys_sparc_64.c
@@ -646,28 +646,6 @@ SYSCALL_DEFINE5(rt_sigaction, int, sig, const struct sigaction __user *, act,
646 return ret; 646 return ret;
647} 647}
648 648
649/*
650 * Do a system call from kernel instead of calling sys_execve so we
651 * end up with proper pt_regs.
652 */
653int kernel_execve(const char *filename,
654 const char *const argv[],
655 const char *const envp[])
656{
657 long __res;
658 register long __g1 __asm__ ("g1") = __NR_execve;
659 register long __o0 __asm__ ("o0") = (long)(filename);
660 register long __o1 __asm__ ("o1") = (long)(argv);
661 register long __o2 __asm__ ("o2") = (long)(envp);
662 asm volatile ("t 0x6d\n\t"
663 "sub %%g0, %%o0, %0\n\t"
664 "movcc %%xcc, %%o0, %0\n\t"
665 : "=r" (__res), "=&r" (__o0)
666 : "1" (__o0), "r" (__o1), "r" (__o2), "r" (__g1)
667 : "cc");
668 return __res;
669}
670
671asmlinkage long sys_kern_features(void) 649asmlinkage long sys_kern_features(void)
672{ 650{
673 return KERN_FEATURE_MIXED_MODE_STACK; 651 return KERN_FEATURE_MIXED_MODE_STACK;
diff --git a/arch/sparc/kernel/syscalls.S b/arch/sparc/kernel/syscalls.S
index bf2347794e33..e0fed7711a94 100644
--- a/arch/sparc/kernel/syscalls.S
+++ b/arch/sparc/kernel/syscalls.S
@@ -1,23 +1,19 @@
1 /* SunOS's execv() call only specifies the argv argument, the 1 /* SunOS's execv() call only specifies the argv argument, the
2 * environment settings are the same as the calling processes. 2 * environment settings are the same as the calling processes.
3 */ 3 */
4sys_execve: 4sys64_execve:
5 sethi %hi(sparc_execve), %g1 5 set sys_execve, %g1
6 ba,pt %xcc, execve_merge 6 jmpl %g1, %g0
7 or %g1, %lo(sparc_execve), %g1 7 flushw
8 8
9#ifdef CONFIG_COMPAT 9#ifdef CONFIG_COMPAT
10sunos_execv: 10sunos_execv:
11 stx %g0, [%sp + PTREGS_OFF + PT_V9_I2] 11 mov %g0, %o2
12sys32_execve: 12sys32_execve:
13 sethi %hi(sparc32_execve), %g1 13 set compat_sys_execve, %g1
14 or %g1, %lo(sparc32_execve), %g1
15#endif
16
17execve_merge:
18 flushw
19 jmpl %g1, %g0 14 jmpl %g1, %g0
20 add %sp, PTREGS_OFF, %o0 15 flushw
16#endif
21 17
22 .align 32 18 .align 32
23sys_sparc_pipe: 19sys_sparc_pipe:
@@ -112,11 +108,16 @@ sys_clone:
112ret_from_syscall: 108ret_from_syscall:
113 /* Clear current_thread_info()->new_child. */ 109 /* Clear current_thread_info()->new_child. */
114 stb %g0, [%g6 + TI_NEW_CHILD] 110 stb %g0, [%g6 + TI_NEW_CHILD]
115 ldx [%g6 + TI_FLAGS], %l0
116 call schedule_tail 111 call schedule_tail
117 mov %g7, %o0 112 mov %g7, %o0
113 ldx [%sp + PTREGS_OFF + PT_V9_I0], %o0
114 brnz,pt %o0, ret_sys_call
115 ldx [%g6 + TI_FLAGS], %l0
116 ldx [%sp + PTREGS_OFF + PT_V9_G1], %l1
117 call %l1
118 ldx [%sp + PTREGS_OFF + PT_V9_G2], %o0
118 ba,pt %xcc, ret_sys_call 119 ba,pt %xcc, ret_sys_call
119 ldx [%sp + PTREGS_OFF + PT_V9_I0], %o0 120 mov 0, %o0
120 121
121 .globl sparc_exit_group 122 .globl sparc_exit_group
122 .type sparc_exit_group,#function 123 .type sparc_exit_group,#function
@@ -232,7 +233,6 @@ ret_sys_call:
232 ldx [%sp + PTREGS_OFF + PT_V9_TNPC], %l1 ! pc = npc 233 ldx [%sp + PTREGS_OFF + PT_V9_TNPC], %l1 ! pc = npc
233 234
2342: 2352:
235 stb %g0, [%g6 + TI_SYS_NOERROR]
236 /* System call success, clear Carry condition code. */ 236 /* System call success, clear Carry condition code. */
237 andn %g3, %g2, %g3 237 andn %g3, %g2, %g3
2383: 2383:
diff --git a/arch/sparc/kernel/systbls_64.S b/arch/sparc/kernel/systbls_64.S
index 017b74a63dcb..cdbd9b817751 100644
--- a/arch/sparc/kernel/systbls_64.S
+++ b/arch/sparc/kernel/systbls_64.S
@@ -107,7 +107,7 @@ sys_call_table:
107/*40*/ .word sys_newlstat, sys_dup, sys_sparc_pipe, sys_times, sys_nis_syscall 107/*40*/ .word sys_newlstat, sys_dup, sys_sparc_pipe, sys_times, sys_nis_syscall
108 .word sys_umount, sys_setgid, sys_getgid, sys_signal, sys_geteuid 108 .word sys_umount, sys_setgid, sys_getgid, sys_signal, sys_geteuid
109/*50*/ .word sys_getegid, sys_acct, sys_memory_ordering, sys_nis_syscall, sys_ioctl 109/*50*/ .word sys_getegid, sys_acct, sys_memory_ordering, sys_nis_syscall, sys_ioctl
110 .word sys_reboot, sys_nis_syscall, sys_symlink, sys_readlink, sys_execve 110 .word sys_reboot, sys_nis_syscall, sys_symlink, sys_readlink, sys64_execve
111/*60*/ .word sys_umask, sys_chroot, sys_newfstat, sys_fstat64, sys_getpagesize 111/*60*/ .word sys_umask, sys_chroot, sys_newfstat, sys_fstat64, sys_getpagesize
112 .word sys_msync, sys_vfork, sys_pread64, sys_pwrite64, sys_nis_syscall 112 .word sys_msync, sys_vfork, sys_pread64, sys_pwrite64, sys_nis_syscall
113/*70*/ .word sys_nis_syscall, sys_mmap, sys_nis_syscall, sys_64_munmap, sys_mprotect 113/*70*/ .word sys_nis_syscall, sys_mmap, sys_nis_syscall, sys_64_munmap, sys_mprotect
diff --git a/arch/sparc/kernel/traps_64.c b/arch/sparc/kernel/traps_64.c
index b66a77968f35..e7ecf1507d90 100644
--- a/arch/sparc/kernel/traps_64.c
+++ b/arch/sparc/kernel/traps_64.c
@@ -2688,8 +2688,8 @@ void __init trap_init(void)
2688 TI_PRE_COUNT != offsetof(struct thread_info, 2688 TI_PRE_COUNT != offsetof(struct thread_info,
2689 preempt_count) || 2689 preempt_count) ||
2690 TI_NEW_CHILD != offsetof(struct thread_info, new_child) || 2690 TI_NEW_CHILD != offsetof(struct thread_info, new_child) ||
2691 TI_SYS_NOERROR != offsetof(struct thread_info, 2691 TI_CURRENT_DS != offsetof(struct thread_info,
2692 syscall_noerror) || 2692 current_ds) ||
2693 TI_RESTART_BLOCK != offsetof(struct thread_info, 2693 TI_RESTART_BLOCK != offsetof(struct thread_info,
2694 restart_block) || 2694 restart_block) ||
2695 TI_KUNA_REGS != offsetof(struct thread_info, 2695 TI_KUNA_REGS != offsetof(struct thread_info,
diff --git a/arch/sparc/mm/init_64.c b/arch/sparc/mm/init_64.c
index 9e28a118e6a4..85be1ca539b2 100644
--- a/arch/sparc/mm/init_64.c
+++ b/arch/sparc/mm/init_64.c
@@ -624,7 +624,7 @@ static void __init inherit_prom_mappings(void)
624void prom_world(int enter) 624void prom_world(int enter)
625{ 625{
626 if (!enter) 626 if (!enter)
627 set_fs((mm_segment_t) { get_thread_current_ds() }); 627 set_fs(get_fs());
628 628
629 __asm__ __volatile__("flushw"); 629 __asm__ __volatile__("flushw");
630} 630}