ppc: Fix client stack setup
[openbios.git] / arch / ppc / qemu / start.S
blobc9955816255f20a29b7bc803099de30d70e2d9b0
1 /*
2  *   Creation Date: <2001/06/16 21:30:18 samuel>
3  *   Time-stamp: <2003/04/04 16:32:06 samuel>
4  *
5  *      <init.S>
6  *
7  *      Asm glue for ELF images
8  *
9  *   Copyright (C) 2001, 2002, 2003 Samuel Rydh (samuel@ibrium.se)
10  *
11  *   This program is free software; you can redistribute it and/or
12  *   modify it under the terms of the GNU General Public License
13  *   as published by the Free Software Foundation
14  *
15  */
17 #include "asm/asmdefs.h"
18 #include "asm/processor.h"
20 /************************************************************************/
21 /*      Macros                                                          */
22 /************************************************************************/
24 #define ILLEGAL_VECTOR( v )     .org __vectors + v ; bl trap_error ;
25 #define VECTOR( v, dummystr )   .org __vectors + v ; vector__##v
27 /* We're trying to use the same code for the ppc32 and ppc64 handlers here.
28  * On ppc32 we only save/restore the registers, C considers volatile.
29  *
30  * On ppc64 on the other hand, we have to save/restore all registers, because
31  * all OF code is 32 bits, which only saves/restores the low 32 bits of the
32  * registers it clobbers.
33  */
35 #define EXCEPTION_PREAMBLE_TEMPLATE \
36         mtsprg1 r1 ;                            /* scratch */ \
37         mfmsr   r1 ;                            /* unset MSR_SF */ \
38         clrlwi  r1,r1,0 ; \
39         mtmsr   r1 ; \
40         mfsprg0 r1 ;                            /* exception stack in sprg0 */ \
41 .ifc ULONG_SIZE, 8 ; \
42         addi    r1,r1,-(40 * ULONG_SIZE) ;      /* push exception frame */ \
43 .else ; \
44         addi    r1,r1,-(20 * ULONG_SIZE) ;      /* push exception frame */ \
45 .endif ; \
46  \
47         stl     r0,(0 * ULONG_SIZE)(r1) ;       /* save r0 */ \
48         mfsprg1 r0 ; \
49         stl     r0,(1 * ULONG_SIZE)(r1) ;       /* save r1 */ \
50         stl     r2,(2 * ULONG_SIZE)(r1) ;       /* save r2 */ \
51         stl     r3,(3 * ULONG_SIZE)(r1) ;       /* save r3 */ \
52         stl     r4,(4 * ULONG_SIZE)(r1) ; \
53         stl     r5,(5 * ULONG_SIZE)(r1) ; \
54         stl     r6,(6 * ULONG_SIZE)(r1) ; \
55         stl     r7,(7 * ULONG_SIZE)(r1) ; \
56         stl     r8,(8 * ULONG_SIZE)(r1) ; \
57         stl     r9,(9 * ULONG_SIZE)(r1) ; \
58         stl     r10,(10 * ULONG_SIZE)(r1) ; \
59         stl     r11,(11 * ULONG_SIZE)(r1) ; \
60         stl     r12,(12 * ULONG_SIZE)(r1) ; \
61 .ifc ULONG_SIZE, 8 ; \
62         stl     r13,(17 * ULONG_SIZE)(r1) ; \
63         stl     r14,(18 * ULONG_SIZE)(r1) ; \
64         stl     r15,(19 * ULONG_SIZE)(r1) ; \
65         stl     r16,(20 * ULONG_SIZE)(r1) ; \
66         stl     r17,(21 * ULONG_SIZE)(r1) ; \
67         stl     r18,(22 * ULONG_SIZE)(r1) ; \
68         stl     r19,(23 * ULONG_SIZE)(r1) ; \
69         stl     r20,(24 * ULONG_SIZE)(r1) ; \
70         stl     r21,(25 * ULONG_SIZE)(r1) ; \
71         stl     r22,(26 * ULONG_SIZE)(r1) ; \
72         stl     r23,(27 * ULONG_SIZE)(r1) ; \
73         stl     r24,(28 * ULONG_SIZE)(r1) ; \
74         stl     r25,(29 * ULONG_SIZE)(r1) ; \
75         stl     r26,(30 * ULONG_SIZE)(r1) ; \
76         stl     r27,(31 * ULONG_SIZE)(r1) ; \
77         stl     r28,(32 * ULONG_SIZE)(r1) ; \
78         stl     r29,(33 * ULONG_SIZE)(r1) ; \
79         stl     r30,(34 * ULONG_SIZE)(r1) ; \
80         stl     r31,(35 * ULONG_SIZE)(r1) ; \
81 .endif ; \
82  \
83         mflr    r0 ; \
84         stl     r0,(13 * ULONG_SIZE)(r1) ; \
85         mfcr    r0 ; \
86         stl     r0,(14 * ULONG_SIZE)(r1) ; \
87         mfctr   r0 ; \
88         stl     r0,(15 * ULONG_SIZE)(r1) ; \
89         mfxer   r0 ; \
90         stl     r0,(16 * ULONG_SIZE)(r1) ; \
91  \
92         /* 76(r1) unused */ \
93         addi    r1,r1,-16 ;     /* C ABI uses 0(r1) and 4(r1)... */
95 #define EXCEPTION_EPILOGUE_TEMPLATE \
96         addi    r1,r1,16 ;                      /* pop ABI frame */ \
98         ll      r0,(13 * ULONG_SIZE)(r1) ; \
99         mtlr    r0 ; \
100         ll      r0,(14 * ULONG_SIZE)(r1) ; \
101         mtcr    r0 ; \
102         ll      r0,(15 * ULONG_SIZE)(r1) ; \
103         mtctr   r0 ; \
104         ll      r0,(16 * ULONG_SIZE)(r1) ; \
105         mtxer   r0 ; \
107         ll      r0,(0 * ULONG_SIZE)(r1) ; \
108         ll      r2,(2 * ULONG_SIZE)(r1) ; \
109         ll      r3,(3 * ULONG_SIZE)(r1) ; \
110         ll      r4,(4 * ULONG_SIZE)(r1) ; \
111         ll      r5,(5 * ULONG_SIZE)(r1) ; \
112         ll      r6,(6 * ULONG_SIZE)(r1) ; \
113         ll      r7,(7 * ULONG_SIZE)(r1) ; \
114         ll      r8,(8 * ULONG_SIZE)(r1) ; \
115         ll      r9,(9 * ULONG_SIZE)(r1) ; \
116         ll      r10,(10 * ULONG_SIZE)(r1) ; \
117         ll      r11,(11 * ULONG_SIZE)(r1) ; \
118         ll      r12,(12 * ULONG_SIZE)(r1) ; \
119 .ifc ULONG_SIZE, 8 ; \
120         ll      r13,(17 * ULONG_SIZE)(r1) ; \
121         ll      r14,(18 * ULONG_SIZE)(r1) ; \
122         ll      r15,(19 * ULONG_SIZE)(r1) ; \
123         ll      r16,(20 * ULONG_SIZE)(r1) ; \
124         ll      r17,(21 * ULONG_SIZE)(r1) ; \
125         ll      r18,(22 * ULONG_SIZE)(r1) ; \
126         ll      r19,(23 * ULONG_SIZE)(r1) ; \
127         ll      r20,(24 * ULONG_SIZE)(r1) ; \
128         ll      r21,(25 * ULONG_SIZE)(r1) ; \
129         ll      r22,(26 * ULONG_SIZE)(r1) ; \
130         ll      r23,(27 * ULONG_SIZE)(r1) ; \
131         ll      r24,(28 * ULONG_SIZE)(r1) ; \
132         ll      r25,(29 * ULONG_SIZE)(r1) ; \
133         ll      r26,(30 * ULONG_SIZE)(r1) ; \
134         ll      r27,(31 * ULONG_SIZE)(r1) ; \
135         ll      r28,(32 * ULONG_SIZE)(r1) ; \
136         ll      r29,(33 * ULONG_SIZE)(r1) ; \
137         ll      r30,(34 * ULONG_SIZE)(r1) ; \
138         ll      r31,(35 * ULONG_SIZE)(r1) ; \
139 .endif ; \
140         ll      r1,(1 * ULONG_SIZE)(r1) ;       /* restore stack at last */ \
141         rfi
143 // PPC32
145 #define ULONG_SIZE              4
146 #define stl                     stw
147 #define ll                      lwz
149 .macro EXCEPTION_PREAMBLE
150         EXCEPTION_PREAMBLE_TEMPLATE
151 .endm
153 .macro EXCEPTION_EPILOGUE
154         EXCEPTION_EPILOGUE_TEMPLATE
155 .endm
157 #undef ULONG_SIZE
158 #undef stl
159 #undef ll
161 // PPC64
163 #define ULONG_SIZE              8
164 #define stl                     std
165 #define ll                      ld
167 .macro EXCEPTION_PREAMBLE_64
168         EXCEPTION_PREAMBLE_TEMPLATE
169 .endm
171 .macro EXCEPTION_EPILOGUE_64
172         EXCEPTION_EPILOGUE_TEMPLATE
173 .endm
175 #undef ULONG_SIZE
176 #undef stl
177 #undef ll
179 /************************************************************************/
180 /*      vectors                                                         */
181 /************************************************************************/
183         .section .text.vectors, "ax"
184 GLOBL(__vectors):
185         nop                     // NULL-jmp trap
186 1:      nop                     //
187         b       1b
189 exception_return:
190         EXCEPTION_EPILOGUE
192         .globl  __divide_error
193 __divide_error:
194 trap_error:
195         mflr    r3
196         b       unexpected_excep
198 VECTOR( 0x100, "SRE" ):
199         b       _entry
201 ILLEGAL_VECTOR( 0x200 )
203 VECTOR( 0x300, "DSI" ):
204         EXCEPTION_PREAMBLE
205         lis     r3,HA(dsi_exception)
206         addi    r3,r3,LO(dsi_exception)
207         mtctr   r3
208         bctrl
209         ba      exception_return
211 VECTOR( 0x400, "ISI" ):
212         EXCEPTION_PREAMBLE
213         lis     r3,HA(isi_exception)
214         addi    r3,r3,LO(isi_exception)
215         mtctr   r3
216         bctrl
217         ba      exception_return
219         ILLEGAL_VECTOR( 0x500 )
220         ILLEGAL_VECTOR( 0x600 )
221         ILLEGAL_VECTOR( 0x700 )
223 VECTOR( 0x800, "FPU" ):
224         mtsprg1 r3
225         mfsrr1  r3
226         ori     r3,r3,0x2000
227         mtsrr1  r3
228         mfsprg1 r3
229         rfi
231 ILLEGAL_VECTOR( 0x900 )
232 ILLEGAL_VECTOR( 0xa00 )
233 ILLEGAL_VECTOR( 0xb00 )
234 ILLEGAL_VECTOR( 0xc00 )
235 ILLEGAL_VECTOR( 0xd00 )
236 ILLEGAL_VECTOR( 0xe00 )
237 ILLEGAL_VECTOR( 0xf00 )
238 ILLEGAL_VECTOR( 0xf20 )
239 ILLEGAL_VECTOR( 0x1000 )
240 ILLEGAL_VECTOR( 0x1100 )
241 ILLEGAL_VECTOR( 0x1200 )
242 ILLEGAL_VECTOR( 0x1300 )
243 ILLEGAL_VECTOR( 0x1400 )
244 ILLEGAL_VECTOR( 0x1500 )
245 ILLEGAL_VECTOR( 0x1600 )
246 ILLEGAL_VECTOR( 0x1700 )
248 VECTOR( 0x2000, "DSI_64" ):
249         EXCEPTION_PREAMBLE_64
250         lis     r3,HA(dsi_exception)
251         addi    r3,r3,LO(dsi_exception)
252         mtctr   r3
253         bctrl
254         EXCEPTION_EPILOGUE_64
256 VECTOR( 0x2200, "ISI_64" ):
257         EXCEPTION_PREAMBLE_64
258         lis     r3,HA(isi_exception)
259         addi    r3,r3,LO(isi_exception)
260         mtctr   r3
261         bctrl
262         EXCEPTION_EPILOGUE_64
264 GLOBL(__vectors_end):
266 /************************************************************************/
267 /*      entry                                                           */
268 /************************************************************************/
270 GLOBL(_entry):
271         /* clear MSR, disable MMU */
273         li      r0,0
274         mtmsr   r0
276         /* copy exception vectors */
278         lis     r3,HA(__vectors)
279         addi    r3,r3,LO(__vectors)
280         li      r4,0
281         li      r5,__vectors_end - __vectors + 16
282         rlwinm  r5,r5,0,0,28
283 1:      lwz     r6,0(r3)
284         lwz     r7,4(r3)
285         lwz     r8,8(r3)
286         lwz     r9,12(r3)
287         stw     r6,0(r4)
288         stw     r7,4(r4)
289         stw     r8,8(r4)
290         stw     r9,12(r4)
291         dcbst   0,r4
292         sync
293         icbi    0,r4
294         sync
295         addi    r5,r5,-16
296         addi    r3,r3,16
297         addi    r4,r4,16
298         cmpwi   r5,0
299         bgt     1b
300         isync
302         bl compute_ramsize
304         /* Memory map:
305          *
306          * Top +-------------------------+
307          *     |                         |
308          *     | ROM into RAM (1 MB)     |
309          *     |                         |
310          *     +-------------------------+
311          *     |                         |
312          *     | MMU Hash Table (64 kB)  |
313          *     |                         |
314          *     +-------------------------+
315          *     |                         |
316          *     | Exception Stack (32 kB) |
317          *     |                         |
318          *     +-------------------------+
319          *     |                         |
320          *     | Stack (64 kB)           |
321          *     |                         |
322          *     +-------------------------+
323          *     |                         |
324          *     | Client Stack (64 kB)    |
325          *     |                         |
326          *     +-------------------------+
327          *     |                         |
328          *     | Malloc Zone (2 MiB)     |
329          *     |                         |
330          *     +-------------------------+
331          *     :                         :
332          * Bottom
333          */
335         addis   r1, r3, -16             /* ramsize - 1MB */
337         /* setup hash table */
339         addis   r1, r1, -1              /* - 64 kB */
340         clrrwi  r1, r1, 5*4             /* & ~0xfffff */
342         /* setup exception stack */
344         mtsprg0 r1
346         /* setup stack */
348         addi    r1, r1, -32768          /* - 32 kB */
350         /* save memory size in stack */
352         bl      setup_mmu
353         bl      entry
354 1:      nop
355         b       1b
358         /* According to IEEE 1275, PPC bindings:
359          *
360          *      MSR = FP, ME + (DR|IR)
361          *      r1 = stack (32 K + 32 bytes link area above)
362          *      r5 = client interface handler
363          *      r6 = address of client program arguments (unused)
364          *      r7 = length of client program arguments (unused)
365          *
366          *      Yaboot and Linux use r3 and r4 for initrd address and size
367          */
368         .data
369 saved_stack:
370         .long   0
371         .previous
372         /* void call_elf( arg1, arg2, entry ) */
373 GLOBL(call_elf):
374         mflr    r0
375         stwu    r1,-16(r1)
376         stw     r0,20(r1)
377         mtlr    r5
378         lis     r8,HA(saved_stack)
379         addi    r8,r8,LO(saved_stack)           // save our stack pointer
380         stw     r1,0(r8)
381         mfsdr1  r1
382         addi    r1, r1, -32768          /* - 32 KiB exception stack */
383         addis   r1, r1, -1                      /* - 64 KiB stack */
384         lis     r5,HA(of_client_callback)
385         addi    r5,r5,LO(of_client_callback)    // r5 = callback
386         li      r6,0                    // r6 = address of client program arguments (unused)
387         li      r7,0                    // r7 = length of client program arguments (unused)
388         li      r0,MSR_FP | MSR_ME | MSR_DR | MSR_IR
389         mtmsr   r0
390         blrl
392         lis     r8,HA(saved_stack)
393         addi    r8,r8,LO(saved_stack)           // restore stack pointer
394         mr      r1,r8
395         lwz     r0,20(r1)
396         mtlr    r0
397         addi    r1,r1,16
398         // XXX: should restore r12-r31 etc..
399         // we should not really come here though
400         blr
402 #define SAVE_SPACE 140
403 GLOBL(of_client_callback):
405         stwu    r1, -12(r1)
407         /* save r4 */
409         stw     r4, 8(r1)
411         /* save lr */
413         mflr    r4
414         stw     r4, 4(r1)
416         /* restore OF stack */
418         lis     r4,HA(saved_stack)
419         addi    r4,r4,LO(saved_stack)
420         lwz     r4,0(r4)
422         stwu    r4,-SAVE_SPACE(r4)
423         stw     r1,8(r4)                // save caller stack
424         mr      r1,r4
426         stw     r2,12(r1)
427         stw     r0,16(r1)
429         /* save ctr, cr and xer */
431         mfctr   r2
432         stw     r2,20(r1)
433         mfcr    r2
434         stw     r2,24(r1)
435         mfxer   r2
436         stw     r2,28(r1)
438         /* save r5 - r31 */
440         stw     r5, 32(r1)
441         stw     r6,36(r1)
442         stw     r7,40(r1)
443         stw     r8,44(r1)
444         stw     r9,48(r1)
445         stw     r10,52(r1)
446         stw     r11,56(r1)
447         stw     r12,60(r1)
448         stw     r13,64(r1)
449         stw     r14,68(r1)
450         stw     r15,72(r1)
451         stw     r16,76(r1)
452         stw     r17,80(r1)
453         stw     r18,84(r1)
454         stw     r19,88(r1)
455         stw     r20,92(r1)
456         stw     r21,96(r1)
457         stw     r22,100(r1)
458         stw     r23,104(r1)
459         stw     r24,108(r1)
460         stw     r25,112(r1)
461         stw     r26,116(r1)
462         stw     r27,120(r1)
463         stw     r28,124(r1)
464         stw     r29,128(r1)
465         stw     r30,132(r1)
466         stw     r31,136(r1)
468         bl      of_client_interface
470         /* restore r5 - r31 */
472         lwz     r5,32(r1)
473         lwz     r6,36(r1)
474         lwz     r7,40(r1)
475         lwz     r8,44(r1)
476         lwz     r9,48(r1)
477         lwz     r10,52(r1)
478         lwz     r11,56(r1)
479         lwz     r12,60(r1)
480         lwz     r13,64(r1)
481         lwz     r14,68(r1)
482         lwz     r15,72(r1)
483         lwz     r16,76(r1)
484         lwz     r17,80(r1)
485         lwz     r18,84(r1)
486         lwz     r19,88(r1)
487         lwz     r20,92(r1)
488         lwz     r21,96(r1)
489         lwz     r22,100(r1)
490         lwz     r23,104(r1)
491         lwz     r24,108(r1)
492         lwz     r25,112(r1)
493         lwz     r26,116(r1)
494         lwz     r27,120(r1)
495         lwz     r28,124(r1)
496         lwz     r29,128(r1)
497         lwz     r30,132(r1)
498         lwz     r31,136(r1)
500         /* restore ctr, cr and xer */
502         lwz     r2,20(r1)
503         mtctr   r2
504         lwz     r2,24(r1)
505         mtcr    r2
506         lwz     r2,28(r1)
507         mtxer   r2
509         /* restore r0 and r2 */
511         lwz     r2,12(r1)
512         lwz     r0,16(r1)
514         /* restore caller stack */
516         lwz     r1,8(r1)
518         lwz     r4, 4(r1)
519         mtlr    r4
520         lwz     r4, 8(r1)
521         lwz     r1, 0(r1)
523         blr
525         /* rtas glue (must be reloctable) */
526 GLOBL(of_rtas_start):
527         /* r3 = argument buffer, r4 = of_rtas_start */
528         /* according to the CHRP standard, cr must be preserved (cr0/cr1 too?) */
529         blr
530 GLOBL(of_rtas_end):
533 #define CACHE_LINE_SIZE         32
534 #define LG_CACHE_LINE_SIZE      5
536 /* flush_icache_range( unsigned long start, unsigned long stop) */
537 GLOBL(flush_icache_range):
538         li      r5,CACHE_LINE_SIZE-1
539         andc    r3,r3,r5
540         subf    r4,r3,r4
541         add     r4,r4,r5
542         srwi.   r4,r4,LG_CACHE_LINE_SIZE
543         beqlr
544         mtctr   r4
545         mr      r6,r3
546 1:      dcbst   0,r3
547         addi    r3,r3,CACHE_LINE_SIZE
548         bdnz    1b
549         sync                            /* wait for dcbst's to get to ram */
550         mtctr   r4
551 2:      icbi    0,r6
552         addi    r6,r6,CACHE_LINE_SIZE
553         bdnz    2b
554         sync                            /* additional sync needed on g4 */
555         isync
556         blr
558         /* Get RAM size from Qemu configuration device */
560 #define CFG_ADDR 0xf0000510
561 #define FW_CFG_RAM_SIZE         0x03
563 compute_ramsize:
564         lis     r9,HA(CFG_ADDR)
565         ori     r9,r9,LO(CFG_ADDR)
566         li      r0,FW_CFG_RAM_SIZE
567         sth     r0,0(r9)
568         lis     r9,HA(CFG_ADDR + 2)
569         ori     r9,r9,LO(CFG_ADDR + 2)
570         lbz     r1,0(r9)
571         lbz     r0,0(r9)
572         slwi    r0,r0,8
573         or      r1,r1,r0
574         lbz     r0,0(r9)
575         slwi    r0,r0,16
576         or      r1,r1,r0
577         lbz     r0,0(r9)
578         slwi    r0,r0,24
579         or      r3,r1,r0
580         blr
582         /* Hard reset vector */
583         .section .romentry,"ax"
584         bl      _entry