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