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