Update to 3.4-final.
[linux-flexiantxendom0-3.2.10.git] / arch / x86 / ia32 / ia32entry-xen.S
1 /*
2  * Compatibility mode system call entry point for x86-64. 
3  *              
4  * Copyright 2000-2002 Andi Kleen, SuSE Labs.
5  */              
6
7 #include <asm/dwarf2.h>
8 #include <asm/calling.h>
9 #include <asm/asm-offsets.h>
10 #include <asm/current.h>
11 #include <asm/errno.h>
12 #include <asm/ia32_unistd.h>    
13 #include <asm/thread_info.h>    
14 #include <asm/segment.h>
15 #include <asm/irqflags.h>
16 #include <linux/linkage.h>
17 #include <linux/err.h>
18
19 /* Avoid __ASSEMBLER__'ifying <linux/audit.h> just for this.  */
20 #include <linux/elf-em.h>
21 #define AUDIT_ARCH_I386         (EM_386|__AUDIT_ARCH_LE)
22 #define __AUDIT_ARCH_LE    0x40000000
23
24         .section .entry.text, "ax"
25
26         .macro IA32_ARG_FIXUP noebp=0
27         movl    %edi,%r8d
28         .if \noebp
29         jmp     .Lia32_common
30         .else
31         movl    %ebp,%r9d
32 .Lia32_common:
33         .endif
34         xchg    %ecx,%esi
35         movl    %ebx,%edi
36         movl    %edx,%edx       /* zero extension */
37         .endm 
38
39         /* clobbers %eax */     
40         .macro  CLEAR_RREGS offset=0, _r9=rax
41         xorl    %eax,%eax
42         movq    %rax,\offset+R11(%rsp)
43         movq    %rax,\offset+R10(%rsp)
44         movq    %\_r9,\offset+R9(%rsp)
45         movq    %rax,\offset+R8(%rsp)
46         .endm
47
48         /*
49          * Reload arg registers from stack in case ptrace changed them.
50          * We don't reload %eax because syscall_trace_enter() returned
51          * the %rax value we should see.  Instead, we just truncate that
52          * value to 32 bits again as we did on entry from user mode.
53          * If it's a new value set by user_regset during entry tracing,
54          * this matches the normal truncation of the user-mode value.
55          * If it's -1 to make us punt the syscall, then (u32)-1 is still
56          * an appropriately invalid value.
57          */
58         .macro LOAD_ARGS32 offset, _r9=0
59         .if \_r9
60         movl \offset+16(%rsp),%r9d
61         .endif
62         movl \offset+40(%rsp),%ecx
63         movl \offset+48(%rsp),%edx
64         movl \offset+56(%rsp),%esi
65         movl \offset+64(%rsp),%edi
66         movl %eax,%eax                  /* zero extension */
67         .endm
68
69         .macro CFI_STARTPROC32 simple
70         CFI_STARTPROC   \simple
71         CFI_UNDEFINED   r8
72         CFI_UNDEFINED   r9
73         CFI_UNDEFINED   r10
74         CFI_UNDEFINED   r11
75         CFI_UNDEFINED   r12
76         CFI_UNDEFINED   r13
77         CFI_UNDEFINED   r14
78         CFI_UNDEFINED   r15
79         .endm
80
81 #ifdef CONFIG_PARAVIRT
82 ENTRY(native_usergs_sysret32)
83         swapgs
84         sysretl
85 ENDPROC(native_usergs_sysret32)
86
87 ENTRY(native_irq_enable_sysexit)
88         swapgs
89         sti
90         sysexit
91 ENDPROC(native_irq_enable_sysexit)
92 #endif
93
94 /*
95  * 32bit SYSENTER instruction entry.
96  *
97  * Arguments:
98  * %eax System call number.
99  * %ebx Arg1
100  * %ecx Arg2
101  * %edx Arg3
102  * %esi Arg4
103  * %edi Arg5
104  * %ebp user stack
105  * 0(%ebp) Arg6 
106  *      
107  * Interrupts on.
108  *      
109  * This is purely a fast path. For anything complicated we use the int 0x80
110  * path below.  Set up a complete hardware stack frame to share code
111  * with the int 0x80 path.
112  */     
113 ENTRY(ia32_sysenter_target)
114         CFI_STARTPROC32 simple
115         CFI_SIGNAL_FRAME
116         CFI_DEF_CFA     rsp,SS+8-RIP+16
117         /*CFI_REL_OFFSET        ss,SS-RIP+16*/
118         CFI_REL_OFFSET  rsp,RSP-RIP+16
119         /*CFI_REL_OFFSET        rflags,EFLAGS-RIP+16*/
120         /*CFI_REL_OFFSET        cs,CS-RIP+16*/
121         CFI_REL_OFFSET  rip,RIP-RIP+16
122         CFI_REL_OFFSET  r11,8
123         CFI_REL_OFFSET  rcx,0
124         movq    8(%rsp),%r11
125         CFI_RESTORE     r11
126         popq_cfi %rcx
127         CFI_RESTORE     rcx
128         movl    %ebp,%ebp               /* zero extension */
129         movl    %eax,%eax
130         movl    TI_sysenter_return+THREAD_INFO(%rsp,8*6-KERNEL_STACK_OFFSET),%r10d
131         movl    $__USER32_DS,40(%rsp)
132         movq    %rbp,32(%rsp)
133         movl    $__USER32_CS,16(%rsp)
134         movq    %r10,8(%rsp)
135         movq    %rax,(%rsp)
136         cld
137         SAVE_ARGS 0,1,0
138         /* no need to do an access_ok check here because rbp has been
139            32bit zero extended */ 
140 1:      movl    (%rbp),%ebp
141         .section __ex_table,"a"
142         .quad 1b,ia32_badarg
143         .previous       
144         orl     $TS_COMPAT,TI_status+THREAD_INFO(%rsp,RIP-ARGOFFSET)
145         testl   $_TIF_WORK_SYSCALL_ENTRY,TI_flags+THREAD_INFO(%rsp,RIP-ARGOFFSET)
146         jnz  sysenter_tracesys
147         jmp .Lia32_check_call
148
149 #ifdef CONFIG_AUDITSYSCALL
150         .macro auditsys_entry_common
151         movl %esi,%r9d                  /* 6th arg: 4th syscall arg */
152         movl %edx,%r8d                  /* 5th arg: 3rd syscall arg */
153         /* (already in %ecx)               4th arg: 2nd syscall arg */
154         movl %ebx,%edx                  /* 3rd arg: 1st syscall arg */
155         movl %eax,%esi                  /* 2nd arg: syscall number */
156         movl $AUDIT_ARCH_I386,%edi      /* 1st arg: audit arch */
157         call __audit_syscall_entry
158         movl RAX-ARGOFFSET(%rsp),%eax   /* reload syscall number */
159         cmpq $(IA32_NR_syscalls-1),%rax
160         ja ia32_badsys
161         movl %ebx,%edi                  /* reload 1st syscall arg */
162         movl RCX-ARGOFFSET(%rsp),%esi   /* reload 2nd syscall arg */
163         movl RDX-ARGOFFSET(%rsp),%edx   /* reload 3rd syscall arg */
164         movl RSI-ARGOFFSET(%rsp),%ecx   /* reload 4th syscall arg */
165         movl RDI-ARGOFFSET(%rsp),%r8d   /* reload 5th syscall arg */
166         .endm
167
168 sysenter_auditsys:
169         auditsys_entry_common
170         movl %ebp,%r9d                  /* reload 6th syscall arg */
171         jmp .Lia32_dispatch
172 #endif
173         CFI_ENDPROC
174 ENDPROC(ia32_sysenter_target)
175
176 /*
177  * 32bit SYSCALL instruction entry.
178  *
179  * Arguments:
180  * %eax System call number.
181  * %ebx Arg1
182  * %ecx return EIP 
183  * %edx Arg3
184  * %esi Arg4
185  * %edi Arg5
186  * %ebp Arg2    [note: not saved in the stack frame, should not be touched]
187  * %esp user stack 
188  * 0(%esp) Arg6
189  *      
190  * Interrupts on.
191  *      
192  * This is purely a fast path. For anything complicated we use the int 0x80
193  * path below.  Set up a complete hardware stack frame to share code
194  * with the int 0x80 path.      
195  */     
196 ENTRY(ia32_cstar_target)
197         CFI_STARTPROC32 simple
198         CFI_SIGNAL_FRAME
199         CFI_DEF_CFA     rsp,SS+8-RIP+16
200         /*CFI_REL_OFFSET        ss,SS-RIP+16*/
201         CFI_REL_OFFSET  rsp,RSP-RIP+16
202         /*CFI_REL_OFFSET        rflags,EFLAGS-RIP+16*/
203         /*CFI_REL_OFFSET        cs,CS-RIP+16*/
204         CFI_REL_OFFSET  rip,RIP-RIP+16
205         movl    %eax,%eax       /* zero extension */
206         movl    RSP-RIP+16(%rsp),%r8d
207         SAVE_ARGS -8,0,0
208         movq    %rax,ORIG_RAX-ARGOFFSET(%rsp)
209         movq    %rbp,RCX-ARGOFFSET(%rsp) /* this lies slightly to ptrace */
210         movl    %ebp,%ecx
211         movl    $__USER32_CS,CS-ARGOFFSET(%rsp)
212         movl    $__USER32_DS,SS-ARGOFFSET(%rsp)
213         /* no need to do an access_ok check here because r8 has been
214            32bit zero extended */ 
215         /* hardware stack frame is complete now */      
216 1:      movl    (%r8),%r9d
217         .section __ex_table,"a"
218         .quad 1b,ia32_badarg
219         .previous       
220         orl     $TS_COMPAT,TI_status+THREAD_INFO(%rsp,RIP-ARGOFFSET)
221         testl   $_TIF_WORK_SYSCALL_ENTRY,TI_flags+THREAD_INFO(%rsp,RIP-ARGOFFSET)
222         jnz   cstar_tracesys
223         cmpq $IA32_NR_syscalls-1,%rax
224         ja  ia32_badsys
225 cstar_do_call:
226         IA32_ARG_FIXUP 1
227         
228 #ifdef CONFIG_AUDITSYSCALL
229 cstar_auditsys:
230         movl %r9d,R9-ARGOFFSET(%rsp)    /* register to be clobbered by call */
231         auditsys_entry_common
232         movl R9-ARGOFFSET(%rsp),%r9d    /* reload 6th syscall arg */
233         jmp .Lia32_dispatch
234 #endif
235
236 cstar_tracesys:
237 #ifdef CONFIG_AUDITSYSCALL
238         testl $(_TIF_WORK_SYSCALL_ENTRY & ~_TIF_SYSCALL_AUDIT),TI_flags+THREAD_INFO(%rsp,RIP-ARGOFFSET)
239         jz cstar_auditsys
240 #endif
241         xchgl %r9d,%ebp
242         SAVE_REST
243         CLEAR_RREGS 0, r9
244         movq $-ENOSYS,RAX(%rsp) /* ptrace can change this for a bad syscall */
245         movq %rsp,%rdi        /* &pt_regs -> arg1 */
246         call syscall_trace_enter
247         LOAD_ARGS32 ARGOFFSET, 1  /* reload args from stack in case ptrace changed it */
248         RESTORE_REST
249         xchgl %ebp,%r9d
250         cmpq $(IA32_NR_syscalls-1),%rax
251         ja int_ret_from_sys_call /* cstar_tracesys has set RAX(%rsp) */
252         jmp cstar_do_call
253 END(ia32_cstar_target)
254                                 
255 ia32_badarg:
256         movq $-EFAULT,%rax
257         jmp ia32_sysret
258         CFI_ENDPROC
259
260 /* 
261  * Emulated IA32 system calls via int 0x80. 
262  *
263  * Arguments:    
264  * %eax System call number.
265  * %ebx Arg1
266  * %ecx Arg2
267  * %edx Arg3
268  * %esi Arg4
269  * %edi Arg5
270  * %ebp Arg6    [note: not saved in the stack frame, should not be touched]
271  *
272  * Notes:
273  * Uses the same stack frame as the x86-64 version.     
274  * All registers except %eax must be saved (but ptrace may violate that)
275  * Arguments are zero extended. For system calls that want sign extension and
276  * take long arguments a wrapper is needed. Most calls can just be called
277  * directly.
278  * Assumes it is only called from user space and entered with interrupts on.
279  */                             
280
281 ENTRY(ia32_syscall)
282         CFI_STARTPROC32 simple
283         CFI_SIGNAL_FRAME
284         CFI_DEF_CFA     rsp,SS+8-RIP+16
285         /*CFI_REL_OFFSET        ss,SS-RIP+16*/
286         CFI_REL_OFFSET  rsp,RSP-RIP+16
287         /*CFI_REL_OFFSET        rflags,EFLAGS-RIP+16*/
288         /*CFI_REL_OFFSET        cs,CS-RIP+16*/
289         CFI_REL_OFFSET  rip,RIP-RIP+16
290         CFI_REL_OFFSET  r11,8
291         CFI_REL_OFFSET  rcx,0
292         movq 8(%rsp),%r11
293         CFI_RESTORE     r11
294         popq_cfi %rcx
295         CFI_RESTORE     rcx
296         movl %eax,%eax
297         movq %rax,(%rsp)
298         cld
299         /* note the registers are not zero extended to the sf.
300            this could be a problem. */
301         SAVE_ARGS 0,1,0
302         orl $TS_COMPAT,TI_status+THREAD_INFO(%rsp,RIP-ARGOFFSET)
303         testl $_TIF_WORK_SYSCALL_ENTRY,TI_flags+THREAD_INFO(%rsp,RIP-ARGOFFSET)
304         jnz ia32_tracesys
305 .Lia32_check_call:
306         cmpq $(IA32_NR_syscalls-1),%rax
307         ja ia32_badsys
308 ia32_do_call:
309         IA32_ARG_FIXUP
310 .Lia32_dispatch:
311         call *ia32_sys_call_table(,%rax,8) # xxx: rip relative
312 ia32_sysret:
313         movq %rax,RAX-ARGOFFSET(%rsp)
314         CLEAR_RREGS -ARGOFFSET
315         jmp int_ret_from_sys_call 
316
317 sysenter_tracesys:
318 #ifdef CONFIG_AUDITSYSCALL
319         testl $(_TIF_WORK_SYSCALL_ENTRY & ~_TIF_SYSCALL_AUDIT),TI_flags+THREAD_INFO(%rsp,RIP-ARGOFFSET)
320         jz sysenter_auditsys
321 #endif
322 ia32_tracesys:                   
323         SAVE_REST
324         CLEAR_RREGS
325         movq $-ENOSYS,RAX(%rsp) /* ptrace can change this for a bad syscall */
326         movq %rsp,%rdi        /* &pt_regs -> arg1 */
327         call syscall_trace_enter
328         LOAD_ARGS32 ARGOFFSET  /* reload args from stack in case ptrace changed it */
329         RESTORE_REST
330         cmpq $(IA32_NR_syscalls-1),%rax
331         ja  int_ret_from_sys_call       /* ia32_tracesys has set RAX(%rsp) */
332         jmp ia32_do_call
333 END(ia32_syscall)
334
335 ia32_badsys:
336         movq $0,ORIG_RAX-ARGOFFSET(%rsp)
337         movq $-ENOSYS,%rax
338         jmp ia32_sysret
339
340         CFI_ENDPROC
341         
342         .macro PTREGSCALL label, func, arg
343         ALIGN
344 GLOBAL(\label)
345         leaq \func(%rip),%rax
346         leaq -ARGOFFSET+8(%rsp),\arg    /* 8 for return address */
347         jmp  ia32_ptregs_common 
348         .endm
349
350         CFI_STARTPROC32
351
352         PTREGSCALL stub32_rt_sigreturn, sys32_rt_sigreturn, %rdi
353         PTREGSCALL stub32_sigreturn, sys32_sigreturn, %rdi
354         PTREGSCALL stub32_sigaltstack, sys32_sigaltstack, %rdx
355         PTREGSCALL stub32_execve, sys32_execve, %rcx
356         PTREGSCALL stub32_fork, sys_fork, %rdi
357         PTREGSCALL stub32_clone, sys32_clone, %rdx
358         PTREGSCALL stub32_vfork, sys_vfork, %rdi
359         PTREGSCALL stub32_iopl, sys_iopl, %rsi
360
361         ALIGN
362 ia32_ptregs_common:
363         popq %r11
364         CFI_ENDPROC
365         CFI_STARTPROC32 simple
366         CFI_SIGNAL_FRAME
367         CFI_DEF_CFA     rsp,SS+8-ARGOFFSET
368         CFI_REL_OFFSET  rax,RAX-ARGOFFSET
369         CFI_REL_OFFSET  rcx,RCX-ARGOFFSET
370         CFI_REL_OFFSET  rdx,RDX-ARGOFFSET
371         CFI_REL_OFFSET  rsi,RSI-ARGOFFSET
372         CFI_REL_OFFSET  rdi,RDI-ARGOFFSET
373         CFI_REL_OFFSET  rip,RIP-ARGOFFSET
374 /*      CFI_REL_OFFSET  cs,CS-ARGOFFSET*/
375 /*      CFI_REL_OFFSET  rflags,EFLAGS-ARGOFFSET*/
376         CFI_REL_OFFSET  rsp,RSP-ARGOFFSET
377 /*      CFI_REL_OFFSET  ss,SS-ARGOFFSET*/
378         SAVE_REST
379         call *%rax
380         RESTORE_REST
381         jmp  ia32_sysret        /* misbalances the return cache */
382         CFI_ENDPROC
383 END(ia32_ptregs_common)