fix to allow usb modules to compile
[linux-2.4.21-pre4.git] / arch / ppc / kernel / head.S
1 /*
2  * BK Id: SCCS/s.head.S 1.78 12/18/02 00:17:27 benh
3  */
4 /*
5  *  PowerPC version 
6  *    Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
7  *
8  *  Rewritten by Cort Dougan (cort@cs.nmt.edu) for PReP
9  *    Copyright (C) 1996 Cort Dougan <cort@cs.nmt.edu>
10  *  Adapted for Power Macintosh by Paul Mackerras.
11  *  Low-level exception handlers and MMU support
12  *  rewritten by Paul Mackerras.
13  *    Copyright (C) 1996 Paul Mackerras.
14  *  MPC8xx modifications Copyright (C) 1997 Dan Malek (dmalek@jlc.net).
15  *  Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk).
16  *
17  *  This file contains the low-level support and setup for the
18  *  PowerPC platform, including trap and interrupt dispatch.
19  *  (The PPC 8xx embedded CPUs use head_8xx.S instead.)
20  *
21  *  This program is free software; you can redistribute it and/or
22  *  modify it under the terms of the GNU General Public License
23  *  as published by the Free Software Foundation; either version
24  *  2 of the License, or (at your option) any later version.
25  *
26  */
27
28 #include <linux/config.h>
29 #include <linux/threads.h>
30 #include <asm/processor.h>
31 #include <asm/page.h>
32 #include <asm/mmu.h>
33 #include <asm/pgtable.h>
34 #include <asm/cputable.h>
35 #include <asm/cache.h>
36 #include <asm/ppc_asm.h>
37 #include "ppc_defs.h"
38
39 #ifdef CONFIG_APUS
40 #include <asm/amigappc.h>
41 #endif
42
43 #ifdef CONFIG_PPC64BRIDGE
44 #define LOAD_BAT(n, reg, RA, RB)        \
45         ld      RA,(n*32)+0(reg);       \
46         ld      RB,(n*32)+8(reg);       \
47         mtspr   IBAT##n##U,RA;          \
48         mtspr   IBAT##n##L,RB;          \
49         ld      RA,(n*32)+16(reg);      \
50         ld      RB,(n*32)+24(reg);      \
51         mtspr   DBAT##n##U,RA;          \
52         mtspr   DBAT##n##L,RB;          \
53
54 #else /* CONFIG_PPC64BRIDGE */
55
56 /* 601 only have IBAT; cr0.eq is set on 601 when using this macro */
57 #define LOAD_BAT(n, reg, RA, RB)        \
58         /* see the comment for clear_bats() -- Cort */ \
59         li      RA,0;                   \
60         mtspr   IBAT##n##U,RA;          \
61         mtspr   DBAT##n##U,RA;          \
62         lwz     RA,(n*16)+0(reg);       \
63         lwz     RB,(n*16)+4(reg);       \
64         mtspr   IBAT##n##U,RA;          \
65         mtspr   IBAT##n##L,RB;          \
66         beq     1f;                     \
67         lwz     RA,(n*16)+8(reg);       \
68         lwz     RB,(n*16)+12(reg);      \
69         mtspr   DBAT##n##U,RA;          \
70         mtspr   DBAT##n##L,RB;          \
71 1:
72 #endif /* CONFIG_PPC64BRIDGE */  
73
74         .text
75         .stabs  "arch/ppc/kernel/",N_SO,0,0,0f
76         .stabs  "head.S",N_SO,0,0,0f
77 0:
78         .globl  _stext
79 _stext:
80
81 /*
82  * _start is defined this way because the XCOFF loader in the OpenFirmware
83  * on the powermac expects the entry point to be a procedure descriptor.
84  */
85         .text
86         .globl  _start
87 _start:
88         /* 
89          * These are here for legacy reasons, the kernel used to
90          * need to look like a coff function entry for the pmac
91          * but we're always started by some kind of bootloader now.
92          *  -- Cort
93          */
94         nop     /* used by __secondary_hold on prep (mtx) and chrp smp */
95         nop     /* used by __secondary_hold on prep (mtx) and chrp smp */
96         nop
97
98 /* PMAC
99  * Enter here with the kernel text, data and bss loaded starting at
100  * 0, running with virtual == physical mapping.
101  * r5 points to the prom entry point (the client interface handler
102  * address).  Address translation is turned on, with the prom
103  * managing the hash table.  Interrupts are disabled.  The stack
104  * pointer (r1) points to just below the end of the half-meg region
105  * from 0x380000 - 0x400000, which is mapped in already.
106  *
107  * If we are booted from MacOS via BootX, we enter with the kernel
108  * image loaded somewhere, and the following values in registers:
109  *  r3: 'BooX' (0x426f6f58)
110  *  r4: virtual address of boot_infos_t
111  *  r5: 0
112  *
113  * APUS
114  *   r3: 'APUS'
115  *   r4: physical address of memory base
116  *   Linux/m68k style BootInfo structure at &_end.
117  *
118  * PREP
119  * This is jumped to on prep systems right after the kernel is relocated
120  * to its proper place in memory by the boot loader.  The expected layout
121  * of the regs is:
122  *   r3: ptr to residual data
123  *   r4: initrd_start or if no initrd then 0
124  *   r5: initrd_end - unused if r4 is 0
125  *   r6: Start of command line string
126  *   r7: End of command line string
127  *
128  * This just gets a minimal mmu environment setup so we can call
129  * start_here() to do the real work.
130  * -- Cort
131  */
132
133         .globl  __start
134 __start:
135 /*
136  * We have to do any OF calls before we map ourselves to KERNELBASE,
137  * because OF may have I/O devices mapped into that area
138  * (particularly on CHRP).
139  */
140         mr      r31,r3                  /* save parameters */
141         mr      r30,r4
142         mr      r29,r5
143         mr      r28,r6
144         mr      r27,r7
145         li      r24,0                   /* cpu # */
146 /*
147  * early_init() does the early machine identification and does
148  * the necessary low-level setup and clears the BSS
149  *  -- Cort <cort@fsmlabs.com>
150  */ 
151         bl      early_init
152
153 #ifdef CONFIG_APUS
154 /* On APUS the __va/__pa constants need to be set to the correct 
155  * values before continuing. 
156  */
157         mr      r4,r30
158         bl      fix_mem_constants
159 #endif /* CONFIG_APUS */
160
161 /* Switch MMU off, clear BATs and flush TLB. At this point, r3 contains
162  * the physical address we are running at, returned by early_init()
163  */
164         bl      mmu_off
165 __after_mmu_off:
166         bl      clear_bats
167         bl      flush_tlbs
168
169         bl      initial_bats
170 #if !defined(CONFIG_APUS) && defined(CONFIG_BOOTX_TEXT)
171         bl      setup_disp_bat
172 #endif
173
174         /*
175          * Call setup_cpu for CPU 0
176          */
177         bl      reloc_offset
178         li      r24,0                   /* cpu# */
179         bl      call_setup_cpu          /* Call setup_cpu for this CPU */
180 #ifdef CONFIG_6xx
181         bl      reloc_offset
182         bl      init_idle_6xx
183 #endif /* CONFIG_6xx */
184
185 #ifndef CONFIG_APUS
186 /*
187  * We need to run with _start at physical address 0.
188  * On CHRP, we are loaded at 0x10000 since OF on CHRP uses
189  * the exception vectors at 0 (and therefore this copy
190  * overwrites OF's exception vectors with our own).
191  * If the MMU is already turned on, we copy stuff to KERNELBASE,
192  * otherwise we copy it to 0.
193  */
194         bl      reloc_offset
195         mr      r26,r3
196         addis   r4,r3,KERNELBASE@h      /* current address of _start */
197         cmpwi   0,r4,0                  /* are we already running at 0? */
198         bne     relocate_kernel
199 #endif /* CONFIG_APUS */
200 /*
201  * we now have the 1st 16M of ram mapped with the bats.
202  * prep needs the mmu to be turned on here, but pmac already has it on.
203  * this shouldn't bother the pmac since it just gets turned on again
204  * as we jump to our code at KERNELBASE. -- Cort
205  * Actually no, pmac doesn't have it on any more. BootX enters with MMU
206  * off, and in other cases, we now turn it off before changing BATs above.
207  */
208 turn_on_mmu:
209         mfmsr   r0
210         ori     r0,r0,MSR_DR|MSR_IR
211         mtspr   SRR1,r0
212         lis     r0,start_here@h
213         ori     r0,r0,start_here@l
214         mtspr   SRR0,r0
215         SYNC
216         RFI                             /* enables MMU */
217
218 /*
219  * We need __secondary_hold as a place to hold the other cpus on
220  * an SMP machine, even when we are running a UP kernel.
221  */
222         . = 0xc0                        /* for prep bootloader */
223         li      r3,1                    /* MTX only has 1 cpu */
224         .globl  __secondary_hold
225 __secondary_hold:
226         /* tell the master we're here */
227         stw     r3,4(0)
228 #ifdef CONFIG_SMP
229 100:    lwz     r4,0(0)
230         /* wait until we're told to start */
231         cmpw    0,r4,r3
232         bne     100b
233         /* our cpu # was at addr 0 - go */
234         mr      r24,r3                  /* cpu # */
235         b       __secondary_start
236 #else
237         b       .
238 #endif /* CONFIG_SMP */
239
240 /*
241  * Exception entry code.  This code runs with address translation
242  * turned off, i.e. using physical addresses.
243  * We assume sprg3 has the physical address of the current
244  * task's thread_struct.
245  */
246 #define EXCEPTION_PROLOG        \
247         mtspr   SPRG0,r20;      \
248         mtspr   SPRG1,r21;      \
249         mfcr    r20;            \
250         mfspr   r21,SPRG2;              /* exception stack to use from */ \
251         cmpwi   0,r21,0;                /* user mode or RTAS */ \
252         bne     1f;             \
253         tophys(r21,r1);                 /* use tophys(kernel sp) otherwise */ \
254         subi    r21,r21,INT_FRAME_SIZE; /* alloc exc. frame */\
255 1:      CLR_TOP32(r21);         \
256         stw     r20,_CCR(r21);          /* save registers */ \
257         stw     r22,GPR22(r21); \
258         stw     r23,GPR23(r21); \
259         mfspr   r20,SPRG0;      \
260         stw     r20,GPR20(r21); \
261         mfspr   r22,SPRG1;      \
262         stw     r22,GPR21(r21); \
263         mflr    r20;            \
264         stw     r20,_LINK(r21); \
265         mfctr   r22;            \
266         stw     r22,_CTR(r21);  \
267         mfspr   r20,XER;        \
268         stw     r20,_XER(r21);  \
269         mfspr   r22,SRR0;       \
270         mfspr   r23,SRR1;       \
271         stw     r0,GPR0(r21);   \
272         stw     r1,GPR1(r21);   \
273         stw     r2,GPR2(r21);   \
274         stw     r1,0(r21);      \
275         tovirt(r1,r21);                 /* set new kernel sp */ \
276         SAVE_4GPRS(3, r21);     \
277         SAVE_GPR(7, r21);
278 /*
279  * Note: code which follows this uses cr0.eq (set if from kernel),
280  * r21, r22 (SRR0), and r23 (SRR1).
281  */
282
283 /*
284  * Exception vectors.
285  */
286 #define STD_EXCEPTION(n, label, hdlr)           \
287         . = n;                                  \
288 label:                                          \
289         EXCEPTION_PROLOG;                       \
290         addi    r3,r1,STACK_FRAME_OVERHEAD;     \
291         li      r20,MSR_KERNEL;                 \
292         bl      transfer_to_handler;            \
293 i##n:                                           \
294         .long   hdlr;                           \
295         .long   ret_from_except
296
297 /* System reset */
298 /* core99 pmac starts the seconary here by changing the vector, and
299    putting it back to what it was (UnknownException) when done.  */
300 #if defined(CONFIG_GEMINI) && defined(CONFIG_SMP)
301         . = 0x100
302         b       __secondary_start_gemini
303 #else
304         STD_EXCEPTION(0x100, Reset, UnknownException)
305 #endif
306
307 /* Machine check */
308 BEGIN_FTR_SECTION
309         DSSALL
310         sync
311 END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
312         STD_EXCEPTION(0x200, MachineCheck, MachineCheckException)
313
314 /* Data access exception. */
315         . = 0x300
316 #ifdef CONFIG_PPC64BRIDGE
317         b       DataAccess
318 DataAccessCont:
319 #else
320 DataAccess:
321         EXCEPTION_PROLOG
322 #endif /* CONFIG_PPC64BRIDGE */
323         mfspr   r20,DSISR
324 BEGIN_FTR_SECTION
325         andis.  r0,r20,0xa470           /* weird error? */
326         bne     1f                      /* if not, try to put a PTE */
327         mfspr   r4,DAR                  /* into the hash table */
328         rlwinm  r3,r20,32-15,21,21      /* DSISR_STORE -> _PAGE_RW */
329         bl      hash_page
330 END_FTR_SECTION_IFSET(CPU_FTR_HPTE_TABLE)
331 1:      stw     r20,_DSISR(r21)
332         mr      r5,r20
333         mfspr   r4,DAR
334         stw     r4,_DAR(r21)
335         addi    r3,r1,STACK_FRAME_OVERHEAD
336         li      r20,MSR_KERNEL
337         rlwimi  r20,r23,0,16,16         /* copy EE bit from saved MSR */
338         bl      transfer_to_handler
339 i0x300:
340         .long   do_page_fault
341         .long   ret_from_except
342
343 #ifdef CONFIG_PPC64BRIDGE
344 /* SLB fault on data access. */
345         . = 0x380
346         b       DataSegment
347 DataSegmentCont:
348         mfspr   r4,DAR
349         stw     r4,_DAR(r21)
350         addi    r3,r1,STACK_FRAME_OVERHEAD
351         li      r20,MSR_KERNEL
352         rlwimi  r20,r23,0,16,16         /* copy EE bit from saved MSR */
353         bl      transfer_to_handler
354         .long   UnknownException
355         .long   ret_from_except
356 #endif /* CONFIG_PPC64BRIDGE */
357
358 /* Instruction access exception. */
359         . = 0x400
360 #ifdef CONFIG_PPC64BRIDGE
361         b       InstructionAccess
362 InstructionAccessCont:
363 #else
364 InstructionAccess:
365         EXCEPTION_PROLOG
366 #endif /* CONFIG_PPC64BRIDGE */
367 BEGIN_FTR_SECTION
368         andis.  r0,r23,0x4000           /* no pte found? */
369         beq     1f                      /* if so, try to put a PTE */
370         li      r3,0                    /* into the hash table */
371         mr      r4,r22                  /* SRR0 is fault address */
372         bl      hash_page
373 END_FTR_SECTION_IFSET(CPU_FTR_HPTE_TABLE)
374 1:      addi    r3,r1,STACK_FRAME_OVERHEAD
375         mr      r4,r22
376         mr      r5,r23
377         li      r20,MSR_KERNEL
378         rlwimi  r20,r23,0,16,16         /* copy EE bit from saved MSR */
379         bl      transfer_to_handler
380 i0x400:
381         .long   do_page_fault
382         .long   ret_from_except
383
384 #ifdef CONFIG_PPC64BRIDGE
385 /* SLB fault on instruction access. */
386         . = 0x480
387         b       InstructionSegment
388 InstructionSegmentCont:
389         addi    r3,r1,STACK_FRAME_OVERHEAD
390         li      r20,MSR_KERNEL
391         rlwimi  r20,r23,0,16,16         /* copy EE bit from saved MSR */
392         bl      transfer_to_handler
393         .long   UnknownException
394         .long   ret_from_except
395 #endif /* CONFIG_PPC64BRIDGE */
396
397 /* External interrupt */
398         . = 0x500;
399 HardwareInterrupt:
400         EXCEPTION_PROLOG;
401         addi    r3,r1,STACK_FRAME_OVERHEAD
402         li      r20,MSR_KERNEL
403         li      r4,0
404         bl      transfer_to_handler
405         .globl do_IRQ_intercept
406 do_IRQ_intercept:
407         .long   do_IRQ;
408         .long   ret_from_intercept
409
410 /* Alignment exception */
411         . = 0x600
412 Alignment:
413         EXCEPTION_PROLOG
414         mfspr   r4,DAR
415         stw     r4,_DAR(r21)
416         mfspr   r5,DSISR
417         stw     r5,_DSISR(r21)
418         addi    r3,r1,STACK_FRAME_OVERHEAD
419         li      r20,MSR_KERNEL
420         rlwimi  r20,r23,0,16,16         /* copy EE bit from saved MSR */
421         bl      transfer_to_handler
422 i0x600:
423         .long   AlignmentException
424         .long   ret_from_except
425
426 /* Program check exception */
427         . = 0x700
428 ProgramCheck:
429         EXCEPTION_PROLOG
430         addi    r3,r1,STACK_FRAME_OVERHEAD
431         li      r20,MSR_KERNEL
432         rlwimi  r20,r23,0,16,16         /* copy EE bit from saved MSR */
433         bl      transfer_to_handler
434 i0x700:
435         .long   ProgramCheckException
436         .long   ret_from_except
437
438 /* Floating-point unavailable */
439         . = 0x800
440 FPUnavailable:
441         EXCEPTION_PROLOG
442         bne     load_up_fpu             /* if from user, just load it up */
443         li      r20,MSR_KERNEL
444         bl      transfer_to_handler     /* if from kernel, take a trap */
445 i0x800:
446         .long   KernelFP
447         .long   ret_from_except
448
449         . = 0x900
450 Decrementer:
451         EXCEPTION_PROLOG
452         addi    r3,r1,STACK_FRAME_OVERHEAD
453         li      r20,MSR_KERNEL
454         bl      transfer_to_handler
455         .globl timer_interrupt_intercept
456 timer_interrupt_intercept:
457         .long   timer_interrupt
458         .long   ret_from_intercept
459
460         STD_EXCEPTION(0xa00, Trap_0a, UnknownException)
461         STD_EXCEPTION(0xb00, Trap_0b, UnknownException)
462
463 /* System call */
464         . = 0xc00
465 SystemCall:
466         EXCEPTION_PROLOG
467         stw     r3,ORIG_GPR3(r21)
468         li      r20,MSR_KERNEL
469         rlwimi  r20,r23,0,16,16         /* copy EE bit from saved MSR */
470         bl      transfer_to_handler
471         .long   DoSyscall
472         .long   ret_from_except
473
474 /* Single step - not used on 601 */
475         STD_EXCEPTION(0xd00, SingleStep, SingleStepException)
476         STD_EXCEPTION(0xe00, Trap_0e, UnknownException)
477
478 /*
479  * The Altivec unavailable trap is at 0x0f20.  Foo.
480  * We effectively remap it to 0x3000.
481  */
482         . = 0xf00
483         b       Trap_0f
484 trap_0f_cont:
485         addi    r3,r1,STACK_FRAME_OVERHEAD
486         li      r20,MSR_KERNEL
487         bl      transfer_to_handler
488         .long   UnknownException
489         .long   ret_from_except
490
491         . = 0xf20
492 #ifdef CONFIG_ALTIVEC
493         b       AltiVecUnavailable
494 #endif
495 Trap_0f:
496         EXCEPTION_PROLOG
497         b       trap_0f_cont
498
499 /*
500  * Handle TLB miss for instruction on 603/603e.
501  * Note: we get an alternate set of r0 - r3 to use automatically.
502  */
503         . = 0x1000
504 InstructionTLBMiss:
505 /*
506  * r0:  stored ctr
507  * r1:  linux style pte ( later becomes ppc hardware pte )
508  * r2:  ptr to linux-style pte
509  * r3:  scratch
510  */
511         mfctr   r0
512         /* Get PTE (linux-style) and check access */
513         mfspr   r3,IMISS
514         lis     r1,KERNELBASE@h         /* check if kernel address */
515         cmplw   0,r3,r1
516         mfspr   r2,SPRG3
517         li      r1,_PAGE_USER|_PAGE_PRESENT /* low addresses tested as user */
518         lwz     r2,PGDIR(r2)
519         blt+    112f
520         lis     r2,swapper_pg_dir@ha    /* if kernel address, use */
521         addi    r2,r2,swapper_pg_dir@l  /* kernel page table */
522         mfspr   r1,SRR1                 /* and MSR_PR bit from SRR1 */
523         rlwinm  r1,r1,32-12,29,29       /* shift MSR_PR to _PAGE_USER posn */
524 112:    tophys(r2,r2)
525         rlwimi  r2,r3,12,20,29          /* insert top 10 bits of address */
526         lwz     r2,0(r2)                /* get pmd entry */
527         rlwinm. r2,r2,0,0,19            /* extract address of pte page */
528         beq-    InstructionAddressInvalid       /* return if no mapping */
529         tophys(r2,r2)
530         rlwimi  r2,r3,22,20,29          /* insert next 10 bits of address */
531         lwz     r3,0(r2)                /* get linux-style pte */
532         andc.   r1,r1,r3                /* check access & ~permission */
533         bne-    InstructionAddressInvalid /* return if access not permitted */
534         ori     r3,r3,_PAGE_ACCESSED    /* set _PAGE_ACCESSED in pte */
535         /*
536          * NOTE! We are assuming this is not an SMP system, otherwise
537          * we would need to update the pte atomically with lwarx/stwcx.
538          */
539         stw     r3,0(r2)                /* update PTE (accessed bit) */
540         /* Convert linux-style PTE to low word of PPC-style PTE */
541         rlwinm  r1,r3,32-10,31,31       /* _PAGE_RW -> PP lsb */
542         rlwinm  r2,r3,32-7,31,31        /* _PAGE_DIRTY -> PP lsb */
543         and     r1,r1,r2                /* writable if _RW and _DIRTY */
544         rlwimi  r3,r3,32-1,30,30        /* _PAGE_USER -> PP msb */
545         rlwimi  r3,r3,32-1,31,31        /* _PAGE_USER -> PP lsb */
546         ori     r1,r1,0xe14             /* clear out reserved bits and M */
547         andc    r1,r3,r1                /* PP = user? (rw&dirty? 2: 3): 0 */
548         mtspr   RPA,r1
549         mfspr   r3,IMISS
550         tlbli   r3
551         mfspr   r3,SRR1         /* Need to restore CR0 */
552         mtcrf   0x80,r3
553         rfi
554 InstructionAddressInvalid:
555         mfspr   r3,SRR1
556         rlwinm  r1,r3,9,6,6     /* Get load/store bit */
557
558         addis   r1,r1,0x2000
559         mtspr   DSISR,r1        /* (shouldn't be needed) */
560         mtctr   r0              /* Restore CTR */
561         andi.   r2,r3,0xFFFF    /* Clear upper bits of SRR1 */
562         or      r2,r2,r1
563         mtspr   SRR1,r2
564         mfspr   r1,IMISS        /* Get failing address */
565         rlwinm. r2,r2,0,31,31   /* Check for little endian access */
566         rlwimi  r2,r2,1,30,30   /* change 1 -> 3 */
567         xor     r1,r1,r2
568         mtspr   DAR,r1          /* Set fault address */
569         mfmsr   r0              /* Restore "normal" registers */
570         xoris   r0,r0,MSR_TGPR>>16
571         mtcrf   0x80,r3         /* Restore CR0 */
572         mtmsr   r0
573         b       InstructionAccess
574
575 /*
576  * Handle TLB miss for DATA Load operation on 603/603e
577  */
578         . = 0x1100
579 DataLoadTLBMiss:
580 /*
581  * r0:  stored ctr
582  * r1:  linux style pte ( later becomes ppc hardware pte )
583  * r2:  ptr to linux-style pte
584  * r3:  scratch
585  */
586         mfctr   r0
587         /* Get PTE (linux-style) and check access */
588         mfspr   r3,DMISS
589         lis     r1,KERNELBASE@h         /* check if kernel address */
590         cmplw   0,r3,r1
591         mfspr   r2,SPRG3
592         li      r1,_PAGE_USER|_PAGE_PRESENT /* low addresses tested as user */
593         lwz     r2,PGDIR(r2)
594         blt+    112f
595         lis     r2,swapper_pg_dir@ha    /* if kernel address, use */
596         addi    r2,r2,swapper_pg_dir@l  /* kernel page table */
597         mfspr   r1,SRR1                 /* and MSR_PR bit from SRR1 */
598         rlwinm  r1,r1,32-12,29,29       /* shift MSR_PR to _PAGE_USER posn */
599 112:    tophys(r2,r2)
600         rlwimi  r2,r3,12,20,29          /* insert top 10 bits of address */
601         lwz     r2,0(r2)                /* get pmd entry */
602         rlwinm. r2,r2,0,0,19            /* extract address of pte page */
603         beq-    DataAddressInvalid      /* return if no mapping */
604         tophys(r2,r2)
605         rlwimi  r2,r3,22,20,29          /* insert next 10 bits of address */
606         lwz     r3,0(r2)                /* get linux-style pte */
607         andc.   r1,r1,r3                /* check access & ~permission */
608         bne-    DataAddressInvalid      /* return if access not permitted */
609         ori     r3,r3,_PAGE_ACCESSED    /* set _PAGE_ACCESSED in pte */
610         /*
611          * NOTE! We are assuming this is not an SMP system, otherwise
612          * we would need to update the pte atomically with lwarx/stwcx.
613          */
614         stw     r3,0(r2)                /* update PTE (accessed bit) */
615         /* Convert linux-style PTE to low word of PPC-style PTE */
616         rlwinm  r1,r3,32-10,31,31       /* _PAGE_RW -> PP lsb */
617         rlwinm  r2,r3,32-7,31,31        /* _PAGE_DIRTY -> PP lsb */
618         and     r1,r1,r2                /* writable if _RW and _DIRTY */
619         rlwimi  r3,r3,32-1,30,30        /* _PAGE_USER -> PP msb */
620         rlwimi  r3,r3,32-1,31,31        /* _PAGE_USER -> PP lsb */
621         ori     r1,r1,0xe14             /* clear out reserved bits and M */
622         andc    r1,r3,r1                /* PP = user? (rw&dirty? 2: 3): 0 */
623         mtspr   RPA,r1
624         mfspr   r3,DMISS
625         tlbld   r3
626         mfspr   r3,SRR1         /* Need to restore CR0 */
627         mtcrf   0x80,r3
628         rfi
629 DataAddressInvalid:
630         mfspr   r3,SRR1
631         rlwinm  r1,r3,9,6,6     /* Get load/store bit */
632         addis   r1,r1,0x2000
633         mtspr   DSISR,r1
634         mtctr   r0              /* Restore CTR */
635         andi.   r2,r3,0xFFFF    /* Clear upper bits of SRR1 */
636         mtspr   SRR1,r2
637         mfspr   r1,DMISS        /* Get failing address */
638         rlwinm. r2,r2,0,31,31   /* Check for little endian access */
639         beq     20f             /* Jump if big endian */
640         xori    r1,r1,3
641 20:     mtspr   DAR,r1          /* Set fault address */
642         mfmsr   r0              /* Restore "normal" registers */
643         xoris   r0,r0,MSR_TGPR>>16
644         mtcrf   0x80,r3         /* Restore CR0 */
645         mtmsr   r0
646         b       DataAccess
647
648 /*
649  * Handle TLB miss for DATA Store on 603/603e
650  */
651         . = 0x1200
652 DataStoreTLBMiss:
653 /*
654  * r0:  stored ctr
655  * r1:  linux style pte ( later becomes ppc hardware pte )
656  * r2:  ptr to linux-style pte
657  * r3:  scratch
658  */
659         mfctr   r0
660         /* Get PTE (linux-style) and check access */
661         mfspr   r3,DMISS
662         lis     r1,KERNELBASE@h         /* check if kernel address */
663         cmplw   0,r3,r1
664         mfspr   r2,SPRG3
665         li      r1,_PAGE_RW|_PAGE_USER|_PAGE_PRESENT /* access flags */
666         lwz     r2,PGDIR(r2)
667         blt+    112f
668         lis     r2,swapper_pg_dir@ha    /* if kernel address, use */
669         addi    r2,r2,swapper_pg_dir@l  /* kernel page table */
670         mfspr   r1,SRR1                 /* and MSR_PR bit from SRR1 */
671         rlwinm  r1,r1,32-12,29,29       /* shift MSR_PR to _PAGE_USER posn */
672 112:    tophys(r2,r2)
673         rlwimi  r2,r3,12,20,29          /* insert top 10 bits of address */
674         lwz     r2,0(r2)                /* get pmd entry */
675         rlwinm. r2,r2,0,0,19            /* extract address of pte page */
676         beq-    DataAddressInvalid      /* return if no mapping */
677         tophys(r2,r2)
678         rlwimi  r2,r3,22,20,29          /* insert next 10 bits of address */
679         lwz     r3,0(r2)                /* get linux-style pte */
680         andc.   r1,r1,r3                /* check access & ~permission */
681         bne-    DataAddressInvalid      /* return if access not permitted */
682         ori     r3,r3,_PAGE_ACCESSED|_PAGE_DIRTY
683         /*
684          * NOTE! We are assuming this is not an SMP system, otherwise
685          * we would need to update the pte atomically with lwarx/stwcx.
686          */
687         stw     r3,0(r2)                /* update PTE (accessed/dirty bits) */
688         /* Convert linux-style PTE to low word of PPC-style PTE */
689         rlwimi  r3,r3,32-1,30,30        /* _PAGE_USER -> PP msb */
690         li      r1,0xe15                /* clear out reserved bits and M */
691         andc    r1,r3,r1                /* PP = user? 2: 0 */
692         mtspr   RPA,r1
693         mfspr   r3,DMISS
694         tlbld   r3
695         mfspr   r3,SRR1         /* Need to restore CR0 */
696         mtcrf   0x80,r3
697         rfi
698
699         STD_EXCEPTION(0x1300, Trap_13, InstructionBreakpoint)
700         STD_EXCEPTION(0x1400, SMI, SMIException)
701         STD_EXCEPTION(0x1500, Trap_15, UnknownException)
702         STD_EXCEPTION(0x1600, Trap_16, UnknownException)
703         STD_EXCEPTION(0x1700, Trap_17, TAUException)
704         STD_EXCEPTION(0x1800, Trap_18, UnknownException)
705         STD_EXCEPTION(0x1900, Trap_19, UnknownException)
706         STD_EXCEPTION(0x1a00, Trap_1a, UnknownException)
707         STD_EXCEPTION(0x1b00, Trap_1b, UnknownException)
708         STD_EXCEPTION(0x1c00, Trap_1c, UnknownException)
709         STD_EXCEPTION(0x1d00, Trap_1d, UnknownException)
710         STD_EXCEPTION(0x1e00, Trap_1e, UnknownException)
711         STD_EXCEPTION(0x1f00, Trap_1f, UnknownException)
712         STD_EXCEPTION(0x2000, RunMode, RunModeException)
713         STD_EXCEPTION(0x2100, Trap_21, UnknownException)
714         STD_EXCEPTION(0x2200, Trap_22, UnknownException)
715         STD_EXCEPTION(0x2300, Trap_23, UnknownException)
716         STD_EXCEPTION(0x2400, Trap_24, UnknownException)
717         STD_EXCEPTION(0x2500, Trap_25, UnknownException)
718         STD_EXCEPTION(0x2600, Trap_26, UnknownException)
719         STD_EXCEPTION(0x2700, Trap_27, UnknownException)
720         STD_EXCEPTION(0x2800, Trap_28, UnknownException)
721         STD_EXCEPTION(0x2900, Trap_29, UnknownException)
722         STD_EXCEPTION(0x2a00, Trap_2a, UnknownException)
723         STD_EXCEPTION(0x2b00, Trap_2b, UnknownException)
724         STD_EXCEPTION(0x2c00, Trap_2c, UnknownException)
725         STD_EXCEPTION(0x2d00, Trap_2d, UnknownException)
726         STD_EXCEPTION(0x2e00, Trap_2e, UnknownException)
727         STD_EXCEPTION(0x2f00, Trap_2f, UnknownException)
728
729         . = 0x3000
730
731 #ifdef CONFIG_ALTIVEC
732 AltiVecUnavailable:
733         EXCEPTION_PROLOG
734         bne     load_up_altivec         /* if from user, just load it up */
735         li      r20,MSR_KERNEL
736         bl      transfer_to_handler     /* if from kernel, take a trap */
737         .long   KernelAltiVec
738         .long   ret_from_except
739 #endif /* CONFIG_ALTIVEC */
740
741 #ifdef CONFIG_PPC64BRIDGE
742 DataAccess:
743         EXCEPTION_PROLOG
744         b       DataAccessCont
745 InstructionAccess:
746         EXCEPTION_PROLOG
747         b       InstructionAccessCont
748 DataSegment:
749         EXCEPTION_PROLOG
750         b       DataSegmentCont
751 InstructionSegment:
752         EXCEPTION_PROLOG
753         b       InstructionSegmentCont
754 #endif /* CONFIG_PPC64BRIDGE */
755
756 /*
757  * This code finishes saving the registers to the exception frame
758  * and jumps to the appropriate handler for the exception, turning
759  * on address translation.
760  */
761         .globl  transfer_to_handler
762 transfer_to_handler:
763         stw     r22,_NIP(r21)
764         stw     r23,_MSR(r21)
765         SAVE_4GPRS(8, r21)
766         SAVE_8GPRS(12, r21)
767         SAVE_8GPRS(24, r21)
768         andi.   r23,r23,MSR_PR
769         mfspr   r23,SPRG3               /* if from user, fix up THREAD.regs */
770         addi    r2,r23,-THREAD          /* set r2 to current */
771         beq     2f
772         addi    r24,r1,STACK_FRAME_OVERHEAD
773         stw     r24,PT_REGS(r23)
774 #ifdef CONFIG_ALTIVEC
775 BEGIN_FTR_SECTION
776         mfspr   r22,SPRN_VRSAVE         /* if G4, save vrsave register value */
777         stw     r22,THREAD_VRSAVE(r23)
778 END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
779 #endif /* CONFIG_ALTIVEC */
780         .globl transfer_to_handler_cont
781 transfer_to_handler_cont:
782         tovirt(r2,r2)
783         mflr    r23
784         andi.   r24,r23,0x3f00          /* get vector offset */
785         stw     r24,TRAP(r21)
786         li      r22,0
787         stw     r22,RESULT(r21)
788         mtspr   SPRG2,r22               /* r1 is now kernel sp */
789         addi    r24,r2,TASK_STRUCT_SIZE /* check for kernel stack overflow */
790         cmplw   0,r1,r2
791         cmplw   1,r1,r24
792         crand   1,1,4
793         bgt-    stack_ovf               /* if r2 < r1 < r2+TASK_STRUCT_SIZE */
794         lwz     r24,0(r23)              /* virtual address of handler */
795         lwz     r23,4(r23)              /* where to go when done */
796         FIX_SRR1(r20,r22)
797         mtspr   SRR0,r24
798         mtspr   SRR1,r20
799         mtlr    r23
800         SYNC
801         RFI                             /* jump to handler, enable MMU */
802 2:
803         /* Out of line case when returning to kernel,
804          * check return from power_save_6xx
805          */
806 #ifdef CONFIG_6xx
807         
808         mfspr   r24,SPRN_HID0
809         mtcr    r24
810 BEGIN_FTR_SECTION
811         bt-     8,power_save_6xx_restore        /* Check DOZE */
812 END_FTR_SECTION_IFSET(CPU_FTR_CAN_DOZE)
813 BEGIN_FTR_SECTION
814         bt-     9,power_save_6xx_restore        /* Check NAP */
815 END_FTR_SECTION_IFSET(CPU_FTR_CAN_NAP)
816         b       transfer_to_handler_cont
817
818 #endif /* CONFIG_6xx */
819
820 /*
821  * On kernel stack overflow, load up an initial stack pointer
822  * and call StackOverflow(regs), which should not return.
823  */
824 stack_ovf:
825         addi    r3,r1,STACK_FRAME_OVERHEAD
826         lis     r1,init_task_union@ha
827         addi    r1,r1,init_task_union@l
828         addi    r1,r1,TASK_UNION_SIZE-STACK_FRAME_OVERHEAD
829         lis     r24,StackOverflow@ha
830         addi    r24,r24,StackOverflow@l
831         li      r20,MSR_KERNEL
832         FIX_SRR1(r20,r22)
833         mtspr   SRR0,r24
834         mtspr   SRR1,r20
835         SYNC
836         RFI
837
838 /*
839  * This task wants to use the FPU now.
840  * On UP, disable FP for the task which had the FPU previously,
841  * and save its floating-point registers in its thread_struct.
842  * Load up this task's FP registers from its thread_struct,
843  * enable the FPU for the current task and return to the task.
844  */
845 load_up_fpu:
846         mfmsr   r5
847         ori     r5,r5,MSR_FP
848 #ifdef CONFIG_PPC64BRIDGE
849         clrldi  r5,r5,1                 /* turn off 64-bit mode */
850 #endif /* CONFIG_PPC64BRIDGE */
851         SYNC
852         MTMSRD(r5)                      /* enable use of fpu now */
853         isync
854 /*
855  * For SMP, we don't do lazy FPU switching because it just gets too
856  * horrendously complex, especially when a task switches from one CPU
857  * to another.  Instead we call giveup_fpu in switch_to.
858  */
859 #ifndef CONFIG_SMP
860         tophys(r6,0)                    /* get __pa constant */
861         addis   r3,r6,last_task_used_math@ha
862         lwz     r4,last_task_used_math@l(r3)
863         cmpi    0,r4,0
864         beq     1f
865         add     r4,r4,r6
866         addi    r4,r4,THREAD            /* want last_task_used_math->thread */
867         SAVE_32FPRS(0, r4)
868         mffs    fr0
869         stfd    fr0,THREAD_FPSCR-4(r4)
870         lwz     r5,PT_REGS(r4)
871         add     r5,r5,r6
872         lwz     r4,_MSR-STACK_FRAME_OVERHEAD(r5)
873         li      r20,MSR_FP|MSR_FE0|MSR_FE1
874         andc    r4,r4,r20               /* disable FP for previous task */
875         stw     r4,_MSR-STACK_FRAME_OVERHEAD(r5)
876 1:
877 #endif /* CONFIG_SMP */
878         /* enable use of FP after return */
879         mfspr   r5,SPRG3                /* current task's THREAD (phys) */
880         lwz     r4,THREAD_FPEXC_MODE(r5)
881         ori     r23,r23,MSR_FP          /* enable FP for current */
882         or      r23,r23,r4
883         lfd     fr0,THREAD_FPSCR-4(r5)
884         mtfsf   0xff,fr0
885         REST_32FPRS(0, r5)
886 #ifndef CONFIG_SMP
887         subi    r4,r5,THREAD
888         sub     r4,r4,r6
889         stw     r4,last_task_used_math@l(r3)
890 #endif /* CONFIG_SMP */
891         /* restore registers and return */
892         lwz     r3,_CCR(r21)
893         lwz     r4,_LINK(r21)
894         mtcrf   0xff,r3
895         mtlr    r4
896         REST_GPR(1, r21)
897         REST_4GPRS(3, r21)
898         /* we haven't used ctr or xer */
899         mtspr   SRR1,r23
900         mtspr   SRR0,r22
901         REST_GPR(20, r21)
902         REST_2GPRS(22, r21)
903         lwz     r21,GPR21(r21)
904         SYNC
905         RFI
906
907 /*
908  * FP unavailable trap from kernel - print a message, but let
909  * the task use FP in the kernel until it returns to user mode.
910  */
911 KernelFP:
912         lwz     r3,_MSR(r1)
913         ori     r3,r3,MSR_FP
914         stw     r3,_MSR(r1)             /* enable use of FP after return */
915         lis     r3,86f@h
916         ori     r3,r3,86f@l
917         mr      r4,r2                   /* current */
918         lwz     r5,_NIP(r1)
919         bl      printk
920         b       ret_from_except
921 86:     .string "floating point used in kernel (task=%p, pc=%x)\n"
922         .align  4
923
924 #ifdef CONFIG_ALTIVEC
925 /* Note that the AltiVec support is closely modeled after the FP
926  * support.  Changes to one are likely to be applicable to the
927  * other!  */
928 load_up_altivec:
929 /*
930  * Disable AltiVec for the task which had AltiVec previously,
931  * and save its AltiVec registers in its thread_struct.
932  * Enables AltiVec for use in the kernel on return.
933  * On SMP we know the AltiVec units are free, since we give it up every
934  * switch.  -- Kumar
935  */
936         mfmsr   r5
937         oris    r5,r5,MSR_VEC@h
938         mtmsr   r5                      /* enable use of AltiVec now */
939         isync
940 /*
941  * For SMP, we don't do lazy AltiVec switching because it just gets too
942  * horrendously complex, especially when a task switches from one CPU
943  * to another.  Instead we call giveup_altivec in switch_to.
944  */
945 #ifndef CONFIG_SMP
946 #ifndef CONFIG_APUS
947         lis     r6,-KERNELBASE@h
948 #else
949         lis     r6,CYBERBASEp@h
950         lwz     r6,0(r6)
951 #endif
952         addis   r3,r6,last_task_used_altivec@ha
953         lwz     r4,last_task_used_altivec@l(r3)
954         cmpi    0,r4,0
955         beq     1f
956         add     r4,r4,r6
957         addi    r4,r4,THREAD    /* want THREAD of last_task_used_altivec */
958         SAVE_32VR(0,r20,r4)
959         MFVSCR(vr0)
960         li      r20,THREAD_VSCR
961         STVX(vr0,r20,r4)
962         lwz     r5,PT_REGS(r4)
963         add     r5,r5,r6
964         lwz     r4,_MSR-STACK_FRAME_OVERHEAD(r5)
965         lis     r20,MSR_VEC@h
966         andc    r4,r4,r20       /* disable altivec for previous task */
967         stw     r4,_MSR-STACK_FRAME_OVERHEAD(r5)
968 1:
969 #endif /* CONFIG_SMP */
970         /* enable use of AltiVec after return */
971         oris    r23,r23,MSR_VEC@h
972         mfspr   r5,SPRG3                /* current task's THREAD (phys) */
973         li      r20,THREAD_VSCR
974         LVX(vr0,r20,r5)
975         MTVSCR(vr0)
976         REST_32VR(0,r20,r5)
977 #ifndef CONFIG_SMP
978         subi    r4,r5,THREAD
979         sub     r4,r4,r6
980         stw     r4,last_task_used_altivec@l(r3)
981 #endif /* CONFIG_SMP */
982         /* restore registers and return */
983         lwz     r3,_CCR(r21)
984         lwz     r4,_LINK(r21)
985         mtcrf   0xff,r3
986         mtlr    r4
987         REST_GPR(1, r21)
988         REST_4GPRS(3, r21)
989         /* we haven't used ctr or xer */
990         mtspr   SRR1,r23
991         mtspr   SRR0,r22
992         REST_GPR(20, r21)
993         REST_2GPRS(22, r21)
994         lwz     r21,GPR21(r21)
995         SYNC
996         RFI
997
998 /*
999  * AltiVec unavailable trap from kernel - print a message, but let
1000  * the task use AltiVec in the kernel until it returns to user mode.
1001  */
1002 KernelAltiVec:
1003         lwz     r3,_MSR(r1)
1004         oris    r3,r3,MSR_VEC@h
1005         stw     r3,_MSR(r1)     /* enable use of AltiVec after return */
1006         lis     r3,87f@h
1007         ori     r3,r3,87f@l
1008         mr      r4,r2           /* current */
1009         lwz     r5,_NIP(r1)
1010         bl      printk
1011         b       ret_from_except
1012 87:     .string "AltiVec used in kernel  (task=%p, pc=%x)  \n"
1013         .align  4
1014
1015 /*
1016  * giveup_altivec(tsk)
1017  * Disable AltiVec for the task given as the argument,
1018  * and save the AltiVec registers in its thread_struct.
1019  * Enables AltiVec for use in the kernel on return.
1020  */
1021
1022         .globl  giveup_altivec
1023 giveup_altivec:
1024         mfmsr   r5
1025         oris    r5,r5,MSR_VEC@h
1026         SYNC
1027         mtmsr   r5                      /* enable use of AltiVec now */
1028         isync
1029         cmpi    0,r3,0
1030         beqlr-                          /* if no previous owner, done */
1031         addi    r3,r3,THREAD            /* want THREAD of task */
1032         lwz     r5,PT_REGS(r3)
1033         cmpi    0,r5,0
1034         SAVE_32VR(0, r4, r3)
1035         MFVSCR(vr0)
1036         li      r4,THREAD_VSCR
1037         STVX(vr0, r4, r3)
1038         beq     1f
1039         lwz     r4,_MSR-STACK_FRAME_OVERHEAD(r5)
1040         lis     r3,MSR_VEC@h
1041         andc    r4,r4,r3                /* disable AltiVec for previous task */
1042         stw     r4,_MSR-STACK_FRAME_OVERHEAD(r5)
1043 1:
1044 #ifndef CONFIG_SMP
1045         li      r5,0
1046         lis     r4,last_task_used_altivec@ha
1047         stw     r5,last_task_used_altivec@l(r4)
1048 #endif /* CONFIG_SMP */
1049         blr
1050 #endif /* CONFIG_ALTIVEC */
1051
1052 /*
1053  * giveup_fpu(tsk)
1054  * Disable FP for the task given as the argument,
1055  * and save the floating-point registers in its thread_struct.
1056  * Enables the FPU for use in the kernel on return.
1057  */
1058         .globl  giveup_fpu
1059 giveup_fpu:
1060         mfmsr   r5
1061         ori     r5,r5,MSR_FP
1062         SYNC_601
1063         ISYNC_601
1064         mtmsr   r5                      /* enable use of fpu now */
1065         SYNC_601
1066         isync
1067         cmpi    0,r3,0
1068         beqlr-                          /* if no previous owner, done */
1069         addi    r3,r3,THREAD            /* want THREAD of task */
1070         lwz     r5,PT_REGS(r3)
1071         cmpi    0,r5,0
1072         SAVE_32FPRS(0, r3)
1073         mffs    fr0
1074         stfd    fr0,THREAD_FPSCR-4(r3)
1075         beq     1f
1076         lwz     r4,_MSR-STACK_FRAME_OVERHEAD(r5)
1077         li      r3,MSR_FP|MSR_FE0|MSR_FE1
1078         andc    r4,r4,r3                /* disable FP for previous task */
1079         stw     r4,_MSR-STACK_FRAME_OVERHEAD(r5)
1080 1:
1081 #ifndef CONFIG_SMP
1082         li      r5,0
1083         lis     r4,last_task_used_math@ha
1084         stw     r5,last_task_used_math@l(r4)
1085 #endif /* CONFIG_SMP */
1086         blr
1087
1088 /*
1089  * This code is jumped to from the startup code to copy
1090  * the kernel image to physical address 0.
1091  */
1092 relocate_kernel:
1093         addis   r9,r26,klimit@ha        /* fetch klimit */
1094         lwz     r25,klimit@l(r9)
1095         addis   r25,r25,-KERNELBASE@h
1096         li      r3,0                    /* Destination base address */
1097         li      r6,0                    /* Destination offset */
1098         li      r5,0x4000               /* # bytes of memory to copy */
1099         bl      copy_and_flush          /* copy the first 0x4000 bytes */
1100         addi    r0,r3,4f@l              /* jump to the address of 4f */
1101         mtctr   r0                      /* in copy and do the rest. */
1102         bctr                            /* jump to the copy */
1103 4:      mr      r5,r25
1104         bl      copy_and_flush          /* copy the rest */
1105         b       turn_on_mmu
1106
1107 /*
1108  * Copy routine used to copy the kernel to start at physical address 0
1109  * and flush and invalidate the caches as needed.
1110  * r3 = dest addr, r4 = source addr, r5 = copy limit, r6 = start offset
1111  * on exit, r3, r4, r5 are unchanged, r6 is updated to be >= r5.
1112  */
1113 copy_and_flush:
1114         addi    r5,r5,-4
1115         addi    r6,r6,-4
1116 4:      li      r0,L1_CACHE_LINE_SIZE/4
1117         mtctr   r0
1118 3:      addi    r6,r6,4                 /* copy a cache line */
1119         lwzx    r0,r6,r4
1120         stwx    r0,r6,r3
1121         bdnz    3b
1122         dcbst   r6,r3                   /* write it to memory */
1123         sync
1124         icbi    r6,r3                   /* flush the icache line */
1125         cmplw   0,r6,r5
1126         blt     4b
1127         sync                            /* additional sync needed on g4 */
1128         isync
1129         addi    r5,r5,4
1130         addi    r6,r6,4
1131         blr
1132
1133 #ifdef CONFIG_APUS
1134 /*
1135  * On APUS the physical base address of the kernel is not known at compile
1136  * time, which means the __pa/__va constants used are incorrect. In the
1137  * __init section is recorded the virtual addresses of instructions using
1138  * these constants, so all that has to be done is fix these before
1139  * continuing the kernel boot.
1140  *
1141  * r4 = The physical address of the kernel base.
1142  */
1143 fix_mem_constants:
1144         mr      r10,r4
1145         addis   r10,r10,-KERNELBASE@h    /* virt_to_phys constant */
1146         neg     r11,r10                  /* phys_to_virt constant */
1147
1148         lis     r12,__vtop_table_begin@h
1149         ori     r12,r12,__vtop_table_begin@l
1150         add     r12,r12,r10              /* table begin phys address */
1151         lis     r13,__vtop_table_end@h
1152         ori     r13,r13,__vtop_table_end@l
1153         add     r13,r13,r10              /* table end phys address */
1154         subi    r12,r12,4
1155         subi    r13,r13,4
1156 1:      lwzu    r14,4(r12)               /* virt address of instruction */
1157         add     r14,r14,r10              /* phys address of instruction */
1158         lwz     r15,0(r14)               /* instruction, now insert top */
1159         rlwimi  r15,r10,16,16,31         /* half of vp const in low half */
1160         stw     r15,0(r14)               /* of instruction and restore. */
1161         dcbst   r0,r14                   /* write it to memory */
1162         sync
1163         icbi    r0,r14                   /* flush the icache line */
1164         cmpw    r12,r13
1165         bne     1b
1166         sync                            /* additional sync needed on g4 */
1167         isync
1168
1169 /*
1170  * Map the memory where the exception handlers will
1171  * be copied to when hash constants have been patched.  
1172  */
1173 #ifdef CONFIG_APUS_FAST_EXCEPT
1174         lis     r8,0xfff0
1175 #else
1176         lis     r8,0
1177 #endif
1178         ori     r8,r8,0x2               /* 128KB, supervisor */
1179         mtspr   DBAT3U,r8
1180         mtspr   DBAT3L,r8
1181
1182         lis     r12,__ptov_table_begin@h
1183         ori     r12,r12,__ptov_table_begin@l
1184         add     r12,r12,r10              /* table begin phys address */
1185         lis     r13,__ptov_table_end@h
1186         ori     r13,r13,__ptov_table_end@l
1187         add     r13,r13,r10              /* table end phys address */
1188         subi    r12,r12,4
1189         subi    r13,r13,4
1190 1:      lwzu    r14,4(r12)               /* virt address of instruction */
1191         add     r14,r14,r10              /* phys address of instruction */
1192         lwz     r15,0(r14)               /* instruction, now insert top */
1193         rlwimi  r15,r11,16,16,31         /* half of pv const in low half*/
1194         stw     r15,0(r14)               /* of instruction and restore. */
1195         dcbst   r0,r14                   /* write it to memory */
1196         sync
1197         icbi    r0,r14                   /* flush the icache line */
1198         cmpw    r12,r13
1199         bne     1b
1200
1201         sync                            /* additional sync needed on g4 */
1202         isync                           /* No speculative loading until now */
1203         blr
1204
1205 /***********************************************************************
1206  *  Please note that on APUS the exception handlers are located at the
1207  *  physical address 0xfff0000. For this reason, the exception handlers
1208  *  cannot use relative branches to access the code below.
1209  ***********************************************************************/
1210 #endif /* CONFIG_APUS */
1211
1212 #ifdef CONFIG_SMP
1213 #ifdef CONFIG_GEMINI
1214         .globl  __secondary_start_gemini
1215 __secondary_start_gemini:
1216         mfspr   r4,HID0
1217         ori     r4,r4,HID0_ICFI
1218         li      r3,0
1219         ori     r3,r3,HID0_ICE
1220         andc    r4,r4,r3
1221         mtspr   HID0,r4
1222         sync
1223         bl      gemini_prom_init
1224         b       __secondary_start
1225 #endif /* CONFIG_GEMINI */
1226         .globl  __secondary_start_psurge
1227 __secondary_start_psurge:
1228         li      r24,1                   /* cpu # */
1229         b       __secondary_start_psurge99
1230         .globl  __secondary_start_psurge2
1231 __secondary_start_psurge2:
1232         li      r24,2                   /* cpu # */
1233         b       __secondary_start_psurge99
1234         .globl  __secondary_start_psurge3
1235 __secondary_start_psurge3:
1236         li      r24,3                   /* cpu # */
1237         b       __secondary_start_psurge99
1238 __secondary_start_psurge99:
1239         /* we come in here with IR=0 and DR=1, and DBAT 0
1240            set to map the 0xf0000000 - 0xffffffff region */
1241         mfmsr   r0
1242         rlwinm  r0,r0,0,28,26           /* clear DR (0x10) */
1243         SYNC
1244         mtmsr   r0
1245         isync
1246
1247         .globl  __secondary_start
1248 __secondary_start:
1249 #ifdef CONFIG_PPC64BRIDGE
1250         mfmsr   r0
1251         clrldi  r0,r0,1         /* make sure it's in 32-bit mode */
1252         SYNC
1253         MTMSRD(r0)
1254         isync
1255 #endif
1256
1257         lis     r3,-KERNELBASE@h
1258         mr      r4,r24
1259         bl      identify_cpu
1260         bl      call_setup_cpu          /* Call setup_cpu for this CPU */
1261 #ifdef CONFIG_6xx
1262         lis     r3,-KERNELBASE@h
1263         bl      init_idle_6xx
1264 #endif /* CONFIG_6xx */
1265         
1266         /* get current */
1267         lis     r2,current_set@h
1268         ori     r2,r2,current_set@l
1269         tophys(r2,r2)
1270         slwi    r24,r24,2               /* get current_set[cpu#] */
1271         lwzx    r2,r2,r24
1272
1273         /* stack */
1274         addi    r1,r2,TASK_UNION_SIZE-STACK_FRAME_OVERHEAD
1275         li      r0,0
1276         tophys(r3,r1)
1277         stw     r0,0(r3)
1278
1279         /* load up the MMU */
1280         bl      load_up_mmu
1281
1282         /* ptr to phys current thread */
1283         tophys(r4,r2)
1284         addi    r4,r4,THREAD    /* phys address of our thread_struct */
1285         CLR_TOP32(r4)
1286         mtspr   SPRG3,r4
1287         li      r3,0
1288         mtspr   SPRG2,r3        /* 0 => r1 has kernel sp */
1289
1290         /* enable MMU and jump to start_secondary */
1291         li      r4,MSR_KERNEL
1292         lis     r3,start_secondary@h
1293         ori     r3,r3,start_secondary@l
1294         mtspr   SRR0,r3
1295         mtspr   SRR1,r4
1296         SYNC
1297         RFI
1298 #endif /* CONFIG_SMP */
1299
1300 /*
1301  * Enable caches and 604-specific features if necessary.
1302  */
1303 _GLOBAL(__setup_cpu_601)
1304         blr
1305 _GLOBAL(__setup_cpu_603)
1306         b       setup_common_caches
1307 _GLOBAL(__setup_cpu_604)
1308         mflr    r4
1309         bl      setup_common_caches
1310         bl      setup_604_hid0
1311         mtlr    r4
1312         blr
1313 _GLOBAL(__setup_cpu_750)
1314         mflr    r4
1315         bl      setup_common_caches
1316         bl      setup_750_7400_hid0
1317         mtlr    r4
1318         blr
1319 _GLOBAL(__setup_cpu_750cx)
1320         mflr    r4
1321         bl      setup_common_caches
1322         bl      setup_750_7400_hid0
1323         bl      setup_750cx
1324         mtlr    r4
1325         blr
1326 _GLOBAL(__setup_cpu_750fx)
1327         mflr    r4
1328         bl      setup_common_caches
1329         bl      setup_750_7400_hid0
1330         bl      setup_750fx
1331         mtlr    r4
1332         blr
1333 _GLOBAL(__setup_cpu_7400)
1334         mflr    r4
1335         bl      setup_7400_workarounds
1336         bl      setup_common_caches
1337         bl      setup_750_7400_hid0
1338         mtlr    r4
1339         blr
1340 _GLOBAL(__setup_cpu_7410)
1341         mflr    r4
1342         bl      setup_7410_workarounds
1343         bl      setup_common_caches
1344         bl      setup_750_7400_hid0
1345         li      r3,0
1346         mtspr   SPRN_L2CR2,r3
1347         mtlr    r4
1348         blr
1349 _GLOBAL(__setup_cpu_7450)
1350         mflr    r4
1351         bl      setup_common_caches
1352         bl      setup_745x_specifics
1353         mtlr    r4
1354         blr
1355 _GLOBAL(__setup_cpu_7455)
1356         mflr    r4
1357         bl      setup_common_caches
1358         bl      setup_745x_specifics
1359         mtlr    r4
1360         blr
1361 _GLOBAL(__setup_cpu_power3)
1362         blr
1363 _GLOBAL(__setup_cpu_generic)
1364         blr
1365
1366 /* Enable caches for 603's, 604, 750 & 7400 */
1367 setup_common_caches:
1368         mfspr   r11,HID0
1369         andi.   r0,r11,HID0_DCE
1370 #ifdef CONFIG_DCACHE_DISABLE
1371         ori     r11,r11,HID0_ICE
1372 #else
1373         ori     r11,r11,HID0_ICE|HID0_DCE
1374 #endif
1375         ori     r8,r11,HID0_ICFI
1376         bne     1f                      /* don't invalidate the D-cache */
1377         ori     r8,r8,HID0_DCI          /* unless it wasn't enabled */
1378 1:      sync
1379         mtspr   HID0,r8                 /* enable and invalidate caches */
1380         sync
1381         mtspr   HID0,r11                /* enable caches */
1382         sync
1383         isync
1384         blr
1385
1386 /* 604, 604e, 604ev, ...
1387  * Enable superscalar execution & branch history table
1388  */
1389 setup_604_hid0:
1390         mfspr   r11,HID0
1391         ori     r11,r11,HID0_SIED|HID0_BHTE
1392         ori     r8,r11,HID0_BTCD
1393         sync
1394         mtspr   HID0,r8         /* flush branch target address cache */
1395         sync                    /* on 604e/604r */
1396         mtspr   HID0,r11
1397         sync
1398         isync
1399         blr
1400
1401 /* 7400 <= rev 2.7 and 7410 rev = 1.0 suffer from some
1402  * erratas we work around here.
1403  * Moto MPC710CE.pdf describes them, those are errata
1404  * #3, #4 and #5
1405  * Note that we assume the firmware didn't choose to
1406  * apply other workarounds (there are other ones documented
1407  * in the .pdf). It appear that Apple firmware only works
1408  * around #3 and with the same fix we use. We may want to
1409  * check if the CPU is using 60x bus mode in which case
1410  * the workaround for errata #4 is useless. Also, we may
1411  * want to explicitely clear HID0_NOPDST as this is not
1412  * needed once we have applied workaround #5 (though it's
1413  * not set by Apple's firmware at least).
1414  */
1415 setup_7400_workarounds:
1416         mfpvr   r3
1417         rlwinm  r3,r3,0,20,31
1418         cmpwi   0,r3,0x0207
1419         ble     1f
1420         blr
1421 setup_7410_workarounds:
1422         mfpvr   r3
1423         rlwinm  r3,r3,0,20,31
1424         cmpwi   0,r3,0x0100
1425         bnelr
1426 1:
1427         mfspr   r11,SPRN_MSSSR0
1428         /* Errata #3: Set L1OPQ_SIZE to 0x10 */
1429         rlwinm  r11,r11,0,9,6
1430         oris    r11,r11,0x0100
1431         /* Errata #4: Set L2MQ_SIZE to 1 (check for MPX mode first ?) */
1432         oris    r11,r11,0x0002
1433         /* Errata #5: Set DRLT_SIZE to 0x01 */
1434         rlwinm  r11,r11,0,5,2
1435         oris    r11,r11,0x0800
1436         sync
1437         mtspr   SPRN_MSSSR0,r11
1438         sync
1439         isync
1440         blr
1441         
1442 /* 740/750/7400/7410
1443  * Enable Store Gathering (SGE), Address Brodcast (ABE),
1444  * Branch History Table (BHTE), Branch Target ICache (BTIC)
1445  * Dynamic Power Management (DPM), Speculative (SPD)
1446  * Clear Instruction cache throttling (ICTC)
1447  */
1448 setup_750_7400_hid0:
1449         mfspr   r11,HID0
1450         ori     r11,r11,HID0_SGE | HID0_ABE | HID0_BHTE | HID0_BTIC
1451 BEGIN_FTR_SECTION
1452         oris    r11,r11,HID0_DPM@h      /* enable dynamic power mgmt */
1453 END_FTR_SECTION_IFCLR(CPU_FTR_NO_DPM)
1454         li      r3,HID0_SPD
1455         andc    r11,r11,r3              /* clear SPD: enable speculative */
1456         li      r3,0
1457         mtspr   ICTC,r3                 /* Instruction Cache Throttling off */
1458         isync
1459         mtspr   HID0,r11
1460         sync
1461         isync
1462         blr
1463
1464 /* 750cx specific
1465  * Looks like we have to disable NAP feature for some PLL settings...
1466  * (waiting for confirmation)
1467  */
1468 setup_750cx:
1469         mfspr   r10, SPRN_HID1
1470         rlwinm  r10,r10,4,28,31
1471         cmpi    cr0,r10,7
1472         cmpi    cr1,r10,9
1473         cmpi    cr2,r10,11
1474         cror    4*cr0+eq,4*cr0+eq,4*cr1+eq
1475         cror    4*cr0+eq,4*cr0+eq,4*cr2+eq
1476         bnelr
1477         lwz     r6,CPU_SPEC_FEATURES(r5)
1478         li      r7,CPU_FTR_CAN_NAP
1479         andc    r6,r6,r7
1480         stw     r6,CPU_SPEC_FEATURES(r5)
1481         blr
1482
1483 /* 750fx specific
1484  */
1485 setup_750fx:
1486         blr
1487
1488 /* MPC 745x
1489  * Enable Store Gathering (SGE), Branch Folding (FOLD)
1490  * Branch History Table (BHTE), Branch Target ICache (BTIC)
1491  * Dynamic Power Management (DPM), Speculative (SPD)
1492  * Ensure our data cache instructions really operate.
1493  * Timebase has to be running or we wouldn't have made it here,
1494  * just ensure we don't disable it.
1495  * Clear Instruction cache throttling (ICTC)
1496  * Enable L2 HW prefetch
1497  */
1498 setup_745x_specifics:
1499         /* We check for the presence of an L3 cache setup by
1500          * the firmware. If any, we disable NAP capability as
1501          * it's known to be bogus on rev 2.1 and earlier
1502          */
1503         mfspr   r11,SPRN_L3CR
1504         andis.  r11,r11,L3CR_L3E@h
1505         beq     1f
1506         lwz     r6,CPU_SPEC_FEATURES(r5)
1507         andi.   r0,r6,CPU_FTR_L3_DISABLE_NAP
1508         beq     1f
1509         li      r7,CPU_FTR_CAN_NAP
1510         andc    r6,r6,r7
1511         stw     r6,CPU_SPEC_FEATURES(r5)
1512 1:      
1513         mfspr   r11,HID0
1514
1515         /* All of the bits we have to set.....
1516          */
1517         ori     r11,r11,HID0_SGE | HID0_FOLD | HID0_BHTE | HID0_BTIC | HID0_LRSTK
1518 BEGIN_FTR_SECTION
1519         oris    r11,r11,HID0_DPM@h      /* enable dynamic power mgmt */
1520 END_FTR_SECTION_IFCLR(CPU_FTR_NO_DPM)
1521
1522         /* All of the bits we have to clear....
1523          */
1524         li      r3,HID0_SPD | HID0_NOPDST | HID0_NOPTI
1525         andc    r11,r11,r3              /* clear SPD: enable speculative */
1526         li      r3,0
1527
1528         mtspr   ICTC,r3                 /* Instruction Cache Throttling off */
1529         isync
1530         mtspr   HID0,r11
1531         sync
1532         isync
1533
1534         /* Enable L2 HW prefetch
1535          */
1536         mfspr   r3,SPRN_MSSCR0
1537         ori     r3,r3,3
1538         sync
1539         mtspr   SPRN_MSSCR0,r3
1540         sync
1541         isync
1542         blr
1543
1544 /*
1545  * Load stuff into the MMU.  Intended to be called with
1546  * IR=0 and DR=0.
1547  */
1548 load_up_mmu:
1549         /* Load the SDR1 register (hash table base & size) */
1550         lis     r6,_SDR1@ha
1551         tophys(r6,r6)
1552         lwz     r6,_SDR1@l(r6)
1553         mtspr   SDR1,r6
1554 #ifdef CONFIG_PPC64BRIDGE
1555         /* clear the ASR so we only use the pseudo-segment registers. */
1556         li      r6,0
1557         mtasr   r6
1558 #endif /* CONFIG_PPC64BRIDGE */
1559         li      r0,16           /* load up segment register values */
1560         mtctr   r0              /* for context 0 */
1561         lis     r3,0x2000       /* Ku = 1, VSID = 0 */
1562         li      r4,0
1563 3:      mtsrin  r3,r4
1564         addi    r3,r3,0x111     /* increment VSID */
1565         addis   r4,r4,0x1000    /* address of next segment */
1566         bdnz    3b
1567 /* Load the BAT registers with the values set up by MMU_init.
1568    MMU_init takes care of whether we're on a 601 or not. */
1569         mfpvr   r3
1570         srwi    r3,r3,16
1571         cmpwi   r3,1
1572         lis     r3,BATS@ha
1573         addi    r3,r3,BATS@l
1574         tophys(r3,r3)
1575         LOAD_BAT(0,r3,r4,r5)
1576         LOAD_BAT(1,r3,r4,r5)
1577         LOAD_BAT(2,r3,r4,r5)
1578         LOAD_BAT(3,r3,r4,r5)
1579         blr
1580
1581 /*
1582  * This is where the main kernel code starts.
1583  */
1584 start_here:
1585         /* ptr to current */
1586         lis     r2,init_task_union@h
1587         ori     r2,r2,init_task_union@l
1588         /* Set up for using our exception vectors */
1589         /* ptr to phys current thread */
1590         tophys(r4,r2)
1591         addi    r4,r4,THREAD    /* init task's THREAD */
1592         CLR_TOP32(r4)
1593         mtspr   SPRG3,r4
1594         li      r3,0
1595         mtspr   SPRG2,r3        /* 0 => r1 has kernel sp */
1596
1597         /* stack */
1598         addi    r1,r2,TASK_UNION_SIZE
1599         li      r0,0
1600         stwu    r0,-STACK_FRAME_OVERHEAD(r1)
1601 /*
1602  * Do early bootinfo parsing, platform-specific initialization,
1603  * and set up the MMU.
1604  */
1605         mr      r3,r31
1606         mr      r4,r30
1607         mr      r5,r29
1608         mr      r6,r28
1609         mr      r7,r27
1610         bl      machine_init
1611         bl      MMU_init
1612
1613 #ifdef CONFIG_APUS
1614         /* Copy exception code to exception vector base on APUS. */
1615         lis     r4,KERNELBASE@h
1616 #ifdef CONFIG_APUS_FAST_EXCEPT
1617         lis     r3,0xfff0               /* Copy to 0xfff00000 */
1618 #else
1619         lis     r3,0                    /* Copy to 0x00000000 */
1620 #endif
1621         li      r5,0x4000               /* # bytes of memory to copy */
1622         li      r6,0
1623         bl      copy_and_flush          /* copy the first 0x4000 bytes */
1624 #endif  /* CONFIG_APUS */
1625
1626 /*
1627  * Go back to running unmapped so we can load up new values
1628  * for SDR1 (hash table pointer) and the segment registers
1629  * and change to using our exception vectors.
1630  */
1631         lis     r4,2f@h
1632         ori     r4,r4,2f@l
1633         tophys(r4,r4)
1634         li      r3,MSR_KERNEL & ~(MSR_IR|MSR_DR)
1635         FIX_SRR1(r3,r5)
1636         mtspr   SRR0,r4
1637         mtspr   SRR1,r3
1638         SYNC
1639         RFI
1640 /* Load up the kernel context */
1641 2:
1642         sync                    /* Force all PTE updates to finish */
1643         isync
1644         tlbia                   /* Clear all TLB entries */
1645         sync                    /* wait for tlbia/tlbie to finish */
1646         TLBSYNC                 /* ... on all CPUs */
1647
1648         bl      load_up_mmu
1649
1650 #ifdef CONFIG_BDI_SWITCH
1651         /* Add helper information for the Abatron bdiGDB debugger.
1652          * We do this here because we know the mmu is disabled, and
1653          * will be enabled for real in just a few instructions.
1654          */
1655         lis     r5, abatron_pteptrs@h
1656         ori     r5, r5, abatron_pteptrs@l
1657         stw     r5, 0xf0(r0)    /* This much match your Abatron config */
1658         lis     r6, swapper_pg_dir@h
1659         ori     r6, r6, swapper_pg_dir@l
1660         tophys(r5, r5)
1661         stw     r6, 0(r5)
1662 #endif
1663
1664 /* Now turn on the MMU for real! */
1665         li      r4,MSR_KERNEL
1666         FIX_SRR1(r4,r5)
1667         lis     r3,start_kernel@h
1668         ori     r3,r3,start_kernel@l
1669         mtspr   SRR0,r3
1670         mtspr   SRR1,r4
1671         SYNC
1672         RFI
1673
1674 /*
1675  * Set up the segment registers for a new context.
1676  */
1677 _GLOBAL(set_context)
1678         mulli   r3,r3,897       /* multiply context by skew factor */
1679         rlwinm  r3,r3,4,8,27    /* VSID = (context & 0xfffff) << 4 */
1680         addis   r3,r3,0x6000    /* Set Ks, Ku bits */
1681         li      r0,NUM_USER_SEGMENTS
1682         mtctr   r0
1683
1684 #ifdef CONFIG_BDI_SWITCH
1685         /* Context switch the PTE pointer for the Abatron BDI2000.
1686          * The PGDIR is passed as second argument.
1687          */
1688         lis     r5, KERNELBASE@h
1689         lwz     r5, 0xf0(r5)
1690         stw     r4, 0x4(r5)
1691 #endif
1692
1693         li      r4,0
1694 BEGIN_FTR_SECTION
1695         DSSALL
1696         sync
1697 END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
1698 3:      isync
1699 #ifdef CONFIG_PPC64BRIDGE
1700         slbie   r4
1701 #endif /* CONFIG_PPC64BRIDGE */
1702         mtsrin  r3,r4
1703         addi    r3,r3,0x111     /* next VSID */
1704         rlwinm  r3,r3,0,8,3     /* clear out any overflow from VSID field */
1705         addis   r4,r4,0x1000    /* address of next segment */
1706         bdnz    3b
1707         sync
1708         isync
1709         blr
1710
1711 /* 
1712  * An undocumented "feature" of 604e requires that the v bit
1713  * be cleared before changing BAT values.
1714  *
1715  * Also, newer IBM firmware does not clear bat3 and 4 so
1716  * this makes sure it's done.
1717  *  -- Cort 
1718  */
1719 clear_bats:
1720         li      r20,0
1721         mfspr   r9,PVR
1722         rlwinm  r9,r9,16,16,31          /* r9 = 1 for 601, 4 for 604 */
1723         cmpwi   r9, 1
1724         beq     1f
1725
1726         mtspr   DBAT0U,r20
1727         mtspr   DBAT0L,r20
1728         mtspr   DBAT1U,r20
1729         mtspr   DBAT1L,r20
1730         mtspr   DBAT2U,r20
1731         mtspr   DBAT2L,r20
1732         mtspr   DBAT3U,r20
1733         mtspr   DBAT3L,r20
1734 1:
1735         mtspr   IBAT0U,r20
1736         mtspr   IBAT0L,r20
1737         mtspr   IBAT1U,r20
1738         mtspr   IBAT1L,r20
1739         mtspr   IBAT2U,r20
1740         mtspr   IBAT2L,r20
1741         mtspr   IBAT3U,r20
1742         mtspr   IBAT3L,r20
1743         blr
1744
1745 flush_tlbs:
1746         lis     r20, 0x40
1747 1:      addic.  r20, r20, -0x1000
1748         tlbie   r20
1749         blt     1b
1750         sync
1751         blr
1752
1753 mmu_off:
1754         addi    r4, r3, __after_mmu_off - _start
1755         mfmsr   r3
1756         andi.   r0,r3,MSR_DR|MSR_IR             /* MMU enabled? */
1757         beqlr
1758         andc    r3,r3,r0
1759         mtspr   SRR0,r4
1760         mtspr   SRR1,r3
1761         sync
1762         RFI
1763
1764 /*
1765  * Use the first pair of BAT registers to map the 1st 16MB
1766  * of RAM to KERNELBASE.  From this point on we can't safely
1767  * call OF any more.
1768  */
1769 initial_bats:
1770         lis     r11,KERNELBASE@h
1771 #ifndef CONFIG_PPC64BRIDGE
1772         mfspr   r9,PVR
1773         rlwinm  r9,r9,16,16,31          /* r9 = 1 for 601, 4 for 604 */
1774         cmpi    0,r9,1
1775         bne     4f
1776         ori     r11,r11,4               /* set up BAT registers for 601 */
1777         li      r8,0x7f                 /* valid, block length = 8MB */
1778         oris    r9,r11,0x800000@h       /* set up BAT reg for 2nd 8M */
1779         oris    r10,r8,0x800000@h       /* set up BAT reg for 2nd 8M */
1780         mtspr   IBAT0U,r11              /* N.B. 601 has valid bit in */
1781         mtspr   IBAT0L,r8               /* lower BAT register */
1782         mtspr   IBAT1U,r9
1783         mtspr   IBAT1L,r10
1784         isync
1785         blr
1786 #endif /* CONFIG_PPC64BRIDGE */
1787
1788 4:      tophys(r8,r11)
1789 #ifdef CONFIG_SMP
1790         ori     r8,r8,0x12              /* R/W access, M=1 */
1791 #else
1792         ori     r8,r8,2                 /* R/W access */
1793 #endif /* CONFIG_SMP */
1794 #ifdef CONFIG_APUS
1795         ori     r11,r11,BL_8M<<2|0x2    /* set up 8MB BAT registers for 604 */
1796 #else
1797         ori     r11,r11,BL_256M<<2|0x2  /* set up BAT registers for 604 */
1798 #endif /* CONFIG_APUS */
1799
1800 #ifdef CONFIG_PPC64BRIDGE
1801         /* clear out the high 32 bits in the BAT */
1802         clrldi  r11,r11,32
1803         clrldi  r8,r8,32
1804 #endif /* CONFIG_PPC64BRIDGE */
1805         mtspr   DBAT0L,r8               /* N.B. 6xx (not 601) have valid */
1806         mtspr   DBAT0U,r11              /* bit in upper BAT register */
1807         mtspr   IBAT0L,r8
1808         mtspr   IBAT0U,r11
1809         isync
1810         blr
1811
1812 #if !defined(CONFIG_APUS) && defined(CONFIG_BOOTX_TEXT)
1813 setup_disp_bat:
1814         /*
1815          * setup the display bat prepared for us in prom.c
1816          */
1817         mflr    r8
1818         bl      reloc_offset
1819         mtlr    r8
1820         addis   r8,r3,disp_BAT@ha
1821         addi    r8,r8,disp_BAT@l
1822         lwz     r11,0(r8)
1823         lwz     r8,4(r8)
1824         mfspr   r9,PVR
1825         rlwinm  r9,r9,16,16,31          /* r9 = 1 for 601, 4 for 604 */
1826         cmpi    0,r9,1
1827         beq     1f
1828         mtspr   DBAT3L,r8
1829         mtspr   DBAT3U,r11
1830         blr
1831 1:      mtspr   IBAT3L,r8
1832         mtspr   IBAT3U,r11
1833         blr
1834
1835 #endif /* !defined(CONFIG_APUS) && defined(CONFIG_BOOTX_TEXT) */
1836
1837 #ifdef CONFIG_8260
1838 /* Jump into the system reset for the rom.
1839  * We first disable the MMU, and then jump to the ROM reset address.
1840  *
1841  * r3 is the board info structure, r4 is the location for starting.
1842  * I use this for building a small kernel that can load other kernels,
1843  * rather than trying to write or rely on a rom monitor that can tftp load.
1844  */
1845        .globl  m8260_gorom
1846 m8260_gorom:
1847         mfmsr   r0
1848         rlwinm  r0,r0,0,17,15   /* clear MSR_EE in r0 */
1849         sync
1850         mtmsr   r0
1851         sync
1852         mfspr   r11, HID0
1853         lis     r10, 0
1854         ori     r10,r10,HID0_ICE|HID0_DCE
1855         andc    r11, r11, r10
1856         mtspr   HID0, r11
1857         isync
1858         li      r5, MSR_
1859         lis     r6,2f@h
1860         addis   r6,r6,-KERNELBASE@h
1861         ori     r6,r6,2f@l
1862         mtspr   SRR0,r6
1863         mtspr   SRR1,r5
1864         isync
1865         sync
1866         rfi
1867 2:
1868         mtlr    r4
1869         blr
1870 #endif
1871
1872
1873 /*
1874  * We put a few things here that have to be page-aligned.
1875  * This stuff goes at the beginning of the data segment,
1876  * which is page-aligned.
1877  */
1878         .data
1879         .globl  sdata
1880 sdata:
1881         .globl  empty_zero_page
1882 empty_zero_page:
1883         .space  4096
1884
1885         .globl  swapper_pg_dir
1886 swapper_pg_dir:
1887         .space  4096
1888
1889 /*
1890  * This space gets a copy of optional info passed to us by the bootstrap
1891  * Used to pass parameters into the kernel like root=/dev/sda1, etc.
1892  */
1893         .globl  cmd_line
1894 cmd_line:
1895         .space  512
1896
1897         .globl intercept_table
1898 intercept_table:
1899         .long 0, 0, i0x200, i0x300, i0x400, 0, i0x600, i0x700
1900         .long i0x800, 0, 0, 0, 0, i0xd00, 0, 0
1901         .long 0, 0, 0, i0x1300, 0, 0, 0, 0
1902         .long 0, 0, 0, 0, 0, 0, 0, 0
1903         .long 0, 0, 0, 0, 0, 0, 0, 0
1904         .long 0, 0, 0, 0, 0, 0, 0, 0
1905
1906 #ifdef CONFIG_BDI_SWITCH
1907 /* Room for two PTE pointers, usually the kernel and current user pointers
1908  * to their respective root page table.
1909  */
1910 abatron_pteptrs:
1911         .space  8
1912 #endif