Home | History | Annotate | Line # | Download | only in ia64
      1 /*	$NetBSD: locore.S,v 1.10 2023/10/06 11:45:16 skrll 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
     42 kstack:	.space KSTACK_PAGES * PAGE_SIZE
     43 	.global kstack_top
     44 kstack_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  */
     53 ENTRY_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 */
    138 1:	br.cond.sptk.few 1b
    139 END(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
    153 ENTRY_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 	;;
    198 1:	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
    211 2:
    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 */
    248 9:
    249 {	.mfb
    250 	nop	0
    251 	nop	0
    252 	br.sptk	9b
    253 	;;
    254 }
    255 END(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 	;;
    273 1:	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 
    304 2:
    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 
    344 3:
    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 
    350 4:
    351 	add	r16=in0,r17		// BD + A
    352 	;;
    353 	st8	[r15]=r16		// word64 (LSB)
    354 	br.cond.sptk.few 3b
    355 
    356 5:
    357 	add	r16=r16,r17		// S + A
    358 	;;
    359 	st8	[r15]=r16		// word64 (LSB)
    360 	br.cond.sptk.few 3b
    361 
    362 6:
    363 	movl	r17=@gprel(fptr_storage)
    364 	;;
    365 	add	r17=r17,gp		// start of fptrs
    366 	;;
    367 7:	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 
    378 8:					// 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 
    389 9:
    390 	mov	ar.pfs=loc0
    391 	mov	rp=loc1
    392 	;;
    393 	br.ret.sptk.few rp
    394 
    395 END(_reloc)*/
    396 
    397 	.data
    398 	.align	16
    399 	.global fptr_storage
    400 fptr_storage:
    401 	.space	4096*16			// XXX
    402 fptr_storage_end:
    403