This commit was manufactured by cvs2svn to create branch 'vserver'.
[linux-2.6.git] / arch / ppc / kernel / head_e500.S
1 /*
2  * arch/ppc/kernel/head_e500.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  *    Copyright 2004 Freescale Semiconductor, Inc
27  *      PowerPC e500 modifications, Kumar Gala <kumar.gala@freescale.com>
28  *
29  * This program is free software; you can redistribute  it and/or modify it
30  * under  the terms of  the GNU General  Public License as published by the
31  * Free Software Foundation;  either version 2 of the  License, or (at your
32  * option) any later version.
33  */
34
35 #include <linux/config.h>
36 #include <asm/processor.h>
37 #include <asm/page.h>
38 #include <asm/mmu.h>
39 #include <asm/pgtable.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 /* We try to not make any assumptions about how the boot loader
84  * setup or used the TLBs.  We invalidate all mappings from the
85  * boot loader and load a single entry in TLB1[0] to map the
86  * first 16M of kernel memory.  Any boot info passed from the
87  * bootloader needs to live in this first 16M.
88  *
89  * Requirement on bootloader:
90  *  - The page we're executing in needs to reside in TLB1 and
91  *    have IPROT=1.  If not an invalidate broadcast could
92  *    evict the entry we're currently executing in.
93  *
94  *  r3 = Index of TLB1 were executing in
95  *  r4 = Current MSR[IS]
96  *  r5 = Index of TLB1 temp mapping
97  *
98  * Later in mapin_ram we will correctly map lowmem, and resize TLB1[0]
99  * if needed
100  */
101
102 /* 1. Find the index of the entry we're executing in */
103         bl      invstr                          /* Find our address */
104 invstr: mflr    r6                              /* Make it accessible */
105         mfmsr   r7
106         rlwinm  r4,r7,27,31,31                  /* extract MSR[IS] */
107         mfspr   r7, SPRN_PID0
108         slwi    r7,r7,16
109         or      r7,r7,r4
110         mtspr   SPRN_MAS6,r7
111         tlbsx   0,r6                            /* search MSR[IS], SPID=PID0 */
112         mfspr   r7,SPRN_MAS1
113         andis.  r7,r7,MAS1_VALID@h
114         bne     match_TLB
115         mfspr   r7,SPRN_PID1
116         slwi    r7,r7,16
117         or      r7,r7,r4
118         mtspr   SPRN_MAS6,r7
119         tlbsx   0,r6                            /* search MSR[IS], SPID=PID1 */
120         mfspr   r7,SPRN_MAS1
121         andis.  r7,r7,MAS1_VALID@h
122         bne     match_TLB
123         mfspr   r7, SPRN_PID2
124         slwi    r7,r7,16
125         or      r7,r7,r4
126         mtspr   SPRN_MAS6,r7
127         tlbsx   0,r6                            /* Fall through, we had to match */
128 match_TLB:
129         mfspr   r7,SPRN_MAS0
130         rlwinm  r3,r7,16,28,31                  /* Extract MAS0(Entry) */
131
132         mfspr   r7,SPRN_MAS1                    /* Insure IPROT set */
133         oris    r7,r7,MAS1_IPROT@h
134         mtspr   SPRN_MAS1,r7
135         tlbwe
136
137 /* 2. Invalidate all entries except the entry we're executing in */
138         mfspr   r9,SPRN_TLB1CFG
139         andi.   r9,r9,0xfff
140         li      r6,0                            /* Set Entry counter to 0 */
141 1:      lis     r7,0x1000                       /* Set MAS0(TLBSEL) = 1 */
142         rlwimi  r7,r6,16,12,15                  /* Setup MAS0 = TLBSEL | ESEL(r6) */
143         mtspr   SPRN_MAS0,r7
144         tlbre
145         mfspr   r7,SPRN_MAS1
146         rlwinm  r7,r7,0,2,31                    /* Clear MAS1 Valid and IPROT */
147         cmpw    r3,r6
148         beq     skpinv                          /* Dont update the current execution TLB */
149         mtspr   SPRN_MAS1,r7
150         tlbwe
151         isync
152 skpinv: addi    r6,r6,1                         /* Increment */
153         cmpw    r6,r9                           /* Are we done? */
154         bne     1b                              /* If not, repeat */
155
156         /* Invalidate TLB0 */
157         li      r6,0x04
158         tlbivax 0,r6
159 #ifdef CONFIG_SMP
160         tlbsync
161 #endif
162         /* Invalidate TLB1 */
163         li      r6,0x0c
164         tlbivax 0,r6
165 #ifdef CONFIG_SMP
166         tlbsync
167 #endif
168         msync
169
170 /* 3. Setup a temp mapping and jump to it */
171         andi.   r5, r3, 0x1     /* Find an entry not used and is non-zero */
172         addi    r5, r5, 0x1
173         lis     r7,0x1000       /* Set MAS0(TLBSEL) = 1 */
174         rlwimi  r7,r3,16,12,15  /* Setup MAS0 = TLBSEL | ESEL(r3) */
175         mtspr   SPRN_MAS0,r7
176         tlbre
177
178         /* Just modify the entry ID and EPN for the temp mapping */
179         lis     r7,0x1000       /* Set MAS0(TLBSEL) = 1 */
180         rlwimi  r7,r5,16,12,15  /* Setup MAS0 = TLBSEL | ESEL(r5) */
181         mtspr   SPRN_MAS0,r7
182         xori    r6,r4,1         /* Setup TMP mapping in the other Address space */
183         slwi    r6,r6,12
184         oris    r6,r6,(MAS1_VALID|MAS1_IPROT)@h
185         ori     r6,r6,(MAS1_TSIZE(BOOKE_PAGESZ_4K))@l
186         mtspr   SPRN_MAS1,r6
187         mfspr   r6,SPRN_MAS2
188         li      r7,0            /* temp EPN = 0 */
189         rlwimi  r7,r6,0,20,31
190         mtspr   SPRN_MAS2,r7
191         tlbwe
192
193         xori    r6,r4,1
194         slwi    r6,r6,5         /* setup new context with other address space */
195         bl      1f              /* Find our address */
196 1:      mflr    r9
197         rlwimi  r7,r9,0,20,31
198         addi    r7,r7,24
199         mtspr   SRR0,r7
200         mtspr   SRR1,r6
201         rfi
202
203 /* 4. Clear out PIDs & Search info */
204         li      r6,0
205         mtspr   SPRN_PID0,r6
206         mtspr   SPRN_PID1,r6
207         mtspr   SPRN_PID2,r6
208         mtspr   SPRN_MAS6,r6
209
210 /* 5. Invalidate mapping we started in */
211         lis     r7,0x1000       /* Set MAS0(TLBSEL) = 1 */
212         rlwimi  r7,r3,16,12,15  /* Setup MAS0 = TLBSEL | ESEL(r3) */
213         mtspr   SPRN_MAS0,r7
214         tlbre
215         li      r6,0
216         mtspr   SPRN_MAS1,r6
217         tlbwe
218         /* Invalidate TLB1 */
219         li      r9,0x0c
220         tlbivax 0,r9
221 #ifdef CONFIG_SMP
222         tlbsync
223 #endif
224         msync
225
226 /* 6. Setup KERNELBASE mapping in TLB1[0] */
227         lis     r6,0x1000               /* Set MAS0(TLBSEL) = TLB1(1), ESEL = 0 */
228         mtspr   SPRN_MAS0,r6
229         lis     r6,(MAS1_VALID|MAS1_IPROT)@h
230         ori     r6,r6,(MAS1_TSIZE(BOOKE_PAGESZ_16M))@l
231         mtspr   SPRN_MAS1,r6
232         li      r7,0
233         lis     r6,KERNELBASE@h
234         ori     r6,r6,KERNELBASE@l
235         rlwimi  r6,r7,0,20,31
236         mtspr   SPRN_MAS2,r6
237         li      r7,(MAS3_SX|MAS3_SW|MAS3_SR)
238         mtspr   SPRN_MAS3,r7
239         tlbwe
240
241 /* 7. Jump to KERNELBASE mapping */
242         li      r7,0
243         bl      1f                      /* Find our address */
244 1:      mflr    r9
245         rlwimi  r6,r9,0,20,31
246         addi    r6,r6,24
247         mtspr   SRR0,r6
248         mtspr   SRR1,r7
249         rfi                             /* start execution out of TLB1[0] entry */
250
251 /* 8. Clear out the temp mapping */
252         lis     r7,0x1000       /* Set MAS0(TLBSEL) = 1 */
253         rlwimi  r7,r5,16,12,15  /* Setup MAS0 = TLBSEL | ESEL(r5) */
254         mtspr   SPRN_MAS0,r7
255         tlbre
256         mtspr   SPRN_MAS1,r8
257         tlbwe
258         /* Invalidate TLB1 */
259         li      r9,0x0c
260         tlbivax 0,r9
261 #ifdef CONFIG_SMP
262         tlbsync
263 #endif
264         msync
265
266         /* Establish the interrupt vector offsets */
267         SET_IVOR(0,  CriticalInput);
268         SET_IVOR(1,  MachineCheck);
269         SET_IVOR(2,  DataStorage);
270         SET_IVOR(3,  InstructionStorage);
271         SET_IVOR(4,  ExternalInput);
272         SET_IVOR(5,  Alignment);
273         SET_IVOR(6,  Program);
274         SET_IVOR(7,  FloatingPointUnavailable);
275         SET_IVOR(8,  SystemCall);
276         SET_IVOR(9,  AuxillaryProcessorUnavailable);
277         SET_IVOR(10, Decrementer);
278         SET_IVOR(11, FixedIntervalTimer);
279         SET_IVOR(12, WatchdogTimer);
280         SET_IVOR(13, DataTLBError);
281         SET_IVOR(14, InstructionTLBError);
282         SET_IVOR(15, Debug);
283         SET_IVOR(32, SPEUnavailable);
284         SET_IVOR(33, SPEFloatingPointData);
285         SET_IVOR(34, SPEFloatingPointRound);
286         SET_IVOR(35, PerformanceMonitor);
287
288         /* Establish the interrupt vector base */
289         lis     r4,interrupt_base@h     /* IVPR only uses the high 16-bits */
290         mtspr   SPRN_IVPR,r4
291
292         /* Setup the defaults for TLB entries */
293         li      r2,MAS4_TSIZED(BOOKE_PAGESZ_4K)
294         mtspr   SPRN_MAS4, r2
295
296 #if 0
297         /* Enable DOZE */
298         mfspr   r2,SPRN_HID0
299         oris    r2,r2,HID0_DOZE@h
300         mtspr   SPRN_HID0, r2
301 #endif
302
303         /*
304          * This is where the main kernel code starts.
305          */
306
307         /* ptr to current */
308         lis     r2,init_task@h
309         ori     r2,r2,init_task@l
310
311         /* ptr to current thread */
312         addi    r4,r2,THREAD    /* init task's THREAD */
313         mtspr   SPRG3,r4
314
315         /* stack */
316         lis     r1,init_thread_union@h
317         ori     r1,r1,init_thread_union@l
318         li      r0,0
319         stwu    r0,THREAD_SIZE-STACK_FRAME_OVERHEAD(r1)
320
321         bl      early_init
322
323         mfspr   r3,SPRN_TLB1CFG
324         andi.   r3,r3,0xfff
325         lis     r4,num_tlbcam_entries@ha
326         stw     r3,num_tlbcam_entries@l(r4)
327 /*
328  * Decide what sort of machine this is and initialize the MMU.
329  */
330         mr      r3,r31
331         mr      r4,r30
332         mr      r5,r29
333         mr      r6,r28
334         mr      r7,r27
335         bl      machine_init
336         bl      MMU_init
337
338         /* Setup PTE pointers for the Abatron bdiGDB */
339         lis     r6, swapper_pg_dir@h
340         ori     r6, r6, swapper_pg_dir@l
341         lis     r5, abatron_pteptrs@h
342         ori     r5, r5, abatron_pteptrs@l
343         lis     r4, KERNELBASE@h
344         ori     r4, r4, KERNELBASE@l
345         stw     r5, 0(r4)       /* Save abatron_pteptrs at a fixed location */
346         stw     r6, 0(r5)
347
348         /* Let's move on */
349         lis     r4,start_kernel@h
350         ori     r4,r4,start_kernel@l
351         lis     r3,MSR_KERNEL@h
352         ori     r3,r3,MSR_KERNEL@l
353         mtspr   SRR0,r4
354         mtspr   SRR1,r3
355         rfi                     /* change context and jump to start_kernel */
356
357 /*
358  * Interrupt vector entry code
359  *
360  * The Book E MMUs are always on so we don't need to handle
361  * interrupts in real mode as with previous PPC processors. In
362  * this case we handle interrupts in the kernel virtual address
363  * space.
364  *
365  * Interrupt vectors are dynamically placed relative to the
366  * interrupt prefix as determined by the address of interrupt_base.
367  * The interrupt vectors offsets are programmed using the labels
368  * for each interrupt vector entry.
369  *
370  * Interrupt vectors must be aligned on a 16 byte boundary.
371  * We align on a 32 byte cache line boundary for good measure.
372  */
373
374 #define NORMAL_EXCEPTION_PROLOG                                              \
375         mtspr   SPRN_SPRG0,r10;         /* save two registers to work with */\
376         mtspr   SPRN_SPRG1,r11;                                              \
377         mtspr   SPRN_SPRG4W,r1;                                              \
378         mfcr    r10;                    /* save CR in r10 for now          */\
379         mfspr   r11,SPRN_SRR1;          /* check whether user or kernel    */\
380         andi.   r11,r11,MSR_PR;                                              \
381         beq     1f;                                                          \
382         mfspr   r1,SPRG3;               /* if from user, start at top of   */\
383         lwz     r1,THREAD_INFO-THREAD(r1); /* this thread's kernel stack   */\
384         addi    r1,r1,THREAD_SIZE;                                           \
385 1:      subi    r1,r1,INT_FRAME_SIZE;   /* Allocate an exception frame     */\
386         tophys(r11,r1);                                                      \
387         stw     r10,_CCR(r11);          /* save various registers          */\
388         stw     r12,GPR12(r11);                                              \
389         stw     r9,GPR9(r11);                                                \
390         mfspr   r10,SPRG0;                                                   \
391         stw     r10,GPR10(r11);                                              \
392         mfspr   r12,SPRG1;                                                   \
393         stw     r12,GPR11(r11);                                              \
394         mflr    r10;                                                         \
395         stw     r10,_LINK(r11);                                              \
396         mfspr   r10,SPRG4R;                                                  \
397         mfspr   r12,SRR0;                                                    \
398         stw     r10,GPR1(r11);                                               \
399         mfspr   r9,SRR1;                                                     \
400         stw     r10,0(r11);                                                  \
401         rlwinm  r9,r9,0,14,12;          /* clear MSR_WE (necessary?)       */\
402         stw     r0,GPR0(r11);                                                \
403         SAVE_4GPRS(3, r11);                                                  \
404         SAVE_2GPRS(7, r11)
405
406 /*
407  * Exception prolog for critical exceptions.  This is a little different
408  * from the normal exception prolog above since a critical exception
409  * can potentially occur at any point during normal exception processing.
410  * Thus we cannot use the same SPRG registers as the normal prolog above.
411  * Instead we use a couple of words of memory at low physical addresses.
412  * This is OK since we don't support SMP on these processors. For Book E
413  * processors, we also have a reserved register (SPRG2) that is only used
414  * in critical exceptions so we can free up a GPR to use as the base for
415  * indirect access to the critical exception save area.  This is necessary
416  * since the MMU is always on and the save area is offset from KERNELBASE.
417  */
418 #define CRITICAL_EXCEPTION_PROLOG                                            \
419         mtspr   SPRG2,r8;               /* SPRG2 only used in criticals */   \
420         lis     r8,crit_save@ha;                                             \
421         stw     r10,crit_r10@l(r8);                                          \
422         stw     r11,crit_r11@l(r8);                                          \
423         mfspr   r10,SPRG0;                                                   \
424         stw     r10,crit_sprg0@l(r8);                                        \
425         mfspr   r10,SPRG1;                                                   \
426         stw     r10,crit_sprg1@l(r8);                                        \
427         mfspr   r10,SPRG4R;                                                  \
428         stw     r10,crit_sprg4@l(r8);                                        \
429         mfspr   r10,SPRG5R;                                                  \
430         stw     r10,crit_sprg5@l(r8);                                        \
431         mfspr   r10,SPRG7R;                                                  \
432         stw     r10,crit_sprg7@l(r8);                                        \
433         mfspr   r10,SPRN_PID;                                                \
434         stw     r10,crit_pid@l(r8);                                          \
435         mfspr   r10,SRR0;                                                    \
436         stw     r10,crit_srr0@l(r8);                                         \
437         mfspr   r10,SRR1;                                                    \
438         stw     r10,crit_srr1@l(r8);                                         \
439         mfspr   r8,SPRG2;               /* SPRG2 only used in criticals */   \
440         mfcr    r10;                    /* save CR in r10 for now          */\
441         mfspr   r11,SPRN_CSRR1;         /* check whether user or kernel    */\
442         andi.   r11,r11,MSR_PR;                                              \
443         lis     r11,critical_stack_top@h;                                    \
444         ori     r11,r11,critical_stack_top@l;                                \
445         beq     1f;                                                          \
446         /* COMING FROM USER MODE */                                          \
447         mfspr   r11,SPRG3;              /* if from user, start at top of   */\
448         lwz     r11,THREAD_INFO-THREAD(r11); /* this thread's kernel stack */\
449         addi    r11,r11,THREAD_SIZE;                                         \
450 1:      subi    r11,r11,INT_FRAME_SIZE; /* Allocate an exception frame     */\
451         stw     r10,_CCR(r11);          /* save various registers          */\
452         stw     r12,GPR12(r11);                                              \
453         stw     r9,GPR9(r11);                                                \
454         mflr    r10;                                                         \
455         stw     r10,_LINK(r11);                                              \
456         mfspr   r12,SPRN_DEAR;          /* save DEAR and ESR in the frame  */\
457         stw     r12,_DEAR(r11);         /* since they may have had stuff   */\
458         mfspr   r9,SPRN_ESR;            /* in them at the point where the  */\
459         stw     r9,_ESR(r11);           /* exception was taken             */\
460         mfspr   r12,CSRR0;                                                   \
461         stw     r1,GPR1(r11);                                                \
462         mfspr   r9,CSRR1;                                                    \
463         stw     r1,0(r11);                                                   \
464         tovirt(r1,r11);                                                      \
465         rlwinm  r9,r9,0,14,12;          /* clear MSR_WE (necessary?)       */\
466         stw     r0,GPR0(r11);                                                \
467         SAVE_4GPRS(3, r11);                                                  \
468         SAVE_2GPRS(7, r11)
469
470 /*
471  * Exception prolog for machine check exceptions.  This is similar to
472  * the critical exception prolog, except that machine check exceptions
473  * have their own save area.  For Book E processors, we also have a
474  * reserved register (SPRG6) that is only used in machine check exceptions
475  * so we can free up a GPR to use as the base for indirect access to the
476  * machine check exception save area.  This is necessary since the MMU
477  * is always on and the save area is offset from KERNELBASE.
478  */
479 #define MCHECK_EXCEPTION_PROLOG                                      \
480         mtspr   SPRG6W,r8;              /* SPRG6 used in machine checks */   \
481         lis     r8,mcheck_save@ha;                                           \
482         stw     r10,mcheck_r10@l(r8);                                        \
483         stw     r11,mcheck_r11@l(r8);                                        \
484         mfspr   r10,SPRG0;                                                   \
485         stw     r10,mcheck_sprg0@l(r8);                                      \
486         mfspr   r10,SPRG1;                                                   \
487         stw     r10,mcheck_sprg1@l(r8);                                      \
488         mfspr   r10,SPRG4R;                                                  \
489         stw     r10,mcheck_sprg4@l(r8);                                      \
490         mfspr   r10,SPRG5R;                                                  \
491         stw     r10,mcheck_sprg5@l(r8);                                      \
492         mfspr   r10,SPRG7R;                                                  \
493         stw     r10,mcheck_sprg7@l(r8);                                      \
494         mfspr   r10,SPRN_PID;                                                \
495         stw     r10,mcheck_pid@l(r8);                                        \
496         mfspr   r10,SRR0;                                                    \
497         stw     r10,mcheck_srr0@l(r8);                                       \
498         mfspr   r10,SRR1;                                                    \
499         stw     r10,mcheck_srr1@l(r8);                                       \
500         mfspr   r10,CSRR0;                                                   \
501         stw     r10,mcheck_csrr0@l(r8);                                      \
502         mfspr   r10,CSRR1;                                                   \
503         stw     r10,mcheck_csrr1@l(r8);                                      \
504         mfspr   r8,SPRG6R;              /* SPRG6 used in machine checks */   \
505         mfcr    r10;                    /* save CR in r10 for now          */\
506         mfspr   r11,SPRN_MCSRR1;        /* check whether user or kernel    */\
507         andi.   r11,r11,MSR_PR;                                              \
508         lis     r11,mcheck_stack_top@h;                                      \
509         ori     r11,r11,mcheck_stack_top@l;                                  \
510         beq     1f;                                                          \
511         /* COMING FROM USER MODE */                                          \
512         mfspr   r11,SPRG3;              /* if from user, start at top of   */\
513         lwz     r11,THREAD_INFO-THREAD(r11); /* this thread's kernel stack */\
514         addi    r11,r11,THREAD_SIZE;                                         \
515 1:      subi    r11,r11,INT_FRAME_SIZE; /* Allocate an exception frame     */\
516         stw     r10,_CCR(r11);          /* save various registers          */\
517         stw     r12,GPR12(r11);                                              \
518         stw     r9,GPR9(r11);                                                \
519         mflr    r10;                                                         \
520         stw     r10,_LINK(r11);                                              \
521         mfspr   r12,SPRN_DEAR;          /* save DEAR and ESR in the frame  */\
522         stw     r12,_DEAR(r11);         /* since they may have had stuff   */\
523         mfspr   r9,SPRN_ESR;            /* in them at the point where the  */\
524         stw     r9,_ESR(r11);           /* exception was taken             */\
525         mfspr   r12,MCSRR0;                                                  \
526         stw     r1,GPR1(r11);                                                \
527         mfspr   r9,MCSRR1;                                                   \
528         stw     r1,0(r11);                                                   \
529         tovirt(r1,r11);                                                      \
530         rlwinm  r9,r9,0,14,12;          /* clear MSR_WE (necessary?)       */\
531         stw     r0,GPR0(r11);                                                \
532         SAVE_4GPRS(3, r11);                                                  \
533         SAVE_2GPRS(7, r11)
534
535 /*
536  * Exception vectors.
537  */
538 #define START_EXCEPTION(label)                                               \
539         .align 5;                                                            \
540 label:
541
542 #define FINISH_EXCEPTION(func)                                  \
543         bl      transfer_to_handler_full;                       \
544         .long   func;                                           \
545         .long   ret_from_except_full
546
547 #define EXCEPTION(n, label, hdlr, xfer)                         \
548         START_EXCEPTION(label);                                 \
549         NORMAL_EXCEPTION_PROLOG;                                \
550         addi    r3,r1,STACK_FRAME_OVERHEAD;                     \
551         xfer(n, hdlr)
552
553 #define CRITICAL_EXCEPTION(n, label, hdlr)                      \
554         START_EXCEPTION(label);                                 \
555         CRITICAL_EXCEPTION_PROLOG;                              \
556         addi    r3,r1,STACK_FRAME_OVERHEAD;                     \
557         EXC_XFER_TEMPLATE(hdlr, n+2, (MSR_KERNEL & ~(MSR_ME|MSR_DE|MSR_CE)), \
558                           NOCOPY, transfer_to_handler_full, \
559                           ret_from_except_full)
560
561 #define MCHECK_EXCEPTION(n, label, hdlr)                        \
562         START_EXCEPTION(label);                                 \
563         MCHECK_EXCEPTION_PROLOG;                                \
564         mfspr   r5,SPRN_ESR;                                    \
565         stw     r5,_ESR(r11);                                   \
566         addi    r3,r1,STACK_FRAME_OVERHEAD;                     \
567         EXC_XFER_TEMPLATE(hdlr, n+2, (MSR_KERNEL & ~(MSR_ME|MSR_DE|MSR_CE)), \
568                           NOCOPY, mcheck_transfer_to_handler,   \
569                           ret_from_mcheck_exc)
570
571 #define EXC_XFER_TEMPLATE(hdlr, trap, msr, copyee, tfer, ret)   \
572         li      r10,trap;                                       \
573         stw     r10,TRAP(r11);                                  \
574         lis     r10,msr@h;                                      \
575         ori     r10,r10,msr@l;                                  \
576         copyee(r10, r9);                                        \
577         bl      tfer;                                           \
578         .long   hdlr;                                           \
579         .long   ret
580
581 #define COPY_EE(d, s)           rlwimi d,s,0,16,16
582 #define NOCOPY(d, s)
583
584 #define EXC_XFER_STD(n, hdlr)           \
585         EXC_XFER_TEMPLATE(hdlr, n, MSR_KERNEL, NOCOPY, transfer_to_handler_full, \
586                           ret_from_except_full)
587
588 #define EXC_XFER_LITE(n, hdlr)          \
589         EXC_XFER_TEMPLATE(hdlr, n+1, MSR_KERNEL, NOCOPY, transfer_to_handler, \
590                           ret_from_except)
591
592 #define EXC_XFER_EE(n, hdlr)            \
593         EXC_XFER_TEMPLATE(hdlr, n, MSR_KERNEL, COPY_EE, transfer_to_handler_full, \
594                           ret_from_except_full)
595
596 #define EXC_XFER_EE_LITE(n, hdlr)       \
597         EXC_XFER_TEMPLATE(hdlr, n+1, MSR_KERNEL, COPY_EE, transfer_to_handler, \
598                           ret_from_except)
599
600 interrupt_base:
601         /* Critical Input Interrupt */
602         CRITICAL_EXCEPTION(0x0100, CriticalInput, UnknownException)
603
604         /* Machine Check Interrupt */
605         MCHECK_EXCEPTION(0x0200, MachineCheck, MachineCheckException)
606
607         /* Data Storage Interrupt */
608         START_EXCEPTION(DataStorage)
609         mtspr   SPRG0, r10              /* Save some working registers */
610         mtspr   SPRG1, r11
611         mtspr   SPRG4W, r12
612         mtspr   SPRG5W, r13
613         mfcr    r11
614         mtspr   SPRG7W, r11
615
616         /*
617          * Check if it was a store fault, if not then bail
618          * because a user tried to access a kernel or
619          * read-protected page.  Otherwise, get the
620          * offending address and handle it.
621          */
622         mfspr   r10, SPRN_ESR
623         andis.  r10, r10, ESR_ST@h
624         beq     2f
625
626         mfspr   r10, SPRN_DEAR          /* Get faulting address */
627
628         /* If we are faulting a kernel address, we have to use the
629          * kernel page tables.
630          */
631         lis     r11, TASK_SIZE@h
632         ori     r11, r11, TASK_SIZE@l
633         cmplw   0, r10, r11
634         bge     2f
635
636         /* Get the PGD for the current thread */
637 3:
638         mfspr   r11,SPRG3
639         lwz     r11,PGDIR(r11)
640 4:
641         rlwimi  r11, r10, 12, 20, 29    /* Create L1 (pgdir/pmd) address */
642         lwz     r11, 0(r11)             /* Get L1 entry */
643         rlwinm. r12, r11, 0, 0, 19      /* Extract L2 (pte) base address */
644         beq     2f                      /* Bail if no table */
645
646         rlwimi  r12, r10, 22, 20, 29    /* Compute PTE address */
647         lwz     r11, 0(r12)             /* Get Linux PTE */
648
649         /* Are _PAGE_USER & _PAGE_RW set & _PAGE_HWWRITE not? */
650         andi.   r13, r11, _PAGE_RW|_PAGE_USER|_PAGE_HWWRITE
651         cmpwi   0, r13, _PAGE_RW|_PAGE_USER
652         bne     2f                      /* Bail if not */
653
654         /* Update 'changed'. */
655         ori     r11, r11, _PAGE_DIRTY|_PAGE_ACCESSED|_PAGE_HWWRITE
656         stw     r11, 0(r12)             /* Update Linux page table */
657
658         /* MAS2 not updated as the entry does exist in the tlb, this
659            fault taken to detect state transition (eg: COW -> DIRTY)
660          */
661         lis     r12, MAS3_RPN@h
662         ori     r12, r12, _PAGE_HWEXEC | MAS3_RPN@l
663         and     r11, r11, r12
664         rlwimi  r11, r11, 31, 27, 27    /* SX <- _PAGE_HWEXEC */
665         ori     r11, r11, (MAS3_UW|MAS3_SW|MAS3_UR|MAS3_SR)@l /* set static perms */
666
667         /* update search PID in MAS6, AS = 0 */
668         mfspr   r12, SPRN_PID0
669         slwi    r12, r12, 16
670         mtspr   SPRN_MAS6, r12
671
672         /* find the TLB index that caused the fault.  It has to be here. */
673         tlbsx   0, r10
674
675         mtspr   SPRN_MAS3,r11
676         tlbwe
677
678         /* Done...restore registers and get out of here.  */
679         mfspr   r11, SPRG7R
680         mtcr    r11
681         mfspr   r13, SPRG5R
682         mfspr   r12, SPRG4R
683         mfspr   r11, SPRG1
684         mfspr   r10, SPRG0
685         rfi                     /* Force context change */
686
687 2:
688         /*
689          * The bailout.  Restore registers to pre-exception conditions
690          * and call the heavyweights to help us out.
691          */
692         mfspr   r11, SPRG7R
693         mtcr    r11
694         mfspr   r13, SPRG5R
695         mfspr   r12, SPRG4R
696         mfspr   r11, SPRG1
697         mfspr   r10, SPRG0
698         b       data_access
699
700         /* Instruction Storage Interrupt */
701         START_EXCEPTION(InstructionStorage)
702         NORMAL_EXCEPTION_PROLOG
703         mfspr   r5,SPRN_ESR             /* Grab the ESR and save it */
704         stw     r5,_ESR(r11)
705         mr      r4,r12                  /* Pass SRR0 as arg2 */
706         li      r5,0                    /* Pass zero as arg3 */
707         EXC_XFER_EE_LITE(0x0400, handle_page_fault)
708
709         /* External Input Interrupt */
710         EXCEPTION(0x0500, ExternalInput, do_IRQ, EXC_XFER_LITE)
711
712         /* Alignment Interrupt */
713         START_EXCEPTION(Alignment)
714         NORMAL_EXCEPTION_PROLOG
715         mfspr   r4,SPRN_DEAR            /* Grab the DEAR and save it */
716         stw     r4,_DEAR(r11)
717         addi    r3,r1,STACK_FRAME_OVERHEAD
718         EXC_XFER_EE(0x0600, AlignmentException)
719
720         /* Program Interrupt */
721         START_EXCEPTION(Program)
722         NORMAL_EXCEPTION_PROLOG
723         mfspr   r4,SPRN_ESR             /* Grab the ESR and save it */
724         stw     r4,_ESR(r11)
725         addi    r3,r1,STACK_FRAME_OVERHEAD
726         EXC_XFER_STD(0x0700, ProgramCheckException)
727
728         /* Floating Point Unavailable Interrupt */
729         EXCEPTION(0x0800, FloatingPointUnavailable, UnknownException, EXC_XFER_EE)
730
731         /* System Call Interrupt */
732         START_EXCEPTION(SystemCall)
733         NORMAL_EXCEPTION_PROLOG
734         EXC_XFER_EE_LITE(0x0c00, DoSyscall)
735
736         /* Auxillary Processor Unavailable Interrupt */
737         EXCEPTION(0x2900, AuxillaryProcessorUnavailable, UnknownException, EXC_XFER_EE)
738
739         /* Decrementer Interrupt */
740         START_EXCEPTION(Decrementer)
741         NORMAL_EXCEPTION_PROLOG
742         lis     r0,TSR_DIS@h            /* Setup the DEC interrupt mask */
743         mtspr   SPRN_TSR,r0             /* Clear the DEC interrupt */
744         addi    r3,r1,STACK_FRAME_OVERHEAD
745         EXC_XFER_LITE(0x0900, timer_interrupt)
746
747         /* Fixed Internal Timer Interrupt */
748         /* TODO: Add FIT support */
749         EXCEPTION(0x3100, FixedIntervalTimer, UnknownException, EXC_XFER_EE)
750
751         /* Watchdog Timer Interrupt */
752         /* TODO: Add watchdog support */
753         CRITICAL_EXCEPTION(0x3200, WatchdogTimer, UnknownException)
754
755         /* Data TLB Error Interrupt */
756         START_EXCEPTION(DataTLBError)
757         mtspr   SPRG0, r10              /* Save some working registers */
758         mtspr   SPRG1, r11
759         mtspr   SPRG4W, r12
760         mtspr   SPRG5W, r13
761         mfcr    r11
762         mtspr   SPRG7W, r11
763         mfspr   r10, SPRN_DEAR          /* Get faulting address */
764
765         /* If we are faulting a kernel address, we have to use the
766          * kernel page tables.
767          */
768         lis     r11, TASK_SIZE@h
769         ori     r11, r11, TASK_SIZE@l
770         cmplw   5, r10, r11
771         blt     5, 3f
772         lis     r11, swapper_pg_dir@h
773         ori     r11, r11, swapper_pg_dir@l
774
775         mfspr   r12,SPRN_MAS1           /* Set TID to 0 */
776         li      r13,MAS1_TID@l
777         andc    r12,r12,r13
778         mtspr   SPRN_MAS1,r12
779
780         b       4f
781
782         /* Get the PGD for the current thread */
783 3:
784         mfspr   r11,SPRG3
785         lwz     r11,PGDIR(r11)
786
787 4:
788         rlwimi  r11, r10, 12, 20, 29    /* Create L1 (pgdir/pmd) address */
789         lwz     r11, 0(r11)             /* Get L1 entry */
790         rlwinm. r12, r11, 0, 0, 19      /* Extract L2 (pte) base address */
791         beq     2f                      /* Bail if no table */
792
793         rlwimi  r12, r10, 22, 20, 29    /* Compute PTE address */
794         lwz     r11, 0(r12)             /* Get Linux PTE */
795         andi.   r13, r11, _PAGE_PRESENT
796         beq     2f
797
798         ori     r11, r11, _PAGE_ACCESSED
799         stw     r11, 0(r12)
800
801          /* Jump to common tlb load */
802         b       finish_tlb_load
803 2:
804         /* The bailout.  Restore registers to pre-exception conditions
805          * and call the heavyweights to help us out.
806          */
807         mfspr   r11, SPRG7R
808         mtcr    r11
809         mfspr   r13, SPRG5R
810         mfspr   r12, SPRG4R
811         mfspr   r11, SPRG1
812         mfspr   r10, SPRG0
813         b       data_access
814
815         /* Instruction TLB Error Interrupt */
816         /*
817          * Nearly the same as above, except we get our
818          * information from different registers and bailout
819          * to a different point.
820          */
821         START_EXCEPTION(InstructionTLBError)
822         mtspr   SPRG0, r10              /* Save some working registers */
823         mtspr   SPRG1, r11
824         mtspr   SPRG4W, r12
825         mtspr   SPRG5W, r13
826         mfcr    r11
827         mtspr   SPRG7W, r11
828         mfspr   r10, SRR0               /* Get faulting address */
829
830         /* If we are faulting a kernel address, we have to use the
831          * kernel page tables.
832          */
833         lis     r11, TASK_SIZE@h
834         ori     r11, r11, TASK_SIZE@l
835         cmplw   5, r10, r11
836         blt     5, 3f
837         lis     r11, swapper_pg_dir@h
838         ori     r11, r11, swapper_pg_dir@l
839
840         mfspr   r12,SPRN_MAS1           /* Set TID to 0 */
841         li      r13,MAS1_TID@l
842         andc    r12,r12,r13
843         mtspr   SPRN_MAS1,r12
844
845         b       4f
846
847         /* Get the PGD for the current thread */
848 3:
849         mfspr   r11,SPRG3
850         lwz     r11,PGDIR(r11)
851
852 4:
853         rlwimi  r11, r10, 12, 20, 29    /* Create L1 (pgdir/pmd) address */
854         lwz     r11, 0(r11)             /* Get L1 entry */
855         rlwinm. r12, r11, 0, 0, 19      /* Extract L2 (pte) base address */
856         beq     2f                      /* Bail if no table */
857
858         rlwimi  r12, r10, 22, 20, 29    /* Compute PTE address */
859         lwz     r11, 0(r12)             /* Get Linux PTE */
860         andi.   r13, r11, _PAGE_PRESENT
861         beq     2f
862
863         ori     r11, r11, _PAGE_ACCESSED
864         stw     r11, 0(r12)
865
866         /* Jump to common TLB load point */
867         b       finish_tlb_load
868
869 2:
870         /* The bailout.  Restore registers to pre-exception conditions
871          * and call the heavyweights to help us out.
872          */
873         mfspr   r11, SPRG7R
874         mtcr    r11
875         mfspr   r13, SPRG5R
876         mfspr   r12, SPRG4R
877         mfspr   r11, SPRG1
878         mfspr   r10, SPRG0
879         b       InstructionStorage
880
881 #ifdef CONFIG_SPE
882         /* SPE Unavailable */
883         START_EXCEPTION(SPEUnavailable)
884         NORMAL_EXCEPTION_PROLOG
885         bne     load_up_spe
886         addi    r3,r1,STACK_FRAME_OVERHEAD
887         EXC_XFER_EE_LITE(0x2010, KernelSPE)
888 #else
889         EXCEPTION(0x2020, SPEUnavailable, UnknownException, EXC_XFER_EE)
890 #endif /* CONFIG_SPE */
891
892         /* SPE Floating Point Data */
893 #ifdef CONFIG_SPE
894         EXCEPTION(0x2030, SPEFloatingPointData, SPEFloatingPointException, EXC_XFER_EE);
895 #else
896         EXCEPTION(0x2040, SPEFloatingPointData, UnknownException, EXC_XFER_EE)
897 #endif /* CONFIG_SPE */
898
899         /* SPE Floating Point Round */
900         EXCEPTION(0x2050, SPEFloatingPointRound, UnknownException, EXC_XFER_EE)
901
902         /* Performance Monitor */
903         EXCEPTION(0x2060, PerformanceMonitor, UnknownException, EXC_XFER_EE)
904
905 /* Check for a single step debug exception while in an exception
906  * handler before state has been saved.  This is to catch the case
907  * where an instruction that we are trying to single step causes
908  * an exception (eg ITLB/DTLB miss) and thus the first instruction of
909  * the exception handler generates a single step debug exception.
910  *
911  * If we get a debug trap on the first instruction of an exception handler,
912  * we reset the MSR_DE in the _exception handler's_ MSR (the debug trap is
913  * a critical exception, so we are using SPRN_CSRR1 to manipulate the MSR).
914  * The exception handler was handling a non-critical interrupt, so it will
915  * save (and later restore) the MSR via SPRN_SRR1, which will still have
916  * the MSR_DE bit set.
917  */
918         /* Debug Interrupt */
919         START_EXCEPTION(Debug)
920         CRITICAL_EXCEPTION_PROLOG
921
922         /*
923          * If this is a single step or branch-taken exception in an
924          * exception entry sequence, it was probably meant to apply to
925          * the code where the exception occurred (since exception entry
926          * doesn't turn off DE automatically).  We simulate the effect
927          * of turning off DE on entry to an exception handler by turning
928          * off DE in the CSRR1 value and clearing the debug status.
929          */
930         mfspr   r10,SPRN_DBSR           /* check single-step/branch taken */
931         andis.  r10,r10,(DBSR_IC|DBSR_BT)@h
932         beq+    1f
933         andi.   r0,r9,MSR_PR            /* check supervisor */
934         beq     2f                      /* branch if we need to fix it up... */
935
936         /* continue normal handling for a critical exception... */
937 1:      mfspr   r4,SPRN_DBSR
938         addi    r3,r1,STACK_FRAME_OVERHEAD
939         EXC_XFER_TEMPLATE(DebugException, 0x2002, \
940                 (MSR_KERNEL & ~(MSR_ME|MSR_DE|MSR_CE)), \
941                 NOCOPY, crit_transfer_to_handler, ret_from_crit_exc)
942
943         /* here it looks like we got an inappropriate debug exception. */
944 2:      rlwinm  r9,r9,0,~MSR_DE         /* clear DE in the CSRR1 value */
945         mtspr   SPRN_DBSR,r10           /* clear the IC/BT debug intr status */
946         /* restore state and get out */
947         lwz     r10,_CCR(r11)
948         lwz     r0,GPR0(r11)
949         lwz     r1,GPR1(r11)
950         mtcrf   0x80,r10
951         mtspr   CSRR0,r12
952         mtspr   CSRR1,r9
953         lwz     r9,GPR9(r11)
954
955         mtspr   SPRG2,r8;               /* SPRG2 only used in criticals */
956         lis     r8,crit_save@ha;
957         lwz     r10,crit_r10@l(r8)
958         lwz     r11,crit_r11@l(r8)
959         mfspr   r8,SPRG2
960
961         rfci
962         b       .
963
964 /*
965  * Local functions
966  */
967         /*
968          * Data TLB exceptions will bail out to this point
969          * if they can't resolve the lightweight TLB fault.
970          */
971 data_access:
972         NORMAL_EXCEPTION_PROLOG
973         mfspr   r5,SPRN_ESR             /* Grab the ESR, save it, pass arg3 */
974         stw     r5,_ESR(r11)
975         mfspr   r4,SPRN_DEAR            /* Grab the DEAR, save it, pass arg2 */
976         andis.  r10,r5,(ESR_ILK|ESR_DLK)@h
977         bne     1f
978         EXC_XFER_EE_LITE(0x0300, handle_page_fault)
979 1:
980         addi    r3,r1,STACK_FRAME_OVERHEAD
981         EXC_XFER_EE_LITE(0x0300, CacheLockingException)
982
983 /*
984
985  * Both the instruction and data TLB miss get to this
986  * point to load the TLB.
987  *      r10 - EA of fault
988  *      r11 - TLB (info from Linux PTE)
989  *      r12, r13 - available to use
990  *      CR5 - results of addr < TASK_SIZE
991  *      MAS0, MAS1 - loaded with proper value when we get here
992  *      MAS2, MAS3 - will need additional info from Linux PTE
993  *      Upon exit, we reload everything and RFI.
994  */
995 finish_tlb_load:
996         /*
997          * We set execute, because we don't have the granularity to
998          * properly set this at the page level (Linux problem).
999          * Many of these bits are software only.  Bits we don't set
1000          * here we (properly should) assume have the appropriate value.
1001          */
1002
1003         mfspr   r12, SPRN_MAS2
1004         rlwimi  r12, r11, 26, 27, 31    /* extract WIMGE from pte */
1005         mtspr   SPRN_MAS2, r12
1006
1007         bge     5, 1f
1008
1009         /* addr > TASK_SIZE */
1010         li      r10, (MAS3_UX | MAS3_UW | MAS3_UR)
1011         andi.   r13, r11, (_PAGE_USER | _PAGE_HWWRITE | _PAGE_HWEXEC)
1012         andi.   r12, r11, _PAGE_USER    /* Test for _PAGE_USER */
1013         iseleq  r12, 0, r10
1014         and     r10, r12, r13
1015         srwi    r12, r10, 1
1016         or      r12, r12, r10   /* Copy user perms into supervisor */
1017         b       2f
1018
1019         /* addr <= TASK_SIZE */
1020 1:      rlwinm  r12, r11, 31, 29, 29    /* Extract _PAGE_HWWRITE into SW */
1021         ori     r12, r12, (MAS3_SX | MAS3_SR)
1022
1023 2:      rlwimi  r11, r12, 0, 20, 31     /* Extract RPN from PTE and merge with perms */
1024         mtspr   SPRN_MAS3, r11
1025         tlbwe
1026
1027         /* Done...restore registers and get out of here.  */
1028         mfspr   r11, SPRG7R
1029         mtcr    r11
1030         mfspr   r13, SPRG5R
1031         mfspr   r12, SPRG4R
1032         mfspr   r11, SPRG1
1033         mfspr   r10, SPRG0
1034         rfi                                     /* Force context change */
1035
1036 #ifdef CONFIG_SPE
1037 /* Note that the SPE support is closely modeled after the AltiVec
1038  * support.  Changes to one are likely to be applicable to the
1039  * other!  */
1040 load_up_spe:
1041 /*
1042  * Disable SPE for the task which had SPE previously,
1043  * and save its SPE registers in its thread_struct.
1044  * Enables SPE for use in the kernel on return.
1045  * On SMP we know the SPE units are free, since we give it up every
1046  * switch.  -- Kumar
1047  */
1048         mfmsr   r5
1049         oris    r5,r5,MSR_SPE@h
1050         mtmsr   r5                      /* enable use of SPE now */
1051         isync
1052 /*
1053  * For SMP, we don't do lazy SPE switching because it just gets too
1054  * horrendously complex, especially when a task switches from one CPU
1055  * to another.  Instead we call giveup_spe in switch_to.
1056  */
1057 #ifndef CONFIG_SMP
1058         lis     r3,last_task_used_spe@ha
1059         lwz     r4,last_task_used_spe@l(r3)
1060         cmpi    0,r4,0
1061         beq     1f
1062         addi    r4,r4,THREAD    /* want THREAD of last_task_used_spe */
1063         SAVE_32EVR(0,r10,r4)
1064         evxor   evr10, evr10, evr10     /* clear out evr10 */
1065         evmwumiaa evr10, evr10, evr10   /* evr10 <- ACC = 0 * 0 + ACC */
1066         li      r5,THREAD_ACC
1067         evstddx evr10, r4, r5           /* save off accumulator */
1068         lwz     r5,PT_REGS(r4)
1069         lwz     r4,_MSR-STACK_FRAME_OVERHEAD(r5)
1070         lis     r10,MSR_SPE@h
1071         andc    r4,r4,r10       /* disable SPE for previous task */
1072         stw     r4,_MSR-STACK_FRAME_OVERHEAD(r5)
1073 1:
1074 #endif /* CONFIG_SMP */
1075         /* enable use of SPE after return */
1076         oris    r9,r9,MSR_SPE@h
1077         mfspr   r5,SPRG3                /* current task's THREAD (phys) */
1078         li      r4,1
1079         li      r10,THREAD_ACC
1080         stw     r4,THREAD_USED_SPE(r5)
1081         evlddx  evr4,r10,r5
1082         evmra   evr4,evr4
1083         REST_32EVR(0,r10,r5)
1084 #ifndef CONFIG_SMP
1085         subi    r4,r5,THREAD
1086         stw     r4,last_task_used_spe@l(r3)
1087 #endif /* CONFIG_SMP */
1088         /* restore registers and return */
1089 2:      REST_4GPRS(3, r11)
1090         lwz     r10,_CCR(r11)
1091         REST_GPR(1, r11)
1092         mtcr    r10
1093         lwz     r10,_LINK(r11)
1094         mtlr    r10
1095         REST_GPR(10, r11)
1096         mtspr   SRR1,r9
1097         mtspr   SRR0,r12
1098         REST_GPR(9, r11)
1099         REST_GPR(12, r11)
1100         lwz     r11,GPR11(r11)
1101         SYNC
1102         rfi
1103
1104
1105
1106 /*
1107  * SPE unavailable trap from kernel - print a message, but let
1108  * the task use SPE in the kernel until it returns to user mode.
1109  */
1110 KernelSPE:
1111         lwz     r3,_MSR(r1)
1112         oris    r3,r3,MSR_SPE@h
1113         stw     r3,_MSR(r1)     /* enable use of SPE after return */
1114         lis     r3,87f@h
1115         ori     r3,r3,87f@l
1116         mr      r4,r2           /* current */
1117         lwz     r5,_NIP(r1)
1118         bl      printk
1119         b       ret_from_except
1120 87:     .string "SPE used in kernel  (task=%p, pc=%x)  \n"
1121         .align  4,0
1122
1123 #endif /* CONFIG_SPE */
1124
1125 /*
1126  * Global functions
1127  */
1128
1129 /*
1130  * extern void loadcam_entry(unsigned int index)
1131  *
1132  * Load TLBCAM[index] entry in to the L2 CAM MMU
1133  */
1134 _GLOBAL(loadcam_entry)
1135         lis     r4,TLBCAM@ha
1136         addi    r4,r4,TLBCAM@l
1137         mulli   r5,r3,20
1138         add     r3,r5,r4
1139         lwz     r4,0(r3)
1140         mtspr   SPRN_MAS0,r4
1141         lwz     r4,4(r3)
1142         mtspr   SPRN_MAS1,r4
1143         lwz     r4,8(r3)
1144         mtspr   SPRN_MAS2,r4
1145         lwz     r4,12(r3)
1146         mtspr   SPRN_MAS3,r4
1147         tlbwe
1148         isync
1149         blr
1150
1151 /*
1152  * extern void giveup_altivec(struct task_struct *prev)
1153  *
1154  * The e500 core does not have an AltiVec unit.
1155  */
1156 _GLOBAL(giveup_altivec)
1157         blr
1158
1159 #ifdef CONFIG_SPE
1160 /*
1161  * extern void giveup_spe(struct task_struct *prev)
1162  *
1163  */
1164 _GLOBAL(giveup_spe)
1165         mfmsr   r5
1166         oris    r5,r5,MSR_SPE@h
1167         SYNC
1168         mtmsr   r5                      /* enable use of SPE now */
1169         isync
1170         cmpi    0,r3,0
1171         beqlr-                          /* if no previous owner, done */
1172         addi    r3,r3,THREAD            /* want THREAD of task */
1173         lwz     r5,PT_REGS(r3)
1174         cmpi    0,r5,0
1175         SAVE_32EVR(0, r4, r3)
1176         evxor   evr6, evr6, evr6        /* clear out evr6 */
1177         evmwumiaa evr6, evr6, evr6      /* evr6 <- ACC = 0 * 0 + ACC */
1178         li      r4,THREAD_ACC
1179         evstddx evr6, r4, r3            /* save off accumulator */
1180         beq     1f
1181         lwz     r4,_MSR-STACK_FRAME_OVERHEAD(r5)
1182         lis     r3,MSR_SPE@h
1183         andc    r4,r4,r3                /* disable SPE for previous task */
1184         stw     r4,_MSR-STACK_FRAME_OVERHEAD(r5)
1185 1:
1186 #ifndef CONFIG_SMP
1187         li      r5,0
1188         lis     r4,last_task_used_spe@ha
1189         stw     r5,last_task_used_spe@l(r4)
1190 #endif /* CONFIG_SMP */
1191         blr
1192 #endif /* CONFIG_SPE */
1193
1194 /*
1195  * extern void giveup_fpu(struct task_struct *prev)
1196  *
1197  * The e500 core does not have an FPU.
1198  */
1199 _GLOBAL(giveup_fpu)
1200         blr
1201
1202 /*
1203  * extern void abort(void)
1204  *
1205  * At present, this routine just applies a system reset.
1206  */
1207 _GLOBAL(abort)
1208         li      r13,0
1209         mtspr   SPRN_DBCR0,r13          /* disable all debug events */
1210         mfmsr   r13
1211         ori     r13,r13,MSR_DE@l        /* Enable Debug Events */
1212         mtmsr   r13
1213         mfspr   r13,SPRN_DBCR0
1214         lis     r13,(DBCR0_IDM|DBCR0_RST_CHIP)@h
1215         mtspr   SPRN_DBCR0,r13
1216
1217 _GLOBAL(set_context)
1218
1219 #ifdef CONFIG_BDI_SWITCH
1220         /* Context switch the PTE pointer for the Abatron BDI2000.
1221          * The PGDIR is the second parameter.
1222          */
1223         lis     r5, abatron_pteptrs@h
1224         ori     r5, r5, abatron_pteptrs@l
1225         stw     r4, 0x4(r5)
1226 #endif
1227         mtspr   SPRN_PID,r3
1228         isync                   /* Force context change */
1229         blr
1230
1231 /*
1232  * We put a few things here that have to be page-aligned. This stuff
1233  * goes at the beginning of the data segment, which is page-aligned.
1234  */
1235         .data
1236 _GLOBAL(sdata)
1237 _GLOBAL(empty_zero_page)
1238         .space  4096
1239 _GLOBAL(swapper_pg_dir)
1240         .space  4096
1241
1242         .section .bss
1243 /* Stack for handling critical exceptions from kernel mode */
1244 critical_stack_bottom:
1245         .space 4096
1246 critical_stack_top:
1247         .previous
1248
1249 /* Stack for handling machine check exceptions from kernel mode */
1250 mcheck_stack_bottom:
1251         .space 4096
1252 mcheck_stack_top:
1253         .previous
1254
1255 /*
1256  * This area is used for temporarily saving registers during the
1257  * critical and machine check exception prologs. It must always
1258  * follow the page aligned allocations, so it starts on a page
1259  * boundary, ensuring that all crit_save areas are in a single
1260  * page.
1261  */
1262
1263 /* crit_save */
1264 _GLOBAL(crit_save)
1265         .space  4
1266 _GLOBAL(crit_r10)
1267         .space  4
1268 _GLOBAL(crit_r11)
1269         .space  4
1270 _GLOBAL(crit_sprg0)
1271         .space  4
1272 _GLOBAL(crit_sprg1)
1273         .space  4
1274 _GLOBAL(crit_sprg4)
1275         .space  4
1276 _GLOBAL(crit_sprg5)
1277         .space  4
1278 _GLOBAL(crit_sprg7)
1279         .space  4
1280 _GLOBAL(crit_pid)
1281         .space  4
1282 _GLOBAL(crit_srr0)
1283         .space  4
1284 _GLOBAL(crit_srr1)
1285         .space  4
1286
1287 /* mcheck_save */
1288 _GLOBAL(mcheck_save)
1289         .space  4
1290 _GLOBAL(mcheck_r10)
1291         .space  4
1292 _GLOBAL(mcheck_r11)
1293         .space  4
1294 _GLOBAL(mcheck_sprg0)
1295         .space  4
1296 _GLOBAL(mcheck_sprg1)
1297         .space  4
1298 _GLOBAL(mcheck_sprg4)
1299         .space  4
1300 _GLOBAL(mcheck_sprg5)
1301         .space  4
1302 _GLOBAL(mcheck_sprg7)
1303         .space  4
1304 _GLOBAL(mcheck_pid)
1305         .space  4
1306 _GLOBAL(mcheck_srr0)
1307         .space  4
1308 _GLOBAL(mcheck_srr1)
1309         .space  4
1310 _GLOBAL(mcheck_csrr0)
1311         .space  4
1312 _GLOBAL(mcheck_csrr1)
1313         .space  4
1314
1315 /*
1316  * This space gets a copy of optional info passed to us by the bootstrap
1317  * which is used to pass parameters into the kernel like root=/dev/sda1, etc.
1318  */
1319 _GLOBAL(cmd_line)
1320         .space  512
1321
1322 /*
1323  * Room for two PTE pointers, usually the kernel and current user pointers
1324  * to their respective root page table.
1325  */
1326 abatron_pteptrs:
1327         .space  8
1328
1329