]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - sys/ia64/ia64/locore.S
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / sys / ia64 / ia64 / locore.S
1 /*-
2  * Copyright (c) 2001-2011 Marcel Moolenaar
3  * Copyright (c) 1998 Doug Rabson
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
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.
14  *
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
25  * SUCH DAMAGE.
26  *
27  * $FreeBSD$
28  */
29
30 #include <machine/asm.h>
31 #include <machine/ia64_cpu.h>
32 #include <machine/intrcnt.h>
33 #include <machine/pte.h>
34 #include <assym.s>
35
36 /*
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.
39  */
40 #define FW_STACK_SIZE   3*PAGE_SIZE
41
42         .section .ivt.data, "aw"
43         .align  PAGE_SIZE
44         .global kstack
45 kstack: .space  FW_STACK_SIZE
46         .global kstack_top
47 kstack_top:
48
49         .text
50
51 /*
52  * Not really a leaf but we can't return.
53  * The EFI loader passes the physical address of the bootinfo block in
54  * register r8.
55  */
56 ENTRY_NOPROFILE(__start, 1)
57         .prologue
58         .save   rp,r0
59         .body
60 {       .mlx
61         mov     ar.rsc=0
62         movl    r16=ia64_vector_table   // set up IVT early
63         ;;
64 }
65 {       .mlx
66         mov     cr.iva=r16
67         movl    r16=kstack
68         ;;
69 }
70 {       .mmi
71         srlz.i
72         ;;
73         ssm     IA64_PSR_DFH
74         mov     r17=FW_STACK_SIZE-16
75         ;;
76 }
77 {       .mlx
78         add     sp=r16,r17              // proc0's stack
79         movl    gp=__gp                 // find kernel globals
80         ;;
81 }
82 {       .mlx
83         mov     ar.bspstore=r16         // switch backing store
84         movl    r16=bootinfo
85         ;;
86 }
87 {       .mmi
88         st8     [r16]=r8                // save the PA of the bootinfo block
89         loadrs                          // invalidate regs
90         mov     r17=IA64_DCR_DEFAULT
91         ;;
92 }
93 {       .mmi
94         mov     cr.dcr=r17
95         mov     ar.rsc=3                // turn rse back on
96         nop     0
97         ;;
98 }
99 {       .mmi
100         srlz.d
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
104 }
105 {       .mib
106         nop     0
107         nop     0
108         br.call.sptk.many rp=_reloc
109         ;;
110 }
111 {       .mib
112         nop     0
113         nop     0
114         br.call.sptk.many rp=ia64_init
115         ;;
116 }
117         // We have the new bspstore in r8 and the new sp in r9.
118         // Switch onto the new stack and call mi_startup().
119 {       .mmi
120         mov     ar.rsc = 0
121         ;;
122         mov     ar.bspstore = r8
123         mov     sp = r9
124         ;;
125 }
126 {       .mmi
127         loadrs
128         ;;
129         mov     ar.rsc = 3
130         nop     0
131         ;;
132 }
133 {       .mib
134         nop     0
135         nop     0
136         br.call.sptk.many rp=mi_startup
137         ;;
138 }
139         /* NOTREACHED */
140 1:      br.cond.sptk.few 1b
141 END(__start)
142
143 /*
144  * fork_trampoline()
145  *
146  * Arrange for a function to be invoked neatly, after a cpu_switch().
147  *
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.
151  *
152  * The callout function and its argument is in the trapframe in scratch
153  * registers r2 and r3.
154  */
155 ENTRY(fork_trampoline, 0)
156         .prologue
157         .save   rp,r0
158         .body
159 {       .mmi
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
163         ;;
164 }
165 {       .mmi
166         ld8             out0=[r15]
167         ld8             out1=[r16]
168         nop             0
169 }
170 {       .mib
171         add             out2=16,sp
172         nop             0
173         br.call.sptk    rp=fork_exit
174         ;;
175 }
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
180 enter_userland:
181 {       .mib
182         nop             0
183         nop             0
184         br.sptk         epc_syscall_return
185         ;;
186 }
187 END(fork_trampoline)
188
189 /*
190  * Create a default interrupt name table. The first entry (vector 0) is
191  * hardwaired to the clock interrupt.
192  */
193         .data
194         .align 8
195 EXPORT(intrnames)
196         .ascii "clock"
197         .fill INTRNAME_LEN - 5 - 1, 1, ' '
198         .byte 0
199 intr_n = 1
200 .rept INTRCNT_COUNT - 1
201         .ascii "#"
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, ' '
206         .byte 0
207         intr_n = intr_n + 1
208 .endr
209 EXPORT(sintrnames)
210         data8 INTRCNT_COUNT * INTRNAME_LEN
211
212         .align 8
213 EXPORT(intrcnt)
214         .fill INTRCNT_COUNT, 8, 0
215 EXPORT(sintrcnt)
216         data8 INTRCNT_COUNT * 8
217
218         .text
219         // in0: image base
220 STATIC_ENTRY(_reloc, 1)
221         alloc   loc0=ar.pfs,1,2,0,0
222         mov     loc1=rp
223         ;; 
224         movl    r15=@gprel(_DYNAMIC)    // find _DYNAMIC etc.
225         movl    r2=@gprel(fptr_storage)
226         movl    r3=@gprel(fptr_storage_end)
227         ;;
228         add     r15=r15,gp              // relocate _DYNAMIC etc.
229         add     r2=r2,gp
230         add     r3=r3,gp
231         ;;
232 1:      ld8     r16=[r15],8             // read r15->d_tag
233         ;;
234         ld8     r17=[r15],8             // and r15->d_val
235         ;;
236         cmp.eq  p6,p0=DT_NULL,r16       // done?
237 (p6)    br.cond.dpnt.few 2f
238         ;; 
239         cmp.eq  p6,p0=DT_RELA,r16
240         ;; 
241 (p6)    add     r18=r17,in0             // found rela section
242         ;; 
243         cmp.eq  p6,p0=DT_RELASZ,r16
244         ;; 
245 (p6)    mov     r19=r17                 // found rela size
246         ;; 
247         cmp.eq  p6,p0=DT_SYMTAB,r16
248         ;; 
249 (p6)    add     r20=r17,in0             // found symbol table
250         ;; 
251 (p6)    setf.sig f8=r20
252         ;; 
253         cmp.eq  p6,p0=DT_SYMENT,r16
254         ;; 
255 (p6)    setf.sig f9=r17                 // found symbol entry size
256         ;; 
257         cmp.eq  p6,p0=DT_RELAENT,r16
258         ;; 
259 (p6)    mov     r22=r17                 // found rela entry size
260         ;;
261         br.sptk.few 1b
262         
263 2:      
264         ld8     r15=[r18],8             // read r_offset
265         ;; 
266         ld8     r16=[r18],8             // read r_info
267         add     r15=r15,in0             // relocate r_offset
268         ;;
269         ld8     r17=[r18],8             // read r_addend
270         sub     r19=r19,r22             // update relasz
271
272         extr.u  r23=r16,0,32            // ELF64_R_TYPE(r16)
273         ;;
274         cmp.eq  p6,p0=R_IA_64_NONE,r23
275 (p6)    br.cond.dpnt.few 3f
276         ;;
277         cmp.eq  p6,p0=R_IA_64_REL64LSB,r23
278 (p6)    br.cond.dptk.few 4f
279         ;;
280
281         extr.u  r16=r16,32,32           // ELF64_R_SYM(r16)
282         ;; 
283         setf.sig f10=r16                // so we can multiply
284         ;;
285         xma.lu  f10=f10,f9,f8           // f10=symtab + r_sym*syment
286         ;;
287         getf.sig r16=f10
288         ;;
289         add     r16=8,r16               // address of st_value
290         ;;
291         ld8     r16=[r16]               // read symbol value
292         ;;
293         add     r16=r16,in0             // relocate symbol value
294         ;;
295
296         cmp.eq  p6,p0=R_IA_64_DIR64LSB,r23
297 (p6)    br.cond.dptk.few 5f
298         ;;
299         cmp.eq  p6,p0=R_IA_64_FPTR64LSB,r23
300 (p6)    br.cond.dptk.few 6f
301         ;;
302
303 3:
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
308
309 4:
310         add     r16=in0,r17             // BD + A
311         ;;
312         st8     [r15]=r16               // word64 (LSB)
313         br.cond.sptk.few 3b
314
315 5:
316         add     r16=r16,r17             // S + A
317         ;;
318         st8     [r15]=r16               // word64 (LSB)
319         br.cond.sptk.few 3b
320
321 6:
322         movl    r17=@gprel(fptr_storage)
323         ;;
324         add     r17=r17,gp              // start of fptrs
325         ;;
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
329         ;;
330         cmp.eq  p6,p0=r16,r20           // same function?
331         ;;
332 (p6)    st8     [r15]=r17               // reuse fptr
333 (p6)    br.cond.sptk.few 3b             // done
334         add     r17=16,r17              // next fptr
335         br.cond.sptk.few 7b
336
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
341
342         st8     [r15]=r2                // install fptr
343         st8     [r2]=r16,8              // write fptr address
344         ;;
345         st8     [r2]=gp,8               // write fptr gp
346         br.cond.sptk.few 3b
347
348 9:
349         mov     ar.pfs=loc0
350         mov     rp=loc1
351         ;;
352         br.ret.sptk.few rp
353
354 END(_reloc)
355
356         .data
357         .align  16
358         .global fptr_storage
359 fptr_storage:
360         .space  4096*16                 // XXX
361 fptr_storage_end: