source: rtems/c/src/lib/libbsp/powerpc/shared/bootloader/head.S @ 3605c4e

Last change on this file since 3605c4e was 9cd4a6e8, checked in by Joel Sherrill <joel.sherrill@…>, on 01/03/03 at 16:48:28

2002-12-08 Greg Menke <gregory.menke@…>

  • bootloader/head.S: Added support for optional debug via PPCbug. Also turn off mmu/caches for the bootstrap phase, which seems to cause trouble with the 603. The cpu init functions in the bsp get all that stuff going properly.
  • Property mode set to 100644
File size: 8.9 KB
Line 
1/*
2 *  head.S -- Bootloader Entry point
3 *
4 *  Copyright (C) 1998, 1999 Gabriel Paubert, paubert@iram.es
5 *
6 *  Modified to compile in RTEMS development environment
7 *  by Eric Valette
8 *
9 *  Copyright (C) 1999 Eric Valette. valette@crf.canon.fr
10 *
11 *  The license and distribution terms for this file may be
12 *  found in found in the file LICENSE in this distribution or at
13 *  http://www.OARcorp.com/rtems/license.html.
14 *
15 * $Id$
16 */
17
18#include <asm.h>
19#include <rtems/score/cpu.h>
20#include "bootldr.h"
21
22#define TEST_PPCBUG_CALLS               
23#undef TEST_PPCBUG_CALLS
24       
25#define FRAME_SIZE 32
26#define LOCK_CACHES (HID0_DLOCK | HID0_ILOCK)
27#define INVL_CACHES (HID0_DCI | HID0_ICFI)
28#define ENBL_CACHES (HID0_DCE | HID0_ICE)
29
30#define USE_PPCBUG
31#undef  USE_PPCBUG
32
33       
34#define PRINT_CHAR(c)           \
35        addi    r20,r3,0        ; \
36        li      r3,c            ; \
37        li      r10,0x20        ; \
38        sc                      ; \
39        addi    r3,r20,0        ; \
40        li      r10,0x26        ; \
41        sc
42       
43       
44       
45       
46#define MONITOR_ENTER                   \
47        mfmsr   r10             ;       \
48        ori     r10,r10,MSR_IP  ;       \
49        mtmsr   r10             ;       \
50        li      r10,0x63        ;       \
51        sc
52
53       
54               
55        START_GOT
56        GOT_ENTRY(_GOT2_TABLE_)
57        GOT_ENTRY(_FIXUP_TABLE_)
58        GOT_ENTRY(.bss)
59        GOT_ENTRY(codemove)
60        GOT_ENTRY(0)
61        GOT_ENTRY(__bd)
62        GOT_ENTRY(moved)
63        GOT_ENTRY(_binary_rtems_gz_start)
64        GOT_ENTRY(_binary_initrd_gz_start)
65        GOT_ENTRY(_binary_initrd_gz_end)
66#ifdef TEST_PPCBUG_CALLS       
67        GOT_ENTRY(banner_start)
68        GOT_ENTRY(banner_end)
69#endif 
70        END_GOT
71        .globl  start
72        .type   start,@function
73       
74/* Point the stack into the PreP partition header in the x86 reserved
75 * code area, so that simple C routines can be called.
76 */
77start: 
78#ifdef  USE_PPCBUG
79        MONITOR_ENTER
80#endif
81        bl      1f
821:      mflr    r1
83        li      r0,0
84        stwu    r0,start-1b-0x400+0x1b0-FRAME_SIZE(r1)
85        stmw    r26,FRAME_SIZE-24(r1)
86        GET_GOT
87        mfmsr   r28                     /* Turn off interrupts */
88        ori     r0,r28,MSR_EE
89        xori    r0,r0,MSR_EE
90        mtmsr   r0
91       
92/* Enable the caches, from now on cr2.eq set means processor is 601 */
93       
94        mfpvr   r0
95        mfspr   r29,HID0
96        srwi    r0,r0,16
97        cmplwi  cr2,r0,1
98        beq     2,2f
99
100
101/*
102 * commented out, 11/7/2002, gregm.  This instruction sequence seems to
103 * be pathological on the 603e.
104 *
105       
106#ifndef USE_PPCBUG
107        ori     r0,r29,ENBL_CACHES|INVL_CACHES|LOCK_CACHES
108        xori    r0,r0,INVL_CACHES|LOCK_CACHES
109        sync
110        isync
111        mtspr   HID0,r0
112#endif
113*/
114       
115                       
1162:      bl      reloc
117       
118/* save all the parameters and the orginal msr/hid0/r31 */
119        lwz     bd,GOT(__bd)
120        stw     r3,0(bd)
121        stw     r4,4(bd)
122        stw     r5,8(bd)
123        stw     r6,12(bd)
124        lis     r3,__size@sectoff@ha
125        stw     r7,16(bd)
126        stw     r8,20(bd)
127        addi    r3,r3,__size@sectoff@l
128        stw     r9,24(bd)
129        stw     r10,28(bd)
130        stw     r28,o_msr(bd)
131        stw     r29,o_hid0(bd)
132        stw     r31,o_r31(bd)
133
134/* Call the routine to fill boot_data structure from residual data.
135 * And to find where the code has to be moved.
136 */
137        bl      early_setup
138
139/* Now we need to relocate ourselves, where we are told to. First put a
140 * copy of the codemove routine to some place in memory.
141 * (which may be where the 0x41 partition was loaded, so size is critical).
142 */
143        lwz     r4,GOT(codemove)
144        li      r5,_size_codemove
145        lwz     r3,mover(bd)
146        lwz     r6,cache_lsize(bd)
147
148        bl      codemove
149
150        mtctr   r3              # Where the temporary codemove is.
151        lwz     r3,image(bd)
152        lis     r5,_edata@sectoff@ha
153        lwz     r4,GOT(0)       # Our own address
154        addi    r5,r5,_edata@sectoff@l
155        lwz     r6,cache_lsize(bd)
156        lwz     r8,GOT(moved)
157
158        sub     r7,r3,r4        # Difference to adjust pointers.
159        add     r8,r8,r7
160        add     r30,r30,r7
161        add     bd,bd,r7
162
163/* Call the copy routine but return to the new area. */
164
165        mtlr    r8              # for the return address
166        bctr                    # returns to the moved instruction
167       
168/* Establish the new top stack frame. */
169moved:  lwz     r1,stack(bd)
170        li      r0,0
171        stwu    r0,-16(r1)
172
173/* relocate again */
174        bl      reloc   
175/* Clear all of BSS */
176        lwz     r10,GOT(.bss)
177        li      r0,__bss_words@sectoff@l
178        subi    r10,r10,4
179        cmpwi   r0,0
180        mtctr   r0
181        li      r0,0
182        beq     4f
1833:      stwu    r0,4(r10)
184        bdnz    3b
185
186/* Final memory initialization. First switch to unmapped mode
187 * in case the FW had set the MMU on, and flush the TLB to avoid
188 * stale entries from interfering. No I/O access is allowed
189 * during this time!
190 */
1914:
192#ifdef USE_PPCBUG
193        PRINT_CHAR('M')
194#endif
195        bl      MMUoff
196
197#ifdef USE_PPCBUG       
198        PRINT_CHAR('B')
199#endif
200        bl      flush_tlb
201
202/* Some firmware versions leave stale values in the BATs, it's time
203 * to invalidate them to avoid interferences with our own mappings.
204 * But the 601 valid bit is in the BATL (IBAT only) and others are in
205 * the [ID]BATU. Bloat, bloat.. fortunately thrown away later.
206 */
207#ifdef USE_PPCBUG       
208        PRINT_CHAR('T')
209#endif
210        li      r3,0
211        beq     cr2,5f
212        mtdbatu 0,r3
213        mtdbatu 1,r3
214        mtdbatu 2,r3
215        mtdbatu 3,r3
2165:      mtibatu 0,r3
217        mtibatl 0,r3
218        mtibatu 1,r3
219        mtibatl 1,r3
220        mtibatu 2,r3
221        mtibatl 2,r3
222        mtibatu 3,r3
223        mtibatl 3,r3
224        lis     r3,__size@sectoff@ha
225        addi    r3,r3,__size@sectoff@l
226        sync                            # We are going to touch SDR1 !
227#ifdef USE_PPCBUG       
228        PRINT_CHAR('i')
229#endif
230        bl      mm_init
231       
232#ifdef USE_PPCBUG       
233        PRINT_CHAR('M')
234#endif
235        bl      MMUon
236       
237/* Now we are mapped and can perform I/O if we want */
238#ifdef TEST_PPCBUG_CALLS       
239/* Experience seems to show that PPCBug can only be called with the
240 * data cache disabled and with MMU disabled. Bummer.
241 */     
242        li      r10,0x22                # .OUTLN
243        lwz     r3,GOT(banner_start)
244        lwz     r4,GOT(banner_end)
245        sc
246#endif 
247#ifdef USE_PPCBUG       
248        PRINT_CHAR('H')
249#endif
250        bl      setup_hw
251        lwz     r4,GOT(_binary_rtems_gz_start)
252        lis     r5,_rtems_gz_size@sectoff@ha
253        lwz     r6,GOT(_binary_initrd_gz_start)
254        lis     r3,_rtems_size@sectoff@ha
255        lwz     r7,GOT(_binary_initrd_gz_end)
256        addi    r5,r5,_rtems_gz_size@sectoff@l
257        addi    r3,r3,_rtems_size@sectoff@l
258        sub     r7,r7,r6
259        bl      decompress_kernel
260
261/* Back here we are unmapped and we start the kernel, passing up to eight
262 * parameters just in case, only r3 to r7 used for now. Flush the tlb so
263 * that the loaded image starts in a clean state.
264 */
265        bl      flush_tlb
266        lwz     r3,0(bd)
267        lwz     r4,4(bd)
268        lwz     r5,8(bd)
269        lwz     r6,12(bd)
270        lwz     r7,16(bd)
271        lwz     r8,20(bd)
272        lwz     r9,24(bd)
273        lwz     r10,28(bd)
274
275        lwz     r30,0(0)
276        mtctr   r30
277/*
278 *      Linux code again
279 *
280        lis     r30,0xdeadc0de@ha
281        addi    r30,r30,0xdeadc0de@l
282        stw     r30,0(0)
283        li      r30,0
284*/
285        dcbst   0,r30   /* Make sure it's in memory ! */
286       
287/* We just flash invalidate and disable the dcache, unless it's a 601,
288 * critical areas have been flushed and we don't care about the stack
289 * and other scratch areas.
290 */
291        beq     cr2,1f
292        mfspr   r0,HID0
293        ori     r0,r0,HID0_DCI|HID0_DCE
294        sync
295        mtspr   HID0,r0
296        xori    r0,r0,HID0_DCI|HID0_DCE
297        mtspr   HID0,r0
298       
299/* Provisional return to FW, works for PPCBug */
300#if 0
301        MONITOR_ENTER
302#else
3031:      bctr
304#endif
305               
306       
307
308/* relocation function, r30 must point to got2+0x8000 */
309reloc: 
310/* Adjust got2 pointers, no need to check for 0, this code already puts
311 * a few entries in the table.
312 */
313        li      r0,__got2_entries@sectoff@l
314        la      r12,GOT(_GOT2_TABLE_)
315        lwz     r11,GOT(_GOT2_TABLE_)
316        mtctr   r0
317        sub     r11,r12,r11
318        addi    r12,r12,-4
3191:      lwzu    r0,4(r12)
320        add     r0,r0,r11
321        stw     r0,0(r12)
322        bdnz    1b
323       
324/* Now adjust the fixups and the pointers to the fixups in case we need
325 * to move ourselves again.
326 */     
3272:      li      r0,__fixup_entries@sectoff@l
328        lwz     r12,GOT(_FIXUP_TABLE_)
329        cmpwi   r0,0
330        mtctr   r0
331        addi    r12,r12,-4
332        beqlr
3333:      lwzu    r10,4(r12)
334        lwzux   r0,r10,r11
335        add     r0,r0,r11
336        stw     r10,0(r12)
337        stw     r0,0(r10)
338        bdnz    3b
339        blr             
340
341/* Set the MMU on and off: code is always mapped 1:1 and does not need MMU,
342 * but it does not cost so much to map it also and it catches calls through
343 * NULL function pointers.
344 */
345        .globl  MMUon
346        .type   MMUon,@function
347MMUon:  blr
348        nop
349
350/*     
351        mfmsr   r0
352        ori     r0,r0,MSR_IR|MSR_DR|MSR_IP
353        mflr    r11
354        xori    r0,r0,MSR_IP
355        mtsrr0  r11
356        mtsrr1  r0
357        rfi
358*/
359        .globl  MMUoff
360        .type   MMUoff,@function
361MMUoff: blr
362        nop
363       
364/*
365        mfmsr   r0
366        ori     r0,r0,MSR_IR|MSR_DR|MSR_IP
367        mflr    r11
368        xori    r0,r0,MSR_IR|MSR_DR
369        mtsrr0  r11
370        mtsrr1  r0
371        rfi
372*/
373
374/* Due to the PPC architecture (and according to the specifications), a
375 * series of tlbie which goes through a whole 256 MB segment always flushes
376 * the whole TLB. This is obviously overkill and slow, but who cares ?
377 * It takes about 1 ms on a 200 MHz 603e and works even if residual data
378 * get the number of TLB entries wrong.
379 */
380flush_tlb:
381        lis     r11,0x1000
3821:      addic.  r11,r11,-0x1000
383        tlbie   r11
384        bnl     1b
385/* tlbsync is not implemented on 601, so use sync which seems to be a superset
386 * of tlbsync in all cases and do not bother with CPU dependant code
387 */
388        sync   
389        blr                                     
390
391        .globl  codemove
392codemove:
393        .type   codemove,@function
394/* r3 dest, r4 src, r5 length in bytes, r6 cachelinesize */
395        cmplw   cr1,r3,r4
396        addi    r0,r5,3
397        srwi.   r0,r0,2
398        beq     cr1,4f  /* In place copy is not necessary */
399        beq     7f      /* Protect against 0 count */
400        mtctr   r0
401        bge     cr1,2f
402       
403        la      r8,-4(r4)
404        la      r7,-4(r3)
4051:      lwzu    r0,4(r8)
406        stwu    r0,4(r7)       
407        bdnz    1b
408        b       4f
409
4102:      slwi    r0,r0,2
411        add     r8,r4,r0
412        add     r7,r3,r0
4133:      lwzu    r0,-4(r8)
414        stwu    r0,-4(r7)
415        bdnz    3b
416       
417/* Now flush the cache: note that we must start from a cache aligned
418 * address. Otherwise we might miss one cache line.
419 */
4204:      cmpwi   r6,0
421        add     r5,r3,r5
422        beq     7f      /* Always flush prefetch queue in any case */
423        subi    r0,r6,1
424        andc    r3,r3,r0
425        mr      r4,r3
4265:      cmplw   r4,r5   
427        dcbst   0,r4
428        add     r4,r4,r6
429        blt     5b
430        sync            /* Wait for all dcbst to complete on bus */
431        mr      r4,r3
4326:      cmplw   r4,r5   
433        icbi    0,r4
434        add     r4,r4,r6
435        blt     6b
4367:      sync            /* Wait for all icbi to complete on bus */
437        isync
438        blr
439        .size   codemove,.-codemove
440_size_codemove=.-codemove
441
442        .section        ".data" # .rodata
443        .align 2
444#ifdef TEST_PPCBUG_CALLS       
445banner_start:   
446        .ascii "This message was printed by PPCBug with MMU enabled"
447banner_end:     
448#endif
Note: See TracBrowser for help on using the repository browser.