1/* $NetBSD: srt0.s,v 1.6 2007/10/17 19:57:16 garbled Exp $ */ 2 3/* 4 * Copyright (C) 1995, 1996 Wolfgang Solfrank. 5 * Copyright (C) 1995, 1996 TooLs GmbH. 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. All advertising materials mentioning features or use of this software 17 * must display the following acknowledgement: 18 * This product includes software developed by TooLs GmbH. 19 * 4. The name of TooLs GmbH may not be used to endorse or promote products 20 * derived from this software without specific prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR 23 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 24 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 25 * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 27 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 28 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 29 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 30 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 31 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 */ 33 34#include <machine/psl.h> 35#include <machine/param.h> 36#include <machine/frame.h> 37#include <machine/asm.h> 38#include <machine/ctlreg.h> 39 40 41#ifdef _LP64 42#define LDPTR ldx 43#else 44#define LDPTR lduw 45#endif 46 47 48 .register %g2,#ignore 49 .register %g3,#ignore 50 51/* 52 * Globals 53 */ 54 .globl _esym 55 .data 56_esym: .word 0 /* end of symbol table */ 57 58/* 59 * Startup entry 60 */ 61 .text 62 .globl _start, _C_LABEL(kernel_text) 63 _C_LABEL(kernel_text) = _start 64_start: 65 nop ! For some reason this is needed to fixup the text section 66 67 /* 68 * Start by creating a stack for ourselves. 69 */ 70#ifdef _LP64 71 /* 64-bit stack */ 72 btst 1, %sp 73 set CC64FSZ, %g1 ! Frame Size (negative) 74 bnz 1f 75 set BIAS, %g2 ! Bias (negative) 76 andn %sp, 0x0f, %sp ! 16 byte align, per ELF spec. 77 add %g1, %g2, %g1 ! Frame + Bias 781: 79 sub %sp, %g1, %g1 80 save %g1, %g0, %sp 81#else 82 /* 32-bit stack */ 83 btst 1, %sp 84 set CC64FSZ, %g1 ! Frame Size (negative) 85 bz 1f 86 set BIAS, %g2 87 sub %g1, %g2, %g1 881: 89 sub %sp, %g1, %g1 ! This is so we properly sign-extend things 90 andn %g1, 0x7, %g1 91 save %g1, %g0, %sp 92#endif 93 94 /* 95 * Set the psr into a known state: 96 * Set supervisor mode, interrupt level >= 13, traps enabled 97 */ 98 wrpr %g0, 0, %pil ! So I lied 99 wrpr %g0, PSTATE_PRIV+PSTATE_IE, %pstate 100 101 clr %g4 ! Point %g4 to start of data segment 102 ! only problem is that apparently the 103 ! start of the data segment is 0 104 105 /* 106 * void 107 * main(void *openfirmware) 108 */ 109 call _C_LABEL(main) 110 mov %i4, %o0 111 call _C_LABEL(OF_exit) 112 nop 113 114/* 115 * void syncicache(void* start, int size) 116 * 117 * I$ flush. Really simple. Just flush over the whole range. 118 */ 119 .align 8 120 .globl _C_LABEL(syncicache) 121_C_LABEL(syncicache): 122 dec 4, %o1 123 flush %o0 124 brgz,a,pt %o1, _C_LABEL(syncicache) 125 inc 4, %o0 126 retl 127 nop 128 129/* 130 * openfirmware(cell* param); 131 * 132 * OpenFirmware entry point 133 * 134 * If we're running in 32-bit mode we need to convert to a 64-bit stack 135 * and 64-bit cells. The cells we'll allocate off the stack for simplicity. 136 */ 137 .align 8 138 .globl _C_LABEL(openfirmware) 139 .proc 1 140 FTYPE(openfirmware) 141_C_LABEL(openfirmware): 142 andcc %sp, 1, %g0 143 bz,pt %icc, 1f 144 sethi %hi(_C_LABEL(romp)), %o1 145 146 LDPTR [%o1+%lo(_C_LABEL(romp))], %o4 ! v9 stack, just load the addr and callit 147 save %sp, -CC64FSZ, %sp 148 mov %i0, %o0 ! Copy over our parameter 149 mov %g1, %l1 150 mov %g2, %l2 151 mov %g3, %l3 152 mov %g4, %l4 153 mov %g5, %l5 154 mov %g6, %l6 155 mov %g7, %l7 156 rdpr %pstate, %l0 157 jmpl %i4, %o7 158 wrpr %g0, PSTATE_PROM|PSTATE_IE, %pstate 159 wrpr %l0, %g0, %pstate 160 mov %l1, %g1 161 mov %l2, %g2 162 mov %l3, %g3 163 mov %l4, %g4 164 mov %l5, %g5 165 mov %l6, %g6 166 mov %l7, %g7 167 ret 168 restore %o0, %g0, %o0 169 1701: ! v8 -- need to screw with stack & params 171 save %sp, -CC64FSZ, %sp ! Get a new 64-bit stack frame 172 add %sp, -BIAS, %sp 173 sethi %hi(_C_LABEL(romp)), %o1 174 rdpr %pstate, %l0 175 LDPTR [%o1+%lo(_C_LABEL(romp))], %o1 ! Do the actual call 176 srl %sp, 0, %sp 177 mov %i0, %o0 178 mov %g1, %l1 179 mov %g2, %l2 180 mov %g3, %l3 181 mov %g4, %l4 182 mov %g5, %l5 183 mov %g6, %l6 184 mov %g7, %l7 185 jmpl %o1, %o7 186 wrpr %g0, PSTATE_PROM|PSTATE_IE, %pstate ! Enable 64-bit addresses for the prom 187 wrpr %l0, 0, %pstate 188 mov %l1, %g1 189 mov %l2, %g2 190 mov %l3, %g3 191 mov %l4, %g4 192 mov %l5, %g5 193 mov %l6, %g6 194 mov %l7, %g7 195 ret 196 restore %o0, %g0, %o0 197 198/* 199 * vaddr_t 200 * itlb_va_to_pa(vaddr_t) 201 * 202 * Find out if there is a mapping in iTLB for a given virtual address, 203 * return -1 if there is none. 204 */ 205 .align 8 206 .globl _C_LABEL(itlb_va_to_pa) 207_C_LABEL(itlb_va_to_pa): 208 set _C_LABEL(itlb_slot_max), %o3 209 ld [%o3], %o3 210 dec %o3 211 sllx %o3, 3, %o3 212 clr %o1 2130: ldxa [%o1] ASI_IMMU_TLB_TAG, %o2 214 cmp %o2, %o0 215 bne,a %xcc, 1f 216 nop 217 /* return PA of matching entry */ 218 ldxa [%o1] ASI_IMMU_TLB_DATA, %o0 219 sllx %o0, 23, %o0 220 srlx %o0, PGSHIFT+23, %o0 221 sllx %o0, PGSHIFT, %o0 222 retl 223 mov %o0, %o1 2241: cmp %o1, %o3 225 blu %xcc, 0b 226 add %o1, 8, %o1 227 clr %o0 228 retl 229 not %o0 230 231/* 232 * vaddr_t 233 * dtlb_va_to_pa(vaddr_t) 234 * 235 * Find out if there is a mapping in dTLB for a given virtual address, 236 * return -1 if there is none. 237 */ 238 .align 8 239 .globl _C_LABEL(dtlb_va_to_pa) 240_C_LABEL(dtlb_va_to_pa): 241 set _C_LABEL(dtlb_slot_max), %o3 242 ld [%o3], %o3 243 dec %o3 244 sllx %o3, 3, %o3 245 clr %o1 2460: ldxa [%o1] ASI_DMMU_TLB_TAG, %o2 247 cmp %o2, %o0 248 bne,a %xcc, 1f 249 nop 250 /* return PA of matching entry */ 251 ldxa [%o1] ASI_DMMU_TLB_DATA, %o0 252 sllx %o0, 23, %o0 253 srlx %o0, PGSHIFT+23, %o0 254 sllx %o0, PGSHIFT, %o0 255 retl 256 mov %o0, %o1 2571: cmp %o1, %o3 258 blu %xcc, 0b 259 add %o1, 8, %o1 260 clr %o0 261 retl 262 not %o0 263 264/* 265 * void 266 * itlb_enter(vaddr_t vpn, uint32_t data_hi, uint32_t data_lo) 267 * 268 * Insert new mapping into iTLB. Data tag is passed in two different 269 * registers so that it works even with 32-bit compilers. 270 */ 271 .align 8 272 .globl _C_LABEL(itlb_enter) 273_C_LABEL(itlb_enter): 274 sllx %o1, 32, %o1 275 or %o1, %o2, %o1 276 rdpr %pstate, %o4 277 wrpr %o4, PSTATE_IE, %pstate 278 mov TLB_TAG_ACCESS, %o3 279 stxa %o0, [%o3] ASI_IMMU 280 stxa %o1, [%g0] ASI_IMMU_DATA_IN 281 membar #Sync 282 retl 283 wrpr %o4, 0, %pstate 284 285 286/* 287 * void 288 * dtlb_replace(vaddr_t vpn, uint32_t data_hi, uint32_t data_lo) 289 * 290 * Replace mapping in dTLB. Data tag is passed in two different 291 * registers so that it works even with 32-bit compilers. 292 */ 293 .align 8 294 .globl _C_LABEL(dtlb_replace) 295_C_LABEL(dtlb_replace): 296 sllx %o1, 32, %o1 297 or %o1, %o2, %o1 298 rdpr %pstate, %o4 299 wrpr %o4, PSTATE_IE, %pstate 300 /* loop over dtlb entries */ 301 clr %o5 3020: 303 ldxa [%o5] ASI_DMMU_TLB_TAG, %o2 304 cmp %o2, %o0 305 bne,a %xcc, 1f 306 nop 307 /* found - modify entry */ 308 mov TLB_TAG_ACCESS, %o2 309 stxa %o0, [%o2] ASI_DMMU 310 stxa %o1, [%o5] ASI_DMMU_TLB_DATA 311 membar #Sync 312 retl 313 wrpr %o4, 0, %pstate 314 315 /* advance to next tlb entry */ 3161: cmp %o5, 63<<3 317 blu %xcc, 0b 318 add %o5, 8, %o5 319 retl 320 nop 321 322/* 323 * void 324 * dtlb_enter(vaddr_t vpn, uint32_t data_hi, uint32_t data_lo) 325 * 326 * Insert new mapping into dTLB. Data tag is passed in two different 327 * registers so that it works even with 32-bit compilers. 328 */ 329 .align 8 330 .globl _C_LABEL(dtlb_enter) 331_C_LABEL(dtlb_enter): 332 sllx %o1, 32, %o1 333 or %o1, %o2, %o1 334 rdpr %pstate, %o4 335 wrpr %o4, PSTATE_IE, %pstate 336 mov TLB_TAG_ACCESS, %o3 337 stxa %o0, [%o3] ASI_DMMU 338 stxa %o1, [%g0] ASI_DMMU_DATA_IN 339 membar #Sync 340 retl 341 wrpr %o4, 0, %pstate 342 343/* 344 * u_int 345 * get_cpuid(void); 346 * 347 * Return UPA identifier for the CPU we're running on. 348 */ 349 .align 8 350 .globl _C_LABEL(get_cpuid) 351_C_LABEL(get_cpuid): 352 UPA_GET_MID(%o0) 353 retl 354 nop 355 356#if 0 357 .data 358 .align 8 359bootstack: 360#define STACK_SIZE 0x14000 361 .skip STACK_SIZE 362ebootstack: ! end (top) of boot stack 363#endif 364