f9a462f588efee77bc0929b20343f0f1b7f199bc
[linux-flexiantxendom0-3.2.10.git] / arch / ia64 / kernel / entry.S
1 /*
2  * ia64/kernel/entry.S
3  *
4  * Kernel entry points.
5  *
6  * Copyright (C) 1998-2003 Hewlett-Packard Co
7  *      David Mosberger-Tang <davidm@hpl.hp.com>
8  * Copyright (C) 1999, 2002-2003
9  *      Asit Mallick <Asit.K.Mallick@intel.com>
10  *      Don Dugger <Don.Dugger@intel.com>
11  *      Suresh Siddha <suresh.b.siddha@intel.com>
12  *      Fenghua Yu <fenghua.yu@intel.com>
13  * Copyright (C) 1999 VA Linux Systems
14  * Copyright (C) 1999 Walt Drummond <drummond@valinux.com>
15  */
16 /*
17  * ia64_switch_to now places correct virtual mapping in in TR2 for
18  * kernel stack. This allows us to handle interrupts without changing
19  * to physical mode.
20  *
21  * Jonathan Nicklin     <nicklin@missioncriticallinux.com>
22  * Patrick O'Rourke     <orourke@missioncriticallinux.com>
23  * 11/07/2000
24  /
25 /*
26  * Global (preserved) predicate usage on syscall entry/exit path:
27  *
28  *      pKStk:          See entry.h.
29  *      pUStk:          See entry.h.
30  *      pSys:           See entry.h.
31  *      pNonSys:        !pSys
32  */
33
34 #include <linux/config.h>
35
36 #include <asm/asmmacro.h>
37 #include <asm/cache.h>
38 #include <asm/errno.h>
39 #include <asm/kregs.h>
40 #include <asm/offsets.h>
41 #include <asm/pgtable.h>
42 #include <asm/percpu.h>
43 #include <asm/processor.h>
44 #include <asm/thread_info.h>
45 #include <asm/unistd.h>
46
47 #include "minstate.h"
48
49         /*
50          * execve() is special because in case of success, we need to
51          * setup a null register window frame.
52          */
53 ENTRY(ia64_execve)
54         .prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(3)
55         alloc loc1=ar.pfs,3,2,4,0
56         mov loc0=rp
57         .body
58         mov out0=in0                    // filename
59         ;;                              // stop bit between alloc and call
60         mov out1=in1                    // argv
61         mov out2=in2                    // envp
62         add out3=16,sp                  // regs
63         br.call.sptk.many rp=sys_execve
64 .ret0:
65 #ifdef CONFIG_IA32_SUPPORT
66         /*
67          * Check if we're returning to ia32 mode. If so, we need to restore ia32 registers
68          * from pt_regs.
69          */
70         adds r16=PT(CR_IPSR)+16,sp
71         ;;
72         ld8 r16=[r16]
73 #endif
74         cmp4.ge p6,p7=r8,r0
75         mov ar.pfs=loc1                 // restore ar.pfs
76         sxt4 r8=r8                      // return 64-bit result
77         ;;
78         stf.spill [sp]=f0
79 (p6)    cmp.ne pKStk,pUStk=r0,r0        // a successful execve() lands us in user-mode...
80         mov rp=loc0
81 (p6)    mov ar.pfs=r0                   // clear ar.pfs on success
82 (p7)    br.ret.sptk.many rp
83
84         /*
85          * In theory, we'd have to zap this state only to prevent leaking of
86          * security sensitive state (e.g., if current->mm->dumpable is zero).  However,
87          * this executes in less than 20 cycles even on Itanium, so it's not worth
88          * optimizing for...).
89          */
90         mov ar.unat=0;          mov ar.lc=0
91         mov r4=0;               mov f2=f0;              mov b1=r0
92         mov r5=0;               mov f3=f0;              mov b2=r0
93         mov r6=0;               mov f4=f0;              mov b3=r0
94         mov r7=0;               mov f5=f0;              mov b4=r0
95         ldf.fill f12=[sp];      mov f13=f0;             mov b5=r0
96         ldf.fill f14=[sp];      ldf.fill f15=[sp];      mov f16=f0
97         ldf.fill f17=[sp];      ldf.fill f18=[sp];      mov f19=f0
98         ldf.fill f20=[sp];      ldf.fill f21=[sp];      mov f22=f0
99         ldf.fill f23=[sp];      ldf.fill f24=[sp];      mov f25=f0
100         ldf.fill f26=[sp];      ldf.fill f27=[sp];      mov f28=f0
101         ldf.fill f29=[sp];      ldf.fill f30=[sp];      mov f31=f0
102 #ifdef CONFIG_IA32_SUPPORT
103         tbit.nz p6,p0=r16, IA64_PSR_IS_BIT
104         movl loc0=ia64_ret_from_ia32_execve
105         ;;
106 (p6)    mov rp=loc0
107 #endif
108         br.ret.sptk.many rp
109 END(ia64_execve)
110
111 /*
112  * sys_clone2(u64 flags, u64 ustack_base, u64 ustack_size, u64 parent_tidptr, u64 child_tidptr,
113  *            u64 tls)
114  */
115 GLOBAL_ENTRY(sys_clone2)
116         .prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(6)
117         alloc r16=ar.pfs,6,2,6,0
118         DO_SAVE_SWITCH_STACK
119         adds r2=PT(R16)+IA64_SWITCH_STACK_SIZE+16,sp
120         mov loc0=rp
121         mov loc1=r16                            // save ar.pfs across do_fork
122         .body
123         mov out1=in1
124         mov out3=in2
125         tbit.nz p6,p0=in0,CLONE_SETTLS_BIT
126         mov out4=in3    // parent_tidptr: valid only w/CLONE_PARENT_SETTID
127         ;;
128 (p6)    st8 [r2]=in5                            // store TLS in r16 for copy_thread()
129         mov out5=in4    // child_tidptr:  valid only w/CLONE_CHILD_SETTID or CLONE_CHILD_CLEARTID
130         adds out2=IA64_SWITCH_STACK_SIZE+16,sp  // out2 = &regs
131         dep out0=0,in0,CLONE_IDLETASK_BIT,1     // out0 = clone_flags & ~CLONE_IDLETASK
132         br.call.sptk.many rp=do_fork
133 .ret1:  .restore sp
134         adds sp=IA64_SWITCH_STACK_SIZE,sp       // pop the switch stack
135         mov ar.pfs=loc1
136         mov rp=loc0
137         br.ret.sptk.many rp
138 END(sys_clone2)
139
140 /*
141  * sys_clone(u64 flags, u64 ustack_base, u64 parent_tidptr, u64 child_tidptr, u64 tls)
142  *      Deprecated.  Use sys_clone2() instead.
143  */
144 GLOBAL_ENTRY(sys_clone)
145         .prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(5)
146         alloc r16=ar.pfs,5,2,6,0
147         DO_SAVE_SWITCH_STACK
148         adds r2=PT(R16)+IA64_SWITCH_STACK_SIZE+16,sp
149         mov loc0=rp
150         mov loc1=r16                            // save ar.pfs across do_fork
151         .body
152         mov out1=in1
153         mov out3=16                             // stacksize (compensates for 16-byte scratch area)
154         tbit.nz p6,p0=in0,CLONE_SETTLS_BIT
155         mov out4=in2    // parent_tidptr: valid only w/CLONE_PARENT_SETTID
156         ;;
157 (p6)    st8 [r2]=in4                            // store TLS in r13 (tp)
158         mov out5=in3    // child_tidptr:  valid only w/CLONE_CHILD_SETTID or CLONE_CHILD_CLEARTID
159         adds out2=IA64_SWITCH_STACK_SIZE+16,sp  // out2 = &regs
160         dep out0=0,in0,CLONE_IDLETASK_BIT,1     // out0 = clone_flags & ~CLONE_IDLETASK
161         br.call.sptk.many rp=do_fork
162 .ret2:  .restore sp
163         adds sp=IA64_SWITCH_STACK_SIZE,sp       // pop the switch stack
164         mov ar.pfs=loc1
165         mov rp=loc0
166         br.ret.sptk.many rp
167 END(sys_clone)
168
169 /*
170  * prev_task <- ia64_switch_to(struct task_struct *next)
171  *      With Ingo's new scheduler, interrupts are disabled when this routine gets
172  *      called.  The code starting at .map relies on this.  The rest of the code
173  *      doesn't care about the interrupt masking status.
174  */
175 GLOBAL_ENTRY(ia64_switch_to)
176         .prologue
177         alloc r16=ar.pfs,1,0,0,0
178         DO_SAVE_SWITCH_STACK
179         .body
180
181         adds r22=IA64_TASK_THREAD_KSP_OFFSET,r13
182         mov r27=IA64_KR(CURRENT_STACK)
183         dep r20=0,in0,61,3              // physical address of "current"
184         ;;
185         st8 [r22]=sp                    // save kernel stack pointer of old task
186         shr.u r26=r20,IA64_GRANULE_SHIFT
187         adds r21=IA64_TASK_THREAD_KSP_OFFSET,in0
188         ;;
189         /*
190          * If we've already mapped this task's page, we can skip doing it again.
191          */
192         cmp.eq p7,p6=r26,r27
193 (p6)    br.cond.dpnt .map
194         ;;
195 .done:
196 (p6)    ssm psr.ic                      // if we we had to map, renable the psr.ic bit FIRST!!!
197         ;;
198 (p6)    srlz.d
199         ld8 sp=[r21]                    // load kernel stack pointer of new task
200         mov IA64_KR(CURRENT)=in0        // update "current" application register
201         mov r8=r13                      // return pointer to previously running task
202         mov r13=in0                     // set "current" pointer
203         ;;
204         DO_LOAD_SWITCH_STACK
205
206 #ifdef CONFIG_SMP
207         sync.i                          // ensure "fc"s done by this CPU are visible on other CPUs
208 #endif
209         br.ret.sptk.many rp             // boogie on out in new context
210
211 .map:
212         rsm psr.ic                      // interrupts (psr.i) are already disabled here
213         movl r25=PAGE_KERNEL
214         ;;
215         srlz.d
216         or r23=r25,r20                  // construct PA | page properties
217         mov r25=IA64_GRANULE_SHIFT<<2
218         ;;
219         mov cr.itir=r25
220         mov cr.ifa=in0                  // VA of next task...
221         ;;
222         mov r25=IA64_TR_CURRENT_STACK
223         mov IA64_KR(CURRENT_STACK)=r26  // remember last page we mapped...
224         ;;
225         itr.d dtr[r25]=r23              // wire in new mapping...
226         br.cond.sptk .done
227 END(ia64_switch_to)
228
229 /*
230  * Note that interrupts are enabled during save_switch_stack and load_switch_stack.  This
231  * means that we may get an interrupt with "sp" pointing to the new kernel stack while
232  * ar.bspstore is still pointing to the old kernel backing store area.  Since ar.rsc,
233  * ar.rnat, ar.bsp, and ar.bspstore are all preserved by interrupts, this is not a
234  * problem.  Also, we don't need to specify unwind information for preserved registers
235  * that are not modified in save_switch_stack as the right unwind information is already
236  * specified at the call-site of save_switch_stack.
237  */
238
239 /*
240  * save_switch_stack:
241  *      - r16 holds ar.pfs
242  *      - b7 holds address to return to
243  *      - rp (b0) holds return address to save
244  */
245 GLOBAL_ENTRY(save_switch_stack)
246         .prologue
247         .altrp b7
248         flushrs                 // flush dirty regs to backing store (must be first in insn group)
249         .save @priunat,r17
250         mov r17=ar.unat         // preserve caller's
251         .body
252 #ifdef CONFIG_ITANIUM
253         adds r2=16+128,sp
254         adds r3=16+64,sp
255         adds r14=SW(R4)+16,sp
256         ;;
257         st8.spill [r14]=r4,16           // spill r4
258         lfetch.fault.excl.nt1 [r3],128
259         ;;
260         lfetch.fault.excl.nt1 [r2],128
261         lfetch.fault.excl.nt1 [r3],128
262         ;;
263         lfetch.fault.excl [r2]
264         lfetch.fault.excl [r3]
265         adds r15=SW(R5)+16,sp
266 #else
267         add r2=16+3*128,sp
268         add r3=16,sp
269         add r14=SW(R4)+16,sp
270         ;;
271         st8.spill [r14]=r4,SW(R6)-SW(R4)        // spill r4 and prefetch offset 0x1c0
272         lfetch.fault.excl.nt1 [r3],128  //              prefetch offset 0x010
273         ;;
274         lfetch.fault.excl.nt1 [r3],128  //              prefetch offset 0x090
275         lfetch.fault.excl.nt1 [r2],128  //              prefetch offset 0x190
276         ;;
277         lfetch.fault.excl.nt1 [r3]      //              prefetch offset 0x110
278         lfetch.fault.excl.nt1 [r2]      //              prefetch offset 0x210
279         adds r15=SW(R5)+16,sp
280 #endif
281         ;;
282         st8.spill [r15]=r5,SW(R7)-SW(R5)        // spill r5
283         mov.m ar.rsc=0                  // put RSE in mode: enforced lazy, little endian, pl 0
284         add r2=SW(F2)+16,sp             // r2 = &sw->f2
285         ;;
286         st8.spill [r14]=r6,SW(B0)-SW(R6)        // spill r6
287         mov.m r18=ar.fpsr               // preserve fpsr
288         add r3=SW(F3)+16,sp             // r3 = &sw->f3
289         ;;
290         stf.spill [r2]=f2,32
291         mov.m r19=ar.rnat
292         mov r21=b0
293
294         stf.spill [r3]=f3,32
295         st8.spill [r15]=r7,SW(B2)-SW(R7)        // spill r7
296         mov r22=b1
297         ;;
298         // since we're done with the spills, read and save ar.unat:
299         mov.m r29=ar.unat
300         mov.m r20=ar.bspstore
301         mov r23=b2
302         stf.spill [r2]=f4,32
303         stf.spill [r3]=f5,32
304         mov r24=b3
305         ;;
306         st8 [r14]=r21,SW(B1)-SW(B0)             // save b0
307         st8 [r15]=r23,SW(B3)-SW(B2)             // save b2
308         mov r25=b4
309         mov r26=b5
310         ;;
311         st8 [r14]=r22,SW(B4)-SW(B1)             // save b1
312         st8 [r15]=r24,SW(AR_PFS)-SW(B3)         // save b3
313         mov r21=ar.lc           // I-unit
314         stf.spill [r2]=f12,32
315         stf.spill [r3]=f13,32
316         ;;
317         st8 [r14]=r25,SW(B5)-SW(B4)             // save b4
318         st8 [r15]=r16,SW(AR_LC)-SW(AR_PFS)      // save ar.pfs
319         stf.spill [r2]=f14,32
320         stf.spill [r3]=f15,32
321         ;;
322         st8 [r14]=r26                           // save b5
323         st8 [r15]=r21                           // save ar.lc
324         stf.spill [r2]=f16,32
325         stf.spill [r3]=f17,32
326         ;;
327         stf.spill [r2]=f18,32
328         stf.spill [r3]=f19,32
329         ;;
330         stf.spill [r2]=f20,32
331         stf.spill [r3]=f21,32
332         ;;
333         stf.spill [r2]=f22,32
334         stf.spill [r3]=f23,32
335         ;;
336         stf.spill [r2]=f24,32
337         stf.spill [r3]=f25,32
338         ;;
339         stf.spill [r2]=f26,32
340         stf.spill [r3]=f27,32
341         ;;
342         stf.spill [r2]=f28,32
343         stf.spill [r3]=f29,32
344         ;;
345         stf.spill [r2]=f30,SW(AR_UNAT)-SW(F30)
346         stf.spill [r3]=f31,SW(PR)-SW(F31)
347         add r14=SW(CALLER_UNAT)+16,sp
348         ;;
349         st8 [r2]=r29,SW(AR_RNAT)-SW(AR_UNAT)    // save ar.unat
350         st8 [r14]=r17,SW(AR_FPSR)-SW(CALLER_UNAT) // save caller_unat
351         mov r21=pr
352         ;;
353         st8 [r2]=r19,SW(AR_BSPSTORE)-SW(AR_RNAT) // save ar.rnat
354         st8 [r3]=r21                            // save predicate registers
355         ;;
356         st8 [r2]=r20                            // save ar.bspstore
357         st8 [r14]=r18                           // save fpsr
358         mov ar.rsc=3            // put RSE back into eager mode, pl 0
359         br.cond.sptk.many b7
360 END(save_switch_stack)
361
362 /*
363  * load_switch_stack:
364  *      - "invala" MUST be done at call site (normally in DO_LOAD_SWITCH_STACK)
365  *      - b7 holds address to return to
366  *      - must not touch r8-r11
367  */
368 ENTRY(load_switch_stack)
369         .prologue
370         .altrp b7
371
372         .body
373         lfetch.fault.nt1 [sp]
374         adds r2=SW(AR_BSPSTORE)+16,sp
375         adds r3=SW(AR_UNAT)+16,sp
376         mov ar.rsc=0                                            // put RSE into enforced lazy mode
377         adds r14=SW(CALLER_UNAT)+16,sp
378         adds r15=SW(AR_FPSR)+16,sp
379         ;;
380         ld8 r27=[r2],(SW(B0)-SW(AR_BSPSTORE))   // bspstore
381         ld8 r29=[r3],(SW(B1)-SW(AR_UNAT))       // unat
382         ;;
383         ld8 r21=[r2],16         // restore b0
384         ld8 r22=[r3],16         // restore b1
385         ;;
386         ld8 r23=[r2],16         // restore b2
387         ld8 r24=[r3],16         // restore b3
388         ;;
389         ld8 r25=[r2],16         // restore b4
390         ld8 r26=[r3],16         // restore b5
391         ;;
392         ld8 r16=[r2],(SW(PR)-SW(AR_PFS))        // ar.pfs
393         ld8 r17=[r3],(SW(AR_RNAT)-SW(AR_LC))    // ar.lc
394         ;;
395         ld8 r28=[r2]            // restore pr
396         ld8 r30=[r3]            // restore rnat
397         ;;
398         ld8 r18=[r14],16        // restore caller's unat
399         ld8 r19=[r15],24        // restore fpsr
400         ;;
401         ldf.fill f2=[r14],32
402         ldf.fill f3=[r15],32
403         ;;
404         ldf.fill f4=[r14],32
405         ldf.fill f5=[r15],32
406         ;;
407         ldf.fill f12=[r14],32
408         ldf.fill f13=[r15],32
409         ;;
410         ldf.fill f14=[r14],32
411         ldf.fill f15=[r15],32
412         ;;
413         ldf.fill f16=[r14],32
414         ldf.fill f17=[r15],32
415         ;;
416         ldf.fill f18=[r14],32
417         ldf.fill f19=[r15],32
418         mov b0=r21
419         ;;
420         ldf.fill f20=[r14],32
421         ldf.fill f21=[r15],32
422         mov b1=r22
423         ;;
424         ldf.fill f22=[r14],32
425         ldf.fill f23=[r15],32
426         mov b2=r23
427         ;;
428         mov ar.bspstore=r27
429         mov ar.unat=r29         // establish unat holding the NaT bits for r4-r7
430         mov b3=r24
431         ;;
432         ldf.fill f24=[r14],32
433         ldf.fill f25=[r15],32
434         mov b4=r25
435         ;;
436         ldf.fill f26=[r14],32
437         ldf.fill f27=[r15],32
438         mov b5=r26
439         ;;
440         ldf.fill f28=[r14],32
441         ldf.fill f29=[r15],32
442         mov ar.pfs=r16
443         ;;
444         ldf.fill f30=[r14],32
445         ldf.fill f31=[r15],24
446         mov ar.lc=r17
447         ;;
448         ld8.fill r4=[r14],16
449         ld8.fill r5=[r15],16
450         mov pr=r28,-1
451         ;;
452         ld8.fill r6=[r14],16
453         ld8.fill r7=[r15],16
454
455         mov ar.unat=r18                         // restore caller's unat
456         mov ar.rnat=r30                         // must restore after bspstore but before rsc!
457         mov ar.fpsr=r19                         // restore fpsr
458         mov ar.rsc=3                            // put RSE back into eager mode, pl 0
459         br.cond.sptk.many b7
460 END(load_switch_stack)
461
462 GLOBAL_ENTRY(__ia64_syscall)
463         .regstk 6,0,0,0
464         mov r15=in5                             // put syscall number in place
465         break __BREAK_SYSCALL
466         movl r2=errno
467         cmp.eq p6,p7=-1,r10
468         ;;
469 (p6)    st4 [r2]=r8
470 (p6)    mov r8=-1
471         br.ret.sptk.many rp
472 END(__ia64_syscall)
473
474 GLOBAL_ENTRY(execve)
475         mov r15=__NR_execve                     // put syscall number in place
476         break __BREAK_SYSCALL
477         br.ret.sptk.many rp
478 END(execve)
479
480 GLOBAL_ENTRY(clone)
481         mov r15=__NR_clone                      // put syscall number in place
482         break __BREAK_SYSCALL
483         br.ret.sptk.many rp
484 END(clone)
485
486         /*
487          * We invoke syscall_trace through this intermediate function to
488          * ensure that the syscall input arguments are not clobbered.  We
489          * also use it to preserve b6, which contains the syscall entry point.
490          */
491 GLOBAL_ENTRY(invoke_syscall_trace)
492         .prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(8)
493         alloc loc1=ar.pfs,8,3,0,0
494         mov loc0=rp
495         .body
496         mov loc2=b6
497         ;;
498         br.call.sptk.many rp=syscall_trace
499 .ret3:  mov rp=loc0
500         mov ar.pfs=loc1
501         mov b6=loc2
502         br.ret.sptk.many rp
503 END(invoke_syscall_trace)
504
505         /*
506          * Invoke a system call, but do some tracing before and after the call.
507          * We MUST preserve the current register frame throughout this routine
508          * because some system calls (such as ia64_execve) directly
509          * manipulate ar.pfs.
510          *
511          * Input:
512          *      r15 = syscall number
513          *      b6  = syscall entry point
514          */
515         .global ia64_strace_leave_kernel
516
517 GLOBAL_ENTRY(ia64_trace_syscall)
518         PT_REGS_UNWIND_INFO(0)
519 {       /*
520          * Some versions of gas generate bad unwind info if the first instruction of a
521          * procedure doesn't go into the first slot of a bundle.  This is a workaround.
522          */
523         nop.m 0
524         nop.i 0
525         br.call.sptk.many rp=invoke_syscall_trace // give parent a chance to catch syscall args
526 }
527 .ret6:  br.call.sptk.many rp=b6                 // do the syscall
528 strace_check_retval:
529         cmp.lt p6,p0=r8,r0                      // syscall failed?
530         adds r2=PT(R8)+16,sp                    // r2 = &pt_regs.r8
531         adds r3=PT(R10)+16,sp                   // r3 = &pt_regs.r10
532         mov r10=0
533 (p6)    br.cond.sptk strace_error               // syscall failed ->
534         ;;                                      // avoid RAW on r10
535 strace_save_retval:
536 .mem.offset 0,0; st8.spill [r2]=r8              // store return value in slot for r8
537 .mem.offset 8,0; st8.spill [r3]=r10             // clear error indication in slot for r10
538 ia64_strace_leave_kernel:
539         br.call.sptk.many rp=invoke_syscall_trace // give parent a chance to catch return value
540 .rety:  br.cond.sptk ia64_leave_syscall
541
542 strace_error:
543         ld8 r3=[r2]                             // load pt_regs.r8
544         sub r9=0,r8                             // negate return value to get errno value
545         ;;
546         cmp.ne p6,p0=r3,r0                      // is pt_regs.r8!=0?
547         adds r3=16,r2                           // r3=&pt_regs.r10
548         ;;
549 (p6)    mov r10=-1
550 (p6)    mov r8=r9
551         br.cond.sptk strace_save_retval
552 END(ia64_trace_syscall)
553
554 GLOBAL_ENTRY(ia64_ret_from_clone)
555         PT_REGS_UNWIND_INFO(0)
556 {       /*
557          * Some versions of gas generate bad unwind info if the first instruction of a
558          * procedure doesn't go into the first slot of a bundle.  This is a workaround.
559          */
560         nop.m 0
561         nop.i 0
562         /*
563          * We need to call schedule_tail() to complete the scheduling process.
564          * Called by ia64_switch_to() after do_fork()->copy_thread().  r8 contains the
565          * address of the previously executing task.
566          */
567         br.call.sptk.many rp=ia64_invoke_schedule_tail
568 }
569 .ret8:
570         adds r2=TI_FLAGS+IA64_TASK_SIZE,r13
571         ;;
572         ld4 r2=[r2]
573         ;;
574         mov r8=0
575         tbit.nz p6,p0=r2,TIF_SYSCALL_TRACE
576 (p6)    br.cond.spnt strace_check_retval
577         ;;                                      // added stop bits to prevent r8 dependency
578 END(ia64_ret_from_clone)
579         // fall through
580 GLOBAL_ENTRY(ia64_ret_from_syscall)
581         PT_REGS_UNWIND_INFO(0)
582         cmp.ge p6,p7=r8,r0                      // syscall executed successfully?
583         adds r2=PT(R8)+16,sp                    // r2 = &pt_regs.r8
584         adds r3=PT(R10)+16,sp                   // r3 = &pt_regs.r10
585         ;;
586 .mem.offset 0,0; (p6) st8.spill [r2]=r8 // store return value in slot for r8 and set unat bit
587 .mem.offset 8,0; (p6) st8.spill [r3]=r0 // clear error indication in slot for r10 and set unat bit
588 (p7)    br.cond.spnt handle_syscall_error       // handle potential syscall failure
589 END(ia64_ret_from_syscall)
590         // fall through
591 /*
592  * ia64_leave_syscall(): Same as ia64_leave_kernel, except that it doesn't
593  *      need to switch to bank 0 and doesn't restore the scratch registers.
594  *      To avoid leaking kernel bits, the scratch registers are set to
595  *      the following known-to-be-safe values:
596  *
597  *                r1: restored (global pointer)
598  *                r2: cleared
599  *                r3: 1 (when returning to user-level)
600  *            r8-r11: restored (syscall return value(s))
601  *               r12: restored (user-level stack pointer)
602  *               r13: restored (user-level thread pointer)
603  *               r14: cleared
604  *               r15: restored (syscall #)
605  *           r16-r19: cleared
606  *               r20: user-level ar.fpsr
607  *               r21: user-level b0
608  *               r22: user-level b6
609  *               r23: user-level ar.bspstore
610  *               r24: user-level ar.rnat
611  *               r25: user-level ar.unat
612  *               r26: user-level ar.pfs
613  *               r27: user-level ar.rsc
614  *               r28: user-level ip
615  *               r29: user-level psr
616  *               r30: user-level cfm
617  *               r31: user-level pr
618  *            f6-f11: cleared
619  *                pr: restored (user-level pr)
620  *                b0: restored (user-level rp)
621  *                b6: restored
622  *                b7: cleared
623  *           ar.unat: restored (user-level ar.unat)
624  *            ar.pfs: restored (user-level ar.pfs)
625  *            ar.rsc: restored (user-level ar.rsc)
626  *           ar.rnat: restored (user-level ar.rnat)
627  *       ar.bspstore: restored (user-level ar.bspstore)
628  *           ar.fpsr: restored (user-level ar.fpsr)
629  *            ar.ccv: cleared
630  *            ar.csd: cleared
631  *            ar.ssd: cleared
632  */
633 GLOBAL_ENTRY(ia64_leave_syscall)
634         PT_REGS_UNWIND_INFO(0)
635         /*
636          * work.need_resched etc. mustn't get changed by this CPU before it returns to
637          * user- or fsys-mode, hence we disable interrupts early on:
638          */
639 #ifdef CONFIG_PREEMPT
640         rsm psr.i                               // disable interrupts
641 #else
642 (pUStk) rsm psr.i
643 #endif
644         cmp.eq pLvSys,p0=r0,r0                  // pLvSys=1: leave from syscall
645 (pUStk) cmp.eq.unc p6,p0=r0,r0                  // p6 <- pUStk
646 .work_processed_syscall:
647 #ifdef CONFIG_PREEMPT
648 (pKStk) adds r20=TI_PRE_COUNT+IA64_TASK_SIZE,r13
649         ;;
650         .pred.rel.mutex pUStk,pKStk
651 (pKStk) ld4 r21=[r20]                   // r21 <- preempt_count
652 (pUStk) mov r21=0                       // r21 <- 0
653         ;;
654 (p6)    cmp.eq.unc p6,p0=r21,r0         // p6 <- p6 && (r21 == 0)
655 #endif /* CONFIG_PREEMPT */
656         adds r16=PT(LOADRS)+16,r12
657         adds r17=PT(AR_BSPSTORE)+16,r12
658         adds r18=TI_FLAGS+IA64_TASK_SIZE,r13
659         ;;
660 (p6)    ld4 r31=[r18]                           // load current_thread_info()->flags
661         ld8 r19=[r16],PT(B6)-PT(LOADRS)         // load ar.rsc value for "loadrs"
662         nop.i 0
663         ;;
664         ld8 r23=[r17],PT(R9)-PT(AR_BSPSTORE)    // load ar.bspstore (may be garbage)
665         ld8 r22=[r16],PT(R8)-PT(B6)             // load b6
666 (p6)    and r15=TIF_WORK_MASK,r31               // any work other than TIF_SYSCALL_TRACE?
667         ;;
668
669         mov.m ar.ccv=r0         // clear ar.ccv
670 (p6)    cmp4.ne.unc p6,p0=r15, r0               // any special work pending?
671 (p6)    br.cond.spnt .work_pending
672         ;;
673         // start restoring the state saved on the kernel stack (struct pt_regs):
674         ld8.fill r8=[r16],16
675         ld8.fill r9=[r17],16
676         mov f6=f0               // clear f6
677         ;;
678         ld8.fill r10=[r16],16
679         ld8.fill r11=[r17],16
680         mov f7=f0               // clear f7
681         ;;
682         ld8 r29=[r16],16        // load cr.ipsr
683         ld8 r28=[r17],16        // load cr.iip
684         mov f8=f0               // clear f8
685         ;;
686         ld8 r30=[r16],16        // load cr.ifs
687         ld8 r25=[r17],16        // load ar.unat
688         cmp.eq p9,p0=r0,r0      // set p9 to indicate that we should restore cr.ifs
689         ;;
690         rsm psr.i | psr.ic      // initiate turning off of interrupt and interruption collection
691         invala                  // invalidate ALAT
692         mov f9=f0               // clear f9
693
694         mov.m ar.ssd=r0         // clear ar.ssd
695         mov.m ar.csd=r0         // clear ar.csd
696         mov f10=f0              // clear f10
697         ;;
698         ld8 r26=[r16],16        // load ar.pfs
699         ld8 r27=[r17],PT(PR)-PT(AR_RSC) // load ar.rsc
700         mov f11=f0              // clear f11
701         ;;
702         ld8 r24=[r16],PT(B0)-PT(AR_RNAT)        // load ar.rnat (may be garbage)
703         ld8 r31=[r17],PT(R1)-PT(PR)             // load predicates
704 (pUStk) add r14=IA64_TASK_THREAD_ON_USTACK_OFFSET,r13
705         ;;
706         ld8 r21=[r16],PT(R12)-PT(B0) // load b0
707         ld8.fill r1=[r17],16    // load r1
708 (pUStk) mov r3=1
709         ;;
710         ld8.fill r12=[r16],16
711         ld8.fill r13=[r17],16
712         mov r2=r0               // clear r2
713         ;;
714         ld8 r20=[r16]           // load ar.fpsr
715         ld8.fill r15=[r17]      // load r15
716         mov b7=r0               // clear b7
717         ;;
718 (pUStk) st1 [r14]=r3
719         addl r17=THIS_CPU(ia64_phys_stacked_size_p8),r0
720         ;;
721         mov r16=ar.bsp          // get existing backing store pointer
722         srlz.i                  // ensure interruption collection is off
723         mov r14=r0              // clear r14
724         ;;
725         ld4 r17=[r17]           // r17 = cpu_data->phys_stacked_size_p8
726         mov b6=r22                              // restore b6
727         shr.u r18=r19,16        // get byte size of existing "dirty" partition
728 (pKStk) br.cond.dpnt.many skip_rbs_switch
729         br.cond.sptk.many rbs_switch
730 END(ia64_leave_syscall)
731
732 #ifdef CONFIG_IA32_SUPPORT
733 GLOBAL_ENTRY(ia64_ret_from_ia32_execve)
734         PT_REGS_UNWIND_INFO(0)
735         adds r2=PT(R8)+16,sp                    // r2 = &pt_regs.r8
736         adds r3=PT(R10)+16,sp                   // r3 = &pt_regs.r10
737         ;;
738         .mem.offset 0,0
739         st8.spill [r2]=r8       // store return value in slot for r8 and set unat bit
740         .mem.offset 8,0
741         st8.spill [r3]=r0       // clear error indication in slot for r10 and set unat bit
742 END(ia64_ret_from_ia32_execve_syscall)
743         // fall through
744 #endif /* CONFIG_IA32_SUPPORT */
745 GLOBAL_ENTRY(ia64_leave_kernel)
746         PT_REGS_UNWIND_INFO(0)
747         /*
748          * work.need_resched etc. mustn't get changed by this CPU before it returns to
749          * user- or fsys-mode, hence we disable interrupts early on:
750          */
751 #ifdef CONFIG_PREEMPT
752         rsm psr.i                               // disable interrupts
753 #else
754 (pUStk) rsm psr.i
755 #endif
756         cmp.eq p0,pLvSys=r0,r0                  // pLvSys=0: leave from kernel
757 (pUStk) cmp.eq.unc p6,p0=r0,r0                  // p6 <- pUStk
758         ;;
759 .work_processed_kernel:
760 #ifdef CONFIG_PREEMPT
761         adds r20=TI_PRE_COUNT+IA64_TASK_SIZE,r13
762         ;;
763         .pred.rel.mutex pUStk,pKStk
764 (pKStk) ld4 r21=[r20]                   // r21 <- preempt_count
765 (pUStk) mov r21=0                       // r21 <- 0
766         ;;
767 (p6)    cmp.eq.unc p6,p0=r21,r0         // p6 <- p6 && (r21 == 0)
768 #endif /* CONFIG_PREEMPT */
769         adds r17=TI_FLAGS+IA64_TASK_SIZE,r13
770         ;;
771 (p6)    ld4 r31=[r17]                           // load current_thread_info()->flags
772         adds r21=PT(PR)+16,r12
773         ;;
774
775         lfetch [r21],PT(CR_IPSR)-PT(PR)
776         adds r2=PT(B6)+16,r12
777         adds r3=PT(R16)+16,r12
778         ;;
779         lfetch [r21]
780         ld8 r28=[r2],8          // load b6
781         adds r29=PT(R24)+16,r12
782
783         ld8.fill r16=[r3],PT(AR_CSD)-PT(R16)
784         adds r30=PT(AR_CCV)+16,r12
785 (p6)    and r19=TIF_WORK_MASK,r31               // any work other than TIF_SYSCALL_TRACE?
786         ;;
787         ld8.fill r24=[r29]
788         ld8 r15=[r30]           // load ar.ccv
789 (p6)    cmp4.ne.unc p6,p0=r19, r0               // any special work pending?
790         ;;
791         ld8 r29=[r2],16         // load b7
792         ld8 r30=[r3],16         // load ar.csd
793 (p6)    br.cond.spnt .work_pending
794         ;;
795         ld8 r31=[r2],16         // load ar.ssd
796         ld8.fill r8=[r3],16
797         ;;
798         ld8.fill r9=[r2],16
799         ld8.fill r10=[r3],PT(R17)-PT(R10)
800         ;;
801         ld8.fill r11=[r2],PT(R18)-PT(R11)
802         ld8.fill r17=[r3],16
803         ;;
804         ld8.fill r18=[r2],16
805         ld8.fill r19=[r3],16
806         ;;
807         ld8.fill r20=[r2],16
808         ld8.fill r21=[r3],16
809         mov ar.csd=r30
810         mov ar.ssd=r31
811         ;;
812         rsm psr.i | psr.ic      // initiate turning off of interrupt and interruption collection
813         invala                  // invalidate ALAT
814         ;;
815         ld8.fill r22=[r2],24
816         ld8.fill r23=[r3],24
817         mov b6=r28
818         ;;
819         ld8.fill r25=[r2],16
820         ld8.fill r26=[r3],16
821         mov b7=r29
822         ;;
823         ld8.fill r27=[r2],16
824         ld8.fill r28=[r3],16
825         ;;
826         ld8.fill r29=[r2],16
827         ld8.fill r30=[r3],24
828         ;;
829         ld8.fill r31=[r2],PT(F9)-PT(R31)
830         adds r3=PT(F10)-PT(F6),r3
831         ;;
832         ldf.fill f9=[r2],PT(F6)-PT(F9)
833         ldf.fill f10=[r3],PT(F8)-PT(F10)
834         ;;
835         ldf.fill f6=[r2],PT(F7)-PT(F6)
836         ;;
837         ldf.fill f7=[r2],PT(F11)-PT(F7)
838         ldf.fill f8=[r3],32
839         ;;
840         srlz.i                  // ensure interruption collection is off
841         mov ar.ccv=r15
842         ;;
843         bsw.0                   // switch back to bank 0 (no stop bit required beforehand...)
844         ;;
845         ldf.fill f11=[r2]
846 (pUStk) mov r18=IA64_KR(CURRENT)        // Itanium 2: 12 cycle read latency
847         adds r16=PT(CR_IPSR)+16,r12
848         adds r17=PT(CR_IIP)+16,r12
849         ;;
850         ld8 r29=[r16],16        // load cr.ipsr
851         ld8 r28=[r17],16        // load cr.iip
852         ;;
853         ld8 r30=[r16],16        // load cr.ifs
854         ld8 r25=[r17],16        // load ar.unat
855         ;;
856         ld8 r26=[r16],16        // load ar.pfs
857         ld8 r27=[r17],16        // load ar.rsc
858         cmp.eq p9,p0=r0,r0      // set p9 to indicate that we should restore cr.ifs
859         ;;
860         ld8 r24=[r16],16        // load ar.rnat (may be garbage)
861         ld8 r23=[r17],16// load ar.bspstore (may be garbage)
862         ;;
863         ld8 r31=[r16],16        // load predicates
864         ld8 r21=[r17],16        // load b0
865         ;;
866         ld8 r19=[r16],16        // load ar.rsc value for "loadrs"
867         ld8.fill r1=[r17],16    // load r1
868         ;;
869         ld8.fill r12=[r16],16
870         ld8.fill r13=[r17],16
871 (pUStk) adds r18=IA64_TASK_THREAD_ON_USTACK_OFFSET,r18
872         ;;
873         ld8 r20=[r16],16        // ar.fpsr
874         ld8.fill r15=[r17],16
875         ;;
876         ld8.fill r14=[r16],16
877         ld8.fill r2=[r17]
878 (pUStk) mov r17=1
879         ;;
880         ld8.fill r3=[r16]
881 (pUStk) st1 [r18]=r17           // restore current->thread.on_ustack
882         shr.u r18=r19,16        // get byte size of existing "dirty" partition
883         ;;
884         mov r16=ar.bsp          // get existing backing store pointer
885         addl r17=THIS_CPU(ia64_phys_stacked_size_p8),r0
886         ;;
887         ld4 r17=[r17]           // r17 = cpu_data->phys_stacked_size_p8
888 (pKStk) br.cond.dpnt skip_rbs_switch
889
890         /*
891          * Restore user backing store.
892          *
893          * NOTE: alloc, loadrs, and cover can't be predicated.
894          */
895 (pNonSys) br.cond.dpnt dont_preserve_current_frame
896
897 rbs_switch:
898         cover                           // add current frame into dirty partition and set cr.ifs
899         ;;
900         mov r19=ar.bsp                  // get new backing store pointer
901         sub r16=r16,r18                 // krbs = old bsp - size of dirty partition
902         cmp.ne p9,p0=r0,r0              // clear p9 to skip restore of cr.ifs
903         ;;
904         sub r19=r19,r16                 // calculate total byte size of dirty partition
905         add r18=64,r18                  // don't force in0-in7 into memory...
906         ;;
907         shl r19=r19,16                  // shift size of dirty partition into loadrs position
908         ;;
909 dont_preserve_current_frame:
910         /*
911          * To prevent leaking bits between the kernel and user-space,
912          * we must clear the stacked registers in the "invalid" partition here.
913          * Not pretty, but at least it's fast (3.34 registers/cycle on Itanium,
914          * 5 registers/cycle on McKinley).
915          */
916 #       define pRecurse p6
917 #       define pReturn  p7
918 #ifdef CONFIG_ITANIUM
919 #       define Nregs    10
920 #else
921 #       define Nregs    14
922 #endif
923         alloc loc0=ar.pfs,2,Nregs-2,2,0
924         shr.u loc1=r18,9                // RNaTslots <= floor(dirtySize / (64*8))
925         sub r17=r17,r18                 // r17 = (physStackedSize + 8) - dirtySize
926         ;;
927         mov ar.rsc=r19                  // load ar.rsc to be used for "loadrs"
928         shladd in0=loc1,3,r17
929         mov in1=0
930         ;;
931 rse_clear_invalid:
932 #ifdef CONFIG_ITANIUM
933         // cycle 0
934  { .mii
935         alloc loc0=ar.pfs,2,Nregs-2,2,0
936         cmp.lt pRecurse,p0=Nregs*8,in0  // if more than Nregs regs left to clear, (re)curse
937         add out0=-Nregs*8,in0
938 }{ .mfb
939         add out1=1,in1                  // increment recursion count
940         nop.f 0
941         nop.b 0                         // can't do br.call here because of alloc (WAW on CFM)
942         ;;
943 }{ .mfi // cycle 1
944         mov loc1=0
945         nop.f 0
946         mov loc2=0
947 }{ .mib
948         mov loc3=0
949         mov loc4=0
950 (pRecurse) br.call.sptk.many b0=rse_clear_invalid
951
952 }{ .mfi // cycle 2
953         mov loc5=0
954         nop.f 0
955         cmp.ne pReturn,p0=r0,in1        // if recursion count != 0, we need to do a br.ret
956 }{ .mib
957         mov loc6=0
958         mov loc7=0
959 (pReturn) br.ret.sptk.many b0
960 }
961 #else /* !CONFIG_ITANIUM */
962         alloc loc0=ar.pfs,2,Nregs-2,2,0
963         cmp.lt pRecurse,p0=Nregs*8,in0  // if more than Nregs regs left to clear, (re)curse
964         add out0=-Nregs*8,in0
965         add out1=1,in1                  // increment recursion count
966         mov loc1=0
967         mov loc2=0
968         ;;
969         mov loc3=0
970         mov loc4=0
971         mov loc5=0
972         mov loc6=0
973         mov loc7=0
974 (pRecurse) br.call.sptk.few b0=rse_clear_invalid
975         ;;
976         mov loc8=0
977         mov loc9=0
978         cmp.ne pReturn,p0=r0,in1        // if recursion count != 0, we need to do a br.ret
979         mov loc10=0
980         mov loc11=0
981 (pReturn) br.ret.sptk.many b0
982 #endif /* !CONFIG_ITANIUM */
983 #       undef pRecurse
984 #       undef pReturn
985         ;;
986         alloc r17=ar.pfs,0,0,0,0        // drop current register frame
987         ;;
988         loadrs
989         ;;
990 skip_rbs_switch:
991 (pLvSys)        mov r19=r0              // clear r19 for leave_syscall, no-op otherwise
992         mov b0=r21
993         mov ar.pfs=r26
994 (pUStk) mov ar.bspstore=r23
995 (p9)    mov cr.ifs=r30
996 (pLvSys)mov r16=r0              // clear r16 for leave_syscall, no-op otherwise
997         mov cr.ipsr=r29
998         mov ar.fpsr=r20
999 (pLvSys)mov r17=r0              // clear r17 for leave_syscall, no-op otherwise
1000         mov cr.iip=r28
1001         ;;
1002 (pUStk) mov ar.rnat=r24         // must happen with RSE in lazy mode
1003 (pLvSys)mov r18=r0              // clear r18 for leave_syscall, no-op otherwise
1004         mov ar.rsc=r27
1005         mov ar.unat=r25
1006         mov pr=r31,-1
1007         rfi
1008
1009         /*
1010          * On entry:
1011          *      r20 = &current->thread_info->pre_count (if CONFIG_PREEMPT)
1012          *      r31 = current->thread_info->flags
1013          * On exit:
1014          *      p6 = TRUE if work-pending-check needs to be redone
1015          */
1016 .work_pending:
1017         tbit.z p6,p0=r31,TIF_NEED_RESCHED               // current_thread_info()->need_resched==0?
1018 (p6)    br.cond.sptk.few .notify
1019 #ifdef CONFIG_PREEMPT
1020 (pKStk) dep r21=-1,r0,PREEMPT_ACTIVE_BIT,1
1021         ;;
1022 (pKStk) st4 [r20]=r21
1023         ssm psr.i               // enable interrupts
1024 #endif
1025         br.call.spnt.many rp=schedule
1026 .ret9:  cmp.eq p6,p0=r0,r0                              // p6 <- 1
1027         rsm psr.i               // disable interrupts
1028         ;;
1029 #ifdef CONFIG_PREEMPT
1030 (pKStk) adds r20=TI_PRE_COUNT+IA64_TASK_SIZE,r13
1031         ;;
1032 (pKStk) st4 [r20]=r0            // preempt_count() <- 0
1033 #endif
1034 (pLvSys)br.cond.sptk.many .work_processed_syscall       // re-check
1035         br.cond.sptk.many .work_processed_kernel        // re-check
1036
1037 .notify:
1038         br.call.spnt.many rp=notify_resume_user
1039 .ret10: cmp.ne p6,p0=r0,r0                              // p6 <- 0
1040 (pLvSys)br.cond.sptk.many .work_processed_syscall       // don't re-check
1041         br.cond.sptk.many .work_processed_kernel        // don't re-check
1042 END(ia64_leave_kernel)
1043
1044 ENTRY(handle_syscall_error)
1045         /*
1046          * Some system calls (e.g., ptrace, mmap) can return arbitrary values which could
1047          * lead us to mistake a negative return value as a failed syscall.  Those syscall
1048          * must deposit a non-zero value in pt_regs.r8 to indicate an error.  If
1049          * pt_regs.r8 is zero, we assume that the call completed successfully.
1050          */
1051         PT_REGS_UNWIND_INFO(0)
1052         ld8 r3=[r2]             // load pt_regs.r8
1053         sub r9=0,r8             // negate return value to get errno
1054         ;;
1055         mov r10=-1              // return -1 in pt_regs.r10 to indicate error
1056         cmp.eq p6,p7=r3,r0      // is pt_regs.r8==0?
1057         adds r3=16,r2           // r3=&pt_regs.r10
1058         ;;
1059 (p6)    mov r9=r8
1060 (p6)    mov r10=0
1061         ;;
1062 .mem.offset 0,0; st8.spill [r2]=r9      // store errno in pt_regs.r8 and set unat bit
1063 .mem.offset 8,0; st8.spill [r3]=r10     // store error indication in pt_regs.r10 and set unat bit
1064         br.cond.sptk ia64_leave_syscall
1065 END(handle_syscall_error)
1066
1067         /*
1068          * Invoke schedule_tail(task) while preserving in0-in7, which may be needed
1069          * in case a system call gets restarted.
1070          */
1071 GLOBAL_ENTRY(ia64_invoke_schedule_tail)
1072         .prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(8)
1073         alloc loc1=ar.pfs,8,2,1,0
1074         mov loc0=rp
1075         mov out0=r8                             // Address of previous task
1076         ;;
1077         br.call.sptk.many rp=schedule_tail
1078 .ret11: mov ar.pfs=loc1
1079         mov rp=loc0
1080         br.ret.sptk.many rp
1081 END(ia64_invoke_schedule_tail)
1082
1083         /*
1084          * Setup stack and call do_notify_resume_user().  Note that pSys and pNonSys need to
1085          * be set up by the caller.  We declare 8 input registers so the system call
1086          * args get preserved, in case we need to restart a system call.
1087          */
1088 ENTRY(notify_resume_user)
1089         .prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(8)
1090         alloc loc1=ar.pfs,8,2,3,0 // preserve all eight input regs in case of syscall restart!
1091         mov r9=ar.unat
1092         mov loc0=rp                             // save return address
1093         mov out0=0                              // there is no "oldset"
1094         adds out1=8,sp                          // out1=&sigscratch->ar_pfs
1095 (pSys)  mov out2=1                              // out2==1 => we're in a syscall
1096         ;;
1097 (pNonSys) mov out2=0                            // out2==0 => not a syscall
1098         .fframe 16
1099         .spillpsp ar.unat, 16                   // (note that offset is relative to psp+0x10!)
1100         st8 [sp]=r9,-16                         // allocate space for ar.unat and save it
1101         st8 [out1]=loc1,-8                      // save ar.pfs, out1=&sigscratch
1102         .body
1103         br.call.sptk.many rp=do_notify_resume_user
1104 .ret15: .restore sp
1105         adds sp=16,sp                           // pop scratch stack space
1106         ;;
1107         ld8 r9=[sp]                             // load new unat from sigscratch->scratch_unat
1108         mov rp=loc0
1109         ;;
1110         mov ar.unat=r9
1111         mov ar.pfs=loc1
1112         br.ret.sptk.many rp
1113 END(notify_resume_user)
1114
1115 GLOBAL_ENTRY(sys_rt_sigsuspend)
1116         .prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(8)
1117         alloc loc1=ar.pfs,8,2,3,0 // preserve all eight input regs in case of syscall restart!
1118         mov r9=ar.unat
1119         mov loc0=rp                             // save return address
1120         mov out0=in0                            // mask
1121         mov out1=in1                            // sigsetsize
1122         adds out2=8,sp                          // out2=&sigscratch->ar_pfs
1123         ;;
1124         .fframe 16
1125         .spillpsp ar.unat, 16                   // (note that offset is relative to psp+0x10!)
1126         st8 [sp]=r9,-16                         // allocate space for ar.unat and save it
1127         st8 [out2]=loc1,-8                      // save ar.pfs, out2=&sigscratch
1128         .body
1129         br.call.sptk.many rp=ia64_rt_sigsuspend
1130 .ret17: .restore sp
1131         adds sp=16,sp                           // pop scratch stack space
1132         ;;
1133         ld8 r9=[sp]                             // load new unat from sw->caller_unat
1134         mov rp=loc0
1135         ;;
1136         mov ar.unat=r9
1137         mov ar.pfs=loc1
1138         br.ret.sptk.many rp
1139 END(sys_rt_sigsuspend)
1140
1141 ENTRY(sys_rt_sigreturn)
1142         PT_REGS_UNWIND_INFO(0)
1143         alloc r2=ar.pfs,0,0,1,0
1144         .prologue
1145         PT_REGS_SAVES(16)
1146         adds sp=-16,sp
1147         .body
1148         cmp.eq pNonSys,pSys=r0,r0               // sigreturn isn't a normal syscall...
1149         ;;
1150         /*
1151          * leave_kernel() restores f6-f11 from pt_regs, but since the streamlined
1152          * syscall-entry path does not save them we save them here instead.  Note: we
1153          * don't need to save any other registers that are not saved by the stream-lined
1154          * syscall path, because restore_sigcontext() restores them.
1155          */
1156         adds r16=PT(F6)+32,sp
1157         adds r17=PT(F7)+32,sp
1158         ;;
1159         stf.spill [r16]=f6,32
1160         stf.spill [r17]=f7,32
1161         ;;
1162         stf.spill [r16]=f8,32
1163         stf.spill [r17]=f9,32
1164         ;;
1165         stf.spill [r16]=f10
1166         stf.spill [r17]=f11
1167         adds out0=16,sp                         // out0 = &sigscratch
1168         br.call.sptk.many rp=ia64_rt_sigreturn
1169 .ret19: .restore sp 0
1170         adds sp=16,sp
1171         ;;
1172         ld8 r9=[sp]                             // load new ar.unat
1173         mov.sptk b7=r8,ia64_leave_kernel
1174         ;;
1175         mov ar.unat=r9
1176         br.many b7
1177 END(sys_rt_sigreturn)
1178
1179 GLOBAL_ENTRY(ia64_prepare_handle_unaligned)
1180         .prologue
1181         /*
1182          * r16 = fake ar.pfs, we simply need to make sure privilege is still 0
1183          */
1184         mov r16=r0
1185         DO_SAVE_SWITCH_STACK
1186         br.call.sptk.many rp=ia64_handle_unaligned      // stack frame setup in ivt
1187 .ret21: .body
1188         DO_LOAD_SWITCH_STACK
1189         br.cond.sptk.many rp                            // goes to ia64_leave_kernel
1190 END(ia64_prepare_handle_unaligned)
1191
1192         //
1193         // unw_init_running(void (*callback)(info, arg), void *arg)
1194         //
1195 #       define EXTRA_FRAME_SIZE ((UNW_FRAME_INFO_SIZE+15)&~15)
1196
1197 GLOBAL_ENTRY(unw_init_running)
1198         .prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(2)
1199         alloc loc1=ar.pfs,2,3,3,0
1200         ;;
1201         ld8 loc2=[in0],8
1202         mov loc0=rp
1203         mov r16=loc1
1204         DO_SAVE_SWITCH_STACK
1205         .body
1206
1207         .prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(2)
1208         .fframe IA64_SWITCH_STACK_SIZE+EXTRA_FRAME_SIZE
1209         SWITCH_STACK_SAVES(EXTRA_FRAME_SIZE)
1210         adds sp=-EXTRA_FRAME_SIZE,sp
1211         .body
1212         ;;
1213         adds out0=16,sp                         // &info
1214         mov out1=r13                            // current
1215         adds out2=16+EXTRA_FRAME_SIZE,sp        // &switch_stack
1216         br.call.sptk.many rp=unw_init_frame_info
1217 1:      adds out0=16,sp                         // &info
1218         mov b6=loc2
1219         mov loc2=gp                             // save gp across indirect function call
1220         ;;
1221         ld8 gp=[in0]
1222         mov out1=in1                            // arg
1223         br.call.sptk.many rp=b6                 // invoke the callback function
1224 1:      mov gp=loc2                             // restore gp
1225
1226         // For now, we don't allow changing registers from within
1227         // unw_init_running; if we ever want to allow that, we'd
1228         // have to do a load_switch_stack here:
1229         .restore sp
1230         adds sp=IA64_SWITCH_STACK_SIZE+EXTRA_FRAME_SIZE,sp
1231
1232         mov ar.pfs=loc1
1233         mov rp=loc0
1234         br.ret.sptk.many rp
1235 END(unw_init_running)
1236
1237         .rodata
1238         .align 8
1239         .globl sys_call_table
1240 sys_call_table:
1241         data8 sys_ni_syscall            //  This must be sys_ni_syscall!  See ivt.S.
1242         data8 sys_exit                          // 1025
1243         data8 sys_read
1244         data8 sys_write
1245         data8 sys_open
1246         data8 sys_close
1247         data8 sys_creat                         // 1030
1248         data8 sys_link
1249         data8 sys_unlink
1250         data8 ia64_execve
1251         data8 sys_chdir
1252         data8 sys_fchdir                        // 1035
1253         data8 sys_utimes
1254         data8 sys_mknod
1255         data8 sys_chmod
1256         data8 sys_chown
1257         data8 sys_lseek                         // 1040
1258         data8 sys_getpid
1259         data8 sys_getppid
1260         data8 sys_mount
1261         data8 sys_umount
1262         data8 sys_setuid                        // 1045
1263         data8 sys_getuid
1264         data8 sys_geteuid
1265         data8 sys_ptrace
1266         data8 sys_access
1267         data8 sys_sync                          // 1050
1268         data8 sys_fsync
1269         data8 sys_fdatasync
1270         data8 sys_kill
1271         data8 sys_rename
1272         data8 sys_mkdir                         // 1055
1273         data8 sys_rmdir
1274         data8 sys_dup
1275         data8 sys_pipe
1276         data8 sys_times
1277         data8 ia64_brk                          // 1060
1278         data8 sys_setgid
1279         data8 sys_getgid
1280         data8 sys_getegid
1281         data8 sys_acct
1282         data8 sys_ioctl                         // 1065
1283         data8 sys_fcntl
1284         data8 sys_umask
1285         data8 sys_chroot
1286         data8 sys_ustat
1287         data8 sys_dup2                          // 1070
1288         data8 sys_setreuid
1289         data8 sys_setregid
1290         data8 sys_getresuid
1291         data8 sys_setresuid
1292         data8 sys_getresgid                     // 1075
1293         data8 sys_setresgid
1294         data8 sys_getgroups
1295         data8 sys_setgroups
1296         data8 sys_getpgid
1297         data8 sys_setpgid                       // 1080
1298         data8 sys_setsid
1299         data8 sys_getsid
1300         data8 sys_sethostname
1301         data8 sys_setrlimit
1302         data8 sys_getrlimit                     // 1085
1303         data8 sys_getrusage
1304         data8 sys_gettimeofday
1305         data8 sys_settimeofday
1306         data8 sys_select
1307         data8 sys_poll                          // 1090
1308         data8 sys_symlink
1309         data8 sys_readlink
1310         data8 sys_uselib
1311         data8 sys_swapon
1312         data8 sys_swapoff                       // 1095
1313         data8 sys_reboot
1314         data8 sys_truncate
1315         data8 sys_ftruncate
1316         data8 sys_fchmod
1317         data8 sys_fchown                        // 1100
1318         data8 ia64_getpriority
1319         data8 sys_setpriority
1320         data8 sys_statfs
1321         data8 sys_fstatfs
1322         data8 sys_gettid                        // 1105
1323         data8 sys_semget
1324         data8 sys_semop
1325         data8 sys_semctl
1326         data8 sys_msgget
1327         data8 sys_msgsnd                        // 1110
1328         data8 sys_msgrcv
1329         data8 sys_msgctl
1330         data8 sys_shmget
1331         data8 ia64_shmat
1332         data8 sys_shmdt                         // 1115
1333         data8 sys_shmctl
1334         data8 sys_syslog
1335         data8 sys_setitimer
1336         data8 sys_getitimer
1337         data8 ia64_ni_syscall                   // 1120         /* was: ia64_oldstat */
1338         data8 ia64_ni_syscall                                   /* was: ia64_oldlstat */
1339         data8 ia64_ni_syscall                                   /* was: ia64_oldfstat */
1340         data8 sys_vhangup
1341         data8 sys_lchown
1342         data8 sys_remap_file_pages              // 1125
1343         data8 sys_wait4
1344         data8 sys_sysinfo
1345         data8 sys_clone
1346         data8 sys_setdomainname
1347         data8 sys_newuname                      // 1130
1348         data8 sys_adjtimex
1349         data8 ia64_ni_syscall                                   /* was: ia64_create_module */
1350         data8 sys_init_module
1351         data8 sys_delete_module
1352         data8 ia64_ni_syscall                   // 1135         /* was: sys_get_kernel_syms */
1353         data8 ia64_ni_syscall                                   /* was: sys_query_module */
1354         data8 sys_quotactl
1355         data8 sys_bdflush
1356         data8 sys_sysfs
1357         data8 sys_personality                   // 1140
1358         data8 ia64_ni_syscall           // sys_afs_syscall
1359         data8 sys_setfsuid
1360         data8 sys_setfsgid
1361         data8 sys_getdents
1362         data8 sys_flock                         // 1145
1363         data8 sys_readv
1364         data8 sys_writev
1365         data8 sys_pread64
1366         data8 sys_pwrite64
1367         data8 sys_sysctl                        // 1150
1368         data8 sys_mmap
1369         data8 sys_munmap
1370         data8 sys_mlock
1371         data8 sys_mlockall
1372         data8 sys_mprotect                      // 1155
1373         data8 ia64_mremap
1374         data8 sys_msync
1375         data8 sys_munlock
1376         data8 sys_munlockall
1377         data8 sys_sched_getparam                // 1160
1378         data8 sys_sched_setparam
1379         data8 sys_sched_getscheduler
1380         data8 sys_sched_setscheduler
1381         data8 sys_sched_yield
1382         data8 sys_sched_get_priority_max        // 1165
1383         data8 sys_sched_get_priority_min
1384         data8 sys_sched_rr_get_interval
1385         data8 sys_nanosleep
1386         data8 sys_nfsservctl
1387         data8 sys_prctl                         // 1170
1388         data8 sys_getpagesize
1389         data8 sys_mmap2
1390         data8 sys_pciconfig_read
1391         data8 sys_pciconfig_write
1392         data8 sys_perfmonctl                    // 1175
1393         data8 sys_sigaltstack
1394         data8 sys_rt_sigaction
1395         data8 sys_rt_sigpending
1396         data8 sys_rt_sigprocmask
1397         data8 sys_rt_sigqueueinfo               // 1180
1398         data8 sys_rt_sigreturn
1399         data8 sys_rt_sigsuspend
1400         data8 sys_rt_sigtimedwait
1401         data8 sys_getcwd
1402         data8 sys_capget                        // 1185
1403         data8 sys_capset
1404         data8 sys_sendfile
1405         data8 sys_ni_syscall            // sys_getpmsg (STREAMS)
1406         data8 sys_ni_syscall            // sys_putpmsg (STREAMS)
1407         data8 sys_socket                        // 1190
1408         data8 sys_bind
1409         data8 sys_connect
1410         data8 sys_listen
1411         data8 sys_accept
1412         data8 sys_getsockname                   // 1195
1413         data8 sys_getpeername
1414         data8 sys_socketpair
1415         data8 sys_send
1416         data8 sys_sendto
1417         data8 sys_recv                          // 1200
1418         data8 sys_recvfrom
1419         data8 sys_shutdown
1420         data8 sys_setsockopt
1421         data8 sys_getsockopt
1422         data8 sys_sendmsg                       // 1205
1423         data8 sys_recvmsg
1424         data8 sys_pivot_root
1425         data8 sys_mincore
1426         data8 sys_madvise
1427         data8 sys_newstat                       // 1210
1428         data8 sys_newlstat
1429         data8 sys_newfstat
1430         data8 sys_clone2
1431         data8 sys_getdents64
1432         data8 sys_getunwind                     // 1215
1433         data8 sys_readahead
1434         data8 sys_setxattr
1435         data8 sys_lsetxattr
1436         data8 sys_fsetxattr
1437         data8 sys_getxattr                      // 1220
1438         data8 sys_lgetxattr
1439         data8 sys_fgetxattr
1440         data8 sys_listxattr
1441         data8 sys_llistxattr
1442         data8 sys_flistxattr                    // 1225
1443         data8 sys_removexattr
1444         data8 sys_lremovexattr
1445         data8 sys_fremovexattr
1446         data8 sys_tkill
1447         data8 sys_futex                         // 1230
1448         data8 sys_sched_setaffinity
1449         data8 sys_sched_getaffinity
1450         data8 sys_set_tid_address
1451         data8 sys_fadvise64_64
1452         data8 sys_tgkill                        // 1235
1453         data8 sys_exit_group
1454         data8 sys_lookup_dcookie
1455         data8 sys_io_setup
1456         data8 sys_io_destroy
1457         data8 sys_io_getevents                  // 1240
1458         data8 sys_io_submit
1459         data8 sys_io_cancel
1460         data8 sys_epoll_create
1461         data8 sys_epoll_ctl
1462         data8 sys_epoll_wait                    // 1245
1463         data8 sys_restart_syscall
1464         data8 sys_semtimedop
1465         data8 sys_timer_create
1466         data8 sys_timer_settime
1467         data8 sys_timer_gettime                 // 1250
1468         data8 sys_timer_getoverrun
1469         data8 sys_timer_delete
1470         data8 sys_clock_settime
1471         data8 sys_clock_gettime
1472         data8 sys_clock_getres                  // 1255
1473         data8 sys_clock_nanosleep
1474         data8 sys_fstatfs64
1475         data8 sys_statfs64
1476         data8 ia64_ni_syscall
1477         data8 ia64_ni_syscall                   // 1260
1478         data8 ia64_ni_syscall
1479         data8 ia64_ni_syscall
1480         data8 ia64_ni_syscall
1481         data8 ia64_ni_syscall
1482         data8 ia64_ni_syscall                   // 1265
1483         data8 ia64_ni_syscall
1484         data8 ia64_ni_syscall
1485         data8 ia64_ni_syscall
1486         data8 ia64_ni_syscall
1487         data8 ia64_ni_syscall                   // 1270
1488         data8 ia64_ni_syscall
1489         data8 ia64_ni_syscall
1490         data8 ia64_ni_syscall
1491         data8 ia64_ni_syscall
1492         data8 ia64_ni_syscall                   // 1275
1493         data8 ia64_ni_syscall
1494         data8 ia64_ni_syscall
1495         data8 ia64_ni_syscall
1496         data8 ia64_ni_syscall
1497
1498         .org sys_call_table + 8*NR_syscalls     // guard against failures to increase NR_syscalls