Add qemu 2.4.0
[kvmfornfv.git] / qemu / roms / openbios / arch / sparc32 / entry.S
1 /**
2  ** Standalone startup code for Linux PROM emulator.
3  ** Copyright 1999 Pete A. Zaitcev
4  ** This code is licensed under GNU General Public License.
5  **/
6 /*
7  * $Id: head.S,v 1.12 2002/07/23 05:47:09 zaitcev Exp $
8  */
9
10 #define __ASSEMBLY
11 #include "psr.h"
12 #include "asm/asi.h"
13 #include "asm/crs.h"
14 #define NO_QEMU_PROTOS
15 #define NO_OPENBIOS_PROTOS
16 #include "arch/common/fw_cfg.h"
17
18 #define CFG_ADDR 0x00000510
19 #define CFG_ASI  0x2d
20
21 #define PHYS_JJ_INTR0   0x71E00000  /* CPU0 interrupt control registers */
22
23 #define PHYS_SS10_INTR0         0xf1400000
24
25 #define PHYS_SS2_INTR0  0xf5000000
26 #define SER_ADDR2       0xf1000004
27
28 #define PHYS_SS1000_SBI         0x02800000
29 #define SER_ADDR1000            0x00200004
30
31 #define WRITE_PAUSE    nop; nop; nop; /* Have to do this after %wim/%psr chg */
32
33         .globl  entry, _entry
34
35         .section ".text", "ax"
36         .align  8
37
38         /* Memory map:
39          *
40          * Top +-------------------------+
41          *     | SMP CPU table           |
42          *     | s + 0x1f00 ... 0x1f0f   |
43          *     | s + 0x1f0c valid        |
44          *     | s + 0x1f08 entry        |
45          *     | s + 0x1f04 ctxtbl       |
46          *     | s + 0x1f00 ctx          |
47          *     +-------------------------+
48          *     | Bootstrap               |
49          *     | MMU L3 tables 8 * 0x100 |
50          *     | s + 0xa00 ... 0x11ff    |
51          *     +-------------------------+
52          *     | Bootstrap               |
53          *     | MMU L2 tables 2 * 0x100 |
54          *     | s + 0x800 ... 0x9ff     |
55          *     +-------------------------+
56          *     | Bootstrap               |
57          *     | MMU L1 table 0x400      |
58          *     | s + 0x400 ... 0x7ff     |
59          *     +-------------------------+
60          *     | Bootstrap               |
61          *     | MMU L0/ctx table 0x400  |
62          *     | s + 0x000 ... 0x3ff     |
63          *     +-------------------------+
64          *     |                         |
65          *     | ROM into RAM            |
66          *     |                         |
67          *     +-------------------------+
68          *     :                         :
69          * Bottom
70          */
71
72 /*
73  * Entry point
74  * We start execution from here.
75  */
76 _entry:
77 entry:
78         /* Switch to our main context.
79          * Main context is statically defined in C.
80          */
81
82         ! Check signature "QEMU"
83         set     CFG_ADDR, %g5
84         mov     FW_CFG_SIGNATURE, %g2
85         stha    %g2, [%g5] CFG_ASI
86         add     %g5, 2, %g5
87         lduba   [%g5] CFG_ASI, %g2
88         cmp     %g2, 'Q'
89         bne     bad_conf
90          nop
91         lduba   [%g5] CFG_ASI, %g2
92         cmp     %g2, 'E'
93         bne     bad_conf
94          nop
95         lduba   [%g5] CFG_ASI, %g2
96         cmp     %g2, 'M'
97         bne     bad_conf
98          nop
99         lduba   [%g5] CFG_ASI, %g2
100         cmp     %g2, 'U'
101         bne     bad_conf
102          nop
103
104         ! Get memory size from configuration device
105         ! NB: little endian format
106         mov     FW_CFG_RAM_SIZE, %g2
107         sub     %g5, 2, %g5
108         stha    %g2, [%g5] CFG_ASI
109         add     %g5, 2, %g5
110         lduba   [%g5] CFG_ASI, %g4
111
112         lduba   [%g5] CFG_ASI, %g3
113         sll     %g3, 8, %g3
114         or      %g3, %g4, %g4
115
116         lduba   [%g5] CFG_ASI, %g3
117         sll     %g3, 16, %g3
118         or      %g3, %g4, %g4
119
120         lduba   [%g5] CFG_ASI, %g3
121         sll     %g3, 24, %g3
122         or      %g3, %g4, %g1
123         ! %g1 contains end of memory
124
125         ! Get kernel address from configuration device
126         ! NB: little endian format
127         mov     FW_CFG_KERNEL_ADDR, %g2
128         sub     %g5, 2, %g5
129         stha    %g2, [%g5] CFG_ASI
130         add     %g5, 2, %g5
131         lduba   [%g5] CFG_ASI, %g4
132
133         lduba   [%g5] CFG_ASI, %g3
134         sll     %g3, 8, %g3
135         or      %g3, %g4, %g4
136
137         lduba   [%g5] CFG_ASI, %g3
138         sll     %g3, 16, %g3
139         or      %g3, %g4, %g4
140
141         lduba   [%g5] CFG_ASI, %g3
142         sll     %g3, 24, %g3
143         or      %g3, %g4, %g4
144
145         ! If kernel address is set, don't clear from base of RAM in order to
146         ! leave the kernel image intact
147         mov     0, %g6
148         cmp     %g4, 0
149         beq     clear_mem
150          nop
151
152         ! Start from 16M
153         set     0x1000000, %g6
154
155 clear_mem:
156         sta     %g0, [%g6] ASI_M_BYPASS
157         add     %g6, 0x4, %g6
158         cmp     %g6, %g1
159         bl      clear_mem
160          nop
161
162 clear_done:
163         ! Start of private memory in %g6
164         set     0x2000, %g3
165         sub     %g1, %g3, %g6
166
167         ! Check if this is the boot CPU and skip SMP table check if yes
168         ! XXX: not all CPUs should have MXCC
169         set     0x1c00f00, %g2
170         ldda    [%g2] ASI_CONTROL, %g2
171         srl     %g3, 24, %g7
172         sub     %g7, 8, %g7
173         tst     %g7
174         bz      skip_table
175          nop
176
177         ! Calculate SMP table location
178         set     0x1f0c, %g2
179         add     %g6, %g2, %g2                 ! valid?
180         lda     [%g2] ASI_M_BYPASS, %g7
181         sta     %g0, [%g2] ASI_M_BYPASS
182
183 skip_table:
184         ! Get machine ID from configuration device
185         mov     FW_CFG_MACHINE_ID, %g2
186         sub     %g5, 2, %g5
187         stha    %g2, [%g5] CFG_ASI
188         add     %g5, 2, %g5
189         lduba   [%g5] CFG_ASI, %g4
190
191         lduba   [%g5] CFG_ASI, %g3
192         sll     %g3, 8, %g3
193         or      %g3, %g4, %g4
194         mov     %g4, %y
195
196         cmp     %g4, 96
197         bgeu    ss1000
198          cmp    %g4, 64
199         bgeu    ss10
200          cmp    %g4, 32
201         blu     ss2
202          nop
203
204         ! Ok, this is SS-5
205
206         tst     %g7
207         bz      first_cpu
208          nop
209
210         ! Clear softints used for SMP CPU startup
211         set     PHYS_JJ_INTR0 + 0x04, %g1
212         sll     %g2, 12, %g2
213         add     %g1, %g2, %g2
214         set     0xffffffff, %g1
215         sta     %g1, [%g2] ASI_M_BYPASS         ! clear softints
216         add     %g2, 4, %g2
217         sta     %g0, [%g2] ASI_M_BYPASS         ! clear softints
218
219 load_ctx:
220         ! SMP init, jump to user specified address
221         set     0x1f04, %g5
222         add     %g6, %g5, %g5                 ! ctxtbl
223         lda     [%g5] ASI_M_BYPASS, %g2
224         sta     %g0, [%g5] ASI_M_BYPASS
225         set     AC_M_CTPR, %g1
226         sta     %g2, [%g1] ASI_M_MMUREGS        ! set ctx table ptr
227         set     0x1f00, %g5
228         add     %g6, %g5, %g5                 ! ctx
229         lda     [%g5] ASI_M_BYPASS, %g2
230         sta     %g0, [%g5] ASI_M_BYPASS
231         set     AC_M_CXR, %g1
232         sta     %g2, [%g1] ASI_M_MMUREGS        ! set context
233         set     0x1f08, %g5
234         add     %g6, %g5, %g5                 ! entry
235         lda     [%g5] ASI_M_BYPASS, %g2
236         sta     %g0, [%g5] ASI_M_BYPASS
237         set     1, %g1
238         jmp     %g2                             ! jump to kernel
239          sta    %g1, [%g0] ASI_M_MMUREGS        ! enable mmu
240
241 ss10:
242         ! Ok, this is SS-10 or SS-600MP
243         tst     %g7
244         bz      first_cpu
245          nop
246
247         ! Clear softints used for SMP CPU startup
248         set     PHYS_SS10_INTR0 + 0x04, %g1
249         sll     %g2, 12, %g2
250         add     %g1, %g2, %g2
251         set     0xffffffff, %g1
252         sta     %g1, [%g2] ASI_M_CTL            ! clear softints
253         add     %g2, 4, %g2
254         b       load_ctx
255          sta    %g0, [%g2] ASI_M_CTL            ! clear softints
256
257 ss2:
258         ! Ok, this is SS-2
259         set     ss2_error, %o2
260         b       ss2_ss1000_halt
261          nop
262
263 ss1000:
264         ! Ok, this is SS-1000 or SS-2000
265         set     ss1000_error, %o2
266         b       ss2_ss1000_halt
267          nop
268
269 first_cpu:
270         /* Create temporary page tables and map the ROM area to end of
271         RAM. This will be done properly in iommu.c later. */
272         ! Calculate start of page tables etc. to %g6
273         set     0x2000, %g4
274         sub     %g1, %g4, %g6                   ! start of private memory
275
276         mov     %g6, %g2                        ! ctx table at s+0x0
277         add     %g2, 0x400, %g3                 ! l1 table at s+0x400
278         srl     %g3, 0x4, %g3
279         or      %g3, 0x1, %g3
280         sta     %g3, [%g2] ASI_M_BYPASS
281         add     %g2, 0x400, %g2                 ! s+0x400
282         add     %g2, 0x400, %g3                 ! l2 table for ram (00xxxxxx) at s+0x800
283         srl     %g3, 0x4, %g3
284         or      %g3, 0x1, %g3
285         sta     %g3, [%g2] ASI_M_BYPASS
286         add     %g2, 0x500, %g3                 ! l2 table for rom (ffxxxxxx) at s+0x900
287         add     %g2, 0x3fc, %g2                 ! s+0x7fc
288         srl     %g3, 0x4, %g3
289         or      %g3, 0x1, %g3
290         sta     %g3, [%g2] ASI_M_BYPASS
291         add     %g2, 0x4, %g2                   ! s+0x800
292 #if 0
293         set     0x40, %g6
294         set     ((7 << 2) | 2), %g3             ! 7 = U: --- S: RWX (main memory)
295 1:      sta     %g3, [%g2] ASI_M_BYPASS
296         add     %g2, 4, %g2
297         deccc   %g6
298         bne     1b
299          nop
300 #else
301         add     %g2, 0x100, %g2
302 #endif
303                                                 ! s+0x900
304         add     %g2, 0xa00 - 0x900, %g3         ! l3 table for rom at s+0xa00
305         add     %g2, 0x0d0, %g2                 ! s+0x9d0
306         srl     %g3, 0x4, %g3
307         or      %g3, 0x1, %g3
308         sta     %g3, [%g2] ASI_M_BYPASS
309         add     %g2, 4, %g2                     ! s+0x9d4
310         add     %g2, 0xb00 - 0x9d4, %g3         ! 2nd l3 table for rom at s+0xb00
311         srl     %g3, 0x4, %g3
312         or      %g3, 0x1, %g3
313         sta     %g3, [%g2] ASI_M_BYPASS
314         add     %g2, 4, %g2                     ! s+0x9d8
315         add     %g2, 0xc00 - 0x9d8, %g3         ! 3rd l3 table for rom at s+0xc00
316         srl     %g3, 0x4, %g3
317         or      %g3, 0x1, %g3
318         sta     %g3, [%g2] ASI_M_BYPASS
319         add     %g2, 4, %g2                     ! s+0x9dc
320         add     %g2, 0xd00 - 0x9dc, %g3         ! 4th l3 table for rom at s+0xd00
321         srl     %g3, 0x4, %g3
322         or      %g3, 0x1, %g3
323         sta     %g3, [%g2] ASI_M_BYPASS
324         add     %g2, 4, %g2                     ! s+0x9e0
325         add     %g2, 0xe00 - 0x9e0, %g3         ! 5th l3 table for rom at s+0xe00
326         srl     %g3, 0x4, %g3
327         or      %g3, 0x1, %g3
328         sta     %g3, [%g2] ASI_M_BYPASS
329         add     %g2, 4, %g2                     ! s+0x9e4
330         add     %g2, 0xf00 - 0x9e4, %g3         ! 6th l3 table for rom at s+0xf00
331         srl     %g3, 0x4, %g3
332         or      %g3, 0x1, %g3
333         sta     %g3, [%g2] ASI_M_BYPASS
334         add     %g2, 4, %g2                     ! s+0x9e8
335         add     %g2, 0x1000 - 0x9e8, %g3        ! 7th l3 table for rom at s+0x1000
336         srl     %g3, 0x4, %g3
337         or      %g3, 0x1, %g3
338         sta     %g3, [%g2] ASI_M_BYPASS
339         add     %g2, 4, %g2                     ! s+0x9ec
340         add     %g2, 0x1100 - 0x9ec, %g3        ! 8th l3 table for rom at s+0x1100
341         srl     %g3, 0x4, %g3
342         or      %g3, 0x1, %g3
343         sta     %g3, [%g2] ASI_M_BYPASS
344       add       %g2, 0xa00-0x9ec, %g2           ! s+0xa00
345
346         /* Use end of ram for code, rodata, data, and bss
347         sections. SunOS wants to write to trap table... */
348         set     _end, %g6
349         set     _start, %g4
350         sub     %g6, %g4, %g6
351         sub     %g1, %g6, %g3
352         set     0x1000, %g5
353         sub     %g3, %g5, %g3
354         sub     %g3, %g5, %g3                   ! start of ROM copy
355         mov     %g3, %g7                        ! save in %g7
356         srl     %g6, 12, %g6                    ! # of all pages
357 1:      srl     %g3, 0x4, %g4
358         or      %g4, ((7 << 2) | 2), %g4        ! 7 = U: --- S: RWX
359         sta     %g4, [%g2] ASI_M_BYPASS
360         add     %g2, 4, %g2
361         add     %g3, %g5, %g3
362         deccc   %g6
363         bne     1b
364          nop
365
366         mov     %g1, %g6                        ! %g6 = memory size
367
368         /* Copy the code, rodata and data sections from ROM. */
369         sub     %g7, 4, %g3
370         set     _start - 4, %g4                 ! First address of TEXT - 4
371         set     _bss, %g5                       ! Last address of DATA
372         ba      2f
373          nop
374 1:
375         lda     [%g4] ASI_M_KERNELTXT, %g1
376         sta     %g1, [%g3] ASI_M_BYPASS
377 2:
378         cmp     %g4, %g5
379         add     %g3, 0x4, %g3
380         bl      1b
381          add    %g4, 0x4, %g4
382
383         set     0x2000, %g3
384         sub     %g6, %g3, %g7                   ! ctx table at s+0x0
385         set     AC_M_CTPR, %g2
386         srl     %g7, 4, %g7
387         sta     %g7, [%g2] ASI_M_MMUREGS        ! set ctx table ptr
388         set     AC_M_CXR, %g2
389         sta     %g0, [%g2] ASI_M_MMUREGS        ! context 0
390         set     highmem, %g2
391         set     1, %g1
392         jmp     %g2
393          sta    %g1, [%g0] ASI_M_MMUREGS        ! enable mmu
394 highmem:
395         /*
396          * The code which enables traps is a simplified version of
397          * kernel head.S.
398          *
399          * We know number of windows as 8 so we do not calculate them.
400          * The deadwood is here for any case.
401          */
402
403         /* Turn on Supervisor, EnableFloating, and all the PIL bits.
404          * Also puts us in register window zero with traps off.
405          */
406         set     (PSR_PS | PSR_S | PSR_PIL | PSR_EF), %g2
407         wr      %g2, 0x0, %psr
408         WRITE_PAUSE
409
410         /* Zero out our BSS section. */
411         set     _bss - 4, %o0           ! First address of BSS
412         set     _estack - 4, %o1        ! Last address of BSS
413         ba      2f
414          nop
415 1:
416         st      %g0, [%o0]
417 2:
418         subcc   %o0, %o1, %g0
419         bl      1b
420          add    %o0, 0x4, %o0
421
422         set     trap_table, %g1
423         wr      %g1, 0x0, %tbr
424
425         set     qemu_mem_size, %g1
426         st      %g6, [%g1]
427
428         set     _end, %o0                       ! Store va->pa conversion factor
429         set     _start, %o2
430         sub     %o0, %o2, %o0
431         sub     %g6, %o0, %o0
432         set     0x2000, %o1
433         sub     %o0, %o1, %o0                   ! start of ROM copy
434         sub     %o2, %o0, %o0                   ! start of ROM copy
435         set     va_shift, %g1
436         st      %o0, [%g1]
437
438         set     qemu_machine_type, %g1
439         mov     %y, %g2
440         st      %g2, [%g1]
441
442         /* Compute NWINDOWS and stash it away. Now uses %wim trick explained
443          * in the V8 manual. Ok, this method seems to work, Sparc is cool...
444          * No, it doesn't work, have to play the save/readCWP/restore trick.
445          */
446
447         wr      %g0, 0x0, %wim                  ! so we do not get a trap
448         WRITE_PAUSE
449
450         save
451
452         rd      %psr, %g3
453
454         restore
455
456         and     %g3, 0x1f, %g3
457         add     %g3, 0x1, %g3
458
459         mov     2, %g1
460         wr      %g1, 0x0, %wim                  ! make window 1 invalid
461         WRITE_PAUSE
462
463         cmp     %g3, 0x7
464         bne     1f
465          nop
466
467         /* Adjust our window handling routines to
468          * do things correctly on 7 window Sparcs.
469          */
470 #define PATCH_INSN(src, dest) \
471         set     src, %g5; \
472         set     dest, %g2; \
473         ld      [%g5], %g4; \
474         st      %g4, [%g2];
475
476         /* Patch for window spills... */
477         PATCH_INSN(spnwin_patch1_7win, spnwin_patch1)
478         PATCH_INSN(spnwin_patch2_7win, spnwin_patch2)
479
480         /* Patch for window fills... */
481         PATCH_INSN(fnwin_patch1_7win, fnwin_patch1)
482         PATCH_INSN(fnwin_patch2_7win, fnwin_patch2)
483
484 1:
485         /* Finally, turn on traps so that we can call c-code. */
486         rd      %psr, %g3
487         wr      %g3, 0x0, %psr
488         WRITE_PAUSE
489
490         wr      %g3, PSR_ET, %psr
491         WRITE_PAUSE
492
493         set     0, %fp
494         call    __switch_context_nosave
495          nop
496
497         /* We get here when the main context switches back to
498          * the boot context.
499          * Return to previous bootloader.
500          */
501         ret
502          nop
503
504 ss2_ss1000_halt:
505         set     SER_ADDR2, %o0
506         set     SER_ADDR1000, %o1
507         mov     0x05, %o3 /* Reg 5, TXCTRL2 */
508         stba    %o3, [%o0] ASI_M_BYPASS
509         stba    %o3, [%o1] ASI_M_CTL
510         mov     0x68, %o3 /* 8 bits, Tx enabled */
511         stba    %o3, [%o0] ASI_M_BYPASS
512         stba    %o3, [%o1] ASI_M_CTL
513         add     %o0, 2, %o0
514         add     %o1, 2, %o1
515
516 1:      lduba   [%o2] ASI_M_KERNELTXT, %o3
517         cmp     %o3, 0
518         be      2f
519          nop
520         stba    %o3, [%o0] ASI_M_BYPASS
521         stba    %o3, [%o1] ASI_M_CTL
522         b       1b
523          inc    %o2
524 bad_conf:
525 2:      b       2b
526          nop
527
528         .section .rodata
529 ss2_error:
530         .string "Sun4c machines are not supported by OpenBIOS yet, freezing\r\n"
531 ss1000_error:
532         .string "Sun4d machines are not supported by OpenBIOS yet, freezing\r\n"