diff options
Diffstat (limited to 'arch/m68k/kernel/process.c')
| -rw-r--r-- | arch/m68k/kernel/process.c | 104 |
1 files changed, 24 insertions, 80 deletions
diff --git a/arch/m68k/kernel/process.c b/arch/m68k/kernel/process.c index ac2892e49c7c..c51bb172e14d 100644 --- a/arch/m68k/kernel/process.c +++ b/arch/m68k/kernel/process.c | |||
| @@ -35,6 +35,7 @@ | |||
| 35 | 35 | ||
| 36 | 36 | ||
| 37 | asmlinkage void ret_from_fork(void); | 37 | asmlinkage void ret_from_fork(void); |
| 38 | asmlinkage void ret_from_kernel_thread(void); | ||
| 38 | 39 | ||
| 39 | 40 | ||
| 40 | /* | 41 | /* |
| @@ -123,51 +124,6 @@ void show_regs(struct pt_regs * regs) | |||
| 123 | printk("USP: %08lx\n", rdusp()); | 124 | printk("USP: %08lx\n", rdusp()); |
| 124 | } | 125 | } |
| 125 | 126 | ||
| 126 | /* | ||
| 127 | * Create a kernel thread | ||
| 128 | */ | ||
| 129 | int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) | ||
| 130 | { | ||
| 131 | int pid; | ||
| 132 | mm_segment_t fs; | ||
| 133 | |||
| 134 | fs = get_fs(); | ||
| 135 | set_fs (KERNEL_DS); | ||
| 136 | |||
| 137 | { | ||
| 138 | register long retval __asm__ ("d0"); | ||
| 139 | register long clone_arg __asm__ ("d1") = flags | CLONE_VM | CLONE_UNTRACED; | ||
| 140 | |||
| 141 | retval = __NR_clone; | ||
| 142 | __asm__ __volatile__ | ||
| 143 | ("clrl %%d2\n\t" | ||
| 144 | "trap #0\n\t" /* Linux/m68k system call */ | ||
| 145 | "tstl %0\n\t" /* child or parent */ | ||
| 146 | "jne 1f\n\t" /* parent - jump */ | ||
| 147 | #ifdef CONFIG_MMU | ||
| 148 | "lea %%sp@(%c7),%6\n\t" /* reload current */ | ||
| 149 | "movel %6@,%6\n\t" | ||
| 150 | #endif | ||
| 151 | "movel %3,%%sp@-\n\t" /* push argument */ | ||
| 152 | "jsr %4@\n\t" /* call fn */ | ||
| 153 | "movel %0,%%d1\n\t" /* pass exit value */ | ||
| 154 | "movel %2,%%d0\n\t" /* exit */ | ||
| 155 | "trap #0\n" | ||
| 156 | "1:" | ||
| 157 | : "+d" (retval) | ||
| 158 | : "i" (__NR_clone), "i" (__NR_exit), | ||
| 159 | "r" (arg), "a" (fn), "d" (clone_arg), "r" (current), | ||
| 160 | "i" (-THREAD_SIZE) | ||
| 161 | : "d2"); | ||
| 162 | |||
| 163 | pid = retval; | ||
| 164 | } | ||
| 165 | |||
| 166 | set_fs (fs); | ||
| 167 | return pid; | ||
| 168 | } | ||
| 169 | EXPORT_SYMBOL(kernel_thread); | ||
| 170 | |||
| 171 | void flush_thread(void) | 127 | void flush_thread(void) |
| 172 | { | 128 | { |
| 173 | current->thread.fs = __USER_DS; | 129 | current->thread.fs = __USER_DS; |
| @@ -219,30 +175,18 @@ asmlinkage int m68k_clone(struct pt_regs *regs) | |||
| 219 | } | 175 | } |
| 220 | 176 | ||
| 221 | int copy_thread(unsigned long clone_flags, unsigned long usp, | 177 | int copy_thread(unsigned long clone_flags, unsigned long usp, |
| 222 | unsigned long unused, | 178 | unsigned long arg, |
| 223 | struct task_struct * p, struct pt_regs * regs) | 179 | struct task_struct * p, struct pt_regs * regs) |
| 224 | { | 180 | { |
| 225 | struct pt_regs * childregs; | 181 | struct pt_regs * childregs; |
| 226 | struct switch_stack * childstack, *stack; | 182 | struct switch_stack *childstack; |
| 227 | unsigned long *retp; | ||
| 228 | 183 | ||
| 229 | childregs = (struct pt_regs *) (task_stack_page(p) + THREAD_SIZE) - 1; | 184 | childregs = (struct pt_regs *) (task_stack_page(p) + THREAD_SIZE) - 1; |
| 230 | |||
| 231 | *childregs = *regs; | ||
| 232 | childregs->d0 = 0; | ||
| 233 | |||
| 234 | retp = ((unsigned long *) regs); | ||
| 235 | stack = ((struct switch_stack *) retp) - 1; | ||
| 236 | |||
| 237 | childstack = ((struct switch_stack *) childregs) - 1; | 185 | childstack = ((struct switch_stack *) childregs) - 1; |
| 238 | *childstack = *stack; | ||
| 239 | childstack->retpc = (unsigned long)ret_from_fork; | ||
| 240 | 186 | ||
| 241 | p->thread.usp = usp; | 187 | p->thread.usp = usp; |
| 242 | p->thread.ksp = (unsigned long)childstack; | 188 | p->thread.ksp = (unsigned long)childstack; |
| 243 | 189 | p->thread.esp0 = (unsigned long)childregs; | |
| 244 | if (clone_flags & CLONE_SETTLS) | ||
| 245 | task_thread_info(p)->tp_value = regs->d5; | ||
| 246 | 190 | ||
| 247 | /* | 191 | /* |
| 248 | * Must save the current SFC/DFC value, NOT the value when | 192 | * Must save the current SFC/DFC value, NOT the value when |
| @@ -250,6 +194,26 @@ int copy_thread(unsigned long clone_flags, unsigned long usp, | |||
| 250 | */ | 194 | */ |
| 251 | p->thread.fs = get_fs().seg; | 195 | p->thread.fs = get_fs().seg; |
| 252 | 196 | ||
| 197 | if (unlikely(!regs)) { | ||
| 198 | /* kernel thread */ | ||
| 199 | memset(childstack, 0, | ||
| 200 | sizeof(struct switch_stack) + sizeof(struct pt_regs)); | ||
| 201 | childregs->sr = PS_S; | ||
| 202 | childstack->a3 = usp; /* function */ | ||
| 203 | childstack->d7 = arg; | ||
| 204 | childstack->retpc = (unsigned long)ret_from_kernel_thread; | ||
| 205 | p->thread.usp = 0; | ||
| 206 | return 0; | ||
| 207 | } | ||
| 208 | *childregs = *regs; | ||
| 209 | childregs->d0 = 0; | ||
| 210 | |||
| 211 | *childstack = ((struct switch_stack *) regs)[-1]; | ||
| 212 | childstack->retpc = (unsigned long)ret_from_fork; | ||
| 213 | |||
| 214 | if (clone_flags & CLONE_SETTLS) | ||
| 215 | task_thread_info(p)->tp_value = regs->d5; | ||
| 216 | |||
| 253 | #ifdef CONFIG_FPU | 217 | #ifdef CONFIG_FPU |
| 254 | if (!FPU_IS_EMU) { | 218 | if (!FPU_IS_EMU) { |
| 255 | /* Copy the current fpu state */ | 219 | /* Copy the current fpu state */ |
| @@ -337,26 +301,6 @@ int dump_fpu (struct pt_regs *regs, struct user_m68kfp_struct *fpu) | |||
| 337 | EXPORT_SYMBOL(dump_fpu); | 301 | EXPORT_SYMBOL(dump_fpu); |
| 338 | #endif /* CONFIG_FPU */ | 302 | #endif /* CONFIG_FPU */ |
| 339 | 303 | ||
| 340 | /* | ||
| 341 | * sys_execve() executes a new program. | ||
| 342 | */ | ||
| 343 | asmlinkage int sys_execve(const char __user *name, | ||
| 344 | const char __user *const __user *argv, | ||
| 345 | const char __user *const __user *envp) | ||
| 346 | { | ||
| 347 | int error; | ||
| 348 | char * filename; | ||
| 349 | struct pt_regs *regs = (struct pt_regs *) &name; | ||
| 350 | |||
| 351 | filename = getname(name); | ||
| 352 | error = PTR_ERR(filename); | ||
| 353 | if (IS_ERR(filename)) | ||
| 354 | return error; | ||
| 355 | error = do_execve(filename, argv, envp, regs); | ||
| 356 | putname(filename); | ||
| 357 | return error; | ||
| 358 | } | ||
| 359 | |||
| 360 | unsigned long get_wchan(struct task_struct *p) | 304 | unsigned long get_wchan(struct task_struct *p) |
| 361 | { | 305 | { |
| 362 | unsigned long fp, pc; | 306 | unsigned long fp, pc; |
