diff options
Diffstat (limited to 'arch/sh/kernel/process_32.c')
-rw-r--r-- | arch/sh/kernel/process_32.c | 87 |
1 files changed, 19 insertions, 68 deletions
diff --git a/arch/sh/kernel/process_32.c b/arch/sh/kernel/process_32.c index ba7345f37bc9..fce8029de922 100644 --- a/arch/sh/kernel/process_32.c +++ b/arch/sh/kernel/process_32.c | |||
@@ -68,38 +68,6 @@ void show_regs(struct pt_regs * regs) | |||
68 | show_code(regs); | 68 | show_code(regs); |
69 | } | 69 | } |
70 | 70 | ||
71 | /* | ||
72 | * Create a kernel thread | ||
73 | */ | ||
74 | __noreturn void kernel_thread_helper(void *arg, int (*fn)(void *)) | ||
75 | { | ||
76 | do_exit(fn(arg)); | ||
77 | } | ||
78 | |||
79 | /* Don't use this in BL=1(cli). Or else, CPU resets! */ | ||
80 | int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) | ||
81 | { | ||
82 | struct pt_regs regs; | ||
83 | int pid; | ||
84 | |||
85 | memset(®s, 0, sizeof(regs)); | ||
86 | regs.regs[4] = (unsigned long)arg; | ||
87 | regs.regs[5] = (unsigned long)fn; | ||
88 | |||
89 | regs.pc = (unsigned long)kernel_thread_helper; | ||
90 | regs.sr = SR_MD; | ||
91 | #if defined(CONFIG_SH_FPU) | ||
92 | regs.sr |= SR_FD; | ||
93 | #endif | ||
94 | |||
95 | /* Ok, create the new process.. */ | ||
96 | pid = do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, | ||
97 | ®s, 0, NULL, NULL); | ||
98 | |||
99 | return pid; | ||
100 | } | ||
101 | EXPORT_SYMBOL(kernel_thread); | ||
102 | |||
103 | void start_thread(struct pt_regs *regs, unsigned long new_pc, | 71 | void start_thread(struct pt_regs *regs, unsigned long new_pc, |
104 | unsigned long new_sp) | 72 | unsigned long new_sp) |
105 | { | 73 | { |
@@ -157,9 +125,10 @@ int dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpu) | |||
157 | EXPORT_SYMBOL(dump_fpu); | 125 | EXPORT_SYMBOL(dump_fpu); |
158 | 126 | ||
159 | asmlinkage void ret_from_fork(void); | 127 | asmlinkage void ret_from_fork(void); |
128 | asmlinkage void ret_from_kernel_thread(void); | ||
160 | 129 | ||
161 | int copy_thread(unsigned long clone_flags, unsigned long usp, | 130 | int copy_thread(unsigned long clone_flags, unsigned long usp, |
162 | unsigned long unused, | 131 | unsigned long arg, |
163 | struct task_struct *p, struct pt_regs *regs) | 132 | struct task_struct *p, struct pt_regs *regs) |
164 | { | 133 | { |
165 | struct thread_info *ti = task_thread_info(p); | 134 | struct thread_info *ti = task_thread_info(p); |
@@ -177,29 +146,34 @@ int copy_thread(unsigned long clone_flags, unsigned long usp, | |||
177 | } | 146 | } |
178 | #endif | 147 | #endif |
179 | 148 | ||
180 | childregs = task_pt_regs(p); | 149 | memset(p->thread.ptrace_bps, 0, sizeof(p->thread.ptrace_bps)); |
181 | *childregs = *regs; | ||
182 | 150 | ||
183 | if (user_mode(regs)) { | 151 | childregs = task_pt_regs(p); |
184 | childregs->regs[15] = usp; | 152 | p->thread.sp = (unsigned long) childregs; |
185 | ti->addr_limit = USER_DS; | 153 | if (unlikely(p->flags & PF_KTHREAD)) { |
186 | } else { | 154 | memset(childregs, 0, sizeof(struct pt_regs)); |
187 | childregs->regs[15] = (unsigned long)childregs; | 155 | p->thread.pc = (unsigned long) ret_from_kernel_thread; |
156 | childregs->regs[4] = arg; | ||
157 | childregs->regs[5] = usp; | ||
158 | childregs->sr = SR_MD; | ||
159 | #if defined(CONFIG_SH_FPU) | ||
160 | childregs->sr |= SR_FD; | ||
161 | #endif | ||
188 | ti->addr_limit = KERNEL_DS; | 162 | ti->addr_limit = KERNEL_DS; |
189 | ti->status &= ~TS_USEDFPU; | 163 | ti->status &= ~TS_USEDFPU; |
190 | p->fpu_counter = 0; | 164 | p->fpu_counter = 0; |
165 | return 0; | ||
191 | } | 166 | } |
167 | *childregs = *regs; | ||
168 | |||
169 | childregs->regs[15] = usp; | ||
170 | ti->addr_limit = USER_DS; | ||
192 | 171 | ||
193 | if (clone_flags & CLONE_SETTLS) | 172 | if (clone_flags & CLONE_SETTLS) |
194 | childregs->gbr = childregs->regs[0]; | 173 | childregs->gbr = childregs->regs[0]; |
195 | 174 | ||
196 | childregs->regs[0] = 0; /* Set return value for child */ | 175 | childregs->regs[0] = 0; /* Set return value for child */ |
197 | |||
198 | p->thread.sp = (unsigned long) childregs; | ||
199 | p->thread.pc = (unsigned long) ret_from_fork; | 176 | p->thread.pc = (unsigned long) ret_from_fork; |
200 | |||
201 | memset(p->thread.ptrace_bps, 0, sizeof(p->thread.ptrace_bps)); | ||
202 | |||
203 | return 0; | 177 | return 0; |
204 | } | 178 | } |
205 | 179 | ||
@@ -288,29 +262,6 @@ asmlinkage int sys_vfork(unsigned long r4, unsigned long r5, | |||
288 | 0, NULL, NULL); | 262 | 0, NULL, NULL); |
289 | } | 263 | } |
290 | 264 | ||
291 | /* | ||
292 | * sys_execve() executes a new program. | ||
293 | */ | ||
294 | asmlinkage int sys_execve(const char __user *ufilename, | ||
295 | const char __user *const __user *uargv, | ||
296 | const char __user *const __user *uenvp, | ||
297 | unsigned long r7, struct pt_regs __regs) | ||
298 | { | ||
299 | struct pt_regs *regs = RELOC_HIDE(&__regs, 0); | ||
300 | int error; | ||
301 | struct filename *filename; | ||
302 | |||
303 | filename = getname(ufilename); | ||
304 | error = PTR_ERR(filename); | ||
305 | if (IS_ERR(filename)) | ||
306 | goto out; | ||
307 | |||
308 | error = do_execve(filename->name, uargv, uenvp, regs); | ||
309 | putname(filename); | ||
310 | out: | ||
311 | return error; | ||
312 | } | ||
313 | |||
314 | unsigned long get_wchan(struct task_struct *p) | 265 | unsigned long get_wchan(struct task_struct *p) |
315 | { | 266 | { |
316 | unsigned long pc; | 267 | unsigned long pc; |