Merge ../torvalds-2.6/
[linux-2.6] / arch / ia64 / ia32 / ia32_entry.S
1 #include <asm/asmmacro.h>
2 #include <asm/ia32.h>
3 #include <asm/asm-offsets.h>
4 #include <asm/signal.h>
5 #include <asm/thread_info.h>
6
7 #include "../kernel/minstate.h"
8
9         /*
10          * execve() is special because in case of success, we need to
11          * setup a null register window frame (in case an IA-32 process
12          * is exec'ing an IA-64 program).
13          */
14 ENTRY(ia32_execve)
15         .prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(3)
16         alloc loc1=ar.pfs,3,2,4,0
17         mov loc0=rp
18         .body
19         zxt4 out0=in0                   // filename
20         ;;                              // stop bit between alloc and call
21         zxt4 out1=in1                   // argv
22         zxt4 out2=in2                   // envp
23         add out3=16,sp                  // regs
24         br.call.sptk.few rp=sys32_execve
25 1:      cmp.ge p6,p0=r8,r0
26         mov ar.pfs=loc1                 // restore ar.pfs
27         ;;
28 (p6)    mov ar.pfs=r0                   // clear ar.pfs in case of success
29         sxt4 r8=r8                      // return 64-bit result
30         mov rp=loc0
31         br.ret.sptk.few rp
32 END(ia32_execve)
33
34 ENTRY(ia32_clone)
35         .prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(5)
36         alloc r16=ar.pfs,5,2,6,0
37         DO_SAVE_SWITCH_STACK
38         mov loc0=rp
39         mov loc1=r16                            // save ar.pfs across do_fork
40         .body
41         zxt4 out1=in1                           // newsp
42         mov out3=16                             // stacksize (compensates for 16-byte scratch area)
43         adds out2=IA64_SWITCH_STACK_SIZE+16,sp  // out2 = &regs
44         mov out0=in0                            // out0 = clone_flags
45         zxt4 out4=in2                           // out4 = parent_tidptr
46         zxt4 out5=in4                           // out5 = child_tidptr
47         br.call.sptk.many rp=do_fork
48 .ret0:  .restore sp
49         adds sp=IA64_SWITCH_STACK_SIZE,sp       // pop the switch stack
50         mov ar.pfs=loc1
51         mov rp=loc0
52         br.ret.sptk.many rp
53 END(ia32_clone)
54
55 ENTRY(sys32_rt_sigsuspend)
56         .prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(8)
57         alloc loc1=ar.pfs,8,2,3,0               // preserve all eight input regs
58         mov loc0=rp
59         mov out0=in0                            // mask
60         mov out1=in1                            // sigsetsize
61         mov out2=sp                             // out2 = &sigscratch
62         .fframe 16
63         adds sp=-16,sp                          // allocate dummy "sigscratch"
64         ;;
65         .body
66         br.call.sptk.many rp=ia32_rt_sigsuspend
67 1:      .restore sp
68         adds sp=16,sp
69         mov rp=loc0
70         mov ar.pfs=loc1
71         br.ret.sptk.many rp
72 END(sys32_rt_sigsuspend)
73
74 ENTRY(sys32_sigsuspend)
75         .prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(8)
76         alloc loc1=ar.pfs,8,2,3,0               // preserve all eight input regs
77         mov loc0=rp
78         mov out0=in2                            // mask (first two args are ignored)
79         ;;
80         mov out1=sp                             // out1 = &sigscratch
81         .fframe 16
82         adds sp=-16,sp                          // allocate dummy "sigscratch"
83         .body
84         br.call.sptk.many rp=ia32_sigsuspend
85 1:      .restore sp
86         adds sp=16,sp
87         mov rp=loc0
88         mov ar.pfs=loc1
89         br.ret.sptk.many rp
90 END(sys32_sigsuspend)
91
92 GLOBAL_ENTRY(ia32_ret_from_clone)
93         PT_REGS_UNWIND_INFO(0)
94 {       /*
95          * Some versions of gas generate bad unwind info if the first instruction of a
96          * procedure doesn't go into the first slot of a bundle.  This is a workaround.
97          */
98         nop.m 0
99         nop.i 0
100         /*
101          * We need to call schedule_tail() to complete the scheduling process.
102          * Called by ia64_switch_to after do_fork()->copy_thread().  r8 contains the
103          * address of the previously executing task.
104          */
105         br.call.sptk.many rp=ia64_invoke_schedule_tail
106 }
107 .ret1:
108         adds r2=TI_FLAGS+IA64_TASK_SIZE,r13
109         ;;
110         ld4 r2=[r2]
111         ;;
112         mov r8=0
113         and r2=_TIF_SYSCALL_TRACEAUDIT,r2
114         ;;
115         cmp.ne p6,p0=r2,r0
116 (p6)    br.cond.spnt .ia32_strace_check_retval
117         ;;                                      // prevent RAW on r8
118 END(ia32_ret_from_clone)
119         // fall thrugh
120 GLOBAL_ENTRY(ia32_ret_from_syscall)
121         PT_REGS_UNWIND_INFO(0)
122
123         cmp.ge p6,p7=r8,r0                      // syscall executed successfully?
124         adds r2=IA64_PT_REGS_R8_OFFSET+16,sp    // r2 = &pt_regs.r8
125         ;;
126         alloc r3=ar.pfs,0,0,0,0                 // drop the syscall argument frame
127         st8 [r2]=r8                             // store return value in slot for r8
128         br.cond.sptk.many ia64_leave_kernel
129 END(ia32_ret_from_syscall)
130
131         //
132         // Invoke a system call, but do some tracing before and after the call.
133         // We MUST preserve the current register frame throughout this routine
134         // because some system calls (such as ia64_execve) directly
135         // manipulate ar.pfs.
136         //
137         // Input:
138         //      r8 = syscall number
139         //      b6 = syscall entry point
140         //
141 GLOBAL_ENTRY(ia32_trace_syscall)
142         PT_REGS_UNWIND_INFO(0)
143         mov r3=-38
144         adds r2=IA64_PT_REGS_R8_OFFSET+16,sp
145         ;;
146         st8 [r2]=r3                             // initialize return code to -ENOSYS
147         br.call.sptk.few rp=syscall_trace_enter // give parent a chance to catch syscall args
148 .ret2:  // Need to reload arguments (they may be changed by the tracing process)
149         adds r2=IA64_PT_REGS_R1_OFFSET+16,sp    // r2 = &pt_regs.r1
150         adds r3=IA64_PT_REGS_R13_OFFSET+16,sp   // r3 = &pt_regs.r13
151         mov r15=IA32_NR_syscalls
152         ;;
153         ld4 r8=[r2],IA64_PT_REGS_R9_OFFSET-IA64_PT_REGS_R1_OFFSET
154         movl r16=ia32_syscall_table
155         ;;
156         ld4 r33=[r2],8                          // r9 == ecx
157         ld4 r37=[r3],16                         // r13 == ebp
158         cmp.ltu.unc p6,p7=r8,r15
159         ;;
160         ld4 r34=[r2],8                          // r10 == edx
161         ld4 r36=[r3],8                          // r15 == edi
162 (p6)    shladd r16=r8,3,r16     // force ni_syscall if not valid syscall number
163         ;;
164         ld8 r16=[r16]
165         ;;
166         ld4 r32=[r2],8                          // r11 == ebx
167         mov b6=r16
168         ld4 r35=[r3],8                          // r14 == esi
169         br.call.sptk.few rp=b6                  // do the syscall
170 .ia32_strace_check_retval:
171         cmp.lt p6,p0=r8,r0                      // syscall failed?
172         adds r2=IA64_PT_REGS_R8_OFFSET+16,sp    // r2 = &pt_regs.r8
173         ;;
174         st8.spill [r2]=r8                       // store return value in slot for r8
175         br.call.sptk.few rp=syscall_trace_leave // give parent a chance to catch return value
176 .ret4:  alloc r2=ar.pfs,0,0,0,0                 // drop the syscall argument frame
177         br.cond.sptk.many ia64_leave_kernel
178 END(ia32_trace_syscall)
179
180 GLOBAL_ENTRY(sys32_vfork)
181         alloc r16=ar.pfs,2,2,4,0;;
182         mov out0=IA64_CLONE_VFORK|IA64_CLONE_VM|SIGCHLD // out0 = clone_flags
183         br.cond.sptk.few .fork1                 // do the work
184 END(sys32_vfork)
185
186 GLOBAL_ENTRY(sys32_fork)
187         .prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(2)
188         alloc r16=ar.pfs,2,2,4,0
189         mov out0=SIGCHLD                        // out0 = clone_flags
190         ;;
191 .fork1:
192         mov loc0=rp
193         mov loc1=r16                            // save ar.pfs across do_fork
194         DO_SAVE_SWITCH_STACK
195
196         .body
197
198         mov out1=0
199         mov out3=0
200         adds out2=IA64_SWITCH_STACK_SIZE+16,sp  // out2 = &regs
201         br.call.sptk.few rp=do_fork
202 .ret5:  .restore sp
203         adds sp=IA64_SWITCH_STACK_SIZE,sp       // pop the switch stack
204         mov ar.pfs=loc1
205         mov rp=loc0
206         br.ret.sptk.many rp
207 END(sys32_fork)
208
209         .rodata
210         .align 8
211         .globl ia32_syscall_table
212 ia32_syscall_table:
213         data8 sys_ni_syscall      /* 0  -  old "setup(" system call*/
214         data8 sys_exit
215         data8 sys32_fork
216         data8 sys_read
217         data8 sys_write
218         data8 compat_sys_open     /* 5 */
219         data8 sys_close
220         data8 sys32_waitpid
221         data8 sys_creat
222         data8 sys_link
223         data8 sys_unlink          /* 10 */
224         data8 ia32_execve
225         data8 sys_chdir
226         data8 compat_sys_time
227         data8 sys_mknod
228         data8 sys_chmod           /* 15 */
229         data8 sys_lchown        /* 16-bit version */
230         data8 sys_ni_syscall      /* old break syscall holder */
231         data8 sys_ni_syscall
232         data8 sys32_lseek
233         data8 sys_getpid          /* 20 */
234         data8 compat_sys_mount
235         data8 sys_oldumount
236         data8 sys_setuid        /* 16-bit version */
237         data8 sys_getuid        /* 16-bit version */
238         data8 compat_sys_stime    /* 25 */
239         data8 sys32_ptrace
240         data8 sys32_alarm
241         data8 sys_ni_syscall
242         data8 sys32_pause
243         data8 compat_sys_utime    /* 30 */
244         data8 sys_ni_syscall      /* old stty syscall holder */
245         data8 sys_ni_syscall      /* old gtty syscall holder */
246         data8 sys_access
247         data8 sys_nice
248         data8 sys_ni_syscall      /* 35 */        /* old ftime syscall holder */
249         data8 sys_sync
250         data8 sys_kill
251         data8 sys_rename
252         data8 sys_mkdir
253         data8 sys_rmdir           /* 40 */
254         data8 sys_dup
255         data8 sys32_pipe
256         data8 compat_sys_times
257         data8 sys_ni_syscall      /* old prof syscall holder */
258         data8 sys32_brk           /* 45 */
259         data8 sys_setgid        /* 16-bit version */
260         data8 sys_getgid        /* 16-bit version */
261         data8 sys32_signal
262         data8 sys_geteuid       /* 16-bit version */
263         data8 sys_getegid       /* 16-bit version */      /* 50 */
264         data8 sys_acct
265         data8 sys_umount          /* recycled never used phys( */
266         data8 sys_ni_syscall      /* old lock syscall holder */
267         data8 compat_sys_ioctl
268         data8 compat_sys_fcntl    /* 55 */
269         data8 sys_ni_syscall      /* old mpx syscall holder */
270         data8 sys_setpgid
271         data8 sys_ni_syscall      /* old ulimit syscall holder */
272         data8 sys_ni_syscall
273         data8 sys_umask           /* 60 */
274         data8 sys_chroot
275         data8 sys_ustat
276         data8 sys_dup2
277         data8 sys_getppid
278         data8 sys_getpgrp         /* 65 */
279         data8 sys_setsid
280         data8 sys32_sigaction
281         data8 sys_ni_syscall
282         data8 sys_ni_syscall
283         data8 sys_setreuid      /* 16-bit version */      /* 70 */
284         data8 sys_setregid      /* 16-bit version */
285         data8 sys32_sigsuspend
286         data8 compat_sys_sigpending
287         data8 sys_sethostname
288         data8 compat_sys_setrlimit        /* 75 */
289         data8 compat_sys_old_getrlimit
290         data8 compat_sys_getrusage
291         data8 sys32_gettimeofday
292         data8 sys32_settimeofday
293         data8 sys32_getgroups16   /* 80 */
294         data8 sys32_setgroups16
295         data8 sys32_old_select
296         data8 sys_symlink
297         data8 sys_ni_syscall
298         data8 sys_readlink        /* 85 */
299         data8 sys_uselib
300         data8 sys_swapon
301         data8 sys_reboot
302         data8 sys32_readdir
303         data8 sys32_mmap          /* 90 */
304         data8 sys32_munmap
305         data8 sys_truncate
306         data8 sys_ftruncate
307         data8 sys_fchmod
308         data8 sys_fchown        /* 16-bit version */      /* 95 */
309         data8 sys_getpriority
310         data8 sys_setpriority
311         data8 sys_ni_syscall      /* old profil syscall holder */
312         data8 compat_sys_statfs
313         data8 compat_sys_fstatfs          /* 100 */
314         data8 sys_ni_syscall    /* ioperm */
315         data8 compat_sys_socketcall
316         data8 sys_syslog
317         data8 compat_sys_setitimer
318         data8 compat_sys_getitimer        /* 105 */
319         data8 compat_sys_newstat
320         data8 compat_sys_newlstat
321         data8 compat_sys_newfstat
322         data8 sys_ni_syscall
323         data8 sys_ni_syscall    /* iopl */      /* 110 */
324         data8 sys_vhangup
325         data8 sys_ni_syscall            /* used to be sys_idle */
326         data8 sys_ni_syscall
327         data8 compat_sys_wait4
328         data8 sys_swapoff         /* 115 */
329         data8 sys32_sysinfo
330         data8 sys32_ipc
331         data8 sys_fsync
332         data8 sys32_sigreturn
333         data8 ia32_clone          /* 120 */
334         data8 sys_setdomainname
335         data8 sys32_newuname
336         data8 sys32_modify_ldt
337         data8 sys_ni_syscall    /* adjtimex */
338         data8 sys32_mprotect      /* 125 */
339         data8 compat_sys_sigprocmask
340         data8 sys_ni_syscall    /* create_module */
341         data8 sys_ni_syscall    /* init_module */
342         data8 sys_ni_syscall    /* delete_module */
343         data8 sys_ni_syscall    /* get_kernel_syms */  /* 130 */
344         data8 sys_quotactl
345         data8 sys_getpgid
346         data8 sys_fchdir
347         data8 sys_ni_syscall    /* sys_bdflush */
348         data8 sys_sysfs         /* 135 */
349         data8 sys32_personality
350         data8 sys_ni_syscall      /* for afs_syscall */
351         data8 sys_setfsuid      /* 16-bit version */
352         data8 sys_setfsgid      /* 16-bit version */
353         data8 sys_llseek          /* 140 */
354         data8 compat_sys_getdents
355         data8 compat_sys_select
356         data8 sys_flock
357         data8 sys32_msync
358         data8 compat_sys_readv    /* 145 */
359         data8 compat_sys_writev
360         data8 sys_getsid
361         data8 sys_fdatasync
362         data8 sys32_sysctl
363         data8 sys_mlock           /* 150 */
364         data8 sys_munlock
365         data8 sys_mlockall
366         data8 sys_munlockall
367         data8 sys_sched_setparam
368         data8 sys_sched_getparam  /* 155 */
369         data8 sys_sched_setscheduler
370         data8 sys_sched_getscheduler
371         data8 sys_sched_yield
372         data8 sys_sched_get_priority_max
373         data8 sys_sched_get_priority_min         /* 160 */
374         data8 sys32_sched_rr_get_interval
375         data8 compat_sys_nanosleep
376         data8 sys32_mremap
377         data8 sys_setresuid     /* 16-bit version */
378         data8 sys32_getresuid16 /* 16-bit version */      /* 165 */
379         data8 sys_ni_syscall    /* vm86 */
380         data8 sys_ni_syscall    /* sys_query_module */
381         data8 sys_poll
382         data8 sys_ni_syscall    /* nfsservctl */
383         data8 sys_setresgid       /* 170 */
384         data8 sys32_getresgid16
385         data8 sys_prctl
386         data8 sys32_rt_sigreturn
387         data8 sys32_rt_sigaction
388         data8 sys32_rt_sigprocmask /* 175 */
389         data8 sys_rt_sigpending
390         data8 compat_sys_rt_sigtimedwait
391         data8 sys32_rt_sigqueueinfo
392         data8 sys32_rt_sigsuspend
393         data8 sys32_pread         /* 180 */
394         data8 sys32_pwrite
395         data8 sys_chown /* 16-bit version */
396         data8 sys_getcwd
397         data8 sys_capget
398         data8 sys_capset          /* 185 */
399         data8 sys32_sigaltstack
400         data8 sys32_sendfile
401         data8 sys_ni_syscall              /* streams1 */
402         data8 sys_ni_syscall              /* streams2 */
403         data8 sys32_vfork         /* 190 */
404         data8 compat_sys_getrlimit
405         data8 sys32_mmap2
406         data8 sys32_truncate64
407         data8 sys32_ftruncate64
408         data8 sys32_stat64        /* 195 */
409         data8 sys32_lstat64
410         data8 sys32_fstat64
411         data8 sys_lchown
412         data8 sys_getuid
413         data8 sys_getgid          /* 200 */
414         data8 sys_geteuid
415         data8 sys_getegid
416         data8 sys_setreuid
417         data8 sys_setregid
418         data8 sys_getgroups       /* 205 */
419         data8 sys_setgroups
420         data8 sys_fchown
421         data8 sys_setresuid
422         data8 sys_getresuid
423         data8 sys_setresgid       /* 210 */
424         data8 sys_getresgid
425         data8 sys_chown
426         data8 sys_setuid
427         data8 sys_setgid
428         data8 sys_setfsuid        /* 215 */
429         data8 sys_setfsgid
430         data8 sys_pivot_root
431         data8 sys_mincore
432         data8 sys_madvise
433         data8 compat_sys_getdents64       /* 220 */
434         data8 compat_sys_fcntl64
435         data8 sys_ni_syscall            /* reserved for TUX */
436         data8 sys_ni_syscall            /* reserved for Security */
437         data8 sys_gettid
438         data8 sys_readahead       /* 225 */
439         data8 sys_setxattr
440         data8 sys_lsetxattr
441         data8 sys_fsetxattr
442         data8 sys_getxattr
443         data8 sys_lgetxattr     /* 230 */
444         data8 sys_fgetxattr
445         data8 sys_listxattr
446         data8 sys_llistxattr
447         data8 sys_flistxattr
448         data8 sys_removexattr   /* 235 */
449         data8 sys_lremovexattr
450         data8 sys_fremovexattr
451         data8 sys_tkill
452         data8 sys_sendfile64
453         data8 compat_sys_futex  /* 240 */
454         data8 compat_sys_sched_setaffinity
455         data8 compat_sys_sched_getaffinity
456         data8 sys32_set_thread_area
457         data8 sys32_get_thread_area
458         data8 compat_sys_io_setup       /* 245 */
459         data8 sys_io_destroy
460         data8 compat_sys_io_getevents
461         data8 compat_sys_io_submit
462         data8 sys_io_cancel
463         data8 sys_fadvise64     /* 250 */
464         data8 sys_ni_syscall
465         data8 sys_exit_group
466         data8 sys_lookup_dcookie
467         data8 sys_epoll_create
468         data8 sys32_epoll_ctl   /* 255 */
469         data8 sys32_epoll_wait
470         data8 sys_remap_file_pages
471         data8 sys_set_tid_address
472         data8 sys32_timer_create
473         data8 compat_sys_timer_settime  /* 260 */
474         data8 compat_sys_timer_gettime
475         data8 sys_timer_getoverrun
476         data8 sys_timer_delete
477         data8 compat_sys_clock_settime
478         data8 compat_sys_clock_gettime /* 265 */
479         data8 compat_sys_clock_getres
480         data8 compat_sys_clock_nanosleep
481         data8 compat_sys_statfs64
482         data8 compat_sys_fstatfs64
483         data8 sys_tgkill        /* 270 */
484         data8 compat_sys_utimes
485         data8 sys32_fadvise64_64
486         data8 sys_ni_syscall
487         data8 sys_ni_syscall
488         data8 sys_ni_syscall    /* 275 */
489         data8 sys_ni_syscall
490         data8 compat_sys_mq_open
491         data8 sys_mq_unlink
492         data8 compat_sys_mq_timedsend
493         data8 compat_sys_mq_timedreceive        /* 280 */
494         data8 compat_sys_mq_notify
495         data8 compat_sys_mq_getsetattr
496         data8 sys_ni_syscall            /* reserved for kexec */
497         data8 compat_sys_waitid
498
499         // guard against failures to increase IA32_NR_syscalls
500         .org ia32_syscall_table + 8*IA32_NR_syscalls