xref: /netbsd/sys/arch/ia64/ia64/locore.S (revision 08a86671)
1/*	$NetBSD: locore.S,v 1.9 2018/11/20 20:36:24 scole 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
42kstack:	.space KSTACK_PAGES * PAGE_SIZE
43	.global kstack_top
44kstack_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 */
53ENTRY_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 */
1381:	br.cond.sptk.few 1b
139END(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
153ENTRY_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	;;
1981:	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
2112:
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 */
2489:
249{	.mfb
250	nop	0
251	nop	0
252	br.sptk	9b
253	;;
254}
255END(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	;;
2731:	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
3042:
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
3443:
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
3504:
351	add	r16=in0,r17		// BD + A
352	;;
353	st8	[r15]=r16		// word64 (LSB)
354	br.cond.sptk.few 3b
355
3565:
357	add	r16=r16,r17		// S + A
358	;;
359	st8	[r15]=r16		// word64 (LSB)
360	br.cond.sptk.few 3b
361
3626:
363	movl	r17=@gprel(fptr_storage)
364	;;
365	add	r17=r17,gp		// start of fptrs
366	;;
3677:	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
3788:					// 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
3899:
390	mov	ar.pfs=loc0
391	mov	rp=loc1
392	;;
393	br.ret.sptk.few rp
394
395END(_reloc)*/
396
397	.data
398	.align	16
399	.global fptr_storage
400fptr_storage:
401	.space	4096*16			// XXX
402fptr_storage_end:
403