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