1 /* $Id: process.c,v 1.28 2004/05/05 16:54:23 lethal Exp $ 2 * 3 * linux/arch/sh/kernel/process.c 4 * 5 * Copyright (C) 1995 Linus Torvalds 6 * 7 * SuperH version: Copyright (C) 1999, 2000 Niibe Yutaka & Kaz Kojima 8 */ 9 10 /* 11 * This file handles the architecture-dependent parts of process handling.. 12 */ 13 14 #include <linux/module.h> 15 #include <linux/unistd.h> 16 #include <linux/mm.h> 17 #include <linux/elfcore.h> 18 #include <linux/a.out.h> 19 #include <linux/slab.h> 20 #include <linux/pm.h> 21 #include <linux/ptrace.h> 22 #include <linux/kallsyms.h> 23 #include <linux/kexec.h> 24 25 #include <asm/io.h> 26 #include <asm/uaccess.h> 27 #include <asm/mmu_context.h> 28 #include <asm/elf.h> 29 30 static int hlt_counter=0; 31 32 int ubc_usercnt = 0; 33 34 #define HARD_IDLE_TIMEOUT (HZ / 3) 35 36 void (*pm_idle)(void); 37 38 void (*pm_power_off)(void); 39 EXPORT_SYMBOL(pm_power_off); 40 41 void disable_hlt(void) 42 { 43 hlt_counter++; 44 } 45 46 EXPORT_SYMBOL(disable_hlt); 47 48 void enable_hlt(void) 49 { 50 hlt_counter--; 51 } 52 53 EXPORT_SYMBOL(enable_hlt); 54 55 void default_idle(void) 56 { 57 if (!hlt_counter) 58 cpu_sleep(); 59 else 60 cpu_relax(); 61 } 62 63 void cpu_idle(void) 64 { 65 /* endless idle loop with no priority at all */ 66 while (1) { 67 void (*idle)(void) = pm_idle; 68 69 if (!idle) 70 idle = default_idle; 71 72 while (!need_resched()) 73 idle(); 74 75 preempt_enable_no_resched(); 76 schedule(); 77 preempt_disable(); 78 } 79 } 80 81 void machine_restart(char * __unused) 82 { 83 84 #ifdef CONFIG_KEXEC 85 struct kimage *image; 86 image = xchg(&kexec_image, 0); 87 if (image) { 88 machine_shutdown(); 89 machine_kexec(image); 90 } 91 #endif 92 93 /* SR.BL=1 and invoke address error to let CPU reset (manual reset) */ 94 asm volatile("ldc %0, sr\n\t" 95 "mov.l @%1, %0" : : "r" (0x10000000), "r" (0x80000001)); 96 } 97 98 void machine_halt(void) 99 { 100 local_irq_disable(); 101 102 while (1) 103 cpu_sleep(); 104 } 105 106 void machine_power_off(void) 107 { 108 if (pm_power_off) 109 pm_power_off(); 110 } 111 112 void show_regs(struct pt_regs * regs) 113 { 114 printk("\n"); 115 printk("Pid : %d, Comm: %20s\n", current->pid, current->comm); 116 print_symbol("PC is at %s\n", regs->pc); 117 printk("PC : %08lx SP : %08lx SR : %08lx ", 118 regs->pc, regs->regs[15], regs->sr); 119 #ifdef CONFIG_MMU 120 printk("TEA : %08x ", ctrl_inl(MMU_TEA)); 121 #else 122 printk(" "); 123 #endif 124 printk("%s\n", print_tainted()); 125 126 printk("R0 : %08lx R1 : %08lx R2 : %08lx R3 : %08lx\n", 127 regs->regs[0],regs->regs[1], 128 regs->regs[2],regs->regs[3]); 129 printk("R4 : %08lx R5 : %08lx R6 : %08lx R7 : %08lx\n", 130 regs->regs[4],regs->regs[5], 131 regs->regs[6],regs->regs[7]); 132 printk("R8 : %08lx R9 : %08lx R10 : %08lx R11 : %08lx\n", 133 regs->regs[8],regs->regs[9], 134 regs->regs[10],regs->regs[11]); 135 printk("R12 : %08lx R13 : %08lx R14 : %08lx\n", 136 regs->regs[12],regs->regs[13], 137 regs->regs[14]); 138 printk("MACH: %08lx MACL: %08lx GBR : %08lx PR : %08lx\n", 139 regs->mach, regs->macl, regs->gbr, regs->pr); 140 141 /* 142 * If we're in kernel mode, dump the stack too.. 143 */ 144 if (!user_mode(regs)) { 145 extern void show_task(unsigned long *sp); 146 unsigned long sp = regs->regs[15]; 147 148 show_task((unsigned long *)sp); 149 } 150 } 151 152 /* 153 * Create a kernel thread 154 */ 155 156 /* 157 * This is the mechanism for creating a new kernel thread. 158 * 159 */ 160 extern void kernel_thread_helper(void); 161 __asm__(".align 5\n" 162 "kernel_thread_helper:\n\t" 163 "jsr @r5\n\t" 164 " nop\n\t" 165 "mov.l 1f, r1\n\t" 166 "jsr @r1\n\t" 167 " mov r0, r4\n\t" 168 ".align 2\n\t" 169 "1:.long do_exit"); 170 171 int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) 172 { /* Don't use this in BL=1(cli). Or else, CPU resets! */ 173 struct pt_regs regs; 174 175 memset(®s, 0, sizeof(regs)); 176 regs.regs[4] = (unsigned long) arg; 177 regs.regs[5] = (unsigned long) fn; 178 179 regs.pc = (unsigned long) kernel_thread_helper; 180 regs.sr = (1 << 30); 181 182 /* Ok, create the new process.. */ 183 return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, ®s, 0, NULL, NULL); 184 } 185 186 /* 187 * Free current thread data structures etc.. 188 */ 189 void exit_thread(void) 190 { 191 if (current->thread.ubc_pc) { 192 current->thread.ubc_pc = 0; 193 ubc_usercnt -= 1; 194 } 195 } 196 197 void flush_thread(void) 198 { 199 #if defined(CONFIG_SH_FPU) 200 struct task_struct *tsk = current; 201 /* Forget lazy FPU state */ 202 clear_fpu(tsk, task_pt_regs(tsk)); 203 clear_used_math(); 204 #endif 205 } 206 207 void release_thread(struct task_struct *dead_task) 208 { 209 /* do nothing */ 210 } 211 212 /* Fill in the fpu structure for a core dump.. */ 213 int dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpu) 214 { 215 int fpvalid = 0; 216 217 #if defined(CONFIG_SH_FPU) 218 struct task_struct *tsk = current; 219 220 fpvalid = !!tsk_used_math(tsk); 221 if (fpvalid) { 222 unlazy_fpu(tsk, regs); 223 memcpy(fpu, &tsk->thread.fpu.hard, sizeof(*fpu)); 224 } 225 #endif 226 227 return fpvalid; 228 } 229 230 /* 231 * Capture the user space registers if the task is not running (in user space) 232 */ 233 int dump_task_regs(struct task_struct *tsk, elf_gregset_t *regs) 234 { 235 struct pt_regs ptregs; 236 237 ptregs = *task_pt_regs(tsk); 238 elf_core_copy_regs(regs, &ptregs); 239 240 return 1; 241 } 242 243 int 244 dump_task_fpu (struct task_struct *tsk, elf_fpregset_t *fpu) 245 { 246 int fpvalid = 0; 247 248 #if defined(CONFIG_SH_FPU) 249 fpvalid = !!tsk_used_math(tsk); 250 if (fpvalid) { 251 unlazy_fpu(tsk, task_pt_regs(tsk)); 252 memcpy(fpu, &tsk->thread.fpu.hard, sizeof(*fpu)); 253 } 254 #endif 255 256 return fpvalid; 257 } 258 259 asmlinkage void ret_from_fork(void); 260 261 int copy_thread(int nr, unsigned long clone_flags, unsigned long usp, 262 unsigned long unused, 263 struct task_struct *p, struct pt_regs *regs) 264 { 265 struct pt_regs *childregs; 266 #if defined(CONFIG_SH_FPU) 267 struct task_struct *tsk = current; 268 269 unlazy_fpu(tsk, regs); 270 p->thread.fpu = tsk->thread.fpu; 271 copy_to_stopped_child_used_math(p); 272 #endif 273 274 childregs = task_pt_regs(p); 275 *childregs = *regs; 276 277 if (user_mode(regs)) { 278 childregs->regs[15] = usp; 279 } else { 280 childregs->regs[15] = (unsigned long)task_stack_page(p) + THREAD_SIZE; 281 } 282 if (clone_flags & CLONE_SETTLS) { 283 childregs->gbr = childregs->regs[0]; 284 } 285 childregs->regs[0] = 0; /* Set return value for child */ 286 287 p->thread.sp = (unsigned long) childregs; 288 p->thread.pc = (unsigned long) ret_from_fork; 289 290 p->thread.ubc_pc = 0; 291 292 return 0; 293 } 294 295 /* Tracing by user break controller. */ 296 static void 297 ubc_set_tracing(int asid, unsigned long pc) 298 { 299 ctrl_outl(pc, UBC_BARA); 300 301 /* We don't have any ASID settings for the SH-2! */ 302 if (cpu_data->type != CPU_SH7604) 303 ctrl_outb(asid, UBC_BASRA); 304 305 ctrl_outl(0, UBC_BAMRA); 306 307 if (cpu_data->type == CPU_SH7729) { 308 ctrl_outw(BBR_INST | BBR_READ | BBR_CPU, UBC_BBRA); 309 ctrl_outl(BRCR_PCBA | BRCR_PCTE, UBC_BRCR); 310 } else { 311 ctrl_outw(BBR_INST | BBR_READ, UBC_BBRA); 312 ctrl_outw(BRCR_PCBA, UBC_BRCR); 313 } 314 } 315 316 /* 317 * switch_to(x,y) should switch tasks from x to y. 318 * 319 */ 320 struct task_struct *__switch_to(struct task_struct *prev, struct task_struct *next) 321 { 322 #if defined(CONFIG_SH_FPU) 323 unlazy_fpu(prev, task_pt_regs(prev)); 324 #endif 325 326 #ifdef CONFIG_PREEMPT 327 { 328 unsigned long flags; 329 struct pt_regs *regs; 330 331 local_irq_save(flags); 332 regs = task_pt_regs(prev); 333 if (user_mode(regs) && regs->regs[15] >= 0xc0000000) { 334 int offset = (int)regs->regs[15]; 335 336 /* Reset stack pointer: clear critical region mark */ 337 regs->regs[15] = regs->regs[1]; 338 if (regs->pc < regs->regs[0]) 339 /* Go to rewind point */ 340 regs->pc = regs->regs[0] + offset; 341 } 342 local_irq_restore(flags); 343 } 344 #endif 345 346 /* 347 * Restore the kernel mode register 348 * k7 (r7_bank1) 349 */ 350 asm volatile("ldc %0, r7_bank" 351 : /* no output */ 352 : "r" (task_thread_info(next))); 353 354 #ifdef CONFIG_MMU 355 /* If no tasks are using the UBC, we're done */ 356 if (ubc_usercnt == 0) 357 /* If no tasks are using the UBC, we're done */; 358 else if (next->thread.ubc_pc && next->mm) { 359 ubc_set_tracing(next->mm->context & MMU_CONTEXT_ASID_MASK, 360 next->thread.ubc_pc); 361 } else { 362 ctrl_outw(0, UBC_BBRA); 363 ctrl_outw(0, UBC_BBRB); 364 } 365 #endif 366 367 return prev; 368 } 369 370 asmlinkage int sys_fork(unsigned long r4, unsigned long r5, 371 unsigned long r6, unsigned long r7, 372 struct pt_regs regs) 373 { 374 #ifdef CONFIG_MMU 375 return do_fork(SIGCHLD, regs.regs[15], ®s, 0, NULL, NULL); 376 #else 377 /* fork almost works, enough to trick you into looking elsewhere :-( */ 378 return -EINVAL; 379 #endif 380 } 381 382 asmlinkage int sys_clone(unsigned long clone_flags, unsigned long newsp, 383 unsigned long parent_tidptr, 384 unsigned long child_tidptr, 385 struct pt_regs regs) 386 { 387 if (!newsp) 388 newsp = regs.regs[15]; 389 return do_fork(clone_flags, newsp, ®s, 0, 390 (int __user *)parent_tidptr, (int __user *)child_tidptr); 391 } 392 393 /* 394 * This is trivial, and on the face of it looks like it 395 * could equally well be done in user mode. 396 * 397 * Not so, for quite unobvious reasons - register pressure. 398 * In user mode vfork() cannot have a stack frame, and if 399 * done by calling the "clone()" system call directly, you 400 * do not have enough call-clobbered registers to hold all 401 * the information you need. 402 */ 403 asmlinkage int sys_vfork(unsigned long r4, unsigned long r5, 404 unsigned long r6, unsigned long r7, 405 struct pt_regs regs) 406 { 407 return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs.regs[15], ®s, 408 0, NULL, NULL); 409 } 410 411 /* 412 * sys_execve() executes a new program. 413 */ 414 asmlinkage int sys_execve(char *ufilename, char **uargv, 415 char **uenvp, unsigned long r7, 416 struct pt_regs regs) 417 { 418 int error; 419 char *filename; 420 421 filename = getname((char __user *)ufilename); 422 error = PTR_ERR(filename); 423 if (IS_ERR(filename)) 424 goto out; 425 426 error = do_execve(filename, 427 (char __user * __user *)uargv, 428 (char __user * __user *)uenvp, 429 ®s); 430 if (error == 0) { 431 task_lock(current); 432 current->ptrace &= ~PT_DTRACE; 433 task_unlock(current); 434 } 435 putname(filename); 436 out: 437 return error; 438 } 439 440 unsigned long get_wchan(struct task_struct *p) 441 { 442 unsigned long schedule_frame; 443 unsigned long pc; 444 445 if (!p || p == current || p->state == TASK_RUNNING) 446 return 0; 447 448 /* 449 * The same comment as on the Alpha applies here, too ... 450 */ 451 pc = thread_saved_pc(p); 452 if (in_sched_functions(pc)) { 453 schedule_frame = ((unsigned long *)(long)p->thread.sp)[1]; 454 return (unsigned long)((unsigned long *)schedule_frame)[1]; 455 } 456 return pc; 457 } 458 459 asmlinkage void break_point_trap(unsigned long r4, unsigned long r5, 460 unsigned long r6, unsigned long r7, 461 struct pt_regs regs) 462 { 463 /* Clear tracing. */ 464 ctrl_outw(0, UBC_BBRA); 465 ctrl_outw(0, UBC_BBRB); 466 current->thread.ubc_pc = 0; 467 ubc_usercnt -= 1; 468 469 force_sig(SIGTRAP, current); 470 } 471 472 asmlinkage void break_point_trap_software(unsigned long r4, unsigned long r5, 473 unsigned long r6, unsigned long r7, 474 struct pt_regs regs) 475 { 476 regs.pc -= 2; 477 force_sig(SIGTRAP, current); 478 } 479