make oldconfig will rebuild these...
[linux-2.4.21-pre4.git] / arch / ppc / kernel / entry.S
1 /*
2  * BK Id: SCCS/s.entry.S 1.46 09/02/02 12:29:57 paulus
3  */
4 /*
5  *  PowerPC version 
6  *    Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
7  *  Rewritten by Cort Dougan (cort@fsmlabs.com) for PReP
8  *    Copyright (C) 1996 Cort Dougan <cort@fsmlabs.com>
9  *  Adapted for Power Macintosh by Paul Mackerras.
10  *  Low-level exception handlers and MMU support
11  *  rewritten by Paul Mackerras.
12  *    Copyright (C) 1996 Paul Mackerras.
13  *  MPC8xx modifications Copyright (C) 1997 Dan Malek (dmalek@jlc.net).
14  *  Adaptations for iSeries Lpar by Mike Corrigan & Dave Boutcher
15  *
16  *  This file contains the system call entry code, context switch
17  *  code, and exception/interrupt return code for PowerPC.
18  *
19  *  This program is free software; you can redistribute it and/or
20  *  modify it under the terms of the GNU General Public License
21  *  as published by the Free Software Foundation; either version
22  *  2 of the License, or (at your option) any later version.
23  *      
24  */
25
26 #include <linux/config.h>
27 #include <linux/errno.h>
28 #include <linux/sys.h>
29 #include <linux/threads.h>
30 #include <asm/processor.h>
31 #include <asm/page.h>
32 #include <asm/mmu.h>
33 #include <asm/cputable.h>
34 #include <asm/ppc_asm.h>
35 #include "ppc_defs.h"
36 #ifdef  CONFIG_PPC_ISERIES
37 #include "iSeries_asm.h"
38 #endif /* CONFIG_PPC_ISERIES */
39
40 #undef SHOW_SYSCALLS
41 #undef SHOW_SYSCALLS_TASK
42
43 #ifdef SHOW_SYSCALLS_TASK
44         .data
45 show_syscalls_task:
46         .long   -1
47 #endif
48
49 /*
50  * Handle a system call.
51  */
52         .text
53         .stabs  "arch/ppc/kernel/",N_SO,0,0,0f
54         .stabs  "entry.S",N_SO,0,0,0f
55 0:
56
57 _GLOBAL(DoSyscall)
58         stw     r0,THREAD+LAST_SYSCALL(r2)
59         lwz     r11,_CCR(r1)    /* Clear SO bit in CR */
60         lis     r10,0x1000
61         andc    r11,r11,r10
62         stw     r11,_CCR(r1)
63 #ifdef SHOW_SYSCALLS
64 #ifdef SHOW_SYSCALLS_TASK
65         lis     r31,show_syscalls_task@ha
66         lwz     r31,show_syscalls_task@l(r31)
67         cmp     0,r2,r31
68         bne     1f
69 #endif
70         lis     r3,7f@ha
71         addi    r3,r3,7f@l
72         lwz     r4,GPR0(r1)
73         lwz     r5,GPR3(r1)
74         lwz     r6,GPR4(r1)
75         lwz     r7,GPR5(r1)
76         lwz     r8,GPR6(r1)
77         lwz     r9,GPR7(r1)
78         bl      printk
79         lis     r3,77f@ha
80         addi    r3,r3,77f@l
81         lwz     r4,GPR8(r1)
82         lwz     r5,GPR9(r1)
83         mr      r6,r2
84         bl      printk
85         lwz     r0,GPR0(r1)
86         lwz     r3,GPR3(r1)
87         lwz     r4,GPR4(r1)
88         lwz     r5,GPR5(r1)
89         lwz     r6,GPR6(r1)
90         lwz     r7,GPR7(r1)
91         lwz     r8,GPR8(r1)
92 1:
93 #endif /* SHOW_SYSCALLS */
94         cmpi    0,r0,0x7777     /* Special case for 'sys_sigreturn' */
95         beq-    10f
96         cmpi    0,r0,0x6666     /* Special case for 'sys_rt_sigreturn' */
97         beq-    16f
98         lwz     r10,TASK_PTRACE(r2)
99         andi.   r10,r10,PT_TRACESYS
100         bne-    50f
101         cmpli   0,r0,NR_syscalls
102         bge-    66f
103         lis     r10,sys_call_table@h
104         ori     r10,r10,sys_call_table@l
105         slwi    r0,r0,2
106         lwzx    r10,r10,r0      /* Fetch system call handler [ptr] */
107         cmpi    0,r10,0
108         beq-    66f
109         mtlr    r10
110         addi    r9,r1,STACK_FRAME_OVERHEAD
111         blrl                    /* Call handler */
112         .globl  ret_from_syscall_1
113 ret_from_syscall_1:
114 20:     stw     r3,RESULT(r1)   /* Save result */
115 #ifdef SHOW_SYSCALLS
116 #ifdef SHOW_SYSCALLS_TASK
117         cmp     0,r2,r31
118         bne     91f
119 #endif
120         mr      r4,r3
121         lis     r3,79f@ha
122         addi    r3,r3,79f@l
123         bl      printk
124         lwz     r3,RESULT(r1)
125 91:
126 #endif
127         li      r10,-_LAST_ERRNO
128         cmpl    0,r3,r10
129         blt     30f
130         neg     r3,r3
131         cmpi    0,r3,ERESTARTNOHAND
132         bne     22f
133         li      r3,EINTR
134 22:     lwz     r10,_CCR(r1)    /* Set SO bit in CR */
135         oris    r10,r10,0x1000
136         stw     r10,_CCR(r1)
137 30:     stw     r3,GPR3(r1)     /* Update return value */
138         b       ret_from_except
139 66:     li      r3,ENOSYS
140         b       22b
141 /* sys_sigreturn */
142 10:     addi    r3,r1,STACK_FRAME_OVERHEAD
143         bl      sys_sigreturn
144         cmpi    0,r3,0          /* Check for restarted system call */
145         bge     ret_from_except
146         b       20b
147 /* sys_rt_sigreturn */
148 16:     addi    r3,r1,STACK_FRAME_OVERHEAD
149         bl      sys_rt_sigreturn
150         cmpi    0,r3,0          /* Check for restarted system call */
151         bge     ret_from_except
152         b       20b
153 /* Traced system call support */
154 50:     bl      syscall_trace
155         lwz     r0,GPR0(r1)     /* Restore original registers */
156         lwz     r3,GPR3(r1)
157         lwz     r4,GPR4(r1)
158         lwz     r5,GPR5(r1)
159         lwz     r6,GPR6(r1)
160         lwz     r7,GPR7(r1)
161         lwz     r8,GPR8(r1)
162         lwz     r9,GPR9(r1)
163         cmpli   0,r0,NR_syscalls
164         bge-    66f
165         lis     r10,sys_call_table@h
166         ori     r10,r10,sys_call_table@l
167         slwi    r0,r0,2
168         lwzx    r10,r10,r0      /* Fetch system call handler [ptr] */
169         cmpi    0,r10,0
170         beq-    66f
171         mtlr    r10
172         addi    r9,r1,STACK_FRAME_OVERHEAD
173         blrl                    /* Call handler */
174         .globl  ret_from_syscall_2
175 ret_from_syscall_2:
176         stw     r3,RESULT(r1)   /* Save result */       
177         stw     r3,GPR0(r1)     /* temporary gross hack to make strace work */
178         li      r10,-_LAST_ERRNO
179         cmpl    0,r3,r10
180         blt     60f
181         neg     r3,r3
182         cmpi    0,r3,ERESTARTNOHAND
183         bne     52f
184         li      r3,EINTR
185 52:     lwz     r10,_CCR(r1)    /* Set SO bit in CR */
186         oris    r10,r10,0x1000
187         stw     r10,_CCR(r1)
188 60:     stw     r3,GPR3(r1)     /* Update return value */
189         bl      syscall_trace
190         b       ret_from_except
191 66:     li      r3,ENOSYS
192         b       52b
193 #ifdef SHOW_SYSCALLS
194 7:      .string "syscall %d(%x, %x, %x, %x, %x, "
195 77:     .string "%x, %x), current=%p\n"
196 79:     .string " -> %x\n"
197         .align  2,0
198 #endif
199
200 /*
201  * This routine switches between two different tasks.  The process
202  * state of one is saved on its kernel stack.  Then the state
203  * of the other is restored from its kernel stack.  The memory
204  * management hardware is updated to the second process's state.
205  * Finally, we can return to the second process.
206  * On entry, r3 points to the THREAD for the current task, r4
207  * points to the THREAD for the new task.
208  *
209  * This routine is always called with interrupts disabled
210  * (soft disabled for iSeries).
211  *
212  * Note: there are two ways to get to the "going out" portion
213  * of this code; either by coming in via the entry (_switch)
214  * or via "fork" which must set up an environment equivalent
215  * to the "_switch" path.  If you change this , you'll have to
216  * change the fork code also.
217  *
218  * The code which creates the new task context is in 'copy_thread'
219  * in arch/ppc/kernel/process.c
220  */     
221 _GLOBAL(_switch)
222         stwu    r1,-INT_FRAME_SIZE(r1)
223         stw     r0,GPR0(r1)
224         lwz     r0,0(r1)
225         stw     r0,GPR1(r1)
226         /* r3-r13 are caller saved -- Cort */
227         SAVE_GPR(2, r1)
228         SAVE_8GPRS(14, r1)
229         SAVE_10GPRS(22, r1)
230         mflr    r20             /* Return to switch caller */
231         stw     r20,INT_FRAME_SIZE+4(r1)
232         mfmsr   r22
233         li      r0,MSR_FP       /* Disable floating-point */
234 #ifdef CONFIG_ALTIVEC
235 BEGIN_FTR_SECTION
236         oris    r0,r0,MSR_VEC@h /* Disable altivec */
237 END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
238 #endif /* CONFIG_ALTIVEC */
239         and.    r0,r0,r22       /* FP or altivec enabled? */
240         beq+    1f
241         andc    r22,r22,r0
242         mtmsr   r22
243         isync
244 1:      stw     r20,_NIP(r1)
245         stw     r22,_MSR(r1)
246         stw     r20,_LINK(r1)
247         mfcr    r20
248         mfctr   r22
249         mfspr   r23,XER
250         stw     r20,_CCR(r1)
251         stw     r22,_CTR(r1)
252         stw     r23,_XER(r1)
253         li      r0,0x0ff0
254         stw     r0,TRAP(r1)
255         stw     r1,KSP(r3)      /* Set old stack pointer */
256
257         tophys(r0,r4)
258         CLR_TOP32(r0)
259         mtspr   SPRG3,r0        /* Update current THREAD phys addr */
260         lwz     r1,KSP(r4)      /* Load new stack pointer */
261         /* save the old current 'last' for return value */
262         mr      r3,r2
263         addi    r2,r4,-THREAD   /* Update current */
264         lwz     r0,_CCR(r1)
265         mtcrf   0xFF,r0
266         /* r3-r13 are destroyed -- Cort */
267         REST_2GPRS(14, r1)
268         REST_8GPRS(16, r1)
269         REST_8GPRS(24, r1)
270
271         lwz     r4,_NIP(r1)     /* Return to _switch caller in new task */
272         mtlr    r4
273         addi    r1,r1,INT_FRAME_SIZE
274         blr
275
276         .globl  ret_from_fork
277 ret_from_fork:
278         bl      schedule_tail
279         lwz     r0,TASK_PTRACE(r2)
280         andi.   r0,r0,PT_TRACESYS
281         bnel-   syscall_trace
282         b       ret_from_except
283
284         .globl  ret_from_intercept
285 ret_from_intercept:
286         /*
287          * We may be returning from RTL and cannot do the normal checks
288          * -- Cort
289          */
290         cmpi    0,r3,0
291         beq     restore
292         .globl  ret_from_except
293 ret_from_except:
294 #ifdef CONFIG_PPC_ISERIES
295         bl      iSeries_check_intr
296 #endif /* CONFIG_PPC_ISERIES */
297         lwz     r3,_MSR(r1)     /* Returning to user mode? */
298         andi.   r3,r3,MSR_PR
299         beq+    do_signal_ret   /* if so, check need_resched and signals */
300         lwz     r3,NEED_RESCHED(r2)
301         cmpi    0,r3,0          /* check need_resched flag */
302         beq+    7f
303         bl      schedule
304 7:      lwz     r5,SIGPENDING(r2) /* Check for pending unblocked signals */
305         cmpwi   0,r5,0
306         beq+    do_signal_ret
307         li      r3,0
308         addi    r4,r1,STACK_FRAME_OVERHEAD
309         bl      do_signal
310         .globl  do_signal_ret
311 do_signal_ret:
312         .globl ret_to_user_hook 
313 ret_to_user_hook:
314         nop
315 #ifdef CONFIG_PPC_ISERIES
316         mfmsr   r0              /* Hard disable */
317         rlwinm  r0,r0,0,17,15
318         mtmsr   r0
319
320         mfspr   r5,SPRG1
321         lbz     r5,PACAPROCENABLED(r5)
322         cmpi    0,r5,0
323         bne     restore         /* skip checks if already soft enabled */
324
325         lwz     r5,_SOFTE(r1)
326         cmpi    0,r5,0
327         beq     restore
328
329 irq_recheck:
330         CHECKANYINT(r4,r5,r6)
331         beq+    restore
332
333         ori     r0,r0,MSR_EE
334         mtmsr   r0              /* Hard enable */
335         b       ret_from_except /* An interrupt came in after we checked above */
336 #endif /* CONFIG_PPC_ISERIES */
337 restore:
338         lwz     r3,_XER(r1)
339         mtspr   XER,r3
340         REST_10GPRS(9,r1)
341         REST_10GPRS(19,r1)
342         REST_2GPRS(29,r1)
343         REST_GPR(31,r1)
344
345         /* make sure we hard disable here, even if rtl is active, to protect
346          * SRR[01] and SPRG2 -- Cort 
347          */
348         mfmsr   r0              /* Get current interrupt state */
349         rlwinm  r0,r0,0,17,15   /* clear MSR_EE in r0 */
350 #ifdef CONFIG_4xx
351         rlwinm  r0,r0,0,23,21   /* clear MSR_DE in r0 */
352 #endif
353         SYNC                    /* Some chip revs have problems here... */
354         mtmsr   r0              /* Update machine state */
355
356         PPC405_ERR77(0,r1)
357         stwcx.  r0,0,r1         /* to clear the reservation */
358
359         /* if returning to user mode, set new sprg2 and save kernel SP */
360         lwz     r0,_MSR(r1)
361         andi.   r0,r0,MSR_PR
362         beq+    1f
363 #ifdef CONFIG_ALTIVEC
364 BEGIN_FTR_SECTION
365         lwz     r0,THREAD+THREAD_VRSAVE(r2)
366         mtspr   SPRN_VRSAVE,r0          /* if G4, restore VRSAVE reg */
367 END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
368 #endif /* CONFIG_ALTIVEC */
369 #if defined(CONFIG_4xx) && !defined(CONFIG_BDI_SWITCH)
370         /* Restore the processor debugging state of the thread.  Only do
371          * this if we aren't using an Abatron BDI JTAG debugger.  It doesn't
372          * tolerate others mucking with the debug registers.
373          */
374         lwz     r0,THREAD+THREAD_DBCR0(r2)
375         mtspr   SPRN_DBCR0,r0
376 #endif
377         addi    r0,r1,INT_FRAME_SIZE    /* size of frame */
378         stw     r0,THREAD+KSP(r2)       /* save kernel stack pointer */
379 #ifndef CONFIG_PPC_ISERIES
380         tophys(r8,r1)
381         CLR_TOP32(r8)
382         mtspr   SPRG2,r8                /* phys exception stack pointer */
383 #else /* CONFIG_PPC_ISERIES */
384         mfspr   r2,SPRG1                /* Get Paca address */
385         stw     r1,PACAKSAVE(r2)        /* save exception stack pointer */
386 #endif /* CONFIG_PPC_ISERIES */
387 1:
388         lwz     r3,_CTR(r1)
389         lwz     r0,_LINK(r1)
390         mtctr   r3
391         mtlr    r0
392 #ifdef CONFIG_PPC_ISERIES
393         mfspr   r2,SPRG1                /* Get Paca address */
394         lwz     r0,_SOFTE(r1)
395         stb     r0,PACAPROCENABLED(r2)  /* Restore soft enabled/disabled */
396 #endif /* CONFIG_PPC_ISERIES */
397         REST_4GPRS(3, r1)
398         REST_2GPRS(7, r1)
399
400 #ifndef CONFIG_SMP
401         /* We have to "dummy" load from the context save area in case
402          * these instructions cause an MMU fault.  If this happens
403          * after we load SRR0/SRR1, our return context is hosed.  -- Dan
404          * 
405          * This workaround is not enough, we must also make sure the
406          * actual code for this routine is in the TLB or BAT mapped.
407          * For 6xx/Power3, we know the code is in a BAT, so this should
408          * be enough in UP. In SMP, I limit lowmem to the amount of
409          * RAM that can be BAT mapped. Other CPUs may need additional
410          * tweaks, especially if used SMP or if the code for this routine
411          * crosses page boundaries. The TLB pin down for 4xx should help
412          * for example. --BenH.
413          */
414         lwz     r0,GPR0(r1)
415         lwz     r0,GPR2(r1)
416         lwz     r0,GPR1(r1)
417 #endif /* ndef CONFIG_SMP */
418
419         /* We re-use r3,r4 here (the load above was to cause the MMU
420          * fault if necessary).  Using r3,r4 removes the need to "dummy"
421          * load the CCR and NIP.  Since we load them we may as well
422          * use them.
423          */
424         lwz     r3,_CCR(r1)
425         lwz     r4,_NIP(r1)
426
427         lwz     r0,_MSR(r1)
428         FIX_SRR1(r0,r2)
429         mtspr   SRR1,r0
430         mtcrf   0xFF,r3
431         mtspr   SRR0,r4
432         lwz     r0,GPR0(r1)
433         lwz     r2,GPR2(r1)
434         lwz     r3,GPR3(r1)
435         lwz     r4,GPR4(r1)
436         lwz     r1,GPR1(r1)
437         SYNC
438         PPC405_ERR77_SYNC
439         RFI
440
441
442 /*
443  * PROM code for specific machines follows.  Put it 
444  * here so it's easy to add arch-specific sections later.
445  * -- Cort
446  */
447 #if defined(CONFIG_ALL_PPC)
448 /*
449  * On CHRP, the Run-Time Abstraction Services (RTAS) have to be
450  * called with the MMU off.
451  */
452 _GLOBAL(enter_rtas)
453         mflr    r0
454         stw     r0,20(r1)
455         lis     r4,rtas_data@ha
456         lwz     r4,rtas_data@l(r4)
457         lis     r6,1f@ha        /* physical return address for rtas */
458         addi    r6,r6,1f@l
459         addis   r6,r6,-KERNELBASE@h
460         subi    r7,r1,INT_FRAME_SIZE
461         addis   r7,r7,-KERNELBASE@h
462         lis     r8,rtas_entry@ha
463         lwz     r8,rtas_entry@l(r8)
464         mfmsr   r9
465         stw     r9,8(r1)
466         li      r0,0
467         ori     r0,r0,MSR_EE|MSR_SE|MSR_BE|MSR_FE0|MSR_FE1
468         andc    r0,r9,r0
469         li      r10,MSR_IR|MSR_DR|MSR_FP
470         andc    r9,r0,r10
471         SYNC                    /* disable interrupts so SRR0/1 */
472         mtmsr   r0              /* don't get trashed */
473         mtlr    r6
474         CLR_TOP32(r7)
475         mtspr   SPRG2,r7
476         mtspr   SRR0,r8
477         mtspr   SRR1,r9
478         RFI
479 1:      addis   r9,r1,-KERNELBASE@h
480         lwz     r8,20(r9)       /* get return address */
481         lwz     r9,8(r9)        /* original msr value */
482         FIX_SRR1(r9,r0)
483         li      r0,0
484         mtspr   SPRG2,r0
485         mtspr   SRR0,r8
486         mtspr   SRR1,r9
487         RFI                     /* return to caller */
488 #endif /* CONFIG_ALL_PPC */