2 * Copyright (c) 2001-2011 Marcel Moolenaar
3 * Copyright (c) 1998 Doug Rabson
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
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.
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
30 #include <machine/asm.h>
31 #include <machine/ia64_cpu.h>
32 #include <machine/intrcnt.h>
33 #include <machine/pte.h>
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.
40 #define FW_STACK_SIZE 3*PAGE_SIZE
42 .section .ivt.data, "aw"
45 kstack: .space FW_STACK_SIZE
52 * Not really a leaf but we can't return.
53 * The EFI loader passes the physical address of the bootinfo block in
56 ENTRY_NOPROFILE(__start, 1)
62 movl r16=ia64_vector_table // set up IVT early
74 mov r17=FW_STACK_SIZE-16
78 add sp=r16,r17 // proc0's stack
79 movl gp=__gp // find kernel globals
83 mov ar.bspstore=r16 // switch backing store
88 st8 [r16]=r8 // save the PA of the bootinfo block
89 loadrs // invalidate regs
90 mov r17=IA64_DCR_DEFAULT
95 mov ar.rsc=3 // turn rse back on
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
108 br.call.sptk.many rp=_reloc
114 br.call.sptk.many rp=ia64_init
117 // We have the new bspstore in r8 and the new sp in r9.
118 // Switch onto the new stack and call mi_startup().
136 br.call.sptk.many rp=mi_startup
140 1: br.cond.sptk.few 1b
146 * Arrange for a function to be invoked neatly, after a cpu_switch().
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.
152 * The callout function and its argument is in the trapframe in scratch
153 * registers r2 and r3.
155 ENTRY(fork_trampoline, 0)
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
173 br.call.sptk rp=fork_exit
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
184 br.sptk epc_syscall_return
190 * Create a default interrupt name table. The first entry (vector 0) is
191 * hardwaired to the clock interrupt.
197 .fill INTRNAME_LEN - 5 - 1, 1, ' '
200 .rept INTRCNT_COUNT - 1
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, ' '
210 data8 INTRCNT_COUNT * INTRNAME_LEN
214 .fill INTRCNT_COUNT, 8, 0
216 data8 INTRCNT_COUNT * 8
220 STATIC_ENTRY(_reloc, 1)
221 alloc loc0=ar.pfs,1,2,0,0
224 movl r15=@gprel(_DYNAMIC) // find _DYNAMIC etc.
225 movl r2=@gprel(fptr_storage)
226 movl r3=@gprel(fptr_storage_end)
228 add r15=r15,gp // relocate _DYNAMIC etc.
232 1: ld8 r16=[r15],8 // read r15->d_tag
234 ld8 r17=[r15],8 // and r15->d_val
236 cmp.eq p6,p0=DT_NULL,r16 // done?
237 (p6) br.cond.dpnt.few 2f
239 cmp.eq p6,p0=DT_RELA,r16
241 (p6) add r18=r17,in0 // found rela section
243 cmp.eq p6,p0=DT_RELASZ,r16
245 (p6) mov r19=r17 // found rela size
247 cmp.eq p6,p0=DT_SYMTAB,r16
249 (p6) add r20=r17,in0 // found symbol table
253 cmp.eq p6,p0=DT_SYMENT,r16
255 (p6) setf.sig f9=r17 // found symbol entry size
257 cmp.eq p6,p0=DT_RELAENT,r16
259 (p6) mov r22=r17 // found rela entry size
264 ld8 r15=[r18],8 // read r_offset
266 ld8 r16=[r18],8 // read r_info
267 add r15=r15,in0 // relocate r_offset
269 ld8 r17=[r18],8 // read r_addend
270 sub r19=r19,r22 // update relasz
272 extr.u r23=r16,0,32 // ELF64_R_TYPE(r16)
274 cmp.eq p6,p0=R_IA_64_NONE,r23
275 (p6) br.cond.dpnt.few 3f
277 cmp.eq p6,p0=R_IA_64_REL64LSB,r23
278 (p6) br.cond.dptk.few 4f
281 extr.u r16=r16,32,32 // ELF64_R_SYM(r16)
283 setf.sig f10=r16 // so we can multiply
285 xma.lu f10=f10,f9,f8 // f10=symtab + r_sym*syment
289 add r16=8,r16 // address of st_value
291 ld8 r16=[r16] // read symbol value
293 add r16=r16,in0 // relocate symbol value
296 cmp.eq p6,p0=R_IA_64_DIR64LSB,r23
297 (p6) br.cond.dptk.few 5f
299 cmp.eq p6,p0=R_IA_64_FPTR64LSB,r23
300 (p6) br.cond.dptk.few 6f
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
310 add r16=in0,r17 // BD + A
312 st8 [r15]=r16 // word64 (LSB)
316 add r16=r16,r17 // S + A
318 st8 [r15]=r16 // word64 (LSB)
322 movl r17=@gprel(fptr_storage)
324 add r17=r17,gp // start of fptrs
326 7: 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
330 cmp.eq p6,p0=r16,r20 // same function?
332 (p6) st8 [r15]=r17 // reuse fptr
333 (p6) br.cond.sptk.few 3b // done
334 add r17=16,r17 // next fptr
337 8: // 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
342 st8 [r15]=r2 // install fptr
343 st8 [r2]=r16,8 // write fptr address
345 st8 [r2]=gp,8 // write fptr gp
360 .space 4096*16 // XXX