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

4.104.114.84.95
Last change on this file since acc25ee was acc25ee, checked in by Joel Sherrill <joel.sherrill@…>, on 12/02/99 at 14:31:19

Merged of mcp750 and mvme2307 BSP by Eric Valette <valette@…>.
As part of this effort, the mpc750 libcpu code is now shared with the
ppc6xx.

  • Property mode set to 100644
File size: 8.4 KB
RevLine 
[acc25ee]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 "bootldr.h"
19#include <libcpu/cpu.h>
20#include <rtems/score/targopts.h>
21#include "asm.h"
22               
23#undef TEST_PPCBUG_CALLS       
24#define FRAME_SIZE 32
25#define LOCK_CACHES (HID0_DLOCK|HID0_ILOCK)
26#define INVL_CACHES (HID0_DCI|HID0_ICFI)
27#define ENBL_CACHES (HID0_DCE|HID0_ICE)
28
29#define USE_PPCBUG
30#undef  USE_PPCBUG
31
32#define MONITOR_ENTER                   \
33        mfmsr   r10             ;       \
34        ori     r10,r10,MSR_IP  ;       \
35        mtmsr   r10             ;       \
36        li      r10,0x63        ;       \
37        sc
38       
39        START_GOT
40        GOT_ENTRY(_GOT2_TABLE_)
41        GOT_ENTRY(_FIXUP_TABLE_)
42        GOT_ENTRY(.bss)
43        GOT_ENTRY(codemove)
44        GOT_ENTRY(0)
45        GOT_ENTRY(__bd)
46        GOT_ENTRY(moved)
47        GOT_ENTRY(_binary_rtems_gz_start)
48        GOT_ENTRY(_binary_initrd_gz_start)
49        GOT_ENTRY(_binary_initrd_gz_end)
50#ifdef TEST_PPCBUG_CALLS       
51        GOT_ENTRY(banner_start)
52        GOT_ENTRY(banner_end)
53#endif 
54        END_GOT
55        .globl  start
56        .type   start,@function
57/* Point the stack into the PreP partition header in the x86 reserved
58 * code area, so that simple C routines can be called.
59 */
60start: 
61#ifdef  USE_PPCBUG
62        MONITOR_ENTER   
63#endif
64        bl      1f
651:      mflr    r1
66        li      r0,0
67        stwu    r0,start-1b-0x400+0x1b0-FRAME_SIZE(r1)
68        stmw    r26,FRAME_SIZE-24(r1)
69        GET_GOT
70        mfmsr   r28             /* Turn off interrupts */
71        ori     r0,r28,MSR_EE
72        xori    r0,r0,MSR_EE
73        mtmsr   r0
74       
75/* Enable the caches, from now on cr2.eq set means processor is 601 */
76        mfpvr   r0
77        mfspr   r29,HID0
78        srwi    r0,r0,16
79        cmplwi  cr2,r0,1
80        beq     2,2f
81#ifndef USE_PPCBUG
82        ori     r0,r29,ENBL_CACHES|INVL_CACHES|LOCK_CACHES
83        xori    r0,r0,INVL_CACHES|LOCK_CACHES
84        sync
85        isync
86        mtspr   HID0,r0
87#endif
882:      bl      reloc
89       
90/* save all the parameters and the orginal msr/hid0/r31 */
91        lwz     bd,GOT(__bd)
92        stw     r3,0(bd)
93        stw     r4,4(bd)
94        stw     r5,8(bd)
95        stw     r6,12(bd)
96        lis     r3,__size@sectoff@ha
97        stw     r7,16(bd)
98        stw     r8,20(bd)
99        addi    r3,r3,__size@sectoff@l
100        stw     r9,24(bd)
101        stw     r10,28(bd)
102        stw     r28,o_msr(bd)
103        stw     r29,o_hid0(bd)
104        stw     r31,o_r31(bd)
105
106/* Call the routine to fill boot_data structure from residual data.
107 * And to find where the code has to be moved.
108 */
109        bl      early_setup
110
111/* Now we need to relocate ourselves, where we are told to. First put a
112 * copy of the codemove routine to some place in memory.
113 * (which may be where the 0x41 partition was loaded, so size is critical).
114 */
115        lwz     r4,GOT(codemove)
116        li      r5,_size_codemove
117        lwz     r3,mover(bd)
118        lwz     r6,cache_lsize(bd)
119        bl      codemove
120        mtctr   r3              # Where the temporary codemove is.
121        lwz     r3,image(bd)
122        lis     r5,_edata@sectoff@ha
123        lwz     r4,GOT(0)       # Our own address
124        addi    r5,r5,_edata@sectoff@l
125        lwz     r6,cache_lsize(bd)
126        lwz     r8,GOT(moved)
127        sub     r7,r3,r4        # Difference to adjust pointers.
128        add     r8,r8,r7
129        add     r30,r30,r7
130        add     bd,bd,r7
131/* Call the copy routine but return to the new area. */
132        mtlr    r8              # for the return address
133        bctr                    # returns to the moved instruction
134/* Establish the new top stack frame. */
135moved:  lwz     r1,stack(bd)
136        li      r0,0
137        stwu    r0,-16(r1)
138
139/* relocate again */
140        bl      reloc   
141/* Clear all of BSS */
142        lwz     r10,GOT(.bss)
143        li      r0,__bss_words@sectoff@l
144        subi    r10,r10,4
145        cmpwi   r0,0
146        mtctr   r0
147        li      r0,0
148        beq     4f
1493:      stwu    r0,4(r10)
150        bdnz    3b
151
152/* Final memory initialization. First switch to unmapped mode
153 * in case the FW had set the MMU on, and flush the TLB to avoid
154 * stale entries from interfering. No I/O access is allowed
155 * during this time!
156 */
157#ifndef USE_PPCBUG     
1584:      bl      MMUoff
159#endif 
160        bl      flush_tlb
161/* Some firmware versions leave stale values in the BATs, it's time
162 * to invalidate them to avoid interferences with our own mappings.
163 * But the 601 valid bit is in the BATL (IBAT only) and others are in
164 * the [ID]BATU. Bloat, bloat.. fortunately thrown away later.
165 */
166        li      r3,0
167        beq     cr2,5f
168        mtdbatu 0,r3
169        mtdbatu 1,r3
170        mtdbatu 2,r3
171        mtdbatu 3,r3
1725:      mtibatu 0,r3
173        mtibatl 0,r3
174        mtibatu 1,r3
175        mtibatl 1,r3
176        mtibatu 2,r3
177        mtibatl 2,r3
178        mtibatu 3,r3
179        mtibatl 3,r3
180        lis     r3,__size@sectoff@ha
181        addi    r3,r3,__size@sectoff@l
182        sync                            # We are going to touch SDR1 !
183        bl      mm_init
184        bl      MMUon
185       
186/* Now we are mapped and can perform I/O if we want */
187#ifdef TEST_PPCBUG_CALLS       
188/* Experience seems to show that PPCBug can only be called with the
189 * data cache disabled and with MMU disabled. Bummer.
190 */     
191        li      r10,0x22                # .OUTLN
192        lwz     r3,GOT(banner_start)
193        lwz     r4,GOT(banner_end)
194        sc
195#endif 
196        bl      setup_hw
197        lwz     r4,GOT(_binary_rtems_gz_start)
198        lis     r5,_rtems_gz_size@sectoff@ha
199        lwz     r6,GOT(_binary_initrd_gz_start)
200        lis     r3,_rtems_size@sectoff@ha
201        lwz     r7,GOT(_binary_initrd_gz_end)
202        addi    r5,r5,_rtems_gz_size@sectoff@l
203        addi    r3,r3,_rtems_size@sectoff@l
204        sub     r7,r7,r6
205        bl      decompress_kernel
206
207/* Back here we are unmapped and we start the kernel, passing up to eight
208 * parameters just in case, only r3 to r7 used for now. Flush the tlb so
209 * that the loaded image starts in a clean state.
210 */
211        bl      flush_tlb
212        lwz     r3,0(bd)
213        lwz     r4,4(bd)
214        lwz     r5,8(bd)
215        lwz     r6,12(bd)
216        lwz     r7,16(bd)
217        lwz     r8,20(bd)
218        lwz     r9,24(bd)
219        lwz     r10,28(bd)
220
221        lwz     r30,0(0)
222        mtctr   r30
223/*
224 *      Linux code again
225        lis     r30,0xdeadc0de@ha
226        addi    r30,r30,0xdeadc0de@l
227        stw     r30,0(0)
228        li      r30,0
229*/
230        dcbst   0,r30   /* Make sure it's in memory ! */
231/* We just flash invalidate and disable the dcache, unless it's a 601,
232 * critical areas have been flushed and we don't care about the stack
233 * and other scratch areas.
234 */
235        beq     cr2,1f
236        mfspr   r0,HID0
237        ori     r0,r0,HID0_DCI|HID0_DCE
238        sync
239        mtspr   HID0,r0
240        xori    r0,r0,HID0_DCI|HID0_DCE
241        mtspr   HID0,r0
242/* Provisional return to FW, works for PPCBug */
243#if 0
244        MONITOR_ENTER
245#else
2461:      bctr
247#endif
248               
249       
250
251/* relocation function, r30 must point to got2+0x8000 */
252reloc: 
253/* Adjust got2 pointers, no need to check for 0, this code already puts
254 * a few entries in the table.
255 */
256        li      r0,__got2_entries@sectoff@l
257        la      r12,GOT(_GOT2_TABLE_)
258        lwz     r11,GOT(_GOT2_TABLE_)
259        mtctr   r0
260        sub     r11,r12,r11
261        addi    r12,r12,-4
2621:      lwzu    r0,4(r12)
263        add     r0,r0,r11
264        stw     r0,0(r12)
265        bdnz    1b
266       
267/* Now adjust the fixups and the pointers to the fixups in case we need
268 * to move ourselves again.
269 */     
2702:      li      r0,__fixup_entries@sectoff@l
271        lwz     r12,GOT(_FIXUP_TABLE_)
272        cmpwi   r0,0
273        mtctr   r0
274        addi    r12,r12,-4
275        beqlr
2763:      lwzu    r10,4(r12)
277        lwzux   r0,r10,r11
278        add     r0,r0,r11
279        stw     r10,0(r12)
280        stw     r0,0(r10)
281        bdnz    3b
282        blr             
283
284/* Set the MMU on and off: code is always mapped 1:1 and does not need MMU,
285 * but it does not cost so much to map it also and it catches calls through
286 * NULL function pointers.
287 */
288        .globl  MMUon
289        .type   MMUon,@function
290MMUon:  mfmsr   r0
291        ori     r0,r0,MSR_IR|MSR_DR|MSR_IP
292        mflr    r11
293        xori    r0,r0,MSR_IP
294        mtsrr0  r11
295        mtsrr1  r0
296        rfi
297        .globl  MMUoff
298        .type   MMUoff,@function
299MMUoff: mfmsr   r0
300        ori     r0,r0,MSR_IR|MSR_DR|MSR_IP
301        mflr    r11
302        xori    r0,r0,MSR_IR|MSR_DR
303        mtsrr0  r11
304        mtsrr1  r0
305        rfi
306
307/* Due to the PPC architecture (and according to the specifications), a
308 * series of tlbie which goes through a whole 256 MB segment always flushes
309 * the whole TLB. This is obviously overkill and slow, but who cares ?
310 * It takes about 1 ms on a 200 MHz 603e and works even if residual data
311 * get the number of TLB entries wrong.
312 */
313flush_tlb:
314        lis     r11,0x1000
3151:      addic.  r11,r11,-0x1000
316        tlbie   r11
317        bnl     1b
318/* tlbsync is not implemented on 601, so use sync which seems to be a superset
319 * of tlbsync in all cases and do not bother with CPU dependant code
320 */
321        sync   
322        blr                                     
323
324        .globl  codemove
325codemove:
326        .type   codemove,@function
327/* r3 dest, r4 src, r5 length in bytes, r6 cachelinesize */
328        cmplw   cr1,r3,r4
329        addi    r0,r5,3
330        srwi.   r0,r0,2
331        beq     cr1,4f  /* In place copy is not necessary */
332        beq     7f      /* Protect against 0 count */
333        mtctr   r0
334        bge     cr1,2f
335       
336        la      r8,-4(r4)
337        la      r7,-4(r3)
3381:      lwzu    r0,4(r8)
339        stwu    r0,4(r7)       
340        bdnz    1b
341        b       4f
342
3432:      slwi    r0,r0,2
344        add     r8,r4,r0
345        add     r7,r3,r0
3463:      lwzu    r0,-4(r8)
347        stwu    r0,-4(r7)
348        bdnz    3b
349       
350/* Now flush the cache: note that we must start from a cache aligned
351 * address. Otherwise we might miss one cache line.
352 */
3534:      cmpwi   r6,0
354        add     r5,r3,r5
355        beq     7f      /* Always flush prefetch queue in any case */
356        subi    r0,r6,1
357        andc    r3,r3,r0
358        mr      r4,r3
3595:      cmplw   r4,r5   
360        dcbst   0,r4
361        add     r4,r4,r6
362        blt     5b
363        sync            /* Wait for all dcbst to complete on bus */
364        mr      r4,r3
3656:      cmplw   r4,r5   
366        icbi    0,r4
367        add     r4,r4,r6
368        blt     6b
3697:      sync            /* Wait for all icbi to complete on bus */
370        isync
371        blr
372        .size   codemove,.-codemove
373_size_codemove=.-codemove
374
375        .section        ".data" # .rodata
376        .align 2
377#ifdef TEST_PPCBUG_CALLS       
378banner_start:   
379        .ascii "This message was printed by PPCBug with MMU enabled"
380banner_end:     
381#endif
Note: See TracBrowser for help on using the repository browser.