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 <asm/asi.h>
12#include "pstate.h"
13#include "lsu.h"
14#include "cpustate.h"
15#define NO_QEMU_PROTOS
16#define NO_OPENBIOS_PROTOS
17#include "arch/common/fw_cfg.h"
18
19#define PROM_ADDR 0x1fff0000000
20#define CFG_ADDR  0x1fe02000510
21#define HZ        1 * 1000 * 1000
22#define TICK_INT_DIS 0x8000000000000000
23
24        .globl	entry, _entry
25
26	.section ".text", "ax"
27	.align	8
28        .register %g2, #scratch
29        .register %g3, #scratch
30        .register %g6, #scratch
31        .register %g7, #scratch
32
33/*
34 * Entry point
35 * We start execution from here.
36 */
37_entry:
38entry:
39        ! Set up CPU state
40        wrpr    %g0, PSTATE_PRIV, %pstate
41        wr      %g0, 0, %fprs
42        wrpr    %g0, 0x0, %tl
43
44        ! Extract NWINDOWS from %ver
45        rdpr    %ver, %g1
46        and     %g1, 0xf, %g1
47        dec     %g1
48        wrpr    %g1, 0, %cleanwin
49        wrpr    %g1, 0, %cansave
50        wrpr    %g0, 0, %canrestore
51        wrpr    %g0, 0, %otherwin
52        wrpr    %g0, 0, %wstate
53        ! disable timer now
54        setx    TICK_INT_DIS, %g2, %g1
55        wr      %g1, 0, %tick_cmpr
56
57        ! Disable I/D MMUs and caches
58        stxa    %g0, [%g0] ASI_LSU_CONTROL
59
60        ! Check signature "QEMU"
61        setx    CFG_ADDR, %g2, %g5
62        mov     FW_CFG_SIGNATURE, %g2
63        stha    %g2, [%g5] ASI_PHYS_BYPASS_EC_E_L
64        inc     %g5
65        lduba   [%g5] ASI_PHYS_BYPASS_EC_E, %g2
66        cmp     %g2, 'Q'
67        bne     bad_conf
68         nop
69        lduba   [%g5] ASI_PHYS_BYPASS_EC_E, %g2
70        cmp     %g2, 'E'
71        bne     bad_conf
72         nop
73        lduba   [%g5] ASI_PHYS_BYPASS_EC_E, %g2
74        cmp     %g2, 'M'
75        bne     bad_conf
76         nop
77        lduba   [%g5] ASI_PHYS_BYPASS_EC_E, %g2
78        cmp     %g2, 'U'
79        bne     bad_conf
80         nop
81
82        ! Clear ITLB
83        mov     6 << 3, %g1
84        stxa    %g0, [%g1] ASI_IMMU
85        stxa    %g0, [%g1] ASI_DMMU
86        mov     63 << 3, %g1
871:      stxa    %g0, [%g1] ASI_ITLB_DATA_ACCESS
88        subcc   %g1, 1 << 3, %g1
89        bpos    1b
90         nop
91
92        ! Clear DTLB
93        mov     63 << 3, %g1
941:      stxa    %g0, [%g1] ASI_DTLB_DATA_ACCESS
95        subcc   %g1, 1 << 3, %g1
96        bpos    1b
97         nop
98
99        ! Get memory size from configuration device
100        ! NB: little endian format
101        mov     FW_CFG_RAM_SIZE, %g2
102        dec     %g5
103        stha    %g2, [%g5] ASI_PHYS_BYPASS_EC_E_L
104        inc     %g5
105        lduba   [%g5] ASI_PHYS_BYPASS_EC_E, %g4
106
107        lduba   [%g5] ASI_PHYS_BYPASS_EC_E, %g3
108        sllx    %g3, 8, %g3
109        or      %g3, %g4, %g4
110
111        lduba   [%g5] ASI_PHYS_BYPASS_EC_E, %g3
112        sllx    %g3, 16, %g3
113        or      %g3, %g4, %g4
114
115        lduba   [%g5] ASI_PHYS_BYPASS_EC_E, %g3
116        sllx    %g3, 24, %g3
117        or      %g3, %g4, %g4
118
119        lduba   [%g5] ASI_PHYS_BYPASS_EC_E, %g3
120        sllx    %g3, 32, %g3
121        or      %g3, %g4, %g4
122
123        lduba   [%g5] ASI_PHYS_BYPASS_EC_E, %g3
124        sllx    %g3, 40, %g3
125        or      %g3, %g4, %g4
126
127        lduba   [%g5] ASI_PHYS_BYPASS_EC_E, %g3
128        sllx    %g3, 48, %g3
129        or      %g3, %g4, %g4
130
131        lduba   [%g5] ASI_PHYS_BYPASS_EC_E, %g3
132        sllx    %g3, 56, %g3
133        or      %g3, %g4, %g1
134        ! %g1 contains end of memory
135
136        setx    _end, %g7, %g3
137        set     0x7ffff, %g2
138        add     %g3, %g2, %g3
139        andn    %g3, %g2, %g3
140        setx    _data, %g7, %g2
141        sub     %g3, %g2, %g2
142        sub	%g1, %g2, %g2			! %g2 = start of private memory
143        mov     %g2, %l0
144
145	! setup .data & .bss
146        setx    _data, %g7, %g4
147        sub     %g3, %g4, %g5
148        srlx    %g5, 19, %g6			! %g6 = # of 512k .bss pages
149	set	0xc0000000, %g3
150	sllx	%g3, 32, %g3
151	or	%g3, 0x7e, %g3
152	! valid, 512k, locked, cacheable(I/E/C), priv, writable
153	set	48, %g7
1541:	stxa	%g4, [%g7] ASI_DMMU		! vaddr = _data + N * 0x80000, ctx=0
155	or	%g2, %g3, %g5
156	! paddr = start_mem + N * 0x80000
157	stxa	%g5, [%g0] ASI_DTLB_DATA_IN
158	set	0x80000, %g5
159	add	%g2, %g5, %g2
160	add	%g4, %g5, %g4
161	deccc	%g6
162	bne	1b
163	 nop
164
165	! setup .rodata, also make .text readable
166	setx	_data, %g7, %g5
167	setx	_start, %g7, %g4
168        sub     %g5, %g4, %g5
169	srlx    %g5, 19, %g6			! %g6 = # of 512k .rodata pages
170	set	48, %g7
171	set	0x80000, %g5
172        setx    PROM_ADDR, %l1, %l2
1731:      stxa	%g4, [%g7] ASI_DMMU		! vaddr = _rodata, ctx=0
174	set	0xc0000000, %g3
175	sllx	%g3, 32, %g3
176	or	%g3, 0x7c, %g3
177	or	%l2, %g3, %g3
178	! valid, 512k, locked, cacheable(I/E/C), priv
179	! paddr = _rodata + N * 0x10000
180	stxa	%g3, [%g0] ASI_DTLB_DATA_IN
181	add	%g4, %g5, %g4
182	deccc	%g6
183	bne	1b
184	 add	%l2, %g5, %l2
185
186	membar	#Sync
187
188	setx	_start, %g7, %g4
189	setx	_rodata, %g7, %g5
190        sub     %g5, %g4, %g5
191	set 0x7ffff, %g7
192	add %g5, %g7, %g5					! round to 512k
193        srlx    %g5, 19, %g6			! %g6 = # of 512k .text pages
194	set	0x80000, %g5
195	set	48, %g7
196        setx    PROM_ADDR, %l1, %l2
1971:      stxa	%g4, [%g7] ASI_IMMU		! vaddr = _start, ctx=0
198	set	0xc0000000, %g3
199	sllx	%g3, 32, %g3
200	or	%g3, 0x7c, %g3
201	or	%l2, %g3, %g3
202	! valid, 512k, locked, cacheable(I/E/C), priv
203	! paddr = _start + N * 0x80000
204	stxa	%g3, [%g0] ASI_ITLB_DATA_IN
205	add	%g4, %g5, %g4
206	deccc	%g6
207	bne	1b
208	 add	%l2, %g5, %l2
209
210	flush	%g4
211
212	mov	%g1, %g3
213
214	set     8, %g2
215	sta     %g0, [%g2] ASI_DMMU		! set primary ctx=0
216
217	! Enable I/D MMUs and caches
218        setx    lowmem, %g2, %g1
219	set	LSU_CONTROL_DM|LSU_CONTROL_IM|LSU_CONTROL_DC|LSU_CONTROL_IC, %g2
220        jmp     %g1
221         stxa	%g2, [%g0] ASI_LSU_CONTROL
222
223lowmem:
224        /* Copy the DATA section from ROM. */
225        setx	_data - 8, %o7, %o0             ! First address of DATA
226        setx	_bss, %o7, %o1                  ! Last address of DATA
227        setx    _start, %o7, %o2
228        sub     %o0, %o2, %o2                   ! _data - _start
229        setx    PROM_ADDR, %o7, %o3
230        add     %o3, %o2, %o2                   ! PROM_ADDR + (_data - _start)
231        ba	2f
232         nop
2331:
234        ldxa    [%o2] ASI_PHYS_BYPASS_EC_E, %g1
235        stx	%g1, [%o0]
2362:
237        add	%o2, 0x8, %o2
238        subcc	%o0, %o1, %g0
239        bl	1b
240         add	%o0, 0x8, %o0
241
242        /* Zero out our BSS section. */
243        setx    _bss - 8, %o7, %o0              ! First address of BSS
244        setx    _end - 8, %o7, %o1                  ! Last address of BSS
245        ba	2f
246         nop
2471:
248        stx     %g0, [%o0]
2492:
250        subcc	%o0, %o1, %g0
251        bl	1b
252         add	%o0, 0x8, %o0
253
254        setx    trap_table, %g2, %g1
255        wrpr    %g1, %tba
256
257        setx    qemu_mem_size, %g7, %g1
258        stx     %g3, [%g1]
259
260        setx    _data, %g7, %g1                 ! Store va->pa conversion factor
261        sub     %g1, %l0, %g2
262        setx    va_shift, %g7, %g1
263        stx     %g2, [%g1]
264
265        /* Finally, turn on traps so that we can call c-code. */
266	wrpr    %g0, (PSTATE_PRIV|PSTATE_PEF|PSTATE_IE), %pstate
267
268        /* Set up a default context */
269        setx    __context, %g2, %g1
270        ldx     [%g1], %g1
271
272        SAVE_CPU_STATE(entry)
273
274        /* Set up local stack pointer */
275        setx    _estack - 2047, %o2, %sp
276
277        /* And for the main context */
278        add	%sp, - 192 - 0x500, %g2
279        stx	%g2, [%g1 + 0xa0]
280
281        ! 100 Hz timer
282        setx    TICK_INT_DIS, %g2, %g1
283        rd      %tick, %g2
284        andn    %g2, %g1, %g2
285        set     HZ, %g1
286        add     %g1, %g2, %g1
287        wr      %g1, 0, %tick_cmpr
288
289        /* Switch to our main context.
290         * Main context is statically defined in C.
291         */
292
293        call    __switch_context
294         nop
295
296        /* We get here when the main context switches back to
297         * the boot context.
298         */
299bad_conf:
300        b       bad_conf
301         nop
302