Unify access to I/O and memory of the microchannel bus. Spares one segment register.
[linux-2.6/power.git] / arch / power / kernel / head.S
blobf915200894ea71c99115089deab8d724cba2c296
1 #include <asm/processor.h>
2 #include <asm/page.h>
3 #include <asm/mmu.h>
4 #include <asm/pgtable.h>
5 #include <asm/cputable.h>
6 #include <asm/cache.h>
7 #include <asm/thread_info.h>
8 #include <asm/ppc_asm.h>
9 #include <asm/asm-offsets.h>
12  * Code execution starts here.
13  *
14  * The code is loaded at the correct address (0) by the boot loader.
15  * The following registers contain valid information:
16  * 
17  *    r3 - IPL info block
18  *    r4 - IPL extended info block
19  *
20  */
21         .text
22         .stabs  "arch/ppc/kernel/",N_SO,0,0,0f
23         .stabs  "head.S",N_SO,0,0,0f
25         .global _stext
26 _stext:
28         .global _start
29 _start:
30         /*
31          * Save parameters we are passed
32          */
33         mr      r31,r3
34         mr      r30,r4
35         li      r24,0   /* CPU number */
37 #if 1
38         /*
39          * Establish a default MSR
40          */
41         li      r3,0x3880
42         mtmsr   r3
43 #endif
45 #if 0   /* No need its there anyway. */
46         /*
47          * Setup a stack right in front of the BIOS information passed
48          */
49         subi    r1,r3,16
50 #endif
52 #if 1   /* Initialize serial port for debugging */
53         bl      init_serial
54 #endif
57  * early_init() does the early machine identification and does
58  * the necessary low-level setup and clears the BSS
59  *  -- Cort <cort@fsmlabs.com>
60  */
61         mr      r3,r31
62         bl      early_init
64 /* Switch MMU off, clear BATs and flush TLB. At this point, r3 contains
65  * the physical address we are running at, returned by early_init()
66  */
67         bl      mmu_off
68 __after_mmu_off:
69         bl      flush_tlbs
71 /* Setup some kind of mapping
72  */
73         bl      initial_mmu
75 /* Start into the kernel address space
76  */
77         mfmsr   r0
78         ori     r0,r0,MSR_DR|MSR_IR
79         mtspr   SPRN_SRR1,r0
80         lis     r0,start_here@h
81         ori     r0,r0,start_here@l
82         mtspr   SPRN_SRR0,r0
83         SYNC
84         RFI                             /* enables MMU */
87 #define SVC_PROLOG                              \
88         stw     r10,_SPRG0@l(0);                \
89         stw     r11,_SPRG1@l(0);                \
90         mfcr    r10;                            \
91         mflr    r11;                            \
92         mtspr   SPRN_SRR0,r11;                  \
93         mfctr   r11;                            \
94         andil.  r11,r11,0xffff;                 \
95         mtspr   SPRN_SRR1,r11;                  \
96         EXCEPTION_PROLOG_1;                     \
97         EXCEPTION_PROLOG_2
100 #define EXCEPTION(n, label, hdlr, xfer)         \
101         . = n;                                  \
102 label:                                          \
103         EXCEPTION_PROLOG;                       \
104         addi    r3,r1,STACK_FRAME_OVERHEAD;     \
105         xfer(n, hdlr)
108 #define EXCEPTION_PROLOG                        \
109         stw     r10,_SPRG0@l(0);                \
110         stw     r11,_SPRG1@l(0);                \
111         mfcr    r10;                            \
112         EXCEPTION_PROLOG_1;                     \
113         EXCEPTION_PROLOG_2
115 #define EXCEPTION_PROLOG_1                      \
116         mfspr   r11,SPRN_SRR1;          /* check wether user or kernel */       \
117         andi.   r11,r11,MSR_PR;                 \
118         tophys(r11,r1);                 /* use tophys(r1) if kernel    */       \
119         beq     1f;                             \
120         lwz     r11,_SPRG3@l(0);                        \
121         lwz     r11,THREAD_INFO-THREAD(r11);    \
122         addi    r11,r11,THREAD_SIZE;            \
123         tophys(r11,r11);                        \
124 1:      subi    r11,r11,INT_FRAME_SIZE; /* alloc exc- frame */
126 #define EXCEPTION_PROLOG_2                      \
127         CLR_TOP32(r11);                         \
128         stw     r10,_CCR(r11);                  \
129         stw     r12,GPR12(r11);                 \
130         stw     r9,GPR9(r11);                   \
131         lwz     r10,_SPRG0@l(0);                \
132         stw     r10,GPR10(r11);                 \
133         lwz     r12,_SPRG1@l(0);                \
134         stw     r12,GPR11(r11);                 \
135         mflr    r10;                            \
136         stw     r10,_LINK(r11);                 \
137         mfspr   r12,SPRN_SRR0;                  \
138         mfspr   r9,SPRN_SRR1;                   \
139         stw     r1,GPR1(11);                    \
140         stw     r1,0(r11);                      \
141         tovirt(r1,r11);                 /* set new kernel sp */ \
142         li      r10,MSR_KERNEL & ~(MSR_IR|MSR_DR); /* can take exceptions */ \
143         MTMSRD(r10);                            \
144         stw     r0,GPR0(r11);                   \
145         SAVE_4GPRS(3, r11);                     \
146         SAVE_2GPRS(7, r11)
148 #define EXC_XFER_TEMPLATE(n, hdlr, trap, copyee, tfer, ret)     \
149         li      r10,trap;                                       \
150         stw     r10,TRAP(r11);                                  \
151         li      r10,MSR_KERNEL;                                 \
152         copyee(r10, r9);                                        \
153         bl      tfer;                                           \
154 i##n:                                                           \
155         .long   hdlr;                                           \
156         .long   ret
158 #define COPY_EE(d, s)           rlwimi d,s,0,16,16
159 #define NOCOPY(d, s)
161 #define EXC_XFER_STD(n, hdlr)           \
162         EXC_XFER_TEMPLATE(n, hdlr, n, NOCOPY, transfer_to_handler_full, \
163                           ret_from_except_full)
165 #define EXC_XFER_LITE(n, hdlr)          \
166         EXC_XFER_TEMPLATE(n, hdlr, n+1, NOCOPY, transfer_to_handler, \
167                           ret_from_except)
169 #define EXC_XFER_EE(n, hdlr)            \
170         EXC_XFER_TEMPLATE(n, hdlr, n, COPY_EE, transfer_to_handler_full, \
171                           ret_from_except_full)
173 #define EXC_XFER_EE_LITE(n, hdlr)       \
174         EXC_XFER_TEMPLATE(n, hdlr, n+1, COPY_EE, transfer_to_handler, \
175                           ret_from_except)
179 #if 1   /* For debugging purpose we install our own trap handlers */
181 .macro panic errtxt, ledcod
182         stm     0,saved_regs_ex-_start(0)
183         # last segment, wraps to zero on first loop run
184         lis     2,0xF000
185         # offset to reach the next segment
186         liu     4,0x1000
187         # start saving 4 bytes later
188         li      5,saved_regs_ex-_start+32*4-4
189         # stop when we would next store there
190         li      6,saved_regs_ex-_start+32*4+16*4
192         mfsri   3,2,4
193         stu     3,4(5)
194         cmpl    0,5,6
195         bne     1b
197         li      1,_stack_ex-_start+4096-16
199         lis     3,0x820C
200         ori     3,3,0x00E0
201         mtsr    11,3
203         lis     3,0
204         li      3,\errtxt - _start
205         bl      puts
206         lis     3,0
207         li      3,t_at - _start
208         bl      puts
210         bl      2f
212         mflr    0
213         ai      0,0,\errtxt - 1b 
214         mr      3,0
215         bl      puts
217         mfsrr0  3
218         bl      display_long
219         lis     3,0
220         li      3,nl - _start
221         bl      puts
223         b       dump_regs
225         lis     3,0x8204
226         ori     3,3,0x0080
227         mtsr    11,3
228         lis     3,0xB0A0
229         ics
230         lis     4,\ledcod
231         st      4,0x300(3)
233         b       .
235 .endm
237 . = 0x100
238         panic   err1,0xe010
239 #. = 0x200
240 #        panic   err2,0xe020
241 /* Machine check */
242         . = 0x200
243         stw     r10,_SPRG0@l(0)
244         stw     r11,_SPRG1@l(0)
245         mfcr    r10
246         EXCEPTION_PROLOG_1
247 7:      EXCEPTION_PROLOG_2
248         addi    r3,r1,STACK_FRAME_OVERHEAD
249         EXC_XFER_STD(0x200, machine_check_exception)
251 #. = 0x300
252 #        panic   err3,0xe030
253 /* Data access exception. */
254         . = 0x300
255 DataAccess:
256         EXCEPTION_PROLOG
257         mfspr   r10,SPRN_DSISR
258         andis.  r0,r10,0xa470           /* weird error? */
259         bne     1f                      /* if not, try to put a PTE */
260         mfspr   r4,SPRN_DAR             /* into the hash table */
261         rlwinm  r3,r10,32-20,26,26      /* DSISR_STORE -> _PAGE_RW */
262         bl      hash_page
263 1:      stw     r10,_DSISR(r11)
264         mr      r5,r10
265         mfspr   r4,SPRN_DAR
266         EXC_XFER_EE_LITE(0x300, handle_page_fault)
268 . = 0x400
269         panic   err4,0xe040
270 #. = 0x500
271 #        panic   err5,0xe050
272         EXCEPTION(0x500, HardwareInterrupt, do_IRQ, EXC_XFER_LITE)
273 . = 0x600
274         panic   err6,0xe060
275 #. = 0x700
276 #        panic   err7,0xe070
277         EXCEPTION(0x700, ProgramCheck, program_check_exception, EXC_XFER_STD)
278 #. = 0x800
279 #        panic   err8,0xe080
280 /* Floating-point unavailable */
281         . = 0x800
282 FPUnavailable:
283         EXCEPTION_PROLOG
284         bne     load_up_fpu             /* if from user, just load it up */
285         addi    r3,r1,STACK_FRAME_OVERHEAD
286         EXC_XFER_EE_LITE(0x800, kernel_fp_unavailable_exception)
288 . = 0x900
289         panic   err9,0xe090
290 . = 0xA00
291         panic   err10,0xe100
292 . = 0xB00
293         panic   err11,0xe110
294 . = 0xC00
295         panic   err12,0xe120
296 . = 0xD00
297         panic   err13,0xe130
298 . = 0xE00
299         panic   err14,0xe140
300 . = 0xF00
301         panic   err15,0xe150
302 . = 0x1000
303 #        panic   err16,0xe160
304 SystemCall:
305         SVC_PROLOG
306         EXC_XFER_EE_LITE(0x1000, DoSyscall)
308 . = 0x2000
309 _stack_ex:
310 . = 0x3000
313 saved_regs_ex:  .space 32*4
314                 .space 16*4
316 err1:   .asciz  "\r\nPANIC ERROR SYSTEM RESET"
317 err2:   .asciz  "\r\nPANIC ERROR MACHINE CHECK"
318 err3:   .asciz  "\r\nPANIC ERROR DATA STORAGE"
319 err4:   .asciz  "\r\nPANIC ERROR INSTRUCTION STORAGE"
320 err5:   .asciz  "\r\nPANIC ERROR EXTERNAL INTERRUPT"
321 err6:   .asciz  "\r\nPANIC ERROR ALIGNMENT INTERRUPT"
322 err7:   .asciz  "\r\nPANIC ERROR PROGRAM"
323 err8:   .asciz  "\r\nPANIC ERROR FPU UNAVAIL"
324 err9:   .asciz  "\r\nPANIC ERROR 9"
325 err10:   .asciz  "\r\nPANIC ERROR 10"
326 err11:   .asciz  "\r\nPANIC ERROR 11"
327 err12:   .asciz  "\r\nPANIC ERROR 12"
328 err13:   .asciz  "\r\nPANIC ERROR 13"
329 err14:   .asciz  "\r\nPANIC ERROR 14"
330 err15:   .asciz  "\r\nPANIC ERROR 15"
331 err16:   .asciz  "\r\nPANIC SYSTEM CALL 0"
332 t_at:   .asciz  " at "
333 nl:     .asciz  "\r\n"
335 _r0:    .asciz "\r\nr0   ";
336 _r1:    .asciz " r1   ";
337 _r2:    .asciz " r2   ";
338 _r3:    .asciz " r3   ";
339 _r4:    .asciz " r4   ";
340 _r5:    .asciz " r5   ";
341 _r6:    .asciz " r6   ";
342 _r7:    .asciz " r7   ";
343 _r8:    .asciz "\r\nr8   ";
344 _r9:    .asciz " r9   ";
345 _r10:   .asciz " r10  ";
346 _r11:   .asciz " r11  ";
347 _r12:   .asciz " r12  ";
348 _r13:   .asciz " r13  ";
349 _r14:   .asciz " r14  ";
350 _r15:   .asciz " r15  ";
351 _r16:   .asciz "\r\nr16  ";
352 _r17:   .asciz " r17  ";
353 _r18:   .asciz " r18  ";
354 _r19:   .asciz " r19  ";
355 _r20:   .asciz " r20  ";
356 _r21:   .asciz " r21  ";
357 _r22:   .asciz " r22  ";
358 _r23:   .asciz " r23  ";
359 _r24:   .asciz "\r\nr24  ";
360 _r25:   .asciz " r25  ";
361 _r26:   .asciz " r26  ";
362 _r27:   .asciz " r27  ";
363 _r28:   .asciz " r28  ";
364 _r29:   .asciz " r29  ";
365 _r30:   .asciz " r30  ";
366 _r31:   .asciz " r31  ";
367 _sr0:   .asciz "\r\nsr0   ";
368 _sr1:   .asciz " sr1   ";
369 _sr2:   .asciz " sr2   ";
370 _sr3:   .asciz " sr3   ";
371 _sr4:   .asciz " sr4   ";
372 _sr5:   .asciz " sr5   ";
373 _sr6:   .asciz " sr6   ";
374 _sr7:   .asciz " sr7   ";
375 _sr8:   .asciz "\r\nsr8   ";
376 _sr9:   .asciz " sr9   ";
377 _sr10:  .asciz " sr10  ";
378 _sr11:  .asciz " sr11  ";
379 _sr12:  .asciz " sr12  ";
380 _sr13:  .asciz " sr13  ";
381 _sr14:  .asciz " sr14  ";
382 _sr15:  .asciz " sr15  ";
383         .align 4
385 _regs:
386         .long _r0 - _start
387         .long _r1 - _start
388         .long _r2 - _start
389         .long _r3 - _start
390         .long _r4 - _start
391         .long _r5 - _start
392         .long _r6 - _start
393         .long _r7 - _start
394         .long _r8 - _start
395         .long _r9 - _start
396         .long _r10 - _start
397         .long _r11 - _start
398         .long _r12 - _start
399         .long _r13 - _start
400         .long _r14 - _start
401         .long _r15 - _start
402         .long _r16 - _start
403         .long _r17 - _start
404         .long _r18 - _start
405         .long _r19 - _start
406         .long _r20 - _start
407         .long _r21 - _start
408         .long _r22 - _start
409         .long _r23 - _start
410         .long _r24 - _start
411         .long _r25 - _start
412         .long _r26 - _start
413         .long _r27 - _start
414         .long _r28 - _start
415         .long _r29 - _start
416         .long _r30 - _start
417         .long _r31 - _start
418         .long _sr0 - _start
419         .long _sr1 - _start
420         .long _sr2 - _start
421         .long _sr3 - _start
422         .long _sr4 - _start
423         .long _sr5 - _start
424         .long _sr6 - _start
425         .long _sr7 - _start
426         .long _sr8 - _start
427         .long _sr9 - _start
428         .long _sr10 - _start
429         .long _sr11 - _start
430         .long _sr12 - _start
431         .long _sr13 - _start
432         .long _sr14 - _start
433         .long _sr15 - _start
434         .long 0
436 dump_regs:
437         lis     r25,0
438         li      r25,_regs - _start - 4 
439         lis     26,0
440         li      26,saved_regs_ex - _start - 4
443         lwzu    r3,4(r25)
444         or.     r3,r3,r3
446         beq-    3f
448         bl      puts
449         lwzu    r3,4(r26)
450         bl      display_long
451         b       2b
454         li      3,nl - _start
455         bl      puts
457         lis     26,0
458         li      26,saved_regs_ex - _start - 4
459         lwz     25,8(26)        # saved 1
460         rlwinm  25,25,0,0,19
461         tophys(r25,r25)
462         ai      24,25,0xffc
463         ai      25,25,-4
464         
467         lwzu    r26,4(25)
468         mr      r3,r25
469         bl      display_long
470         lil     r3,0x20
471         bl      rs6000_serial_putc
472         mr      r3,r26
473         bl      display_long
474         lil     r3,0x20
475         bl      rs6000_serial_putc
476         lwzu    r3,4(25)
477         bl      display_long
478         lil     r3,0x20
479         bl      rs6000_serial_putc
480         lwzu    r3,4(25)
481         bl      display_long
482         lil     r3,0x20
483         bl      rs6000_serial_putc
484         lwzu    r3,4(25)
485         bl      display_long
486         lil     r3,0x20
487         bl      rs6000_serial_putc
488         lwzu    r3,4(25)
489         bl      display_long
490         lil     r3,0x20
491         bl      rs6000_serial_putc
492         lwzu    r3,4(25)
493         bl      display_long
494         lil     r3,0x20
495         bl      rs6000_serial_putc
496         lwzu    r3,4(25)
497         bl      display_long
498         lil     r3,0x20
499         bl      rs6000_serial_putc
500         lwzu    r3,4(25)
501         bl      display_long
502         lis     3,0
503         li      3,nl - _start
504         bl      puts
506         cmp     0,r25,r24
507         blt     0,4b
509         b       .
510 #else
514         EXCEPTION(0x100, Reset, unknown_exception, EXC_XFER_STD)
516 /* Machine check */
517         . = 0x200
518         stw     r10,_SPRG0@l(0)
519         stw     r11,_SPRG1@l(0)
520         mfcr    r10
521         EXCEPTION_PROLOG_1
522 7:      EXCEPTION_PROLOG_2
523         addi    r3,r1,STACK_FRAME_OVERHEAD
524         EXC_XFER_STD(0x200, machine_check_exception)
526 /* Data access exception. */
527         . = 0x300
528 DataAccess:
529         EXCEPTION_PROLOG
530         mfspr   r10,SPRN_DSISR
531         andis.  r0,r10,0xa470           /* weird error? */
532         bne     1f                      /* if not, try to put a PTE */
533         mfspr   r4,SPRN_DAR             /* into the hash table */
534         rlwinm  r3,r10,32-15,21,21      /* DSISR_STORE -> _PAGE_RW */
535         bl      hash_page
536 1:      stw     r10,_DSISR(r11)
537         mr      r5,r10
538         mfspr   r4,SPRN_DAR
539         EXC_XFER_EE_LITE(0x300, handle_page_fault)
541 /* Instruction access exception. */
542         . = 0x400
543 InstructionAccess:
544         EXCEPTION_PROLOG
545         andis.  r0,r9,0x4000            /* no pte found? */
546         beq     1f                      /* if so, try to put a PTE */
547         li      r3,0                    /* into the hash table */
548         mr      r4,r12                  /* SRR0 is fault address */
549         bl      hash_page
550 1:      mr      r4,r12
551         mr      r5,r9
552         EXC_XFER_EE_LITE(0x400, handle_page_fault)
554 /* External interrupt */
555         EXCEPTION(0x500, HardwareInterrupt, do_IRQ, EXC_XFER_LITE)
557 /* Alignment exception */
558         . = 0x600
559 Alignment:
560         EXCEPTION_PROLOG
561         mfspr   r4,SPRN_DAR
562         stw     r4,_DAR(r11)
563         mfspr   r5,SPRN_DSISR
564         stw     r5,_DSISR(r11)
565         addi    r3,r1,STACK_FRAME_OVERHEAD
566         EXC_XFER_EE(0x600, alignment_exception)
568 /* Program check exception */
569         EXCEPTION(0x700, ProgramCheck, program_check_exception, EXC_XFER_STD)
571 /* Floating-point unavailable */
572         . = 0x800
573 FPUnavailable:
574         EXCEPTION_PROLOG
575         bne     load_up_fpu             /* if from user, just load it up */
576         addi    r3,r1,STACK_FRAME_OVERHEAD
577         EXC_XFER_EE_LITE(0x800, kernel_fp_unavailable_exception)
579 /* Decrementer */
580         EXCEPTION(0x900, Decrementer, timer_interrupt, EXC_XFER_LITE)
582         EXCEPTION(0xa00, Trap_0a, unknown_exception, EXC_XFER_EE)
583         EXCEPTION(0xb00, Trap_0b, unknown_exception, EXC_XFER_EE)
585 /* System call */
586         . = 0xc00
587 SystemCall:
588         EXCEPTION_PROLOG
589         EXC_XFER_EE_LITE(0xc00, DoSyscall)
592         EXCEPTION(0xe00, Trap_0e, unknown_exception, EXC_XFER_EE)
594         . = 0xf00
595         b       Trap_0f
597 Trap_0f:
598         EXCEPTION_PROLOG
599         addi    r3,r1,STACK_FRAME_OVERHEAD
600         EXC_XFER_EE(0xf00, unknown_exception)
602 #endif  // Debugging traps
604         .global _SPRG0
605 _SPRG0: .long 0
606         .global _SPRG1
607 _SPRG1: .long 0
608         .global _SPRG2
609 _SPRG2: .long 0
610         .global _SPRG3
611 _SPRG3: .long 0
614  * Load stuff into the MMU.  Intended to be called with
615  * IR=0 and DR=0.
616  */
617 #if 0
618 load_up_mmu:
619         dcs                    /* Force all PTE updates to finish */
620         ics
621         bl      flush_tlbs      /* (was: tlbia) Clear all TLB entries */
622         dcs                     /* wait for tlbia/tlbie to finish */
623         TLBSYNC                 /* ... on all CPUs */
624         /* Load the SDR1 register (hash table base & size) */
625         lis     r6,_SDR1@ha
626         tophys(r6,r6)
627         lwz     r6,_SDR1@l(r6)
628         mtspr   SPRN_SDR1,r6
629         li      r0,16           /* load up segment register values */
630         mtctr   r0              /* for context 0 */
631         lis     r3,0x2000       /* Ku = 1, VSID = 0 */
632         li      r4,0
633 3:      mtsri   r3,r4
634         addi    r3,r3,0x111     /* increment VSID */
635         addis   r4,r4,0x1000    /* address of next segment */
636         bdnz    3b
637 #endif
639 #if 0
640 /* Load the BAT registers with the values set up by MMU_init.
641    MMU_init takes care of whether we're on a 601 or not. */
642         mfpvr   r3
643         srwi    r3,r3,16
644         cmpwi   r3,1
645         lis     r3,BATS@ha
646         addi    r3,r3,BATS@l
647         tophys(r3,r3)
648         LOAD_BAT(0,r3,r4,r5)
649         LOAD_BAT(1,r3,r4,r5)
650         LOAD_BAT(2,r3,r4,r5)
651         LOAD_BAT(3,r3,r4,r5)
652 #endif
654         blr
657 /* This is where the main kernel code starts.
658  */
659 start_here:
660         /* ptr to current */
661         lis     r2,init_task@h
662         ori     r2,r2,init_task@l
664         /* ptr to phys current thread */
665         tophys(r4,r2)
666         addi    r4,r4,THREAD    /* init task's THREAD */
667         CLR_TOP32(r4)
668         lis     r3,_SPRG3@h
669         stw     r4,_SPRG3@l(r3)
671         /* stack */
672         lis     r1,init_thread_union@ha
673         addi    r1,r1,init_thread_union@l
674         li      r0,0
675         stwu    r0,THREAD_SIZE-STACK_FRAME_OVERHEAD(r1)
678         lis     r3,hello_world@h
679         ori     r3,r3,hello_world@l
680         bl      puts
683  * Do early bootinfo parsing, platform-specific initialization,
684  * and set up the MMU.
685  */
686         mr      r3,r31
687         mr      r4,r30
688         li      r5,0
689         li      r6,0
690         li      r7,0
691         bl      machine_init
692         bl      MMU_init
694 #if 0
696  * Go back to running unmapped so we can load up new values
697  * for SDR1 (hash table pointer) and the segment registers
698  * and change to using our exception vectors.
699  */
700         lis     r4,2f@h
701         ori     r4,r4,2f@l
702         tophys(r4,r4)
703         li      r3,MSR_KERNEL & ~(MSR_IR|MSR_DR)
704         FIX_SRR1(r3,r5)
705         mtspr   SPRN_SRR0,r4
706         mtspr   SPRN_SRR1,r3
707         SYNC
708         RFI
709 /* Load up the kernel context */
710 2:      bl      load_up_mmu
711 #endif
714         mfsr    r4,15
718  * Setup some segment register values which stick
719  */
720         //
721         // local IOCC
722         //
723         lis     r0,0x8000
724         mtsr    15,r0
725         //
726         // We can address the first MCA bus by
727         // the following segment values:
728         //  820C0000   I/O only
729         //  820C0020   Memory 
730         //  820C0030   both
731         //
732         lis     r0,0x820C
733         ori     r0,r0,0x30
734         mtsr    14,r0
735         //
736         // IOCC of first MCA bus
737         //
738         lis     0,0x820C
739         ori     0,0,0x00E0
740         mtsr    11,r0
741         ics
743         /*
744          * Enable all interrupts in the local IOCC
745          */
746         lis     r0,-1
747         ori     r0,r0,0xffff
748         lis     r3,0xF000
749         stw     r0,0(r3)
750         stw     r0,4(r3)
753         mtsr    r4,15
754         ics
757 /* Now turn on the MMU for real! */
758         li      r4,MSR_KERNEL
759         FIX_SRR1(r4,r5)
760         lis     r3,start_kernel@h
761         ori     r3,r3,start_kernel@l
762         mtspr   SPRN_SRR0,r3
763         mtspr   SPRN_SRR1,r4
764         SYNC
765         RFI
768  * Set up the segment registers for a new context.
769  */
770 _GLOBAL(set_context)
771         mulli   r3,r3,897       /* multiply context by skew factor */
772         rlwinm  r3,r3,4,8,27    /* VSID = (context & 0xfffff) << 4 */
773         addis   r3,r3,0x6000    /* Set Ks, Ku bits */
774         li      r0,NUM_USER_SEGMENTS
775         mtctr   r0
777 #ifdef CONFIG_BDI_SWITCH
778         /* Context switch the PTE pointer for the Abatron BDI2000.
779          * The PGDIR is passed as second argument.
780          */
781         lis     r5, KERNELBASE@h
782         lwz     r5, 0xf0(r5)
783         stw     r4, 0x4(r5)
784 #endif
785         li      r4,0
786         ics
788         mtsri   r3,r4
789         addi    r3,r3,0x111     /* next VSID */
790         rlwinm  r3,r3,0,8,3     /* clear out any overflow from VSID field */
791         addis   r4,r4,0x1000    /* address of next segment */
792         bdnz    3b
793         dcs
794         ics
795         blr
797 flush_tlbs:
798         lis     r10, 0x40
799 1:      addic.  r10, r10, -0x1000
800         tlbi    0, r10
801         blt     1b
802         dcs
803         blr
805 mmu_off:
806         addi    r4, r3, __after_mmu_off - _start
807         mfmsr   r3
808         andi.   r0,r3,MSR_DR|MSR_IR             /* MMU enabled? */
809         beqlr
810         andc    r3,r3,r0
811         mtspr   SPRN_SRR0,r4
812         mtspr   SPRN_SRR1,r3
813         dcs
814         RFI
816 init_serial:
817 #       mfmsr   r6
818         lis     r5,0x820C
819         ori     r5,r5,0x00E0
820         mtsr    11,r5
821         lis     r29,0xB000
822         ori     r29,r29,0x0030
823 #       ori     r5,r6,0x10
824 #       mtmsr   r5
825 #       ics
826         lil     28,0x80
827         stb     28,3(29)
828         lil     28,52   # 9600 baud
829         stb     28,0(29)
830         lil     28,0    # 9600 baud
831         stb     28,1(29)
832         lil     28,0x03 # 8N1
833         stb     28,3(29)
834         lil     28,0
835         stb     28,4(29)
836         lil     28,7
837         stb     28,2(29)
838         lil     28,0
839         stb     28,1(29)
840 #       mtmsr   r6
841 #       ics
842         blr
844         .macro enter firstreg,alloc=0
845                 .set SAVED_REGS_START,\firstreg
846                 .set SAVED_REGS_OFS,-4*(32-SAVED_REGS_START)
847                 .set SAVED_SP,SAVED_REGS_OFS-16-\alloc
848 #               .set SAVED_LR,8
849                 .set SAVED_LR,4
850                 .set RESTORE_LR,SAVED_LR-SAVED_SP
851                 mflr    0               # Get return address
852                 stm     SAVED_REGS_START,SAVED_REGS_OFS(1)
853                 st      0,SAVED_LR(1)
854                 stu     1,SAVED_SP(1)
855         .endm
857         .macro leave
858                 l       0,RESTORE_LR(1)
859                 ai      1,1,-SAVED_SP
860                 mtlr    0
861                 lm      SAVED_REGS_START,SAVED_REGS_OFS(1)
862         .endm
865 .global rs6000_serial_putc
866 rs6000_serial_putc:
867         enter   27
869 #        mfmsr   27
870         lis     r29,0xB000
871 #        oril    28,27,0x10
872         ori     r29,r29,0x0030
873 #        mtmsr   28
874 #        ics
876         lbz     28,5(29)
877         rlinm.  28,28,0,0x20
878         beq     1b
879         stb     3,0(29)
880 #        mtmsr   27
881 #        ics
882         leave
883         brl
885 .global rs6000_display_long
886 rs6000_display_long:
887 display_long:
888         enter   26
889         mfcr    26
890         mflr    27
891         lil     28,8
892         mtctr   28
893         mr      28,3
895         rlinm   28,28,4,0xffffffff      # rotate 4
896         rlinm   29,28,0,0xf             # select lower 4
897         ai.     3,29,-10                 # convert to letter
898         ai      3,3,0x41
899         bge     1f
900         ai      3,29,0x30                # convert to number
902         bl      rs6000_serial_putc
903         bdn     2b
904 #if 0
905         lil     4,8
906         mtctr   4
907         mr      4,3
909         rlinm   4,4,4,0xffffffff        # rotate 4
910         rlinm   5,4,0,0xf               # select lower 4
911         ai.     3,5,-10                 # convert to letter
912         ai      3,3,0x41
913         bge     1f
914         ai      3,5,0x30                # convert to number
916         bl      rs6000_serial_putc
917         bdn     2b
918 #endif
919         mtlr    27
920         mtcr    26
921         leave
922         brl
924 .global rs6000_puts
925 rs6000_puts:
926 puts:
927         enter   27
928         ai      28,3,-1
930         lil     27,1
931         lbzux   3,28,27
932         or.     3,3,3
933         beq     2f
934         bl      rs6000_serial_putc
935         b       1b
938         leave
939         brl
941 hello_world:    .asciz "Hello world!\r\n"
942         .align 4
944 .global setled
945 setled:
946         enter   26
947 #        mfmsr   28
948         mfsr    27,11
949         lis     26,0x8204
950         ori     26,26,0x0080
951         mtsr    11,26
952 #        oril    26,28,0x10
953 #        mtmsr   26
954         lis     26,0xB0A0
955         ics
956         st      3,0x300(26)
957 #        mtmsr   28
958         mtsr    11,27
959         ics
960         leave
961         brl
964  * Initialize the MMU
966  * Setup the HAT and PFT entries for segment 0 until the HAT is fully
967  * populated. A 32kB HAT has 8192 entries which map 32 MB. This
968  * should be sufficient to hold the kernel.
970  * 
971  */
972 initial_mmu:
973         lil     r3,-0x8000              # - Size of HAT, 32kB
974         add     r29,r3,r31              # Position of HAT
975         rlinm   r29,r29,0,0,16          # Align to 32kB boundary
976         addis   r3,r29,-0x10            # - 1 MB
977         rlinm   r28,r3,0,0,11           # Align to 1MB border
980 #if 0
981         lis     r5,0
982         ori     r5,r5,0x2000            # -> 8192 entries
983         mtctr   r5
984         lis     r5,0                    # Page index
985         addi    r6,r29,-4               # HAT address
986         addi    r7,r28,-4               # PFT address
987         lil     r8,0x10                 # First word of PFT entry
988         lis     r3,-0x8000
989         lil     r4,0                    # Zero
990 #else
991         lis     r5,0
992         ori     r5,r5,0x1FFF            # -> 8192 entries
993         mtctr   r5
994         lis     r5,0                    # Page index
995         addi    r6,r29,-4               # HAT address
996         addi    r7,r28,-4               # PFT address
997         lil     r8,0x10                 # First word of PFT entry
998         lis     r3,-0x8000
999         lil     r4,0                    # Zero
1001         stu     r3,4(r6)
1002         stu     r4,4(r7)
1003         stu     r4,4(r7)
1004         stu     r4,4(r7)
1005         stu     r4,4(r7)
1006         ai      r5,r5,1         # next PFT entry
1007 #endif
1009         stu     r5,4(r6)                # Page index is HAT entry
1010         # First word of PFT entry is zero but the valid bit
1011         stu     r8,4(r7)
1012         # Next entry has only bit 0 set for invalid
1013         stu     r3,4(r7)
1014         # Other words of PFT entry are zero
1015         stu     r4,4(r7)
1016         stu     r4,4(r7)
1018         ai      r5,r5,1         # next PFT entry
1019         bdn     1b
1021         # Load SDRx register
1022         mtspr   SPRN_SDR0,r28
1023         rotlwi  r3,r29,1
1024         mtspr   SPRN_SDR1,r3    # HAT mask is 0 anyway
1025         stw     r4,_SPRG3@l(0)
1026         mtsr    12,r4
1028         brl
1032  * We put a few things here that have to be page-aligned.
1033  * This stuff goes at the beginning of the data segment,
1034  * which is page-aligned.
1035  */
1036         .data
1037         .globl  sdata
1038 sdata:
1039         .globl  empty_zero_page
1040 empty_zero_page:
1041         .space  4096
1043         .globl  swapper_pg_dir
1044 swapper_pg_dir:
1045         .space  4096
1048  * This space gets a copy of optional info passed to us by the bootstrap
1049  * Used to pass parameters into the kernel like root=/dev/sda1, etc.
1050  */
1051         .globl  cmd_line
1052 cmd_line:
1053         .space  512