patch-2_6_7-vs1_9_1_12
[linux-2.6.git] / arch / ppc / kernel / head_44x.S
1 /*
2  * arch/ppc/kernel/head_44x.S
3  *
4  * Kernel execution entry point code.
5  *
6  *    Copyright (c) 1995-1996 Gary Thomas <gdt@linuxppc.org>
7  *      Initial PowerPC version.
8  *    Copyright (c) 1996 Cort Dougan <cort@cs.nmt.edu>
9  *      Rewritten for PReP
10  *    Copyright (c) 1996 Paul Mackerras <paulus@cs.anu.edu.au>
11  *      Low-level exception handers, MMU support, and rewrite.
12  *    Copyright (c) 1997 Dan Malek <dmalek@jlc.net>
13  *      PowerPC 8xx modifications.
14  *    Copyright (c) 1998-1999 TiVo, Inc.
15  *      PowerPC 403GCX modifications.
16  *    Copyright (c) 1999 Grant Erickson <grant@lcse.umn.edu>
17  *      PowerPC 403GCX/405GP modifications.
18  *    Copyright 2000 MontaVista Software Inc.
19  *      PPC405 modifications
20  *      PowerPC 403GCX/405GP modifications.
21  *      Author: MontaVista Software, Inc.
22  *              frank_rowand@mvista.com or source@mvista.com
23  *              debbie_chu@mvista.com
24  *    Copyright 2002-2004 MontaVista Software, Inc.
25  *      PowerPC 44x support, Matt Porter <mporter@kernel.crashing.org>
26  *
27  * This program is free software; you can redistribute  it and/or modify it
28  * under  the terms of  the GNU General  Public License as published by the
29  * Free Software Foundation;  either version 2 of the  License, or (at your
30  * option) any later version.
31  */
32
33 #include <linux/config.h>
34 #include <asm/processor.h>
35 #include <asm/page.h>
36 #include <asm/mmu.h>
37 #include <asm/pgtable.h>
38 #include <asm/ibm4xx.h>
39 #include <asm/ibm44x.h>
40 #include <asm/cputable.h>
41 #include <asm/thread_info.h>
42 #include <asm/ppc_asm.h>
43 #include <asm/offsets.h>
44
45 /*
46  * Macros
47  */
48
49 #define SET_IVOR(vector_number, vector_label)           \
50                 li      r26,vector_label@l;             \
51                 mtspr   SPRN_IVOR##vector_number,r26;   \
52                 sync
53                                 
54 /* As with the other PowerPC ports, it is expected that when code
55  * execution begins here, the following registers contain valid, yet
56  * optional, information:
57  *
58  *   r3 - Board info structure pointer (DRAM, frequency, MAC address, etc.)
59  *   r4 - Starting address of the init RAM disk
60  *   r5 - Ending address of the init RAM disk
61  *   r6 - Start of kernel command line string (e.g. "mem=128")
62  *   r7 - End of kernel command line string
63  *
64  */
65         .text
66 _GLOBAL(_stext)
67 _GLOBAL(_start)
68         /*
69          * Reserve a word at a fixed location to store the address
70          * of abatron_pteptrs
71          */
72         nop
73 /*
74  * Save parameters we are passed
75  */
76         mr      r31,r3
77         mr      r30,r4
78         mr      r29,r5
79         mr      r28,r6
80         mr      r27,r7
81         li      r24,0           /* CPU number */
82
83 /*
84  * Set up the initial MMU state
85  *
86  * We are still executing code at the virtual address
87  * mappings set by the firmware for the base of RAM.
88  *
89  * We first invalidate all TLB entries but the one
90  * we are running from.  We then load the KERNELBASE
91  * mappings so we can begin to use kernel addresses
92  * natively and so the interrupt vector locations are
93  * permanently pinned (necessary since Book E
94  * implementations always have translation enabled).
95  *
96  * TODO: Use the known TLB entry we are running from to
97  *       determine which physical region we are located
98  *       in.  This can be used to determine where in RAM
99  *       (on a shared CPU system) or PCI memory space
100  *       (on a DRAMless system) we are located.
101  *       For now, we assume a perfect world which means
102  *       we are located at the base of DRAM (physical 0).
103  */
104
105 /*
106  * Search TLB for entry that we are currently using.
107  * Invalidate all entries but the one we are using.
108  */
109         /* Load our current PID->MMUCR TID and MSR IS->MMUCR STS */
110         mfspr   r3,SPRN_PID                     /* Get PID */
111         mfmsr   r4                              /* Get MSR */
112         andi.   r4,r4,MSR_IS@l                  /* TS=1? */
113         beq     wmmucr                          /* If not, leave STS=0 */
114         oris    r3,r3,PPC44x_MMUCR_STS@h        /* Set STS=1 */
115 wmmucr: mtspr   SPRN_MMUCR,r3                   /* Put MMUCR */
116         sync
117
118         bl      invstr                          /* Find our address */
119 invstr: mflr    r5                              /* Make it accessible */
120         tlbsx   r23,0,r5                        /* Find entry we are in */
121         li      r4,0                            /* Start at TLB entry 0 */
122         li      r3,0                            /* Set PAGEID inval value */
123 1:      cmpw    r23,r4                          /* Is this our entry? */
124         beq     skpinv                          /* If so, skip the inval */
125         tlbwe   r3,r4,PPC44x_TLB_PAGEID         /* If not, inval the entry */
126 skpinv: addi    r4,r4,1                         /* Increment */
127         cmpwi   r4,64                           /* Are we done? */
128         bne     1b                              /* If not, repeat */
129         isync                                   /* If so, context change */
130
131 /*
132  * Configure and load pinned entry into TLB slot 63.
133  */
134
135         lis     r3,KERNELBASE@h         /* Load the kernel virtual address */
136         ori     r3,r3,KERNELBASE@l
137
138         /* Kernel is at the base of RAM */
139         li r4, 0                        /* Load the kernel physical address */
140
141         /* Load the kernel PID = 0 */
142         li      r0,0
143         mtspr   SPRN_PID,r0
144         sync
145
146         /* Initialize MMUCR */
147         li      r5,0
148         mtspr   SPRN_MMUCR,r5
149         sync
150
151         /* pageid fields */
152         clrrwi  r3,r3,10                /* Mask off the effective page number */
153         ori     r3,r3,PPC44x_TLB_VALID | PPC44x_TLB_256M
154
155         /* xlat fields */
156         clrrwi  r4,r4,10                /* Mask off the real page number */
157                                         /* ERPN is 0 for first 4GB page */
158
159         /* attrib fields */
160         /* Added guarded bit to protect against speculative loads/stores */
161         li      r5,0
162         ori     r5,r5,(PPC44x_TLB_SW | PPC44x_TLB_SR | PPC44x_TLB_SX | PPC44x_TLB_G)
163
164         li      r0,63                    /* TLB slot 63 */
165
166         tlbwe   r3,r0,PPC44x_TLB_PAGEID /* Load the pageid fields */
167         tlbwe   r4,r0,PPC44x_TLB_XLAT   /* Load the translation fields */
168         tlbwe   r5,r0,PPC44x_TLB_ATTRIB /* Load the attrib/access fields */
169
170         /* Force context change */
171         mfmsr   r0
172         mtspr   SRR1, r0
173         lis     r0,3f@h
174         ori     r0,r0,3f@l
175         mtspr   SRR0,r0
176         sync
177         rfi
178
179         /* If necessary, invalidate original entry we used */
180 3:      cmpwi   r23,62
181         beq     4f
182         li      r6,0
183         tlbwe   r6,r23,PPC44x_TLB_PAGEID
184         sync
185
186 4:
187 #ifdef CONFIG_SERIAL_TEXT_DEBUG
188         /*
189          * Add temporary UART mapping for early debug.  This
190          * mapping must be identical to that used by the early
191          * bootloader code since the same asm/serial.h parameters
192          * are used for polled operation.
193          */
194         /* pageid fields */
195         lis     r3,0xe000       
196         ori     r3,r3,PPC44x_TLB_VALID | PPC44x_TLB_256M
197
198         /* xlat fields */
199         lis     r4,0x4000               /* RPN is 0x40000000 */
200         ori     r4,r4,0x0001            /* ERPN is 1 for second 4GB page */
201
202         /* attrib fields */
203         li      r5,0
204         ori     r5,r5,(PPC44x_TLB_SW | PPC44x_TLB_SR | PPC44x_TLB_I | PPC44x_TLB_G)
205
206         li      r0,1                    /* TLB slot 1 */
207
208         tlbwe   r3,r0,PPC44x_TLB_PAGEID /* Load the pageid fields */
209         tlbwe   r4,r0,PPC44x_TLB_XLAT   /* Load the translation fields */
210         tlbwe   r5,r0,PPC44x_TLB_ATTRIB /* Load the attrib/access fields */
211
212         ori     r3,r3,PPC44x_TLB_TS     /* Translation state 1 */
213
214         li      r0,1                    /* TLB slot 1 */
215
216         tlbwe   r3,r0,PPC44x_TLB_PAGEID /* Load the pageid fields */
217         tlbwe   r4,r0,PPC44x_TLB_XLAT   /* Load the translation fields */
218         tlbwe   r5,r0,PPC44x_TLB_ATTRIB /* Load the attrib/access fields */
219
220         /* Force context change */
221         isync
222 #endif /* CONFIG_SERIAL_TEXT_DEBUG */
223
224         /* Establish the interrupt vector offsets */
225         SET_IVOR(0,  CriticalInput);
226         SET_IVOR(1,  MachineCheck);
227         SET_IVOR(2,  DataStorage);
228         SET_IVOR(3,  InstructionStorage);
229         SET_IVOR(4,  ExternalInput);
230         SET_IVOR(5,  Alignment);
231         SET_IVOR(6,  Program);
232         SET_IVOR(7,  FloatingPointUnavailable);
233         SET_IVOR(8,  SystemCall);
234         SET_IVOR(9,  AuxillaryProcessorUnavailable);
235         SET_IVOR(10, Decrementer);
236         SET_IVOR(11, FixedIntervalTimer);
237         SET_IVOR(12, WatchdogTimer);
238         SET_IVOR(13, DataTLBError);
239         SET_IVOR(14, InstructionTLBError);
240         SET_IVOR(15, Debug);
241
242         /* Establish the interrupt vector base */
243         lis     r4,interrupt_base@h     /* IVPR only uses the high 16-bits */
244         mtspr   SPRN_IVPR,r4
245
246         /*
247          * This is where the main kernel code starts.
248          */
249
250         /* ptr to current */
251         lis     r2,init_task@h
252         ori     r2,r2,init_task@l
253
254         /* ptr to current thread */
255         addi    r4,r2,THREAD    /* init task's THREAD */
256         mtspr   SPRG3,r4
257
258         /* stack */
259         lis     r1,init_thread_union@h
260         ori     r1,r1,init_thread_union@l
261         li      r0,0
262         stwu    r0,THREAD_SIZE-STACK_FRAME_OVERHEAD(r1)
263
264         bl      early_init
265
266 /*
267  * Decide what sort of machine this is and initialize the MMU.
268  */
269         mr      r3,r31
270         mr      r4,r30
271         mr      r5,r29
272         mr      r6,r28
273         mr      r7,r27
274         bl      machine_init
275         bl      MMU_init
276
277         /* Setup PTE pointers for the Abatron bdiGDB */
278         lis     r6, swapper_pg_dir@h
279         ori     r6, r6, swapper_pg_dir@l
280         lis     r5, abatron_pteptrs@h
281         ori     r5, r5, abatron_pteptrs@l
282         lis     r4, KERNELBASE@h
283         ori     r4, r4, KERNELBASE@l
284         stw     r5, 0(r4)       /* Save abatron_pteptrs at a fixed location */
285         stw     r6, 0(r5)
286
287         /* Let's move on */
288         lis     r4,start_kernel@h
289         ori     r4,r4,start_kernel@l
290         lis     r3,MSR_KERNEL@h
291         ori     r3,r3,MSR_KERNEL@l
292         mtspr   SRR0,r4
293         mtspr   SRR1,r3
294         rfi                     /* change context and jump to start_kernel */
295
296 /*
297  * Interrupt vector entry code
298  *
299  * The Book E MMUs are always on so we don't need to handle
300  * interrupts in real mode as with previous PPC processors. In
301  * this case we handle interrupts in the kernel virtual address
302  * space.
303  *
304  * Interrupt vectors are dynamically placed relative to the
305  * interrupt prefix as determined by the address of interrupt_base.
306  * The interrupt vectors offsets are programmed using the labels
307  * for each interrupt vector entry.
308  *
309  * Interrupt vectors must be aligned on a 16 byte boundary.
310  * We align on a 32 byte cache line boundary for good measure.
311  */
312
313 #define NORMAL_EXCEPTION_PROLOG                                              \
314         mtspr   SPRN_SPRG0,r10;         /* save two registers to work with */\
315         mtspr   SPRN_SPRG1,r11;                                              \
316         mtspr   SPRN_SPRG4W,r1;                                              \
317         mfcr    r10;                    /* save CR in r10 for now          */\
318         mfspr   r11,SPRN_SRR1;          /* check whether user or kernel    */\
319         andi.   r11,r11,MSR_PR;                                              \
320         beq     1f;                                                          \
321         mfspr   r1,SPRG3;               /* if from user, start at top of   */\
322         lwz     r1,THREAD_INFO-THREAD(r1); /* this thread's kernel stack   */\
323         addi    r1,r1,THREAD_SIZE;                                           \
324 1:      subi    r1,r1,INT_FRAME_SIZE;   /* Allocate an exception frame     */\
325         tophys(r11,r1);                                                      \
326         stw     r10,_CCR(r11);          /* save various registers          */\
327         stw     r12,GPR12(r11);                                              \
328         stw     r9,GPR9(r11);                                                \
329         mfspr   r10,SPRG0;                                                   \
330         stw     r10,GPR10(r11);                                              \
331         mfspr   r12,SPRG1;                                                   \
332         stw     r12,GPR11(r11);                                              \
333         mflr    r10;                                                         \
334         stw     r10,_LINK(r11);                                              \
335         mfspr   r10,SPRG4R;                                                  \
336         mfspr   r12,SRR0;                                                    \
337         stw     r10,GPR1(r11);                                               \
338         mfspr   r9,SRR1;                                                     \
339         stw     r10,0(r11);                                                  \
340         rlwinm  r9,r9,0,14,12;          /* clear MSR_WE (necessary?)       */\
341         stw     r0,GPR0(r11);                                                \
342         SAVE_4GPRS(3, r11);                                                  \
343         SAVE_2GPRS(7, r11)
344
345 /*
346  * Exception prolog for critical exceptions.  This is a little different
347  * from the normal exception prolog above since a critical exception
348  * can potentially occur at any point during normal exception processing.
349  * Thus we cannot use the same SPRG registers as the normal prolog above.
350  * Instead we use a couple of words of memory at low physical addresses.
351  * This is OK since we don't support SMP on these processors. For Book E
352  * processors, we also have a reserved register (SPRG2) that is only used
353  * in critical exceptions so we can free up a GPR to use as the base for
354  * indirect access to the critical exception save area.  This is necessary
355  * since the MMU is always on and the save area is offset from KERNELBASE.
356  */
357 #define CRITICAL_EXCEPTION_PROLOG                                            \
358         mtspr   SPRG2,r8;               /* SPRG2 only used in criticals */   \
359         lis     r8,crit_save@ha;                                             \
360         stw     r10,crit_r10@l(r8);                                          \
361         stw     r11,crit_r11@l(r8);                                          \
362         mfspr   r10,SPRG0;                                                   \
363         stw     r10,crit_sprg0@l(r8);                                        \
364         mfspr   r10,SPRG1;                                                   \
365         stw     r10,crit_sprg1@l(r8);                                        \
366         mfspr   r10,SPRG4R;                                                  \
367         stw     r10,crit_sprg4@l(r8);                                        \
368         mfspr   r10,SPRG5R;                                                  \
369         stw     r10,crit_sprg5@l(r8);                                        \
370         mfspr   r10,SPRG7R;                                                  \
371         stw     r10,crit_sprg7@l(r8);                                        \
372         mfspr   r10,SPRN_PID;                                                \
373         stw     r10,crit_pid@l(r8);                                          \
374         mfspr   r10,SRR0;                                                    \
375         stw     r10,crit_srr0@l(r8);                                         \
376         mfspr   r10,SRR1;                                                    \
377         stw     r10,crit_srr1@l(r8);                                         \
378         mfspr   r8,SPRG2;               /* SPRG2 only used in criticals */   \
379         mfcr    r10;                    /* save CR in r10 for now          */\
380         mfspr   r11,SPRN_CSRR1;         /* check whether user or kernel    */\
381         andi.   r11,r11,MSR_PR;                                              \
382         lis     r11,critical_stack_top@h;                                    \
383         ori     r11,r11,critical_stack_top@l;                                \
384         beq     1f;                                                          \
385         /* COMING FROM USER MODE */                                          \
386         mfspr   r11,SPRG3;              /* if from user, start at top of   */\
387         lwz     r11,THREAD_INFO-THREAD(r11); /* this thread's kernel stack */\
388         addi    r11,r11,THREAD_SIZE;                                         \
389 1:      subi    r11,r11,INT_FRAME_SIZE; /* Allocate an exception frame     */\
390         stw     r10,_CCR(r11);          /* save various registers          */\
391         stw     r12,GPR12(r11);                                              \
392         stw     r9,GPR9(r11);                                                \
393         mflr    r10;                                                         \
394         stw     r10,_LINK(r11);                                              \
395         mfspr   r12,SPRN_DEAR;          /* save DEAR and ESR in the frame  */\
396         stw     r12,_DEAR(r11);         /* since they may have had stuff   */\
397         mfspr   r9,SPRN_ESR;            /* in them at the point where the  */\
398         stw     r9,_ESR(r11);           /* exception was taken             */\
399         mfspr   r12,CSRR0;                                                   \
400         stw     r1,GPR1(r11);                                                \
401         mfspr   r9,CSRR1;                                                    \
402         stw     r1,0(r11);                                                   \
403         tovirt(r1,r11);                                                      \
404         rlwinm  r9,r9,0,14,12;          /* clear MSR_WE (necessary?)       */\
405         stw     r0,GPR0(r11);                                                \
406         SAVE_4GPRS(3, r11);                                                  \
407         SAVE_2GPRS(7, r11)
408
409 /*
410  * Exception prolog for machine check exceptions.  This is similar to
411  * the critical exception prolog, except that machine check exceptions
412  * have their own save area.  For Book E processors, we also have a
413  * reserved register (SPRG6) that is only used in machine check exceptions
414  * so we can free up a GPR to use as the base for indirect access to the
415  * machine check exception save area.  This is necessary since the MMU
416  * is always on and the save area is offset from KERNELBASE.
417  */
418 #define MCHECK_EXCEPTION_PROLOG                                      \
419         mtspr   SPRG6W,r8;              /* SPRG6 used in machine checks */   \
420         lis     r8,mcheck_save@ha;                                           \
421         stw     r10,mcheck_r10@l(r8);                                        \
422         stw     r11,mcheck_r11@l(r8);                                        \
423         mfspr   r10,SPRG0;                                                   \
424         stw     r10,mcheck_sprg0@l(r8);                                      \
425         mfspr   r10,SPRG1;                                                   \
426         stw     r10,mcheck_sprg1@l(r8);                                      \
427         mfspr   r10,SPRG4R;                                                  \
428         stw     r10,mcheck_sprg4@l(r8);                                      \
429         mfspr   r10,SPRG5R;                                                  \
430         stw     r10,mcheck_sprg5@l(r8);                                      \
431         mfspr   r10,SPRG7R;                                                  \
432         stw     r10,mcheck_sprg7@l(r8);                                      \
433         mfspr   r10,SPRN_PID;                                                \
434         stw     r10,mcheck_pid@l(r8);                                        \
435         mfspr   r10,SRR0;                                                    \
436         stw     r10,mcheck_srr0@l(r8);                                       \
437         mfspr   r10,SRR1;                                                    \
438         stw     r10,mcheck_srr1@l(r8);                                       \
439         mfspr   r10,CSRR0;                                                   \
440         stw     r10,mcheck_csrr0@l(r8);                                      \
441         mfspr   r10,CSRR1;                                                   \
442         stw     r10,mcheck_csrr1@l(r8);                                      \
443         mfspr   r8,SPRG6R;              /* SPRG6 used in machine checks */   \
444         mfcr    r10;                    /* save CR in r10 for now          */\
445         mfspr   r11,SPRN_MCSRR1;        /* check whether user or kernel    */\
446         andi.   r11,r11,MSR_PR;                                              \
447         lis     r11,mcheck_stack_top@h;                                      \
448         ori     r11,r11,mcheck_stack_top@l;                                  \
449         beq     1f;                                                          \
450         /* COMING FROM USER MODE */                                          \
451         mfspr   r11,SPRG3;              /* if from user, start at top of   */\
452         lwz     r11,THREAD_INFO-THREAD(r11); /* this thread's kernel stack */\
453         addi    r11,r11,THREAD_SIZE;                                         \
454 1:      subi    r11,r11,INT_FRAME_SIZE; /* Allocate an exception frame     */\
455         stw     r10,_CCR(r11);          /* save various registers          */\
456         stw     r12,GPR12(r11);                                              \
457         stw     r9,GPR9(r11);                                                \
458         mflr    r10;                                                         \
459         stw     r10,_LINK(r11);                                              \
460         mfspr   r12,SPRN_DEAR;          /* save DEAR and ESR in the frame  */\
461         stw     r12,_DEAR(r11);         /* since they may have had stuff   */\
462         mfspr   r9,SPRN_ESR;            /* in them at the point where the  */\
463         stw     r9,_ESR(r11);           /* exception was taken             */\
464         mfspr   r12,MCSRR0;                                                  \
465         stw     r1,GPR1(r11);                                                \
466         mfspr   r9,MCSRR1;                                                   \
467         stw     r1,0(r11);                                                   \
468         tovirt(r1,r11);                                                      \
469         rlwinm  r9,r9,0,14,12;          /* clear MSR_WE (necessary?)       */\
470         stw     r0,GPR0(r11);                                                \
471         SAVE_4GPRS(3, r11);                                                  \
472         SAVE_2GPRS(7, r11)
473
474 /*
475  * Exception vectors.
476  */
477 #define START_EXCEPTION(label)                                               \
478         .align 5;                                                            \
479 label:
480
481 #define FINISH_EXCEPTION(func)                                  \
482         bl      transfer_to_handler_full;                       \
483         .long   func;                                           \
484         .long   ret_from_except_full
485
486 #define EXCEPTION(n, label, hdlr, xfer)                         \
487         START_EXCEPTION(label);                                 \
488         NORMAL_EXCEPTION_PROLOG;                                \
489         addi    r3,r1,STACK_FRAME_OVERHEAD;                     \
490         xfer(n, hdlr)
491
492 #define CRITICAL_EXCEPTION(n, label, hdlr)                      \
493         START_EXCEPTION(label);                                 \
494         CRITICAL_EXCEPTION_PROLOG;                              \
495         addi    r3,r1,STACK_FRAME_OVERHEAD;                     \
496         EXC_XFER_TEMPLATE(hdlr, n+2, (MSR_KERNEL & ~(MSR_ME|MSR_DE|MSR_CE)), \
497                           NOCOPY, transfer_to_handler_full, \
498                           ret_from_except_full)
499
500 #define MCHECK_EXCEPTION(n, label, hdlr)                        \
501         START_EXCEPTION(label);                                 \
502         MCHECK_EXCEPTION_PROLOG;                                \
503         lis     r4,MCSR_MCS@h;                                  \
504         mtspr   SPRN_MCSR,r4;                                   \
505         mfspr   r5,SPRN_ESR;                                    \
506         stw     r5,_ESR(r11);                                   \
507         addi    r3,r1,STACK_FRAME_OVERHEAD;                     \
508         EXC_XFER_TEMPLATE(hdlr, n+2, (MSR_KERNEL & ~(MSR_ME|MSR_DE|MSR_CE)), \
509                           NOCOPY, mcheck_transfer_to_handler,   \
510                           ret_from_mcheck_exc)
511
512 #define EXC_XFER_TEMPLATE(hdlr, trap, msr, copyee, tfer, ret)   \
513         li      r10,trap;                                       \
514         stw     r10,TRAP(r11);                                  \
515         lis     r10,msr@h;                                      \
516         ori     r10,r10,msr@l;                                  \
517         copyee(r10, r9);                                        \
518         bl      tfer;                                           \
519         .long   hdlr;                                           \
520         .long   ret
521
522 #define COPY_EE(d, s)           rlwimi d,s,0,16,16
523 #define NOCOPY(d, s)
524
525 #define EXC_XFER_STD(n, hdlr)           \
526         EXC_XFER_TEMPLATE(hdlr, n, MSR_KERNEL, NOCOPY, transfer_to_handler_full, \
527                           ret_from_except_full)
528
529 #define EXC_XFER_LITE(n, hdlr)          \
530         EXC_XFER_TEMPLATE(hdlr, n+1, MSR_KERNEL, NOCOPY, transfer_to_handler, \
531                           ret_from_except)
532
533 #define EXC_XFER_EE(n, hdlr)            \
534         EXC_XFER_TEMPLATE(hdlr, n, MSR_KERNEL, COPY_EE, transfer_to_handler_full, \
535                           ret_from_except_full)
536
537 #define EXC_XFER_EE_LITE(n, hdlr)       \
538         EXC_XFER_TEMPLATE(hdlr, n+1, MSR_KERNEL, COPY_EE, transfer_to_handler, \
539                           ret_from_except)
540
541 interrupt_base:
542         /* Critical Input Interrupt */
543         CRITICAL_EXCEPTION(0x0100, CriticalInput, UnknownException)
544
545         /* Machine Check Interrupt */
546 #ifdef CONFIG_440A
547         MCHECK_EXCEPTION(0x0200, MachineCheck, MachineCheckException)
548 #else
549         CRITICAL_EXCEPTION(0x0200, MachineCheck, MachineCheckException)
550 #endif
551
552         /* Data Storage Interrupt */
553         START_EXCEPTION(DataStorage)
554         mtspr   SPRG0, r10              /* Save some working registers */
555         mtspr   SPRG1, r11
556         mtspr   SPRG4W, r12
557         mtspr   SPRG5W, r13
558         mfcr    r11
559         mtspr   SPRG7W, r11
560
561         /*
562          * Check if it was a store fault, if not then bail
563          * because a user tried to access a kernel or
564          * read-protected page.  Otherwise, get the
565          * offending address and handle it.
566          */
567         mfspr   r10, SPRN_ESR
568         andis.  r10, r10, ESR_ST@h
569         beq     2f
570
571         mfspr   r10, SPRN_DEAR          /* Get faulting address */
572
573         /* If we are faulting a kernel address, we have to use the
574          * kernel page tables.
575          */
576         andis.  r11, r10, 0x8000
577         beq     3f
578         lis     r11, swapper_pg_dir@h
579         ori     r11, r11, swapper_pg_dir@l
580
581         mfspr   r12,SPRN_MMUCR
582         rlwinm  r12,r12,0,0,23          /* Clear TID */
583
584         b       4f
585
586         /* Get the PGD for the current thread */
587 3:
588         mfspr   r11,SPRG3
589         lwz     r11,PGDIR(r11)
590
591         /* Load PID into MMUCR TID */
592         mfspr   r12,SPRN_MMUCR          /* Get MMUCR */
593         mfspr   r13,SPRN_PID            /* Get PID */
594         rlwimi  r12,r13,0,24,31         /* Set TID */
595
596 4:
597         mtspr   SPRN_MMUCR,r12
598
599         rlwinm  r12, r10, 13, 19, 29    /* Compute pgdir/pmd offset */
600         lwzx    r11, r12, r11           /* Get pgd/pmd entry */
601         rlwinm. r12, r11, 0, 0, 20      /* Extract pt base address */
602         beq     2f                      /* Bail if no table */
603
604         rlwimi  r12, r10, 23, 20, 28    /* Compute pte address */
605         lwz     r11, 4(r12)             /* Get pte entry */
606
607         andi.   r13, r11, _PAGE_RW      /* Is it writeable? */
608         beq     2f                      /* Bail if not */
609
610         /* Update 'changed'.
611         */
612         ori     r11, r11, _PAGE_DIRTY|_PAGE_ACCESSED|_PAGE_HWWRITE
613         stw     r11, 4(r12)             /* Update Linux page table */
614
615         li      r13, PPC44x_TLB_SR@l    /* Set SR */
616         rlwimi  r13, r11, 29, 29, 29    /* SX = _PAGE_HWEXEC */
617         rlwimi  r13, r11, 0, 30, 30     /* SW = _PAGE_RW */
618         rlwimi  r13, r11, 29, 28, 28    /* UR = _PAGE_USER */
619         rlwimi  r12, r11, 31, 26, 26    /* (_PAGE_USER>>1)->r12 */
620         rlwimi  r12, r11, 29, 30, 30    /* (_PAGE_USER>>3)->r12 */
621         and     r12, r12, r11           /* HWEXEC/RW & USER */
622         rlwimi  r13, r12, 0, 26, 26     /* UX = HWEXEC & USER */
623         rlwimi  r13, r12, 3, 27, 27     /* UW = RW & USER */
624
625         rlwimi  r11,r13,0,26,31         /* Insert static perms */
626
627         rlwinm  r11,r11,0,20,15         /* Clear U0-U3 */
628
629         /* find the TLB index that caused the fault.  It has to be here. */
630         tlbsx   r10, 0, r10
631
632         tlbwe   r11, r10, PPC44x_TLB_ATTRIB     /* Write ATTRIB */
633
634         /* Done...restore registers and get out of here.
635         */
636         mfspr   r11, SPRG7R
637         mtcr    r11
638         mfspr   r13, SPRG5R
639         mfspr   r12, SPRG4R
640
641         mfspr   r11, SPRG1
642         mfspr   r10, SPRG0
643         rfi                     /* Force context change */
644
645 2:
646         /*
647          * The bailout.  Restore registers to pre-exception conditions
648          * and call the heavyweights to help us out.
649          */
650         mfspr   r11, SPRG7R
651         mtcr    r11
652         mfspr   r13, SPRG5R
653         mfspr   r12, SPRG4R
654
655         mfspr   r11, SPRG1
656         mfspr   r10, SPRG0
657         b       data_access
658
659         /* Instruction Storage Interrupt */
660         START_EXCEPTION(InstructionStorage)
661         NORMAL_EXCEPTION_PROLOG
662         mr      r4,r12                  /* Pass SRR0 as arg2 */
663         li      r5,0                    /* Pass zero as arg3 */
664         EXC_XFER_EE_LITE(0x0400, handle_page_fault)
665
666         /* External Input Interrupt */
667         EXCEPTION(0x0500, ExternalInput, do_IRQ, EXC_XFER_LITE)
668
669         /* Alignment Interrupt */
670         START_EXCEPTION(Alignment)
671         NORMAL_EXCEPTION_PROLOG
672         mfspr   r4,SPRN_DEAR            /* Grab the DEAR and save it */
673         stw     r4,_DEAR(r11)
674         addi    r3,r1,STACK_FRAME_OVERHEAD
675         EXC_XFER_EE(0x0600, AlignmentException)
676
677         /* Program Interrupt */
678         START_EXCEPTION(Program)
679         NORMAL_EXCEPTION_PROLOG
680         mfspr   r4,SPRN_ESR             /* Grab the ESR and save it */
681         stw     r4,_ESR(r11)
682         addi    r3,r1,STACK_FRAME_OVERHEAD
683         EXC_XFER_EE(0x700, ProgramCheckException)
684
685         /* Floating Point Unavailable Interrupt */
686         EXCEPTION(0x2010, FloatingPointUnavailable, UnknownException, EXC_XFER_EE)
687
688         /* System Call Interrupt */
689         START_EXCEPTION(SystemCall)
690         NORMAL_EXCEPTION_PROLOG
691         EXC_XFER_EE_LITE(0x0c00, DoSyscall)
692
693         /* Auxillary Processor Unavailable Interrupt */
694         EXCEPTION(0x2020, AuxillaryProcessorUnavailable, UnknownException, EXC_XFER_EE)
695
696         /* Decrementer Interrupt */
697         START_EXCEPTION(Decrementer)
698         NORMAL_EXCEPTION_PROLOG
699         lis     r0,TSR_DIS@h            /* Setup the DEC interrupt mask */
700         mtspr   SPRN_TSR,r0             /* Clear the DEC interrupt */
701         addi    r3,r1,STACK_FRAME_OVERHEAD
702         EXC_XFER_LITE(0x1000, timer_interrupt)
703
704         /* Fixed Internal Timer Interrupt */
705         /* TODO: Add FIT support */
706         EXCEPTION(0x1010, FixedIntervalTimer, UnknownException, EXC_XFER_EE)
707
708         /* Watchdog Timer Interrupt */
709         /* TODO: Add watchdog support */
710         CRITICAL_EXCEPTION(0x1020, WatchdogTimer, UnknownException)
711
712         /* Data TLB Error Interrupt */
713         START_EXCEPTION(DataTLBError)
714         mtspr   SPRG0, r10              /* Save some working registers */
715         mtspr   SPRG1, r11
716         mtspr   SPRG4W, r12
717         mtspr   SPRG5W, r13
718         mfcr    r11
719         mtspr   SPRG7W, r11
720         mfspr   r10, SPRN_DEAR          /* Get faulting address */
721
722         /* If we are faulting a kernel address, we have to use the
723          * kernel page tables.
724          */
725         andis.  r11, r10, 0x8000
726         beq     3f
727         lis     r11, swapper_pg_dir@h
728         ori     r11, r11, swapper_pg_dir@l
729
730         mfspr   r12,SPRN_MMUCR
731         rlwinm  r12,r12,0,0,23          /* Clear TID */
732
733         b       4f
734
735         /* Get the PGD for the current thread */
736 3:
737         mfspr   r11,SPRG3
738         lwz     r11,PGDIR(r11)
739
740         /* Load PID into MMUCR TID */
741         mfspr   r12,SPRN_MMUCR
742         mfspr   r13,SPRN_PID            /* Get PID */
743         rlwimi  r12,r13,0,24,31         /* Set TID */
744
745 4:
746         mtspr   SPRN_MMUCR,r12
747
748         rlwinm  r12, r10, 13, 19, 29    /* Compute pgdir/pmd offset */
749         lwzx    r11, r12, r11           /* Get pgd/pmd entry */
750         rlwinm. r12, r11, 0, 0, 20      /* Extract pt base address */
751         beq     2f                      /* Bail if no table */
752
753         rlwimi  r12, r10, 23, 20, 28    /* Compute pte address */
754         lwz     r11, 4(r12)             /* Get pte entry */
755         andi.   r13, r11, _PAGE_PRESENT /* Is the page present? */
756         beq     2f                      /* Bail if not present */
757
758         ori     r11, r11, _PAGE_ACCESSED
759         stw     r11, 4(r12)
760
761          /* Jump to common tlb load */
762         b       finish_tlb_load
763
764 2:
765         /* The bailout.  Restore registers to pre-exception conditions
766          * and call the heavyweights to help us out.
767          */
768         mfspr   r11, SPRG7R
769         mtcr    r11
770         mfspr   r13, SPRG5R
771         mfspr   r12, SPRG4R
772         mfspr   r11, SPRG1
773         mfspr   r10, SPRG0
774         b       data_access
775
776         /* Instruction TLB Error Interrupt */
777         /*
778          * Nearly the same as above, except we get our
779          * information from different registers and bailout
780          * to a different point.
781          */
782         START_EXCEPTION(InstructionTLBError)
783         mtspr   SPRG0, r10              /* Save some working registers */
784         mtspr   SPRG1, r11
785         mtspr   SPRG4W, r12
786         mtspr   SPRG5W, r13
787         mfcr    r11
788         mtspr   SPRG7W, r11
789         mfspr   r10, SRR0               /* Get faulting address */
790
791         /* If we are faulting a kernel address, we have to use the
792          * kernel page tables.
793          */
794         andis.  r11, r10, 0x8000
795         beq     3f
796         lis     r11, swapper_pg_dir@h
797         ori     r11, r11, swapper_pg_dir@l
798
799         mfspr   r12,SPRN_MMUCR
800         rlwinm  r12,r12,0,0,23          /* Clear TID */
801
802         b       4f
803
804         /* Get the PGD for the current thread */
805 3:
806         mfspr   r11,SPRG3
807         lwz     r11,PGDIR(r11)
808
809         /* Load PID into MMUCR TID */
810         mfspr   r12,SPRN_MMUCR
811         mfspr   r13,SPRN_PID            /* Get PID */
812         rlwimi  r12,r13,0,24,31         /* Set TID */
813
814 4:
815         mtspr   SPRN_MMUCR,r12
816
817         rlwinm  r12, r10, 13, 19, 29    /* Compute pgdir/pmd offset */
818         lwzx    r11, r12, r11           /* Get pgd/pmd entry */
819         rlwinm. r12, r11, 0, 0, 20      /* Extract pt base address */
820         beq     2f                      /* Bail if no table */
821
822         rlwimi  r12, r10, 23, 20, 28    /* Compute pte address */
823         lwz     r11, 4(r12)             /* Get pte entry */
824         andi.   r13, r11, _PAGE_PRESENT /* Is the page present? */
825         beq     2f                      /* Bail if not present */
826
827         ori     r11, r11, _PAGE_ACCESSED
828         stw     r11, 4(r12)
829
830         /* Jump to common TLB load point */
831         b       finish_tlb_load
832
833 2:
834         /* The bailout.  Restore registers to pre-exception conditions
835          * and call the heavyweights to help us out.
836          */
837         mfspr   r11, SPRG7R
838         mtcr    r11
839         mfspr   r13, SPRG5R
840         mfspr   r12, SPRG4R
841         mfspr   r11, SPRG1
842         mfspr   r10, SPRG0
843         b       InstructionStorage
844
845 /* Check for a single step debug exception while in an exception
846  * handler before state has been saved.  This is to catch the case
847  * where an instruction that we are trying to single step causes
848  * an exception (eg ITLB/DTLB miss) and thus the first instruction of
849  * the exception handler generates a single step debug exception.
850  *
851  * If we get a debug trap on the first instruction of an exception handler,
852  * we reset the MSR_DE in the _exception handler's_ MSR (the debug trap is
853  * a critical exception, so we are using SPRN_CSRR1 to manipulate the MSR).
854  * The exception handler was handling a non-critical interrupt, so it will
855  * save (and later restore) the MSR via SPRN_SRR1, which will still have
856  * the MSR_DE bit set.
857  */
858         /* Debug Interrupt */
859         START_EXCEPTION(Debug)
860         CRITICAL_EXCEPTION_PROLOG
861
862         /*
863          * If this is a single step or branch-taken exception in an
864          * exception entry sequence, it was probably meant to apply to
865          * the code where the exception occurred (since exception entry
866          * doesn't turn off DE automatically).  We simulate the effect
867          * of turning off DE on entry to an exception handler by turning
868          * off DE in the CSRR1 value and clearing the debug status.
869          */
870         mfspr   r10,SPRN_DBSR           /* check single-step/branch taken */
871         andis.  r10,r10,(DBSR_IC|DBSR_BT)@h
872         beq+    1f
873         andi.   r0,r9,MSR_PR            /* check supervisor */
874         beq     2f                      /* branch if we need to fix it up... */
875
876         /* continue normal handling for a critical exception... */
877 1:      mfspr   r4,SPRN_DBSR
878         addi    r3,r1,STACK_FRAME_OVERHEAD
879         EXC_XFER_TEMPLATE(DebugException, 0x2002, \
880                 (MSR_KERNEL & ~(MSR_ME|MSR_DE|MSR_CE)), \
881                 NOCOPY, crit_transfer_to_handler, ret_from_crit_exc)
882
883         /* here it looks like we got an inappropriate debug exception. */
884 2:      rlwinm  r9,r9,0,~MSR_DE         /* clear DE in the CSRR1 value */
885         mtspr   SPRN_DBSR,r10           /* clear the IC/BT debug intr status */
886         /* restore state and get out */
887         lwz     r10,_CCR(r11)
888         lwz     r0,GPR0(r11)
889         lwz     r1,GPR1(r11)
890         mtcrf   0x80,r10
891         mtspr   CSRR0,r12
892         mtspr   CSRR1,r9
893         lwz     r9,GPR9(r11)
894
895         mtspr   SPRG2,r8;               /* SPRG2 only used in criticals */
896         lis     r8,crit_save@ha;
897         lwz     r10,crit_r10@l(r8)
898         lwz     r11,crit_r11@l(r8)
899         mfspr   r8,SPRG2
900
901         rfci
902         b       .
903
904 /*
905  * Local functions
906  */
907         /*
908          * Data TLB exceptions will bail out to this point
909          * if they can't resolve the lightweight TLB fault.
910          */
911 data_access:
912         NORMAL_EXCEPTION_PROLOG
913         mfspr   r5,SPRN_ESR             /* Grab the ESR, save it, pass arg3 */
914         stw     r5,_ESR(r11)
915         mfspr   r4,SPRN_DEAR            /* Grab the DEAR, save it, pass arg2 */
916         EXC_XFER_EE_LITE(0x0300, handle_page_fault)
917
918 /*
919
920  * Both the instruction and data TLB miss get to this
921  * point to load the TLB.
922  *      r10 - EA of fault
923  *      r11 - available to use
924  *      r12 - Pointer to the 64-bit PTE
925  *      r13 - available to use
926  *      MMUCR - loaded with proper value when we get here
927  *      Upon exit, we reload everything and RFI.
928  */
929 finish_tlb_load:
930         /*
931          * We set execute, because we don't have the granularity to
932          * properly set this at the page level (Linux problem).
933          * If shared is set, we cause a zero PID->TID load.
934          * Many of these bits are software only.  Bits we don't set
935          * here we (properly should) assume have the appropriate value.
936          */
937
938         /* Load the next available TLB index */
939         lis     r13, tlb_44x_index@ha
940         lwz     r13, tlb_44x_index@l(r13)
941         /* Load the TLB high watermark */
942         lis     r11, tlb_44x_hwater@ha
943         lwz     r11, tlb_44x_hwater@l(r11)
944
945         /* Increment, rollover, and store TLB index */
946         addi    r13, r13, 1
947         cmpw    0, r13, r11                     /* reserve entries */
948         ble     7f
949         li      r13, 0
950 7:
951         /* Store the next available TLB index */
952         lis     r11, tlb_44x_index@ha
953         stw     r13, tlb_44x_index@l(r11)
954
955         lwz     r11, 0(r12)                     /* Get MS word of PTE */
956         lwz     r12, 4(r12)                     /* Get LS word of PTE */
957         rlwimi  r11, r12, 0, 0 , 19             /* Insert RPN */
958         tlbwe   r11, r13, PPC44x_TLB_XLAT       /* Write XLAT */
959
960         /*
961          * Create PAGEID. This is the faulting address,
962          * page size, and valid flag.
963          */
964         li      r11, PPC44x_TLB_VALID | PPC44x_TLB_4K
965         rlwimi  r10, r11, 0, 20, 31             /* Insert valid and page size */
966         tlbwe   r10, r13, PPC44x_TLB_PAGEID     /* Write PAGEID */
967
968         li      r10, PPC44x_TLB_SR@l            /* Set SR */
969         rlwimi  r10, r12, 0, 30, 30             /* Set SW = _PAGE_RW */
970         rlwimi  r10, r12, 29, 29, 29            /* SX = _PAGE_HWEXEC */
971         rlwimi  r10, r12, 29, 28, 28            /* UR = _PAGE_USER */
972         rlwimi  r11, r12, 31, 26, 26            /* (_PAGE_USER>>1)->r12 */
973         and     r11, r12, r11                   /* HWEXEC & USER */
974         rlwimi  r10, r11, 0, 26, 26             /* UX = HWEXEC & USER */
975
976         rlwimi  r12, r10, 0, 26, 31             /* Insert static perms */
977         rlwinm  r12, r12, 0, 20, 15             /* Clear U0-U3 */
978         tlbwe   r12, r13, PPC44x_TLB_ATTRIB     /* Write ATTRIB */
979
980         /* Done...restore registers and get out of here.
981         */
982         mfspr   r11, SPRG7R
983         mtcr    r11
984         mfspr   r13, SPRG5R
985         mfspr   r12, SPRG4R
986         mfspr   r11, SPRG1
987         mfspr   r10, SPRG0
988         rfi                                     /* Force context change */
989
990 /*
991  * Global functions
992  */
993
994 /*
995  * extern void giveup_altivec(struct task_struct *prev)
996  *
997  * The 44x core does not have an AltiVec unit.
998  */
999 _GLOBAL(giveup_altivec)
1000         blr
1001
1002 /*
1003  * extern void giveup_fpu(struct task_struct *prev)
1004  *
1005  * The 44x core does not have an FPU.
1006  */
1007 _GLOBAL(giveup_fpu)
1008         blr
1009
1010 /*
1011  * extern void abort(void)
1012  *
1013  * At present, this routine just applies a system reset.
1014  */
1015 _GLOBAL(abort)
1016         mfspr   r13,SPRN_DBCR0
1017         oris    r13,r13,DBCR0_RST_SYSTEM@h
1018         mtspr   SPRN_DBCR0,r13
1019
1020 _GLOBAL(set_context)
1021
1022 #ifdef CONFIG_BDI_SWITCH
1023         /* Context switch the PTE pointer for the Abatron BDI2000.
1024          * The PGDIR is the second parameter.
1025          */
1026         lis     r5, abatron_pteptrs@h
1027         ori     r5, r5, abatron_pteptrs@l
1028         stw     r4, 0x4(r5)
1029 #endif
1030         mtspr   SPRN_PID,r3
1031         isync                   /* Force context change */
1032         blr
1033
1034 /*
1035  * We put a few things here that have to be page-aligned. This stuff
1036  * goes at the beginning of the data segment, which is page-aligned.
1037  */
1038         .data
1039 _GLOBAL(sdata)
1040 _GLOBAL(empty_zero_page)
1041         .space  4096
1042
1043 /*
1044  * To support >32-bit physical addresses, we use an 8KB pgdir.
1045  */
1046 _GLOBAL(swapper_pg_dir)
1047         .space  8192
1048
1049         .section .bss
1050 /* Stack for handling critical exceptions from kernel mode */
1051 critical_stack_bottom:
1052         .space 4096
1053 critical_stack_top:
1054         .previous
1055
1056 /* Stack for handling machine check exceptions from kernel mode */
1057 mcheck_stack_bottom:
1058         .space 4096
1059 mcheck_stack_top:
1060         .previous
1061
1062 /*
1063  * This area is used for temporarily saving registers during the
1064  * critical and machine check exception prologs. It must always
1065  * follow the page aligned allocations, so it starts on a page
1066  * boundary, ensuring that all crit_save areas are in a single
1067  * page.
1068  */
1069
1070 /* crit_save */
1071 _GLOBAL(crit_save)
1072         .space  4
1073 _GLOBAL(crit_r10)
1074         .space  4
1075 _GLOBAL(crit_r11)
1076         .space  4
1077 _GLOBAL(crit_sprg0)
1078         .space  4
1079 _GLOBAL(crit_sprg1)
1080         .space  4
1081 _GLOBAL(crit_sprg4)
1082         .space  4
1083 _GLOBAL(crit_sprg5)
1084         .space  4
1085 _GLOBAL(crit_sprg7)
1086         .space  4
1087 _GLOBAL(crit_pid)
1088         .space  4
1089 _GLOBAL(crit_srr0)
1090         .space  4
1091 _GLOBAL(crit_srr1)
1092         .space  4
1093
1094 /* mcheck_save */
1095 _GLOBAL(mcheck_save)
1096         .space  4
1097 _GLOBAL(mcheck_r10)
1098         .space  4
1099 _GLOBAL(mcheck_r11)
1100         .space  4
1101 _GLOBAL(mcheck_sprg0)
1102         .space  4
1103 _GLOBAL(mcheck_sprg1)
1104         .space  4
1105 _GLOBAL(mcheck_sprg4)
1106         .space  4
1107 _GLOBAL(mcheck_sprg5)
1108         .space  4
1109 _GLOBAL(mcheck_sprg7)
1110         .space  4
1111 _GLOBAL(mcheck_pid)
1112         .space  4
1113 _GLOBAL(mcheck_srr0)
1114         .space  4
1115 _GLOBAL(mcheck_srr1)
1116         .space  4
1117 _GLOBAL(mcheck_csrr0)
1118         .space  4
1119 _GLOBAL(mcheck_csrr1)
1120         .space  4
1121
1122 /*
1123  * This space gets a copy of optional info passed to us by the bootstrap
1124  * which is used to pass parameters into the kernel like root=/dev/sda1, etc.
1125  */
1126 _GLOBAL(cmd_line)
1127         .space  512
1128
1129 /*
1130  * Room for two PTE pointers, usually the kernel and current user pointers
1131  * to their respective root page table.
1132  */
1133 abatron_pteptrs:
1134         .space  8
1135
1136