1/* $NetBSD: locore.S,v 1.9 2018/11/20 20:36:24 scole 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 42kstack: .space KSTACK_PAGES * PAGE_SIZE 43 .global kstack_top 44kstack_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 */ 53ENTRY_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 */ 1381: br.cond.sptk.few 1b 139END(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 153ENTRY_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 ;; 1981: 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 2112: 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 */ 2489: 249{ .mfb 250 nop 0 251 nop 0 252 br.sptk 9b 253 ;; 254} 255END(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 ;; 2731: 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 3042: 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 3443: 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 3504: 351 add r16=in0,r17 // BD + A 352 ;; 353 st8 [r15]=r16 // word64 (LSB) 354 br.cond.sptk.few 3b 355 3565: 357 add r16=r16,r17 // S + A 358 ;; 359 st8 [r15]=r16 // word64 (LSB) 360 br.cond.sptk.few 3b 361 3626: 363 movl r17=@gprel(fptr_storage) 364 ;; 365 add r17=r17,gp // start of fptrs 366 ;; 3677: 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 3788: // 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 3899: 390 mov ar.pfs=loc0 391 mov rp=loc1 392 ;; 393 br.ret.sptk.few rp 394 395END(_reloc)*/ 396 397 .data 398 .align 16 399 .global fptr_storage 400fptr_storage: 401 .space 4096*16 // XXX 402fptr_storage_end: 403