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