aboutsummaryrefslogtreecommitdiffstats
path: root/arch/parisc/kernel/process.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/parisc/kernel/process.c')
-rw-r--r--arch/parisc/kernel/process.c142
1 files changed, 23 insertions, 119 deletions
diff --git a/arch/parisc/kernel/process.c b/arch/parisc/kernel/process.c
index cbc37216bf90..d13507246c5d 100644
--- a/arch/parisc/kernel/process.c
+++ b/arch/parisc/kernel/process.c
@@ -52,6 +52,7 @@
52 52
53#include <asm/io.h> 53#include <asm/io.h>
54#include <asm/asm-offsets.h> 54#include <asm/asm-offsets.h>
55#include <asm/assembly.h>
55#include <asm/pdc.h> 56#include <asm/pdc.h>
56#include <asm/pdc_chassis.h> 57#include <asm/pdc_chassis.h>
57#include <asm/pgalloc.h> 58#include <asm/pgalloc.h>
@@ -165,23 +166,6 @@ void (*pm_power_off)(void) = machine_power_off;
165EXPORT_SYMBOL(pm_power_off); 166EXPORT_SYMBOL(pm_power_off);
166 167
167/* 168/*
168 * Create a kernel thread
169 */
170
171extern pid_t __kernel_thread(int (*fn)(void *), void *arg, unsigned long flags);
172pid_t kernel_thread(int (*fn)(void *), void *arg, unsigned long flags)
173{
174
175 /*
176 * FIXME: Once we are sure we don't need any debug here,
177 * kernel_thread can become a #define.
178 */
179
180 return __kernel_thread(fn, arg, flags);
181}
182EXPORT_SYMBOL(kernel_thread);
183
184/*
185 * Free current thread data structures etc.. 169 * Free current thread data structures etc..
186 */ 170 */
187void exit_thread(void) 171void exit_thread(void)
@@ -218,48 +202,11 @@ int dump_task_fpu (struct task_struct *tsk, elf_fpregset_t *r)
218 return 1; 202 return 1;
219} 203}
220 204
221/* Note that "fork()" is implemented in terms of clone, with
222 parameters (SIGCHLD, regs->gr[30], regs). */
223int
224sys_clone(unsigned long clone_flags, unsigned long usp,
225 struct pt_regs *regs)
226{
227 /* Arugments from userspace are:
228 r26 = Clone flags.
229 r25 = Child stack.
230 r24 = parent_tidptr.
231 r23 = Is the TLS storage descriptor
232 r22 = child_tidptr
233
234 However, these last 3 args are only examined
235 if the proper flags are set. */
236 int __user *parent_tidptr = (int __user *)regs->gr[24];
237 int __user *child_tidptr = (int __user *)regs->gr[22];
238
239 /* usp must be word aligned. This also prevents users from
240 * passing in the value 1 (which is the signal for a special
241 * return for a kernel thread) */
242 usp = ALIGN(usp, 4);
243
244 /* A zero value for usp means use the current stack */
245 if (usp == 0)
246 usp = regs->gr[30];
247
248 return do_fork(clone_flags, usp, regs, 0, parent_tidptr, child_tidptr);
249}
250
251int
252sys_vfork(struct pt_regs *regs)
253{
254 return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->gr[30], regs, 0, NULL, NULL);
255}
256
257int 205int
258copy_thread(unsigned long clone_flags, unsigned long usp, 206copy_thread(unsigned long clone_flags, unsigned long usp,
259 unsigned long unused, /* in ia64 this is "user_stack_size" */ 207 unsigned long arg, struct task_struct *p)
260 struct task_struct * p, struct pt_regs * pregs)
261{ 208{
262 struct pt_regs * cregs = &(p->thread.regs); 209 struct pt_regs *cregs = &(p->thread.regs);
263 void *stack = task_stack_page(p); 210 void *stack = task_stack_page(p);
264 211
265 /* We have to use void * instead of a function pointer, because 212 /* We have to use void * instead of a function pointer, because
@@ -270,48 +217,39 @@ copy_thread(unsigned long clone_flags, unsigned long usp,
270#ifdef CONFIG_HPUX 217#ifdef CONFIG_HPUX
271 extern void * const hpux_child_return; 218 extern void * const hpux_child_return;
272#endif 219#endif
220 if (unlikely(p->flags & PF_KTHREAD)) {
221 memset(cregs, 0, sizeof(struct pt_regs));
222 if (!usp) /* idle thread */
223 return 0;
273 224
274 *cregs = *pregs;
275
276 /* Set the return value for the child. Note that this is not
277 actually restored by the syscall exit path, but we put it
278 here for consistency in case of signals. */
279 cregs->gr[28] = 0; /* child */
280
281 /*
282 * We need to differentiate between a user fork and a
283 * kernel fork. We can't use user_mode, because the
284 * the syscall path doesn't save iaoq. Right now
285 * We rely on the fact that kernel_thread passes
286 * in zero for usp.
287 */
288 if (usp == 1) {
289 /* kernel thread */ 225 /* kernel thread */
290 cregs->ksp = (unsigned long)stack + THREAD_SZ_ALGN;
291 /* Must exit via ret_from_kernel_thread in order 226 /* Must exit via ret_from_kernel_thread in order
292 * to call schedule_tail() 227 * to call schedule_tail()
293 */ 228 */
229 cregs->ksp = (unsigned long)stack + THREAD_SZ_ALGN + FRAME_SIZE;
294 cregs->kpc = (unsigned long) &ret_from_kernel_thread; 230 cregs->kpc = (unsigned long) &ret_from_kernel_thread;
295 /* 231 /*
296 * Copy function and argument to be called from 232 * Copy function and argument to be called from
297 * ret_from_kernel_thread. 233 * ret_from_kernel_thread.
298 */ 234 */
299#ifdef CONFIG_64BIT 235#ifdef CONFIG_64BIT
300 cregs->gr[27] = pregs->gr[27]; 236 cregs->gr[27] = ((unsigned long *)usp)[3];
237 cregs->gr[26] = ((unsigned long *)usp)[2];
238#else
239 cregs->gr[26] = usp;
301#endif 240#endif
302 cregs->gr[26] = pregs->gr[26]; 241 cregs->gr[25] = arg;
303 cregs->gr[25] = pregs->gr[25];
304 } else { 242 } else {
305 /* user thread */ 243 /* user thread */
306 /* 244 /* usp must be word aligned. This also prevents users from
307 * Note that the fork wrappers are responsible 245 * passing in the value 1 (which is the signal for a special
308 * for setting gr[21]. 246 * return for a kernel thread) */
309 */ 247 if (usp) {
310 248 usp = ALIGN(usp, 4);
311 /* Use same stack depth as parent */ 249 if (likely(usp))
312 cregs->ksp = (unsigned long)stack 250 cregs->gr[30] = usp;
313 + (pregs->gr[21] & (THREAD_SIZE - 1)); 251 }
314 cregs->gr[30] = usp; 252 cregs->ksp = (unsigned long)stack + THREAD_SZ_ALGN + FRAME_SIZE;
315 if (personality(p->personality) == PER_HPUX) { 253 if (personality(p->personality) == PER_HPUX) {
316#ifdef CONFIG_HPUX 254#ifdef CONFIG_HPUX
317 cregs->kpc = (unsigned long) &hpux_child_return; 255 cregs->kpc = (unsigned long) &hpux_child_return;
@@ -323,8 +261,7 @@ copy_thread(unsigned long clone_flags, unsigned long usp,
323 } 261 }
324 /* Setup thread TLS area from the 4th parameter in clone */ 262 /* Setup thread TLS area from the 4th parameter in clone */
325 if (clone_flags & CLONE_SETTLS) 263 if (clone_flags & CLONE_SETTLS)
326 cregs->cr27 = pregs->gr[23]; 264 cregs->cr27 = cregs->gr[23];
327
328 } 265 }
329 266
330 return 0; 267 return 0;
@@ -335,39 +272,6 @@ unsigned long thread_saved_pc(struct task_struct *t)
335 return t->thread.regs.kpc; 272 return t->thread.regs.kpc;
336} 273}
337 274
338/*
339 * sys_execve() executes a new program.
340 */
341
342asmlinkage int sys_execve(struct pt_regs *regs)
343{
344 int error;
345 struct filename *filename;
346
347 filename = getname((const char __user *) regs->gr[26]);
348 error = PTR_ERR(filename);
349 if (IS_ERR(filename))
350 goto out;
351 error = do_execve(filename->name,
352 (const char __user *const __user *) regs->gr[25],
353 (const char __user *const __user *) regs->gr[24],
354 regs);
355 putname(filename);
356out:
357
358 return error;
359}
360
361extern int __execve(const char *filename,
362 const char *const argv[],
363 const char *const envp[], struct task_struct *task);
364int kernel_execve(const char *filename,
365 const char *const argv[],
366 const char *const envp[])
367{
368 return __execve(filename, argv, envp, current);
369}
370
371unsigned long 275unsigned long
372get_wchan(struct task_struct *p) 276get_wchan(struct task_struct *p)
373{ 277{