]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blob - arch/powerpc/kernel/entry_32.S
c94aba54b5dd75f64aadbb4056e529807b7d7f14
[linux-2.6-omap-h63xx.git] / arch / powerpc / kernel / entry_32.S
1 /*
2  *  PowerPC version
3  *    Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
4  *  Rewritten by Cort Dougan (cort@fsmlabs.com) for PReP
5  *    Copyright (C) 1996 Cort Dougan <cort@fsmlabs.com>
6  *  Adapted for Power Macintosh by Paul Mackerras.
7  *  Low-level exception handlers and MMU support
8  *  rewritten by Paul Mackerras.
9  *    Copyright (C) 1996 Paul Mackerras.
10  *  MPC8xx modifications Copyright (C) 1997 Dan Malek (dmalek@jlc.net).
11  *
12  *  This file contains the system call entry code, context switch
13  *  code, and exception/interrupt return code for PowerPC.
14  *
15  *  This program is free software; you can redistribute it and/or
16  *  modify it under the terms of the GNU General Public License
17  *  as published by the Free Software Foundation; either version
18  *  2 of the License, or (at your option) any later version.
19  *
20  */
21
22 #include <linux/errno.h>
23 #include <linux/sys.h>
24 #include <linux/threads.h>
25 #include <asm/reg.h>
26 #include <asm/page.h>
27 #include <asm/mmu.h>
28 #include <asm/cputable.h>
29 #include <asm/thread_info.h>
30 #include <asm/ppc_asm.h>
31 #include <asm/asm-offsets.h>
32 #include <asm/unistd.h>
33
34 #undef SHOW_SYSCALLS
35 #undef SHOW_SYSCALLS_TASK
36
37 /*
38  * MSR_KERNEL is > 0x10000 on 4xx/Book-E since it include MSR_CE.
39  */
40 #if MSR_KERNEL >= 0x10000
41 #define LOAD_MSR_KERNEL(r, x)   lis r,(x)@h; ori r,r,(x)@l
42 #else
43 #define LOAD_MSR_KERNEL(r, x)   li r,(x)
44 #endif
45
46 #ifdef CONFIG_BOOKE
47         .globl  mcheck_transfer_to_handler
48 mcheck_transfer_to_handler:
49         b       transfer_to_handler_full
50
51         .globl  debug_transfer_to_handler
52 debug_transfer_to_handler:
53         b       transfer_to_handler_full
54
55         .globl  crit_transfer_to_handler
56 crit_transfer_to_handler:
57         /* fall through */
58 #endif
59
60 #ifdef CONFIG_40x
61         .globl  crit_transfer_to_handler
62 crit_transfer_to_handler:
63         lwz     r0,crit_r10@l(0)
64         stw     r0,GPR10(r11)
65         lwz     r0,crit_r11@l(0)
66         stw     r0,GPR11(r11)
67         /* fall through */
68 #endif
69
70 /*
71  * This code finishes saving the registers to the exception frame
72  * and jumps to the appropriate handler for the exception, turning
73  * on address translation.
74  * Note that we rely on the caller having set cr0.eq iff the exception
75  * occurred in kernel mode (i.e. MSR:PR = 0).
76  */
77         .globl  transfer_to_handler_full
78 transfer_to_handler_full:
79         SAVE_NVGPRS(r11)
80         /* fall through */
81
82         .globl  transfer_to_handler
83 transfer_to_handler:
84         stw     r2,GPR2(r11)
85         stw     r12,_NIP(r11)
86         stw     r9,_MSR(r11)
87         andi.   r2,r9,MSR_PR
88         mfctr   r12
89         mfspr   r2,SPRN_XER
90         stw     r12,_CTR(r11)
91         stw     r2,_XER(r11)
92         mfspr   r12,SPRN_SPRG3
93         addi    r2,r12,-THREAD
94         tovirt(r2,r2)                   /* set r2 to current */
95         beq     2f                      /* if from user, fix up THREAD.regs */
96         addi    r11,r1,STACK_FRAME_OVERHEAD
97         stw     r11,PT_REGS(r12)
98 #if defined(CONFIG_40x) || defined(CONFIG_BOOKE)
99         /* Check to see if the dbcr0 register is set up to debug.  Use the
100            internal debug mode bit to do this. */
101         lwz     r12,THREAD_DBCR0(r12)
102         andis.  r12,r12,DBCR0_IDM@h
103         beq+    3f
104         /* From user and task is ptraced - load up global dbcr0 */
105         li      r12,-1                  /* clear all pending debug events */
106         mtspr   SPRN_DBSR,r12
107         lis     r11,global_dbcr0@ha
108         tophys(r11,r11)
109         addi    r11,r11,global_dbcr0@l
110 #ifdef CONFIG_SMP
111         rlwinm  r9,r1,0,0,(31-THREAD_SHIFT)
112         lwz     r9,TI_CPU(r9)
113         slwi    r9,r9,3
114         add     r11,r11,r9
115 #endif
116         lwz     r12,0(r11)
117         mtspr   SPRN_DBCR0,r12
118         lwz     r12,4(r11)
119         addi    r12,r12,-1
120         stw     r12,4(r11)
121 #endif
122         b       3f
123
124 2:      /* if from kernel, check interrupted DOZE/NAP mode and
125          * check for stack overflow
126          */
127         lwz     r9,KSP_LIMIT(r12)
128         cmplw   r1,r9                   /* if r1 <= ksp_limit */
129         ble-    stack_ovf               /* then the kernel stack overflowed */
130 5:
131 #ifdef CONFIG_6xx
132         rlwinm  r9,r1,0,0,31-THREAD_SHIFT
133         tophys(r9,r9)                   /* check local flags */
134         lwz     r12,TI_LOCAL_FLAGS(r9)
135         mtcrf   0x01,r12
136         bt-     31-TLF_NAPPING,4f
137         bt-     31-TLF_SLEEPING,7f
138 #endif /* CONFIG_6xx */
139         .globl transfer_to_handler_cont
140 transfer_to_handler_cont:
141 3:
142         mflr    r9
143         lwz     r11,0(r9)               /* virtual address of handler */
144         lwz     r9,4(r9)                /* where to go when done */
145         mtspr   SPRN_SRR0,r11
146         mtspr   SPRN_SRR1,r10
147         mtlr    r9
148         SYNC
149         RFI                             /* jump to handler, enable MMU */
150
151 #ifdef CONFIG_6xx
152 4:      rlwinm  r12,r12,0,~_TLF_NAPPING
153         stw     r12,TI_LOCAL_FLAGS(r9)
154         b       power_save_6xx_restore
155
156 7:      rlwinm  r12,r12,0,~_TLF_SLEEPING
157         stw     r12,TI_LOCAL_FLAGS(r9)
158         lwz     r9,_MSR(r11)            /* if sleeping, clear MSR.EE */
159         rlwinm  r9,r9,0,~MSR_EE
160         lwz     r12,_LINK(r11)          /* and return to address in LR */
161         b       fast_exception_return
162 #endif
163
164 /*
165  * On kernel stack overflow, load up an initial stack pointer
166  * and call StackOverflow(regs), which should not return.
167  */
168 stack_ovf:
169         /* sometimes we use a statically-allocated stack, which is OK. */
170         lis     r12,_end@h
171         ori     r12,r12,_end@l
172         cmplw   r1,r12
173         ble     5b                      /* r1 <= &_end is OK */
174         SAVE_NVGPRS(r11)
175         addi    r3,r1,STACK_FRAME_OVERHEAD
176         lis     r1,init_thread_union@ha
177         addi    r1,r1,init_thread_union@l
178         addi    r1,r1,THREAD_SIZE-STACK_FRAME_OVERHEAD
179         lis     r9,StackOverflow@ha
180         addi    r9,r9,StackOverflow@l
181         LOAD_MSR_KERNEL(r10,MSR_KERNEL)
182         FIX_SRR1(r10,r12)
183         mtspr   SPRN_SRR0,r9
184         mtspr   SPRN_SRR1,r10
185         SYNC
186         RFI
187
188 /*
189  * Handle a system call.
190  */
191         .stabs  "arch/powerpc/kernel/",N_SO,0,0,0f
192         .stabs  "entry_32.S",N_SO,0,0,0f
193 0:
194
195 _GLOBAL(DoSyscall)
196         stw     r3,ORIG_GPR3(r1)
197         li      r12,0
198         stw     r12,RESULT(r1)
199         lwz     r11,_CCR(r1)    /* Clear SO bit in CR */
200         rlwinm  r11,r11,0,4,2
201         stw     r11,_CCR(r1)
202 #ifdef SHOW_SYSCALLS
203         bl      do_show_syscall
204 #endif /* SHOW_SYSCALLS */
205         rlwinm  r10,r1,0,0,(31-THREAD_SHIFT)    /* current_thread_info() */
206         lwz     r11,TI_FLAGS(r10)
207         andi.   r11,r11,_TIF_SYSCALL_T_OR_A
208         bne-    syscall_dotrace
209 syscall_dotrace_cont:
210         cmplwi  0,r0,NR_syscalls
211         lis     r10,sys_call_table@h
212         ori     r10,r10,sys_call_table@l
213         slwi    r0,r0,2
214         bge-    66f
215         lwzx    r10,r10,r0      /* Fetch system call handler [ptr] */
216         mtlr    r10
217         addi    r9,r1,STACK_FRAME_OVERHEAD
218         PPC440EP_ERR42
219         blrl                    /* Call handler */
220         .globl  ret_from_syscall
221 ret_from_syscall:
222 #ifdef SHOW_SYSCALLS
223         bl      do_show_syscall_exit
224 #endif
225         mr      r6,r3
226         rlwinm  r12,r1,0,0,(31-THREAD_SHIFT)    /* current_thread_info() */
227         /* disable interrupts so current_thread_info()->flags can't change */
228         LOAD_MSR_KERNEL(r10,MSR_KERNEL) /* doesn't include MSR_EE */
229         SYNC
230         MTMSRD(r10)
231         lwz     r9,TI_FLAGS(r12)
232         li      r8,-_LAST_ERRNO
233         andi.   r0,r9,(_TIF_SYSCALL_T_OR_A|_TIF_SINGLESTEP|_TIF_USER_WORK_MASK|_TIF_PERSYSCALL_MASK)
234         bne-    syscall_exit_work
235         cmplw   0,r3,r8
236         blt+    syscall_exit_cont
237         lwz     r11,_CCR(r1)                    /* Load CR */
238         neg     r3,r3
239         oris    r11,r11,0x1000  /* Set SO bit in CR */
240         stw     r11,_CCR(r1)
241 syscall_exit_cont:
242 #if defined(CONFIG_4xx) || defined(CONFIG_BOOKE)
243         /* If the process has its own DBCR0 value, load it up.  The internal
244            debug mode bit tells us that dbcr0 should be loaded. */
245         lwz     r0,THREAD+THREAD_DBCR0(r2)
246         andis.  r10,r0,DBCR0_IDM@h
247         bnel-   load_dbcr0
248 #endif
249 #ifdef CONFIG_44x
250         lis     r4,icache_44x_need_flush@ha
251         lwz     r5,icache_44x_need_flush@l(r4)
252         cmplwi  cr0,r5,0
253         bne-    2f
254 1:
255 #endif /* CONFIG_44x */
256 BEGIN_FTR_SECTION
257         lwarx   r7,0,r1
258 END_FTR_SECTION_IFSET(CPU_FTR_NEED_PAIRED_STWCX)
259         stwcx.  r0,0,r1                 /* to clear the reservation */
260         lwz     r4,_LINK(r1)
261         lwz     r5,_CCR(r1)
262         mtlr    r4
263         mtcr    r5
264         lwz     r7,_NIP(r1)
265         lwz     r8,_MSR(r1)
266         FIX_SRR1(r8, r0)
267         lwz     r2,GPR2(r1)
268         lwz     r1,GPR1(r1)
269         mtspr   SPRN_SRR0,r7
270         mtspr   SPRN_SRR1,r8
271         SYNC
272         RFI
273 #ifdef CONFIG_44x
274 2:      li      r7,0
275         iccci   r0,r0
276         stw     r7,icache_44x_need_flush@l(r4)
277         b       1b
278 #endif  /* CONFIG_44x */
279
280 66:     li      r3,-ENOSYS
281         b       ret_from_syscall
282
283         .globl  ret_from_fork
284 ret_from_fork:
285         REST_NVGPRS(r1)
286         bl      schedule_tail
287         li      r3,0
288         b       ret_from_syscall
289
290 /* Traced system call support */
291 syscall_dotrace:
292         SAVE_NVGPRS(r1)
293         li      r0,0xc00
294         stw     r0,_TRAP(r1)
295         addi    r3,r1,STACK_FRAME_OVERHEAD
296         bl      do_syscall_trace_enter
297         lwz     r0,GPR0(r1)     /* Restore original registers */
298         lwz     r3,GPR3(r1)
299         lwz     r4,GPR4(r1)
300         lwz     r5,GPR5(r1)
301         lwz     r6,GPR6(r1)
302         lwz     r7,GPR7(r1)
303         lwz     r8,GPR8(r1)
304         REST_NVGPRS(r1)
305         b       syscall_dotrace_cont
306
307 syscall_exit_work:
308         andi.   r0,r9,_TIF_RESTOREALL
309         beq+    0f
310         REST_NVGPRS(r1)
311         b       2f
312 0:      cmplw   0,r3,r8
313         blt+    1f
314         andi.   r0,r9,_TIF_NOERROR
315         bne-    1f
316         lwz     r11,_CCR(r1)                    /* Load CR */
317         neg     r3,r3
318         oris    r11,r11,0x1000  /* Set SO bit in CR */
319         stw     r11,_CCR(r1)
320
321 1:      stw     r6,RESULT(r1)   /* Save result */
322         stw     r3,GPR3(r1)     /* Update return value */
323 2:      andi.   r0,r9,(_TIF_PERSYSCALL_MASK)
324         beq     4f
325
326         /* Clear per-syscall TIF flags if any are set.  */
327
328         li      r11,_TIF_PERSYSCALL_MASK
329         addi    r12,r12,TI_FLAGS
330 3:      lwarx   r8,0,r12
331         andc    r8,r8,r11
332 #ifdef CONFIG_IBM405_ERR77
333         dcbt    0,r12
334 #endif
335         stwcx.  r8,0,r12
336         bne-    3b
337         subi    r12,r12,TI_FLAGS
338         
339 4:      /* Anything which requires enabling interrupts? */
340         andi.   r0,r9,(_TIF_SYSCALL_T_OR_A|_TIF_SINGLESTEP)
341         beq     ret_from_except
342
343         /* Re-enable interrupts */
344         ori     r10,r10,MSR_EE
345         SYNC
346         MTMSRD(r10)
347
348         /* Save NVGPRS if they're not saved already */
349         lwz     r4,_TRAP(r1)
350         andi.   r4,r4,1
351         beq     5f
352         SAVE_NVGPRS(r1)
353         li      r4,0xc00
354         stw     r4,_TRAP(r1)
355 5:
356         addi    r3,r1,STACK_FRAME_OVERHEAD
357         bl      do_syscall_trace_leave
358         b       ret_from_except_full
359
360 #ifdef SHOW_SYSCALLS
361 do_show_syscall:
362 #ifdef SHOW_SYSCALLS_TASK
363         lis     r11,show_syscalls_task@ha
364         lwz     r11,show_syscalls_task@l(r11)
365         cmp     0,r2,r11
366         bnelr
367 #endif
368         stw     r31,GPR31(r1)
369         mflr    r31
370         lis     r3,7f@ha
371         addi    r3,r3,7f@l
372         lwz     r4,GPR0(r1)
373         lwz     r5,GPR3(r1)
374         lwz     r6,GPR4(r1)
375         lwz     r7,GPR5(r1)
376         lwz     r8,GPR6(r1)
377         lwz     r9,GPR7(r1)
378         bl      printk
379         lis     r3,77f@ha
380         addi    r3,r3,77f@l
381         lwz     r4,GPR8(r1)
382         mr      r5,r2
383         bl      printk
384         lwz     r0,GPR0(r1)
385         lwz     r3,GPR3(r1)
386         lwz     r4,GPR4(r1)
387         lwz     r5,GPR5(r1)
388         lwz     r6,GPR6(r1)
389         lwz     r7,GPR7(r1)
390         lwz     r8,GPR8(r1)
391         mtlr    r31
392         lwz     r31,GPR31(r1)
393         blr
394
395 do_show_syscall_exit:
396 #ifdef SHOW_SYSCALLS_TASK
397         lis     r11,show_syscalls_task@ha
398         lwz     r11,show_syscalls_task@l(r11)
399         cmp     0,r2,r11
400         bnelr
401 #endif
402         stw     r31,GPR31(r1)
403         mflr    r31
404         stw     r3,RESULT(r1)   /* Save result */
405         mr      r4,r3
406         lis     r3,79f@ha
407         addi    r3,r3,79f@l
408         bl      printk
409         lwz     r3,RESULT(r1)
410         mtlr    r31
411         lwz     r31,GPR31(r1)
412         blr
413
414 7:      .string "syscall %d(%x, %x, %x, %x, %x, "
415 77:     .string "%x), current=%p\n"
416 79:     .string " -> %x\n"
417         .align  2,0
418
419 #ifdef SHOW_SYSCALLS_TASK
420         .data
421         .globl  show_syscalls_task
422 show_syscalls_task:
423         .long   -1
424         .text
425 #endif
426 #endif /* SHOW_SYSCALLS */
427
428 /*
429  * The fork/clone functions need to copy the full register set into
430  * the child process. Therefore we need to save all the nonvolatile
431  * registers (r13 - r31) before calling the C code.
432  */
433         .globl  ppc_fork
434 ppc_fork:
435         SAVE_NVGPRS(r1)
436         lwz     r0,_TRAP(r1)
437         rlwinm  r0,r0,0,0,30            /* clear LSB to indicate full */
438         stw     r0,_TRAP(r1)            /* register set saved */
439         b       sys_fork
440
441         .globl  ppc_vfork
442 ppc_vfork:
443         SAVE_NVGPRS(r1)
444         lwz     r0,_TRAP(r1)
445         rlwinm  r0,r0,0,0,30            /* clear LSB to indicate full */
446         stw     r0,_TRAP(r1)            /* register set saved */
447         b       sys_vfork
448
449         .globl  ppc_clone
450 ppc_clone:
451         SAVE_NVGPRS(r1)
452         lwz     r0,_TRAP(r1)
453         rlwinm  r0,r0,0,0,30            /* clear LSB to indicate full */
454         stw     r0,_TRAP(r1)            /* register set saved */
455         b       sys_clone
456
457         .globl  ppc_swapcontext
458 ppc_swapcontext:
459         SAVE_NVGPRS(r1)
460         lwz     r0,_TRAP(r1)
461         rlwinm  r0,r0,0,0,30            /* clear LSB to indicate full */
462         stw     r0,_TRAP(r1)            /* register set saved */
463         b       sys_swapcontext
464
465 /*
466  * Top-level page fault handling.
467  * This is in assembler because if do_page_fault tells us that
468  * it is a bad kernel page fault, we want to save the non-volatile
469  * registers before calling bad_page_fault.
470  */
471         .globl  handle_page_fault
472 handle_page_fault:
473         stw     r4,_DAR(r1)
474         addi    r3,r1,STACK_FRAME_OVERHEAD
475         bl      do_page_fault
476         cmpwi   r3,0
477         beq+    ret_from_except
478         SAVE_NVGPRS(r1)
479         lwz     r0,_TRAP(r1)
480         clrrwi  r0,r0,1
481         stw     r0,_TRAP(r1)
482         mr      r5,r3
483         addi    r3,r1,STACK_FRAME_OVERHEAD
484         lwz     r4,_DAR(r1)
485         bl      bad_page_fault
486         b       ret_from_except_full
487
488 /*
489  * This routine switches between two different tasks.  The process
490  * state of one is saved on its kernel stack.  Then the state
491  * of the other is restored from its kernel stack.  The memory
492  * management hardware is updated to the second process's state.
493  * Finally, we can return to the second process.
494  * On entry, r3 points to the THREAD for the current task, r4
495  * points to the THREAD for the new task.
496  *
497  * This routine is always called with interrupts disabled.
498  *
499  * Note: there are two ways to get to the "going out" portion
500  * of this code; either by coming in via the entry (_switch)
501  * or via "fork" which must set up an environment equivalent
502  * to the "_switch" path.  If you change this , you'll have to
503  * change the fork code also.
504  *
505  * The code which creates the new task context is in 'copy_thread'
506  * in arch/ppc/kernel/process.c
507  */
508 _GLOBAL(_switch)
509         stwu    r1,-INT_FRAME_SIZE(r1)
510         mflr    r0
511         stw     r0,INT_FRAME_SIZE+4(r1)
512         /* r3-r12 are caller saved -- Cort */
513         SAVE_NVGPRS(r1)
514         stw     r0,_NIP(r1)     /* Return to switch caller */
515         mfmsr   r11
516         li      r0,MSR_FP       /* Disable floating-point */
517 #ifdef CONFIG_ALTIVEC
518 BEGIN_FTR_SECTION
519         oris    r0,r0,MSR_VEC@h /* Disable altivec */
520         mfspr   r12,SPRN_VRSAVE /* save vrsave register value */
521         stw     r12,THREAD+THREAD_VRSAVE(r2)
522 END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
523 #endif /* CONFIG_ALTIVEC */
524 #ifdef CONFIG_SPE
525 BEGIN_FTR_SECTION
526         oris    r0,r0,MSR_SPE@h  /* Disable SPE */
527         mfspr   r12,SPRN_SPEFSCR /* save spefscr register value */
528         stw     r12,THREAD+THREAD_SPEFSCR(r2)
529 END_FTR_SECTION_IFSET(CPU_FTR_SPE)
530 #endif /* CONFIG_SPE */
531         and.    r0,r0,r11       /* FP or altivec or SPE enabled? */
532         beq+    1f
533         andc    r11,r11,r0
534         MTMSRD(r11)
535         isync
536 1:      stw     r11,_MSR(r1)
537         mfcr    r10
538         stw     r10,_CCR(r1)
539         stw     r1,KSP(r3)      /* Set old stack pointer */
540
541 #ifdef CONFIG_SMP
542         /* We need a sync somewhere here to make sure that if the
543          * previous task gets rescheduled on another CPU, it sees all
544          * stores it has performed on this one.
545          */
546         sync
547 #endif /* CONFIG_SMP */
548
549         tophys(r0,r4)
550         CLR_TOP32(r0)
551         mtspr   SPRN_SPRG3,r0   /* Update current THREAD phys addr */
552         lwz     r1,KSP(r4)      /* Load new stack pointer */
553
554         /* save the old current 'last' for return value */
555         mr      r3,r2
556         addi    r2,r4,-THREAD   /* Update current */
557
558 #ifdef CONFIG_ALTIVEC
559 BEGIN_FTR_SECTION
560         lwz     r0,THREAD+THREAD_VRSAVE(r2)
561         mtspr   SPRN_VRSAVE,r0          /* if G4, restore VRSAVE reg */
562 END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
563 #endif /* CONFIG_ALTIVEC */
564 #ifdef CONFIG_SPE
565 BEGIN_FTR_SECTION
566         lwz     r0,THREAD+THREAD_SPEFSCR(r2)
567         mtspr   SPRN_SPEFSCR,r0         /* restore SPEFSCR reg */
568 END_FTR_SECTION_IFSET(CPU_FTR_SPE)
569 #endif /* CONFIG_SPE */
570
571         lwz     r0,_CCR(r1)
572         mtcrf   0xFF,r0
573         /* r3-r12 are destroyed -- Cort */
574         REST_NVGPRS(r1)
575
576         lwz     r4,_NIP(r1)     /* Return to _switch caller in new task */
577         mtlr    r4
578         addi    r1,r1,INT_FRAME_SIZE
579         blr
580
581         .globl  fast_exception_return
582 fast_exception_return:
583 #if !(defined(CONFIG_4xx) || defined(CONFIG_BOOKE))
584         andi.   r10,r9,MSR_RI           /* check for recoverable interrupt */
585         beq     1f                      /* if not, we've got problems */
586 #endif
587
588 2:      REST_4GPRS(3, r11)
589         lwz     r10,_CCR(r11)
590         REST_GPR(1, r11)
591         mtcr    r10
592         lwz     r10,_LINK(r11)
593         mtlr    r10
594         REST_GPR(10, r11)
595         mtspr   SPRN_SRR1,r9
596         mtspr   SPRN_SRR0,r12
597         REST_GPR(9, r11)
598         REST_GPR(12, r11)
599         lwz     r11,GPR11(r11)
600         SYNC
601         RFI
602
603 #if !(defined(CONFIG_4xx) || defined(CONFIG_BOOKE))
604 /* check if the exception happened in a restartable section */
605 1:      lis     r3,exc_exit_restart_end@ha
606         addi    r3,r3,exc_exit_restart_end@l
607         cmplw   r12,r3
608         bge     3f
609         lis     r4,exc_exit_restart@ha
610         addi    r4,r4,exc_exit_restart@l
611         cmplw   r12,r4
612         blt     3f
613         lis     r3,fee_restarts@ha
614         tophys(r3,r3)
615         lwz     r5,fee_restarts@l(r3)
616         addi    r5,r5,1
617         stw     r5,fee_restarts@l(r3)
618         mr      r12,r4          /* restart at exc_exit_restart */
619         b       2b
620
621         .section .bss
622         .align  2
623 fee_restarts:
624         .space  4
625         .previous
626
627 /* aargh, a nonrecoverable interrupt, panic */
628 /* aargh, we don't know which trap this is */
629 /* but the 601 doesn't implement the RI bit, so assume it's OK */
630 3:
631 BEGIN_FTR_SECTION
632         b       2b
633 END_FTR_SECTION_IFSET(CPU_FTR_601)
634         li      r10,-1
635         stw     r10,_TRAP(r11)
636         addi    r3,r1,STACK_FRAME_OVERHEAD
637         lis     r10,MSR_KERNEL@h
638         ori     r10,r10,MSR_KERNEL@l
639         bl      transfer_to_handler_full
640         .long   nonrecoverable_exception
641         .long   ret_from_except
642 #endif
643
644         .globl  ret_from_except_full
645 ret_from_except_full:
646         REST_NVGPRS(r1)
647         /* fall through */
648
649         .globl  ret_from_except
650 ret_from_except:
651         /* Hard-disable interrupts so that current_thread_info()->flags
652          * can't change between when we test it and when we return
653          * from the interrupt. */
654         LOAD_MSR_KERNEL(r10,MSR_KERNEL)
655         SYNC                    /* Some chip revs have problems here... */
656         MTMSRD(r10)             /* disable interrupts */
657
658         lwz     r3,_MSR(r1)     /* Returning to user mode? */
659         andi.   r0,r3,MSR_PR
660         beq     resume_kernel
661
662 user_exc_return:                /* r10 contains MSR_KERNEL here */
663         /* Check current_thread_info()->flags */
664         rlwinm  r9,r1,0,0,(31-THREAD_SHIFT)
665         lwz     r9,TI_FLAGS(r9)
666         andi.   r0,r9,_TIF_USER_WORK_MASK
667         bne     do_work
668
669 restore_user:
670 #if defined(CONFIG_4xx) || defined(CONFIG_BOOKE)
671         /* Check whether this process has its own DBCR0 value.  The internal
672            debug mode bit tells us that dbcr0 should be loaded. */
673         lwz     r0,THREAD+THREAD_DBCR0(r2)
674         andis.  r10,r0,DBCR0_IDM@h
675         bnel-   load_dbcr0
676 #endif
677
678 #ifdef CONFIG_PREEMPT
679         b       restore
680
681 /* N.B. the only way to get here is from the beq following ret_from_except. */
682 resume_kernel:
683         /* check current_thread_info->preempt_count */
684         rlwinm  r9,r1,0,0,(31-THREAD_SHIFT)
685         lwz     r0,TI_PREEMPT(r9)
686         cmpwi   0,r0,0          /* if non-zero, just restore regs and return */
687         bne     restore
688         lwz     r0,TI_FLAGS(r9)
689         andi.   r0,r0,_TIF_NEED_RESCHED
690         beq+    restore
691         andi.   r0,r3,MSR_EE    /* interrupts off? */
692         beq     restore         /* don't schedule if so */
693 1:      bl      preempt_schedule_irq
694         rlwinm  r9,r1,0,0,(31-THREAD_SHIFT)
695         lwz     r3,TI_FLAGS(r9)
696         andi.   r0,r3,_TIF_NEED_RESCHED
697         bne-    1b
698 #else
699 resume_kernel:
700 #endif /* CONFIG_PREEMPT */
701
702         /* interrupts are hard-disabled at this point */
703 restore:
704 #ifdef CONFIG_44x
705         lis     r4,icache_44x_need_flush@ha
706         lwz     r5,icache_44x_need_flush@l(r4)
707         cmplwi  cr0,r5,0
708         beq+    1f
709         li      r6,0
710         iccci   r0,r0
711         stw     r6,icache_44x_need_flush@l(r4)
712 1:
713 #endif  /* CONFIG_44x */
714         lwz     r0,GPR0(r1)
715         lwz     r2,GPR2(r1)
716         REST_4GPRS(3, r1)
717         REST_2GPRS(7, r1)
718
719         lwz     r10,_XER(r1)
720         lwz     r11,_CTR(r1)
721         mtspr   SPRN_XER,r10
722         mtctr   r11
723
724         PPC405_ERR77(0,r1)
725 BEGIN_FTR_SECTION
726         lwarx   r11,0,r1
727 END_FTR_SECTION_IFSET(CPU_FTR_NEED_PAIRED_STWCX)
728         stwcx.  r0,0,r1                 /* to clear the reservation */
729
730 #if !(defined(CONFIG_4xx) || defined(CONFIG_BOOKE))
731         lwz     r9,_MSR(r1)
732         andi.   r10,r9,MSR_RI           /* check if this exception occurred */
733         beql    nonrecoverable          /* at a bad place (MSR:RI = 0) */
734
735         lwz     r10,_CCR(r1)
736         lwz     r11,_LINK(r1)
737         mtcrf   0xFF,r10
738         mtlr    r11
739
740         /*
741          * Once we put values in SRR0 and SRR1, we are in a state
742          * where exceptions are not recoverable, since taking an
743          * exception will trash SRR0 and SRR1.  Therefore we clear the
744          * MSR:RI bit to indicate this.  If we do take an exception,
745          * we can't return to the point of the exception but we
746          * can restart the exception exit path at the label
747          * exc_exit_restart below.  -- paulus
748          */
749         LOAD_MSR_KERNEL(r10,MSR_KERNEL & ~MSR_RI)
750         SYNC
751         MTMSRD(r10)             /* clear the RI bit */
752         .globl exc_exit_restart
753 exc_exit_restart:
754         lwz     r9,_MSR(r1)
755         lwz     r12,_NIP(r1)
756         FIX_SRR1(r9,r10)
757         mtspr   SPRN_SRR0,r12
758         mtspr   SPRN_SRR1,r9
759         REST_4GPRS(9, r1)
760         lwz     r1,GPR1(r1)
761         .globl exc_exit_restart_end
762 exc_exit_restart_end:
763         SYNC
764         RFI
765
766 #else /* !(CONFIG_4xx || CONFIG_BOOKE) */
767         /*
768          * This is a bit different on 4xx/Book-E because it doesn't have
769          * the RI bit in the MSR.
770          * The TLB miss handler checks if we have interrupted
771          * the exception exit path and restarts it if so
772          * (well maybe one day it will... :).
773          */
774         lwz     r11,_LINK(r1)
775         mtlr    r11
776         lwz     r10,_CCR(r1)
777         mtcrf   0xff,r10
778         REST_2GPRS(9, r1)
779         .globl exc_exit_restart
780 exc_exit_restart:
781         lwz     r11,_NIP(r1)
782         lwz     r12,_MSR(r1)
783 exc_exit_start:
784         mtspr   SPRN_SRR0,r11
785         mtspr   SPRN_SRR1,r12
786         REST_2GPRS(11, r1)
787         lwz     r1,GPR1(r1)
788         .globl exc_exit_restart_end
789 exc_exit_restart_end:
790         PPC405_ERR77_SYNC
791         rfi
792         b       .                       /* prevent prefetch past rfi */
793
794 /*
795  * Returning from a critical interrupt in user mode doesn't need
796  * to be any different from a normal exception.  For a critical
797  * interrupt in the kernel, we just return (without checking for
798  * preemption) since the interrupt may have happened at some crucial
799  * place (e.g. inside the TLB miss handler), and because we will be
800  * running with r1 pointing into critical_stack, not the current
801  * process's kernel stack (and therefore current_thread_info() will
802  * give the wrong answer).
803  * We have to restore various SPRs that may have been in use at the
804  * time of the critical interrupt.
805  *
806  */
807 #ifdef CONFIG_40x
808 #define PPC_40x_TURN_OFF_MSR_DR                                             \
809         /* avoid any possible TLB misses here by turning off MSR.DR, we     \
810          * assume the instructions here are mapped by a pinned TLB entry */ \
811         li      r10,MSR_IR;                                                 \
812         mtmsr   r10;                                                        \
813         isync;                                                              \
814         tophys(r1, r1);
815 #else
816 #define PPC_40x_TURN_OFF_MSR_DR
817 #endif
818
819 #define RET_FROM_EXC_LEVEL(exc_lvl_srr0, exc_lvl_srr1, exc_lvl_rfi)     \
820         REST_NVGPRS(r1);                                                \
821         lwz     r3,_MSR(r1);                                            \
822         andi.   r3,r3,MSR_PR;                                           \
823         LOAD_MSR_KERNEL(r10,MSR_KERNEL);                                \
824         bne     user_exc_return;                                        \
825         lwz     r0,GPR0(r1);                                            \
826         lwz     r2,GPR2(r1);                                            \
827         REST_4GPRS(3, r1);                                              \
828         REST_2GPRS(7, r1);                                              \
829         lwz     r10,_XER(r1);                                           \
830         lwz     r11,_CTR(r1);                                           \
831         mtspr   SPRN_XER,r10;                                           \
832         mtctr   r11;                                                    \
833         PPC405_ERR77(0,r1);                                             \
834         stwcx.  r0,0,r1;                /* to clear the reservation */  \
835         lwz     r11,_LINK(r1);                                          \
836         mtlr    r11;                                                    \
837         lwz     r10,_CCR(r1);                                           \
838         mtcrf   0xff,r10;                                               \
839         PPC_40x_TURN_OFF_MSR_DR;                                        \
840         lwz     r9,_DEAR(r1);                                           \
841         lwz     r10,_ESR(r1);                                           \
842         mtspr   SPRN_DEAR,r9;                                           \
843         mtspr   SPRN_ESR,r10;                                           \
844         lwz     r11,_NIP(r1);                                           \
845         lwz     r12,_MSR(r1);                                           \
846         mtspr   exc_lvl_srr0,r11;                                       \
847         mtspr   exc_lvl_srr1,r12;                                       \
848         lwz     r9,GPR9(r1);                                            \
849         lwz     r12,GPR12(r1);                                          \
850         lwz     r10,GPR10(r1);                                          \
851         lwz     r11,GPR11(r1);                                          \
852         lwz     r1,GPR1(r1);                                            \
853         PPC405_ERR77_SYNC;                                              \
854         exc_lvl_rfi;                                                    \
855         b       .;              /* prevent prefetch past exc_lvl_rfi */
856
857         .globl  ret_from_crit_exc
858 ret_from_crit_exc:
859         RET_FROM_EXC_LEVEL(SPRN_CSRR0, SPRN_CSRR1, RFCI)
860
861 #ifdef CONFIG_BOOKE
862         .globl  ret_from_debug_exc
863 ret_from_debug_exc:
864         RET_FROM_EXC_LEVEL(SPRN_DSRR0, SPRN_DSRR1, RFDI)
865
866         .globl  ret_from_mcheck_exc
867 ret_from_mcheck_exc:
868         RET_FROM_EXC_LEVEL(SPRN_MCSRR0, SPRN_MCSRR1, RFMCI)
869 #endif /* CONFIG_BOOKE */
870
871 /*
872  * Load the DBCR0 value for a task that is being ptraced,
873  * having first saved away the global DBCR0.  Note that r0
874  * has the dbcr0 value to set upon entry to this.
875  */
876 load_dbcr0:
877         mfmsr   r10             /* first disable debug exceptions */
878         rlwinm  r10,r10,0,~MSR_DE
879         mtmsr   r10
880         isync
881         mfspr   r10,SPRN_DBCR0
882         lis     r11,global_dbcr0@ha
883         addi    r11,r11,global_dbcr0@l
884 #ifdef CONFIG_SMP
885         rlwinm  r9,r1,0,0,(31-THREAD_SHIFT)
886         lwz     r9,TI_CPU(r9)
887         slwi    r9,r9,3
888         add     r11,r11,r9
889 #endif
890         stw     r10,0(r11)
891         mtspr   SPRN_DBCR0,r0
892         lwz     r10,4(r11)
893         addi    r10,r10,1
894         stw     r10,4(r11)
895         li      r11,-1
896         mtspr   SPRN_DBSR,r11   /* clear all pending debug events */
897         blr
898
899         .section .bss
900         .align  4
901 global_dbcr0:
902         .space  8*NR_CPUS
903         .previous
904 #endif /* !(CONFIG_4xx || CONFIG_BOOKE) */
905
906 do_work:                        /* r10 contains MSR_KERNEL here */
907         andi.   r0,r9,_TIF_NEED_RESCHED
908         beq     do_user_signal
909
910 do_resched:                     /* r10 contains MSR_KERNEL here */
911         ori     r10,r10,MSR_EE
912         SYNC
913         MTMSRD(r10)             /* hard-enable interrupts */
914         bl      schedule
915 recheck:
916         LOAD_MSR_KERNEL(r10,MSR_KERNEL)
917         SYNC
918         MTMSRD(r10)             /* disable interrupts */
919         rlwinm  r9,r1,0,0,(31-THREAD_SHIFT)
920         lwz     r9,TI_FLAGS(r9)
921         andi.   r0,r9,_TIF_NEED_RESCHED
922         bne-    do_resched
923         andi.   r0,r9,_TIF_USER_WORK_MASK
924         beq     restore_user
925 do_user_signal:                 /* r10 contains MSR_KERNEL here */
926         ori     r10,r10,MSR_EE
927         SYNC
928         MTMSRD(r10)             /* hard-enable interrupts */
929         /* save r13-r31 in the exception frame, if not already done */
930         lwz     r3,_TRAP(r1)
931         andi.   r0,r3,1
932         beq     2f
933         SAVE_NVGPRS(r1)
934         rlwinm  r3,r3,0,0,30
935         stw     r3,_TRAP(r1)
936 2:      li      r3,0
937         addi    r4,r1,STACK_FRAME_OVERHEAD
938         bl      do_signal
939         REST_NVGPRS(r1)
940         b       recheck
941
942 /*
943  * We come here when we are at the end of handling an exception
944  * that occurred at a place where taking an exception will lose
945  * state information, such as the contents of SRR0 and SRR1.
946  */
947 nonrecoverable:
948         lis     r10,exc_exit_restart_end@ha
949         addi    r10,r10,exc_exit_restart_end@l
950         cmplw   r12,r10
951         bge     3f
952         lis     r11,exc_exit_restart@ha
953         addi    r11,r11,exc_exit_restart@l
954         cmplw   r12,r11
955         blt     3f
956         lis     r10,ee_restarts@ha
957         lwz     r12,ee_restarts@l(r10)
958         addi    r12,r12,1
959         stw     r12,ee_restarts@l(r10)
960         mr      r12,r11         /* restart at exc_exit_restart */
961         blr
962 3:      /* OK, we can't recover, kill this process */
963         /* but the 601 doesn't implement the RI bit, so assume it's OK */
964 BEGIN_FTR_SECTION
965         blr
966 END_FTR_SECTION_IFSET(CPU_FTR_601)
967         lwz     r3,_TRAP(r1)
968         andi.   r0,r3,1
969         beq     4f
970         SAVE_NVGPRS(r1)
971         rlwinm  r3,r3,0,0,30
972         stw     r3,_TRAP(r1)
973 4:      addi    r3,r1,STACK_FRAME_OVERHEAD
974         bl      nonrecoverable_exception
975         /* shouldn't return */
976         b       4b
977
978         .section .bss
979         .align  2
980 ee_restarts:
981         .space  4
982         .previous
983
984 /*
985  * PROM code for specific machines follows.  Put it
986  * here so it's easy to add arch-specific sections later.
987  * -- Cort
988  */
989 #ifdef CONFIG_PPC_RTAS
990 /*
991  * On CHRP, the Run-Time Abstraction Services (RTAS) have to be
992  * called with the MMU off.
993  */
994 _GLOBAL(enter_rtas)
995         stwu    r1,-INT_FRAME_SIZE(r1)
996         mflr    r0
997         stw     r0,INT_FRAME_SIZE+4(r1)
998         LOAD_REG_ADDR(r4, rtas)
999         lis     r6,1f@ha        /* physical return address for rtas */
1000         addi    r6,r6,1f@l
1001         tophys(r6,r6)
1002         tophys(r7,r1)
1003         lwz     r8,RTASENTRY(r4)
1004         lwz     r4,RTASBASE(r4)
1005         mfmsr   r9
1006         stw     r9,8(r1)
1007         LOAD_MSR_KERNEL(r0,MSR_KERNEL)
1008         SYNC                    /* disable interrupts so SRR0/1 */
1009         MTMSRD(r0)              /* don't get trashed */
1010         li      r9,MSR_KERNEL & ~(MSR_IR|MSR_DR)
1011         mtlr    r6
1012         mtspr   SPRN_SPRG2,r7
1013         mtspr   SPRN_SRR0,r8
1014         mtspr   SPRN_SRR1,r9
1015         RFI
1016 1:      tophys(r9,r1)
1017         lwz     r8,INT_FRAME_SIZE+4(r9) /* get return address */
1018         lwz     r9,8(r9)        /* original msr value */
1019         FIX_SRR1(r9,r0)
1020         addi    r1,r1,INT_FRAME_SIZE
1021         li      r0,0
1022         mtspr   SPRN_SPRG2,r0
1023         mtspr   SPRN_SRR0,r8
1024         mtspr   SPRN_SRR1,r9
1025         RFI                     /* return to caller */
1026
1027         .globl  machine_check_in_rtas
1028 machine_check_in_rtas:
1029         twi     31,0,0
1030         /* XXX load up BATs and panic */
1031
1032 #endif /* CONFIG_PPC_RTAS */