locore.S revision 93458
1/*-
2 * Copyright (c) 1998 Doug Rabson
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
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.
13 *
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
24 * SUCH DAMAGE.
25 *
26 * $FreeBSD: head/sys/ia64/ia64/locore.S 93458 2002-03-30 23:25:22Z marcel $
27 */
28/*
29 * Copyright (c) 1994, 1995, 1996 Carnegie-Mellon University.
30 * All rights reserved.
31 *
32 * Author: Chris G. Demetriou
33 *
34 * Permission to use, copy, modify and distribute this software and
35 * its documentation is hereby granted, provided that both the copyright
36 * notice and this permission notice appear in all copies of the
37 * software, derivative works or modified versions, and any portions
38 * thereof, and that both notices appear in supporting documentation.
39 *
40 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
41 * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
42 * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
43 *
44 * Carnegie Mellon requests users of this software to return to
45 *
46 *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
47 *  School of Computer Science
48 *  Carnegie Mellon University
49 *  Pittsburgh PA 15213-3890
50 *
51 * any improvements or extensions that they make and grant Carnegie the
52 * rights to redistribute these changes.
53 */
54
55#include <machine/asm.h>
56#include <machine/ia64_cpu.h>
57#include <machine/fpu.h>
58#include <machine/pte.h>
59#include <sys/syscall.h>
60#include <assym.s>
61
62#ifndef EVCNT_COUNTERS
63#define _LOCORE
64#include <machine/intrcnt.h>
65#endif
66
67	.section .data.proc0,"aw"
68	.global	kstack
69	.align	PAGE_SIZE
70kstack:	.space KSTACK_PAGES * PAGE_SIZE
71
72	.text
73
74/*
75 * Not really a leaf but we can't return.
76 * The EFI loader passes the physical address of the bootinfo block in
77 * register r8.
78 */
79ENTRY(__start, 1)
80	movl	r16=ia64_vector_table	// set up IVT early
81	;;
82	mov	cr.iva=r16
83	movl	r16=ia64_vhpt+(1<<8)+(15<<2)+1	// and VHPT
84	;;
85	mov	cr.pta=r16
86	movl	r16=kstack
87	;;
88	srlz.i
89	;;
90	mov	r17=KSTACK_PAGES*PAGE_SIZE-SIZEOF_PCB-SIZEOF_TRAPFRAME-16
91	movl	gp=__gp			// find kernel globals
92	;;
93	add	sp=r16,r17		// proc0's stack
94	mov	ar.rsc=0		// turn off rse
95	;;
96	mov	ar.bspstore=r16		// switch backing store
97	movl	r16=pa_bootinfo
98	;;
99	st8	[r16]=r8		// save the PA of the bootinfo block
100	loadrs				// invalidate regs
101	;;
102	mov	ar.rsc=3		// turn rse back on
103	;;
104	alloc	r16=ar.pfs,0,0,1,0
105	;;
106	movl	out0=0			// we are linked at the right address
107	;;				// we just need to process fptrs
108	br.call.sptk.many rp=_reloc
109	;;
110	br.call.sptk.many rp=ia64_init
111
112	/*
113	 * switch to thread0 and then initialise the rest of the kernel.
114	 */
115	alloc	r16=ar.pfs,0,0,1,0
116	;;
117	movl	out0=thread0
118	;;
119	add	out0=TD_PCB,out0
120	;;
121	ld8	out0=[out0]
122	;;
123	add	r16=PCB_B0,out0		// return to mi_startup_trampoline
124	movl	r17=mi_startup_trampoline
125	;;
126	st8	[r16]=r17
127	;;
128	br.call.sptk.many rp=restorectx
129
130	/* NOTREACHED */
131
132END(__start)
133
134
135ENTRY(mi_startup_trampoline, 0)
136	.prologue
137	.save	rp,r0
138	.body
139
140	br.call.sptk.many rp=mi_startup
141
142	// Should never happen
1431:	br.cond.sptk.few 1b
144
145END(mi_startup_trampoline)
146
147#ifdef SMP
148/*
149 * AP wake-up entry point. The handoff state is similar as for the BSP,
150 * as described on page 3-9 of the IPF SAL Specification. The difference
151 * lies in the contents of register b0. For APs this register holds the
152 * return address into the SAL rendezvous routine.
153 *
154 * Note that we're responsible for clearing the IRR bit by reading cr.ivr
155 * and issuing the EOI to the local SAPIC.
156 */
157	.align	32
158ENTRY(os_boot_rendez,0)
159	mov	r16=cr.ivr	// clear IRR bit
160	;;
161	srlz.d
162	mov	cr.eoi=r0	// ACK the wake-up
163	;;
164	srlz.d
165	rsm	IA64_PSR_IC|IA64_PSR_I
166	;;
167	mov	r16 = (5<<8)|(PAGE_SHIFT<<2)|1
168	movl	r17 = 5<<61
169	;;
170	mov	rr[r17] = r16
171	;;
172	srlz.d
173	mov	r16 = (6<<8)|(28<<2)
174	movl	r17 = 6<<61
175	;;
176	mov	rr[r17] = r16
177	;;
178	srlz.d
179	mov	r16 = (7<<8)|(28<<2)
180	movl	r17 = 7<<61
181	;;
182	mov	rr[r17] = r16
183	;;
184	srlz.d
185	mov	r16 = (PTE_P|PTE_MA_WB|PTE_A|PTE_D|PTE_PL_KERN|PTE_AR_RWX)
186	mov	r18 = 28<<2
187	;;
188
189	mov	cr.ifa = r17
190	mov	cr.itir = r18
191	ptr.d	r17, r18
192	ptr.i	r17, r18
193	;;
194	srlz.i
195	;;
196	itr.d	dtr[r0] = r16
197	;;
198	itr.i	itr[r0] = r16
199	;;
200	srlz.i
201	;;
2021:	mov	r16 = ip
203	add	r17 = 2f-1b, r17
204	movl	r18 = (IA64_PSR_AC|IA64_PSR_DT|IA64_PSR_RT|IA64_PSR_IT|IA64_PSR_BN)
205	;;
206	add	r17 = r17, r16
207	mov	cr.ipsr = r18
208	mov	cr.ifs = r0
209	;;
210	mov	cr.iip = r17
211	;;
212	rfi
213
214	.align	32
2152:	movl	r16 = ia64_vector_table			// set up IVT early
216	;;
217	mov	cr.iva = r16
218	;;
219	srlz.i
220	;;
221	movl	r16 = ap_stack
222	movl	r17 = ap_pcpu
223	mov	ar.rsc = 0
224	movl	gp = __gp
225	;;
226	ld8	r16 = [r16]
227	ld8	r17 = [r17]
228	mov	r18 = KSTACK_PAGES*PAGE_SIZE-SIZEOF_PCB-SIZEOF_TRAPFRAME-16
229	;;
230	add	sp = r18, r16
231	mov	ar.bspstore = r16
232	mov	ar.k4 = r17
233	mov	r13 = r17	/* gas doesn't know tp as an alias for r13 */
234	;;
235	loadrs
236	movl	r16 = ia64_pal_base
237	;;
238	mov	ar.rsc = 3
239	ld8	r16 = [r16]
240	;;
241	cmp.eq	p1, p0 = 0, r16
242(p1)	br.cond.spnt	1f
243	;;
244	mov	r18 = 28<<2
245	movl	r17 = 7<<61
246	;;
247	mov	cr.itir = r18
248	or	r17 = r17, r16
249	mov	r16 = (PTE_P|PTE_MA_WB|PTE_A|PTE_D|PTE_PL_KERN|PTE_AR_RWX)
250	;;
251	mov	cr.ifa = r17
252	extr.u  r18 = r17, 12, 38
253	;;
254	srlz.i
255	shl	r18 = r18, 12
256	;;
257	add	r17 = 1, r0
258	or	r16 = r16, r18
259	;;
260	itr.i	itr[r17] = r16
261	;;
262	srlz.i
263	;;
2641:	alloc	r16 = ar.pfs, 0, 0, 0, 0
265	;;
266	br.call.sptk.few rp = ia64_ap_startup
267	/* NOT REACHED */
2689:	br	9b
269END(os_boot_rendez)
270
271#endif /* !SMP */
272
273/**************************************************************************/
274
275/*
276 * Signal "trampoline" code. Invoked from RTE setup by sendsig().
277 *
278 * On entry, registers look like:
279 *
280 *      r14	signal number
281 *      r15	pointer to siginfo_t
282 *	r16	pointer to signal context frame (scp)
283 *      r17	address of handler function descriptor
284 *	r18	address of new backing store (if any)
285 *      sp+16	pointer to sigframe
286 */
287
288ENTRY(sigcode,0)
289	ld8	r8=[r17],8		// function address
290	;;
291	ld8	gp=[r17]		// function's gp value
292	mov	b6=r8			// transfer to a branch register
293	cover
294	;;
295	add	r8=UC_MCONTEXT_MC_AR_BSP,r16 // address or mc_ar_bsp
296	mov	r9=ar.bsp		// save ar.bsp
297	;;
298	st8	[r8]=r9
299	cmp.eq	p1,p2=r0,r18		// check for new bs
300(p1)	br.cond.sptk.few 1f		// branch if not switching
301	flushrs				// flush out to old bs
302	mov	ar.rsc=0		// switch off RSE
303	add	r8=UC_MCONTEXT_MC_AR_RNAT,r16 // address of mc_ar_rnat
304	;;
305	mov	r9=ar.rnat		// value of ar.rnat after flush
306	mov	ar.bspstore=r18		// point at new bs
307	;;
308	st8	[r8]=r9			// remember ar.rnat
309	mov	ar.rsc=15		// XXX bogus value - check
310	invala
311	;;
3121:	alloc	r5=ar.pfs,0,0,3,0	// register frame for call
313	;;
314	mov	out0=r14		// signal number
315	mov	out1=r15		// siginfo
316	mov	out2=r16		// ucontext
317	mov	r4=r16			// save from call
318	br.call.sptk.few rp=b6		// call the signal handler
319	;;
320	alloc	r14=ar.pfs,0,0,0,0	// discard call frame
321	;;
322	flushrs
323	;;
324(p1)	br.cond.sptk.few 2f		// note: p1 is preserved
325	mov	ar.rsc=0
326	add	r8=UC_MCONTEXT_MC_AR_RNAT,r4 // address of mc_ar_rnat
327	;;
328	ld8	r9=[r8]
329	;;
330	add	r8=UC_MCONTEXT_MC_AR_BSP,r4 // address of mc_ar_bsp
331	;;
332	ld8	r10=[r8]
333	;;
334	mov	ar.bspstore=r10
335	;;
336	mov	ar.rnat=r9
337	mov	ar.rsc=15
338	;;
3392:	CALLSYS_NOERROR(sigreturn)	// call sigreturn()
340	alloc	r14=ar.pfs,0,0,1,0 ;;
341	mov	out0=ret0		// if that failed, get error code
342	CALLSYS_NOERROR(exit)		// and call exit() with it.
343XENTRY(esigcode)
344	END(sigcode)
345
346	.data
347	EXPORT(szsigcode)
348	.quad	esigcode-sigcode
349	.text
350
351/* XXX: make systat/vmstat happy */
352	.data
353EXPORT(intrnames)
354	.asciz	"clock"
355intr_n = 0
356.rept INTRCNT_COUNT
357	.ascii "intr "
358	.byte intr_n / 10 + '0, intr_n % 10 + '0
359	.asciz "     "		/* space for platform-specific rewrite */
360	intr_n = intr_n + 1
361.endr
362EXPORT(eintrnames)
363	.align 8
364EXPORT(intrcnt)
365	.fill INTRCNT_COUNT + 1, 8, 0
366EXPORT(eintrcnt)
367	.text
368
369	// in0:	image base
370STATIC_ENTRY(_reloc, 1)
371	alloc	loc0=ar.pfs,1,2,0,0
372	mov	loc1=rp
373	;;
374	movl	r15=@gprel(_DYNAMIC)	// find _DYNAMIC etc.
375	movl	r2=@gprel(fptr_storage)
376	movl	r3=@gprel(fptr_storage_end)
377	;;
378	add	r15=r15,gp		// relocate _DYNAMIC etc.
379	add	r2=r2,gp
380	add	r3=r3,gp
381	;;
3821:	ld8	r16=[r15],8		// read r15->d_tag
383	;;
384	ld8	r17=[r15],8		// and r15->d_val
385	;;
386	cmp.eq	p6,p0=DT_NULL,r16	// done?
387(p6)	br.cond.dpnt.few 2f
388	;;
389	cmp.eq	p6,p0=DT_RELA,r16
390	;;
391(p6)	add	r18=r17,in0		// found rela section
392	;;
393	cmp.eq	p6,p0=DT_RELASZ,r16
394	;;
395(p6)	mov	r19=r17			// found rela size
396	;;
397	cmp.eq	p6,p0=DT_SYMTAB,r16
398	;;
399(p6)	add	r20=r17,in0		// found symbol table
400	;;
401(p6)	setf.sig f8=r20
402	;;
403	cmp.eq	p6,p0=DT_SYMENT,r16
404	;;
405(p6)	setf.sig f9=r17			// found symbol entry size
406	;;
407	cmp.eq	p6,p0=DT_RELAENT,r16
408	;;
409(p6)	mov	r22=r17			// found rela entry size
410	;;
411	br.sptk.few 1b
412
4132:
414	ld8	r15=[r18],8		// read r_offset
415	;;
416	ld8	r16=[r18],8		// read r_info
417	add	r15=r15,in0		// relocate r_offset
418	;;
419	ld8	r17=[r18],8		// read r_addend
420	sub	r19=r19,r22		// update relasz
421
422	extr.u	r23=r16,0,32		// ELF64_R_TYPE(r16)
423	;;
424	cmp.eq	p6,p0=R_IA64_NONE,r23
425(p6)	br.cond.dpnt.few 3f
426	;;
427	cmp.eq	p6,p0=R_IA64_DIR64LSB,r23
428	;;
429(p6)	br.cond.dptk.few 4f
430	;;
431	cmp.eq	p6,p0=R_IA64_FPTR64LSB,r23
432	;;
433(p6)	br.cond.dptk.few 5f
434	;;
435	cmp.eq	p6,p0=R_IA64_REL64LSB,r23
436	;;
437(p6)	br.cond.dptk.few 4f
438	;;
439
4403:	cmp.ltu	p6,p0=0,r19		// more?
441(p6)	br.cond.dptk.few 2b		// loop
442
443	mov	r8=0			// success return value
444	;;
445	br.cond.sptk.few 9f		// done
446
4474:
448	ld8	r16=[r15]		// read value
449	;;
450	add	r16=r16,in0		// relocate it
451	;;
452	st8	[r15]=r16		// and store it back
453	br.cond.sptk.few 3b
454
4555:
456	extr.u	r23=r16,32,32		// ELF64_R_SYM(r16)
457	;;
458	setf.sig f10=r23		// so we can multiply
459	;;
460	xma.lu	f10=f10,f9,f8		// f10=symtab + r_sym*syment
461	;;
462	getf.sig r16=f10
463	;;
464	add	r16=8,r16		// address of st_value
465	;;
466	ld8	r16=[r16]		// read symbol value
467	;;
468	add	r16=r16,in0		// relocate symbol value
469	;;
470	movl	r17=@gprel(fptr_storage)
471	;;
472	add	r17=r17,gp		// start of fptrs
473	;;
4746:	cmp.geu	p6,p0=r17,r2		// end of fptrs?
475(p6)	br.cond.dpnt.few 7f		// can't find existing fptr
476	ld8	r20=[r17]		// read function from fptr
477	;;
478	cmp.eq	p6,p0=r16,r20		// same function?
479	;;
480(p6)	st8	[r15]=r17		// reuse fptr
481(p6)	br.cond.sptk.few 3b		// done
482	add	r17=16,r17		// next fptr
483	br.cond.sptk.few 6b
484
4857:					// allocate new fptr
486	mov	r8=1			// failure return value
487	;;
488	cmp.geu	p6,p0=r2,r3		// space left?
489(p6)	br.cond.dpnt.few 9f		// bail out
490
491	st8	[r15]=r2		// install fptr
492	st8	[r2]=r16,8		// write fptr address
493	;;
494	st8	[r2]=gp,8		// write fptr gp
495	br.cond.sptk.few 3b
496
4979:
498	mov	ar.pfs=loc0
499	mov	rp=loc1
500	;;
501	br.ret.sptk.few rp
502
503END(_reloc)
504
505	.data
506	.align	16
507
508fptr_storage:
509	.space	4096*16			// XXX
510fptr_storage_end:
511