]> Pileus Git - ~andy/linux/blob - arch/powerpc/kernel/exceptions-64e.S
Merge tag 'efi-urgent' into x86/urgent
[~andy/linux] / arch / powerpc / kernel / exceptions-64e.S
1 /*
2  *  Boot code and exception vectors for Book3E processors
3  *
4  *  Copyright (C) 2007 Ben. Herrenschmidt (benh@kernel.crashing.org), IBM Corp.
5  *
6  *  This program is free software; you can redistribute it and/or
7  *  modify it under the terms of the GNU General Public License
8  *  as published by the Free Software Foundation; either version
9  *  2 of the License, or (at your option) any later version.
10  */
11
12 #include <linux/threads.h>
13 #include <asm/reg.h>
14 #include <asm/page.h>
15 #include <asm/ppc_asm.h>
16 #include <asm/asm-offsets.h>
17 #include <asm/cputable.h>
18 #include <asm/setup.h>
19 #include <asm/thread_info.h>
20 #include <asm/reg_a2.h>
21 #include <asm/exception-64e.h>
22 #include <asm/bug.h>
23 #include <asm/irqflags.h>
24 #include <asm/ptrace.h>
25 #include <asm/ppc-opcode.h>
26 #include <asm/mmu.h>
27 #include <asm/hw_irq.h>
28 #include <asm/kvm_asm.h>
29 #include <asm/kvm_booke_hv_asm.h>
30
31 /* XXX This will ultimately add space for a special exception save
32  *     structure used to save things like SRR0/SRR1, SPRGs, MAS, etc...
33  *     when taking special interrupts. For now we don't support that,
34  *     special interrupts from within a non-standard level will probably
35  *     blow you up
36  */
37 #define SPECIAL_EXC_FRAME_SIZE  INT_FRAME_SIZE
38
39 /* Exception prolog code for all exceptions */
40 #define EXCEPTION_PROLOG(n, intnum, type, addition)                         \
41         mtspr   SPRN_SPRG_##type##_SCRATCH,r13; /* get spare registers */   \
42         mfspr   r13,SPRN_SPRG_PACA;     /* get PACA */                      \
43         std     r10,PACA_EX##type+EX_R10(r13);                              \
44         std     r11,PACA_EX##type+EX_R11(r13);                              \
45         PROLOG_STORE_RESTORE_SCRATCH_##type;                                \
46         mfcr    r10;                    /* save CR */                       \
47         mfspr   r11,SPRN_##type##_SRR1;/* what are we coming from */        \
48         DO_KVM  intnum,SPRN_##type##_SRR1;    /* KVM hook */                \
49         stw     r10,PACA_EX##type+EX_CR(r13); /* save old CR in the PACA */ \
50         addition;                       /* additional code for that exc. */ \
51         std     r1,PACA_EX##type+EX_R1(r13); /* save old r1 in the PACA */  \
52         type##_SET_KSTACK;              /* get special stack if necessary */\
53         andi.   r10,r11,MSR_PR;         /* save stack pointer */            \
54         beq     1f;                     /* branch around if supervisor */   \
55         ld      r1,PACAKSAVE(r13);      /* get kernel stack coming from usr */\
56 1:      cmpdi   cr1,r1,0;               /* check if SP makes sense */       \
57         bge-    cr1,exc_##n##_bad_stack;/* bad stack (TODO: out of line) */ \
58         mfspr   r10,SPRN_##type##_SRR0; /* read SRR0 before touching stack */
59
60 /* Exception type-specific macros */
61 #define GEN_SET_KSTACK                                                      \
62         subi    r1,r1,INT_FRAME_SIZE;   /* alloc frame on kernel stack */
63 #define SPRN_GEN_SRR0   SPRN_SRR0
64 #define SPRN_GEN_SRR1   SPRN_SRR1
65
66 #define GDBELL_SET_KSTACK       GEN_SET_KSTACK
67 #define SPRN_GDBELL_SRR0        SPRN_GSRR0
68 #define SPRN_GDBELL_SRR1        SPRN_GSRR1
69
70 #define CRIT_SET_KSTACK                                                     \
71         ld      r1,PACA_CRIT_STACK(r13);                                    \
72         subi    r1,r1,SPECIAL_EXC_FRAME_SIZE;
73 #define SPRN_CRIT_SRR0  SPRN_CSRR0
74 #define SPRN_CRIT_SRR1  SPRN_CSRR1
75
76 #define DBG_SET_KSTACK                                                      \
77         ld      r1,PACA_DBG_STACK(r13);                                     \
78         subi    r1,r1,SPECIAL_EXC_FRAME_SIZE;
79 #define SPRN_DBG_SRR0   SPRN_DSRR0
80 #define SPRN_DBG_SRR1   SPRN_DSRR1
81
82 #define MC_SET_KSTACK                                                       \
83         ld      r1,PACA_MC_STACK(r13);                                      \
84         subi    r1,r1,SPECIAL_EXC_FRAME_SIZE;
85 #define SPRN_MC_SRR0    SPRN_MCSRR0
86 #define SPRN_MC_SRR1    SPRN_MCSRR1
87
88 #define NORMAL_EXCEPTION_PROLOG(n, intnum, addition)                        \
89         EXCEPTION_PROLOG(n, intnum, GEN, addition##_GEN(n))
90
91 #define CRIT_EXCEPTION_PROLOG(n, intnum, addition)                          \
92         EXCEPTION_PROLOG(n, intnum, CRIT, addition##_CRIT(n))
93
94 #define DBG_EXCEPTION_PROLOG(n, intnum, addition)                           \
95         EXCEPTION_PROLOG(n, intnum, DBG, addition##_DBG(n))
96
97 #define MC_EXCEPTION_PROLOG(n, intnum, addition)                            \
98         EXCEPTION_PROLOG(n, intnum, MC, addition##_MC(n))
99
100 #define GDBELL_EXCEPTION_PROLOG(n, intnum, addition)                        \
101         EXCEPTION_PROLOG(n, intnum, GDBELL, addition##_GDBELL(n))
102
103 /*
104  * Store user-visible scratch in PACA exception slots and restore proper value
105  */
106 #define PROLOG_STORE_RESTORE_SCRATCH_GEN
107 #define PROLOG_STORE_RESTORE_SCRATCH_GDBELL
108 #define PROLOG_STORE_RESTORE_SCRATCH_DBG
109 #define PROLOG_STORE_RESTORE_SCRATCH_MC
110
111 #define PROLOG_STORE_RESTORE_SCRATCH_CRIT                                   \
112         mfspr   r10,SPRN_SPRG_CRIT_SCRATCH;     /* get r13 */               \
113         std     r10,PACA_EXCRIT+EX_R13(r13);                                \
114         ld      r11,PACA_SPRG3(r13);                                        \
115         mtspr   SPRN_SPRG_CRIT_SCRATCH,r11;
116
117 /* Variants of the "addition" argument for the prolog
118  */
119 #define PROLOG_ADDITION_NONE_GEN(n)
120 #define PROLOG_ADDITION_NONE_GDBELL(n)
121 #define PROLOG_ADDITION_NONE_CRIT(n)
122 #define PROLOG_ADDITION_NONE_DBG(n)
123 #define PROLOG_ADDITION_NONE_MC(n)
124
125 #define PROLOG_ADDITION_MASKABLE_GEN(n)                                     \
126         lbz     r10,PACASOFTIRQEN(r13); /* are irqs soft-disabled ? */      \
127         cmpwi   cr0,r10,0;              /* yes -> go out of line */         \
128         beq     masked_interrupt_book3e_##n
129
130 #define PROLOG_ADDITION_2REGS_GEN(n)                                        \
131         std     r14,PACA_EXGEN+EX_R14(r13);                                 \
132         std     r15,PACA_EXGEN+EX_R15(r13)
133
134 #define PROLOG_ADDITION_1REG_GEN(n)                                         \
135         std     r14,PACA_EXGEN+EX_R14(r13);
136
137 #define PROLOG_ADDITION_2REGS_CRIT(n)                                       \
138         std     r14,PACA_EXCRIT+EX_R14(r13);                                \
139         std     r15,PACA_EXCRIT+EX_R15(r13)
140
141 #define PROLOG_ADDITION_2REGS_DBG(n)                                        \
142         std     r14,PACA_EXDBG+EX_R14(r13);                                 \
143         std     r15,PACA_EXDBG+EX_R15(r13)
144
145 #define PROLOG_ADDITION_2REGS_MC(n)                                         \
146         std     r14,PACA_EXMC+EX_R14(r13);                                  \
147         std     r15,PACA_EXMC+EX_R15(r13)
148
149
150 /* Core exception code for all exceptions except TLB misses.
151  * XXX: Needs to make SPRN_SPRG_GEN depend on exception type
152  */
153 #define EXCEPTION_COMMON(n, excf, ints)                                     \
154 exc_##n##_common:                                                           \
155         std     r0,GPR0(r1);            /* save r0 in stackframe */         \
156         std     r2,GPR2(r1);            /* save r2 in stackframe */         \
157         SAVE_4GPRS(3, r1);              /* save r3 - r6 in stackframe */    \
158         SAVE_2GPRS(7, r1);              /* save r7, r8 in stackframe */     \
159         std     r9,GPR9(r1);            /* save r9 in stackframe */         \
160         std     r10,_NIP(r1);           /* save SRR0 to stackframe */       \
161         std     r11,_MSR(r1);           /* save SRR1 to stackframe */       \
162         beq     2f;                     /* if from kernel mode */           \
163         ACCOUNT_CPU_USER_ENTRY(r10,r11);/* accounting (uses cr0+eq) */      \
164 2:      ld      r3,excf+EX_R10(r13);    /* get back r10 */                  \
165         ld      r4,excf+EX_R11(r13);    /* get back r11 */                  \
166         mfspr   r5,SPRN_SPRG_GEN_SCRATCH;/* get back r13 */                 \
167         std     r12,GPR12(r1);          /* save r12 in stackframe */        \
168         ld      r2,PACATOC(r13);        /* get kernel TOC into r2 */        \
169         mflr    r6;                     /* save LR in stackframe */         \
170         mfctr   r7;                     /* save CTR in stackframe */        \
171         mfspr   r8,SPRN_XER;            /* save XER in stackframe */        \
172         ld      r9,excf+EX_R1(r13);     /* load orig r1 back from PACA */   \
173         lwz     r10,excf+EX_CR(r13);    /* load orig CR back from PACA  */  \
174         lbz     r11,PACASOFTIRQEN(r13); /* get current IRQ softe */         \
175         ld      r12,exception_marker@toc(r2);                               \
176         li      r0,0;                                                       \
177         std     r3,GPR10(r1);           /* save r10 to stackframe */        \
178         std     r4,GPR11(r1);           /* save r11 to stackframe */        \
179         std     r5,GPR13(r1);           /* save it to stackframe */         \
180         std     r6,_LINK(r1);                                               \
181         std     r7,_CTR(r1);                                                \
182         std     r8,_XER(r1);                                                \
183         li      r3,(n)+1;               /* indicate partial regs in trap */ \
184         std     r9,0(r1);               /* store stack frame back link */   \
185         std     r10,_CCR(r1);           /* store orig CR in stackframe */   \
186         std     r9,GPR1(r1);            /* store stack frame back link */   \
187         std     r11,SOFTE(r1);          /* and save it to stackframe */     \
188         std     r12,STACK_FRAME_OVERHEAD-16(r1); /* mark the frame */       \
189         std     r3,_TRAP(r1);           /* set trap number              */  \
190         std     r0,RESULT(r1);          /* clear regs->result */            \
191         ints;
192
193 /* Variants for the "ints" argument. This one does nothing when we want
194  * to keep interrupts in their original state
195  */
196 #define INTS_KEEP
197
198 /* This second version is meant for exceptions that don't immediately
199  * hard-enable. We set a bit in paca->irq_happened to ensure that
200  * a subsequent call to arch_local_irq_restore() will properly
201  * hard-enable and avoid the fast-path, and then reconcile irq state.
202  */
203 #define INTS_DISABLE    RECONCILE_IRQ_STATE(r3,r4)
204
205 /* This is called by exceptions that used INTS_KEEP (that did not touch
206  * irq indicators in the PACA). This will restore MSR:EE to it's previous
207  * value
208  *
209  * XXX In the long run, we may want to open-code it in order to separate the
210  *     load from the wrtee, thus limiting the latency caused by the dependency
211  *     but at this point, I'll favor code clarity until we have a near to final
212  *     implementation
213  */
214 #define INTS_RESTORE_HARD                                                   \
215         ld      r11,_MSR(r1);                                               \
216         wrtee   r11;
217
218 /* XXX FIXME: Restore r14/r15 when necessary */
219 #define BAD_STACK_TRAMPOLINE(n)                                             \
220 exc_##n##_bad_stack:                                                        \
221         li      r1,(n);                 /* get exception number */          \
222         sth     r1,PACA_TRAP_SAVE(r13); /* store trap */                    \
223         b       bad_stack_book3e;       /* bad stack error */
224
225 /* WARNING: If you change the layout of this stub, make sure you chcek
226         *   the debug exception handler which handles single stepping
227         *   into exceptions from userspace, and the MM code in
228         *   arch/powerpc/mm/tlb_nohash.c which patches the branch here
229         *   and would need to be updated if that branch is moved
230         */
231 #define EXCEPTION_STUB(loc, label)                                      \
232         . = interrupt_base_book3e + loc;                                \
233         nop;    /* To make debug interrupts happy */                    \
234         b       exc_##label##_book3e;
235
236 #define ACK_NONE(r)
237 #define ACK_DEC(r)                                                      \
238         lis     r,TSR_DIS@h;                                            \
239         mtspr   SPRN_TSR,r
240 #define ACK_FIT(r)                                                      \
241         lis     r,TSR_FIS@h;                                            \
242         mtspr   SPRN_TSR,r
243
244 /* Used by asynchronous interrupt that may happen in the idle loop.
245  *
246  * This check if the thread was in the idle loop, and if yes, returns
247  * to the caller rather than the PC. This is to avoid a race if
248  * interrupts happen before the wait instruction.
249  */
250 #define CHECK_NAPPING()                                                 \
251         CURRENT_THREAD_INFO(r11, r1);                                   \
252         ld      r10,TI_LOCAL_FLAGS(r11);                                \
253         andi.   r9,r10,_TLF_NAPPING;                                    \
254         beq+    1f;                                                     \
255         ld      r8,_LINK(r1);                                           \
256         rlwinm  r7,r10,0,~_TLF_NAPPING;                                 \
257         std     r8,_NIP(r1);                                            \
258         std     r7,TI_LOCAL_FLAGS(r11);                                 \
259 1:
260
261
262 #define MASKABLE_EXCEPTION(trapnum, intnum, label, hdlr, ack)           \
263         START_EXCEPTION(label);                                         \
264         NORMAL_EXCEPTION_PROLOG(trapnum, intnum, PROLOG_ADDITION_MASKABLE)\
265         EXCEPTION_COMMON(trapnum, PACA_EXGEN, INTS_DISABLE)             \
266         ack(r8);                                                        \
267         CHECK_NAPPING();                                                \
268         addi    r3,r1,STACK_FRAME_OVERHEAD;                             \
269         bl      hdlr;                                                   \
270         b       .ret_from_except_lite;
271
272 /* This value is used to mark exception frames on the stack. */
273         .section        ".toc","aw"
274 exception_marker:
275         .tc     ID_EXC_MARKER[TC],STACK_FRAME_REGS_MARKER
276
277
278 /*
279  * And here we have the exception vectors !
280  */
281
282         .text
283         .balign 0x1000
284         .globl interrupt_base_book3e
285 interrupt_base_book3e:                                  /* fake trap */
286         EXCEPTION_STUB(0x000, machine_check)            /* 0x0200 */
287         EXCEPTION_STUB(0x020, critical_input)           /* 0x0580 */
288         EXCEPTION_STUB(0x040, debug_crit)               /* 0x0d00 */
289         EXCEPTION_STUB(0x060, data_storage)             /* 0x0300 */
290         EXCEPTION_STUB(0x080, instruction_storage)      /* 0x0400 */
291         EXCEPTION_STUB(0x0a0, external_input)           /* 0x0500 */
292         EXCEPTION_STUB(0x0c0, alignment)                /* 0x0600 */
293         EXCEPTION_STUB(0x0e0, program)                  /* 0x0700 */
294         EXCEPTION_STUB(0x100, fp_unavailable)           /* 0x0800 */
295         EXCEPTION_STUB(0x120, system_call)              /* 0x0c00 */
296         EXCEPTION_STUB(0x140, ap_unavailable)           /* 0x0f20 */
297         EXCEPTION_STUB(0x160, decrementer)              /* 0x0900 */
298         EXCEPTION_STUB(0x180, fixed_interval)           /* 0x0980 */
299         EXCEPTION_STUB(0x1a0, watchdog)                 /* 0x09f0 */
300         EXCEPTION_STUB(0x1c0, data_tlb_miss)
301         EXCEPTION_STUB(0x1e0, instruction_tlb_miss)
302         EXCEPTION_STUB(0x200, altivec_unavailable)      /* 0x0f20 */
303         EXCEPTION_STUB(0x220, altivec_assist)           /* 0x1700 */
304         EXCEPTION_STUB(0x260, perfmon)
305         EXCEPTION_STUB(0x280, doorbell)
306         EXCEPTION_STUB(0x2a0, doorbell_crit)
307         EXCEPTION_STUB(0x2c0, guest_doorbell)
308         EXCEPTION_STUB(0x2e0, guest_doorbell_crit)
309         EXCEPTION_STUB(0x300, hypercall)
310         EXCEPTION_STUB(0x320, ehpriv)
311         EXCEPTION_STUB(0x340, lrat_error)
312
313         .globl interrupt_end_book3e
314 interrupt_end_book3e:
315
316 /* Critical Input Interrupt */
317         START_EXCEPTION(critical_input);
318         CRIT_EXCEPTION_PROLOG(0x100, BOOKE_INTERRUPT_CRITICAL,
319                               PROLOG_ADDITION_NONE)
320 //      EXCEPTION_COMMON(0x100, PACA_EXCRIT, INTS_DISABLE)
321 //      bl      special_reg_save_crit
322 //      CHECK_NAPPING();
323 //      addi    r3,r1,STACK_FRAME_OVERHEAD
324 //      bl      .critical_exception
325 //      b       ret_from_crit_except
326         b       .
327
328 /* Machine Check Interrupt */
329         START_EXCEPTION(machine_check);
330         MC_EXCEPTION_PROLOG(0x200, BOOKE_INTERRUPT_MACHINE_CHECK,
331                             PROLOG_ADDITION_NONE)
332 //      EXCEPTION_COMMON(0x200, PACA_EXMC, INTS_DISABLE)
333 //      bl      special_reg_save_mc
334 //      addi    r3,r1,STACK_FRAME_OVERHEAD
335 //      CHECK_NAPPING();
336 //      bl      .machine_check_exception
337 //      b       ret_from_mc_except
338         b       .
339
340 /* Data Storage Interrupt */
341         START_EXCEPTION(data_storage)
342         NORMAL_EXCEPTION_PROLOG(0x300, BOOKE_INTERRUPT_DATA_STORAGE,
343                                 PROLOG_ADDITION_2REGS)
344         mfspr   r14,SPRN_DEAR
345         mfspr   r15,SPRN_ESR
346         EXCEPTION_COMMON(0x300, PACA_EXGEN, INTS_DISABLE)
347         b       storage_fault_common
348
349 /* Instruction Storage Interrupt */
350         START_EXCEPTION(instruction_storage);
351         NORMAL_EXCEPTION_PROLOG(0x400, BOOKE_INTERRUPT_INST_STORAGE,
352                                 PROLOG_ADDITION_2REGS)
353         li      r15,0
354         mr      r14,r10
355         EXCEPTION_COMMON(0x400, PACA_EXGEN, INTS_DISABLE)
356         b       storage_fault_common
357
358 /* External Input Interrupt */
359         MASKABLE_EXCEPTION(0x500, BOOKE_INTERRUPT_EXTERNAL,
360                            external_input, .do_IRQ, ACK_NONE)
361
362 /* Alignment */
363         START_EXCEPTION(alignment);
364         NORMAL_EXCEPTION_PROLOG(0x600, BOOKE_INTERRUPT_ALIGNMENT,
365                                 PROLOG_ADDITION_2REGS)
366         mfspr   r14,SPRN_DEAR
367         mfspr   r15,SPRN_ESR
368         EXCEPTION_COMMON(0x600, PACA_EXGEN, INTS_KEEP)
369         b       alignment_more  /* no room, go out of line */
370
371 /* Program Interrupt */
372         START_EXCEPTION(program);
373         NORMAL_EXCEPTION_PROLOG(0x700, BOOKE_INTERRUPT_PROGRAM,
374                                 PROLOG_ADDITION_1REG)
375         mfspr   r14,SPRN_ESR
376         EXCEPTION_COMMON(0x700, PACA_EXGEN, INTS_DISABLE)
377         std     r14,_DSISR(r1)
378         addi    r3,r1,STACK_FRAME_OVERHEAD
379         ld      r14,PACA_EXGEN+EX_R14(r13)
380         bl      .save_nvgprs
381         bl      .program_check_exception
382         b       .ret_from_except
383
384 /* Floating Point Unavailable Interrupt */
385         START_EXCEPTION(fp_unavailable);
386         NORMAL_EXCEPTION_PROLOG(0x800, BOOKE_INTERRUPT_FP_UNAVAIL,
387                                 PROLOG_ADDITION_NONE)
388         /* we can probably do a shorter exception entry for that one... */
389         EXCEPTION_COMMON(0x800, PACA_EXGEN, INTS_KEEP)
390         ld      r12,_MSR(r1)
391         andi.   r0,r12,MSR_PR;
392         beq-    1f
393         bl      .load_up_fpu
394         b       fast_exception_return
395 1:      INTS_DISABLE
396         bl      .save_nvgprs
397         addi    r3,r1,STACK_FRAME_OVERHEAD
398         bl      .kernel_fp_unavailable_exception
399         b       .ret_from_except
400
401 /* Altivec Unavailable Interrupt */
402         START_EXCEPTION(altivec_unavailable);
403         NORMAL_EXCEPTION_PROLOG(0x200, BOOKE_INTERRUPT_SPE_ALTIVEC_UNAVAIL,
404                                 PROLOG_ADDITION_NONE)
405         /* we can probably do a shorter exception entry for that one... */
406         EXCEPTION_COMMON(0x200, PACA_EXGEN, INTS_KEEP)
407 #ifdef CONFIG_ALTIVEC
408 BEGIN_FTR_SECTION
409         ld      r12,_MSR(r1)
410         andi.   r0,r12,MSR_PR;
411         beq-    1f
412         bl      .load_up_altivec
413         b       fast_exception_return
414 1:
415 END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
416 #endif
417         INTS_DISABLE
418         bl      .save_nvgprs
419         addi    r3,r1,STACK_FRAME_OVERHEAD
420         bl      .altivec_unavailable_exception
421         b       .ret_from_except
422
423 /* AltiVec Assist */
424         START_EXCEPTION(altivec_assist);
425         NORMAL_EXCEPTION_PROLOG(0x220,
426                                 BOOKE_INTERRUPT_SPE_FP_DATA_ALTIVEC_ASSIST,
427                                 PROLOG_ADDITION_NONE)
428         EXCEPTION_COMMON(0x220, PACA_EXGEN, INTS_DISABLE)
429         bl      .save_nvgprs
430         addi    r3,r1,STACK_FRAME_OVERHEAD
431 #ifdef CONFIG_ALTIVEC
432 BEGIN_FTR_SECTION
433         bl      .altivec_assist_exception
434 END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
435 #else
436         bl      .unknown_exception
437 #endif
438         b       .ret_from_except
439
440
441 /* Decrementer Interrupt */
442         MASKABLE_EXCEPTION(0x900, BOOKE_INTERRUPT_DECREMENTER,
443                            decrementer, .timer_interrupt, ACK_DEC)
444
445 /* Fixed Interval Timer Interrupt */
446         MASKABLE_EXCEPTION(0x980, BOOKE_INTERRUPT_FIT,
447                            fixed_interval, .unknown_exception, ACK_FIT)
448
449 /* Watchdog Timer Interrupt */
450         START_EXCEPTION(watchdog);
451         CRIT_EXCEPTION_PROLOG(0x9f0, BOOKE_INTERRUPT_WATCHDOG,
452                               PROLOG_ADDITION_NONE)
453 //      EXCEPTION_COMMON(0x9f0, PACA_EXCRIT, INTS_DISABLE)
454 //      bl      special_reg_save_crit
455 //      CHECK_NAPPING();
456 //      addi    r3,r1,STACK_FRAME_OVERHEAD
457 //      bl      .unknown_exception
458 //      b       ret_from_crit_except
459         b       .
460
461 /* System Call Interrupt */
462         START_EXCEPTION(system_call)
463         mr      r9,r13                  /* keep a copy of userland r13 */
464         mfspr   r11,SPRN_SRR0           /* get return address */
465         mfspr   r12,SPRN_SRR1           /* get previous MSR */
466         mfspr   r13,SPRN_SPRG_PACA      /* get our PACA */
467         b       system_call_common
468
469 /* Auxiliary Processor Unavailable Interrupt */
470         START_EXCEPTION(ap_unavailable);
471         NORMAL_EXCEPTION_PROLOG(0xf20, BOOKE_INTERRUPT_AP_UNAVAIL,
472                                 PROLOG_ADDITION_NONE)
473         EXCEPTION_COMMON(0xf20, PACA_EXGEN, INTS_DISABLE)
474         bl      .save_nvgprs
475         addi    r3,r1,STACK_FRAME_OVERHEAD
476         bl      .unknown_exception
477         b       .ret_from_except
478
479 /* Debug exception as a critical interrupt*/
480         START_EXCEPTION(debug_crit);
481         CRIT_EXCEPTION_PROLOG(0xd00, BOOKE_INTERRUPT_DEBUG,
482                               PROLOG_ADDITION_2REGS)
483
484         /*
485          * If there is a single step or branch-taken exception in an
486          * exception entry sequence, it was probably meant to apply to
487          * the code where the exception occurred (since exception entry
488          * doesn't turn off DE automatically).  We simulate the effect
489          * of turning off DE on entry to an exception handler by turning
490          * off DE in the CSRR1 value and clearing the debug status.
491          */
492
493         mfspr   r14,SPRN_DBSR           /* check single-step/branch taken */
494         andis.  r15,r14,(DBSR_IC|DBSR_BT)@h
495         beq+    1f
496
497         LOAD_REG_IMMEDIATE(r14,interrupt_base_book3e)
498         LOAD_REG_IMMEDIATE(r15,interrupt_end_book3e)
499         cmpld   cr0,r10,r14
500         cmpld   cr1,r10,r15
501         blt+    cr0,1f
502         bge+    cr1,1f
503
504         /* here it looks like we got an inappropriate debug exception. */
505         lis     r14,(DBSR_IC|DBSR_BT)@h         /* clear the event */
506         rlwinm  r11,r11,0,~MSR_DE       /* clear DE in the CSRR1 value */
507         mtspr   SPRN_DBSR,r14
508         mtspr   SPRN_CSRR1,r11
509         lwz     r10,PACA_EXCRIT+EX_CR(r13)      /* restore registers */
510         ld      r1,PACA_EXCRIT+EX_R1(r13)
511         ld      r14,PACA_EXCRIT+EX_R14(r13)
512         ld      r15,PACA_EXCRIT+EX_R15(r13)
513         mtcr    r10
514         ld      r10,PACA_EXCRIT+EX_R10(r13)     /* restore registers */
515         ld      r11,PACA_EXCRIT+EX_R11(r13)
516         ld      r13,PACA_EXCRIT+EX_R13(r13)
517         rfci
518
519         /* Normal debug exception */
520         /* XXX We only handle coming from userspace for now since we can't
521          *     quite save properly an interrupted kernel state yet
522          */
523 1:      andi.   r14,r11,MSR_PR;         /* check for userspace again */
524         beq     kernel_dbg_exc;         /* if from kernel mode */
525
526         /* Now we mash up things to make it look like we are coming on a
527          * normal exception
528          */
529         ld      r15,PACA_EXCRIT+EX_R13(r13)
530         mtspr   SPRN_SPRG_GEN_SCRATCH,r15
531         mfspr   r14,SPRN_DBSR
532         EXCEPTION_COMMON(0xd00, PACA_EXCRIT, INTS_DISABLE)
533         std     r14,_DSISR(r1)
534         addi    r3,r1,STACK_FRAME_OVERHEAD
535         mr      r4,r14
536         ld      r14,PACA_EXCRIT+EX_R14(r13)
537         ld      r15,PACA_EXCRIT+EX_R15(r13)
538         bl      .save_nvgprs
539         bl      .DebugException
540         b       .ret_from_except
541
542 kernel_dbg_exc:
543         b       .       /* NYI */
544
545 /* Debug exception as a debug interrupt*/
546         START_EXCEPTION(debug_debug);
547         DBG_EXCEPTION_PROLOG(0xd00, BOOKE_INTERRUPT_DEBUG,
548                                                  PROLOG_ADDITION_2REGS)
549
550         /*
551          * If there is a single step or branch-taken exception in an
552          * exception entry sequence, it was probably meant to apply to
553          * the code where the exception occurred (since exception entry
554          * doesn't turn off DE automatically).  We simulate the effect
555          * of turning off DE on entry to an exception handler by turning
556          * off DE in the DSRR1 value and clearing the debug status.
557          */
558
559         mfspr   r14,SPRN_DBSR           /* check single-step/branch taken */
560         andis.  r15,r14,(DBSR_IC|DBSR_BT)@h
561         beq+    1f
562
563         LOAD_REG_IMMEDIATE(r14,interrupt_base_book3e)
564         LOAD_REG_IMMEDIATE(r15,interrupt_end_book3e)
565         cmpld   cr0,r10,r14
566         cmpld   cr1,r10,r15
567         blt+    cr0,1f
568         bge+    cr1,1f
569
570         /* here it looks like we got an inappropriate debug exception. */
571         lis     r14,(DBSR_IC|DBSR_BT)@h         /* clear the event */
572         rlwinm  r11,r11,0,~MSR_DE       /* clear DE in the DSRR1 value */
573         mtspr   SPRN_DBSR,r14
574         mtspr   SPRN_DSRR1,r11
575         lwz     r10,PACA_EXDBG+EX_CR(r13)       /* restore registers */
576         ld      r1,PACA_EXDBG+EX_R1(r13)
577         ld      r14,PACA_EXDBG+EX_R14(r13)
578         ld      r15,PACA_EXDBG+EX_R15(r13)
579         mtcr    r10
580         ld      r10,PACA_EXDBG+EX_R10(r13)      /* restore registers */
581         ld      r11,PACA_EXDBG+EX_R11(r13)
582         mfspr   r13,SPRN_SPRG_DBG_SCRATCH
583         rfdi
584
585         /* Normal debug exception */
586         /* XXX We only handle coming from userspace for now since we can't
587          *     quite save properly an interrupted kernel state yet
588          */
589 1:      andi.   r14,r11,MSR_PR;         /* check for userspace again */
590         beq     kernel_dbg_exc;         /* if from kernel mode */
591
592         /* Now we mash up things to make it look like we are coming on a
593          * normal exception
594          */
595         mfspr   r15,SPRN_SPRG_DBG_SCRATCH
596         mtspr   SPRN_SPRG_GEN_SCRATCH,r15
597         mfspr   r14,SPRN_DBSR
598         EXCEPTION_COMMON(0xd08, PACA_EXDBG, INTS_DISABLE)
599         std     r14,_DSISR(r1)
600         addi    r3,r1,STACK_FRAME_OVERHEAD
601         mr      r4,r14
602         ld      r14,PACA_EXDBG+EX_R14(r13)
603         ld      r15,PACA_EXDBG+EX_R15(r13)
604         bl      .save_nvgprs
605         bl      .DebugException
606         b       .ret_from_except
607
608         START_EXCEPTION(perfmon);
609         NORMAL_EXCEPTION_PROLOG(0x260, BOOKE_INTERRUPT_PERFORMANCE_MONITOR,
610                                 PROLOG_ADDITION_NONE)
611         EXCEPTION_COMMON(0x260, PACA_EXGEN, INTS_DISABLE)
612         CHECK_NAPPING()
613         addi    r3,r1,STACK_FRAME_OVERHEAD
614         bl      .performance_monitor_exception
615         b       .ret_from_except_lite
616
617 /* Doorbell interrupt */
618         MASKABLE_EXCEPTION(0x280, BOOKE_INTERRUPT_DOORBELL,
619                            doorbell, .doorbell_exception, ACK_NONE)
620
621 /* Doorbell critical Interrupt */
622         START_EXCEPTION(doorbell_crit);
623         CRIT_EXCEPTION_PROLOG(0x2a0, BOOKE_INTERRUPT_DOORBELL_CRITICAL,
624                               PROLOG_ADDITION_NONE)
625 //      EXCEPTION_COMMON(0x2a0, PACA_EXCRIT, INTS_DISABLE)
626 //      bl      special_reg_save_crit
627 //      CHECK_NAPPING();
628 //      addi    r3,r1,STACK_FRAME_OVERHEAD
629 //      bl      .doorbell_critical_exception
630 //      b       ret_from_crit_except
631         b       .
632
633 /*
634  *      Guest doorbell interrupt
635  *      This general exception use GSRRx save/restore registers
636  */
637         START_EXCEPTION(guest_doorbell);
638         GDBELL_EXCEPTION_PROLOG(0x2c0, BOOKE_INTERRUPT_GUEST_DBELL,
639                                 PROLOG_ADDITION_NONE)
640         EXCEPTION_COMMON(0x2c0, PACA_EXGEN, INTS_KEEP)
641         addi    r3,r1,STACK_FRAME_OVERHEAD
642         bl      .save_nvgprs
643         INTS_RESTORE_HARD
644         bl      .unknown_exception
645         b       .ret_from_except
646
647 /* Guest Doorbell critical Interrupt */
648         START_EXCEPTION(guest_doorbell_crit);
649         CRIT_EXCEPTION_PROLOG(0x2e0, BOOKE_INTERRUPT_GUEST_DBELL_CRIT,
650                               PROLOG_ADDITION_NONE)
651 //      EXCEPTION_COMMON(0x2e0, PACA_EXCRIT, INTS_DISABLE)
652 //      bl      special_reg_save_crit
653 //      CHECK_NAPPING();
654 //      addi    r3,r1,STACK_FRAME_OVERHEAD
655 //      bl      .guest_doorbell_critical_exception
656 //      b       ret_from_crit_except
657         b       .
658
659 /* Hypervisor call */
660         START_EXCEPTION(hypercall);
661         NORMAL_EXCEPTION_PROLOG(0x310, BOOKE_INTERRUPT_HV_SYSCALL,
662                                 PROLOG_ADDITION_NONE)
663         EXCEPTION_COMMON(0x310, PACA_EXGEN, INTS_KEEP)
664         addi    r3,r1,STACK_FRAME_OVERHEAD
665         bl      .save_nvgprs
666         INTS_RESTORE_HARD
667         bl      .unknown_exception
668         b       .ret_from_except
669
670 /* Embedded Hypervisor priviledged  */
671         START_EXCEPTION(ehpriv);
672         NORMAL_EXCEPTION_PROLOG(0x320, BOOKE_INTERRUPT_HV_PRIV,
673                                 PROLOG_ADDITION_NONE)
674         EXCEPTION_COMMON(0x320, PACA_EXGEN, INTS_KEEP)
675         addi    r3,r1,STACK_FRAME_OVERHEAD
676         bl      .save_nvgprs
677         INTS_RESTORE_HARD
678         bl      .unknown_exception
679         b       .ret_from_except
680
681 /* LRAT Error interrupt */
682         START_EXCEPTION(lrat_error);
683         NORMAL_EXCEPTION_PROLOG(0x340, BOOKE_INTERRUPT_LRAT_ERROR,
684                                 PROLOG_ADDITION_NONE)
685         EXCEPTION_COMMON(0x340, PACA_EXGEN, INTS_KEEP)
686         addi    r3,r1,STACK_FRAME_OVERHEAD
687         bl      .save_nvgprs
688         INTS_RESTORE_HARD
689         bl      .unknown_exception
690         b       .ret_from_except
691
692 /*
693  * An interrupt came in while soft-disabled; We mark paca->irq_happened
694  * accordingly and if the interrupt is level sensitive, we hard disable
695  */
696
697 .macro masked_interrupt_book3e paca_irq full_mask
698         lbz     r10,PACAIRQHAPPENED(r13)
699         ori     r10,r10,\paca_irq
700         stb     r10,PACAIRQHAPPENED(r13)
701
702         .if \full_mask == 1
703         rldicl  r10,r11,48,1            /* clear MSR_EE */
704         rotldi  r11,r10,16
705         mtspr   SPRN_SRR1,r11
706         .endif
707
708         lwz     r11,PACA_EXGEN+EX_CR(r13)
709         mtcr    r11
710         ld      r10,PACA_EXGEN+EX_R10(r13)
711         ld      r11,PACA_EXGEN+EX_R11(r13)
712         mfspr   r13,SPRN_SPRG_GEN_SCRATCH
713         rfi
714         b       .
715 .endm
716
717 masked_interrupt_book3e_0x500:
718         // XXX When adding support for EPR, use PACA_IRQ_EE_EDGE
719         masked_interrupt_book3e PACA_IRQ_EE 1
720
721 masked_interrupt_book3e_0x900:
722         ACK_DEC(r10);
723         masked_interrupt_book3e PACA_IRQ_DEC 0
724
725 masked_interrupt_book3e_0x980:
726         ACK_FIT(r10);
727         masked_interrupt_book3e PACA_IRQ_DEC 0
728
729 masked_interrupt_book3e_0x280:
730 masked_interrupt_book3e_0x2c0:
731         masked_interrupt_book3e PACA_IRQ_DBELL 0
732
733 /*
734  * Called from arch_local_irq_enable when an interrupt needs
735  * to be resent. r3 contains either 0x500,0x900,0x260 or 0x280
736  * to indicate the kind of interrupt. MSR:EE is already off.
737  * We generate a stackframe like if a real interrupt had happened.
738  *
739  * Note: While MSR:EE is off, we need to make sure that _MSR
740  * in the generated frame has EE set to 1 or the exception
741  * handler will not properly re-enable them.
742  */
743 _GLOBAL(__replay_interrupt)
744         /* We are going to jump to the exception common code which
745          * will retrieve various register values from the PACA which
746          * we don't give a damn about.
747          */
748         mflr    r10
749         mfmsr   r11
750         mfcr    r4
751         mtspr   SPRN_SPRG_GEN_SCRATCH,r13;
752         std     r1,PACA_EXGEN+EX_R1(r13);
753         stw     r4,PACA_EXGEN+EX_CR(r13);
754         ori     r11,r11,MSR_EE
755         subi    r1,r1,INT_FRAME_SIZE;
756         cmpwi   cr0,r3,0x500
757         beq     exc_0x500_common
758         cmpwi   cr0,r3,0x900
759         beq     exc_0x900_common
760         cmpwi   cr0,r3,0x280
761         beq     exc_0x280_common
762         blr
763
764
765 /*
766  * This is called from 0x300 and 0x400 handlers after the prologs with
767  * r14 and r15 containing the fault address and error code, with the
768  * original values stashed away in the PACA
769  */
770 storage_fault_common:
771         std     r14,_DAR(r1)
772         std     r15,_DSISR(r1)
773         addi    r3,r1,STACK_FRAME_OVERHEAD
774         mr      r4,r14
775         mr      r5,r15
776         ld      r14,PACA_EXGEN+EX_R14(r13)
777         ld      r15,PACA_EXGEN+EX_R15(r13)
778         bl      .do_page_fault
779         cmpdi   r3,0
780         bne-    1f
781         b       .ret_from_except_lite
782 1:      bl      .save_nvgprs
783         mr      r5,r3
784         addi    r3,r1,STACK_FRAME_OVERHEAD
785         ld      r4,_DAR(r1)
786         bl      .bad_page_fault
787         b       .ret_from_except
788
789 /*
790  * Alignment exception doesn't fit entirely in the 0x100 bytes so it
791  * continues here.
792  */
793 alignment_more:
794         std     r14,_DAR(r1)
795         std     r15,_DSISR(r1)
796         addi    r3,r1,STACK_FRAME_OVERHEAD
797         ld      r14,PACA_EXGEN+EX_R14(r13)
798         ld      r15,PACA_EXGEN+EX_R15(r13)
799         bl      .save_nvgprs
800         INTS_RESTORE_HARD
801         bl      .alignment_exception
802         b       .ret_from_except
803
804 /*
805  * We branch here from entry_64.S for the last stage of the exception
806  * return code path. MSR:EE is expected to be off at that point
807  */
808 _GLOBAL(exception_return_book3e)
809         b       1f
810
811 /* This is the return from load_up_fpu fast path which could do with
812  * less GPR restores in fact, but for now we have a single return path
813  */
814         .globl fast_exception_return
815 fast_exception_return:
816         wrteei  0
817 1:      mr      r0,r13
818         ld      r10,_MSR(r1)
819         REST_4GPRS(2, r1)
820         andi.   r6,r10,MSR_PR
821         REST_2GPRS(6, r1)
822         beq     1f
823         ACCOUNT_CPU_USER_EXIT(r10, r11)
824         ld      r0,GPR13(r1)
825
826 1:      stdcx.  r0,0,r1         /* to clear the reservation */
827
828         ld      r8,_CCR(r1)
829         ld      r9,_LINK(r1)
830         ld      r10,_CTR(r1)
831         ld      r11,_XER(r1)
832         mtcr    r8
833         mtlr    r9
834         mtctr   r10
835         mtxer   r11
836         REST_2GPRS(8, r1)
837         ld      r10,GPR10(r1)
838         ld      r11,GPR11(r1)
839         ld      r12,GPR12(r1)
840         mtspr   SPRN_SPRG_GEN_SCRATCH,r0
841
842         std     r10,PACA_EXGEN+EX_R10(r13);
843         std     r11,PACA_EXGEN+EX_R11(r13);
844         ld      r10,_NIP(r1)
845         ld      r11,_MSR(r1)
846         ld      r0,GPR0(r1)
847         ld      r1,GPR1(r1)
848         mtspr   SPRN_SRR0,r10
849         mtspr   SPRN_SRR1,r11
850         ld      r10,PACA_EXGEN+EX_R10(r13)
851         ld      r11,PACA_EXGEN+EX_R11(r13)
852         mfspr   r13,SPRN_SPRG_GEN_SCRATCH
853         rfi
854
855 /*
856  * Trampolines used when spotting a bad kernel stack pointer in
857  * the exception entry code.
858  *
859  * TODO: move some bits like SRR0 read to trampoline, pass PACA
860  * index around, etc... to handle crit & mcheck
861  */
862 BAD_STACK_TRAMPOLINE(0x000)
863 BAD_STACK_TRAMPOLINE(0x100)
864 BAD_STACK_TRAMPOLINE(0x200)
865 BAD_STACK_TRAMPOLINE(0x220)
866 BAD_STACK_TRAMPOLINE(0x260)
867 BAD_STACK_TRAMPOLINE(0x280)
868 BAD_STACK_TRAMPOLINE(0x2a0)
869 BAD_STACK_TRAMPOLINE(0x2c0)
870 BAD_STACK_TRAMPOLINE(0x2e0)
871 BAD_STACK_TRAMPOLINE(0x300)
872 BAD_STACK_TRAMPOLINE(0x310)
873 BAD_STACK_TRAMPOLINE(0x320)
874 BAD_STACK_TRAMPOLINE(0x340)
875 BAD_STACK_TRAMPOLINE(0x400)
876 BAD_STACK_TRAMPOLINE(0x500)
877 BAD_STACK_TRAMPOLINE(0x600)
878 BAD_STACK_TRAMPOLINE(0x700)
879 BAD_STACK_TRAMPOLINE(0x800)
880 BAD_STACK_TRAMPOLINE(0x900)
881 BAD_STACK_TRAMPOLINE(0x980)
882 BAD_STACK_TRAMPOLINE(0x9f0)
883 BAD_STACK_TRAMPOLINE(0xa00)
884 BAD_STACK_TRAMPOLINE(0xb00)
885 BAD_STACK_TRAMPOLINE(0xc00)
886 BAD_STACK_TRAMPOLINE(0xd00)
887 BAD_STACK_TRAMPOLINE(0xd08)
888 BAD_STACK_TRAMPOLINE(0xe00)
889 BAD_STACK_TRAMPOLINE(0xf00)
890 BAD_STACK_TRAMPOLINE(0xf20)
891
892         .globl  bad_stack_book3e
893 bad_stack_book3e:
894         /* XXX: Needs to make SPRN_SPRG_GEN depend on exception type */
895         mfspr   r10,SPRN_SRR0;            /* read SRR0 before touching stack */
896         ld      r1,PACAEMERGSP(r13)
897         subi    r1,r1,64+INT_FRAME_SIZE
898         std     r10,_NIP(r1)
899         std     r11,_MSR(r1)
900         ld      r10,PACA_EXGEN+EX_R1(r13) /* FIXME for crit & mcheck */
901         lwz     r11,PACA_EXGEN+EX_CR(r13) /* FIXME for crit & mcheck */
902         std     r10,GPR1(r1)
903         std     r11,_CCR(r1)
904         mfspr   r10,SPRN_DEAR
905         mfspr   r11,SPRN_ESR
906         std     r10,_DAR(r1)
907         std     r11,_DSISR(r1)
908         std     r0,GPR0(r1);            /* save r0 in stackframe */         \
909         std     r2,GPR2(r1);            /* save r2 in stackframe */         \
910         SAVE_4GPRS(3, r1);              /* save r3 - r6 in stackframe */    \
911         SAVE_2GPRS(7, r1);              /* save r7, r8 in stackframe */     \
912         std     r9,GPR9(r1);            /* save r9 in stackframe */         \
913         ld      r3,PACA_EXGEN+EX_R10(r13);/* get back r10 */                \
914         ld      r4,PACA_EXGEN+EX_R11(r13);/* get back r11 */                \
915         mfspr   r5,SPRN_SPRG_GEN_SCRATCH;/* get back r13 XXX can be wrong */ \
916         std     r3,GPR10(r1);           /* save r10 to stackframe */        \
917         std     r4,GPR11(r1);           /* save r11 to stackframe */        \
918         std     r12,GPR12(r1);          /* save r12 in stackframe */        \
919         std     r5,GPR13(r1);           /* save it to stackframe */         \
920         mflr    r10
921         mfctr   r11
922         mfxer   r12
923         std     r10,_LINK(r1)
924         std     r11,_CTR(r1)
925         std     r12,_XER(r1)
926         SAVE_10GPRS(14,r1)
927         SAVE_8GPRS(24,r1)
928         lhz     r12,PACA_TRAP_SAVE(r13)
929         std     r12,_TRAP(r1)
930         addi    r11,r1,INT_FRAME_SIZE
931         std     r11,0(r1)
932         li      r12,0
933         std     r12,0(r11)
934         ld      r2,PACATOC(r13)
935 1:      addi    r3,r1,STACK_FRAME_OVERHEAD
936         bl      .kernel_bad_stack
937         b       1b
938
939 /*
940  * Setup the initial TLB for a core. This current implementation
941  * assume that whatever we are running off will not conflict with
942  * the new mapping at PAGE_OFFSET.
943  */
944 _GLOBAL(initial_tlb_book3e)
945
946         /* Look for the first TLB with IPROT set */
947         mfspr   r4,SPRN_TLB0CFG
948         andi.   r3,r4,TLBnCFG_IPROT
949         lis     r3,MAS0_TLBSEL(0)@h
950         bne     found_iprot
951
952         mfspr   r4,SPRN_TLB1CFG
953         andi.   r3,r4,TLBnCFG_IPROT
954         lis     r3,MAS0_TLBSEL(1)@h
955         bne     found_iprot
956
957         mfspr   r4,SPRN_TLB2CFG
958         andi.   r3,r4,TLBnCFG_IPROT
959         lis     r3,MAS0_TLBSEL(2)@h
960         bne     found_iprot
961
962         lis     r3,MAS0_TLBSEL(3)@h
963         mfspr   r4,SPRN_TLB3CFG
964         /* fall through */
965
966 found_iprot:
967         andi.   r5,r4,TLBnCFG_HES
968         bne     have_hes
969
970         mflr    r8                              /* save LR */
971 /* 1. Find the index of the entry we're executing in
972  *
973  * r3 = MAS0_TLBSEL (for the iprot array)
974  * r4 = SPRN_TLBnCFG
975  */
976         bl      invstr                          /* Find our address */
977 invstr: mflr    r6                              /* Make it accessible */
978         mfmsr   r7
979         rlwinm  r5,r7,27,31,31                  /* extract MSR[IS] */
980         mfspr   r7,SPRN_PID
981         slwi    r7,r7,16
982         or      r7,r7,r5
983         mtspr   SPRN_MAS6,r7
984         tlbsx   0,r6                            /* search MSR[IS], SPID=PID */
985
986         mfspr   r3,SPRN_MAS0
987         rlwinm  r5,r3,16,20,31                  /* Extract MAS0(Entry) */
988
989         mfspr   r7,SPRN_MAS1                    /* Insure IPROT set */
990         oris    r7,r7,MAS1_IPROT@h
991         mtspr   SPRN_MAS1,r7
992         tlbwe
993
994 /* 2. Invalidate all entries except the entry we're executing in
995  *
996  * r3 = MAS0 w/TLBSEL & ESEL for the entry we are running in
997  * r4 = SPRN_TLBnCFG
998  * r5 = ESEL of entry we are running in
999  */
1000         andi.   r4,r4,TLBnCFG_N_ENTRY           /* Extract # entries */
1001         li      r6,0                            /* Set Entry counter to 0 */
1002 1:      mr      r7,r3                           /* Set MAS0(TLBSEL) */
1003         rlwimi  r7,r6,16,4,15                   /* Setup MAS0 = TLBSEL | ESEL(r6) */
1004         mtspr   SPRN_MAS0,r7
1005         tlbre
1006         mfspr   r7,SPRN_MAS1
1007         rlwinm  r7,r7,0,2,31                    /* Clear MAS1 Valid and IPROT */
1008         cmpw    r5,r6
1009         beq     skpinv                          /* Dont update the current execution TLB */
1010         mtspr   SPRN_MAS1,r7
1011         tlbwe
1012         isync
1013 skpinv: addi    r6,r6,1                         /* Increment */
1014         cmpw    r6,r4                           /* Are we done? */
1015         bne     1b                              /* If not, repeat */
1016
1017         /* Invalidate all TLBs */
1018         PPC_TLBILX_ALL(0,R0)
1019         sync
1020         isync
1021
1022 /* 3. Setup a temp mapping and jump to it
1023  *
1024  * r3 = MAS0 w/TLBSEL & ESEL for the entry we are running in
1025  * r5 = ESEL of entry we are running in
1026  */
1027         andi.   r7,r5,0x1       /* Find an entry not used and is non-zero */
1028         addi    r7,r7,0x1
1029         mr      r4,r3           /* Set MAS0(TLBSEL) = 1 */
1030         mtspr   SPRN_MAS0,r4
1031         tlbre
1032
1033         rlwimi  r4,r7,16,4,15   /* Setup MAS0 = TLBSEL | ESEL(r7) */
1034         mtspr   SPRN_MAS0,r4
1035
1036         mfspr   r7,SPRN_MAS1
1037         xori    r6,r7,MAS1_TS           /* Setup TMP mapping in the other Address space */
1038         mtspr   SPRN_MAS1,r6
1039
1040         tlbwe
1041
1042         mfmsr   r6
1043         xori    r6,r6,MSR_IS
1044         mtspr   SPRN_SRR1,r6
1045         bl      1f              /* Find our address */
1046 1:      mflr    r6
1047         addi    r6,r6,(2f - 1b)
1048         mtspr   SPRN_SRR0,r6
1049         rfi
1050 2:
1051
1052 /* 4. Clear out PIDs & Search info
1053  *
1054  * r3 = MAS0 w/TLBSEL & ESEL for the entry we started in
1055  * r4 = MAS0 w/TLBSEL & ESEL for the temp mapping
1056  * r5 = MAS3
1057  */
1058         li      r6,0
1059         mtspr   SPRN_MAS6,r6
1060         mtspr   SPRN_PID,r6
1061
1062 /* 5. Invalidate mapping we started in
1063  *
1064  * r3 = MAS0 w/TLBSEL & ESEL for the entry we started in
1065  * r4 = MAS0 w/TLBSEL & ESEL for the temp mapping
1066  * r5 = MAS3
1067  */
1068         mtspr   SPRN_MAS0,r3
1069         tlbre
1070         mfspr   r6,SPRN_MAS1
1071         rlwinm  r6,r6,0,2,31    /* clear IPROT and VALID */
1072         mtspr   SPRN_MAS1,r6
1073         tlbwe
1074         sync
1075         isync
1076
1077 /* The mapping only needs to be cache-coherent on SMP */
1078 #ifdef CONFIG_SMP
1079 #define M_IF_SMP        MAS2_M
1080 #else
1081 #define M_IF_SMP        0
1082 #endif
1083
1084 /* 6. Setup KERNELBASE mapping in TLB[0]
1085  *
1086  * r3 = MAS0 w/TLBSEL & ESEL for the entry we started in
1087  * r4 = MAS0 w/TLBSEL & ESEL for the temp mapping
1088  * r5 = MAS3
1089  */
1090         rlwinm  r3,r3,0,16,3    /* clear ESEL */
1091         mtspr   SPRN_MAS0,r3
1092         lis     r6,(MAS1_VALID|MAS1_IPROT)@h
1093         ori     r6,r6,(MAS1_TSIZE(BOOK3E_PAGESZ_1GB))@l
1094         mtspr   SPRN_MAS1,r6
1095
1096         LOAD_REG_IMMEDIATE(r6, PAGE_OFFSET | M_IF_SMP)
1097         mtspr   SPRN_MAS2,r6
1098
1099         rlwinm  r5,r5,0,0,25
1100         ori     r5,r5,MAS3_SR | MAS3_SW | MAS3_SX
1101         mtspr   SPRN_MAS3,r5
1102         li      r5,-1
1103         rlwinm  r5,r5,0,0,25
1104
1105         tlbwe
1106
1107 /* 7. Jump to KERNELBASE mapping
1108  *
1109  * r4 = MAS0 w/TLBSEL & ESEL for the temp mapping
1110  */
1111         /* Now we branch the new virtual address mapped by this entry */
1112         LOAD_REG_IMMEDIATE(r6,2f)
1113         lis     r7,MSR_KERNEL@h
1114         ori     r7,r7,MSR_KERNEL@l
1115         mtspr   SPRN_SRR0,r6
1116         mtspr   SPRN_SRR1,r7
1117         rfi                             /* start execution out of TLB1[0] entry */
1118 2:
1119
1120 /* 8. Clear out the temp mapping
1121  *
1122  * r4 = MAS0 w/TLBSEL & ESEL for the entry we are running in
1123  */
1124         mtspr   SPRN_MAS0,r4
1125         tlbre
1126         mfspr   r5,SPRN_MAS1
1127         rlwinm  r5,r5,0,2,31    /* clear IPROT and VALID */
1128         mtspr   SPRN_MAS1,r5
1129         tlbwe
1130         sync
1131         isync
1132
1133         /* We translate LR and return */
1134         tovirt(r8,r8)
1135         mtlr    r8
1136         blr
1137
1138 have_hes:
1139         /* Setup MAS 0,1,2,3 and 7 for tlbwe of a 1G entry that maps the
1140          * kernel linear mapping. We also set MAS8 once for all here though
1141          * that will have to be made dependent on whether we are running under
1142          * a hypervisor I suppose.
1143          */
1144
1145         /* BEWARE, MAGIC
1146          * This code is called as an ordinary function on the boot CPU. But to
1147          * avoid duplication, this code is also used in SCOM bringup of
1148          * secondary CPUs. We read the code between the initial_tlb_code_start
1149          * and initial_tlb_code_end labels one instruction at a time and RAM it
1150          * into the new core via SCOM. That doesn't process branches, so there
1151          * must be none between those two labels. It also means if this code
1152          * ever takes any parameters, the SCOM code must also be updated to
1153          * provide them.
1154          */
1155         .globl a2_tlbinit_code_start
1156 a2_tlbinit_code_start:
1157
1158         ori     r11,r3,MAS0_WQ_ALLWAYS
1159         oris    r11,r11,MAS0_ESEL(3)@h /* Use way 3: workaround A2 erratum 376 */
1160         mtspr   SPRN_MAS0,r11
1161         lis     r3,(MAS1_VALID | MAS1_IPROT)@h
1162         ori     r3,r3,BOOK3E_PAGESZ_1GB << MAS1_TSIZE_SHIFT
1163         mtspr   SPRN_MAS1,r3
1164         LOAD_REG_IMMEDIATE(r3, PAGE_OFFSET | MAS2_M)
1165         mtspr   SPRN_MAS2,r3
1166         li      r3,MAS3_SR | MAS3_SW | MAS3_SX
1167         mtspr   SPRN_MAS7_MAS3,r3
1168         li      r3,0
1169         mtspr   SPRN_MAS8,r3
1170
1171         /* Write the TLB entry */
1172         tlbwe
1173
1174         .globl a2_tlbinit_after_linear_map
1175 a2_tlbinit_after_linear_map:
1176
1177         /* Now we branch the new virtual address mapped by this entry */
1178         LOAD_REG_IMMEDIATE(r3,1f)
1179         mtctr   r3
1180         bctr
1181
1182 1:      /* We are now running at PAGE_OFFSET, clean the TLB of everything
1183          * else (including IPROTed things left by firmware)
1184          * r4 = TLBnCFG
1185          * r3 = current address (more or less)
1186          */
1187
1188         li      r5,0
1189         mtspr   SPRN_MAS6,r5
1190         tlbsx   0,r3
1191
1192         rlwinm  r9,r4,0,TLBnCFG_N_ENTRY
1193         rlwinm  r10,r4,8,0xff
1194         addi    r10,r10,-1      /* Get inner loop mask */
1195
1196         li      r3,1
1197
1198         mfspr   r5,SPRN_MAS1
1199         rlwinm  r5,r5,0,(~(MAS1_VALID|MAS1_IPROT))
1200
1201         mfspr   r6,SPRN_MAS2
1202         rldicr  r6,r6,0,51              /* Extract EPN */
1203
1204         mfspr   r7,SPRN_MAS0
1205         rlwinm  r7,r7,0,0xffff0fff      /* Clear HES and WQ */
1206
1207         rlwinm  r8,r7,16,0xfff          /* Extract ESEL */
1208
1209 2:      add     r4,r3,r8
1210         and     r4,r4,r10
1211
1212         rlwimi  r7,r4,16,MAS0_ESEL_MASK
1213
1214         mtspr   SPRN_MAS0,r7
1215         mtspr   SPRN_MAS1,r5
1216         mtspr   SPRN_MAS2,r6
1217         tlbwe
1218
1219         addi    r3,r3,1
1220         and.    r4,r3,r10
1221
1222         bne     3f
1223         addis   r6,r6,(1<<30)@h
1224 3:
1225         cmpw    r3,r9
1226         blt     2b
1227
1228         .globl  a2_tlbinit_after_iprot_flush
1229 a2_tlbinit_after_iprot_flush:
1230
1231 #ifdef CONFIG_PPC_EARLY_DEBUG_WSP
1232         /* Now establish early debug mappings if applicable */
1233         /* Restore the MAS0 we used for linear mapping load */
1234         mtspr   SPRN_MAS0,r11
1235
1236         lis     r3,(MAS1_VALID | MAS1_IPROT)@h
1237         ori     r3,r3,(BOOK3E_PAGESZ_4K << MAS1_TSIZE_SHIFT)
1238         mtspr   SPRN_MAS1,r3
1239         LOAD_REG_IMMEDIATE(r3, WSP_UART_VIRT | MAS2_I | MAS2_G)
1240         mtspr   SPRN_MAS2,r3
1241         LOAD_REG_IMMEDIATE(r3, WSP_UART_PHYS | MAS3_SR | MAS3_SW)
1242         mtspr   SPRN_MAS7_MAS3,r3
1243         /* re-use the MAS8 value from the linear mapping */
1244         tlbwe
1245 #endif /* CONFIG_PPC_EARLY_DEBUG_WSP */
1246
1247         PPC_TLBILX(0,0,R0)
1248         sync
1249         isync
1250
1251         .globl a2_tlbinit_code_end
1252 a2_tlbinit_code_end:
1253
1254         /* We translate LR and return */
1255         mflr    r3
1256         tovirt(r3,r3)
1257         mtlr    r3
1258         blr
1259
1260 /*
1261  * Main entry (boot CPU, thread 0)
1262  *
1263  * We enter here from head_64.S, possibly after the prom_init trampoline
1264  * with r3 and r4 already saved to r31 and 30 respectively and in 64 bits
1265  * mode. Anything else is as it was left by the bootloader
1266  *
1267  * Initial requirements of this port:
1268  *
1269  * - Kernel loaded at 0 physical
1270  * - A good lump of memory mapped 0:0 by UTLB entry 0
1271  * - MSR:IS & MSR:DS set to 0
1272  *
1273  * Note that some of the above requirements will be relaxed in the future
1274  * as the kernel becomes smarter at dealing with different initial conditions
1275  * but for now you have to be careful
1276  */
1277 _GLOBAL(start_initialization_book3e)
1278         mflr    r28
1279
1280         /* First, we need to setup some initial TLBs to map the kernel
1281          * text, data and bss at PAGE_OFFSET. We don't have a real mode
1282          * and always use AS 0, so we just set it up to match our link
1283          * address and never use 0 based addresses.
1284          */
1285         bl      .initial_tlb_book3e
1286
1287         /* Init global core bits */
1288         bl      .init_core_book3e
1289
1290         /* Init per-thread bits */
1291         bl      .init_thread_book3e
1292
1293         /* Return to common init code */
1294         tovirt(r28,r28)
1295         mtlr    r28
1296         blr
1297
1298
1299 /*
1300  * Secondary core/processor entry
1301  *
1302  * This is entered for thread 0 of a secondary core, all other threads
1303  * are expected to be stopped. It's similar to start_initialization_book3e
1304  * except that it's generally entered from the holding loop in head_64.S
1305  * after CPUs have been gathered by Open Firmware.
1306  *
1307  * We assume we are in 32 bits mode running with whatever TLB entry was
1308  * set for us by the firmware or POR engine.
1309  */
1310 _GLOBAL(book3e_secondary_core_init_tlb_set)
1311         li      r4,1
1312         b       .generic_secondary_smp_init
1313
1314 _GLOBAL(book3e_secondary_core_init)
1315         mflr    r28
1316
1317         /* Do we need to setup initial TLB entry ? */
1318         cmplwi  r4,0
1319         bne     2f
1320
1321         /* Setup TLB for this core */
1322         bl      .initial_tlb_book3e
1323
1324         /* We can return from the above running at a different
1325          * address, so recalculate r2 (TOC)
1326          */
1327         bl      .relative_toc
1328
1329         /* Init global core bits */
1330 2:      bl      .init_core_book3e
1331
1332         /* Init per-thread bits */
1333 3:      bl      .init_thread_book3e
1334
1335         /* Return to common init code at proper virtual address.
1336          *
1337          * Due to various previous assumptions, we know we entered this
1338          * function at either the final PAGE_OFFSET mapping or using a
1339          * 1:1 mapping at 0, so we don't bother doing a complicated check
1340          * here, we just ensure the return address has the right top bits.
1341          *
1342          * Note that if we ever want to be smarter about where we can be
1343          * started from, we have to be careful that by the time we reach
1344          * the code below we may already be running at a different location
1345          * than the one we were called from since initial_tlb_book3e can
1346          * have moved us already.
1347          */
1348         cmpdi   cr0,r28,0
1349         blt     1f
1350         lis     r3,PAGE_OFFSET@highest
1351         sldi    r3,r3,32
1352         or      r28,r28,r3
1353 1:      mtlr    r28
1354         blr
1355
1356 _GLOBAL(book3e_secondary_thread_init)
1357         mflr    r28
1358         b       3b
1359
1360 _STATIC(init_core_book3e)
1361         /* Establish the interrupt vector base */
1362         LOAD_REG_IMMEDIATE(r3, interrupt_base_book3e)
1363         mtspr   SPRN_IVPR,r3
1364         sync
1365         blr
1366
1367 _STATIC(init_thread_book3e)
1368         lis     r3,(SPRN_EPCR_ICM | SPRN_EPCR_GICM)@h
1369         mtspr   SPRN_EPCR,r3
1370
1371         /* Make sure interrupts are off */
1372         wrteei  0
1373
1374         /* disable all timers and clear out status */
1375         li      r3,0
1376         mtspr   SPRN_TCR,r3
1377         mfspr   r3,SPRN_TSR
1378         mtspr   SPRN_TSR,r3
1379
1380         blr
1381
1382 _GLOBAL(__setup_base_ivors)
1383         SET_IVOR(0, 0x020) /* Critical Input */
1384         SET_IVOR(1, 0x000) /* Machine Check */
1385         SET_IVOR(2, 0x060) /* Data Storage */ 
1386         SET_IVOR(3, 0x080) /* Instruction Storage */
1387         SET_IVOR(4, 0x0a0) /* External Input */ 
1388         SET_IVOR(5, 0x0c0) /* Alignment */ 
1389         SET_IVOR(6, 0x0e0) /* Program */ 
1390         SET_IVOR(7, 0x100) /* FP Unavailable */ 
1391         SET_IVOR(8, 0x120) /* System Call */ 
1392         SET_IVOR(9, 0x140) /* Auxiliary Processor Unavailable */ 
1393         SET_IVOR(10, 0x160) /* Decrementer */ 
1394         SET_IVOR(11, 0x180) /* Fixed Interval Timer */ 
1395         SET_IVOR(12, 0x1a0) /* Watchdog Timer */ 
1396         SET_IVOR(13, 0x1c0) /* Data TLB Error */ 
1397         SET_IVOR(14, 0x1e0) /* Instruction TLB Error */
1398         SET_IVOR(15, 0x040) /* Debug */
1399
1400         sync
1401
1402         blr
1403
1404 _GLOBAL(setup_altivec_ivors)
1405         SET_IVOR(32, 0x200) /* AltiVec Unavailable */
1406         SET_IVOR(33, 0x220) /* AltiVec Assist */
1407         blr
1408
1409 _GLOBAL(setup_perfmon_ivor)
1410         SET_IVOR(35, 0x260) /* Performance Monitor */
1411         blr
1412
1413 _GLOBAL(setup_doorbell_ivors)
1414         SET_IVOR(36, 0x280) /* Processor Doorbell */
1415         SET_IVOR(37, 0x2a0) /* Processor Doorbell Crit */
1416         blr
1417
1418 _GLOBAL(setup_ehv_ivors)
1419         SET_IVOR(40, 0x300) /* Embedded Hypervisor System Call */
1420         SET_IVOR(41, 0x320) /* Embedded Hypervisor Privilege */
1421         SET_IVOR(38, 0x2c0) /* Guest Processor Doorbell */
1422         SET_IVOR(39, 0x2e0) /* Guest Processor Doorbell Crit/MC */
1423         blr
1424
1425 _GLOBAL(setup_lrat_ivor)
1426         SET_IVOR(42, 0x340) /* LRAT Error */
1427         blr