Ok. I didn't make 2.4.0 in 2000. Tough. I tried, but we had some
[davej-history.git] / arch / ppc / kernel / head_8xx.S
blob40579ce63052ecf9c18a1d0792b3d4c8d94305f9
1 /*
2  *  arch/ppc/kernel/except_8xx.S
3  *
4  *  $Id: head_8xx.S,v 1.4 1999/09/18 18:43:19 dmalek Exp $
5  *
6  *  PowerPC version 
7  *    Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
8  *  Rewritten by Cort Dougan (cort@cs.nmt.edu) for PReP
9  *    Copyright (C) 1996 Cort Dougan <cort@cs.nmt.edu>
10  *  Low-level exception handlers and MMU support
11  *  rewritten by Paul Mackerras.
12  *    Copyright (C) 1996 Paul Mackerras.
13  *  MPC8xx modifications by Dan Malek
14  *    Copyright (C) 1997 Dan Malek (dmalek@jlc.net).
15  *
16  *  This file contains low-level support and setup for PowerPC 8xx
17  *  embedded processors, including trap and interrupt dispatch.
18  *
19  *  This program is free software; you can redistribute it and/or
20  *  modify it under the terms of the GNU General Public License
21  *  as published by the Free Software Foundation; either version
22  *  2 of the License, or (at your option) any later version.
23  *      
24  */
26 #include "ppc_asm.h"
27 #include <asm/processor.h>
28 #include <asm/page.h>
29 #include <linux/config.h>
30 #include <asm/mmu.h>
31 #include <asm/cache.h>
32 #include <asm/pgtable.h>
33         
34 /* XXX need definitions here for 16 byte cachelines on some/all 8xx
35    -- paulus */
36 CACHELINE_BYTES = 32
37 LG_CACHELINE_BYTES = 5
38 CACHELINE_MASK = 0x1f
39 CACHELINE_WORDS = 8
41         .text
42         .globl  _stext
43 _stext:
46  * _start is defined this way because the XCOFF loader in the OpenFirmware
47  * on the powermac expects the entry point to be a procedure descriptor.
48  */
49         .text
50         .globl  _start
51 _start:
53 /* MPC8xx
54  * This port was done on an MBX board with an 860.  Right now I only
55  * support an ELF compressed (zImage) boot from EPPC-Bug because the
56  * code there loads up some registers before calling us:
57  *   r3: ptr to board info data
58  *   r4: initrd_start or if no initrd then 0
59  *   r5: initrd_end - unused if r4 is 0
60  *   r6: Start of command line string
61  *   r7: End of command line string
62  *
63  * I decided to use conditional compilation instead of checking PVR and
64  * adding more processor specific branches around code I don't need.
65  * Since this is an embedded processor, I also appreciate any memory
66  * savings I can get.
67  *
68  * The MPC8xx does not have any BATs, but it supports large page sizes.
69  * We first initialize the MMU to support 8M byte pages, then load one
70  * entry into each of the instruction and data TLBs to map the first
71  * 8M 1:1.  I also mapped an additional I/O space 1:1 so we can get to
72  * the "internal" processor registers before MMU_init is called.
73  *
74  * The TLB code currently contains a major hack.  Since I use the condition
75  * code register, I have to save and restore it.  I am out of registers, so
76  * I just store it in memory location 0 (the TLB handlers are not reentrant).
77  * To avoid making any decisions, I need to use the "segment" valid bit
78  * in the first level table, but that would require many changes to the
79  * Linux page directory/table functions that I don't want to do right now.
80  *
81  * I used to use SPRG2 for a temporary register in the TLB handler, but it
82  * has since been put to other uses.  I now use a hack to save a register
83  * and the CCR at memory location 0.....Someday I'll fix this.....
84  *      -- Dan
85  */
86         
87         .globl  __start
88 __start:
89         mr      r31,r3                  /* save parameters */
90         mr      r30,r4
91         mr      r29,r5
92         mr      r28,r6
93         mr      r27,r7
94         li      r24,0                   /* cpu # */
96         tlbia                   /* Invalidate all TLB entries */
97         li      r8, 0
98         mtspr   MI_CTR, r8      /* Set instruction control to zero */
99         lis     r8, MD_RESETVAL@h
100 #ifndef CONFIG_8xx_COPYBACK
101         oris    r8, r8, MD_WTDEF@h
102 #endif
103         mtspr   MD_CTR, r8      /* Set data TLB control */
105         /* Now map the lower 8 Meg into the TLBs.  For this quick hack,
106          * we can load the instruction and data TLB registers with the
107          * same values.
108          */
109         lis     r8, KERNELBASE@h        /* Create vaddr for TLB */
110         ori     r8, r8, MI_EVALID       /* Mark it valid */
111         mtspr   MI_EPN, r8
112         mtspr   MD_EPN, r8
113         li      r8, MI_PS8MEG           /* Set 8M byte page */
114         ori     r8, r8, MI_SVALID       /* Make it valid */
115         mtspr   MI_TWC, r8
116         mtspr   MD_TWC, r8
117         li      r8, MI_BOOTINIT         /* Create RPN for address 0 */
118         mtspr   MI_RPN, r8              /* Store TLB entry */
119         mtspr   MD_RPN, r8
120         lis     r8, MI_Kp@h             /* Set the protection mode */
121         mtspr   MI_AP, r8
122         mtspr   MD_AP, r8
124         /* Map another 8 MByte at the IMMR to get the processor
125          * internal registers (among other things).
126          */
127         mfspr   r9, 638                 /* Get current IMMR */
128         andis.  r9, r9, 0xff80          /* Get 8Mbyte boundary */
130         mr      r8, r9                  /* Create vaddr for TLB */
131         ori     r8, r8, MD_EVALID       /* Mark it valid */
132         mtspr   MD_EPN, r8
133         li      r8, MD_PS8MEG           /* Set 8M byte page */
134         ori     r8, r8, MD_SVALID       /* Make it valid */
135         mtspr   MD_TWC, r8
136         mr      r8, r9                  /* Create paddr for TLB */
137         ori     r8, r8, MI_BOOTINIT|0x2 /* Inhibit cache -- Cort */
138         mtspr   MD_RPN, r8
140         /* Since the cache is enabled according to the information we
141          * just loaded into the TLB, invalidate and enable the caches here.
142          * We should probably check/set other modes....later.
143          */
144         lis     r8, IDC_INVALL@h
145         mtspr   IC_CST, r8
146         mtspr   DC_CST, r8
147         lis     r8, IDC_ENABLE@h
148         mtspr   IC_CST, r8
149 #ifdef CONFIG_8xx_COPYBACK
150         mtspr   DC_CST, r8
151 #else
152         /* For a debug option, I left this here to easily enable
153          * the write through cache mode
154          */
155         lis     r8, DC_SFWT@h
156         mtspr   DC_CST, r8
157         lis     r8, IDC_ENABLE@h
158         mtspr   DC_CST, r8
159 #endif
161 /* We now have the lower 8 Meg mapped into TLB entries, and the caches
162  * ready to work.
163  */
165 turn_on_mmu:
166         mfmsr   r0
167         ori     r0,r0,MSR_DR|MSR_IR
168         mtspr   SRR1,r0
169         lis     r0,start_here@h
170         ori     r0,r0,start_here@l
171         mtspr   SRR0,r0
172         SYNC
173         rfi                             /* enables MMU */
176  * Exception entry code.  This code runs with address translation
177  * turned off, i.e. using physical addresses.
178  * We assume sprg3 has the physical address of the current
179  * task's thread_struct.
180  */
181 #define EXCEPTION_PROLOG        \
182         mtspr   SPRG0,r20;      \
183         mtspr   SPRG1,r21;      \
184         mfcr    r20;            \
185         mfspr   r21,SPRG2;              /* exception stack to use from */ \
186         cmpwi   0,r21,0;                /* user mode or RTAS */ \
187         bne     1f;             \
188         tophys(r21,r1);                 /* use tophys(kernel sp) otherwise */ \
189         subi    r21,r21,INT_FRAME_SIZE; /* alloc exc. frame */\
190 1:      stw     r20,_CCR(r21);          /* save registers */ \
191         stw     r22,GPR22(r21); \
192         stw     r23,GPR23(r21); \
193         mfspr   r20,SPRG0;      \
194         stw     r20,GPR20(r21); \
195         mfspr   r22,SPRG1;      \
196         stw     r22,GPR21(r21); \
197         mflr    r20;            \
198         stw     r20,_LINK(r21); \
199         mfctr   r22;            \
200         stw     r22,_CTR(r21);  \
201         mfspr   r20,XER;        \
202         stw     r20,_XER(r21);  \
203         mfspr   r22,SRR0;       \
204         mfspr   r23,SRR1;       \
205         stw     r0,GPR0(r21);   \
206         stw     r1,GPR1(r21);   \
207         stw     r2,GPR2(r21);   \
208         stw     r1,0(r21);      \
209         tovirt(r1,r21);                 /* set new kernel sp */ \
210         SAVE_4GPRS(3, r21);     \
211         SAVE_GPR(7, r21);
213  * Note: code which follows this uses cr0.eq (set if from kernel),
214  * r21, r22 (SRR0), and r23 (SRR1).
215  */
218  * Exception vectors.
219  */
220 #define STD_EXCEPTION(n, label, hdlr)           \
221         . = n;                                  \
222 label:                                          \
223         EXCEPTION_PROLOG;                       \
224         addi    r3,r1,STACK_FRAME_OVERHEAD;     \
225         li      r20,MSR_KERNEL;                 \
226         bl      transfer_to_handler;            \
227         .long   hdlr;                           \
228         .long   ret_from_except
230 /* System reset */
231 #ifdef CONFIG_SMP /* MVME/MTX start the secondary here */
232         STD_EXCEPTION(0x100, Reset, __secondary_start_psurge)
233 #else
234         STD_EXCEPTION(0x100, Reset, UnknownException)
235 #endif  
237 /* Machine check */
238         STD_EXCEPTION(0x200, MachineCheck, MachineCheckException)
240 /* Data access exception.
241  * This is "never generated" by the MPC8xx.  We jump to it for other
242  * translation errors.
243  */
244         . = 0x300
245 DataAccess:
246         EXCEPTION_PROLOG
247         mfspr   r20,DSISR
248         stw     r20,_DSISR(r21)
249         mr      r5,r20
250         mfspr   r4,DAR
251         stw     r4,_DAR(r21)
252         addi    r3,r1,STACK_FRAME_OVERHEAD
253         li      r20,MSR_KERNEL
254         rlwimi  r20,r23,0,16,16         /* copy EE bit from saved MSR */
255         bl      transfer_to_handler
256         .long   do_page_fault
257         .long   ret_from_except
259 /* Instruction access exception.
260  * This is "never generated" by the MPC8xx.  We jump to it for other
261  * translation errors.
262  */
263         . = 0x400
264 InstructionAccess:
265         EXCEPTION_PROLOG
266         addi    r3,r1,STACK_FRAME_OVERHEAD
267         mr      r4,r22
268         mr      r5,r23
269         li      r20,MSR_KERNEL
270         rlwimi  r20,r23,0,16,16         /* copy EE bit from saved MSR */
271         bl      transfer_to_handler
272         .long   do_page_fault
273         .long   ret_from_except
275 /* External interrupt */
276         . = 0x500;
277 HardwareInterrupt:
278         EXCEPTION_PROLOG;
279         addi    r3,r1,STACK_FRAME_OVERHEAD
280         li      r20,MSR_KERNEL
281         li      r4,0
282         bl      transfer_to_handler
283         .globl do_IRQ_intercept
284 do_IRQ_intercept:
285         .long   do_IRQ;
286         .long   ret_from_intercept
287         
289 /* Alignment exception */
290         . = 0x600
291 Alignment:
292         EXCEPTION_PROLOG
293         mfspr   r4,DAR
294         stw     r4,_DAR(r21)
295         mfspr   r5,DSISR
296         stw     r5,_DSISR(r21)
297         addi    r3,r1,STACK_FRAME_OVERHEAD
298         li      r20,MSR_KERNEL
299         rlwimi  r20,r23,0,16,16         /* copy EE bit from saved MSR */
300         bl      transfer_to_handler
301         .long   AlignmentException
302         .long   ret_from_except
304 /* Program check exception */
305         . = 0x700
306 ProgramCheck:
307         EXCEPTION_PROLOG
308         addi    r3,r1,STACK_FRAME_OVERHEAD
309         li      r20,MSR_KERNEL
310         rlwimi  r20,r23,0,16,16         /* copy EE bit from saved MSR */
311         bl      transfer_to_handler
312         .long   ProgramCheckException
313         .long   ret_from_except
315 /* No FPU on MPC8xx.  This exception is not supposed to happen.
317         STD_EXCEPTION(0x800, FPUnavailable, UnknownException)
319         . = 0x900
320 Decrementer:
321         EXCEPTION_PROLOG
322         addi    r3,r1,STACK_FRAME_OVERHEAD
323         li      r20,MSR_KERNEL
324         bl      transfer_to_handler
325         .globl timer_interrupt_intercept
326 timer_interrupt_intercept:
327         .long   timer_interrupt
328         .long   ret_from_intercept
330         STD_EXCEPTION(0xa00, Trap_0a, UnknownException)
331         STD_EXCEPTION(0xb00, Trap_0b, UnknownException)
333 /* System call */
334         . = 0xc00
335 SystemCall:
336         EXCEPTION_PROLOG
337         stw     r3,ORIG_GPR3(r21)
338         li      r20,MSR_KERNEL
339         rlwimi  r20,r23,0,16,16         /* copy EE bit from saved MSR */
340         bl      transfer_to_handler
341         .long   DoSyscall
342         .long   ret_from_except
344 /* Single step - not used on 601 */
345         STD_EXCEPTION(0xd00, SingleStep, SingleStepException)
347         STD_EXCEPTION(0xe00, Trap_0e, UnknownException)
348         STD_EXCEPTION(0xf00, Trap_0f, UnknownException)
350 /* On the MPC8xx, this is a software emulation interrupt.  It occurs
351  * for all unimplemented and illegal instructions.
352  */
353         STD_EXCEPTION(0x1000, SoftEmu, SoftwareEmulation)
355         . = 0x1100
357  * For the MPC8xx, this is a software tablewalk to load the instruction
358  * TLB.  It is modelled after the example in the Motorola manual.  The task
359  * switch loads the M_TWB register with the pointer to the first level table.
360  * If we discover there is no second level table (the value is zero), the
361  * plan was to load that into the TLB, which causes another fault into the
362  * TLB Error interrupt where we can handle such problems.  However, that did
363  * not work, so if we discover there is no second level table, we restore
364  * registers and branch to the error exception.  We have to use the MD_xxx
365  * registers for the tablewalk because the equivalent MI_xxx registers
366  * only perform the attribute functions.
367  */
368 InstructionTLBMiss:
369 #ifdef CONFIG_8xx_CPU6
370         stw     r3, 8(r0)
371         li      r3, 0x3f80
372         stw     r3, 12(r0)
373         lwz     r3, 12(r0)
374 #endif
375         mtspr   M_TW, r20       /* Save a couple of working registers */
376         mfcr    r20
377         stw     r20, 0(r0)
378         stw     r21, 4(r0)
379         mfspr   r20, SRR0       /* Get effective address of fault */
380 #ifdef CONFIG_8xx_CPU6
381         li      r3, 0x3780
382         stw     r3, 12(r0)
383         lwz     r3, 12(r0)
384 #endif
385         mtspr   MD_EPN, r20     /* Have to use MD_EPN for walk, MI_EPN can't */
386         mfspr   r20, M_TWB      /* Get level 1 table entry address */
388         /* If we are faulting a kernel address, we have to use the
389          * kernel page tables.
390          */
391         andi.   r21, r20, 0x0800        /* Address >= 0x80000000 */
392         beq     3f
393         lis     r21, swapper_pg_dir@h
394         ori     r21, r21, swapper_pg_dir@l
395         rlwimi  r20, r21, 0, 2, 19
397         lwz     r21, 0(r20)     /* Get the level 1 entry */
398         rlwinm. r20, r21,0,0,19 /* Extract page descriptor page address */
399         beq     2f              /* If zero, don't try to find a pte */
401         /* We have a pte table, so load the MI_TWC with the attributes
402          * for this page, which has only bit 31 set.
403          */
404         tophys(r21,r21)
405         ori     r21,r21,1               /* Set valid bit */
406 #ifdef CONFIG_8xx_CPU6
407         li      r3, 0x2b80
408         stw     r3, 12(r0)
409         lwz     r3, 12(r0)
410 #endif
411         mtspr   MI_TWC, r21     /* Set page attributes */
412 #ifdef CONFIG_8xx_CPU6
413         li      r3, 0x3b80
414         stw     r3, 12(r0)
415         lwz     r3, 12(r0)
416 #endif
417         mtspr   MD_TWC, r21     /* Load pte table base address */
418         mfspr   r21, MD_TWC     /* ....and get the pte address */
419         lwz     r20, 0(r21)     /* Get the pte */
420 #if 0
421         ori     r20, r20, _PAGE_ACCESSED
422         stw     r20, 0(r21)
423 #endif
425         /* Set four subpage valid bits (24, 25, 26, and 27).
426          * Clear bit 28 (which should be in the PTE, but we do this anyway).
427          */
428         li      r21, 0x00f0
429         rlwimi  r20, r21, 0, 24, 28
430 #ifdef CONFIG_8xx_CPU6
431         li      r3, 0x2d80
432         stw     r3, 12(r0)
433         lwz     r3, 12(r0)
434 #endif
435         mtspr   MI_RPN, r20     /* Update TLB entry */
437         mfspr   r20, M_TW       /* Restore registers */
438         lwz     r21, 0(r0)
439         mtcr    r21
440         lwz     r21, 4(r0)
441 #ifdef CONFIG_8xx_CPU6
442         lwz     r3, 8(r0)
443 #endif
444         rfi
446 2:      mfspr   r20, M_TW       /* Restore registers */
447         lwz     r21, 0(r0)
448         mtcr    r21
449         lwz     r21, 4(r0)
450 #ifdef CONFIG_8xx_CPU6
451         lwz     r3, 8(r0)
452 #endif
453         b       InstructionAccess
455         . = 0x1200
456 DataStoreTLBMiss:
457 #ifdef CONFIG_8xx_CPU6
458         stw     r3, 8(r0)
459         li      r3, 0x3f80
460         stw     r3, 12(r0)
461         lwz     r3, 12(r0)
462 #endif
463         mtspr   M_TW, r20       /* Save a couple of working registers */
464         mfcr    r20
465         stw     r20, 0(r0)
466         stw     r21, 4(r0)
467         mfspr   r20, M_TWB      /* Get level 1 table entry address */
469         /* If we are faulting a kernel address, we have to use the
470          * kernel page tables.
471          */
472         andi.   r21, r20, 0x0800
473         beq     3f
474         lis     r21, swapper_pg_dir@h
475         ori     r21, r21, swapper_pg_dir@l
476         rlwimi r20, r21, 0, 2, 19
478         lwz     r21, 0(r20)     /* Get the level 1 entry */
479         rlwinm. r20, r21,0,0,19 /* Extract page descriptor page address */
480         beq     2f              /* If zero, don't try to find a pte */
482         /* We have a pte table, so load fetch the pte from the table.
483          */
484         tophys(r21, r21)
485         ori     r21, r21, 1     /* Set valid bit in physical L2 page */
486 #ifdef CONFIG_8xx_CPU6
487         li      r3, 0x3b80
488         stw     r3, 12(r0)
489         lwz     r3, 12(r0)
490 #endif
491         mtspr   MD_TWC, r21     /* Load pte table base address */
492         mfspr   r20, MD_TWC     /* ....and get the pte address */
493         lwz     r20, 0(r20)     /* Get the pte */
495         /* Insert the Guarded flag into the TWC from the Linux PTE.
496          * It is bit 27 of both the Linux PTE and the TWC (at least
497          * I got that right :-).  It will be better when we can put
498          * this into the Linux pgd/pmd and load it in the operation
499          * above.
500          */
501         rlwimi  r21, r20, 0, 27, 27
502 #ifdef CONFIG_8xx_CPU6
503         li      r3, 0x3b80
504         stw     r3, 12(r0)
505         lwz     r3, 12(r0)
506 #endif
507         mtspr   MD_TWC, r21
509         /* Set four subpage valid bits (24, 25, 26, and 27).
510          * Clear bit 28 (which should be in the PTE, but we do this anyway).
511          */
512 #if 0
513         ori     r20, r20, 0x00f0
514 #else
515         li      r21, 0x00f0
516         rlwimi  r20, r21, 0, 24, 28
517 #endif
518 #ifdef CONFIG_8xx_CPU6
519         li      r3, 0x3d80
520         stw     r3, 12(r0)
521         lwz     r3, 12(r0)
522 #endif
523         mtspr   MD_RPN, r20     /* Update TLB entry */
525         mfspr   r20, M_TW       /* Restore registers */
526         lwz     r21, 0(r0)
527         mtcr    r21
528         lwz     r21, 4(r0)
529 #ifdef CONFIG_8xx_CPU6
530         lwz     r3, 8(r0)
531 #endif
532         rfi
534 2:      mfspr   r20, M_TW       /* Restore registers */
535         lwz     r21, 0(r0)
536         mtcr    r21
537         lwz     r21, 4(r0)
538 #ifdef CONFIG_8xx_CPU6
539         lwz     r3, 8(r0)
540 #endif
541         b       DataAccess
543 /* This is an instruction TLB error on the MPC8xx.  This could be due
544  * to many reasons, such as executing guarded memory or illegal instruction
545  * addresses.  There is nothing to do but handle a big time error fault.
546  */
547         . = 0x1300
548 InstructionTLBError:
549         b       InstructionAccess
551 /* This is the data TLB error on the MPC8xx.  This could be due to
552  * many reasons, including a dirty update to a pte.  We can catch that
553  * one here, but anything else is an error.  First, we track down the
554  * Linux pte.  If it is valid, write access is allowed, but the
555  * page dirty bit is not set, we will set it and reload the TLB.  For
556  * any other case, we bail out to a higher level function that can
557  * handle it.
558  */
559         . = 0x1400
560 DataTLBError:
561 #ifdef CONFIG_8xx_CPU6
562         stw     r3, 8(r0)
563         li      r3, 0x3f80
564         stw     r3, 12(r0)
565         lwz     r3, 12(r0)
566 #endif
567         mtspr   M_TW, r20       /* Save a couple of working registers */
568         mfcr    r20
569         stw     r20, 0(r0)
570         stw     r21, 4(r0)
572         /* First, make sure this was a store operation.
573         */
574         mfspr   r20, DSISR
575         andis.  r21, r20, 0x0200        /* If set, indicates store op */
576         beq     2f
578         mfspr   r20, M_TWB      /* Get level 1 table entry address */
580         /* If we are faulting a kernel address, we have to use the
581          * kernel page tables.
582          */
583         andi.   r21, r20, 0x0800
584         beq     3f
585         lis     r21, swapper_pg_dir@h
586         ori     r21, r21, swapper_pg_dir@l
587         rlwimi  r20, r21, 0, 2, 19
589         lwz     r21, 0(r20)     /* Get the level 1 entry */
590         rlwinm. r20, r21,0,0,19 /* Extract page descriptor page address */
591         beq     2f              /* If zero, bail */
593         /* We have a pte table, so fetch the pte from the table.
594          */
595         tophys(r21, r21)
596         ori     r21, r21, 1             /* Set valid bit in physical L2 page */
597 #ifdef CONFIG_8xx_CPU6
598         li      r3, 0x3b80
599         stw     r3, 12(r0)
600         lwz     r3, 12(r0)
601 #endif
602         mtspr   MD_TWC, r21             /* Load pte table base address */
603         mfspr   r21, MD_TWC             /* ....and get the pte address */
604         lwz     r20, 0(r21)             /* Get the pte */
606         andi.   r21, r20, _PAGE_RW      /* Is it writeable? */
607         beq     2f                      /* Bail out if not */
609         /* Update 'changed', among others.
610         */
611         ori     r20, r20, _PAGE_DIRTY|_PAGE_HWWRITE|_PAGE_ACCESSED
612         mfspr   r21, MD_TWC             /* Get pte address again */
613         stw     r20, 0(r21)             /* and update pte in table */
615         /* Set four subpage valid bits (24, 25, 26, and 27).
616          * Clear bit 28 (which should be in the PTE, but we do this anyway).
617          */
618         li      r21, 0x00f0
619         rlwimi  r20, r21, 0, 24, 28
620 #ifdef CONFIG_8xx_CPU6
621         li      r3, 0x3d80
622         stw     r3, 12(r0)
623         lwz     r3, 12(r0)
624 #endif
625         mtspr   MD_RPN, r20     /* Update TLB entry */
627         mfspr   r20, M_TW       /* Restore registers */
628         lwz     r21, 0(r0)
629         mtcr    r21
630         lwz     r21, 4(r0)
631 #ifdef CONFIG_8xx_CPU6
632         lwz     r3, 8(r0)
633 #endif
634         rfi
636         mfspr   r20, M_TW       /* Restore registers */
637         lwz     r21, 0(r0)
638         mtcr    r21
639         lwz     r21, 4(r0)
640 #ifdef CONFIG_8xx_CPU6
641         lwz     r3, 8(r0)
642 #endif
643         b       DataAccess
645         STD_EXCEPTION(0x1500, Trap_15, UnknownException)
646         STD_EXCEPTION(0x1600, Trap_16, UnknownException)
647         STD_EXCEPTION(0x1700, Trap_17, TAUException)
648         STD_EXCEPTION(0x1800, Trap_18, UnknownException)
649         STD_EXCEPTION(0x1900, Trap_19, UnknownException)
650         STD_EXCEPTION(0x1a00, Trap_1a, UnknownException)
651         STD_EXCEPTION(0x1b00, Trap_1b, UnknownException)
653 /* On the MPC8xx, these next four traps are used for development
654  * support of breakpoints and such.  Someday I will get around to
655  * using them.
656  */
657         STD_EXCEPTION(0x1c00, Trap_1c, UnknownException)
658         STD_EXCEPTION(0x1d00, Trap_1d, UnknownException)
659         STD_EXCEPTION(0x1e00, Trap_1e, UnknownException)
660         STD_EXCEPTION(0x1f00, Trap_1f, UnknownException)
662         . = 0x2000
665  * This code finishes saving the registers to the exception frame
666  * and jumps to the appropriate handler for the exception, turning
667  * on address translation.
668  */
669         .globl  transfer_to_handler
670 transfer_to_handler:
671         stw     r22,_NIP(r21)
672         lis     r22,MSR_POW@h
673         andc    r23,r23,r22
674         stw     r23,_MSR(r21)
675         SAVE_4GPRS(8, r21)
676         SAVE_8GPRS(12, r21)
677         SAVE_8GPRS(24, r21)
678         andi.   r23,r23,MSR_PR
679         mfspr   r23,SPRG3               /* if from user, fix up THREAD.regs */
680         beq     2f
681         addi    r24,r1,STACK_FRAME_OVERHEAD
682         stw     r24,PT_REGS(r23)
683 2:      addi    r2,r23,-THREAD          /* set r2 to current */
684         tovirt(r2,r2)
685         mflr    r23
686         andi.   r24,r23,0x3f00          /* get vector offset */
687         stw     r24,TRAP(r21)
688         li      r22,RESULT
689         stwcx.  r22,r22,r21             /* to clear the reservation */
690         li      r22,0
691         stw     r22,RESULT(r21)
692         mtspr   SPRG2,r22               /* r1 is now kernel sp */
693         addi    r24,r2,TASK_STRUCT_SIZE /* check for kernel stack overflow */
694         cmplw   0,r1,r2
695         cmplw   1,r1,r24
696         crand   1,1,4
697         bgt-    stack_ovf               /* if r2 < r1 < r2+TASK_STRUCT_SIZE */
698         lwz     r24,0(r23)              /* virtual address of handler */
699         lwz     r23,4(r23)              /* where to go when done */
700         mtspr   SRR0,r24
701         mtspr   SRR1,r20
702         mtlr    r23
703         SYNC
704         rfi                             /* jump to handler, enable MMU */
707  * On kernel stack overflow, load up an initial stack pointer
708  * and call StackOverflow(regs), which should not return.
709  */
710 stack_ovf:
711         addi    r3,r1,STACK_FRAME_OVERHEAD
712         lis     r1,init_task_union@ha
713         addi    r1,r1,init_task_union@l
714         addi    r1,r1,TASK_UNION_SIZE-STACK_FRAME_OVERHEAD
715         lis     r24,StackOverflow@ha
716         addi    r24,r24,StackOverflow@l
717         li      r20,MSR_KERNEL
718         mtspr   SRR0,r24
719         mtspr   SRR1,r20
720         SYNC
721         rfi
723         .globl  giveup_fpu
724 giveup_fpu:
725         blr
728  * This code is jumped to from the startup code to copy
729  * the kernel image to physical address 0.
730  */
731 relocate_kernel:
732         lis     r9,0x426f               /* if booted from BootX, don't */
733         addi    r9,r9,0x6f58            /* translate source addr */
734         cmpw    r31,r9                  /* (we have to on chrp) */
735         beq     7f
736         rlwinm  r4,r4,0,8,31            /* translate source address */
737         add     r4,r4,r3                /* to region mapped with BATs */
738 7:      addis   r9,r26,klimit@ha        /* fetch klimit */
739         lwz     r25,klimit@l(r9)
740         addis   r25,r25,-KERNELBASE@h
741         li      r6,0                    /* Destination offset */
742         li      r5,0x4000               /* # bytes of memory to copy */
743         bl      copy_and_flush          /* copy the first 0x4000 bytes */
744         addi    r0,r3,4f@l              /* jump to the address of 4f */
745         mtctr   r0                      /* in copy and do the rest. */
746         bctr                            /* jump to the copy */
747 4:      mr      r5,r25
748         bl      copy_and_flush          /* copy the rest */
749         b       turn_on_mmu
752  * Copy routine used to copy the kernel to start at physical address 0
753  * and flush and invalidate the caches as needed.
754  * r3 = dest addr, r4 = source addr, r5 = copy limit, r6 = start offset
755  * on exit, r3, r4, r5 are unchanged, r6 is updated to be >= r5.
756  */
757 copy_and_flush:
758         addi    r5,r5,-4
759         addi    r6,r6,-4
760 4:      li      r0,CACHELINE_WORDS
761         mtctr   r0
762 3:      addi    r6,r6,4                 /* copy a cache line */
763         lwzx    r0,r6,r4
764         stwx    r0,r6,r3
765         bdnz    3b
766         dcbst   r6,r3                   /* write it to memory */
767         sync
768         icbi    r6,r3                   /* flush the icache line */
769         cmplw   0,r6,r5
770         blt     4b
771         isync
772         addi    r5,r5,4
773         addi    r6,r6,4
774         blr
776 #ifdef CONFIG_SMP
777         .globl  __secondary_start_psurge
778 __secondary_start_psurge:
779         li      r24,1                   /* cpu # */
780         b       __secondary_start
782         .globl  __secondary_hold
783 __secondary_hold:
784         /* tell the master we're here */
785         lis     r5,0x4@h
786         ori     r5,r5,0x4@l
787         stw     r3,0(r5)
788         dcbf    0,r5
789 100:
790         lis     r5,0
791         dcbi    0,r5
792         lwz     r4,0(r5)
793         /* wait until we're told to start */
794         cmp     0,r4,r3
795         bne     100b
796         /* our cpu # was at addr 0 - go */
797         lis     r5,__secondary_start@h
798         ori     r5,r5,__secondary_start@l
799         tophys(r5,r5)
800         mtlr    r5
801         mr      r24,r3                  /* cpu # */
802         blr
803 #endif /* CONFIG_SMP */
804         
806  * This is where the main kernel code starts.
807  */
808 start_here:
809 #ifdef CONFIG_SMP
810         /* if we're the second cpu stack and r2 are different
811         * and we want to not clear the bss -- Cort */
812         lis     r5,first_cpu_booted@h
813         ori     r5,r5,first_cpu_booted@l
814         lwz     r5,0(r5)
815         cmpi    0,r5,0
816         beq     99f
818         /* get current */
819         lis     r2,current_set@h
820         ori     r2,r2,current_set@l
821         slwi    r24,r24,2                       /* cpu # to current_set[cpu#] */
822         add     r2,r2,r24
823         lwz     r2,0(r2)
824         b       10f
825 99:     
826 #endif /* CONFIG_SMP */
827         /* ptr to current */
828         lis     r2,init_task_union@h
829         ori     r2,r2,init_task_union@l
830         /* Clear out the BSS */
831         lis     r11,_end@ha
832         addi    r11,r11,_end@l
833         lis     r8,__bss_start@ha
834         addi    r8,r8,__bss_start@l
835         subf    r11,r8,r11
836         addi    r11,r11,3
837         rlwinm. r11,r11,30,2,31
838         beq     2f
839         addi    r8,r8,-4
840         mtctr   r11
841         li      r0,0
842 3:      stwu    r0,4(r8)
843         bdnz    3b
845 #ifdef CONFIG_SMP       
847 #endif /* CONFIG_SMP */
848         /* stack */
849         addi    r1,r2,TASK_UNION_SIZE
850         li      r0,0
851         stwu    r0,-STACK_FRAME_OVERHEAD(r1)
853  * Decide what sort of machine this is and initialize the MMU.
854  */
855         mr      r3,r31
856         mr      r4,r30
857         mr      r5,r29
858         mr      r6,r28
859         mr      r7,r27
860         bl      identify_machine
861         bl      MMU_init
864  * Go back to running unmapped so we can load up new values
865  * for SDR1 (hash table pointer) and the segment registers
866  * and change to using our exception vectors.
867  * On the 8xx, all we have to do is invalidate the TLB to clear
868  * the old 8M byte TLB mappings and load the page table base register.
869  */
870         /* The right way to do this would be to track it down through
871          * init's THREAD like the context switch code does, but this is
872          * easier......until someone changes init's static structures.
873          */
874         lis     r6, swapper_pg_dir@h
875         tophys(r6,r6)
876         ori     r6, r6, swapper_pg_dir@l
877 #ifdef CONFIG_8xx_CPU6
878         lis     r4, cpu6_errata_word@h
879         ori     r4, r4, cpu6_errata_word@l
880         li      r3, 0x3980
881         stw     r3, 12(r4)
882         lwz     r3, 12(r4)
883 #endif
884         mtspr   M_TWB, r6
885         lis     r4,2f@h
886         ori     r4,r4,2f@l
887         tophys(r4,r4)
888         li      r3,MSR_KERNEL & ~(MSR_IR|MSR_DR)
889         mtspr   SRR0,r4
890         mtspr   SRR1,r3
891         rfi
892 /* Load up the kernel context */
894         SYNC                    /* Force all PTE updates to finish */
895         tlbia                   /* Clear all TLB entries */
896         sync                    /* wait for tlbia/tlbie to finish */
897 #ifdef CONFIG_SMP
898         tlbsync                 /* ... on all CPUs */
899         sync
900 #endif
901 /* Set up for using our exception vectors */
902         /* ptr to phys current thread */
903         tophys(r4,r2)
904         addi    r4,r4,THREAD    /* init task's THREAD */
905         mtspr   SPRG3,r4
906         li      r3,0
907         mtspr   SPRG2,r3        /* 0 => r1 has kernel sp */
908 /* Now turn on the MMU for real! */
909         li      r4,MSR_KERNEL
910         lis     r3,start_kernel@h
911         ori     r3,r3,start_kernel@l
912 #ifdef CONFIG_SMP
913         /* the second time through here we go to
914          * start_secondary(). -- Cort
915          */
916         lis     r5,first_cpu_booted@h
917         ori     r5,r5,first_cpu_booted@l
918         tophys(r5,r5)
919         lwz     r5,0(r5)
920         cmpi    0,r5,0
921         beq     10f
922         lis     r3,start_secondary@h
923         ori     r3,r3,start_secondary@l
924 10:     
925 #endif /* CONFIG_SMP */
926         mtspr   SRR0,r3
927         mtspr   SRR1,r4
928         rfi                     /* enable MMU and jump to start_kernel */
931  * Set up to use a given MMU context.
933  * The MPC8xx has something that currently happens "automagically."
934  * Unshared user space address translations are subject to ASID (context)
935  * match.  During each task switch, the ASID is incremented.  We can
936  * guarantee (I hope :-) that no entries currently match this ASID
937  * because every task will cause at least a TLB entry to be loaded for
938  * the first instruction and data access, plus the kernel running will
939  * have displaced several more TLBs.  The MMU contains 32 entries for
940  * each TLB, and there are 16 contexts, so we just need to make sure
941  * two pages get replaced for every context switch, which currently
942  * happens.  There are other TLB management techniques that I will
943  * eventually implement, but this is the easiest for now.  -- Dan
945  * On the MPC8xx, we place the physical address of the new task
946  * page directory loaded into the MMU base register, and set the
947  * ASID compare register with the new "context".
948  */
949 _GLOBAL(set_context)
950 #ifdef CONFIG_8xx_CPU6
951         lis     r6, cpu6_errata_word@h
952         ori     r6, r6, cpu6_errata_word@l
953         tophys  (r4, r4)
954         li      r7, 0x3980
955         stw     r7, 12(r6)
956         lwz     r7, 12(r6)
957         mtspr   M_TWB, r4               /* Update MMU base address */
958         li      r7, 0x3380
959         stw     r7, 12(r6)
960         lwz     r7, 12(r6)
961         mtspr   M_CASID, r3             /* Update context */
962 #else
963         mtspr   M_CASID,r3              /* Update context */
964         tophys  (r4, r4)
965         mtspr   M_TWB, r4               /* and pgd */
966 #endif
967         tlbia
968         SYNC
969         blr
971 /* Jump into the system reset for the rom.
972  * We first disable the MMU, and then jump to the ROM reset address.
974  * r3 is the board info structure, r4 is the location for starting.
975  * I use this for building a small kernel that can load other kernels,
976  * rather than trying to write or rely on a rom monitor that can tftp load.
977  */
978        .globl  m8xx_gorom
979 m8xx_gorom:
980        li      r5,MSR_KERNEL & ~(MSR_IR|MSR_DR)
981        lis     r6,2f@h
982        addis   r6,r6,-KERNELBASE@h
983        ori     r6,r6,2f@l
984        mtspr   SRR0,r6
985        mtspr   SRR1,r5
986        rfi
988        mtlr    r4
989        blr
991 #ifdef CONFIG_8xx_CPU6
992 /* It's here because it is unique to the 8xx.
993  * It is important we get called with interrupts disabled.  I used to
994  * do that, but it appears that all code that calls this already had
995  * interrupt disabled.
996  */
997         .globl  set_dec_cpu6
998 set_dec_cpu6:
999         lis     r7, cpu6_errata_word@h
1000         ori     r7, r7, cpu6_errata_word@l
1001         li      r4, 0x2c00
1002         stw     r4, 8(r7)
1003         lwz     r4, 8(r7)
1004         mtspr   22, r3          /* Update Decrementer */
1005         SYNC
1006         blr
1007 #endif
1008         
1010  * We put a few things here that have to be page-aligned.
1011  * This stuff goes at the beginning of the data segment,
1012  * which is page-aligned.
1013  */
1014         .data
1015         .globl  sdata
1016 sdata:
1017         .globl  empty_zero_page
1018 empty_zero_page:
1019         .space  4096
1021         .globl  swapper_pg_dir
1022 swapper_pg_dir:
1023         .space  4096    
1026  * This space gets a copy of optional info passed to us by the bootstrap
1027  * Used to pass parameters into the kernel like root=/dev/sda1, etc.
1028  */     
1029         .globl  cmd_line
1030 cmd_line:
1031         .space  512
1033 #ifdef CONFIG_8xx_CPU6
1034         .globl  cpu6_errata_word
1035 cpu6_errata_word:
1036         .space  16
1037 #endif