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/sparc | |
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/sparc')
-rw-r--r-- | arch/sparc/Kconfig | 2 | ||||
-rw-r--r-- | arch/sparc/include/asm/processor_32.h | 1 | ||||
-rw-r--r-- | arch/sparc/include/asm/processor_64.h | 11 | ||||
-rw-r--r-- | arch/sparc/include/asm/ptrace.h | 10 | ||||
-rw-r--r-- | arch/sparc/include/asm/signal.h | 2 | ||||
-rw-r--r-- | arch/sparc/include/asm/switch_to_64.h | 2 | ||||
-rw-r--r-- | arch/sparc/include/asm/syscalls.h | 2 | ||||
-rw-r--r-- | arch/sparc/include/asm/thread_info_64.h | 25 | ||||
-rw-r--r-- | arch/sparc/include/asm/uaccess_64.h | 4 | ||||
-rw-r--r-- | arch/sparc/include/asm/unistd.h | 1 | ||||
-rw-r--r-- | arch/sparc/kernel/entry.S | 51 | ||||
-rw-r--r-- | arch/sparc/kernel/etrap_64.S | 8 | ||||
-rw-r--r-- | arch/sparc/kernel/process_32.c | 158 | ||||
-rw-r--r-- | arch/sparc/kernel/process_64.c | 148 | ||||
-rw-r--r-- | arch/sparc/kernel/sys_sparc32.c | 36 | ||||
-rw-r--r-- | arch/sparc/kernel/sys_sparc_32.c | 24 | ||||
-rw-r--r-- | arch/sparc/kernel/sys_sparc_64.c | 22 | ||||
-rw-r--r-- | arch/sparc/kernel/syscalls.S | 30 | ||||
-rw-r--r-- | arch/sparc/kernel/systbls_64.S | 2 | ||||
-rw-r--r-- | arch/sparc/kernel/traps_64.c | 4 | ||||
-rw-r--r-- | arch/sparc/mm/init_64.c | 2 |
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 | ||
45 | config SPARC32 | 47 | config 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) |
109 | extern pid_t kernel_thread(int (*fn)(void *), void * arg, unsigned long flags); | ||
110 | 109 | ||
111 | extern unsigned long get_wchan(struct task_struct *); | 110 | extern 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. */ |
99 | struct task_struct; | 100 | struct 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 | ||
191 | extern pid_t kernel_thread(int (*fn)(void *), void * arg, unsigned long flags); | ||
192 | |||
193 | extern unsigned long get_wchan(struct task_struct *task); | 200 | extern 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 | |||
35 | struct global_reg_snapshot { | 38 | struct 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 | ||
56 | extern union global_cpu_snapshot global_cpu_snapshot[NR_CPUS]; | 59 | extern 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) |
59 | do { 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 | ||
11 | extern 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) \ |
47 | do { \ | 47 | do { \ |
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 | ||
811 | sys_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 | ||
818 | sunos_execv: | 809 | sunos_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 |
960 | linux_sparc_ni_syscall: | 947 | linux_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 | ||
965 | linux_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 | |||
973 | linux_syscall_trace: | 952 | linux_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 | ||
974 | ret_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 | ||
1009 | syscall_is_too_hard: | 1002 | do_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 | */ |
318 | extern void ret_from_fork(void); | 317 | extern void ret_from_fork(void); |
318 | extern void ret_from_kernel_thread(void); | ||
319 | 319 | ||
320 | int copy_thread(unsigned long clone_flags, unsigned long sp, | 320 | int 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 | */ | ||
482 | asmlinkage 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); | ||
502 | out: | ||
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 | */ | ||
514 | pid_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 | } | ||
539 | EXPORT_SYMBOL(kernel_thread); | ||
540 | |||
541 | unsigned long get_wchan(struct task_struct *task) | 477 | unsigned 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 | */ |
624 | int copy_thread(unsigned long clone_flags, unsigned long sp, | 623 | int 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 | */ | ||
705 | pid_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 | } | ||
734 | EXPORT_SYMBOL(kernel_thread); | ||
735 | |||
736 | typedef struct { | 687 | typedef 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 | } |
800 | EXPORT_SYMBOL(dump_fpu); | 751 | EXPORT_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 | */ | ||
806 | asmlinkage 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 | } | ||
833 | out: | ||
834 | return error; | ||
835 | } | ||
836 | |||
837 | unsigned long get_wchan(struct task_struct *task) | 753 | unsigned 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 | */ | ||
403 | asmlinkage 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 | } | ||
431 | out: | ||
432 | return error; | ||
433 | } | ||
434 | |||
435 | #ifdef CONFIG_MODULES | 399 | #ifdef CONFIG_MODULES |
436 | 400 | ||
437 | asmlinkage long sys32_init_module(void __user *umod, u32 len, | 401 | asmlinkage 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 | */ | ||
257 | int 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 | */ | ||
653 | int 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 | |||
671 | asmlinkage long sys_kern_features(void) | 649 | asmlinkage 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 | */ |
4 | sys_execve: | 4 | sys64_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 |
10 | sunos_execv: | 10 | sunos_execv: |
11 | stx %g0, [%sp + PTREGS_OFF + PT_V9_I2] | 11 | mov %g0, %o2 |
12 | sys32_execve: | 12 | sys32_execve: |
13 | sethi %hi(sparc32_execve), %g1 | 13 | set compat_sys_execve, %g1 |
14 | or %g1, %lo(sparc32_execve), %g1 | ||
15 | #endif | ||
16 | |||
17 | execve_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 |
23 | sys_sparc_pipe: | 19 | sys_sparc_pipe: |
@@ -112,11 +108,16 @@ sys_clone: | |||
112 | ret_from_syscall: | 108 | ret_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 | ||
234 | 2: | 235 | 2: |
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 |
238 | 3: | 238 | 3: |
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) | |||
624 | void prom_world(int enter) | 624 | void 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 | } |