|
|
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: ! 129: ! Calculate SMP table location ! 130: set 0x1f0c, %g2 ! 131: add %g6, %g2, %g2 ! valid? ! 132: lda [%g2] ASI_M_BYPASS, %g7 ! 133: sta %g0, [%g2] ASI_M_BYPASS ! 134: ! 135: ! Get machine ID from configuration device ! 136: mov FW_CFG_MACHINE_ID, %g2 ! 137: sub %g5, 2, %g5 ! 138: stha %g2, [%g5] CFG_ASI ! 139: add %g5, 2, %g5 ! 140: lduba [%g5] CFG_ASI, %g4 ! 141: ! 142: lduba [%g5] CFG_ASI, %g3 ! 143: sll %g3, 8, %g3 ! 144: or %g3, %g4, %g4 ! 145: mov %g4, %y ! 146: ! 147: cmp %g4, 96 ! 148: bgeu ss1000 ! 149: cmp %g4, 64 ! 150: bgeu ss10 ! 151: cmp %g4, 32 ! 152: blu ss2 ! 153: nop ! 154: ! 155: ! Ok, this is SS-5 ! 156: ! 157: tst %g7 ! 158: bz first_cpu ! 159: nop ! 160: ! 161: ! Clear softints used for SMP CPU startup ! 162: set PHYS_JJ_INTR0 + 0x04, %g1 ! 163: sll %g2, 12, %g2 ! 164: add %g1, %g2, %g2 ! 165: set 0xffffffff, %g1 ! 166: sta %g1, [%g2] ASI_M_BYPASS ! clear softints ! 167: add %g2, 4, %g2 ! 168: sta %g0, [%g2] ASI_M_BYPASS ! clear softints ! 169: ! 170: load_ctx: ! 171: ! SMP init, jump to user specified address ! 172: set 0x1f04, %g5 ! 173: add %g6, %g5, %g5 ! ctxtbl ! 174: lda [%g5] ASI_M_BYPASS, %g2 ! 175: sta %g0, [%g5] ASI_M_BYPASS ! 176: set AC_M_CTPR, %g1 ! 177: sta %g2, [%g1] ASI_M_MMUREGS ! set ctx table ptr ! 178: set 0x1f00, %g5 ! 179: add %g6, %g5, %g5 ! ctx ! 180: lda [%g5] ASI_M_BYPASS, %g2 ! 181: sta %g0, [%g5] ASI_M_BYPASS ! 182: set AC_M_CXR, %g1 ! 183: sta %g2, [%g1] ASI_M_MMUREGS ! set context ! 184: set 0x1f08, %g5 ! 185: add %g6, %g5, %g5 ! entry ! 186: lda [%g5] ASI_M_BYPASS, %g2 ! 187: sta %g0, [%g5] ASI_M_BYPASS ! 188: set 1, %g1 ! 189: jmp %g2 ! jump to kernel ! 190: sta %g1, [%g0] ASI_M_MMUREGS ! enable mmu ! 191: ! 192: ss10: ! 193: ! Ok, this is SS-10 or SS-600MP ! 194: tst %g7 ! 195: bz first_cpu ! 196: nop ! 197: ! 198: ! Clear softints used for SMP CPU startup ! 199: set PHYS_SS10_INTR0 + 0x04, %g1 ! 200: sll %g2, 12, %g2 ! 201: add %g1, %g2, %g2 ! 202: set 0xffffffff, %g1 ! 203: sta %g1, [%g2] ASI_M_CTL ! clear softints ! 204: add %g2, 4, %g2 ! 205: b load_ctx ! 206: sta %g0, [%g2] ASI_M_CTL ! clear softints ! 207: ! 208: ss2: ! 209: ! Ok, this is SS-2 ! 210: set ss2_error, %o2 ! 211: b ss2_ss1000_halt ! 212: nop ! 213: ! 214: ss1000: ! 215: ! Ok, this is SS-1000 or SS-2000 ! 216: set ss1000_error, %o2 ! 217: b ss2_ss1000_halt ! 218: nop ! 219: ! 220: first_cpu: ! 221: /* Create temporary page tables and map the ROM area to end of ! 222: RAM. This will be done properly in iommu.c later. */ ! 223: ! Calculate start of page tables etc. to %g6 ! 224: set 0x2000, %g4 ! 225: sub %g1, %g4, %g6 ! start of private memory ! 226: ! 227: mov %g6, %g2 ! ctx table at s+0x0 ! 228: add %g2, 0x400, %g3 ! l1 table at s+0x400 ! 229: srl %g3, 0x4, %g3 ! 230: or %g3, 0x1, %g3 ! 231: sta %g3, [%g2] ASI_M_BYPASS ! 232: add %g2, 0x400, %g2 ! s+0x400 ! 233: add %g2, 0x400, %g3 ! l2 table for ram (00xxxxxx) at s+0x800 ! 234: srl %g3, 0x4, %g3 ! 235: or %g3, 0x1, %g3 ! 236: sta %g3, [%g2] ASI_M_BYPASS ! 237: add %g2, 0x500, %g3 ! l2 table for rom (ffxxxxxx) at s+0x900 ! 238: add %g2, 0x3fc, %g2 ! s+0x7fc ! 239: srl %g3, 0x4, %g3 ! 240: or %g3, 0x1, %g3 ! 241: sta %g3, [%g2] ASI_M_BYPASS ! 242: add %g2, 0x4, %g2 ! s+0x800 ! 243: #if 0 ! 244: set 0x40, %g6 ! 245: set ((7 << 2) | 2), %g3 ! 7 = U: --- S: RWX (main memory) ! 246: 1: sta %g3, [%g2] ASI_M_BYPASS ! 247: add %g2, 4, %g2 ! 248: deccc %g6 ! 249: bne 1b ! 250: nop ! 251: #else ! 252: add %g2, 0x100, %g2 ! 253: #endif ! 254: ! s+0x900 ! 255: add %g2, 0xa00 - 0x900, %g3 ! l3 table for rom at s+0xa00 ! 256: add %g2, 0x0d0, %g2 ! s+0x9d0 ! 257: srl %g3, 0x4, %g3 ! 258: or %g3, 0x1, %g3 ! 259: sta %g3, [%g2] ASI_M_BYPASS ! 260: add %g2, 4, %g2 ! s+0x9d4 ! 261: add %g2, 0xb00 - 0x9d4, %g3 ! 2nd l3 table for rom at s+0xb00 ! 262: srl %g3, 0x4, %g3 ! 263: or %g3, 0x1, %g3 ! 264: sta %g3, [%g2] ASI_M_BYPASS ! 265: add %g2, 4, %g2 ! s+0x9d8 ! 266: add %g2, 0xc00 - 0x9d8, %g3 ! 3rd l3 table for rom at s+0xc00 ! 267: srl %g3, 0x4, %g3 ! 268: or %g3, 0x1, %g3 ! 269: sta %g3, [%g2] ASI_M_BYPASS ! 270: add %g2, 4, %g2 ! s+0x9dc ! 271: add %g2, 0xd00 - 0x9dc, %g3 ! 4th l3 table for rom at s+0xd00 ! 272: srl %g3, 0x4, %g3 ! 273: or %g3, 0x1, %g3 ! 274: sta %g3, [%g2] ASI_M_BYPASS ! 275: add %g2, 4, %g2 ! s+0x9e0 ! 276: add %g2, 0xe00 - 0x9e0, %g3 ! 5th l3 table for rom at s+0xe00 ! 277: srl %g3, 0x4, %g3 ! 278: or %g3, 0x1, %g3 ! 279: sta %g3, [%g2] ASI_M_BYPASS ! 280: add %g2, 4, %g2 ! s+0x9e4 ! 281: add %g2, 0xf00 - 0x9e4, %g3 ! 6th l3 table for rom at s+0xf00 ! 282: srl %g3, 0x4, %g3 ! 283: or %g3, 0x1, %g3 ! 284: sta %g3, [%g2] ASI_M_BYPASS ! 285: add %g2, 4, %g2 ! s+0x9e8 ! 286: add %g2, 0x1000 - 0x9e8, %g3 ! 7th l3 table for rom at s+0x1000 ! 287: srl %g3, 0x4, %g3 ! 288: or %g3, 0x1, %g3 ! 289: sta %g3, [%g2] ASI_M_BYPASS ! 290: add %g2, 4, %g2 ! s+0x9ec ! 291: add %g2, 0x1100 - 0x9ec, %g3 ! 8th l3 table for rom at s+0x1100 ! 292: srl %g3, 0x4, %g3 ! 293: or %g3, 0x1, %g3 ! 294: sta %g3, [%g2] ASI_M_BYPASS ! 295: add %g2, 0xa00-0x9ec, %g2 ! s+0xa00 ! 296: ! 297: /* Use end of ram for code, rodata, data, and bss ! 298: sections. SunOS wants to write to trap table... */ ! 299: set _end, %g6 ! 300: set _start, %g4 ! 301: sub %g6, %g4, %g6 ! 302: sub %g1, %g6, %g3 ! 303: set 0x1000, %g5 ! 304: sub %g3, %g5, %g3 ! 305: sub %g3, %g5, %g3 ! start of ROM copy ! 306: mov %g3, %g7 ! save in %g7 ! 307: srl %g6, 12, %g6 ! # of all pages ! 308: 1: srl %g3, 0x4, %g4 ! 309: or %g4, ((7 << 2) | 2), %g4 ! 7 = U: --- S: RWX ! 310: sta %g4, [%g2] ASI_M_BYPASS ! 311: add %g2, 4, %g2 ! 312: add %g3, %g5, %g3 ! 313: deccc %g6 ! 314: bne 1b ! 315: nop ! 316: ! 317: mov %g1, %g6 ! %g6 = memory size ! 318: ! 319: /* Copy the code, rodata and data sections from ROM. */ ! 320: sub %g7, 4, %g3 ! 321: set _start - 4, %g4 ! First address of TEXT - 4 ! 322: set _bss, %g5 ! Last address of DATA ! 323: ba 2f ! 324: nop ! 325: 1: ! 326: lda [%g4] ASI_M_KERNELTXT, %g1 ! 327: sta %g1, [%g3] ASI_M_BYPASS ! 328: 2: ! 329: cmp %g4, %g5 ! 330: add %g3, 0x4, %g3 ! 331: bl 1b ! 332: add %g4, 0x4, %g4 ! 333: ! 334: set 0x2000, %g3 ! 335: sub %g6, %g3, %g7 ! ctx table at s+0x0 ! 336: set AC_M_CTPR, %g2 ! 337: srl %g7, 4, %g7 ! 338: sta %g7, [%g2] ASI_M_MMUREGS ! set ctx table ptr ! 339: set AC_M_CXR, %g2 ! 340: sta %g0, [%g2] ASI_M_MMUREGS ! context 0 ! 341: set highmem, %g2 ! 342: set 1, %g1 ! 343: jmp %g2 ! 344: sta %g1, [%g0] ASI_M_MMUREGS ! enable mmu ! 345: highmem: ! 346: /* ! 347: * The code which enables traps is a simplified version of ! 348: * kernel head.S. ! 349: * ! 350: * We know number of windows as 8 so we do not calculate them. ! 351: * The deadwood is here for any case. ! 352: */ ! 353: ! 354: /* Turn on Supervisor, EnableFloating, and all the PIL bits. ! 355: * Also puts us in register window zero with traps off. ! 356: */ ! 357: set (PSR_PS | PSR_S | PSR_PIL | PSR_EF), %g2 ! 358: wr %g2, 0x0, %psr ! 359: WRITE_PAUSE ! 360: ! 361: /* Zero out our BSS section. */ ! 362: set _bss - 4, %o0 ! First address of BSS ! 363: set _estack - 4, %o1 ! Last address of BSS ! 364: ba 2f ! 365: nop ! 366: 1: ! 367: st %g0, [%o0] ! 368: 2: ! 369: subcc %o0, %o1, %g0 ! 370: bl 1b ! 371: add %o0, 0x4, %o0 ! 372: ! 373: set trap_table, %g1 ! 374: wr %g1, 0x0, %tbr ! 375: ! 376: set qemu_mem_size, %g1 ! 377: st %g6, [%g1] ! 378: ! 379: set _end, %o0 ! Store va->pa conversion factor ! 380: set _start, %o2 ! 381: sub %o0, %o2, %o0 ! 382: sub %g6, %o0, %o0 ! 383: set 0x2000, %o1 ! 384: sub %o0, %o1, %o0 ! start of ROM copy ! 385: sub %o2, %o0, %o0 ! start of ROM copy ! 386: set va_shift, %g1 ! 387: st %o0, [%g1] ! 388: ! 389: set qemu_machine_type, %g1 ! 390: mov %y, %g2 ! 391: st %g2, [%g1] ! 392: ! 393: /* Compute NWINDOWS and stash it away. Now uses %wim trick explained ! 394: * in the V8 manual. Ok, this method seems to work, Sparc is cool... ! 395: * No, it doesn't work, have to play the save/readCWP/restore trick. ! 396: */ ! 397: ! 398: wr %g0, 0x0, %wim ! so we do not get a trap ! 399: WRITE_PAUSE ! 400: ! 401: save ! 402: ! 403: rd %psr, %g3 ! 404: ! 405: restore ! 406: ! 407: and %g3, 0x1f, %g3 ! 408: add %g3, 0x1, %g3 ! 409: ! 410: mov 2, %g1 ! 411: wr %g1, 0x0, %wim ! make window 1 invalid ! 412: WRITE_PAUSE ! 413: ! 414: cmp %g3, 0x7 ! 415: bne 1f ! 416: nop ! 417: ! 418: /* Adjust our window handling routines to ! 419: * do things correctly on 7 window Sparcs. ! 420: */ ! 421: #define PATCH_INSN(src, dest) \ ! 422: set src, %g5; \ ! 423: set dest, %g2; \ ! 424: ld [%g5], %g4; \ ! 425: st %g4, [%g2]; ! 426: ! 427: /* Patch for window spills... */ ! 428: PATCH_INSN(spnwin_patch1_7win, spnwin_patch1) ! 429: PATCH_INSN(spnwin_patch2_7win, spnwin_patch2) ! 430: ! 431: /* Patch for window fills... */ ! 432: PATCH_INSN(fnwin_patch1_7win, fnwin_patch1) ! 433: PATCH_INSN(fnwin_patch2_7win, fnwin_patch2) ! 434: ! 435: 1: ! 436: /* Finally, turn on traps so that we can call c-code. */ ! 437: rd %psr, %g3 ! 438: wr %g3, 0x0, %psr ! 439: WRITE_PAUSE ! 440: ! 441: wr %g3, PSR_ET, %psr ! 442: WRITE_PAUSE ! 443: ! 444: call __switch_context_nosave ! 445: nop ! 446: ! 447: /* We get here when the main context switches back to ! 448: * the boot context. ! 449: * Return to previous bootloader. ! 450: */ ! 451: ret ! 452: nop ! 453: ! 454: ss2_ss1000_halt: ! 455: set SER_ADDR2, %o0 ! 456: set SER_ADDR1000, %o1 ! 457: mov 0x05, %o3 /* Reg 5, TXCTRL2 */ ! 458: stba %o3, [%o0] ASI_M_BYPASS ! 459: stba %o3, [%o1] ASI_M_CTL ! 460: mov 0x68, %o3 /* 8 bits, Tx enabled */ ! 461: stba %o3, [%o0] ASI_M_BYPASS ! 462: stba %o3, [%o1] ASI_M_CTL ! 463: add %o0, 2, %o0 ! 464: add %o1, 2, %o1 ! 465: ! 466: 1: lduba [%o2] ASI_M_KERNELTXT, %o3 ! 467: cmp %o3, 0 ! 468: be 2f ! 469: nop ! 470: stba %o3, [%o0] ASI_M_BYPASS ! 471: stba %o3, [%o1] ASI_M_CTL ! 472: b 1b ! 473: inc %o2 ! 474: bad_conf: ! 475: 2: b 2b ! 476: nop ! 477: ! 478: .section .rodata ! 479: ss2_error: ! 480: .string "Sun4c machines are not supported by OpenBIOS yet, freezing\r\n" ! 481: ss1000_error: ! 482: .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.