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