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