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