PPC32: This changeset adds preemptible kernel support for ppc32
[opensuse:kernel.git] / arch / ppc / kernel / process.c
1 /*
2  * BK Id: %F% %I% %G% %U% %#%
3  */
4 /*
5  *  linux/arch/ppc/kernel/process.c
6  *
7  *  Derived from "arch/i386/kernel/process.c"
8  *    Copyright (C) 1995  Linus Torvalds
9  *
10  *  Updated and modified by Cort Dougan (cort@cs.nmt.edu) and
11  *  Paul Mackerras (paulus@cs.anu.edu.au)
12  *
13  *  PowerPC version 
14  *    Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
15  *
16  *  This program is free software; you can redistribute it and/or
17  *  modify it under the terms of the GNU General Public License
18  *  as published by the Free Software Foundation; either version
19  *  2 of the License, or (at your option) any later version.
20  *
21  */
22
23 #include <linux/config.h>
24 #include <linux/errno.h>
25 #include <linux/sched.h>
26 #include <linux/kernel.h>
27 #include <linux/mm.h>
28 #include <linux/smp.h>
29 #include <linux/smp_lock.h>
30 #include <linux/stddef.h>
31 #include <linux/unistd.h>
32 #include <linux/ptrace.h>
33 #include <linux/slab.h>
34 #include <linux/user.h>
35 #include <linux/elf.h>
36 #include <linux/init.h>
37 #include <linux/prctl.h>
38 #include <linux/init_task.h>
39
40 #include <asm/pgtable.h>
41 #include <asm/uaccess.h>
42 #include <asm/system.h>
43 #include <asm/io.h>
44 #include <asm/processor.h>
45 #include <asm/mmu.h>
46 #include <asm/prom.h>
47 #ifdef CONFIG_PPC_ISERIES
48 #include <asm/iSeries/Paca.h>
49 #endif
50
51 int dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpregs);
52 extern unsigned long _get_SP(void);
53
54 struct task_struct *last_task_used_math = NULL;
55 struct task_struct *last_task_used_altivec = NULL;
56
57 static struct fs_struct init_fs = INIT_FS;
58 static struct files_struct init_files = INIT_FILES;
59 static struct signal_struct init_signals = INIT_SIGNALS;
60 struct mm_struct init_mm = INIT_MM(init_mm);
61
62 /* this is 8kB-aligned so we can get to the thread_info struct
63    at the base of it from the stack pointer with 1 integer instruction. */
64 union thread_union init_thread_union
65         __attribute__((__section__(".data.init_task"))) =
66 { INIT_THREAD_INFO(init_task) };
67
68 /* initial task structure */
69 struct task_struct init_task = INIT_TASK(init_task);
70
71 /* only used to get secondary processor up */
72 struct task_struct *current_set[NR_CPUS] = {&init_task, };
73
74 #undef SHOW_TASK_SWITCHES
75 #undef CHECK_STACK
76
77 #if defined(CHECK_STACK)
78 unsigned long
79 kernel_stack_top(struct task_struct *tsk)
80 {
81         return ((unsigned long)tsk) + sizeof(union task_union);
82 }
83
84 unsigned long
85 task_top(struct task_struct *tsk)
86 {
87         return ((unsigned long)tsk) + sizeof(struct task_struct);
88 }
89
90 /* check to make sure the kernel stack is healthy */
91 int check_stack(struct task_struct *tsk)
92 {
93         unsigned long stack_top = kernel_stack_top(tsk);
94         unsigned long tsk_top = task_top(tsk);
95         int ret = 0;
96
97 #if 0   
98         /* check thread magic */
99         if ( tsk->thread.magic != THREAD_MAGIC )
100         {
101                 ret |= 1;
102                 printk("thread.magic bad: %08x\n", tsk->thread.magic);
103         }
104 #endif
105
106         if ( !tsk )
107                 printk("check_stack(): tsk bad tsk %p\n",tsk);
108         
109         /* check if stored ksp is bad */
110         if ( (tsk->thread.ksp > stack_top) || (tsk->thread.ksp < tsk_top) )
111         {
112                 printk("stack out of bounds: %s/%d\n"
113                        " tsk_top %08lx ksp %08lx stack_top %08lx\n",
114                        tsk->comm,tsk->pid,
115                        tsk_top, tsk->thread.ksp, stack_top);
116                 ret |= 2;
117         }
118         
119         /* check if stack ptr RIGHT NOW is bad */
120         if ( (tsk == current) && ((_get_SP() > stack_top ) || (_get_SP() < tsk_top)) )
121         {
122                 printk("current stack ptr out of bounds: %s/%d\n"
123                        " tsk_top %08lx sp %08lx stack_top %08lx\n",
124                        current->comm,current->pid,
125                        tsk_top, _get_SP(), stack_top);
126                 ret |= 4;
127         }
128
129 #if 0   
130         /* check amount of free stack */
131         for ( i = (unsigned long *)task_top(tsk) ; i < kernel_stack_top(tsk) ; i++ )
132         {
133                 if ( !i )
134                         printk("check_stack(): i = %p\n", i);
135                 if ( *i != 0 )
136                 {
137                         /* only notify if it's less than 900 bytes */
138                         if ( (i - (unsigned long *)task_top(tsk))  < 900 )
139                                 printk("%d bytes free on stack\n",
140                                        i - task_top(tsk));
141                         break;
142                 }
143         }
144 #endif
145
146         if (ret)
147         {
148                 panic("bad kernel stack");
149         }
150         return(ret);
151 }
152 #endif /* defined(CHECK_STACK) */
153
154 #ifdef CONFIG_ALTIVEC
155 int
156 dump_altivec(struct pt_regs *regs, elf_vrregset_t *vrregs)
157 {
158         if (regs->msr & MSR_VEC)
159                 giveup_altivec(current);
160         memcpy(vrregs, &current->thread.vr[0], sizeof(*vrregs));
161         return 1;
162 }
163
164 void 
165 enable_kernel_altivec(void)
166 {
167 #ifdef CONFIG_SMP
168         if (current->thread.regs && (current->thread.regs->msr & MSR_VEC))
169                 giveup_altivec(current);
170         else
171                 giveup_altivec(NULL);   /* just enable AltiVec for kernel - force */
172 #else
173         giveup_altivec(last_task_used_altivec);
174 #endif /* __SMP __ */
175 }
176 #endif /* CONFIG_ALTIVEC */
177
178 void
179 enable_kernel_fp(void)
180 {
181 #ifdef CONFIG_SMP
182         if (current->thread.regs && (current->thread.regs->msr & MSR_FP))
183                 giveup_fpu(current);
184         else
185                 giveup_fpu(NULL);       /* just enables FP for kernel */
186 #else
187         giveup_fpu(last_task_used_math);
188 #endif /* CONFIG_SMP */
189 }
190
191 int
192 dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpregs)
193 {
194         if (regs->msr & MSR_FP)
195                 giveup_fpu(current);
196         memcpy(fpregs, &current->thread.fpr[0], sizeof(*fpregs));
197         return 1;
198 }
199
200 void switch_to(struct task_struct *prev, struct task_struct *new)
201 {
202         struct thread_struct *new_thread, *old_thread;
203         unsigned long s;
204         
205         __save_flags(s);
206         __cli();
207 #if CHECK_STACK
208         check_stack(prev);
209         check_stack(new);
210 #endif
211
212 #ifdef CONFIG_SMP
213         /* avoid complexity of lazy save/restore of fpu
214          * by just saving it every time we switch out if
215          * this task used the fpu during the last quantum.
216          * 
217          * If it tries to use the fpu again, it'll trap and
218          * reload its fp regs.  So we don't have to do a restore
219          * every switch, just a save.
220          *  -- Cort
221          */
222         if (prev->thread.regs && (prev->thread.regs->msr & MSR_FP))
223                 giveup_fpu(prev);
224 #ifdef CONFIG_ALTIVEC   
225         /*
226          * If the previous thread used altivec in the last quantum
227          * (thus changing altivec regs) then save them.
228          * We used to check the VRSAVE register but not all apps
229          * set it, so we don't rely on it now (and in fact we need
230          * to save & restore VSCR even if VRSAVE == 0).  -- paulus
231          *
232          * On SMP we always save/restore altivec regs just to avoid the
233          * complexity of changing processors.
234          *  -- Cort
235          */
236         if ((prev->thread.regs && (prev->thread.regs->msr & MSR_VEC)))
237                 giveup_altivec(prev);
238 #endif /* CONFIG_ALTIVEC */     
239 #endif /* CONFIG_SMP */
240
241         /* Avoid the trap.  On smp this this never happens since
242          * we don't set last_task_used_altivec -- Cort
243          */
244         if (new->thread.regs && last_task_used_altivec == new)
245                 new->thread.regs->msr |= MSR_VEC;
246         new_thread = &new->thread;
247         old_thread = &current->thread;
248         _switch(old_thread, new_thread);
249         __restore_flags(s);
250 }
251
252 void show_regs(struct pt_regs * regs)
253 {
254         int i, trap;
255
256         printk("NIP: %08lX LR: %08lX SP: %08lX REGS: %p TRAP: %04lx    %s\n",
257                regs->nip, regs->link, regs->gpr[1], regs, regs->trap,
258                print_tainted());
259         printk("MSR: %08lx EE: %01x PR: %01x FP: %01x ME: %01x IR/DR: %01x%01x\n",
260                regs->msr, regs->msr&MSR_EE ? 1 : 0, regs->msr&MSR_PR ? 1 : 0,
261                regs->msr & MSR_FP ? 1 : 0,regs->msr&MSR_ME ? 1 : 0,
262                regs->msr&MSR_IR ? 1 : 0,
263                regs->msr&MSR_DR ? 1 : 0);
264         trap = TRAP(regs);
265         if (trap == 0x300 || trap == 0x600)
266                 printk("DAR: %08lX, DSISR: %08lX\n", regs->dar, regs->dsisr);
267         printk("TASK = %p[%d] '%s' ",
268                current, current->pid, current->comm);
269         printk("Last syscall: %ld ", current->thread.last_syscall);
270         printk("\nlast math %p last altivec %p", last_task_used_math,
271                last_task_used_altivec);
272
273 #if defined(CONFIG_4xx) && defined(DCRN_PLB0_BEAR)
274         printk("\nPLB0: bear= 0x%8.8x acr=   0x%8.8x besr=  0x%8.8x\n",
275             mfdcr(DCRN_POB0_BEAR), mfdcr(DCRN_PLB0_ACR),
276             mfdcr(DCRN_PLB0_BESR));
277         printk("PLB0 to OPB: bear= 0x%8.8x besr0= 0x%8.8x besr1= 0x%8.8x\n",
278             mfdcr(DCRN_PLB0_BEAR), mfdcr(DCRN_POB0_BESR0),
279             mfdcr(DCRN_POB0_BESR1));
280 #endif
281         
282 #ifdef CONFIG_SMP
283         printk(" CPU: %d", smp_processor_id());
284 #endif /* CONFIG_SMP */
285
286         for (i = 0;  i < 32;  i++) {
287                 long r;
288                 if ((i % 8) == 0)
289                         printk("\n" KERN_INFO "GPR%02d: ", i);
290                 if (__get_user(r, &regs->gpr[i]))
291                         break;
292                 printk("%08lX ", r);
293                 if (i == 12 && !FULL_REGS(regs))
294                         break;
295         }
296         printk("\n");
297         print_backtrace((unsigned long *)regs->gpr[1]);
298 }
299
300 void exit_thread(void)
301 {
302         if (last_task_used_math == current)
303                 last_task_used_math = NULL;
304         if (last_task_used_altivec == current)
305                 last_task_used_altivec = NULL;
306 }
307
308 void flush_thread(void)
309 {
310         if (last_task_used_math == current)
311                 last_task_used_math = NULL;
312         if (last_task_used_altivec == current)
313                 last_task_used_altivec = NULL;
314 }
315
316 void
317 release_thread(struct task_struct *t)
318 {
319 }
320
321 /*
322  * Copy a thread..
323  */
324 int
325 copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
326             unsigned long unused,
327             struct task_struct *p, struct pt_regs *regs)
328 {
329         struct pt_regs *childregs, *kregs;
330         extern void ret_from_fork(void);
331         unsigned long sp = (unsigned long)p->thread_info + THREAD_SIZE;
332         unsigned long childframe;
333
334         CHECK_FULL_REGS(regs);
335         /* Copy registers */
336         sp -= sizeof(struct pt_regs);
337         childregs = (struct pt_regs *) sp;
338         *childregs = *regs;
339         if ((childregs->msr & MSR_PR) == 0) {
340                 /* for kernel thread, set `current' and stackptr in new task */
341                 childregs->gpr[1] = sp + sizeof(struct pt_regs);
342                 childregs->gpr[2] = (unsigned long) p;
343                 p->thread.regs = NULL;  /* no user register state */
344         } else
345                 p->thread.regs = childregs;
346         childregs->gpr[3] = 0;  /* Result from fork() */
347         sp -= STACK_FRAME_OVERHEAD;
348         childframe = sp;
349
350         /*
351          * The way this works is that at some point in the future
352          * some task will call _switch to switch to the new task.
353          * That will pop off the stack frame created below and start
354          * the new task running at ret_from_fork.  The new task will
355          * do some house keeping and then return from the fork or clone
356          * system call, using the stack frame created above.
357          */
358         sp -= sizeof(struct pt_regs);
359         kregs = (struct pt_regs *) sp;
360         sp -= STACK_FRAME_OVERHEAD;
361         p->thread.ksp = sp;
362         kregs->nip = (unsigned long)ret_from_fork;
363 #ifdef CONFIG_PPC_ISERIES
364         kregs->softEnable = ((struct Paca *)mfspr(SPRG1))->xProcEnabled;
365 #endif  
366
367         /*
368          * copy fpu info - assume lazy fpu switch now always
369          *  -- Cort
370          */
371         if (regs->msr & MSR_FP) {
372                 giveup_fpu(current);
373                 childregs->msr &= ~(MSR_FP | MSR_FE0 | MSR_FE1);
374         }
375         memcpy(&p->thread.fpr, &current->thread.fpr, sizeof(p->thread.fpr));
376         p->thread.fpscr = current->thread.fpscr;
377
378 #ifdef CONFIG_ALTIVEC
379         /*
380          * copy altiVec info - assume lazy altiVec switch
381          * - kumar
382          */
383         if (regs->msr & MSR_VEC)
384                 giveup_altivec(current);
385         memcpy(&p->thread.vr, &current->thread.vr, sizeof(p->thread.vr));
386         p->thread.vscr = current->thread.vscr;
387         childregs->msr &= ~MSR_VEC;
388 #endif /* CONFIG_ALTIVEC */
389
390         p->thread.last_syscall = -1;
391
392         return 0;
393 }
394
395 /*
396  * Set up a thread for executing a new program
397  */
398 void start_thread(struct pt_regs *regs, unsigned long nip, unsigned long sp)
399 {
400         set_fs(USER_DS);
401         memset(regs->gpr, 0, sizeof(regs->gpr));
402         regs->ctr = 0;
403         regs->link = 0;
404         regs->xer = 0;
405         regs->ccr = 0;
406         regs->nip = nip;
407         regs->gpr[1] = sp;
408         regs->msr = MSR_USER;
409         if (last_task_used_math == current)
410                 last_task_used_math = 0;
411         if (last_task_used_altivec == current)
412                 last_task_used_altivec = 0;
413         memset(current->thread.fpr, 0, sizeof(current->thread.fpr));
414         current->thread.fpscr = 0;
415 #ifdef CONFIG_ALTIVEC
416         memset(current->thread.vr, 0, sizeof(current->thread.vr));
417         memset(&current->thread.vscr, 0, sizeof(current->thread.vscr));
418         current->thread.vrsave = 0;
419 #endif /* CONFIG_ALTIVEC */
420 }
421
422 #if 0
423 int set_fpexc_mode(struct task_struct *tsk, unsigned int val)
424 {
425         struct pt_regs *regs = tsk->thread.regs;
426
427         if (val > PR_FP_EXC_PRECISE)
428                 return -EINVAL;
429         tsk->thread.fpexc_mode = __pack_fe01(val);
430         if (regs != NULL && (regs->msr & MSR_FP) != 0)
431                 regs->msr = (regs->msr & ~(MSR_FE0|MSR_FE1))
432                         | tsk->thread.fpexc_mode;
433         return 0;
434 }
435 #endif
436
437 int sys_clone(int p1, int p2, int p3, int p4, int p5, int p6,
438               struct pt_regs *regs)
439 {
440         CHECK_FULL_REGS(regs);
441         return do_fork(p1, regs->gpr[1], regs, 0);
442 }
443
444 int sys_fork(int p1, int p2, int p3, int p4, int p5, int p6,
445              struct pt_regs *regs)
446 {
447         CHECK_FULL_REGS(regs);
448         return do_fork(SIGCHLD, regs->gpr[1], regs, 0);
449 }
450
451 int sys_vfork(int p1, int p2, int p3, int p4, int p5, int p6,
452               struct pt_regs *regs)
453 {
454         CHECK_FULL_REGS(regs);
455         return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->gpr[1], regs, 0);
456 }
457
458 int sys_execve(unsigned long a0, unsigned long a1, unsigned long a2,
459                unsigned long a3, unsigned long a4, unsigned long a5,
460                struct pt_regs *regs)
461 {
462         int error;
463         char * filename;
464
465         filename = getname((char *) a0);
466         error = PTR_ERR(filename);
467         if (IS_ERR(filename))
468                 goto out;
469         if (regs->msr & MSR_FP)
470                 giveup_fpu(current);
471 #ifdef CONFIG_ALTIVEC
472         if (regs->msr & MSR_VEC)
473                 giveup_altivec(current);
474 #endif /* CONFIG_ALTIVEC */ 
475         error = do_execve(filename, (char **) a1, (char **) a2, regs);
476         if (error == 0)
477                 current->ptrace &= ~PT_DTRACE;
478         putname(filename);
479 out:
480         return error;
481 }
482
483 void
484 print_backtrace(unsigned long *sp)
485 {
486         int cnt = 0;
487         unsigned long i;
488
489         printk("Call backtrace: ");
490         while (sp) {
491                 if (__get_user( i, &sp[1] ))
492                         break;
493                 if (cnt++ % 7 == 0)
494                         printk("\n");
495                 printk("%08lX ", i);
496                 if (cnt > 32) break;
497                 if (__get_user(sp, (unsigned long **)sp))
498                         break;
499         }
500         printk("\n");
501 }
502
503 void show_trace_task(struct task_struct *tsk)
504 {
505         unsigned long stack_top = (unsigned long) tsk->thread_info + THREAD_SIZE;
506         unsigned long sp, prev_sp;
507         int count = 0;
508
509         if (tsk == NULL)
510                 return;
511         sp = (unsigned long) &tsk->thread.ksp;
512         do {
513                 prev_sp = sp;
514                 sp = *(unsigned long *)sp;
515                 if (sp <= prev_sp || sp >= stack_top || (sp & 3) != 0)
516                         break;
517                 if (count > 0)
518                         printk("[%08lx] ", *(unsigned long *)(sp + 4));
519         } while (++count < 16);
520         if (count > 1)
521                 printk("\n");
522 }
523
524 #if 0
525 /*
526  * Low level print for debugging - Cort
527  */
528 int __init ll_printk(const char *fmt, ...)
529 {
530         va_list args;
531         char buf[256];
532         int i;
533
534         va_start(args, fmt);
535         i=vsprintf(buf,fmt,args);
536         ll_puts(buf);
537         va_end(args);
538         return i;
539 }
540
541 int lines = 24, cols = 80;
542 int orig_x = 0, orig_y = 0;
543
544 void puthex(unsigned long val)
545 {
546         unsigned char buf[10];
547         int i;
548         for (i = 7;  i >= 0;  i--)
549         {
550                 buf[i] = "0123456789ABCDEF"[val & 0x0F];
551                 val >>= 4;
552         }
553         buf[8] = '\0';
554         prom_print(buf);
555 }
556
557 void __init ll_puts(const char *s)
558 {
559         int x,y;
560         char *vidmem = (char *)/*(_ISA_MEM_BASE + 0xB8000) */0xD00B8000;
561         char c;
562         extern int mem_init_done;
563
564         if ( mem_init_done ) /* assume this means we can printk */
565         {
566                 printk(s);
567                 return;
568         }
569
570 #if 0   
571         if ( have_of )
572         {
573                 prom_print(s);
574                 return;
575         }
576 #endif
577
578         /*
579          * can't ll_puts on chrp without openfirmware yet.
580          * vidmem just needs to be setup for it.
581          * -- Cort
582          */
583         if ( _machine != _MACH_prep )
584                 return;
585         x = orig_x;
586         y = orig_y;
587
588         while ( ( c = *s++ ) != '\0' ) {
589                 if ( c == '\n' ) {
590                         x = 0;
591                         if ( ++y >= lines ) {
592                                 /*scroll();*/
593                                 /*y--;*/
594                                 y = 0;
595                         }
596                 } else {
597                         vidmem [ ( x + cols * y ) * 2 ] = c; 
598                         if ( ++x >= cols ) {
599                                 x = 0;
600                                 if ( ++y >= lines ) {
601                                         /*scroll();*/
602                                         /*y--;*/
603                                         y = 0;
604                                 }
605                         }
606                 }
607         }
608
609         orig_x = x;
610         orig_y = y;
611 }
612 #endif
613
614 /*
615  * These bracket the sleeping functions..
616  */
617 extern void scheduling_functions_start_here(void);
618 extern void scheduling_functions_end_here(void);
619 #define first_sched    ((unsigned long) scheduling_functions_start_here)
620 #define last_sched     ((unsigned long) scheduling_functions_end_here)
621
622 unsigned long get_wchan(struct task_struct *p)
623 {
624         unsigned long ip, sp;
625         unsigned long stack_page = (unsigned long) p->thread_info;
626         int count = 0;
627         if (!p || p == current || p->state == TASK_RUNNING)
628                 return 0;
629         sp = p->thread.ksp;
630         do {
631                 sp = *(unsigned long *)sp;
632                 if (sp < stack_page || sp >= stack_page + 8188)
633                         return 0;
634                 if (count > 0) {
635                         ip = *(unsigned long *)(sp + 4);
636                         if (ip < first_sched || ip >= last_sched)
637                                 return ip;
638                 }
639         } while (count++ < 16);
640         return 0;
641 }