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