1/*- 2 * Copyright (c) 2001-2011 Marcel Moolenaar 3 * Copyright (c) 1998 Doug Rabson 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * SUCH DAMAGE. 26 * 27 * $FreeBSD$ 28 */ 29 30#include <machine/asm.h> 31#include <machine/ia64_cpu.h> 32#include <machine/intrcnt.h> 33#include <machine/pte.h> 34#include <assym.s> 35 36/* 37 * The Altix 350 needs more than the architected 16KB (8KB for stack and 38 * 8KB for RSE backing store) when calling EFI to setup virtual mode. 39 */ 40#define FW_STACK_SIZE 3*PAGE_SIZE 41 42 .section .ivt.data, "aw" 43 .align PAGE_SIZE 44 .global kstack 45kstack: .space FW_STACK_SIZE 46 .global kstack_top 47kstack_top: 48 49 .text 50 51/* 52 * Not really a leaf but we can't return. 53 * The EFI loader passes the physical address of the bootinfo block in 54 * register r8. 55 */ 56ENTRY_NOPROFILE(__start, 1) 57 .prologue 58 .save rp,r0 59 .body 60{ .mlx 61 mov ar.rsc=0 62 movl r16=ia64_vector_table // set up IVT early 63 ;; 64} 65{ .mlx 66 mov cr.iva=r16 67 movl r16=kstack 68 ;; 69} 70{ .mmi 71 srlz.i 72 ;; 73 ssm IA64_PSR_DFH 74 mov r17=FW_STACK_SIZE-16 75 ;; 76} 77{ .mlx 78 add sp=r16,r17 // proc0's stack 79 movl gp=__gp // find kernel globals 80 ;; 81} 82{ .mlx 83 mov ar.bspstore=r16 // switch backing store 84 movl r16=bootinfo 85 ;; 86} 87{ .mmi 88 st8 [r16]=r8 // save the PA of the bootinfo block 89 loadrs // invalidate regs 90 mov r17=IA64_DCR_DEFAULT 91 ;; 92} 93{ .mmi 94 mov cr.dcr=r17 95 mov ar.rsc=3 // turn rse back on 96 nop 0 97 ;; 98} 99{ .mmi 100 srlz.d 101 alloc r16=ar.pfs,0,0,1,0 102 mov out0=r0 // we are linked at the right address 103 ;; // we just need to process fptrs 104} 105{ .mib 106 nop 0 107 nop 0 108 br.call.sptk.many rp=_reloc 109 ;; 110} 111{ .mib 112 nop 0 113 nop 0 114 br.call.sptk.many rp=ia64_init 115 ;; 116} 117 // We have the new bspstore in r8 and the new sp in r9. 118 // Switch onto the new stack and call mi_startup(). 119{ .mmi 120 mov ar.rsc = 0 121 ;; 122 mov ar.bspstore = r8 123 mov sp = r9 124 ;; 125} 126{ .mmi 127 loadrs 128 ;; 129 mov ar.rsc = 3 130 nop 0 131 ;; 132} 133{ .mib 134 nop 0 135 nop 0 136 br.call.sptk.many rp=mi_startup 137 ;; 138} 139 /* NOTREACHED */ 1401: br.cond.sptk.few 1b 141END(__start) 142 143/* 144 * fork_trampoline() 145 * 146 * Arrange for a function to be invoked neatly, after a cpu_switch(). 147 * 148 * Invokes fork_exit() passing in three arguments: a callout function, an 149 * argument to the callout, and a trapframe pointer. For child processes 150 * returning from fork(2), the argument is a pointer to the child process. 151 * 152 * The callout function and its argument is in the trapframe in scratch 153 * registers r2 and r3. 154 */ 155ENTRY(fork_trampoline, 0) 156 .prologue 157 .save rp,r0 158 .body 159{ .mmi 160 alloc r14=ar.pfs,0,0,3,0 161 add r15=32+SIZEOF_SPECIAL+8,sp 162 add r16=32+SIZEOF_SPECIAL+16,sp 163 ;; 164} 165{ .mmi 166 ld8 out0=[r15] 167 ld8 out1=[r16] 168 nop 0 169} 170{ .mib 171 add out2=16,sp 172 nop 0 173 br.call.sptk rp=fork_exit 174 ;; 175} 176 // If we get back here, it means we're a user space process that's 177 // the immediate result of fork(2). 178 .global enter_userland 179 .type enter_userland, @function 180enter_userland: 181{ .mib 182 nop 0 183 nop 0 184 br.sptk epc_syscall_return 185 ;; 186} 187END(fork_trampoline) 188 189/* 190 * Create a default interrupt name table. The first entry (vector 0) is 191 * hardwaired to the clock interrupt. 192 */ 193 .data 194 .align 8 195EXPORT(intrnames) 196 .ascii "clock" 197 .fill INTRNAME_LEN - 5 - 1, 1, ' ' 198 .byte 0 199intr_n = 1 200.rept INTRCNT_COUNT - 1 201 .ascii "#" 202 .byte intr_n / 100 + '0' 203 .byte (intr_n % 100) / 10 + '0' 204 .byte intr_n % 10 + '0' 205 .fill INTRNAME_LEN - 1 - 3 - 1, 1, ' ' 206 .byte 0 207 intr_n = intr_n + 1 208.endr 209EXPORT(sintrnames) 210 data8 INTRCNT_COUNT * INTRNAME_LEN 211 212 .align 8 213EXPORT(intrcnt) 214 .fill INTRCNT_COUNT, 8, 0 215EXPORT(sintrcnt) 216 data8 INTRCNT_COUNT * 8 217 218 .text 219 // in0: image base 220STATIC_ENTRY(_reloc, 1) 221 alloc loc0=ar.pfs,1,2,0,0 222 mov loc1=rp 223 ;; 224 movl r15=@gprel(_DYNAMIC) // find _DYNAMIC etc. 225 movl r2=@gprel(fptr_storage) 226 movl r3=@gprel(fptr_storage_end) 227 ;; 228 add r15=r15,gp // relocate _DYNAMIC etc. 229 add r2=r2,gp 230 add r3=r3,gp 231 ;; 2321: ld8 r16=[r15],8 // read r15->d_tag 233 ;; 234 ld8 r17=[r15],8 // and r15->d_val 235 ;; 236 cmp.eq p6,p0=DT_NULL,r16 // done? 237(p6) br.cond.dpnt.few 2f 238 ;; 239 cmp.eq p6,p0=DT_RELA,r16 240 ;; 241(p6) add r18=r17,in0 // found rela section 242 ;; 243 cmp.eq p6,p0=DT_RELASZ,r16 244 ;; 245(p6) mov r19=r17 // found rela size 246 ;; 247 cmp.eq p6,p0=DT_SYMTAB,r16 248 ;; 249(p6) add r20=r17,in0 // found symbol table 250 ;; 251(p6) setf.sig f8=r20 252 ;; 253 cmp.eq p6,p0=DT_SYMENT,r16 254 ;; 255(p6) setf.sig f9=r17 // found symbol entry size 256 ;; 257 cmp.eq p6,p0=DT_RELAENT,r16 258 ;; 259(p6) mov r22=r17 // found rela entry size 260 ;; 261 br.sptk.few 1b 262 2632: 264 ld8 r15=[r18],8 // read r_offset 265 ;; 266 ld8 r16=[r18],8 // read r_info 267 add r15=r15,in0 // relocate r_offset 268 ;; 269 ld8 r17=[r18],8 // read r_addend 270 sub r19=r19,r22 // update relasz 271 272 extr.u r23=r16,0,32 // ELF64_R_TYPE(r16) 273 ;; 274 cmp.eq p6,p0=R_IA_64_NONE,r23 275(p6) br.cond.dpnt.few 3f 276 ;; 277 cmp.eq p6,p0=R_IA_64_REL64LSB,r23 278(p6) br.cond.dptk.few 4f 279 ;; 280 281 extr.u r16=r16,32,32 // ELF64_R_SYM(r16) 282 ;; 283 setf.sig f10=r16 // so we can multiply 284 ;; 285 xma.lu f10=f10,f9,f8 // f10=symtab + r_sym*syment 286 ;; 287 getf.sig r16=f10 288 ;; 289 add r16=8,r16 // address of st_value 290 ;; 291 ld8 r16=[r16] // read symbol value 292 ;; 293 add r16=r16,in0 // relocate symbol value 294 ;; 295 296 cmp.eq p6,p0=R_IA_64_DIR64LSB,r23 297(p6) br.cond.dptk.few 5f 298 ;; 299 cmp.eq p6,p0=R_IA_64_FPTR64LSB,r23 300(p6) br.cond.dptk.few 6f 301 ;; 302 3033: 304 cmp.ltu p6,p0=0,r19 // more? 305(p6) br.cond.dptk.few 2b // loop 306 mov r8=0 // success return value 307 br.cond.sptk.few 9f // done 308 3094: 310 add r16=in0,r17 // BD + A 311 ;; 312 st8 [r15]=r16 // word64 (LSB) 313 br.cond.sptk.few 3b 314 3155: 316 add r16=r16,r17 // S + A 317 ;; 318 st8 [r15]=r16 // word64 (LSB) 319 br.cond.sptk.few 3b 320 3216: 322 movl r17=@gprel(fptr_storage) 323 ;; 324 add r17=r17,gp // start of fptrs 325 ;; 3267: cmp.geu p6,p0=r17,r2 // end of fptrs? 327(p6) br.cond.dpnt.few 8f // can't find existing fptr 328 ld8 r20=[r17] // read function from fptr 329 ;; 330 cmp.eq p6,p0=r16,r20 // same function? 331 ;; 332(p6) st8 [r15]=r17 // reuse fptr 333(p6) br.cond.sptk.few 3b // done 334 add r17=16,r17 // next fptr 335 br.cond.sptk.few 7b 336 3378: // allocate new fptr 338 mov r8=1 // failure return value 339 cmp.geu p6,p0=r2,r3 // space left? 340(p6) br.cond.dpnt.few 9f // bail out 341 342 st8 [r15]=r2 // install fptr 343 st8 [r2]=r16,8 // write fptr address 344 ;; 345 st8 [r2]=gp,8 // write fptr gp 346 br.cond.sptk.few 3b 347 3489: 349 mov ar.pfs=loc0 350 mov rp=loc1 351 ;; 352 br.ret.sptk.few rp 353 354END(_reloc) 355 356 .data 357 .align 16 358 .global fptr_storage 359fptr_storage: 360 .space 4096*16 // XXX 361fptr_storage_end: 362