1/* $NetBSD: locore.S,v 1.3 2009/07/20 04:41:37 kiyohara 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/ia64_cpu.h> 35#include <machine/pte.h> 36#include <machine/elf_machdep.h> 37#include <sys/syscall.h> 38 39#include <machine/intrcnt.h> 40 41#include "assym.h" 42 43 .section .data.proc0,"aw" 44 .global kstack 45 .align PAGE_SIZE 46kstack: .space KSTACK_PAGES * PAGE_SIZE 47 48 .text 49 50/* 51 * Not really a leaf but we can't return. 52 * The EFI loader passes the physical address of the bootinfo block in 53 * register r8. 54 */ 55ENTRY_NOPROFILE(start, 1) 56 .prologue 57 .save rp,r0 58 .body 59{ .mlx 60 mov ar.rsc=0 61 movl r16=ia64_vector_table // set up IVT early 62 ;; 63} 64{ .mlx 65 mov cr.iva=r16 66 movl r16=kstack 67 ;; 68} 69{ .mmi 70 srlz.i 71 ;; 72 ssm IA64_PSR_DFH 73 mov r17=KSTACK_PAGES*PAGE_SIZE-SIZEOF_PCB-SIZEOF_TRAPFRAME-16 74 ;; 75} 76{ .mlx 77 add sp=r16,r17 // proc0's stack 78 movl gp=__gp // find kernel globals 79 ;; 80} 81{ .mlx 82 mov ar.bspstore=r16 // switch backing store 83 movl r16=pa_bootinfo 84 ;; 85} 86 st8 [r16]=r8 // save the PA of the bootinfo block 87 loadrs // invalidate regs 88 ;; 89 mov ar.rsc=3 // turn rse back on 90 ;; 91 alloc r16=ar.pfs,0,0,1,0 92 ;; 93 movl out0=0 // we are linked at the right address 94 ;; // we just need to process fptrs 95// br.call.sptk.many rp=_reloc // XXX: Look into relocs 96 ;; 97 br.call.sptk.many rp=ia64_init 98 ;; 99 /* NOTREACHED */ 1001: br.cond.sptk.few 1b 101END(start) 102 103 104#ifdef MULTIPROCESSOR 105/* 106 * AP wake-up entry point. The handoff state is similar as for the BSP, 107 * as described on page 3-9 of the IPF SAL Specification. The difference 108 * lies in the contents of register b0. For APs this register holds the 109 * return address into the SAL rendezvous routine. 110 * 111 * Note that we're responsible for clearing the IRR bit by reading cr.ivr 112 * and issuing the EOI to the local SAPIC. 113 */ 114 .align 32 115ENTRY_NOPROFILE(os_boot_rendez,0) 116 mov r16=cr.ivr // clear IRR bit 117 ;; 118 srlz.d 119 mov cr.eoi=r0 // ACK the wake-up 120 ;; 121 srlz.d 122 rsm IA64_PSR_IC|IA64_PSR_I 123 ;; 124 mov r16 = (5<<8)|(PAGE_SHIFT<<2)|1 125 movl r17 = 5<<61 126 ;; 127 mov rr[r17] = r16 128 ;; 129 srlz.d 130 mov r16 = (6<<8)|(IA64_ID_PAGE_SHIFT<<2) 131 movl r17 = 6<<61 132 ;; 133 mov rr[r17] = r16 134 ;; 135 srlz.d 136 mov r16 = (7<<8)|(IA64_ID_PAGE_SHIFT<<2) 137 movl r17 = 7<<61 138 ;; 139 mov rr[r17] = r16 140 ;; 141 srlz.d 142 mov r16 = PTE_PRESENT+PTE_MA_WB+PTE_ACCESSED+PTE_DIRTY+ \ 143 PTE_PL_KERN+PTE_AR_RWX 144 mov r18 = 28<<2 145 ;; 146 147 mov cr.ifa = r17 148 mov cr.itir = r18 149 ptr.d r17, r18 150 ptr.i r17, r18 151 ;; 152 srlz.i 153 ;; 154 itr.d dtr[r0] = r16 155 ;; 156 itr.i itr[r0] = r16 157 ;; 158 srlz.i 159 ;; 1601: mov r16 = ip 161 add r17 = 2f-1b, r17 162 movl r18 = (IA64_PSR_AC|IA64_PSR_BN|IA64_PSR_DFH|IA64_PSR_DT|IA64_PSR_IC|IA64_PSR_IT|IA64_PSR_RT) 163 ;; 164 add r17 = r17, r16 165 mov cr.ipsr = r18 166 mov cr.ifs = r0 167 ;; 168 mov cr.iip = r17 169 ;; 170 rfi 171 172 .align 32 1732: 174{ .mlx 175 mov ar.rsc = 0 176 movl r16 = ia64_vector_table // set up IVT early 177 ;; 178} 179{ .mlx 180 mov cr.iva = r16 181 movl r16 = ap_stack 182 ;; 183} 184{ .mmi 185 srlz.i 186 ;; 187 ld8 r16 = [r16] 188 mov r18 = KSTACK_PAGES*PAGE_SIZE-SIZEOF_PCB-SIZEOF_TRAPFRAME-16 189 ;; 190} 191{ .mlx 192 mov ar.bspstore = r16 193 movl gp = __gp 194 ;; 195} 196{ .mmi 197 loadrs 198 ;; 199 alloc r17 = ar.pfs, 0, 0, 0, 0 200 add sp = r18, r16 201 ;; 202} 203{ .mfb 204 mov ar.rsc = 3 205 nop 0 206 br.call.sptk.few rp = ia64_ap_startup 207 ;; 208} 209 /* NOT REACHED */ 2109: 211{ .mfb 212 nop 0 213 nop 0 214 br.sptk 9b 215 ;; 216} 217END(os_boot_rendez) 218 219#endif /* MULTIPROCESSOR */ 220 221/* 222 * Create a default interrupt name table. The first entry (vector 0) is 223 * hardwaired to the clock interrupt. 224 */ 225 .data 226 .align 8 227EXPORT(intrnames) 228 .ascii "clock" 229 .fill INTRNAME_LEN - 5 - 1, 1, ' ' 230 .byte 0 231intr_n = 0 232.rept INTRCNT_COUNT - 1 233 .ascii "#" 234 .byte intr_n / 100 + '0' 235 .byte (intr_n % 100) / 10 + '0' 236 .byte intr_n % 10 + '0' 237 .fill INTRNAME_LEN - 1 - 3 - 1, 1, ' ' 238 .byte 0 239 intr_n = intr_n + 1 240.endr 241EXPORT(eintrnames) 242 .align 8 243EXPORT(intrcnt) 244 .fill INTRCNT_COUNT, 8, 0 245EXPORT(eintrcnt) 246 247 .text 248 // in0: image base 249/*STATIC_ENTRY(_reloc, 1) 250 alloc loc0=ar.pfs,1,2,0,0 251 mov loc1=rp 252 ;; 253 movl r15=@gprel(_DYNAMIC) // find _DYNAMIC etc. 254 movl r2=@gprel(fptr_storage) 255 movl r3=@gprel(fptr_storage_end) 256 ;; 257 add r15=r15,gp // relocate _DYNAMIC etc. 258 add r2=r2,gp 259 add r3=r3,gp 260 ;; 2611: ld8 r16=[r15],8 // read r15->d_tag 262 ;; 263 ld8 r17=[r15],8 // and r15->d_val 264 ;; 265 cmp.eq p6,p0=DT_NULL,r16 // done? 266(p6) br.cond.dpnt.few 2f 267 ;; 268 cmp.eq p6,p0=DT_RELA,r16 269 ;; 270(p6) add r18=r17,in0 // found rela section 271 ;; 272 cmp.eq p6,p0=DT_RELASZ,r16 273 ;; 274(p6) mov r19=r17 // found rela size 275 ;; 276 cmp.eq p6,p0=DT_SYMTAB,r16 277 ;; 278(p6) add r20=r17,in0 // found symbol table 279 ;; 280(p6) setf.sig f8=r20 281 ;; 282 cmp.eq p6,p0=DT_SYMENT,r16 283 ;; 284(p6) setf.sig f9=r17 // found symbol entry size 285 ;; 286 cmp.eq p6,p0=DT_RELAENT,r16 287 ;; 288(p6) mov r22=r17 // found rela entry size 289 ;; 290 br.sptk.few 1b 291 2922: 293 ld8 r15=[r18],8 // read r_offset 294 ;; 295 ld8 r16=[r18],8 // read r_info 296 add r15=r15,in0 // relocate r_offset 297 ;; 298 ld8 r17=[r18],8 // read r_addend 299 sub r19=r19,r22 // update relasz 300 301 extr.u r23=r16,0,32 // ELF64_R_TYPE(r16) 302 ;; 303 cmp.eq p6,p0=R_IA64_NONE,r23 304(p6) br.cond.dpnt.few 3f 305 ;; 306 cmp.eq p6,p0=R_IA64_REL64LSB,r23 307(p6) br.cond.dptk.few 4f 308 ;; 309 310 extr.u r16=r16,32,32 // ELF64_R_SYM(r16) 311 ;; 312 setf.sig f10=r16 // so we can multiply 313 ;; 314 xma.lu f10=f10,f9,f8 // f10=symtab + r_sym*syment 315 ;; 316 getf.sig r16=f10 317 ;; 318 add r16=8,r16 // address of st_value 319 ;; 320 ld8 r16=[r16] // read symbol value 321 ;; 322 add r16=r16,in0 // relocate symbol value 323 ;; 324 325 cmp.eq p6,p0=R_IA64_DIR64LSB,r23 326(p6) br.cond.dptk.few 5f 327 ;; 328 cmp.eq p6,p0=R_IA64_FPTR64LSB,r23 329(p6) br.cond.dptk.few 6f 330 ;; 331 3323: 333 cmp.ltu p6,p0=0,r19 // more? 334(p6) br.cond.dptk.few 2b // loop 335 mov r8=0 // success return value 336 br.cond.sptk.few 9f // done 337 3384: 339 add r16=in0,r17 // BD + A 340 ;; 341 st8 [r15]=r16 // word64 (LSB) 342 br.cond.sptk.few 3b 343 3445: 345 add r16=r16,r17 // S + A 346 ;; 347 st8 [r15]=r16 // word64 (LSB) 348 br.cond.sptk.few 3b 349 3506: 351 movl r17=@gprel(fptr_storage) 352 ;; 353 add r17=r17,gp // start of fptrs 354 ;; 3557: cmp.geu p6,p0=r17,r2 // end of fptrs? 356(p6) br.cond.dpnt.few 8f // can't find existing fptr 357 ld8 r20=[r17] // read function from fptr 358 ;; 359 cmp.eq p6,p0=r16,r20 // same function? 360 ;; 361(p6) st8 [r15]=r17 // reuse fptr 362(p6) br.cond.sptk.few 3b // done 363 add r17=16,r17 // next fptr 364 br.cond.sptk.few 7b 365 3668: // allocate new fptr 367 mov r8=1 // failure return value 368 cmp.geu p6,p0=r2,r3 // space left? 369(p6) br.cond.dpnt.few 9f // bail out 370 371 st8 [r15]=r2 // install fptr 372 st8 [r2]=r16,8 // write fptr address 373 ;; 374 st8 [r2]=gp,8 // write fptr gp 375 br.cond.sptk.few 3b 376 3779: 378 mov ar.pfs=loc0 379 mov rp=loc1 380 ;; 381 br.ret.sptk.few rp 382 383END(_reloc)*/ 384 385 .data 386 .align 16 387 .global fptr_storage 388fptr_storage: 389 .space 4096*16 // XXX 390fptr_storage_end: 391