upgrade to linux 2.6.10-1.12_FC2
[linux-2.6.git] / arch / ppc64 / kernel / head.S
1 /*
2  *  arch/ppc64/kernel/head.S
3  *
4  *  PowerPC version
5  *    Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
6  *
7  *  Rewritten by Cort Dougan (cort@cs.nmt.edu) for PReP
8  *    Copyright (C) 1996 Cort Dougan <cort@cs.nmt.edu>
9  *  Adapted for Power Macintosh by Paul Mackerras.
10  *  Low-level exception handlers and MMU support
11  *  rewritten by Paul Mackerras.
12  *    Copyright (C) 1996 Paul Mackerras.
13  *
14  *  Adapted for 64bit PowerPC by Dave Engebretsen, Peter Bergner, and
15  *    Mike Corrigan {engebret|bergner|mikejc}@us.ibm.com
16  *
17  *  This file contains the low-level support and setup for the
18  *  PowerPC-64 platform, including trap and interrupt dispatch.
19  *
20  *  This program is free software; you can redistribute it and/or
21  *  modify it under the terms of the GNU General Public License
22  *  as published by the Free Software Foundation; either version
23  *  2 of the License, or (at your option) any later version.
24  */
25
26 #define SECONDARY_PROCESSORS
27
28 #include <linux/config.h>
29 #include <linux/threads.h>
30 #include <asm/processor.h>
31 #include <asm/page.h>
32 #include <asm/mmu.h>
33 #include <asm/naca.h>
34 #include <asm/systemcfg.h>
35 #include <asm/ppc_asm.h>
36 #include <asm/offsets.h>
37 #include <asm/bug.h>
38 #include <asm/cputable.h>
39 #include <asm/setup.h>
40
41 #ifdef CONFIG_PPC_ISERIES
42 #define DO_SOFT_DISABLE
43 #endif
44
45 /*
46  * hcall interface to pSeries LPAR
47  */
48 #define HVSC            .long 0x44000022
49 #define H_SET_ASR       0x30
50
51 /*
52  * We layout physical memory as follows:
53  * 0x0000 - 0x00ff : Secondary processor spin code
54  * 0x0100 - 0x2fff : pSeries Interrupt prologs
55  * 0x3000 - 0x3fff : Interrupt support
56  * 0x4000 - 0x4fff : NACA
57  * 0x5000 - 0x5fff : SystemCfg
58  * 0x6000          : iSeries and common interrupt prologs
59  * 0x9000 - 0x9fff : Initial segment table
60  */
61
62 /*
63  *   SPRG Usage
64  *
65  *   Register   Definition
66  *
67  *   SPRG0      reserved for hypervisor
68  *   SPRG1      temp - used to save gpr
69  *   SPRG2      temp - used to save gpr
70  *   SPRG3      virt addr of paca
71  */
72
73 /*
74  * Entering into this code we make the following assumptions:
75  *  For pSeries:
76  *   1. The MMU is off & open firmware is running in real mode.
77  *   2. The kernel is entered at __start
78  *
79  *  For iSeries:
80  *   1. The MMU is on (as it always is for iSeries)
81  *   2. The kernel is entered at SystemReset_Iseries
82  */
83
84         .text
85         .globl  _stext
86 _stext:
87 #ifdef CONFIG_PPC_MULTIPLATFORM
88 _GLOBAL(__start)
89         /* NOP this out unconditionally */
90 BEGIN_FTR_SECTION
91         b .__start_initialization_multiplatform
92 END_FTR_SECTION(0, 1)
93 #endif /* CONFIG_PPC_MULTIPLATFORM */
94
95         /* Catch branch to 0 in real mode */
96         trap
97 #ifdef CONFIG_PPC_ISERIES
98         /*
99          * At offset 0x20, there is a pointer to iSeries LPAR data.
100          * This is required by the hypervisor
101          */
102         . = 0x20
103         .llong hvReleaseData-KERNELBASE
104
105         /*
106          * At offset 0x28 and 0x30 are offsets to the msChunks
107          * array (used by the iSeries LPAR debugger to do translation
108          * between physical addresses and absolute addresses) and
109          * to the pidhash table (also used by the debugger)
110          */
111         .llong msChunks-KERNELBASE
112         .llong 0        /* pidhash-KERNELBASE SFRXXX */
113
114         /* Offset 0x38 - Pointer to start of embedded System.map */
115         .globl  embedded_sysmap_start
116 embedded_sysmap_start:
117         .llong  0
118         /* Offset 0x40 - Pointer to end of embedded System.map */
119         .globl  embedded_sysmap_end
120 embedded_sysmap_end:
121         .llong  0
122
123 #else /* CONFIG_PPC_ISERIES */
124
125         /* Secondary processors spin on this value until it goes to 1. */
126         .globl  __secondary_hold_spinloop
127 __secondary_hold_spinloop:
128         .llong  0x0
129
130         /* Secondary processors write this value with their cpu # */
131         /* after they enter the spin loop immediately below.      */
132         .globl  __secondary_hold_acknowledge
133 __secondary_hold_acknowledge:
134         .llong  0x0
135
136         . = 0x60
137 /*
138  * The following code is used on pSeries to hold secondary processors
139  * in a spin loop after they have been freed from OpenFirmware, but
140  * before the bulk of the kernel has been relocated.  This code
141  * is relocated to physical address 0x60 before prom_init is run.
142  * All of it must fit below the first exception vector at 0x100.
143  */
144 _GLOBAL(__secondary_hold)
145         mfmsr   r24
146         ori     r24,r24,MSR_RI
147         mtmsrd  r24                     /* RI on */
148
149         /* Grab our linux cpu number */
150         mr      r24,r3
151
152         /* Tell the master cpu we're here */
153         /* Relocation is off & we are located at an address less */
154         /* than 0x100, so only need to grab low order offset.    */
155         std     r24,__secondary_hold_acknowledge@l(0)
156         sync
157
158         /* All secondary cpu's wait here until told to start. */
159 100:    ld      r4,__secondary_hold_spinloop@l(0)
160         cmpdi   0,r4,1
161         bne     100b
162
163 #ifdef CONFIG_HMT
164         b       .hmt_init
165 #else
166 #ifdef CONFIG_SMP
167         mr      r3,r24
168         b       .pseries_secondary_smp_init
169 #else
170         BUG_OPCODE
171 #endif
172 #endif
173 #endif
174
175 /* This value is used to mark exception frames on the stack. */
176         .section ".toc","aw"
177 exception_marker:
178         .tc     ID_72656773_68657265[TC],0x7265677368657265
179         .text
180
181 /*
182  * The following macros define the code that appears as
183  * the prologue to each of the exception handlers.  They
184  * are split into two parts to allow a single kernel binary
185  * to be used for pSeries and iSeries.
186  * LOL.  One day... - paulus
187  */
188
189 /*
190  * We make as much of the exception code common between native
191  * exception handlers (including pSeries LPAR) and iSeries LPAR
192  * implementations as possible.
193  */
194
195 /*
196  * This is the start of the interrupt handlers for pSeries
197  * This code runs with relocation off.
198  */
199 #define EX_R9           0
200 #define EX_R10          8
201 #define EX_R11          16
202 #define EX_R12          24
203 #define EX_R13          32
204 #define EX_SRR0         40
205 #define EX_R3           40      /* SLB miss saves R3, but not SRR0 */
206 #define EX_DAR          48
207 #define EX_LR           48      /* SLB miss saves LR, but not DAR */
208 #define EX_DSISR        56
209 #define EX_CCR          60
210
211 #define EXCEPTION_PROLOG_PSERIES(area, label)                           \
212         mfspr   r13,SPRG3;              /* get paca address into r13 */ \
213         std     r9,area+EX_R9(r13);     /* save r9 - r12 */             \
214         std     r10,area+EX_R10(r13);                                   \
215         std     r11,area+EX_R11(r13);                                   \
216         std     r12,area+EX_R12(r13);                                   \
217         mfspr   r9,SPRG1;                                               \
218         std     r9,area+EX_R13(r13);                                    \
219         mfcr    r9;                                                     \
220         clrrdi  r12,r13,32;             /* get high part of &label */   \
221         mfmsr   r10;                                                    \
222         mfspr   r11,SRR0;               /* save SRR0 */                 \
223         ori     r12,r12,(label)@l;      /* virt addr of handler */      \
224         ori     r10,r10,MSR_IR|MSR_DR|MSR_RI;                           \
225         mtspr   SRR0,r12;                                               \
226         mfspr   r12,SRR1;               /* and SRR1 */                  \
227         mtspr   SRR1,r10;                                               \
228         rfid;                                                           \
229         b       .       /* prevent speculative execution */
230
231 /*
232  * This is the start of the interrupt handlers for iSeries
233  * This code runs with relocation on.
234  */
235 #define EXCEPTION_PROLOG_ISERIES_1(area)                                \
236         mfspr   r13,SPRG3;              /* get paca address into r13 */ \
237         std     r9,area+EX_R9(r13);     /* save r9 - r12 */             \
238         std     r10,area+EX_R10(r13);                                   \
239         std     r11,area+EX_R11(r13);                                   \
240         std     r12,area+EX_R12(r13);                                   \
241         mfspr   r9,SPRG1;                                               \
242         std     r9,area+EX_R13(r13);                                    \
243         mfcr    r9
244
245 #define EXCEPTION_PROLOG_ISERIES_2                                      \
246         mfmsr   r10;                                                    \
247         ld      r11,PACALPPACA+LPPACASRR0(r13);                         \
248         ld      r12,PACALPPACA+LPPACASRR1(r13);                         \
249         ori     r10,r10,MSR_RI;                                         \
250         mtmsrd  r10,1
251
252 /*
253  * The common exception prolog is used for all except a few exceptions
254  * such as a segment miss on a kernel address.  We have to be prepared
255  * to take another exception from the point where we first touch the
256  * kernel stack onwards.
257  *
258  * On entry r13 points to the paca, r9-r13 are saved in the paca,
259  * r9 contains the saved CR, r11 and r12 contain the saved SRR0 and
260  * SRR1, and relocation is on.
261  */
262 #define EXCEPTION_PROLOG_COMMON(n, area)                                   \
263         andi.   r10,r12,MSR_PR;         /* See if coming from user      */ \
264         mr      r10,r1;                 /* Save r1                      */ \
265         subi    r1,r1,INT_FRAME_SIZE;   /* alloc frame on kernel stack  */ \
266         beq-    1f;                                                        \
267         ld      r1,PACAKSAVE(r13);      /* kernel stack to use          */ \
268 1:      cmpdi   cr1,r1,0;               /* check if r1 is in userspace  */ \
269         bge-    cr1,bad_stack;          /* abort if it is               */ \
270         std     r9,_CCR(r1);            /* save CR in stackframe        */ \
271         std     r11,_NIP(r1);           /* save SRR0 in stackframe      */ \
272         std     r12,_MSR(r1);           /* save SRR1 in stackframe      */ \
273         std     r10,0(r1);              /* make stack chain pointer     */ \
274         std     r0,GPR0(r1);            /* save r0 in stackframe        */ \
275         std     r10,GPR1(r1);           /* save r1 in stackframe        */ \
276         std     r2,GPR2(r1);            /* save r2 in stackframe        */ \
277         SAVE_4GPRS(3, r1);              /* save r3 - r6 in stackframe   */ \
278         SAVE_2GPRS(7, r1);              /* save r7, r8 in stackframe    */ \
279         ld      r9,area+EX_R9(r13);     /* move r9, r10 to stackframe   */ \
280         ld      r10,area+EX_R10(r13);                                      \
281         std     r9,GPR9(r1);                                               \
282         std     r10,GPR10(r1);                                             \
283         ld      r9,area+EX_R11(r13);    /* move r11 - r13 to stackframe */ \
284         ld      r10,area+EX_R12(r13);                                      \
285         ld      r11,area+EX_R13(r13);                                      \
286         std     r9,GPR11(r1);                                              \
287         std     r10,GPR12(r1);                                             \
288         std     r11,GPR13(r1);                                             \
289         ld      r2,PACATOC(r13);        /* get kernel TOC into r2       */ \
290         mflr    r9;                     /* save LR in stackframe        */ \
291         std     r9,_LINK(r1);                                              \
292         mfctr   r10;                    /* save CTR in stackframe       */ \
293         std     r10,_CTR(r1);                                              \
294         mfspr   r11,XER;                /* save XER in stackframe       */ \
295         std     r11,_XER(r1);                                              \
296         li      r9,(n)+1;                                                  \
297         std     r9,_TRAP(r1);           /* set trap number              */ \
298         li      r10,0;                                                     \
299         ld      r11,exception_marker@toc(r2);                              \
300         std     r10,RESULT(r1);         /* clear regs->result           */ \
301         std     r11,STACK_FRAME_OVERHEAD-16(r1); /* mark the frame      */
302
303 /*
304  * Exception vectors.
305  */
306 #define STD_EXCEPTION_PSERIES(n, label)                 \
307         . = n;                                          \
308         .globl label##_Pseries;                         \
309 label##_Pseries:                                        \
310         HMT_MEDIUM;                                     \
311         mtspr   SPRG1,r13;              /* save r13 */  \
312         EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, label##_common)
313
314 #define STD_EXCEPTION_ISERIES(n, label, area)           \
315         .globl label##_Iseries;                         \
316 label##_Iseries:                                        \
317         HMT_MEDIUM;                                     \
318         mtspr   SPRG1,r13;              /* save r13 */  \
319         EXCEPTION_PROLOG_ISERIES_1(area);               \
320         EXCEPTION_PROLOG_ISERIES_2;                     \
321         b       label##_common
322
323 #define MASKABLE_EXCEPTION_ISERIES(n, label)                            \
324         .globl label##_Iseries;                                         \
325 label##_Iseries:                                                        \
326         HMT_MEDIUM;                                                     \
327         mtspr   SPRG1,r13;              /* save r13 */                  \
328         EXCEPTION_PROLOG_ISERIES_1(PACA_EXGEN);                         \
329         lbz     r10,PACAPROCENABLED(r13);                               \
330         cmpwi   0,r10,0;                                                \
331         beq-    label##_Iseries_masked;                                 \
332         EXCEPTION_PROLOG_ISERIES_2;                                     \
333         b       label##_common;                                         \
334
335 #ifdef DO_SOFT_DISABLE
336 #define DISABLE_INTS                            \
337         lbz     r10,PACAPROCENABLED(r13);       \
338         li      r11,0;                          \
339         std     r10,SOFTE(r1);                  \
340         mfmsr   r10;                            \
341         stb     r11,PACAPROCENABLED(r13);       \
342         ori     r10,r10,MSR_EE;                 \
343         mtmsrd  r10,1
344
345 #define ENABLE_INTS                             \
346         lbz     r10,PACAPROCENABLED(r13);       \
347         mfmsr   r11;                            \
348         std     r10,SOFTE(r1);                  \
349         ori     r11,r11,MSR_EE;                 \
350         mtmsrd  r11,1
351
352 #else   /* hard enable/disable interrupts */
353 #define DISABLE_INTS
354
355 #define ENABLE_INTS                             \
356         ld      r12,_MSR(r1);                   \
357         mfmsr   r11;                            \
358         rlwimi  r11,r12,0,MSR_EE;               \
359         mtmsrd  r11,1
360
361 #endif
362
363 #define STD_EXCEPTION_COMMON(trap, label, hdlr)         \
364         .align  7;                                      \
365         .globl label##_common;                          \
366 label##_common:                                         \
367         EXCEPTION_PROLOG_COMMON(trap, PACA_EXGEN);      \
368         DISABLE_INTS;                                   \
369         bl      .save_nvgprs;                           \
370         addi    r3,r1,STACK_FRAME_OVERHEAD;             \
371         bl      hdlr;                                   \
372         b       .ret_from_except
373
374 #define STD_EXCEPTION_COMMON_LITE(trap, label, hdlr)    \
375         .align  7;                                      \
376         .globl label##_common;                          \
377 label##_common:                                         \
378         EXCEPTION_PROLOG_COMMON(trap, PACA_EXGEN);      \
379         DISABLE_INTS;                                   \
380         addi    r3,r1,STACK_FRAME_OVERHEAD;             \
381         bl      hdlr;                                   \
382         b       .ret_from_except_lite
383
384 /*
385  * Start of pSeries system interrupt routines
386  */
387         . = 0x100
388         .globl __start_interrupts
389 __start_interrupts:
390
391         STD_EXCEPTION_PSERIES(0x100, SystemReset)
392
393         . = 0x200
394 _MachineCheckPseries:
395         HMT_MEDIUM
396         mtspr   SPRG1,r13               /* save r13 */
397         EXCEPTION_PROLOG_PSERIES(PACA_EXMC, MachineCheck_common)
398
399         . = 0x300
400         .globl DataAccess_Pseries
401 DataAccess_Pseries:
402         HMT_MEDIUM
403         mtspr   SPRG1,r13
404 BEGIN_FTR_SECTION
405         mtspr   SPRG2,r12
406         mfspr   r13,DAR
407         mfspr   r12,DSISR
408         srdi    r13,r13,60
409         rlwimi  r13,r12,16,0x20
410         mfcr    r12
411         cmpwi   r13,0x2c
412         beq     .do_stab_bolted_Pseries
413         mtcrf   0x80,r12
414         mfspr   r12,SPRG2
415 END_FTR_SECTION_IFCLR(CPU_FTR_SLB)
416         EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, DataAccess_common)
417
418         . = 0x380
419         .globl DataAccessSLB_Pseries
420 DataAccessSLB_Pseries:
421         HMT_MEDIUM
422         mtspr   SPRG1,r13
423         mfspr   r13,SPRG3               /* get paca address into r13 */
424         std     r9,PACA_EXSLB+EX_R9(r13)        /* save r9 - r12 */
425         std     r10,PACA_EXSLB+EX_R10(r13)
426         std     r11,PACA_EXSLB+EX_R11(r13)
427         std     r12,PACA_EXSLB+EX_R12(r13)
428         std     r3,PACA_EXSLB+EX_R3(r13)
429         mfspr   r9,SPRG1
430         std     r9,PACA_EXSLB+EX_R13(r13)
431         mfcr    r9
432         mfspr   r12,SRR1                /* and SRR1 */
433         mfspr   r3,DAR
434         b       .do_slb_miss            /* Rel. branch works in real mode */
435
436         STD_EXCEPTION_PSERIES(0x400, InstructionAccess)
437
438         . = 0x480
439         .globl InstructionAccessSLB_Pseries
440 InstructionAccessSLB_Pseries:
441         HMT_MEDIUM
442         mtspr   SPRG1,r13
443         mfspr   r13,SPRG3               /* get paca address into r13 */
444         std     r9,PACA_EXSLB+EX_R9(r13)        /* save r9 - r12 */
445         std     r10,PACA_EXSLB+EX_R10(r13)
446         std     r11,PACA_EXSLB+EX_R11(r13)
447         std     r12,PACA_EXSLB+EX_R12(r13)
448         std     r3,PACA_EXSLB+EX_R3(r13)
449         mfspr   r9,SPRG1
450         std     r9,PACA_EXSLB+EX_R13(r13)
451         mfcr    r9
452         mfspr   r12,SRR1                /* and SRR1 */
453         mfspr   r3,SRR0                 /* SRR0 is faulting address */
454         b       .do_slb_miss            /* Rel. branch works in real mode */
455
456         STD_EXCEPTION_PSERIES(0x500, HardwareInterrupt)
457         STD_EXCEPTION_PSERIES(0x600, Alignment)
458         STD_EXCEPTION_PSERIES(0x700, ProgramCheck)
459         STD_EXCEPTION_PSERIES(0x800, FPUnavailable)
460         STD_EXCEPTION_PSERIES(0x900, Decrementer)
461         STD_EXCEPTION_PSERIES(0xa00, Trap_0a)
462         STD_EXCEPTION_PSERIES(0xb00, Trap_0b)
463
464         . = 0xc00
465         .globl  SystemCall_Pseries
466 SystemCall_Pseries:
467         HMT_MEDIUM
468         mr      r9,r13
469         mfmsr   r10
470         mfspr   r13,SPRG3
471         mfspr   r11,SRR0
472         clrrdi  r12,r13,32
473         oris    r12,r12,SystemCall_common@h
474         ori     r12,r12,SystemCall_common@l
475         mtspr   SRR0,r12
476         ori     r10,r10,MSR_IR|MSR_DR|MSR_RI
477         mfspr   r12,SRR1
478         mtspr   SRR1,r10
479         rfid
480         b       .       /* prevent speculative execution */
481
482         STD_EXCEPTION_PSERIES(0xd00, SingleStep)
483         STD_EXCEPTION_PSERIES(0xe00, Trap_0e)
484
485         /* We need to deal with the Altivec unavailable exception
486          * here which is at 0xf20, thus in the middle of the
487          * prolog code of the PerformanceMonitor one. A little
488          * trickery is thus necessary
489          */
490         . = 0xf00
491         b       PerformanceMonitor_Pseries
492
493         STD_EXCEPTION_PSERIES(0xf20, AltivecUnavailable)
494
495         STD_EXCEPTION_PSERIES(0x1300, InstructionBreakpoint)
496         STD_EXCEPTION_PSERIES(0x1700, AltivecAssist)
497
498         /* moved from 0xf00 */
499         STD_EXCEPTION_PSERIES(0x3000, PerformanceMonitor)
500
501         . = 0x3100
502 _GLOBAL(do_stab_bolted_Pseries)
503         mtcrf   0x80,r12
504         mfspr   r12,SPRG2
505         EXCEPTION_PROLOG_PSERIES(PACA_EXSLB, .do_stab_bolted)
506
507         
508         /* Space for the naca.  Architected to be located at real address
509          * NACA_PHYS_ADDR.  Various tools rely on this location being fixed.
510          * The first dword of the naca is required by iSeries LPAR to
511          * point to itVpdAreas.  On pSeries native, this value is not used.
512          */
513         . = NACA_PHYS_ADDR
514         .globl __end_interrupts
515         .globl __start_naca
516 __end_interrupts:
517 __start_naca:
518 #ifdef CONFIG_PPC_ISERIES
519         .llong itVpdAreas
520 #else
521         .llong 0x0
522 #endif
523         .llong 0x0
524         .llong 0x0
525         .llong paca
526
527         . = SYSTEMCFG_PHYS_ADDR
528         .globl __end_naca
529         .globl __start_systemcfg
530 __end_naca:
531 __start_systemcfg:
532         . = (SYSTEMCFG_PHYS_ADDR + PAGE_SIZE)
533         .globl __end_systemcfg
534 __end_systemcfg:
535
536 #ifdef CONFIG_PPC_ISERIES
537         /*
538          * The iSeries LPAR map is at this fixed address
539          * so that the HvReleaseData structure can address
540          * it with a 32-bit offset.
541          *
542          * The VSID values below are dependent on the
543          * VSID generation algorithm.  See include/asm/mmu_context.h.
544          */
545
546         .llong  2               /* # ESIDs to be mapped by hypervisor    */
547         .llong  1               /* # memory ranges to be mapped by hypervisor */
548         .llong  STAB0_PAGE      /* Page # of segment table within load area     */
549         .llong  0               /* Reserved */
550         .llong  0               /* Reserved */
551         .llong  0               /* Reserved */
552         .llong  0               /* Reserved */
553         .llong  0               /* Reserved */
554         .llong  (KERNELBASE>>SID_SHIFT)
555         .llong  0x408f92c94     /* KERNELBASE VSID */
556         /* We have to list the bolted VMALLOC segment here, too, so that it
557          * will be restored on shared processor switch */
558         .llong  (VMALLOCBASE>>SID_SHIFT)
559         .llong  0xf09b89af5     /* VMALLOCBASE VSID */
560         .llong  8192            /* # pages to map (32 MB) */
561         .llong  0               /* Offset from start of loadarea to start of map */
562         .llong  0x408f92c940000 /* VPN of first page to map */
563
564         . = 0x6100
565
566 /***  ISeries-LPAR interrupt handlers ***/
567
568         STD_EXCEPTION_ISERIES(0x200, MachineCheck, PACA_EXMC)
569
570         .globl DataAccess_Iseries
571 DataAccess_Iseries:
572         mtspr   SPRG1,r13
573 BEGIN_FTR_SECTION
574         mtspr   SPRG2,r12
575         mfspr   r13,DAR
576         mfspr   r12,DSISR
577         srdi    r13,r13,60
578         rlwimi  r13,r12,16,0x20
579         mfcr    r12
580         cmpwi   r13,0x2c
581         beq     .do_stab_bolted_Iseries
582         mtcrf   0x80,r12
583         mfspr   r12,SPRG2
584 END_FTR_SECTION_IFCLR(CPU_FTR_SLB)
585         EXCEPTION_PROLOG_ISERIES_1(PACA_EXGEN)
586         EXCEPTION_PROLOG_ISERIES_2
587         b       DataAccess_common
588
589 .do_stab_bolted_Iseries:
590         mtcrf   0x80,r12
591         mfspr   r12,SPRG2
592         EXCEPTION_PROLOG_ISERIES_1(PACA_EXSLB)
593         EXCEPTION_PROLOG_ISERIES_2
594         b       .do_stab_bolted
595
596         .globl  DataAccessSLB_Iseries
597 DataAccessSLB_Iseries:
598         mtspr   SPRG1,r13               /* save r13 */
599         EXCEPTION_PROLOG_ISERIES_1(PACA_EXSLB)
600         std     r3,PACA_EXSLB+EX_R3(r13)
601         ld      r12,PACALPPACA+LPPACASRR1(r13)
602         mfspr   r3,DAR
603         b       .do_slb_miss
604
605         STD_EXCEPTION_ISERIES(0x400, InstructionAccess, PACA_EXGEN)
606
607         .globl  InstructionAccessSLB_Iseries
608 InstructionAccessSLB_Iseries:
609         mtspr   SPRG1,r13               /* save r13 */
610         EXCEPTION_PROLOG_ISERIES_1(PACA_EXSLB)
611         std     r3,PACA_EXSLB+EX_R3(r13)
612         ld      r12,PACALPPACA+LPPACASRR1(r13)
613         ld      r3,PACALPPACA+LPPACASRR0(r13)
614         b       .do_slb_miss
615
616         MASKABLE_EXCEPTION_ISERIES(0x500, HardwareInterrupt)
617         STD_EXCEPTION_ISERIES(0x600, Alignment, PACA_EXGEN)
618         STD_EXCEPTION_ISERIES(0x700, ProgramCheck, PACA_EXGEN)
619         STD_EXCEPTION_ISERIES(0x800, FPUnavailable, PACA_EXGEN)
620         MASKABLE_EXCEPTION_ISERIES(0x900, Decrementer)
621         STD_EXCEPTION_ISERIES(0xa00, Trap_0a, PACA_EXGEN)
622         STD_EXCEPTION_ISERIES(0xb00, Trap_0b, PACA_EXGEN)
623
624         .globl  SystemCall_Iseries
625 SystemCall_Iseries:
626         mr      r9,r13
627         mfspr   r13,SPRG3
628         EXCEPTION_PROLOG_ISERIES_2
629         b       SystemCall_common
630
631         STD_EXCEPTION_ISERIES( 0xd00, SingleStep, PACA_EXGEN)
632         STD_EXCEPTION_ISERIES( 0xe00, Trap_0e, PACA_EXGEN)
633         STD_EXCEPTION_ISERIES( 0xf00, PerformanceMonitor, PACA_EXGEN)
634
635         .globl SystemReset_Iseries
636 SystemReset_Iseries:
637         mfspr   r13,SPRG3               /* Get paca address */
638         mfmsr   r24
639         ori     r24,r24,MSR_RI
640         mtmsrd  r24                     /* RI on */
641         lhz     r24,PACAPACAINDEX(r13)  /* Get processor # */
642         cmpwi   0,r24,0                 /* Are we processor 0? */
643         beq     .__start_initialization_iSeries /* Start up the first processor */
644         mfspr   r4,CTRLF
645         li      r5,RUNLATCH             /* Turn off the run light */
646         andc    r4,r4,r5
647         mtspr   CTRLT,r4
648
649 1:
650         HMT_LOW
651 #ifdef CONFIG_SMP
652         lbz     r23,PACAPROCSTART(r13)  /* Test if this processor
653                                          * should start */
654         sync
655         LOADADDR(r3,current_set)
656         sldi    r28,r24,3               /* get current_set[cpu#] */
657         ldx     r3,r3,r28
658         addi    r1,r3,THREAD_SIZE
659         subi    r1,r1,STACK_FRAME_OVERHEAD
660
661         cmpwi   0,r23,0
662         beq     iseries_secondary_smp_loop      /* Loop until told to go */
663 #ifdef SECONDARY_PROCESSORS
664         bne     .__secondary_start              /* Loop until told to go */
665 #endif
666 iseries_secondary_smp_loop:
667         /* Let the Hypervisor know we are alive */
668         /* 8002 is a call to HvCallCfg::getLps, a harmless Hypervisor function */
669         lis     r3,0x8002
670         rldicr  r3,r3,32,15             /* r0 = (r3 << 32) & 0xffff000000000000 */
671 #else /* CONFIG_SMP */
672         /* Yield the processor.  This is required for non-SMP kernels
673                 which are running on multi-threaded machines. */
674         lis     r3,0x8000
675         rldicr  r3,r3,32,15             /* r3 = (r3 << 32) & 0xffff000000000000 */
676         addi    r3,r3,18                /* r3 = 0x8000000000000012 which is "yield" */
677         li      r4,0                    /* "yield timed" */
678         li      r5,-1                   /* "yield forever" */
679 #endif /* CONFIG_SMP */
680         li      r0,-1                   /* r0=-1 indicates a Hypervisor call */
681         sc                              /* Invoke the hypervisor via a system call */
682         mfspr   r13,SPRG3               /* Put r13 back ???? */
683         b       1b                      /* If SMP not configured, secondaries
684                                          * loop forever */
685
686         .globl Decrementer_Iseries_masked
687 Decrementer_Iseries_masked:
688         li      r11,1
689         stb     r11,PACALPPACA+LPPACADECRINT(r13)
690         lwz     r12,PACADEFAULTDECR(r13)
691         mtspr   SPRN_DEC,r12
692         /* fall through */
693
694         .globl HardwareInterrupt_Iseries_masked
695 HardwareInterrupt_Iseries_masked:
696         mtcrf   0x80,r9         /* Restore regs */
697         ld      r11,PACALPPACA+LPPACASRR0(r13)
698         ld      r12,PACALPPACA+LPPACASRR1(r13)
699         mtspr   SRR0,r11
700         mtspr   SRR1,r12
701         ld      r9,PACA_EXGEN+EX_R9(r13)
702         ld      r10,PACA_EXGEN+EX_R10(r13)
703         ld      r11,PACA_EXGEN+EX_R11(r13)
704         ld      r12,PACA_EXGEN+EX_R12(r13)
705         ld      r13,PACA_EXGEN+EX_R13(r13)
706         rfid
707         b       .       /* prevent speculative execution */
708 #endif
709
710 /*
711  * Data area reserved for FWNMI option.
712  */
713         .= 0x7000
714         .globl fwnmi_data_area
715 fwnmi_data_area:
716
717 /*
718  * Vectors for the FWNMI option.  Share common code.
719  */
720         . = 0x8000
721         .globl SystemReset_FWNMI
722 SystemReset_FWNMI:
723         HMT_MEDIUM
724         mtspr   SPRG1,r13               /* save r13 */
725         EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, SystemReset_common)
726         .globl MachineCheck_FWNMI
727 MachineCheck_FWNMI:
728         HMT_MEDIUM
729         mtspr   SPRG1,r13               /* save r13 */
730         EXCEPTION_PROLOG_PSERIES(PACA_EXMC, MachineCheck_common)
731
732         /*
733          * Space for the initial segment table
734          * For LPAR, the hypervisor must fill in at least one entry
735          * before we get control (with relocate on)
736          */
737         . = STAB0_PHYS_ADDR
738         .globl __start_stab
739 __start_stab:
740
741         . = (STAB0_PHYS_ADDR + PAGE_SIZE)
742         .globl __end_stab
743 __end_stab:
744
745
746 /*** Common interrupt handlers ***/
747
748         STD_EXCEPTION_COMMON(0x100, SystemReset, .SystemResetException)
749
750         /*
751          * Machine check is different because we use a different
752          * save area: PACA_EXMC instead of PACA_EXGEN.
753          */
754         .align  7
755         .globl MachineCheck_common
756 MachineCheck_common:
757         EXCEPTION_PROLOG_COMMON(0x200, PACA_EXMC)
758         DISABLE_INTS
759         bl      .save_nvgprs
760         addi    r3,r1,STACK_FRAME_OVERHEAD
761         bl      .MachineCheckException
762         b       .ret_from_except
763
764         STD_EXCEPTION_COMMON_LITE(0x900, Decrementer, .timer_interrupt)
765         STD_EXCEPTION_COMMON(0xa00, Trap_0a, .UnknownException)
766         STD_EXCEPTION_COMMON(0xb00, Trap_0b, .UnknownException)
767         STD_EXCEPTION_COMMON(0xd00, SingleStep, .SingleStepException)
768         STD_EXCEPTION_COMMON(0xe00, Trap_0e, .UnknownException)
769         STD_EXCEPTION_COMMON(0xf00, PerformanceMonitor, .PerformanceMonitorException)
770         STD_EXCEPTION_COMMON(0x1300, InstructionBreakpoint, .InstructionBreakpointException)
771 #ifdef CONFIG_ALTIVEC
772         STD_EXCEPTION_COMMON(0x1700, AltivecAssist, .AltivecAssistException)
773 #else
774         STD_EXCEPTION_COMMON(0x1700, AltivecAssist, .UnknownException)
775 #endif
776
777 /*
778  * Here we have detected that the kernel stack pointer is bad.
779  * R9 contains the saved CR, r13 points to the paca,
780  * r10 contains the (bad) kernel stack pointer,
781  * r11 and r12 contain the saved SRR0 and SRR1.
782  * We switch to using the paca guard page as an emergency stack,
783  * save the registers there, and call kernel_bad_stack(), which panics.
784  */
785 bad_stack:
786         ld      r1,PACAEMERGSP(r13)
787         subi    r1,r1,64+INT_FRAME_SIZE
788         std     r9,_CCR(r1)
789         std     r10,GPR1(r1)
790         std     r11,_NIP(r1)
791         std     r12,_MSR(r1)
792         mfspr   r11,DAR
793         mfspr   r12,DSISR
794         std     r11,_DAR(r1)
795         std     r12,_DSISR(r1)
796         mflr    r10
797         mfctr   r11
798         mfxer   r12
799         std     r10,_LINK(r1)
800         std     r11,_CTR(r1)
801         std     r12,_XER(r1)
802         SAVE_GPR(0,r1)
803         SAVE_GPR(2,r1)
804         SAVE_4GPRS(3,r1)
805         SAVE_2GPRS(7,r1)
806         SAVE_10GPRS(12,r1)
807         SAVE_10GPRS(22,r1)
808         addi    r11,r1,INT_FRAME_SIZE
809         std     r11,0(r1)
810         li      r12,0
811         std     r12,0(r11)
812         ld      r2,PACATOC(r13)
813 1:      addi    r3,r1,STACK_FRAME_OVERHEAD
814         bl      .kernel_bad_stack
815         b       1b
816
817 /*
818  * Return from an exception with minimal checks.
819  * The caller is assumed to have done EXCEPTION_PROLOG_COMMON.
820  * If interrupts have been enabled, or anything has been
821  * done that might have changed the scheduling status of
822  * any task or sent any task a signal, you should use
823  * ret_from_except or ret_from_except_lite instead of this.
824  */
825 fast_exception_return:
826         ld      r12,_MSR(r1)
827         ld      r11,_NIP(r1)
828         andi.   r3,r12,MSR_RI           /* check if RI is set */
829         beq-    unrecov_fer
830         ld      r3,_CCR(r1)
831         ld      r4,_LINK(r1)
832         ld      r5,_CTR(r1)
833         ld      r6,_XER(r1)
834         mtcr    r3
835         mtlr    r4
836         mtctr   r5
837         mtxer   r6
838         REST_GPR(0, r1)
839         REST_8GPRS(2, r1)
840
841         mfmsr   r10
842         clrrdi  r10,r10,2               /* clear RI (LE is 0 already) */
843         mtmsrd  r10,1
844
845         mtspr   SRR1,r12
846         mtspr   SRR0,r11
847         REST_4GPRS(10, r1)
848         ld      r1,GPR1(r1)
849         rfid
850         b       .       /* prevent speculative execution */
851
852 unrecov_fer:
853         bl      .save_nvgprs
854 1:      addi    r3,r1,STACK_FRAME_OVERHEAD
855         bl      .unrecoverable_exception
856         b       1b
857
858 /*
859  * Here r13 points to the paca, r9 contains the saved CR,
860  * SRR0 and SRR1 are saved in r11 and r12,
861  * r9 - r13 are saved in paca->exgen.
862  */
863         .align  7
864         .globl DataAccess_common
865 DataAccess_common:
866         mfspr   r10,DAR
867         std     r10,PACA_EXGEN+EX_DAR(r13)
868         mfspr   r10,DSISR
869         stw     r10,PACA_EXGEN+EX_DSISR(r13)
870         EXCEPTION_PROLOG_COMMON(0x300, PACA_EXGEN)
871         ld      r3,PACA_EXGEN+EX_DAR(r13)
872         lwz     r4,PACA_EXGEN+EX_DSISR(r13)
873         li      r5,0x300
874         b       .do_hash_page           /* Try to handle as hpte fault */
875
876         .align  7
877         .globl InstructionAccess_common
878 InstructionAccess_common:
879         EXCEPTION_PROLOG_COMMON(0x400, PACA_EXGEN)
880         ld      r3,_NIP(r1)
881         andis.  r4,r12,0x5820
882         li      r5,0x400
883         b       .do_hash_page           /* Try to handle as hpte fault */
884
885         .align  7
886         .globl HardwareInterrupt_common
887         .globl HardwareInterrupt_entry
888 HardwareInterrupt_common:
889         EXCEPTION_PROLOG_COMMON(0x500, PACA_EXGEN)
890 HardwareInterrupt_entry:
891         DISABLE_INTS
892         addi    r3,r1,STACK_FRAME_OVERHEAD
893         bl      .do_IRQ
894         b       .ret_from_except_lite
895
896         .align  7
897         .globl Alignment_common
898 Alignment_common:
899         mfspr   r10,DAR
900         std     r10,PACA_EXGEN+EX_DAR(r13)
901         mfspr   r10,DSISR
902         stw     r10,PACA_EXGEN+EX_DSISR(r13)
903         EXCEPTION_PROLOG_COMMON(0x600, PACA_EXGEN)
904         ld      r3,PACA_EXGEN+EX_DAR(r13)
905         lwz     r4,PACA_EXGEN+EX_DSISR(r13)
906         std     r3,_DAR(r1)
907         std     r4,_DSISR(r1)
908         bl      .save_nvgprs
909         addi    r3,r1,STACK_FRAME_OVERHEAD
910         ENABLE_INTS
911         bl      .AlignmentException
912         b       .ret_from_except
913
914         .align  7
915         .globl ProgramCheck_common
916 ProgramCheck_common:
917         EXCEPTION_PROLOG_COMMON(0x700, PACA_EXGEN)
918         bl      .save_nvgprs
919         addi    r3,r1,STACK_FRAME_OVERHEAD
920         ENABLE_INTS
921         bl      .ProgramCheckException
922         b       .ret_from_except
923
924         .align  7
925         .globl FPUnavailable_common
926 FPUnavailable_common:
927         EXCEPTION_PROLOG_COMMON(0x800, PACA_EXGEN)
928         bne     .load_up_fpu            /* if from user, just load it up */
929         bl      .save_nvgprs
930         addi    r3,r1,STACK_FRAME_OVERHEAD
931         ENABLE_INTS
932         bl      .KernelFPUnavailableException
933         BUG_OPCODE
934
935         .align  7
936         .globl AltivecUnavailable_common
937 AltivecUnavailable_common:
938         EXCEPTION_PROLOG_COMMON(0xf20, PACA_EXGEN)
939 #ifdef CONFIG_ALTIVEC
940         bne     .load_up_altivec        /* if from user, just load it up */
941 #endif
942         bl      .save_nvgprs
943         addi    r3,r1,STACK_FRAME_OVERHEAD
944         ENABLE_INTS
945         bl      .AltivecUnavailableException
946         b       .ret_from_except
947
948 /*
949  * Hash table stuff
950  */
951         .align  7
952 _GLOBAL(do_hash_page)
953         std     r3,_DAR(r1)
954         std     r4,_DSISR(r1)
955
956         andis.  r0,r4,0xa450            /* weird error? */
957         bne-    .handle_page_fault      /* if not, try to insert a HPTE */
958 BEGIN_FTR_SECTION
959         andis.  r0,r4,0x0020            /* Is it a segment table fault? */
960         bne-    .do_ste_alloc           /* If so handle it */
961 END_FTR_SECTION_IFCLR(CPU_FTR_SLB)
962
963         /*
964          * We need to set the _PAGE_USER bit if MSR_PR is set or if we are
965          * accessing a userspace segment (even from the kernel). We assume
966          * kernel addresses always have the high bit set.
967          */
968         rlwinm  r4,r4,32-23,29,29       /* DSISR_STORE -> _PAGE_RW */
969         rotldi  r0,r3,15                /* Move high bit into MSR_PR posn */
970         orc     r0,r12,r0               /* MSR_PR | ~high_bit */
971         rlwimi  r4,r0,32-13,30,30       /* becomes _PAGE_USER access bit */
972         ori     r4,r4,1                 /* add _PAGE_PRESENT */
973
974         /*
975          * On iSeries, we soft-disable interrupts here, then
976          * hard-enable interrupts so that the hash_page code can spin on
977          * the hash_table_lock without problems on a shared processor.
978          */
979         DISABLE_INTS
980
981         /*
982          * r3 contains the faulting address
983          * r4 contains the required access permissions
984          * r5 contains the trap number
985          *
986          * at return r3 = 0 for success
987          */
988         bl      .hash_page              /* build HPTE if possible */
989         cmpdi   r3,0                    /* see if hash_page succeeded */
990
991 #ifdef DO_SOFT_DISABLE
992         /*
993          * If we had interrupts soft-enabled at the point where the
994          * DSI/ISI occurred, and an interrupt came in during hash_page,
995          * handle it now.
996          * We jump to ret_from_except_lite rather than fast_exception_return
997          * because ret_from_except_lite will check for and handle pending
998          * interrupts if necessary.
999          */
1000         beq     .ret_from_except_lite
1001         /* For a hash failure, we don't bother re-enabling interrupts */
1002         ble-    12f
1003
1004         /*
1005          * hash_page couldn't handle it, set soft interrupt enable back
1006          * to what it was before the trap.  Note that .local_irq_restore
1007          * handles any interrupts pending at this point.
1008          */
1009         ld      r3,SOFTE(r1)
1010         bl      .local_irq_restore
1011         b       11f
1012 #else
1013         beq     fast_exception_return   /* Return from exception on success */
1014         ble-    12f                     /* Failure return from hash_page */
1015
1016         /* fall through */
1017 #endif
1018
1019 /* Here we have a page fault that hash_page can't handle. */
1020 _GLOBAL(handle_page_fault)
1021         ENABLE_INTS
1022 11:     ld      r4,_DAR(r1)
1023         ld      r5,_DSISR(r1)
1024         addi    r3,r1,STACK_FRAME_OVERHEAD
1025         bl      .do_page_fault
1026         cmpdi   r3,0
1027         beq+    .ret_from_except_lite
1028         bl      .save_nvgprs
1029         mr      r5,r3
1030         addi    r3,r1,STACK_FRAME_OVERHEAD
1031         lwz     r4,_DAR(r1)
1032         bl      .bad_page_fault
1033         b       .ret_from_except
1034
1035 /* We have a page fault that hash_page could handle but HV refused
1036  * the PTE insertion
1037  */
1038 12:     bl      .save_nvgprs
1039         addi    r3,r1,STACK_FRAME_OVERHEAD
1040         lwz     r4,_DAR(r1)
1041         bl      .low_hash_fault
1042         b       .ret_from_except
1043
1044         /* here we have a segment miss */
1045 _GLOBAL(do_ste_alloc)
1046         bl      .ste_allocate           /* try to insert stab entry */
1047         cmpdi   r3,0
1048         beq+    fast_exception_return
1049         b       .handle_page_fault
1050
1051 /*
1052  * r13 points to the PACA, r9 contains the saved CR,
1053  * r11 and r12 contain the saved SRR0 and SRR1.
1054  * r9 - r13 are saved in paca->exslb.
1055  * We assume we aren't going to take any exceptions during this procedure.
1056  * We assume (DAR >> 60) == 0xc.
1057  */
1058         .align  7
1059 _GLOBAL(do_stab_bolted)
1060         stw     r9,PACA_EXSLB+EX_CCR(r13)       /* save CR in exc. frame */
1061         std     r11,PACA_EXSLB+EX_SRR0(r13)     /* save SRR0 in exc. frame */
1062
1063         /* Hash to the primary group */
1064         ld      r10,PACASTABVIRT(r13)
1065         mfspr   r11,DAR
1066         srdi    r11,r11,28
1067         rldimi  r10,r11,7,52    /* r10 = first ste of the group */
1068
1069         /* Calculate VSID */
1070         /* This is a kernel address, so protovsid = ESID */
1071         ASM_VSID_SCRAMBLE(r11, r9)
1072         rldic   r9,r11,12,16    /* r9 = vsid << 12 */
1073
1074         /* Search the primary group for a free entry */
1075 1:      ld      r11,0(r10)      /* Test valid bit of the current ste    */
1076         andi.   r11,r11,0x80
1077         beq     2f
1078         addi    r10,r10,16
1079         andi.   r11,r10,0x70
1080         bne     1b
1081
1082         /* Stick for only searching the primary group for now.          */
1083         /* At least for now, we use a very simple random castout scheme */
1084         /* Use the TB as a random number ;  OR in 1 to avoid entry 0    */
1085         mftb    r11
1086         rldic   r11,r11,4,57    /* r11 = (r11 << 4) & 0x70 */
1087         ori     r11,r11,0x10
1088
1089         /* r10 currently points to an ste one past the group of interest */
1090         /* make it point to the randomly selected entry                 */
1091         subi    r10,r10,128
1092         or      r10,r10,r11     /* r10 is the entry to invalidate       */
1093
1094         isync                   /* mark the entry invalid               */
1095         ld      r11,0(r10)
1096         rldicl  r11,r11,56,1    /* clear the valid bit */
1097         rotldi  r11,r11,8
1098         std     r11,0(r10)
1099         sync
1100
1101         clrrdi  r11,r11,28      /* Get the esid part of the ste         */
1102         slbie   r11
1103
1104 2:      std     r9,8(r10)       /* Store the vsid part of the ste       */
1105         eieio
1106
1107         mfspr   r11,DAR         /* Get the new esid                     */
1108         clrrdi  r11,r11,28      /* Permits a full 32b of ESID           */
1109         ori     r11,r11,0x90    /* Turn on valid and kp                 */
1110         std     r11,0(r10)      /* Put new entry back into the stab     */
1111
1112         sync
1113
1114         /* All done -- return from exception. */
1115         lwz     r9,PACA_EXSLB+EX_CCR(r13)       /* get saved CR */
1116         ld      r11,PACA_EXSLB+EX_SRR0(r13)     /* get saved SRR0 */
1117
1118         andi.   r10,r12,MSR_RI
1119         beq-    unrecov_slb
1120
1121         mtcrf   0x80,r9                 /* restore CR */
1122
1123         mfmsr   r10
1124         clrrdi  r10,r10,2
1125         mtmsrd  r10,1
1126
1127         mtspr   SRR0,r11
1128         mtspr   SRR1,r12
1129         ld      r9,PACA_EXSLB+EX_R9(r13)
1130         ld      r10,PACA_EXSLB+EX_R10(r13)
1131         ld      r11,PACA_EXSLB+EX_R11(r13)
1132         ld      r12,PACA_EXSLB+EX_R12(r13)
1133         ld      r13,PACA_EXSLB+EX_R13(r13)
1134         rfid
1135         b       .       /* prevent speculative execution */
1136
1137 /*
1138  * r13 points to the PACA, r9 contains the saved CR,
1139  * r11 and r12 contain the saved SRR0 and SRR1.
1140  * r3 has the faulting address
1141  * r9 - r13 are saved in paca->exslb.
1142  * r3 is saved in paca->slb_r3
1143  * We assume we aren't going to take any exceptions during this procedure.
1144  */
1145 _GLOBAL(do_slb_miss)
1146         mflr    r10
1147
1148         stw     r9,PACA_EXSLB+EX_CCR(r13)       /* save CR in exc. frame */
1149         std     r10,PACA_EXSLB+EX_LR(r13)       /* save LR */
1150
1151         bl      .slb_allocate                   /* handle it */
1152
1153         /* All done -- return from exception. */
1154
1155         ld      r10,PACA_EXSLB+EX_LR(r13)
1156         ld      r3,PACA_EXSLB+EX_R3(r13)
1157         lwz     r9,PACA_EXSLB+EX_CCR(r13)       /* get saved CR */
1158 #ifdef CONFIG_PPC_ISERIES
1159         ld      r11,PACALPPACA+LPPACASRR0(r13)  /* get SRR0 value */
1160 #endif /* CONFIG_PPC_ISERIES */
1161
1162         mtlr    r10
1163
1164         andi.   r10,r12,MSR_RI  /* check for unrecoverable exception */
1165         beq-    unrecov_slb
1166
1167 .machine        push
1168 .machine        "power4"
1169         mtcrf   0x80,r9
1170         mtcrf   0x01,r9         /* slb_allocate uses cr0 and cr7 */
1171 .machine        pop
1172
1173 #ifdef CONFIG_PPC_ISERIES
1174         mtspr   SRR0,r11
1175         mtspr   SRR1,r12
1176 #endif /* CONFIG_PPC_ISERIES */
1177         ld      r9,PACA_EXSLB+EX_R9(r13)
1178         ld      r10,PACA_EXSLB+EX_R10(r13)
1179         ld      r11,PACA_EXSLB+EX_R11(r13)
1180         ld      r12,PACA_EXSLB+EX_R12(r13)
1181         ld      r13,PACA_EXSLB+EX_R13(r13)
1182         rfid
1183         b       .       /* prevent speculative execution */
1184
1185 unrecov_slb:
1186         EXCEPTION_PROLOG_COMMON(0x4100, PACA_EXSLB)
1187         DISABLE_INTS
1188         bl      .save_nvgprs
1189 1:      addi    r3,r1,STACK_FRAME_OVERHEAD
1190         bl      .unrecoverable_exception
1191         b       1b
1192
1193
1194 /*
1195  * On pSeries, secondary processors spin in the following code.
1196  * At entry, r3 = this processor's number (physical cpu id)
1197  */
1198 _GLOBAL(pseries_secondary_smp_init)
1199         mr      r24,r3
1200         
1201         /* turn on 64-bit mode */
1202         bl      .enable_64b_mode
1203         isync
1204
1205         /* Copy some CPU settings from CPU 0 */
1206         bl      .__restore_cpu_setup
1207
1208         /* Set up a paca value for this processor. Since we have the
1209          * physical cpu id in r3, we need to search the pacas to find
1210          * which logical id maps to our physical one.
1211          */
1212         LOADADDR(r13, paca)             /* Get base vaddr of paca array  */
1213         li      r5,0                    /* logical cpu id                */
1214 1:      lhz     r6,PACAHWCPUID(r13)     /* Load HW procid from paca      */
1215         cmpw    r6,r24                  /* Compare to our id             */
1216         beq     2f
1217         addi    r13,r13,PACA_SIZE       /* Loop to next PACA on miss     */
1218         addi    r5,r5,1
1219         cmpwi   r5,NR_CPUS
1220         blt     1b
1221
1222 99:     HMT_LOW                         /* Couldn't find our CPU id      */
1223         b       99b
1224
1225 2:      mtspr   SPRG3,r13               /* Save vaddr of paca in SPRG3   */
1226         /* From now on, r24 is expected to be logica cpuid */
1227         mr      r24,r5
1228 3:      HMT_LOW
1229         lbz     r23,PACAPROCSTART(r13)  /* Test if this processor should */
1230                                         /* start.                        */
1231         sync
1232
1233         /* Create a temp kernel stack for use before relocation is on.  */
1234         ld      r1,PACAEMERGSP(r13)
1235         subi    r1,r1,STACK_FRAME_OVERHEAD
1236
1237         cmpwi   0,r23,0
1238 #ifdef CONFIG_SMP
1239 #ifdef SECONDARY_PROCESSORS
1240         bne     .__secondary_start
1241 #endif
1242 #endif
1243         b       3b                      /* Loop until told to go         */
1244 #ifdef CONFIG_PPC_ISERIES
1245 _STATIC(__start_initialization_iSeries)
1246         /* Clear out the BSS */
1247         LOADADDR(r11,__bss_stop)
1248         LOADADDR(r8,__bss_start)
1249         sub     r11,r11,r8              /* bss size                     */
1250         addi    r11,r11,7               /* round up to an even double word */
1251         rldicl. r11,r11,61,3            /* shift right by 3             */
1252         beq     4f
1253         addi    r8,r8,-8
1254         li      r0,0
1255         mtctr   r11                     /* zero this many doublewords   */
1256 3:      stdu    r0,8(r8)
1257         bdnz    3b
1258 4:
1259         LOADADDR(r1,init_thread_union)
1260         addi    r1,r1,THREAD_SIZE
1261         li      r0,0
1262         stdu    r0,-STACK_FRAME_OVERHEAD(r1)
1263
1264         LOADADDR(r3,cpu_specs)
1265         LOADADDR(r4,cur_cpu_spec)
1266         li      r5,0
1267         bl      .identify_cpu
1268
1269         LOADADDR(r2,__toc_start)
1270         addi    r2,r2,0x4000
1271         addi    r2,r2,0x4000
1272
1273         LOADADDR(r9,systemcfg)
1274         SET_REG_TO_CONST(r4, SYSTEMCFG_VIRT_ADDR)
1275         std     r4,0(r9)                /* set the systemcfg pointer */
1276
1277         LOADADDR(r9,naca)
1278         SET_REG_TO_CONST(r4, NACA_VIRT_ADDR)
1279         std     r4,0(r9)                /* set the naca pointer */
1280
1281         /* Get the pointer to the segment table */
1282         ld      r6,PACA(r4)             /* Get the base paca pointer    */
1283         ld      r4,PACASTABVIRT(r6)
1284
1285         bl      .iSeries_early_setup
1286
1287         /* relocation is on at this point */
1288
1289         b       .start_here_common
1290 #endif /* CONFIG_PPC_ISERIES */
1291
1292 #ifdef CONFIG_PPC_MULTIPLATFORM
1293
1294 _STATIC(__mmu_off)
1295         mfmsr   r3
1296         andi.   r0,r3,MSR_IR|MSR_DR
1297         beqlr
1298         andc    r3,r3,r0
1299         mtspr   SPRN_SRR0,r4
1300         mtspr   SPRN_SRR1,r3
1301         sync
1302         rfid
1303         b       .       /* prevent speculative execution */
1304
1305
1306 /*
1307  * Here is our main kernel entry point. We support currently 2 kind of entries
1308  * depending on the value of r5.
1309  *
1310  *   r5 != NULL -> OF entry, we go to prom_init, "legacy" parameter content
1311  *                 in r3...r7
1312  *   
1313  *   r5 == NULL -> kexec style entry. r3 is a physical pointer to the
1314  *                 DT block, r4 is a physical pointer to the kernel itself
1315  *
1316  */
1317 _GLOBAL(__start_initialization_multiplatform)
1318         /*
1319          * Are we booted from a PROM Of-type client-interface ?
1320          */
1321         cmpldi  cr0,r5,0
1322         bne     .__boot_from_prom               /* yes -> prom */
1323
1324         /* Save parameters */
1325         mr      r31,r3
1326         mr      r30,r4
1327
1328         /* Make sure we are running in 64 bits mode */
1329         bl      .enable_64b_mode
1330
1331         /* Setup some critical 970 SPRs before switching MMU off */
1332         bl      .__970_cpu_preinit
1333
1334         /* cpu # */
1335         li      r24,0
1336
1337         /* Switch off MMU if not already */
1338         LOADADDR(r4, .__after_prom_start - KERNELBASE)
1339         add     r4,r4,r30
1340         bl      .__mmu_off
1341         b       .__after_prom_start
1342
1343 _STATIC(__boot_from_prom)
1344         /* Save parameters */
1345         mr      r31,r3
1346         mr      r30,r4
1347         mr      r29,r5
1348         mr      r28,r6
1349         mr      r27,r7
1350
1351         /* Make sure we are running in 64 bits mode */
1352         bl      .enable_64b_mode
1353
1354         /* put a relocation offset into r3 */
1355         bl      .reloc_offset
1356
1357         LOADADDR(r2,__toc_start)
1358         addi    r2,r2,0x4000
1359         addi    r2,r2,0x4000
1360
1361         /* Relocate the TOC from a virt addr to a real addr */
1362         sub     r2,r2,r3
1363
1364         /* Restore parameters */
1365         mr      r3,r31
1366         mr      r4,r30
1367         mr      r5,r29
1368         mr      r6,r28
1369         mr      r7,r27
1370
1371         /* Do all of the interaction with OF client interface */
1372         bl      .prom_init
1373         /* We never return */
1374         trap
1375
1376 /*
1377  * At this point, r3 contains the physical address we are running at,
1378  * returned by prom_init()
1379  */
1380 _STATIC(__after_prom_start)
1381
1382 /*
1383  * We need to run with __start at physical address 0.
1384  * This will leave some code in the first 256B of
1385  * real memory, which are reserved for software use.
1386  * The remainder of the first page is loaded with the fixed
1387  * interrupt vectors.  The next two pages are filled with
1388  * unknown exception placeholders.
1389  *
1390  * Note: This process overwrites the OF exception vectors.
1391  *      r26 == relocation offset
1392  *      r27 == KERNELBASE
1393  */
1394         bl      .reloc_offset
1395         mr      r26,r3
1396         SET_REG_TO_CONST(r27,KERNELBASE)
1397
1398         li      r3,0                    /* target addr */
1399
1400         // XXX FIXME: Use phys returned by OF (r30)
1401         sub     r4,r27,r26              /* source addr                   */
1402                                         /* current address of _start     */
1403                                         /*   i.e. where we are running   */
1404                                         /*      the source addr          */
1405
1406         LOADADDR(r5,copy_to_here)       /* # bytes of memory to copy     */
1407         sub     r5,r5,r27
1408
1409         li      r6,0x100                /* Start offset, the first 0x100 */
1410                                         /* bytes were copied earlier.    */
1411
1412         bl      .copy_and_flush         /* copy the first n bytes        */
1413                                         /* this includes the code being  */
1414                                         /* executed here.                */
1415
1416         LOADADDR(r0, 4f)                /* Jump to the copy of this code */
1417         mtctr   r0                      /* that we just made/relocated   */
1418         bctr
1419
1420 4:      LOADADDR(r5,klimit)
1421         sub     r5,r5,r26
1422         ld      r5,0(r5)                /* get the value of klimit */
1423         sub     r5,r5,r27
1424         bl      .copy_and_flush         /* copy the rest */
1425         b       .start_here_multiplatform
1426
1427 #endif /* CONFIG_PPC_MULTIPLATFORM */
1428
1429 /*
1430  * Copy routine used to copy the kernel to start at physical address 0
1431  * and flush and invalidate the caches as needed.
1432  * r3 = dest addr, r4 = source addr, r5 = copy limit, r6 = start offset
1433  * on exit, r3, r4, r5 are unchanged, r6 is updated to be >= r5.
1434  *
1435  * Note: this routine *only* clobbers r0, r6 and lr
1436  */
1437 _GLOBAL(copy_and_flush)
1438         addi    r5,r5,-8
1439         addi    r6,r6,-8
1440 4:      li      r0,16                   /* Use the least common         */
1441                                         /* denominator cache line       */
1442                                         /* size.  This results in       */
1443                                         /* extra cache line flushes     */
1444                                         /* but operation is correct.    */
1445                                         /* Can't get cache line size    */
1446                                         /* from NACA as it is being     */
1447                                         /* moved too.                   */
1448
1449         mtctr   r0                      /* put # words/line in ctr      */
1450 3:      addi    r6,r6,8                 /* copy a cache line            */
1451         ldx     r0,r6,r4
1452         stdx    r0,r6,r3
1453         bdnz    3b
1454         dcbst   r6,r3                   /* write it to memory           */
1455         sync
1456         icbi    r6,r3                   /* flush the icache line        */
1457         cmpld   0,r6,r5
1458         blt     4b
1459         sync
1460         addi    r5,r5,8
1461         addi    r6,r6,8
1462         blr
1463
1464 .align 8
1465 copy_to_here:
1466
1467 /*
1468  * load_up_fpu(unused, unused, tsk)
1469  * Disable FP for the task which had the FPU previously,
1470  * and save its floating-point registers in its thread_struct.
1471  * Enables the FPU for use in the kernel on return.
1472  * On SMP we know the fpu is free, since we give it up every
1473  * switch (ie, no lazy save of the FP registers).
1474  * On entry: r13 == 'current' && last_task_used_math != 'current'
1475  */
1476 _STATIC(load_up_fpu)
1477         mfmsr   r5                      /* grab the current MSR */
1478         ori     r5,r5,MSR_FP
1479         mtmsrd  r5                      /* enable use of fpu now */
1480         isync
1481 /*
1482  * For SMP, we don't do lazy FPU switching because it just gets too
1483  * horrendously complex, especially when a task switches from one CPU
1484  * to another.  Instead we call giveup_fpu in switch_to.
1485  *
1486  */
1487 #ifndef CONFIG_SMP
1488         ld      r3,last_task_used_math@got(r2)
1489         ld      r4,0(r3)
1490         cmpdi   0,r4,0
1491         beq     1f
1492         /* Save FP state to last_task_used_math's THREAD struct */
1493         addi    r4,r4,THREAD
1494         SAVE_32FPRS(0, r4)
1495         mffs    fr0
1496         stfd    fr0,THREAD_FPSCR(r4)
1497         /* Disable FP for last_task_used_math */
1498         ld      r5,PT_REGS(r4)
1499         ld      r4,_MSR-STACK_FRAME_OVERHEAD(r5)
1500         li      r6,MSR_FP|MSR_FE0|MSR_FE1
1501         andc    r4,r4,r6
1502         std     r4,_MSR-STACK_FRAME_OVERHEAD(r5)
1503 1:
1504 #endif /* CONFIG_SMP */
1505         /* enable use of FP after return */
1506         ld      r4,PACACURRENT(r13)
1507         addi    r5,r4,THREAD            /* Get THREAD */
1508         ld      r4,THREAD_FPEXC_MODE(r5)
1509         ori     r12,r12,MSR_FP
1510         or      r12,r12,r4
1511         std     r12,_MSR(r1)
1512         lfd     fr0,THREAD_FPSCR(r5)
1513         mtfsf   0xff,fr0
1514         REST_32FPRS(0, r5)
1515 #ifndef CONFIG_SMP
1516         /* Update last_task_used_math to 'current' */
1517         subi    r4,r5,THREAD            /* Back to 'current' */
1518         std     r4,0(r3)
1519 #endif /* CONFIG_SMP */
1520         /* restore registers and return */
1521         b       fast_exception_return
1522
1523 /*
1524  * disable_kernel_fp()
1525  * Disable the FPU.
1526  */
1527 _GLOBAL(disable_kernel_fp)
1528         mfmsr   r3
1529         rldicl  r0,r3,(63-MSR_FP_LG),1
1530         rldicl  r3,r0,(MSR_FP_LG+1),0
1531         mtmsrd  r3                      /* disable use of fpu now */
1532         isync
1533         blr
1534
1535 /*
1536  * giveup_fpu(tsk)
1537  * Disable FP for the task given as the argument,
1538  * and save the floating-point registers in its thread_struct.
1539  * Enables the FPU for use in the kernel on return.
1540  */
1541 _GLOBAL(giveup_fpu)
1542         mfmsr   r5
1543         ori     r5,r5,MSR_FP
1544         mtmsrd  r5                      /* enable use of fpu now */
1545         isync
1546         cmpdi   0,r3,0
1547         beqlr-                          /* if no previous owner, done */
1548         addi    r3,r3,THREAD            /* want THREAD of task */
1549         ld      r5,PT_REGS(r3)
1550         cmpdi   0,r5,0
1551         SAVE_32FPRS(0, r3)
1552         mffs    fr0
1553         stfd    fr0,THREAD_FPSCR(r3)
1554         beq     1f
1555         ld      r4,_MSR-STACK_FRAME_OVERHEAD(r5)
1556         li      r3,MSR_FP|MSR_FE0|MSR_FE1
1557         andc    r4,r4,r3                /* disable FP for previous task */
1558         std     r4,_MSR-STACK_FRAME_OVERHEAD(r5)
1559 1:
1560 #ifndef CONFIG_SMP
1561         li      r5,0
1562         ld      r4,last_task_used_math@got(r2)
1563         std     r5,0(r4)
1564 #endif /* CONFIG_SMP */
1565         blr
1566
1567
1568 #ifdef CONFIG_ALTIVEC
1569                 
1570 /*
1571  * load_up_altivec(unused, unused, tsk)
1572  * Disable VMX for the task which had it previously,
1573  * and save its vector registers in its thread_struct.
1574  * Enables the VMX for use in the kernel on return.
1575  * On SMP we know the VMX is free, since we give it up every
1576  * switch (ie, no lazy save of the vector registers).
1577  * On entry: r13 == 'current' && last_task_used_altivec != 'current'
1578  */
1579 _STATIC(load_up_altivec)
1580         mfmsr   r5                      /* grab the current MSR */
1581         oris    r5,r5,MSR_VEC@h
1582         mtmsrd  r5                      /* enable use of VMX now */
1583         isync
1584         
1585 /*
1586  * For SMP, we don't do lazy VMX switching because it just gets too
1587  * horrendously complex, especially when a task switches from one CPU
1588  * to another.  Instead we call giveup_altvec in switch_to.
1589  * VRSAVE isn't dealt with here, that is done in the normal context
1590  * switch code. Note that we could rely on vrsave value to eventually
1591  * avoid saving all of the VREGs here...
1592  */
1593 #ifndef CONFIG_SMP
1594         ld      r3,last_task_used_altivec@got(r2)
1595         ld      r4,0(r3)
1596         cmpdi   0,r4,0
1597         beq     1f
1598         /* Save VMX state to last_task_used_altivec's THREAD struct */
1599         addi    r4,r4,THREAD
1600         SAVE_32VRS(0,r5,r4)
1601         mfvscr  vr0
1602         li      r10,THREAD_VSCR
1603         stvx    vr0,r10,r4
1604         /* Disable VMX for last_task_used_altivec */
1605         ld      r5,PT_REGS(r4)
1606         ld      r4,_MSR-STACK_FRAME_OVERHEAD(r5)
1607         lis     r6,MSR_VEC@h
1608         andc    r4,r4,r6
1609         std     r4,_MSR-STACK_FRAME_OVERHEAD(r5)
1610 1:
1611 #endif /* CONFIG_SMP */
1612         /* Hack: if we get an altivec unavailable trap with VRSAVE
1613          * set to all zeros, we assume this is a broken application
1614          * that fails to set it properly, and thus we switch it to
1615          * all 1's
1616          */
1617         mfspr   r4,SPRN_VRSAVE
1618         cmpdi   0,r4,0
1619         bne+    1f
1620         li      r4,-1
1621         mtspr   SPRN_VRSAVE,r4
1622 1:
1623         /* enable use of VMX after return */
1624         ld      r4,PACACURRENT(r13)
1625         addi    r5,r4,THREAD            /* Get THREAD */
1626         oris    r12,r12,MSR_VEC@h
1627         std     r12,_MSR(r1)
1628         li      r4,1
1629         li      r10,THREAD_VSCR
1630         stw     r4,THREAD_USED_VR(r5)
1631         lvx     vr0,r10,r5
1632         mtvscr  vr0
1633         REST_32VRS(0,r4,r5)
1634 #ifndef CONFIG_SMP
1635         /* Update last_task_used_math to 'current' */
1636         subi    r4,r5,THREAD            /* Back to 'current' */
1637         std     r4,0(r3)
1638 #endif /* CONFIG_SMP */
1639         /* restore registers and return */
1640         b       fast_exception_return
1641
1642 /*
1643  * disable_kernel_altivec()
1644  * Disable the VMX.
1645  */
1646 _GLOBAL(disable_kernel_altivec)
1647         mfmsr   r3
1648         rldicl  r0,r3,(63-MSR_VEC_LG),1
1649         rldicl  r3,r0,(MSR_VEC_LG+1),0
1650         mtmsrd  r3                      /* disable use of VMX now */
1651         isync
1652         blr
1653
1654 /*
1655  * giveup_altivec(tsk)
1656  * Disable VMX for the task given as the argument,
1657  * and save the vector registers in its thread_struct.
1658  * Enables the VMX for use in the kernel on return.
1659  */
1660 _GLOBAL(giveup_altivec)
1661         mfmsr   r5
1662         oris    r5,r5,MSR_VEC@h
1663         mtmsrd  r5                      /* enable use of VMX now */
1664         isync
1665         cmpdi   0,r3,0
1666         beqlr-                          /* if no previous owner, done */
1667         addi    r3,r3,THREAD            /* want THREAD of task */
1668         ld      r5,PT_REGS(r3)
1669         cmpdi   0,r5,0
1670         SAVE_32VRS(0,r4,r3)
1671         mfvscr  vr0
1672         li      r4,THREAD_VSCR
1673         stvx    vr0,r4,r3
1674         beq     1f
1675         ld      r4,_MSR-STACK_FRAME_OVERHEAD(r5)
1676         lis     r3,MSR_VEC@h
1677         andc    r4,r4,r3                /* disable FP for previous task */
1678         std     r4,_MSR-STACK_FRAME_OVERHEAD(r5)
1679 1:
1680 #ifndef CONFIG_SMP
1681         li      r5,0
1682         ld      r4,last_task_used_altivec@got(r2)
1683         std     r5,0(r4)
1684 #endif /* CONFIG_SMP */
1685         blr
1686
1687 #endif /* CONFIG_ALTIVEC */
1688
1689 #ifdef CONFIG_SMP
1690 #ifdef CONFIG_PPC_PMAC
1691 /*
1692  * On PowerMac, secondary processors starts from the reset vector, which
1693  * is temporarily turned into a call to one of the functions below.
1694  */
1695         .section ".text";
1696         .align 2 ;
1697
1698         .globl  pmac_secondary_start_1  
1699 pmac_secondary_start_1: 
1700         li      r24, 1
1701         b       .pmac_secondary_start
1702         
1703         .globl pmac_secondary_start_2
1704 pmac_secondary_start_2: 
1705         li      r24, 2
1706         b       .pmac_secondary_start
1707         
1708         .globl pmac_secondary_start_3
1709 pmac_secondary_start_3:
1710         li      r24, 3
1711         b       .pmac_secondary_start
1712         
1713 _GLOBAL(pmac_secondary_start)
1714         /* turn on 64-bit mode */
1715         bl      .enable_64b_mode
1716         isync
1717
1718         /* Copy some CPU settings from CPU 0 */
1719         bl      .__restore_cpu_setup
1720
1721         /* pSeries do that early though I don't think we really need it */
1722         mfmsr   r3
1723         ori     r3,r3,MSR_RI
1724         mtmsrd  r3                      /* RI on */
1725
1726         /* Set up a paca value for this processor. */
1727         LOADADDR(r4, paca)               /* Get base vaddr of paca array        */
1728         mulli   r13,r24,PACA_SIZE        /* Calculate vaddr of right paca */
1729         add     r13,r13,r4              /* for this processor.          */
1730         mtspr   SPRG3,r13                /* Save vaddr of paca in SPRG3 */
1731
1732         /* Create a temp kernel stack for use before relocation is on.  */
1733         ld      r1,PACAEMERGSP(r13)
1734         subi    r1,r1,STACK_FRAME_OVERHEAD
1735
1736         b       .__secondary_start
1737
1738 #endif /* CONFIG_PPC_PMAC */
1739
1740 /*
1741  * This function is called after the master CPU has released the
1742  * secondary processors.  The execution environment is relocation off.
1743  * The paca for this processor has the following fields initialized at
1744  * this point:
1745  *   1. Processor number
1746  *   2. Segment table pointer (virtual address)
1747  * On entry the following are set:
1748  *   r1 = stack pointer.  vaddr for iSeries, raddr (temp stack) for pSeries
1749  *   r24   = cpu# (in Linux terms)
1750  *   r13   = paca virtual address
1751  *   SPRG3 = paca virtual address
1752  */
1753 _GLOBAL(__secondary_start)
1754
1755         HMT_MEDIUM                      /* Set thread priority to MEDIUM */
1756
1757         ld      r2,PACATOC(r13)
1758         li      r6,0
1759         stb     r6,PACAPROCENABLED(r13)
1760
1761 #ifndef CONFIG_PPC_ISERIES
1762         /* Initialize the page table pointer register. */
1763         LOADADDR(r6,_SDR1)
1764         ld      r6,0(r6)                /* get the value of _SDR1        */
1765         mtspr   SDR1,r6                 /* set the htab location         */
1766 #endif
1767         /* Initialize the first segment table (or SLB) entry             */
1768         ld      r3,PACASTABVIRT(r13)    /* get addr of segment table     */
1769         bl      .stab_initialize
1770
1771         /* Initialize the kernel stack.  Just a repeat for iSeries.      */
1772         LOADADDR(r3,current_set)
1773         sldi    r28,r24,3               /* get current_set[cpu#]         */
1774         ldx     r1,r3,r28
1775         addi    r1,r1,THREAD_SIZE-STACK_FRAME_OVERHEAD
1776         std     r1,PACAKSAVE(r13)
1777
1778         ld      r3,PACASTABREAL(r13)    /* get raddr of segment table    */
1779         ori     r4,r3,1                 /* turn on valid bit             */
1780
1781 #ifdef CONFIG_PPC_ISERIES
1782         li      r0,-1                   /* hypervisor call */
1783         li      r3,1
1784         sldi    r3,r3,63                /* 0x8000000000000000 */
1785         ori     r3,r3,4                 /* 0x8000000000000004 */
1786         sc                              /* HvCall_setASR */
1787 #else
1788         /* set the ASR */
1789         li      r3,SYSTEMCFG_PHYS_ADDR  /* r3 = ptr to systemcfg         */
1790         lwz     r3,PLATFORM(r3)         /* r3 = platform flags           */
1791         cmpldi  r3,PLATFORM_PSERIES_LPAR
1792         bne     98f
1793         mfspr   r3,PVR
1794         srwi    r3,r3,16
1795         cmpwi   r3,0x37                 /* SStar  */
1796         beq     97f
1797         cmpwi   r3,0x36                 /* IStar  */
1798         beq     97f
1799         cmpwi   r3,0x34                 /* Pulsar */
1800         bne     98f
1801 97:     li      r3,H_SET_ASR            /* hcall = H_SET_ASR */
1802         HVSC                            /* Invoking hcall */
1803         b       99f
1804 98:                                     /* !(rpa hypervisor) || !(star)  */
1805         mtasr   r4                      /* set the stab location         */
1806 99:
1807 #endif
1808         li      r7,0
1809         mtlr    r7
1810
1811         /* enable MMU and jump to start_secondary */
1812         LOADADDR(r3,.start_secondary_prolog)
1813         SET_REG_TO_CONST(r4, MSR_KERNEL)
1814 #ifdef DO_SOFT_DISABLE
1815         ori     r4,r4,MSR_EE
1816 #endif
1817         mtspr   SRR0,r3
1818         mtspr   SRR1,r4
1819         rfid
1820         b       .       /* prevent speculative execution */
1821
1822 /* 
1823  * Running with relocation on at this point.  All we want to do is
1824  * zero the stack back-chain pointer before going into C code.
1825  */
1826 _GLOBAL(start_secondary_prolog)
1827         li      r3,0
1828         std     r3,0(r1)                /* Zero the stack frame pointer */
1829         bl      .start_secondary
1830 #endif
1831
1832 /*
1833  * This subroutine clobbers r11 and r12
1834  */
1835 _GLOBAL(enable_64b_mode)
1836         mfmsr   r11                     /* grab the current MSR */
1837         li      r12,1
1838         rldicr  r12,r12,MSR_SF_LG,(63-MSR_SF_LG)
1839         or      r11,r11,r12
1840         li      r12,1
1841         rldicr  r12,r12,MSR_ISF_LG,(63-MSR_ISF_LG)
1842         or      r11,r11,r12
1843         mtmsrd  r11
1844         isync
1845         blr
1846
1847 #ifdef CONFIG_PPC_MULTIPLATFORM
1848 /*
1849  * This is where the main kernel code starts.
1850  */
1851 _STATIC(start_here_multiplatform)
1852         /* get a new offset, now that the kernel has moved. */
1853         bl      .reloc_offset
1854         mr      r26,r3
1855
1856         /* Clear out the BSS. It may have been done in prom_init,
1857          * already but that's irrelevant since prom_init will soon
1858          * be detached from the kernel completely. Besides, we need
1859          * to clear it now for kexec-style entry.
1860          */
1861         LOADADDR(r11,__bss_stop)
1862         LOADADDR(r8,__bss_start)
1863         sub     r11,r11,r8              /* bss size                     */
1864         addi    r11,r11,7               /* round up to an even double word */
1865         rldicl. r11,r11,61,3            /* shift right by 3             */
1866         beq     4f
1867         addi    r8,r8,-8
1868         li      r0,0
1869         mtctr   r11                     /* zero this many doublewords   */
1870 3:      stdu    r0,8(r8)
1871         bdnz    3b
1872 4:
1873
1874         mfmsr   r6
1875         ori     r6,r6,MSR_RI
1876         mtmsrd  r6                      /* RI on */
1877
1878         /* setup the systemcfg pointer which is needed by *tab_initialize       */
1879         LOADADDR(r6,systemcfg)
1880         sub     r6,r6,r26               /* addr of the variable systemcfg */
1881         li      r27,SYSTEMCFG_PHYS_ADDR
1882         std     r27,0(r6)               /* set the value of systemcfg   */
1883
1884         /* setup the naca pointer which is needed by *tab_initialize    */
1885         LOADADDR(r6,naca)
1886         sub     r6,r6,r26               /* addr of the variable naca    */
1887         li      r27,NACA_PHYS_ADDR
1888         std     r27,0(r6)               /* set the value of naca        */
1889
1890 #ifdef CONFIG_HMT
1891         /* Start up the second thread on cpu 0 */
1892         mfspr   r3,PVR
1893         srwi    r3,r3,16
1894         cmpwi   r3,0x34                 /* Pulsar  */
1895         beq     90f
1896         cmpwi   r3,0x36                 /* Icestar */
1897         beq     90f
1898         cmpwi   r3,0x37                 /* SStar   */
1899         beq     90f
1900         b       91f                     /* HMT not supported */
1901 90:     li      r3,0
1902         bl      .hmt_start_secondary
1903 91:
1904 #endif
1905
1906         /* The following gets the stack and TOC set up with the regs */
1907         /* pointing to the real addr of the kernel stack.  This is   */
1908         /* all done to support the C function call below which sets  */
1909         /* up the htab.  This is done because we have relocated the  */
1910         /* kernel but are still running in real mode. */
1911
1912         LOADADDR(r3,init_thread_union)
1913         sub     r3,r3,r26
1914
1915         /* set up a stack pointer (physical address) */
1916         addi    r1,r3,THREAD_SIZE
1917         li      r0,0
1918         stdu    r0,-STACK_FRAME_OVERHEAD(r1)
1919
1920         /* set up the TOC (physical address) */
1921         LOADADDR(r2,__toc_start)
1922         addi    r2,r2,0x4000
1923         addi    r2,r2,0x4000
1924         sub     r2,r2,r26
1925
1926         LOADADDR(r3,cpu_specs)
1927         sub     r3,r3,r26
1928         LOADADDR(r4,cur_cpu_spec)
1929         sub     r4,r4,r26
1930         mr      r5,r26
1931         bl      .identify_cpu
1932
1933         /* Save some low level config HIDs of CPU0 to be copied to
1934          * other CPUs later on, or used for suspend/resume
1935          */
1936         bl      .__save_cpu_setup
1937         sync
1938
1939         /* Setup a valid physical PACA pointer in SPRG3 for early_setup
1940          * note that boot_cpuid can always be 0 nowadays since there is
1941          * nowhere it can be initialized differently before we reach this
1942          * code
1943          */
1944         LOADADDR(r27, boot_cpuid)
1945         sub     r27,r27,r26
1946         lwz     r27,0(r27)
1947
1948         LOADADDR(r24, paca)             /* Get base vaddr of paca array  */
1949         mulli   r13,r27,PACA_SIZE       /* Calculate vaddr of right paca */
1950         add     r13,r13,r24             /* for this processor.           */
1951         sub     r13,r13,r26             /* convert to physical addr      */
1952         mtspr   SPRG3,r13               /* PPPBBB: Temp... -Peter */
1953         
1954         /* Do very early kernel initializations, including initial hash table,
1955          * stab and slb setup before we turn on relocation.     */
1956
1957         /* Restore parameters passed from prom_init/kexec */
1958         mr      r3,r31
1959         bl      .early_setup
1960
1961         /* set the ASR */
1962         ld      r3,PACASTABREAL(r13)
1963         ori     r4,r3,1                 /* turn on valid bit             */
1964         li      r3,SYSTEMCFG_PHYS_ADDR  /* r3 = ptr to systemcfg */
1965         lwz     r3,PLATFORM(r3)         /* r3 = platform flags */
1966         cmpldi  r3,PLATFORM_PSERIES_LPAR
1967         bne     98f
1968         mfspr   r3,PVR
1969         srwi    r3,r3,16
1970         cmpwi   r3,0x37                 /* SStar */
1971         beq     97f
1972         cmpwi   r3,0x36                 /* IStar  */
1973         beq     97f
1974         cmpwi   r3,0x34                 /* Pulsar */
1975         bne     98f
1976 97:     li      r3,H_SET_ASR            /* hcall = H_SET_ASR */
1977         HVSC                            /* Invoking hcall */
1978         b       99f
1979 98:                                     /* !(rpa hypervisor) || !(star) */
1980         mtasr   r4                      /* set the stab location        */
1981 99:
1982         /* Set SDR1 (hash table pointer) */
1983         li      r3,SYSTEMCFG_PHYS_ADDR  /* r3 = ptr to systemcfg */
1984         lwz     r3,PLATFORM(r3)         /* r3 = platform flags */
1985         /* Test if bit 0 is set (LPAR bit) */
1986         andi.   r3,r3,0x1
1987         bne     98f
1988         LOADADDR(r6,_SDR1)              /* Only if NOT LPAR */
1989         sub     r6,r6,r26
1990         ld      r6,0(r6)                /* get the value of _SDR1 */
1991         mtspr   SDR1,r6                 /* set the htab location  */
1992 98: 
1993         LOADADDR(r3,.start_here_common)
1994         SET_REG_TO_CONST(r4, MSR_KERNEL)
1995         mtspr   SRR0,r3
1996         mtspr   SRR1,r4
1997         rfid
1998         b       .       /* prevent speculative execution */
1999 #endif /* CONFIG_PPC_MULTIPLATFORM */
2000         
2001         /* This is where all platforms converge execution */
2002 _STATIC(start_here_common)
2003         /* relocation is on at this point */
2004
2005         /* The following code sets up the SP and TOC now that we are */
2006         /* running with translation enabled. */
2007
2008         LOADADDR(r3,init_thread_union)
2009
2010         /* set up the stack */
2011         addi    r1,r3,THREAD_SIZE
2012         li      r0,0
2013         stdu    r0,-STACK_FRAME_OVERHEAD(r1)
2014
2015         /* Apply the CPUs-specific fixups (nop out sections not relevant
2016          * to this CPU
2017          */
2018         li      r3,0
2019         bl      .do_cpu_ftr_fixups
2020
2021         /* setup the systemcfg pointer */
2022         LOADADDR(r9,systemcfg)
2023         SET_REG_TO_CONST(r8, SYSTEMCFG_VIRT_ADDR)
2024         std     r8,0(r9)
2025
2026         /* setup the naca pointer */
2027         LOADADDR(r9,naca)
2028         SET_REG_TO_CONST(r8, NACA_VIRT_ADDR)
2029         std     r8,0(r9)                /* set the value of the naca ptr */
2030
2031         LOADADDR(r26, boot_cpuid)
2032         lwz     r26,0(r26)
2033
2034         LOADADDR(r24, paca)             /* Get base vaddr of paca array  */
2035         mulli   r13,r26,PACA_SIZE       /* Calculate vaddr of right paca */
2036         add     r13,r13,r24             /* for this processor.           */
2037         mtspr   SPRG3,r13
2038
2039         /* ptr to current */
2040         LOADADDR(r4,init_task)
2041         std     r4,PACACURRENT(r13)
2042
2043         /* Load the TOC */
2044         ld      r2,PACATOC(r13)
2045         std     r1,PACAKSAVE(r13)
2046
2047         bl      .setup_system
2048
2049         /* Load up the kernel context */
2050 5:
2051 #ifdef DO_SOFT_DISABLE
2052         li      r5,0
2053         stb     r5,PACAPROCENABLED(r13) /* Soft Disabled */
2054         mfmsr   r5
2055         ori     r5,r5,MSR_EE            /* Hard Enabled */
2056         mtmsrd  r5
2057 #endif
2058
2059         bl .start_kernel
2060
2061 _GLOBAL(__setup_cpu_power3)
2062         blr
2063
2064 _GLOBAL(hmt_init)
2065 #ifdef CONFIG_HMT
2066         LOADADDR(r5, hmt_thread_data)
2067         mfspr   r7,PVR
2068         srwi    r7,r7,16
2069         cmpwi   r7,0x34                 /* Pulsar  */
2070         beq     90f
2071         cmpwi   r7,0x36                 /* Icestar */
2072         beq     91f
2073         cmpwi   r7,0x37                 /* SStar   */
2074         beq     91f
2075         b       101f
2076 90:     mfspr   r6,PIR
2077         andi.   r6,r6,0x1f
2078         b       92f
2079 91:     mfspr   r6,PIR
2080         andi.   r6,r6,0x3ff
2081 92:     sldi    r4,r24,3
2082         stwx    r6,r5,r4
2083         bl      .hmt_start_secondary
2084         b       101f
2085
2086 __hmt_secondary_hold:
2087         LOADADDR(r5, hmt_thread_data)
2088         clrldi  r5,r5,4
2089         li      r7,0
2090         mfspr   r6,PIR
2091         mfspr   r8,PVR
2092         srwi    r8,r8,16
2093         cmpwi   r8,0x34
2094         bne     93f
2095         andi.   r6,r6,0x1f
2096         b       103f
2097 93:     andi.   r6,r6,0x3f
2098
2099 103:    lwzx    r8,r5,r7
2100         cmpw    r8,r6
2101         beq     104f
2102         addi    r7,r7,8
2103         b       103b
2104
2105 104:    addi    r7,r7,4
2106         lwzx    r9,r5,r7
2107         mr      r24,r9
2108 101:
2109 #endif
2110         mr      r3,r24
2111         b       .pseries_secondary_smp_init
2112
2113 #ifdef CONFIG_HMT
2114 _GLOBAL(hmt_start_secondary)
2115         LOADADDR(r4,__hmt_secondary_hold)
2116         clrldi  r4,r4,4
2117         mtspr   NIADORM, r4
2118         mfspr   r4, MSRDORM
2119         li      r5, -65
2120         and     r4, r4, r5
2121         mtspr   MSRDORM, r4
2122         lis     r4,0xffef
2123         ori     r4,r4,0x7403
2124         mtspr   TSC, r4
2125         li      r4,0x1f4
2126         mtspr   TST, r4
2127         mfspr   r4, HID0
2128         ori     r4, r4, 0x1
2129         mtspr   HID0, r4
2130         mfspr   r4, CTRLF
2131         oris    r4, r4, 0x40
2132         mtspr   CTRLT, r4
2133         blr
2134 #endif
2135
2136 #if defined(CONFIG_SMP) && !defined(CONFIG_PPC_ISERIES)
2137 _GLOBAL(smp_release_cpus)
2138         /* All secondary cpus are spinning on a common
2139          * spinloop, release them all now so they can start
2140          * to spin on their individual paca spinloops.
2141          * For non SMP kernels, the secondary cpus never
2142          * get out of the common spinloop.
2143          */
2144         li      r3,1
2145         LOADADDR(r5,__secondary_hold_spinloop)
2146         std     r3,0(r5)
2147         sync
2148         blr
2149 #endif /* CONFIG_SMP && !CONFIG_PPC_ISERIES */
2150
2151
2152 /*
2153  * We put a few things here that have to be page-aligned.
2154  * This stuff goes at the beginning of the data segment,
2155  * which is page-aligned.
2156  */
2157         .data
2158         .align  12
2159         .globl  sdata
2160 sdata:
2161         .globl  empty_zero_page
2162 empty_zero_page:
2163         .space  4096
2164
2165         .globl  swapper_pg_dir
2166 swapper_pg_dir:
2167         .space  4096
2168
2169         .globl  ioremap_dir
2170 ioremap_dir:
2171         .space  4096
2172
2173 /* 1 page segment table per cpu (max 48, cpu0 allocated at STAB0_PHYS_ADDR) */
2174         .globl  stab_array
2175 stab_array:
2176         .space  4096 * 48
2177         
2178 /*
2179  * This space gets a copy of optional info passed to us by the bootstrap
2180  * Used to pass parameters into the kernel like root=/dev/sda1, etc.
2181  */
2182         .globl  cmd_line
2183 cmd_line:
2184         .space  COMMAND_LINE_SIZE