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/microblaze | |
| 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/microblaze')
| -rw-r--r-- | arch/microblaze/Kconfig | 3 | ||||
| -rw-r--r-- | arch/microblaze/include/asm/Kbuild | 1 | ||||
| -rw-r--r-- | arch/microblaze/include/asm/processor.h | 8 | ||||
| -rw-r--r-- | arch/microblaze/include/asm/syscalls.h | 16 | ||||
| -rw-r--r-- | arch/microblaze/include/asm/unistd.h | 6 | ||||
| -rw-r--r-- | arch/microblaze/kernel/entry-nommu.S | 20 | ||||
| -rw-r--r-- | arch/microblaze/kernel/entry.S | 57 | ||||
| -rw-r--r-- | arch/microblaze/kernel/process.c | 75 | ||||
| -rw-r--r-- | arch/microblaze/kernel/sys_microblaze.c | 53 | ||||
| -rw-r--r-- | arch/microblaze/kernel/syscall_table.S | 6 |
10 files changed, 52 insertions, 193 deletions
diff --git a/arch/microblaze/Kconfig b/arch/microblaze/Kconfig index 4cba7439f9d..4bcf89148f3 100644 --- a/arch/microblaze/Kconfig +++ b/arch/microblaze/Kconfig | |||
| @@ -26,6 +26,9 @@ config MICROBLAZE | |||
| 26 | select GENERIC_ATOMIC64 | 26 | select GENERIC_ATOMIC64 |
| 27 | select GENERIC_CLOCKEVENTS | 27 | select GENERIC_CLOCKEVENTS |
| 28 | select MODULES_USE_ELF_RELA | 28 | select MODULES_USE_ELF_RELA |
| 29 | select GENERIC_KERNEL_THREAD | ||
| 30 | select GENERIC_KERNEL_EXECVE | ||
| 31 | select CLONE_BACKWARDS | ||
| 29 | 32 | ||
| 30 | config SWAP | 33 | config SWAP |
| 31 | def_bool n | 34 | def_bool n |
diff --git a/arch/microblaze/include/asm/Kbuild b/arch/microblaze/include/asm/Kbuild index 2957fcc7176..eb3a46c096f 100644 --- a/arch/microblaze/include/asm/Kbuild +++ b/arch/microblaze/include/asm/Kbuild | |||
| @@ -4,3 +4,4 @@ header-y += elf.h | |||
| 4 | generic-y += clkdev.h | 4 | generic-y += clkdev.h |
| 5 | generic-y += exec.h | 5 | generic-y += exec.h |
| 6 | generic-y += trace_clock.h | 6 | generic-y += trace_clock.h |
| 7 | generic-y += syscalls.h | ||
diff --git a/arch/microblaze/include/asm/processor.h b/arch/microblaze/include/asm/processor.h index af2bb965239..0759153e811 100644 --- a/arch/microblaze/include/asm/processor.h +++ b/arch/microblaze/include/asm/processor.h | |||
| @@ -31,6 +31,7 @@ extern const struct seq_operations cpuinfo_op; | |||
| 31 | void start_thread(struct pt_regs *regs, unsigned long pc, unsigned long usp); | 31 | void start_thread(struct pt_regs *regs, unsigned long pc, unsigned long usp); |
| 32 | 32 | ||
| 33 | extern void ret_from_fork(void); | 33 | extern void ret_from_fork(void); |
| 34 | extern void ret_from_kernel_thread(void); | ||
| 34 | 35 | ||
| 35 | # endif /* __ASSEMBLY__ */ | 36 | # endif /* __ASSEMBLY__ */ |
| 36 | 37 | ||
| @@ -78,11 +79,6 @@ extern unsigned long thread_saved_pc(struct task_struct *t); | |||
| 78 | 79 | ||
| 79 | extern unsigned long get_wchan(struct task_struct *p); | 80 | extern unsigned long get_wchan(struct task_struct *p); |
| 80 | 81 | ||
| 81 | /* | ||
| 82 | * create a kernel thread without removing it from tasklists | ||
| 83 | */ | ||
| 84 | extern int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags); | ||
| 85 | |||
| 86 | # define KSTK_EIP(tsk) (0) | 82 | # define KSTK_EIP(tsk) (0) |
| 87 | # define KSTK_ESP(tsk) (0) | 83 | # define KSTK_ESP(tsk) (0) |
| 88 | 84 | ||
| @@ -131,8 +127,6 @@ extern inline void release_thread(struct task_struct *dead_task) | |||
| 131 | { | 127 | { |
| 132 | } | 128 | } |
| 133 | 129 | ||
| 134 | extern int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags); | ||
| 135 | |||
| 136 | /* Free current thread data structures etc. */ | 130 | /* Free current thread data structures etc. */ |
| 137 | static inline void exit_thread(void) | 131 | static inline void exit_thread(void) |
| 138 | { | 132 | { |
diff --git a/arch/microblaze/include/asm/syscalls.h b/arch/microblaze/include/asm/syscalls.h deleted file mode 100644 index 27f2f4c0f39..00000000000 --- a/arch/microblaze/include/asm/syscalls.h +++ /dev/null | |||
| @@ -1,16 +0,0 @@ | |||
| 1 | #ifndef __ASM_MICROBLAZE_SYSCALLS_H | ||
| 2 | |||
| 3 | asmlinkage long microblaze_vfork(struct pt_regs *regs); | ||
| 4 | asmlinkage long microblaze_clone(int flags, unsigned long stack, | ||
| 5 | struct pt_regs *regs); | ||
| 6 | asmlinkage long microblaze_execve(const char __user *filenamei, | ||
| 7 | const char __user *const __user *argv, | ||
| 8 | const char __user *const __user *envp, | ||
| 9 | struct pt_regs *regs); | ||
| 10 | |||
| 11 | asmlinkage long sys_clone(int flags, unsigned long stack, struct pt_regs *regs); | ||
| 12 | #define sys_clone sys_clone | ||
| 13 | |||
| 14 | #include <asm-generic/syscalls.h> | ||
| 15 | |||
| 16 | #endif /* __ASM_MICROBLAZE_SYSCALLS_H */ | ||
diff --git a/arch/microblaze/include/asm/unistd.h b/arch/microblaze/include/asm/unistd.h index 6985e6e9d82..94d978986b7 100644 --- a/arch/microblaze/include/asm/unistd.h +++ b/arch/microblaze/include/asm/unistd.h | |||
| @@ -422,6 +422,12 @@ | |||
| 422 | #define __ARCH_WANT_SYS_SIGPROCMASK | 422 | #define __ARCH_WANT_SYS_SIGPROCMASK |
| 423 | #define __ARCH_WANT_SYS_RT_SIGACTION | 423 | #define __ARCH_WANT_SYS_RT_SIGACTION |
| 424 | #define __ARCH_WANT_SYS_RT_SIGSUSPEND | 424 | #define __ARCH_WANT_SYS_RT_SIGSUSPEND |
| 425 | #define __ARCH_WANT_SYS_EXECVE | ||
| 426 | #define __ARCH_WANT_SYS_CLONE | ||
| 427 | #define __ARCH_WANT_SYS_VFORK | ||
| 428 | #ifdef CONFIG_MMU | ||
| 429 | #define __ARCH_WANT_SYS_FORK | ||
| 430 | #endif | ||
| 425 | 431 | ||
| 426 | /* | 432 | /* |
| 427 | * "Conditional" syscalls | 433 | * "Conditional" syscalls |
diff --git a/arch/microblaze/kernel/entry-nommu.S b/arch/microblaze/kernel/entry-nommu.S index 75c3ea1f48a..cb0327f204a 100644 --- a/arch/microblaze/kernel/entry-nommu.S +++ b/arch/microblaze/kernel/entry-nommu.S | |||
| @@ -474,6 +474,14 @@ ENTRY(ret_from_fork) | |||
| 474 | brid ret_to_user | 474 | brid ret_to_user |
| 475 | nop | 475 | nop |
| 476 | 476 | ||
| 477 | ENTRY(ret_from_kernel_thread) | ||
| 478 | brlid r15, schedule_tail | ||
| 479 | addk r5, r0, r3 | ||
| 480 | brald r15, r20 | ||
| 481 | addk r5, r0, r19 | ||
| 482 | brid ret_to_user | ||
| 483 | addk r3, r0, r0 | ||
| 484 | |||
| 477 | work_pending: | 485 | work_pending: |
| 478 | enable_irq | 486 | enable_irq |
| 479 | 487 | ||
| @@ -551,18 +559,6 @@ no_work_pending: | |||
| 551 | rtid r14, 0 | 559 | rtid r14, 0 |
| 552 | nop | 560 | nop |
| 553 | 561 | ||
| 554 | sys_vfork: | ||
| 555 | brid microblaze_vfork | ||
| 556 | addk r5, r1, r0 | ||
| 557 | |||
| 558 | sys_clone: | ||
| 559 | brid microblaze_clone | ||
| 560 | addk r7, r1, r0 | ||
| 561 | |||
| 562 | sys_execve: | ||
| 563 | brid microblaze_execve | ||
| 564 | addk r8, r1, r0 | ||
| 565 | |||
| 566 | sys_rt_sigreturn_wrapper: | 562 | sys_rt_sigreturn_wrapper: |
| 567 | brid sys_rt_sigreturn | 563 | brid sys_rt_sigreturn |
| 568 | addk r5, r1, r0 | 564 | addk r5, r1, r0 |
diff --git a/arch/microblaze/kernel/entry.S b/arch/microblaze/kernel/entry.S index 03f7b8ce6b6..c217367dfc7 100644 --- a/arch/microblaze/kernel/entry.S +++ b/arch/microblaze/kernel/entry.S | |||
| @@ -293,24 +293,6 @@ C_ENTRY(_user_exception): | |||
| 293 | swi r1, r0, TOPHYS(PER_CPU(ENTRY_SP)) /* save stack */ | 293 | swi r1, r0, TOPHYS(PER_CPU(ENTRY_SP)) /* save stack */ |
| 294 | addi r14, r14, 4 /* return address is 4 byte after call */ | 294 | addi r14, r14, 4 /* return address is 4 byte after call */ |
| 295 | 295 | ||
| 296 | mfs r1, rmsr | ||
| 297 | nop | ||
| 298 | andi r1, r1, MSR_UMS | ||
| 299 | bnei r1, 1f | ||
| 300 | |||
| 301 | /* Kernel-mode state save - kernel execve */ | ||
| 302 | lwi r1, r0, TOPHYS(PER_CPU(ENTRY_SP)); /* Reload kernel stack-ptr*/ | ||
| 303 | tophys(r1,r1); | ||
| 304 | |||
| 305 | addik r1, r1, -PT_SIZE; /* Make room on the stack. */ | ||
| 306 | SAVE_REGS | ||
| 307 | |||
| 308 | swi r1, r1, PT_MODE; /* pt_regs -> kernel mode */ | ||
| 309 | brid 2f; | ||
| 310 | nop; /* Fill delay slot */ | ||
| 311 | |||
| 312 | /* User-mode state save. */ | ||
| 313 | 1: | ||
| 314 | lwi r1, r0, TOPHYS(PER_CPU(CURRENT_SAVE)); /* get saved current */ | 296 | lwi r1, r0, TOPHYS(PER_CPU(CURRENT_SAVE)); /* get saved current */ |
| 315 | tophys(r1,r1); | 297 | tophys(r1,r1); |
| 316 | lwi r1, r1, TS_THREAD_INFO; /* get stack from task_struct */ | 298 | lwi r1, r1, TS_THREAD_INFO; /* get stack from task_struct */ |
| @@ -460,18 +442,6 @@ TRAP_return: /* Make global symbol for debugging */ | |||
| 460 | nop; | 442 | nop; |
| 461 | 443 | ||
| 462 | 444 | ||
| 463 | /* These syscalls need access to the struct pt_regs on the stack, so we | ||
| 464 | implement them in assembly (they're basically all wrappers anyway). */ | ||
| 465 | |||
| 466 | C_ENTRY(sys_fork_wrapper): | ||
| 467 | addi r5, r0, SIGCHLD /* Arg 0: flags */ | ||
| 468 | lwi r6, r1, PT_R1 /* Arg 1: child SP (use parent's) */ | ||
| 469 | addik r7, r1, 0 /* Arg 2: parent context */ | ||
| 470 | add r8, r0, r0 /* Arg 3: (unused) */ | ||
| 471 | add r9, r0, r0; /* Arg 4: (unused) */ | ||
| 472 | brid do_fork /* Do real work (tail-call) */ | ||
| 473 | add r10, r0, r0; /* Arg 5: (unused) */ | ||
| 474 | |||
| 475 | /* This the initial entry point for a new child thread, with an appropriate | 445 | /* This the initial entry point for a new child thread, with an appropriate |
| 476 | stack in place that makes it look the the child is in the middle of an | 446 | stack in place that makes it look the the child is in the middle of an |
| 477 | syscall. This function is actually `returned to' from switch_thread | 447 | syscall. This function is actually `returned to' from switch_thread |
| @@ -479,28 +449,19 @@ C_ENTRY(sys_fork_wrapper): | |||
| 479 | saved context). */ | 449 | saved context). */ |
| 480 | C_ENTRY(ret_from_fork): | 450 | C_ENTRY(ret_from_fork): |
| 481 | bralid r15, schedule_tail; /* ...which is schedule_tail's arg */ | 451 | bralid r15, schedule_tail; /* ...which is schedule_tail's arg */ |
| 482 | add r3, r5, r0; /* switch_thread returns the prev task */ | 452 | add r5, r3, r0; /* switch_thread returns the prev task */ |
| 483 | /* ( in the delay slot ) */ | 453 | /* ( in the delay slot ) */ |
| 484 | brid ret_from_trap; /* Do normal trap return */ | 454 | brid ret_from_trap; /* Do normal trap return */ |
| 485 | add r3, r0, r0; /* Child's fork call should return 0. */ | 455 | add r3, r0, r0; /* Child's fork call should return 0. */ |
| 486 | 456 | ||
| 487 | C_ENTRY(sys_vfork): | 457 | C_ENTRY(ret_from_kernel_thread): |
| 488 | brid microblaze_vfork /* Do real work (tail-call) */ | 458 | bralid r15, schedule_tail; /* ...which is schedule_tail's arg */ |
| 489 | addik r5, r1, 0 | 459 | add r5, r3, r0; /* switch_thread returns the prev task */ |
| 490 | 460 | /* ( in the delay slot ) */ | |
| 491 | C_ENTRY(sys_clone): | 461 | brald r15, r20 /* fn was left in r20 */ |
| 492 | bnei r6, 1f; /* See if child SP arg (arg 1) is 0. */ | 462 | addk r5, r0, r19 /* ... and argument - in r19 */ |
| 493 | lwi r6, r1, PT_R1; /* If so, use paret's stack ptr */ | 463 | brid ret_from_trap |
| 494 | 1: addik r7, r1, 0; /* Arg 2: parent context */ | 464 | add r3, r0, r0 |
| 495 | lwi r9, r1, PT_R8; /* parent tid. */ | ||
| 496 | lwi r10, r1, PT_R9; /* child tid. */ | ||
| 497 | /* do_fork will pick up TLS from regs->r10. */ | ||
| 498 | brid do_fork /* Do real work (tail-call) */ | ||
| 499 | add r8, r0, r0; /* Arg 3: (unused) */ | ||
| 500 | |||
| 501 | C_ENTRY(sys_execve): | ||
| 502 | brid microblaze_execve; /* Do real work (tail-call).*/ | ||
| 503 | addik r8, r1, 0; /* add user context as 4th arg */ | ||
| 504 | 465 | ||
| 505 | C_ENTRY(sys_rt_sigreturn_wrapper): | 466 | C_ENTRY(sys_rt_sigreturn_wrapper): |
| 506 | brid sys_rt_sigreturn /* Do real work */ | 467 | brid sys_rt_sigreturn /* Do real work */ |
diff --git a/arch/microblaze/kernel/process.c b/arch/microblaze/kernel/process.c index 1944e00f07e..40823fd1db0 100644 --- a/arch/microblaze/kernel/process.c +++ b/arch/microblaze/kernel/process.c | |||
| @@ -13,6 +13,7 @@ | |||
| 13 | #include <linux/pm.h> | 13 | #include <linux/pm.h> |
| 14 | #include <linux/tick.h> | 14 | #include <linux/tick.h> |
| 15 | #include <linux/bitops.h> | 15 | #include <linux/bitops.h> |
| 16 | #include <linux/ptrace.h> | ||
| 16 | #include <asm/pgalloc.h> | 17 | #include <asm/pgalloc.h> |
| 17 | #include <asm/uaccess.h> /* for USER_DS macros */ | 18 | #include <asm/uaccess.h> /* for USER_DS macros */ |
| 18 | #include <asm/cacheflush.h> | 19 | #include <asm/cacheflush.h> |
| @@ -119,46 +120,38 @@ void flush_thread(void) | |||
| 119 | } | 120 | } |
| 120 | 121 | ||
| 121 | int copy_thread(unsigned long clone_flags, unsigned long usp, | 122 | int copy_thread(unsigned long clone_flags, unsigned long usp, |
| 122 | unsigned long unused, | 123 | unsigned long arg, struct task_struct *p) |
| 123 | struct task_struct *p, struct pt_regs *regs) | ||
| 124 | { | 124 | { |
| 125 | struct pt_regs *childregs = task_pt_regs(p); | 125 | struct pt_regs *childregs = task_pt_regs(p); |
| 126 | struct thread_info *ti = task_thread_info(p); | 126 | struct thread_info *ti = task_thread_info(p); |
| 127 | 127 | ||
| 128 | *childregs = *regs; | 128 | if (unlikely(p->flags & PF_KTHREAD)) { |
| 129 | if (user_mode(regs)) | 129 | /* if we're creating a new kernel thread then just zeroing all |
| 130 | * the registers. That's OK for a brand new thread.*/ | ||
| 131 | memset(childregs, 0, sizeof(struct pt_regs)); | ||
| 132 | memset(&ti->cpu_context, 0, sizeof(struct cpu_context)); | ||
| 133 | ti->cpu_context.r1 = (unsigned long)childregs; | ||
| 134 | ti->cpu_context.r20 = (unsigned long)usp; /* fn */ | ||
| 135 | ti->cpu_context.r19 = (unsigned long)arg; | ||
| 136 | childregs->pt_mode = 1; | ||
| 137 | local_save_flags(childregs->msr); | ||
| 138 | #ifdef CONFIG_MMU | ||
| 139 | ti->cpu_context.msr = childregs->msr & ~MSR_IE; | ||
| 140 | #endif | ||
| 141 | ti->cpu_context.r15 = (unsigned long)ret_from_kernel_thread - 8; | ||
| 142 | return 0; | ||
| 143 | } | ||
| 144 | *childregs = *current_pt_regs(); | ||
| 145 | if (usp) | ||
| 130 | childregs->r1 = usp; | 146 | childregs->r1 = usp; |
| 131 | else | ||
| 132 | childregs->r1 = ((unsigned long) ti) + THREAD_SIZE; | ||
| 133 | 147 | ||
| 134 | #ifndef CONFIG_MMU | ||
| 135 | memset(&ti->cpu_context, 0, sizeof(struct cpu_context)); | 148 | memset(&ti->cpu_context, 0, sizeof(struct cpu_context)); |
| 136 | ti->cpu_context.r1 = (unsigned long)childregs; | 149 | ti->cpu_context.r1 = (unsigned long)childregs; |
| 150 | #ifndef CONFIG_MMU | ||
| 137 | ti->cpu_context.msr = (unsigned long)childregs->msr; | 151 | ti->cpu_context.msr = (unsigned long)childregs->msr; |
| 138 | #else | 152 | #else |
| 153 | childregs->msr |= MSR_UMS; | ||
| 139 | 154 | ||
| 140 | /* if creating a kernel thread then update the current reg (we don't | ||
| 141 | * want to use the parent's value when restoring by POP_STATE) */ | ||
| 142 | if (kernel_mode(regs)) | ||
| 143 | /* save new current on stack to use POP_STATE */ | ||
| 144 | childregs->CURRENT_TASK = (unsigned long)p; | ||
| 145 | /* if returning to user then use the parent's value of this register */ | ||
| 146 | |||
| 147 | /* if we're creating a new kernel thread then just zeroing all | ||
| 148 | * the registers. That's OK for a brand new thread.*/ | ||
| 149 | /* Pls. note that some of them will be restored in POP_STATE */ | ||
| 150 | if (kernel_mode(regs)) | ||
| 151 | memset(&ti->cpu_context, 0, sizeof(struct cpu_context)); | ||
| 152 | /* if this thread is created for fork/vfork/clone, then we want to | ||
| 153 | * restore all the parent's context */ | ||
| 154 | /* in addition to the registers which will be restored by POP_STATE */ | ||
| 155 | else { | ||
| 156 | ti->cpu_context = *(struct cpu_context *)regs; | ||
| 157 | childregs->msr |= MSR_UMS; | ||
| 158 | } | ||
| 159 | |||
| 160 | /* FIXME STATE_SAVE_PT_OFFSET; */ | ||
| 161 | ti->cpu_context.r1 = (unsigned long)childregs; | ||
| 162 | /* we should consider the fact that childregs is a copy of the parent | 155 | /* we should consider the fact that childregs is a copy of the parent |
| 163 | * regs which were saved immediately after entering the kernel state | 156 | * regs which were saved immediately after entering the kernel state |
| 164 | * before enabling VM. This MSR will be restored in switch_to and | 157 | * before enabling VM. This MSR will be restored in switch_to and |
| @@ -209,29 +202,6 @@ unsigned long thread_saved_pc(struct task_struct *tsk) | |||
| 209 | } | 202 | } |
| 210 | #endif | 203 | #endif |
| 211 | 204 | ||
| 212 | static void kernel_thread_helper(int (*fn)(void *), void *arg) | ||
| 213 | { | ||
| 214 | fn(arg); | ||
| 215 | do_exit(-1); | ||
| 216 | } | ||
| 217 | |||
| 218 | int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags) | ||
| 219 | { | ||
| 220 | struct pt_regs regs; | ||
| 221 | |||
| 222 | memset(®s, 0, sizeof(regs)); | ||
| 223 | /* store them in non-volatile registers */ | ||
| 224 | regs.r5 = (unsigned long)fn; | ||
| 225 | regs.r6 = (unsigned long)arg; | ||
| 226 | local_save_flags(regs.msr); | ||
| 227 | regs.pc = (unsigned long)kernel_thread_helper; | ||
| 228 | regs.pt_mode = 1; | ||
| 229 | |||
| 230 | return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, | ||
| 231 | ®s, 0, NULL, NULL); | ||
| 232 | } | ||
| 233 | EXPORT_SYMBOL_GPL(kernel_thread); | ||
| 234 | |||
| 235 | unsigned long get_wchan(struct task_struct *p) | 205 | unsigned long get_wchan(struct task_struct *p) |
| 236 | { | 206 | { |
| 237 | /* TBD (used by procfs) */ | 207 | /* TBD (used by procfs) */ |
| @@ -246,6 +216,7 @@ void start_thread(struct pt_regs *regs, unsigned long pc, unsigned long usp) | |||
| 246 | regs->pt_mode = 0; | 216 | regs->pt_mode = 0; |
| 247 | #ifdef CONFIG_MMU | 217 | #ifdef CONFIG_MMU |
| 248 | regs->msr |= MSR_UMS; | 218 | regs->msr |= MSR_UMS; |
| 219 | regs->msr &= ~MSR_VM; | ||
| 249 | #endif | 220 | #endif |
| 250 | } | 221 | } |
| 251 | 222 | ||
diff --git a/arch/microblaze/kernel/sys_microblaze.c b/arch/microblaze/kernel/sys_microblaze.c index 404c0f24bd4..63647c586b4 100644 --- a/arch/microblaze/kernel/sys_microblaze.c +++ b/arch/microblaze/kernel/sys_microblaze.c | |||
| @@ -34,38 +34,6 @@ | |||
| 34 | 34 | ||
| 35 | #include <asm/syscalls.h> | 35 | #include <asm/syscalls.h> |
| 36 | 36 | ||
| 37 | asmlinkage long microblaze_vfork(struct pt_regs *regs) | ||
| 38 | { | ||
| 39 | return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->r1, | ||
| 40 | regs, 0, NULL, NULL); | ||
| 41 | } | ||
| 42 | |||
| 43 | asmlinkage long microblaze_clone(int flags, unsigned long stack, | ||
| 44 | struct pt_regs *regs) | ||
| 45 | { | ||
| 46 | if (!stack) | ||
| 47 | stack = regs->r1; | ||
| 48 | return do_fork(flags, stack, regs, 0, NULL, NULL); | ||
| 49 | } | ||
| 50 | |||
| 51 | asmlinkage long microblaze_execve(const char __user *filenamei, | ||
| 52 | const char __user *const __user *argv, | ||
| 53 | const char __user *const __user *envp, | ||
| 54 | struct pt_regs *regs) | ||
| 55 | { | ||
| 56 | int error; | ||
| 57 | struct filename *filename; | ||
| 58 | |||
| 59 | filename = getname(filenamei); | ||
| 60 | error = PTR_ERR(filename); | ||
| 61 | if (IS_ERR(filename)) | ||
| 62 | goto out; | ||
| 63 | error = do_execve(filename->name, argv, envp, regs); | ||
| 64 | putname(filename); | ||
| 65 | out: | ||
| 66 | return error; | ||
| 67 | } | ||
| 68 | |||
| 69 | asmlinkage long sys_mmap(unsigned long addr, unsigned long len, | 37 | asmlinkage long sys_mmap(unsigned long addr, unsigned long len, |
| 70 | unsigned long prot, unsigned long flags, | 38 | unsigned long prot, unsigned long flags, |
| 71 | unsigned long fd, off_t pgoff) | 39 | unsigned long fd, off_t pgoff) |
| @@ -75,24 +43,3 @@ asmlinkage long sys_mmap(unsigned long addr, unsigned long len, | |||
| 75 | 43 | ||
| 76 | return sys_mmap_pgoff(addr, len, prot, flags, fd, pgoff >> PAGE_SHIFT); | 44 | return sys_mmap_pgoff(addr, len, prot, flags, fd, pgoff >> PAGE_SHIFT); |
| 77 | } | 45 | } |
| 78 | |||
| 79 | /* | ||
| 80 | * Do a system call from kernel instead of calling sys_execve so we | ||
| 81 | * end up with proper pt_regs. | ||
| 82 | */ | ||
| 83 | int kernel_execve(const char *filename, | ||
| 84 | const char *const argv[], | ||
| 85 | const char *const envp[]) | ||
| 86 | { | ||
| 87 | register const char *__a __asm__("r5") = filename; | ||
| 88 | register const void *__b __asm__("r6") = argv; | ||
| 89 | register const void *__c __asm__("r7") = envp; | ||
| 90 | register unsigned long __syscall __asm__("r12") = __NR_execve; | ||
| 91 | register unsigned long __ret __asm__("r3"); | ||
| 92 | __asm__ __volatile__ ("brki r14, 0x8" | ||
| 93 | : "=r" (__ret), "=r" (__syscall) | ||
| 94 | : "1" (__syscall), "r" (__a), "r" (__b), "r" (__c) | ||
| 95 | : "r4", "r8", "r9", | ||
| 96 | "r10", "r11", "r14", "cc", "memory"); | ||
| 97 | return __ret; | ||
| 98 | } | ||
diff --git a/arch/microblaze/kernel/syscall_table.S b/arch/microblaze/kernel/syscall_table.S index 6a2b294ef6d..ff6431e5468 100644 --- a/arch/microblaze/kernel/syscall_table.S +++ b/arch/microblaze/kernel/syscall_table.S | |||
| @@ -2,11 +2,7 @@ ENTRY(sys_call_table) | |||
| 2 | .long sys_restart_syscall /* 0 - old "setup()" system call, | 2 | .long sys_restart_syscall /* 0 - old "setup()" system call, |
| 3 | * used for restarting */ | 3 | * used for restarting */ |
| 4 | .long sys_exit | 4 | .long sys_exit |
| 5 | #ifdef CONFIG_MMU | 5 | .long sys_fork |
| 6 | .long sys_fork_wrapper | ||
| 7 | #else | ||
| 8 | .long sys_ni_syscall | ||
| 9 | #endif | ||
| 10 | .long sys_read | 6 | .long sys_read |
| 11 | .long sys_write | 7 | .long sys_write |
| 12 | .long sys_open /* 5 */ | 8 | .long sys_open /* 5 */ |
