1 /* $NetBSD: srt0.s,v 1.8 2019/11/28 14:21:25 martin 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 b 1f 67 nop 68 .zero 8192-(.-_start) /* hack for OpenBIOS, see port-sparc64/54719 */ 69 1: 70 /* 71 * Start by creating a stack for ourselves. 72 */ 73 #ifdef _LP64 74 /* 64-bit stack */ 75 btst 1, %sp 76 set CC64FSZ, %g1 ! Frame Size (negative) 77 bnz 1f 78 set BIAS, %g2 ! Bias (negative) 79 andn %sp, 0x0f, %sp ! 16 byte align, per ELF spec. 80 add %g1, %g2, %g1 ! Frame + Bias 81 1: 82 sub %sp, %g1, %g1 83 save %g1, %g0, %sp 84 #else 85 /* 32-bit stack */ 86 btst 1, %sp 87 set CC64FSZ, %g1 ! Frame Size (negative) 88 bz 1f 89 set BIAS, %g2 90 sub %g1, %g2, %g1 91 1: 92 sub %sp, %g1, %g1 ! This is so we properly sign-extend things 93 andn %g1, 0x7, %g1 94 save %g1, %g0, %sp 95 #endif 96 97 /* 98 * Set the psr into a known state: 99 * Set supervisor mode, interrupt level >= 13, traps enabled 100 */ 101 wrpr %g0, 0, %pil ! So I lied 102 wrpr %g0, PSTATE_PRIV+PSTATE_IE, %pstate 103 104 clr %g4 ! Point %g4 to start of data segment 105 ! only problem is that apparently the 106 ! start of the data segment is 0 107 108 /* 109 * void 110 * main(void *openfirmware) 111 */ 112 call _C_LABEL(main) 113 mov %i4, %o0 114 call _C_LABEL(OF_exit) 115 nop 116 117 /* 118 * void syncicache(void* start, int size) 119 * 120 * I$ flush. Really simple. Just flush over the whole range. 121 */ 122 .align 8 123 .globl _C_LABEL(syncicache) 124 _C_LABEL(syncicache): 125 dec 4, %o1 126 flush %o0 127 brgz,a,pt %o1, _C_LABEL(syncicache) 128 inc 4, %o0 129 retl 130 nop 131 132 /* 133 * openfirmware(cell* param); 134 * 135 * OpenFirmware entry point 136 * 137 * If we're running in 32-bit mode we need to convert to a 64-bit stack 138 * and 64-bit cells. The cells we'll allocate off the stack for simplicity. 139 */ 140 .align 8 141 .globl _C_LABEL(openfirmware) 142 FTYPE(openfirmware) 143 _C_LABEL(openfirmware): 144 andcc %sp, 1, %g0 145 bz,pt %icc, 1f 146 sethi %hi(_C_LABEL(romp)), %o1 147 148 LDPTR [%o1+%lo(_C_LABEL(romp))], %o4 ! v9 stack, just load the addr and callit 149 save %sp, -CC64FSZ, %sp 150 mov %i0, %o0 ! Copy over our parameter 151 mov %g1, %l1 152 mov %g2, %l2 153 mov %g3, %l3 154 mov %g4, %l4 155 mov %g5, %l5 156 mov %g6, %l6 157 mov %g7, %l7 158 rdpr %pstate, %l0 159 jmpl %i4, %o7 160 wrpr %g0, PSTATE_PROM|PSTATE_IE, %pstate 161 wrpr %l0, %g0, %pstate 162 mov %l1, %g1 163 mov %l2, %g2 164 mov %l3, %g3 165 mov %l4, %g4 166 mov %l5, %g5 167 mov %l6, %g6 168 mov %l7, %g7 169 ret 170 restore %o0, %g0, %o0 171 172 1: ! v8 -- need to screw with stack & params 173 save %sp, -CC64FSZ, %sp ! Get a new 64-bit stack frame 174 add %sp, -BIAS, %sp 175 sethi %hi(_C_LABEL(romp)), %o1 176 rdpr %pstate, %l0 177 LDPTR [%o1+%lo(_C_LABEL(romp))], %o1 ! Do the actual call 178 srl %sp, 0, %sp 179 mov %i0, %o0 180 mov %g1, %l1 181 mov %g2, %l2 182 mov %g3, %l3 183 mov %g4, %l4 184 mov %g5, %l5 185 mov %g6, %l6 186 mov %g7, %l7 187 jmpl %o1, %o7 188 wrpr %g0, PSTATE_PROM|PSTATE_IE, %pstate ! Enable 64-bit addresses for the prom 189 wrpr %l0, 0, %pstate 190 mov %l1, %g1 191 mov %l2, %g2 192 mov %l3, %g3 193 mov %l4, %g4 194 mov %l5, %g5 195 mov %l6, %g6 196 mov %l7, %g7 197 ret 198 restore %o0, %g0, %o0 199 200 /* 201 * vaddr_t 202 * itlb_va_to_pa(vaddr_t) 203 * 204 * Find out if there is a mapping in iTLB for a given virtual address, 205 * return -1 if there is none. 206 */ 207 .align 8 208 .globl _C_LABEL(itlb_va_to_pa) 209 _C_LABEL(itlb_va_to_pa): 210 set _C_LABEL(itlb_slot_max), %o3 211 ld [%o3], %o3 212 dec %o3 213 sllx %o3, 3, %o3 214 clr %o1 215 0: ldxa [%o1] ASI_IMMU_TLB_TAG, %o2 216 cmp %o2, %o0 217 bne,a %xcc, 1f 218 nop 219 /* return PA of matching entry */ 220 ldxa [%o1] ASI_IMMU_TLB_DATA, %o0 221 sllx %o0, 23, %o0 222 srlx %o0, PGSHIFT+23, %o0 223 sllx %o0, PGSHIFT, %o0 224 retl 225 mov %o0, %o1 226 1: cmp %o1, %o3 227 blu %xcc, 0b 228 add %o1, 8, %o1 229 clr %o0 230 retl 231 not %o0 232 233 /* 234 * vaddr_t 235 * dtlb_va_to_pa(vaddr_t) 236 * 237 * Find out if there is a mapping in dTLB for a given virtual address, 238 * return -1 if there is none. 239 */ 240 .align 8 241 .globl _C_LABEL(dtlb_va_to_pa) 242 _C_LABEL(dtlb_va_to_pa): 243 set _C_LABEL(dtlb_slot_max), %o3 244 ld [%o3], %o3 245 dec %o3 246 sllx %o3, 3, %o3 247 clr %o1 248 0: ldxa [%o1] ASI_DMMU_TLB_TAG, %o2 249 cmp %o2, %o0 250 bne,a %xcc, 1f 251 nop 252 /* return PA of matching entry */ 253 ldxa [%o1] ASI_DMMU_TLB_DATA, %o0 254 sllx %o0, 23, %o0 255 srlx %o0, PGSHIFT+23, %o0 256 sllx %o0, PGSHIFT, %o0 257 retl 258 mov %o0, %o1 259 1: cmp %o1, %o3 260 blu %xcc, 0b 261 add %o1, 8, %o1 262 clr %o0 263 retl 264 not %o0 265 266 /* 267 * void 268 * itlb_enter(vaddr_t vpn, uint32_t data_hi, uint32_t data_lo) 269 * 270 * Insert new mapping into iTLB. Data tag is passed in two different 271 * registers so that it works even with 32-bit compilers. 272 */ 273 .align 8 274 .globl _C_LABEL(itlb_enter) 275 _C_LABEL(itlb_enter): 276 sllx %o1, 32, %o1 277 or %o1, %o2, %o1 278 rdpr %pstate, %o4 279 wrpr %o4, PSTATE_IE, %pstate 280 mov TLB_TAG_ACCESS, %o3 281 stxa %o0, [%o3] ASI_IMMU 282 stxa %o1, [%g0] ASI_IMMU_DATA_IN 283 membar #Sync 284 retl 285 wrpr %o4, 0, %pstate 286 287 288 /* 289 * void 290 * dtlb_replace(vaddr_t vpn, uint32_t data_hi, uint32_t data_lo) 291 * 292 * Replace mapping in dTLB. Data tag is passed in two different 293 * registers so that it works even with 32-bit compilers. 294 */ 295 .align 8 296 .globl _C_LABEL(dtlb_replace) 297 _C_LABEL(dtlb_replace): 298 sllx %o1, 32, %o1 299 or %o1, %o2, %o1 300 rdpr %pstate, %o4 301 wrpr %o4, PSTATE_IE, %pstate 302 /* loop over dtlb entries */ 303 clr %o5 304 0: 305 ldxa [%o5] ASI_DMMU_TLB_TAG, %o2 306 cmp %o2, %o0 307 bne,a %xcc, 1f 308 nop 309 /* found - modify entry */ 310 mov TLB_TAG_ACCESS, %o2 311 stxa %o0, [%o2] ASI_DMMU 312 stxa %o1, [%o5] ASI_DMMU_TLB_DATA 313 membar #Sync 314 retl 315 wrpr %o4, 0, %pstate 316 317 /* advance to next tlb entry */ 318 1: cmp %o5, 63<<3 319 blu %xcc, 0b 320 add %o5, 8, %o5 321 retl 322 nop 323 324 /* 325 * void 326 * dtlb_enter(vaddr_t vpn, uint32_t data_hi, uint32_t data_lo) 327 * 328 * Insert new mapping into dTLB. Data tag is passed in two different 329 * registers so that it works even with 32-bit compilers. 330 */ 331 .align 8 332 .globl _C_LABEL(dtlb_enter) 333 _C_LABEL(dtlb_enter): 334 sllx %o1, 32, %o1 335 or %o1, %o2, %o1 336 rdpr %pstate, %o4 337 wrpr %o4, PSTATE_IE, %pstate 338 mov TLB_TAG_ACCESS, %o3 339 stxa %o0, [%o3] ASI_DMMU 340 stxa %o1, [%g0] ASI_DMMU_DATA_IN 341 membar #Sync 342 retl 343 wrpr %o4, 0, %pstate 344 345 /* 346 * u_int 347 * get_cpuid(void); 348 * 349 * Return UPA identifier for the CPU we're running on. 350 */ 351 .align 8 352 .globl _C_LABEL(get_cpuid) 353 _C_LABEL(get_cpuid): 354 UPA_GET_MID(%o0) 355 retl 356 nop 357 358 #if 0 359 .data 360 .align 8 361 bootstack: 362 #define STACK_SIZE 0x14000 363 .skip STACK_SIZE 364 ebootstack: ! end (top) of boot stack 365 #endif 366