2 * Compatibility mode system call entry point for x86-64.
4 * Copyright 2000-2002 Andi Kleen, SuSE Labs.
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>
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
24 .section .entry.text, "ax"
26 .macro IA32_ARG_FIXUP noebp=0
36 movl %edx,%edx /* zero extension */
40 .macro CLEAR_RREGS offset=0, _r9=rax
42 movq %rax,\offset+R11(%rsp)
43 movq %rax,\offset+R10(%rsp)
44 movq %\_r9,\offset+R9(%rsp)
45 movq %rax,\offset+R8(%rsp)
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.
58 .macro LOAD_ARGS32 offset, _r9=0
60 movl \offset+16(%rsp),%r9d
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 */
69 .macro CFI_STARTPROC32 simple
81 #ifdef CONFIG_PARAVIRT
82 ENTRY(native_usergs_sysret32)
85 ENDPROC(native_usergs_sysret32)
87 ENTRY(native_irq_enable_sysexit)
91 ENDPROC(native_irq_enable_sysexit)
95 * 32bit SYSENTER instruction entry.
98 * %eax System call number.
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.
113 ENTRY(ia32_sysenter_target)
114 CFI_STARTPROC32 simple
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
128 movl %ebp,%ebp /* zero extension */
130 movl TI_sysenter_return+THREAD_INFO(%rsp,8*6-KERNEL_STACK_OFFSET),%r10d
131 movl $__USER32_DS,40(%rsp)
133 movl $__USER32_CS,16(%rsp)
138 /* no need to do an access_ok check here because rbp has been
139 32bit zero extended */
141 .section __ex_table,"a"
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
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
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 */
169 auditsys_entry_common
170 movl %ebp,%r9d /* reload 6th syscall arg */
174 ENDPROC(ia32_sysenter_target)
177 * 32bit SYSCALL instruction entry.
180 * %eax System call number.
186 * %ebp Arg2 [note: not saved in the stack frame, should not be touched]
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.
196 ENTRY(ia32_cstar_target)
197 CFI_STARTPROC32 simple
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
208 movq %rax,ORIG_RAX-ARGOFFSET(%rsp)
209 movq %rbp,RCX-ARGOFFSET(%rsp) /* this lies slightly to ptrace */
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 */
217 .section __ex_table,"a"
220 orl $TS_COMPAT,TI_status+THREAD_INFO(%rsp,RIP-ARGOFFSET)
221 testl $_TIF_WORK_SYSCALL_ENTRY,TI_flags+THREAD_INFO(%rsp,RIP-ARGOFFSET)
223 cmpq $IA32_NR_syscalls-1,%rax
228 #ifdef CONFIG_AUDITSYSCALL
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 */
237 #ifdef CONFIG_AUDITSYSCALL
238 testl $(_TIF_WORK_SYSCALL_ENTRY & ~_TIF_SYSCALL_AUDIT),TI_flags+THREAD_INFO(%rsp,RIP-ARGOFFSET)
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 */
250 cmpq $(IA32_NR_syscalls-1),%rax
251 ja int_ret_from_sys_call /* cstar_tracesys has set RAX(%rsp) */
253 END(ia32_cstar_target)
261 * Emulated IA32 system calls via int 0x80.
264 * %eax System call number.
270 * %ebp Arg6 [note: not saved in the stack frame, should not be touched]
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
278 * Assumes it is only called from user space and entered with interrupts on.
282 CFI_STARTPROC32 simple
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
299 /* note the registers are not zero extended to the sf.
300 this could be a problem. */
302 orl $TS_COMPAT,TI_status+THREAD_INFO(%rsp,RIP-ARGOFFSET)
303 testl $_TIF_WORK_SYSCALL_ENTRY,TI_flags+THREAD_INFO(%rsp,RIP-ARGOFFSET)
306 cmpq $(IA32_NR_syscalls-1),%rax
311 call *ia32_sys_call_table(,%rax,8) # xxx: rip relative
313 movq %rax,RAX-ARGOFFSET(%rsp)
314 CLEAR_RREGS -ARGOFFSET
315 jmp int_ret_from_sys_call
318 #ifdef CONFIG_AUDITSYSCALL
319 testl $(_TIF_WORK_SYSCALL_ENTRY & ~_TIF_SYSCALL_AUDIT),TI_flags+THREAD_INFO(%rsp,RIP-ARGOFFSET)
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 */
330 cmpq $(IA32_NR_syscalls-1),%rax
331 ja int_ret_from_sys_call /* ia32_tracesys has set RAX(%rsp) */
336 movq $0,ORIG_RAX-ARGOFFSET(%rsp)
342 .macro PTREGSCALL label, func, arg
345 leaq \func(%rip),%rax
346 leaq -ARGOFFSET+8(%rsp),\arg /* 8 for return address */
347 jmp ia32_ptregs_common
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
365 CFI_STARTPROC32 simple
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*/
381 jmp ia32_sysret /* misbalances the return cache */
383 END(ia32_ptregs_common)