2 * Copyright (c) 1998 Doug Rabson
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 #include <machine/asm.h>
30 #include <machine/ia64_cpu.h>
31 #include <machine/pte.h>
32 #include <sys/syscall.h>
35 #ifndef EVCNT_COUNTERS
37 #include <machine/intrcnt.h>
40 .section .data.proc0,"aw"
43 kstack: .space KSTACK_PAGES * PAGE_SIZE
48 * Not really a leaf but we can't return.
49 * The EFI loader passes the physical address of the bootinfo block in
52 ENTRY_NOPROFILE(__start, 1)
58 movl r16=ia64_vector_table // set up IVT early
70 mov r17=KSTACK_PAGES*PAGE_SIZE-SIZEOF_PCB-SIZEOF_TRAPFRAME-16
74 add sp=r16,r17 // proc0's stack
75 movl gp=__gp // find kernel globals
79 mov ar.bspstore=r16 // switch backing store
84 st8 [r16]=r8 // save the PA of the bootinfo block
85 loadrs // invalidate regs
86 mov r17=IA64_DCR_DEFAULT
91 mov ar.rsc=3 // turn rse back on
97 alloc r16=ar.pfs,0,0,1,0
98 mov out0=r0 // we are linked at the right address
99 ;; // we just need to process fptrs
104 br.call.sptk.many rp=_reloc
110 br.call.sptk.many rp=ia64_init
114 1: br.cond.sptk.few 1b
120 * Arrange for a function to be invoked neatly, after a cpu_switch().
122 * Invokes fork_exit() passing in three arguments: a callout function, an
123 * argument to the callout, and a trapframe pointer. For child processes
124 * returning from fork(2), the argument is a pointer to the child process.
126 * The callout function and its argument is in the trapframe in scratch
127 * registers r2 and r3.
129 ENTRY(fork_trampoline, 0)
134 alloc r14=ar.pfs,0,0,3,0
135 add r15=32+SIZEOF_SPECIAL+8,sp
136 add r16=32+SIZEOF_SPECIAL+16,sp
147 br.call.sptk rp=fork_exit
150 // If we get back here, it means we're a user space process that's
151 // the immediate result of fork(2).
152 .global enter_userland
153 .type enter_userland, @function
158 br.sptk epc_syscall_return
165 * AP wake-up entry point. The handoff state is similar as for the BSP,
166 * as described on page 3-9 of the IPF SAL Specification. The difference
167 * lies in the contents of register b0. For APs this register holds the
168 * return address into the SAL rendezvous routine.
170 * Note that we're responsible for clearing the IRR bit by reading cr.ivr
171 * and issuing the EOI to the local SAPIC.
174 ENTRY_NOPROFILE(os_boot_rendez,0)
175 mov r16=cr.ivr // clear IRR bit
178 mov cr.eoi=r0 // ACK the wake-up
181 rsm IA64_PSR_IC|IA64_PSR_I
183 mov r16 = (5<<8)|(PAGE_SHIFT<<2)|1
189 mov r16 = (6<<8)|(IA64_ID_PAGE_SHIFT<<2)
195 mov r16 = (7<<8)|(IA64_ID_PAGE_SHIFT<<2)
202 movl r16 = PTE_PRESENT+PTE_MA_WB+PTE_ACCESSED+PTE_DIRTY+ \
203 PTE_PL_KERN+PTE_AR_RWX+PTE_ED
213 mov r18 = IA64_DCR_DEFAULT
222 movl r18 = (IA64_PSR_AC|IA64_PSR_BN|IA64_PSR_DFH|IA64_PSR_DT|IA64_PSR_IC|IA64_PSR_IT|IA64_PSR_RT)
236 movl r16 = ia64_vector_table // set up IVT early
248 mov r18 = KSTACK_PAGES*PAGE_SIZE-SIZEOF_PCB-SIZEOF_TRAPFRAME-16
252 mov ar.bspstore = r16
259 alloc r17 = ar.pfs, 0, 0, 0, 0
266 br.call.sptk.few rp = ia64_ap_startup
282 * Create a default interrupt name table. The first entry (vector 0) is
283 * hardwaired to the clock interrupt.
289 .fill INTRNAME_LEN - 5 - 1, 1, ' '
292 .rept INTRCNT_COUNT - 1
294 .byte intr_n / 100 + '0'
295 .byte (intr_n % 100) / 10 + '0'
296 .byte intr_n % 10 + '0'
297 .fill INTRNAME_LEN - 1 - 3 - 1, 1, ' '
304 .fill INTRCNT_COUNT, 8, 0
309 STATIC_ENTRY(_reloc, 1)
310 alloc loc0=ar.pfs,1,2,0,0
313 movl r15=@gprel(_DYNAMIC) // find _DYNAMIC etc.
314 movl r2=@gprel(fptr_storage)
315 movl r3=@gprel(fptr_storage_end)
317 add r15=r15,gp // relocate _DYNAMIC etc.
321 1: ld8 r16=[r15],8 // read r15->d_tag
323 ld8 r17=[r15],8 // and r15->d_val
325 cmp.eq p6,p0=DT_NULL,r16 // done?
326 (p6) br.cond.dpnt.few 2f
328 cmp.eq p6,p0=DT_RELA,r16
330 (p6) add r18=r17,in0 // found rela section
332 cmp.eq p6,p0=DT_RELASZ,r16
334 (p6) mov r19=r17 // found rela size
336 cmp.eq p6,p0=DT_SYMTAB,r16
338 (p6) add r20=r17,in0 // found symbol table
342 cmp.eq p6,p0=DT_SYMENT,r16
344 (p6) setf.sig f9=r17 // found symbol entry size
346 cmp.eq p6,p0=DT_RELAENT,r16
348 (p6) mov r22=r17 // found rela entry size
353 ld8 r15=[r18],8 // read r_offset
355 ld8 r16=[r18],8 // read r_info
356 add r15=r15,in0 // relocate r_offset
358 ld8 r17=[r18],8 // read r_addend
359 sub r19=r19,r22 // update relasz
361 extr.u r23=r16,0,32 // ELF64_R_TYPE(r16)
363 cmp.eq p6,p0=R_IA_64_NONE,r23
364 (p6) br.cond.dpnt.few 3f
366 cmp.eq p6,p0=R_IA_64_REL64LSB,r23
367 (p6) br.cond.dptk.few 4f
370 extr.u r16=r16,32,32 // ELF64_R_SYM(r16)
372 setf.sig f10=r16 // so we can multiply
374 xma.lu f10=f10,f9,f8 // f10=symtab + r_sym*syment
378 add r16=8,r16 // address of st_value
380 ld8 r16=[r16] // read symbol value
382 add r16=r16,in0 // relocate symbol value
385 cmp.eq p6,p0=R_IA_64_DIR64LSB,r23
386 (p6) br.cond.dptk.few 5f
388 cmp.eq p6,p0=R_IA_64_FPTR64LSB,r23
389 (p6) br.cond.dptk.few 6f
393 cmp.ltu p6,p0=0,r19 // more?
394 (p6) br.cond.dptk.few 2b // loop
395 mov r8=0 // success return value
396 br.cond.sptk.few 9f // done
399 add r16=in0,r17 // BD + A
401 st8 [r15]=r16 // word64 (LSB)
405 add r16=r16,r17 // S + A
407 st8 [r15]=r16 // word64 (LSB)
411 movl r17=@gprel(fptr_storage)
413 add r17=r17,gp // start of fptrs
415 7: cmp.geu p6,p0=r17,r2 // end of fptrs?
416 (p6) br.cond.dpnt.few 8f // can't find existing fptr
417 ld8 r20=[r17] // read function from fptr
419 cmp.eq p6,p0=r16,r20 // same function?
421 (p6) st8 [r15]=r17 // reuse fptr
422 (p6) br.cond.sptk.few 3b // done
423 add r17=16,r17 // next fptr
426 8: // allocate new fptr
427 mov r8=1 // failure return value
428 cmp.geu p6,p0=r2,r3 // space left?
429 (p6) br.cond.dpnt.few 9f // bail out
431 st8 [r15]=r2 // install fptr
432 st8 [r2]=r16,8 // write fptr address
434 st8 [r2]=gp,8 // write fptr gp
449 .space 4096*16 // XXX