]> CyberLeo.Net >> Repos - FreeBSD/releng/8.0.git/blob - sys/ia64/ia64/locore.S
Adjust to reflect 8.0-RELEASE.
[FreeBSD/releng/8.0.git] / sys / ia64 / ia64 / locore.S
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$
27  */
28
29 #include <machine/asm.h>
30 #include <machine/ia64_cpu.h>
31 #include <machine/pte.h>
32 #include <sys/syscall.h>
33 #include <assym.s>
34
35 #ifndef EVCNT_COUNTERS
36 #define _LOCORE
37 #include <machine/intrcnt.h>
38 #endif
39
40         .section .data.proc0,"aw"
41         .global kstack
42         .align  PAGE_SIZE
43 kstack: .space KSTACK_PAGES * PAGE_SIZE
44
45         .text
46
47 /*
48  * Not really a leaf but we can't return.
49  * The EFI loader passes the physical address of the bootinfo block in
50  * register r8.
51  */
52 ENTRY_NOPROFILE(__start, 1)
53         .prologue
54         .save   rp,r0
55         .body
56 {       .mlx
57         mov     ar.rsc=0
58         movl    r16=ia64_vector_table   // set up IVT early
59         ;;
60 }
61 {       .mlx
62         mov     cr.iva=r16
63         movl    r16=kstack
64         ;;
65 }
66 {       .mmi
67         srlz.i
68         ;;
69         ssm     IA64_PSR_DFH
70         mov     r17=KSTACK_PAGES*PAGE_SIZE-SIZEOF_PCB-SIZEOF_TRAPFRAME-16
71         ;;
72 }
73 {       .mlx
74         add     sp=r16,r17              // proc0's stack
75         movl    gp=__gp                 // find kernel globals
76         ;;
77 }
78 {       .mlx
79         mov     ar.bspstore=r16         // switch backing store
80         movl    r16=pa_bootinfo
81         ;;
82 }
83 {       .mmi
84         st8     [r16]=r8                // save the PA of the bootinfo block
85         loadrs                          // invalidate regs
86         mov     r17=IA64_DCR_DEFAULT
87         ;;
88 }
89 {       .mmi
90         mov     cr.dcr=r17
91         mov     ar.rsc=3                // turn rse back on
92         nop     0
93         ;;
94 }
95 {       .mmi
96         srlz.d
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
100 }
101 {       .bbb
102         nop     0
103         nop     0
104         br.call.sptk.many rp=_reloc
105         ;;
106 }
107 {       .bbb
108         nop     0
109         nop     0
110         br.call.sptk.many rp=ia64_init
111         ;;
112 }
113         // We have the new bspstore in r8 and the new sp in r9.
114         // Switch onto the new stack and call mi_startup().
115 {
116         mov     ar.rsc = 0
117         ;;
118         mov     ar.bspstore = r8
119         mov     sp = r9
120         ;;
121 }
122 {
123         loadrs
124         ;;
125         mov     ar.rsc = 3
126         nop     0
127         ;;
128 }
129 {
130         nop     0
131         nop     0
132         br.call.sptk.many rp=mi_startup
133         ;;
134 }
135         /* NOTREACHED */
136 1:      br.cond.sptk.few 1b
137 END(__start)
138
139 /*
140  * fork_trampoline()
141  *
142  * Arrange for a function to be invoked neatly, after a cpu_switch().
143  *
144  * Invokes fork_exit() passing in three arguments: a callout function, an
145  * argument to the callout, and a trapframe pointer.  For child processes
146  * returning from fork(2), the argument is a pointer to the child process.
147  *
148  * The callout function and its argument is in the trapframe in scratch
149  * registers r2 and r3.
150  */
151 ENTRY(fork_trampoline, 0)
152         .prologue
153         .save   rp,r0
154         .body
155 {       .mmi
156         alloc           r14=ar.pfs,0,0,3,0
157         add             r15=32+SIZEOF_SPECIAL+8,sp
158         add             r16=32+SIZEOF_SPECIAL+16,sp
159         ;;
160 }
161 {       .mmi
162         ld8             out0=[r15]
163         ld8             out1=[r16]
164         nop             0
165 }
166 {       .mfb
167         add             out2=16,sp
168         nop             0
169         br.call.sptk    rp=fork_exit
170         ;;
171 }
172         // If we get back here, it means we're a user space process that's
173         // the immediate result of fork(2).
174         .global         enter_userland
175         .type           enter_userland, @function
176 enter_userland:
177 {       .mfb
178         nop             0
179         nop             0
180         br.sptk         epc_syscall_return
181         ;;
182 }
183 END(fork_trampoline)
184
185 #ifdef SMP
186 /*
187  * AP wake-up entry point. The handoff state is similar as for the BSP,
188  * as described on page 3-9 of the IPF SAL Specification. The difference
189  * lies in the contents of register b0. For APs this register holds the
190  * return address into the SAL rendezvous routine.
191  *
192  * Note that we're responsible for clearing the IRR bit by reading cr.ivr
193  * and issuing the EOI to the local SAPIC.
194  */
195         .align  32
196 ENTRY_NOPROFILE(os_boot_rendez,0)
197         mov     r16=cr.ivr      // clear IRR bit
198         ;;
199         srlz.d
200         mov     cr.eoi=r0       // ACK the wake-up
201         ;;
202         srlz.d
203         rsm     IA64_PSR_IC|IA64_PSR_I
204         ;;
205         mov     r16 = (5<<8)|(PAGE_SHIFT<<2)|1
206         movl    r17 = 5<<61
207         ;;
208         mov     rr[r17] = r16
209         ;;
210         srlz.d
211         mov     r16 = (6<<8)|(IA64_ID_PAGE_SHIFT<<2)
212         movl    r17 = 6<<61
213         ;;
214         mov     rr[r17] = r16
215         ;;
216         srlz.d
217         mov     r16 = (7<<8)|(IA64_ID_PAGE_SHIFT<<2)
218         movl    r17 = 7<<61
219         ;;
220         mov     rr[r17] = r16
221         ;;
222         srlz.d
223         mov     r18 = 28<<2
224         movl    r16 = PTE_PRESENT+PTE_MA_WB+PTE_ACCESSED+PTE_DIRTY+ \
225                         PTE_PL_KERN+PTE_AR_RWX+PTE_ED
226         ;;
227         mov     cr.ifa = r17
228         mov     cr.itir = r18
229         ptr.d   r17, r18
230         ptr.i   r17, r18
231         ;;
232         srlz.i
233         ;;
234         itr.d   dtr[r0] = r16
235         mov     r18 = IA64_DCR_DEFAULT
236         ;;
237         itr.i   itr[r0] = r16
238         mov     cr.dcr = r18
239         ;;
240         srlz.i
241         ;;
242 1:      mov     r16 = ip
243         add     r17 = 2f-1b, r17
244         movl    r18 = (IA64_PSR_AC|IA64_PSR_BN|IA64_PSR_DFH|IA64_PSR_DT|IA64_PSR_IC|IA64_PSR_IT|IA64_PSR_RT)
245         ;;
246         add     r17 = r17, r16
247         mov     cr.ipsr = r18
248         mov     cr.ifs = r0
249         ;;
250         mov     cr.iip = r17
251         ;;
252         rfi
253
254         .align  32
255 2:
256 {       .mlx
257         mov     ar.rsc = 0
258         movl    r16 = ia64_vector_table                 // set up IVT early
259         ;;
260 }
261 {       .mlx
262         mov     cr.iva = r16
263         movl    r16 = ap_stack
264         ;;
265 }
266 {       .mmi
267         srlz.i
268         ;;
269         ld8     r16 = [r16]
270         mov     r18 = KSTACK_PAGES*PAGE_SIZE-SIZEOF_PCB-SIZEOF_TRAPFRAME-16
271         ;;
272 }
273 {       .mlx
274         mov     ar.bspstore = r16
275         movl    gp = __gp
276         ;;
277 }
278 {       .mmi
279         loadrs
280         ;;
281         alloc   r17 = ar.pfs, 0, 0, 0, 0
282         add     sp = r18, r16
283         ;;
284 }
285 {       .mfb
286         mov     ar.rsc = 3
287         nop     0
288         br.call.sptk.few rp = ia64_ap_startup
289         ;;
290 }
291         /* NOT REACHED */
292 9:
293 {       .mfb
294         nop     0
295         nop     0
296         br.sptk 9b
297         ;;
298 }
299 END(os_boot_rendez)
300
301 #endif /* !SMP */
302
303 /*
304  * Create a default interrupt name table. The first entry (vector 0) is
305  * hardwaired to the clock interrupt.
306  */
307         .data
308         .align 8
309 EXPORT(intrnames)
310         .ascii "clock"
311         .fill INTRNAME_LEN - 5 - 1, 1, ' '
312         .byte 0
313 intr_n = 0
314 .rept INTRCNT_COUNT - 1
315         .ascii "#"
316         .byte intr_n / 100 + '0'
317         .byte (intr_n % 100) / 10 + '0'
318         .byte intr_n % 10 + '0'
319         .fill INTRNAME_LEN - 1 - 3 - 1, 1, ' '
320         .byte 0
321         intr_n = intr_n + 1
322 .endr
323 EXPORT(eintrnames)
324         .align 8
325 EXPORT(intrcnt)
326         .fill INTRCNT_COUNT, 8, 0
327 EXPORT(eintrcnt)
328
329         .text
330         // in0: image base
331 STATIC_ENTRY(_reloc, 1)
332         alloc   loc0=ar.pfs,1,2,0,0
333         mov     loc1=rp
334         ;; 
335         movl    r15=@gprel(_DYNAMIC)    // find _DYNAMIC etc.
336         movl    r2=@gprel(fptr_storage)
337         movl    r3=@gprel(fptr_storage_end)
338         ;;
339         add     r15=r15,gp              // relocate _DYNAMIC etc.
340         add     r2=r2,gp
341         add     r3=r3,gp
342         ;;
343 1:      ld8     r16=[r15],8             // read r15->d_tag
344         ;;
345         ld8     r17=[r15],8             // and r15->d_val
346         ;;
347         cmp.eq  p6,p0=DT_NULL,r16       // done?
348 (p6)    br.cond.dpnt.few 2f
349         ;; 
350         cmp.eq  p6,p0=DT_RELA,r16
351         ;; 
352 (p6)    add     r18=r17,in0             // found rela section
353         ;; 
354         cmp.eq  p6,p0=DT_RELASZ,r16
355         ;; 
356 (p6)    mov     r19=r17                 // found rela size
357         ;; 
358         cmp.eq  p6,p0=DT_SYMTAB,r16
359         ;; 
360 (p6)    add     r20=r17,in0             // found symbol table
361         ;; 
362 (p6)    setf.sig f8=r20
363         ;; 
364         cmp.eq  p6,p0=DT_SYMENT,r16
365         ;; 
366 (p6)    setf.sig f9=r17                 // found symbol entry size
367         ;; 
368         cmp.eq  p6,p0=DT_RELAENT,r16
369         ;; 
370 (p6)    mov     r22=r17                 // found rela entry size
371         ;;
372         br.sptk.few 1b
373         
374 2:      
375         ld8     r15=[r18],8             // read r_offset
376         ;; 
377         ld8     r16=[r18],8             // read r_info
378         add     r15=r15,in0             // relocate r_offset
379         ;;
380         ld8     r17=[r18],8             // read r_addend
381         sub     r19=r19,r22             // update relasz
382
383         extr.u  r23=r16,0,32            // ELF64_R_TYPE(r16)
384         ;;
385         cmp.eq  p6,p0=R_IA_64_NONE,r23
386 (p6)    br.cond.dpnt.few 3f
387         ;;
388         cmp.eq  p6,p0=R_IA_64_REL64LSB,r23
389 (p6)    br.cond.dptk.few 4f
390         ;;
391
392         extr.u  r16=r16,32,32           // ELF64_R_SYM(r16)
393         ;; 
394         setf.sig f10=r16                // so we can multiply
395         ;;
396         xma.lu  f10=f10,f9,f8           // f10=symtab + r_sym*syment
397         ;;
398         getf.sig r16=f10
399         ;;
400         add     r16=8,r16               // address of st_value
401         ;;
402         ld8     r16=[r16]               // read symbol value
403         ;;
404         add     r16=r16,in0             // relocate symbol value
405         ;;
406
407         cmp.eq  p6,p0=R_IA_64_DIR64LSB,r23
408 (p6)    br.cond.dptk.few 5f
409         ;;
410         cmp.eq  p6,p0=R_IA_64_FPTR64LSB,r23
411 (p6)    br.cond.dptk.few 6f
412         ;;
413
414 3:
415         cmp.ltu p6,p0=0,r19             // more?
416 (p6)    br.cond.dptk.few 2b             // loop
417         mov     r8=0                    // success return value
418         br.cond.sptk.few 9f             // done
419
420 4:
421         add     r16=in0,r17             // BD + A
422         ;;
423         st8     [r15]=r16               // word64 (LSB)
424         br.cond.sptk.few 3b
425
426 5:
427         add     r16=r16,r17             // S + A
428         ;;
429         st8     [r15]=r16               // word64 (LSB)
430         br.cond.sptk.few 3b
431
432 6:
433         movl    r17=@gprel(fptr_storage)
434         ;;
435         add     r17=r17,gp              // start of fptrs
436         ;;
437 7:      cmp.geu p6,p0=r17,r2            // end of fptrs?
438 (p6)    br.cond.dpnt.few 8f             // can't find existing fptr
439         ld8     r20=[r17]               // read function from fptr
440         ;;
441         cmp.eq  p6,p0=r16,r20           // same function?
442         ;;
443 (p6)    st8     [r15]=r17               // reuse fptr
444 (p6)    br.cond.sptk.few 3b             // done
445         add     r17=16,r17              // next fptr
446         br.cond.sptk.few 7b
447
448 8:                                      // allocate new fptr
449         mov     r8=1                    // failure return value
450         cmp.geu p6,p0=r2,r3             // space left?
451 (p6)    br.cond.dpnt.few 9f             // bail out
452
453         st8     [r15]=r2                // install fptr
454         st8     [r2]=r16,8              // write fptr address
455         ;;
456         st8     [r2]=gp,8               // write fptr gp
457         br.cond.sptk.few 3b
458
459 9:
460         mov     ar.pfs=loc0
461         mov     rp=loc1
462         ;;
463         br.ret.sptk.few rp
464
465 END(_reloc)
466
467         .data
468         .align  16
469         .global fptr_storage
470 fptr_storage:
471         .space  4096*16                 // XXX
472 fptr_storage_end: