diff options
| author | Al Viro <viro@zeniv.linux.org.uk> | 2012-10-27 00:13:51 -0400 |
|---|---|---|
| committer | Al Viro <viro@zeniv.linux.org.uk> | 2012-11-28 22:36:47 -0500 |
| commit | 0ad9513d0f81584c25f3fc7ff582c382cc1a93f7 (patch) | |
| tree | 1bf616181ff9fb07d413d5e949e9ea0527fc1915 /arch/sh/kernel | |
| parent | 415bfae9e9dbc2232f1797a3ac78a22049a75e06 (diff) | |
sh: switch to generic fork/vfork/clone
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'arch/sh/kernel')
| -rw-r--r-- | arch/sh/kernel/process_32.c | 52 | ||||
| -rw-r--r-- | arch/sh/kernel/process_64.c | 43 |
2 files changed, 8 insertions, 87 deletions
diff --git a/arch/sh/kernel/process_32.c b/arch/sh/kernel/process_32.c index fce8029de92..1786d16b6c6 100644 --- a/arch/sh/kernel/process_32.c +++ b/arch/sh/kernel/process_32.c | |||
| @@ -129,7 +129,7 @@ asmlinkage void ret_from_kernel_thread(void); | |||
| 129 | 129 | ||
| 130 | int copy_thread(unsigned long clone_flags, unsigned long usp, | 130 | int copy_thread(unsigned long clone_flags, unsigned long usp, |
| 131 | unsigned long arg, | 131 | unsigned long arg, |
| 132 | struct task_struct *p, struct pt_regs *regs) | 132 | struct task_struct *p, struct pt_regs *unused) |
| 133 | { | 133 | { |
| 134 | struct thread_info *ti = task_thread_info(p); | 134 | struct thread_info *ti = task_thread_info(p); |
| 135 | struct pt_regs *childregs; | 135 | struct pt_regs *childregs; |
| @@ -164,9 +164,10 @@ int copy_thread(unsigned long clone_flags, unsigned long usp, | |||
| 164 | p->fpu_counter = 0; | 164 | p->fpu_counter = 0; |
| 165 | return 0; | 165 | return 0; |
| 166 | } | 166 | } |
| 167 | *childregs = *regs; | 167 | *childregs = *current_pt_regs(); |
| 168 | 168 | ||
| 169 | childregs->regs[15] = usp; | 169 | if (usp) |
| 170 | childregs->regs[15] = usp; | ||
| 170 | ti->addr_limit = USER_DS; | 171 | ti->addr_limit = USER_DS; |
| 171 | 172 | ||
| 172 | if (clone_flags & CLONE_SETTLS) | 173 | if (clone_flags & CLONE_SETTLS) |
| @@ -217,51 +218,6 @@ __switch_to(struct task_struct *prev, struct task_struct *next) | |||
| 217 | return prev; | 218 | return prev; |
| 218 | } | 219 | } |
| 219 | 220 | ||
| 220 | asmlinkage int sys_fork(unsigned long r4, unsigned long r5, | ||
| 221 | unsigned long r6, unsigned long r7, | ||
| 222 | struct pt_regs __regs) | ||
| 223 | { | ||
| 224 | #ifdef CONFIG_MMU | ||
| 225 | struct pt_regs *regs = RELOC_HIDE(&__regs, 0); | ||
| 226 | return do_fork(SIGCHLD, regs->regs[15], regs, 0, NULL, NULL); | ||
| 227 | #else | ||
| 228 | /* fork almost works, enough to trick you into looking elsewhere :-( */ | ||
| 229 | return -EINVAL; | ||
| 230 | #endif | ||
| 231 | } | ||
| 232 | |||
| 233 | asmlinkage int sys_clone(unsigned long clone_flags, unsigned long newsp, | ||
| 234 | unsigned long parent_tidptr, | ||
| 235 | unsigned long child_tidptr, | ||
| 236 | struct pt_regs __regs) | ||
| 237 | { | ||
| 238 | struct pt_regs *regs = RELOC_HIDE(&__regs, 0); | ||
| 239 | if (!newsp) | ||
| 240 | newsp = regs->regs[15]; | ||
| 241 | return do_fork(clone_flags, newsp, regs, 0, | ||
| 242 | (int __user *)parent_tidptr, | ||
| 243 | (int __user *)child_tidptr); | ||
| 244 | } | ||
| 245 | |||
| 246 | /* | ||
| 247 | * This is trivial, and on the face of it looks like it | ||
| 248 | * could equally well be done in user mode. | ||
| 249 | * | ||
| 250 | * Not so, for quite unobvious reasons - register pressure. | ||
| 251 | * In user mode vfork() cannot have a stack frame, and if | ||
| 252 | * done by calling the "clone()" system call directly, you | ||
| 253 | * do not have enough call-clobbered registers to hold all | ||
| 254 | * the information you need. | ||
| 255 | */ | ||
| 256 | asmlinkage int sys_vfork(unsigned long r4, unsigned long r5, | ||
| 257 | unsigned long r6, unsigned long r7, | ||
| 258 | struct pt_regs __regs) | ||
| 259 | { | ||
| 260 | struct pt_regs *regs = RELOC_HIDE(&__regs, 0); | ||
| 261 | return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->regs[15], regs, | ||
| 262 | 0, NULL, NULL); | ||
| 263 | } | ||
| 264 | |||
| 265 | unsigned long get_wchan(struct task_struct *p) | 221 | unsigned long get_wchan(struct task_struct *p) |
| 266 | { | 222 | { |
| 267 | unsigned long pc; | 223 | unsigned long pc; |
diff --git a/arch/sh/kernel/process_64.c b/arch/sh/kernel/process_64.c index 3a0f3fd3bb5..d5c86a8a384 100644 --- a/arch/sh/kernel/process_64.c +++ b/arch/sh/kernel/process_64.c | |||
| @@ -383,7 +383,7 @@ int copy_thread(unsigned long clone_flags, unsigned long usp, | |||
| 383 | save_fpu(current); | 383 | save_fpu(current); |
| 384 | disable_fpu(); | 384 | disable_fpu(); |
| 385 | last_task_used_math = NULL; | 385 | last_task_used_math = NULL; |
| 386 | regs->sr |= SR_FD; | 386 | current_pt_regs()->sr |= SR_FD; |
| 387 | } | 387 | } |
| 388 | #endif | 388 | #endif |
| 389 | /* Copy from sh version */ | 389 | /* Copy from sh version */ |
| @@ -399,7 +399,7 @@ int copy_thread(unsigned long clone_flags, unsigned long usp, | |||
| 399 | p->thread.pc = (unsigned long) ret_from_kernel_thread; | 399 | p->thread.pc = (unsigned long) ret_from_kernel_thread; |
| 400 | return 0; | 400 | return 0; |
| 401 | } | 401 | } |
| 402 | *childregs = *regs; | 402 | *childregs = *current_pt_regs(); |
| 403 | 403 | ||
| 404 | /* | 404 | /* |
| 405 | * Sign extend the edited stack. | 405 | * Sign extend the edited stack. |
| @@ -407,7 +407,8 @@ int copy_thread(unsigned long clone_flags, unsigned long usp, | |||
| 407 | * 32-bit wide and context switch must take care | 407 | * 32-bit wide and context switch must take care |
| 408 | * of NEFF sign extension. | 408 | * of NEFF sign extension. |
| 409 | */ | 409 | */ |
| 410 | childregs->regs[15] = neff_sign_extend(usp); | 410 | if (usp) |
| 411 | childregs->regs[15] = neff_sign_extend(usp); | ||
| 411 | p->thread.uregs = childregs; | 412 | p->thread.uregs = childregs; |
| 412 | 413 | ||
| 413 | childregs->regs[9] = 0; /* Set return value for child */ | 414 | childregs->regs[9] = 0; /* Set return value for child */ |
| @@ -418,42 +419,6 @@ int copy_thread(unsigned long clone_flags, unsigned long usp, | |||
| 418 | return 0; | 419 | return 0; |
| 419 | } | 420 | } |
| 420 | 421 | ||
| 421 | asmlinkage int sys_fork(unsigned long r2, unsigned long r3, | ||
| 422 | unsigned long r4, unsigned long r5, | ||
| 423 | unsigned long r6, unsigned long r7, | ||
| 424 | struct pt_regs *pregs) | ||
| 425 | { | ||
| 426 | return do_fork(SIGCHLD, pregs->regs[15], pregs, 0, 0, 0); | ||
| 427 | } | ||
| 428 | |||
| 429 | asmlinkage int sys_clone(unsigned long clone_flags, unsigned long newsp, | ||
| 430 | unsigned long r4, unsigned long r5, | ||
| 431 | unsigned long r6, unsigned long r7, | ||
| 432 | struct pt_regs *pregs) | ||
| 433 | { | ||
| 434 | if (!newsp) | ||
| 435 | newsp = pregs->regs[15]; | ||
| 436 | return do_fork(clone_flags, newsp, pregs, 0, 0, 0); | ||
| 437 | } | ||
| 438 | |||
| 439 | /* | ||
| 440 | * This is trivial, and on the face of it looks like it | ||
| 441 | * could equally well be done in user mode. | ||
| 442 | * | ||
| 443 | * Not so, for quite unobvious reasons - register pressure. | ||
| 444 | * In user mode vfork() cannot have a stack frame, and if | ||
| 445 | * done by calling the "clone()" system call directly, you | ||
| 446 | * do not have enough call-clobbered registers to hold all | ||
| 447 | * the information you need. | ||
| 448 | */ | ||
| 449 | asmlinkage int sys_vfork(unsigned long r2, unsigned long r3, | ||
| 450 | unsigned long r4, unsigned long r5, | ||
| 451 | unsigned long r6, unsigned long r7, | ||
| 452 | struct pt_regs *pregs) | ||
| 453 | { | ||
| 454 | return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, pregs->regs[15], pregs, 0, 0, 0); | ||
| 455 | } | ||
| 456 | |||
| 457 | #ifdef CONFIG_FRAME_POINTER | 422 | #ifdef CONFIG_FRAME_POINTER |
| 458 | static int in_sh64_switch_to(unsigned long pc) | 423 | static int in_sh64_switch_to(unsigned long pc) |
| 459 | { | 424 | { |
