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