|
|
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.