1 /* $NetBSD: locore.S,v 1.10 2023/10/06 11:45:16 skrll Exp $ */ 2 3 /*- 4 * Copyright (c) 1998 Doug Rabson 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 * 28 * $FreeBSD$ 29 */ 30 31 #include "opt_multiprocessor.h" 32 33 #include <machine/asm.h> 34 #include <machine/elf_machdep.h> 35 #include <sys/syscall.h> 36 37 #include "assym.h" 38 39 .section .data.proc0,"aw" 40 .align PAGE_SIZE 41 .global kstack 42 kstack: .space KSTACK_PAGES * PAGE_SIZE 43 .global kstack_top 44 kstack_top: 45 46 .text 47 48 /* 49 * Not really a leaf but we can't return. 50 * The EFI loader passes the physical address of the bootinfo block in 51 * register r8. 52 */ 53 ENTRY_NOPROFILE(start, 1) 54 .prologue 55 .save rp,r0 56 .body 57 { .mlx 58 mov ar.rsc=0 59 movl r16=ia64_vector_table // set up IVT early 60 ;; 61 } 62 { .mlx 63 mov cr.iva=r16 64 movl r16=kstack 65 ;; 66 } 67 { .mmi 68 srlz.i 69 ;; 70 ssm IA64_PSR_DFH 71 mov r17=KSTACK_PAGES*PAGE_SIZE-SIZEOF_PCB-SIZEOF_TRAPFRAME-16 72 ;; 73 } 74 { .mlx 75 add sp=r16,r17 // proc0's stack 76 movl gp=__gp // find kernel globals 77 ;; 78 } 79 { .mlx 80 mov ar.bspstore=r16 // switch backing store 81 movl r16=pa_bootinfo 82 ;; 83 } 84 { .mmi 85 st8 [r16]=r8 // save the PA of the bootinfo block 86 loadrs // invalidate regs 87 mov r17=IA64_DCR_DEFAULT 88 ;; 89 } 90 { .mmi 91 mov cr.dcr=r17 92 mov ar.rsc=3 // turn rse back on 93 nop 0 94 ;; 95 } 96 { .mmi 97 srlz.d 98 alloc r16=ar.pfs,0,0,1,0 99 mov out0=r0 // we are linked at the right address 100 ;; // we just need to process fptrs 101 } 102 #if 0 /* XXX: Look into relocs */ 103 { .mib 104 nop 0 105 nop 0 106 br.call.sptk.many rp=_reloc 107 } 108 #endif 109 { .mib 110 nop 0 111 nop 0 112 br.call.sptk.many rp=ia64_init 113 ;; 114 } 115 /* We have the new bspstore in r8 and the new sp in r9. 116 Switch onto the new stack and call mi_startup(). */ 117 { .mmi 118 mov ar.rsc = 0 119 ;; 120 mov ar.bspstore = r8 121 mov sp = r9 122 ;; 123 } 124 { .mmi 125 loadrs 126 ;; 127 mov ar.rsc = 3 128 nop 0 129 ;; 130 } 131 { .mib 132 nop 0 133 nop 0 134 br.call.sptk.many rp=main 135 ;; 136 } 137 /* NOTREACHED */ 138 1: br.cond.sptk.few 1b 139 END(start) 140 141 142 #ifdef MULTIPROCESSOR 143 /* 144 * AP wake-up entry point. The handoff state is similar as for the BSP, 145 * as described on page 3-9 of the IPF SAL Specification. The difference 146 * lies in the contents of register b0. For APs this register holds the 147 * return address into the SAL rendezvous routine. 148 * 149 * Note that we're responsible for clearing the IRR bit by reading cr.ivr 150 * and issuing the EOI to the local SAPIC. 151 */ 152 .align 32 153 ENTRY_NOPROFILE(os_boot_rendez,0) 154 mov r16=cr.ivr // clear IRR bit 155 ;; 156 srlz.d 157 mov cr.eoi=r0 // ACK the wake-up 158 ;; 159 srlz.d 160 rsm IA64_PSR_IC|IA64_PSR_I 161 ;; 162 mov r16 = (5<<8)|(PAGE_SHIFT<<2)|1 163 movl r17 = 5<<61 164 ;; 165 mov rr[r17] = r16 166 ;; 167 srlz.d 168 mov r16 = (6<<8)|(IA64_ID_PAGE_SHIFT<<2) 169 movl r17 = 6<<61 170 ;; 171 mov rr[r17] = r16 172 ;; 173 srlz.d 174 mov r16 = (7<<8)|(IA64_ID_PAGE_SHIFT<<2) 175 movl r17 = 7<<61 176 ;; 177 mov rr[r17] = r16 178 ;; 179 srlz.d 180 mov r16 = PTE_PRESENT+PTE_MA_WB+PTE_ACCESSED+PTE_DIRTY+ \ 181 PTE_PL_KERN+PTE_AR_RWX 182 mov r18 = 28<<2 183 ;; 184 185 mov cr.ifa = r17 186 mov cr.itir = r18 187 ptr.d r17, r18 188 ptr.i r17, r18 189 ;; 190 srlz.i 191 ;; 192 itr.d dtr[r0] = r16 193 ;; 194 itr.i itr[r0] = r16 195 ;; 196 srlz.i 197 ;; 198 1: mov r16 = ip 199 add r17 = 2f-1b, r17 200 movl r18 = (IA64_PSR_AC|IA64_PSR_BN|IA64_PSR_DFH|IA64_PSR_DT|IA64_PSR_IC|IA64_PSR_IT|IA64_PSR_RT) 201 ;; 202 add r17 = r17, r16 203 mov cr.ipsr = r18 204 mov cr.ifs = r0 205 ;; 206 mov cr.iip = r17 207 ;; 208 rfi 209 210 .align 32 211 2: 212 { .mlx 213 mov ar.rsc = 0 214 movl r16 = ia64_vector_table // set up IVT early 215 ;; 216 } 217 { .mlx 218 mov cr.iva = r16 219 movl r16 = ap_stack 220 ;; 221 } 222 { .mmi 223 srlz.i 224 ;; 225 ld8 r16 = [r16] 226 mov r18 = KSTACK_PAGES*PAGE_SIZE-SIZEOF_PCB-SIZEOF_TRAPFRAME-16 227 ;; 228 } 229 { .mlx 230 mov ar.bspstore = r16 231 movl gp = __gp 232 ;; 233 } 234 { .mmi 235 loadrs 236 ;; 237 alloc r17 = ar.pfs, 0, 0, 0, 0 238 add sp = r18, r16 239 ;; 240 } 241 { .mfb 242 mov ar.rsc = 3 243 nop 0 244 br.call.sptk.few rp = ia64_ap_startup 245 ;; 246 } 247 /* NOT REACHED */ 248 9: 249 { .mfb 250 nop 0 251 nop 0 252 br.sptk 9b 253 ;; 254 } 255 END(os_boot_rendez) 256 257 #endif /* MULTIPROCESSOR */ 258 259 .text 260 // in0: image base 261 /*STATIC_ENTRY(_reloc, 1) 262 alloc loc0=ar.pfs,1,2,0,0 263 mov loc1=rp 264 ;; 265 movl r15=@gprel(_DYNAMIC) // find _DYNAMIC etc. 266 movl r2=@gprel(fptr_storage) 267 movl r3=@gprel(fptr_storage_end) 268 ;; 269 add r15=r15,gp // relocate _DYNAMIC etc. 270 add r2=r2,gp 271 add r3=r3,gp 272 ;; 273 1: ld8 r16=[r15],8 // read r15->d_tag 274 ;; 275 ld8 r17=[r15],8 // and r15->d_val 276 ;; 277 cmp.eq p6,p0=DT_NULL,r16 // done? 278 (p6) br.cond.dpnt.few 2f 279 ;; 280 cmp.eq p6,p0=DT_RELA,r16 281 ;; 282 (p6) add r18=r17,in0 // found rela section 283 ;; 284 cmp.eq p6,p0=DT_RELASZ,r16 285 ;; 286 (p6) mov r19=r17 // found rela size 287 ;; 288 cmp.eq p6,p0=DT_SYMTAB,r16 289 ;; 290 (p6) add r20=r17,in0 // found symbol table 291 ;; 292 (p6) setf.sig f8=r20 293 ;; 294 cmp.eq p6,p0=DT_SYMENT,r16 295 ;; 296 (p6) setf.sig f9=r17 // found symbol entry size 297 ;; 298 cmp.eq p6,p0=DT_RELAENT,r16 299 ;; 300 (p6) mov r22=r17 // found rela entry size 301 ;; 302 br.sptk.few 1b 303 304 2: 305 ld8 r15=[r18],8 // read r_offset 306 ;; 307 ld8 r16=[r18],8 // read r_info 308 add r15=r15,in0 // relocate r_offset 309 ;; 310 ld8 r17=[r18],8 // read r_addend 311 sub r19=r19,r22 // update relasz 312 313 extr.u r23=r16,0,32 // ELF64_R_TYPE(r16) 314 ;; 315 cmp.eq p6,p0=R_IA64_NONE,r23 316 (p6) br.cond.dpnt.few 3f 317 ;; 318 cmp.eq p6,p0=R_IA64_REL64LSB,r23 319 (p6) br.cond.dptk.few 4f 320 ;; 321 322 extr.u r16=r16,32,32 // ELF64_R_SYM(r16) 323 ;; 324 setf.sig f10=r16 // so we can multiply 325 ;; 326 xma.lu f10=f10,f9,f8 // f10=symtab + r_sym*syment 327 ;; 328 getf.sig r16=f10 329 ;; 330 add r16=8,r16 // address of st_value 331 ;; 332 ld8 r16=[r16] // read symbol value 333 ;; 334 add r16=r16,in0 // relocate symbol value 335 ;; 336 337 cmp.eq p6,p0=R_IA64_DIR64LSB,r23 338 (p6) br.cond.dptk.few 5f 339 ;; 340 cmp.eq p6,p0=R_IA64_FPTR64LSB,r23 341 (p6) br.cond.dptk.few 6f 342 ;; 343 344 3: 345 cmp.ltu p6,p0=0,r19 // more? 346 (p6) br.cond.dptk.few 2b // loop 347 mov r8=0 // success return value 348 br.cond.sptk.few 9f // done 349 350 4: 351 add r16=in0,r17 // BD + A 352 ;; 353 st8 [r15]=r16 // word64 (LSB) 354 br.cond.sptk.few 3b 355 356 5: 357 add r16=r16,r17 // S + A 358 ;; 359 st8 [r15]=r16 // word64 (LSB) 360 br.cond.sptk.few 3b 361 362 6: 363 movl r17=@gprel(fptr_storage) 364 ;; 365 add r17=r17,gp // start of fptrs 366 ;; 367 7: cmp.geu p6,p0=r17,r2 // end of fptrs? 368 (p6) br.cond.dpnt.few 8f // can't find existing fptr 369 ld8 r20=[r17] // read function from fptr 370 ;; 371 cmp.eq p6,p0=r16,r20 // same function? 372 ;; 373 (p6) st8 [r15]=r17 // reuse fptr 374 (p6) br.cond.sptk.few 3b // done 375 add r17=16,r17 // next fptr 376 br.cond.sptk.few 7b 377 378 8: // allocate new fptr 379 mov r8=1 // failure return value 380 cmp.geu p6,p0=r2,r3 // space left? 381 (p6) br.cond.dpnt.few 9f // bail out 382 383 st8 [r15]=r2 // install fptr 384 st8 [r2]=r16,8 // write fptr address 385 ;; 386 st8 [r2]=gp,8 // write fptr gp 387 br.cond.sptk.few 3b 388 389 9: 390 mov ar.pfs=loc0 391 mov rp=loc1 392 ;; 393 br.ret.sptk.few rp 394 395 END(_reloc)*/ 396 397 .data 398 .align 16 399 .global fptr_storage 400 fptr_storage: 401 .space 4096*16 // XXX 402 fptr_storage_end: 403