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