Merge branch 'linus' into x86/asm, before applying dependent patch
[cascardo/linux.git] / arch / x86 / ia32 / ia32entry.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 <asm/asm.h>
17 #include <asm/smap.h>
18 #include <linux/linkage.h>
19 #include <linux/err.h>
20
21 /* Avoid __ASSEMBLER__'ifying <linux/audit.h> just for this.  */
22 #include <linux/elf-em.h>
23 #define AUDIT_ARCH_I386         (EM_386|__AUDIT_ARCH_LE)
24 #define __AUDIT_ARCH_LE    0x40000000
25
26 #ifndef CONFIG_AUDITSYSCALL
27 #define sysexit_audit ia32_ret_from_sys_call
28 #define sysretl_audit ia32_ret_from_sys_call
29 #endif
30
31         .section .entry.text, "ax"
32
33         /* clobbers %rax */
34         .macro  CLEAR_RREGS _r9=rax
35         xorl    %eax,%eax
36         movq    %rax,R11(%rsp)
37         movq    %rax,R10(%rsp)
38         movq    %\_r9,R9(%rsp)
39         movq    %rax,R8(%rsp)
40         .endm
41
42         /*
43          * Reload arg registers from stack in case ptrace changed them.
44          * We don't reload %eax because syscall_trace_enter() returned
45          * the %rax value we should see.  Instead, we just truncate that
46          * value to 32 bits again as we did on entry from user mode.
47          * If it's a new value set by user_regset during entry tracing,
48          * this matches the normal truncation of the user-mode value.
49          * If it's -1 to make us punt the syscall, then (u32)-1 is still
50          * an appropriately invalid value.
51          */
52         .macro LOAD_ARGS32 _r9=0
53         .if \_r9
54         movl R9(%rsp),%r9d
55         .endif
56         movl RCX(%rsp),%ecx
57         movl RDX(%rsp),%edx
58         movl RSI(%rsp),%esi
59         movl RDI(%rsp),%edi
60         movl %eax,%eax                  /* zero extension */
61         .endm
62         
63         .macro CFI_STARTPROC32 simple
64         CFI_STARTPROC   \simple
65         CFI_UNDEFINED   r8
66         CFI_UNDEFINED   r9
67         CFI_UNDEFINED   r10
68         CFI_UNDEFINED   r11
69         CFI_UNDEFINED   r12
70         CFI_UNDEFINED   r13
71         CFI_UNDEFINED   r14
72         CFI_UNDEFINED   r15
73         .endm
74
75 #ifdef CONFIG_PARAVIRT
76 ENTRY(native_usergs_sysret32)
77         swapgs
78         sysretl
79 ENDPROC(native_usergs_sysret32)
80 #endif
81
82 /*
83  * 32bit SYSENTER instruction entry.
84  *
85  * SYSENTER loads ss, rsp, cs, and rip from previously programmed MSRs.
86  * IF and VM in rflags are cleared (IOW: interrupts are off).
87  * SYSENTER does not save anything on the stack,
88  * and does not save old rip (!!!) and rflags.
89  *
90  * Arguments:
91  * eax  system call number
92  * ebx  arg1
93  * ecx  arg2
94  * edx  arg3
95  * esi  arg4
96  * edi  arg5
97  * ebp  user stack
98  * 0(%ebp) arg6
99  *
100  * This is purely a fast path. For anything complicated we use the int 0x80
101  * path below. We set up a complete hardware stack frame to share code
102  * with the int 0x80 path.
103  */
104 ENTRY(ia32_sysenter_target)
105         CFI_STARTPROC32 simple
106         CFI_SIGNAL_FRAME
107         CFI_DEF_CFA     rsp,0
108         CFI_REGISTER    rsp,rbp
109
110         /*
111          * Interrupts are off on entry.
112          * We do not frame this tiny irq-off block with TRACE_IRQS_OFF/ON,
113          * it is too small to ever cause noticeable irq latency.
114          */
115         SWAPGS_UNSAFE_STACK
116         movq    PER_CPU_VAR(cpu_tss + TSS_sp0), %rsp
117         ENABLE_INTERRUPTS(CLBR_NONE)
118
119         /* Zero-extending 32-bit regs, do not remove */
120         movl    %ebp, %ebp
121         movl    %eax, %eax
122
123         movl    ASM_THREAD_INFO(TI_sysenter_return, %rsp, 0), %r10d
124         CFI_REGISTER rip,r10
125
126         /* Construct struct pt_regs on stack */
127         pushq_cfi       $__USER32_DS            /* pt_regs->ss */
128         pushq_cfi       %rbp                    /* pt_regs->sp */
129         CFI_REL_OFFSET  rsp,0
130         pushfq_cfi                              /* pt_regs->flags */
131         pushq_cfi       $__USER32_CS            /* pt_regs->cs */
132         pushq_cfi       %r10 /* pt_regs->ip = thread_info->sysenter_return */
133         CFI_REL_OFFSET  rip,0
134         pushq_cfi_reg   rax                     /* pt_regs->orig_ax */
135         pushq_cfi_reg   rdi                     /* pt_regs->di */
136         pushq_cfi_reg   rsi                     /* pt_regs->si */
137         pushq_cfi_reg   rdx                     /* pt_regs->dx */
138         pushq_cfi_reg   rcx                     /* pt_regs->cx */
139         pushq_cfi       $-ENOSYS                /* pt_regs->ax */
140         cld
141         sub     $(10*8),%rsp /* pt_regs->r8-11,bp,bx,r12-15 not saved */
142         CFI_ADJUST_CFA_OFFSET 10*8
143
144         /*
145          * no need to do an access_ok check here because rbp has been
146          * 32bit zero extended
147          */
148         ASM_STAC
149 1:      movl    (%rbp),%ebp
150         _ASM_EXTABLE(1b,ia32_badarg)
151         ASM_CLAC
152
153         /*
154          * Sysenter doesn't filter flags, so we need to clear NT
155          * ourselves.  To save a few cycles, we can check whether
156          * NT was set instead of doing an unconditional popfq.
157          */
158         testl $X86_EFLAGS_NT,EFLAGS(%rsp)
159         jnz sysenter_fix_flags
160 sysenter_flags_fixed:
161
162         orl     $TS_COMPAT, ASM_THREAD_INFO(TI_status, %rsp, SIZEOF_PTREGS)
163         testl   $_TIF_WORK_SYSCALL_ENTRY, ASM_THREAD_INFO(TI_flags, %rsp, SIZEOF_PTREGS)
164         CFI_REMEMBER_STATE
165         jnz  sysenter_tracesys
166 sysenter_do_call:
167         /* 32bit syscall -> 64bit C ABI argument conversion */
168         movl    %edi,%r8d       /* arg5 */
169         movl    %ebp,%r9d       /* arg6 */
170         xchg    %ecx,%esi       /* rsi:arg2, rcx:arg4 */
171         movl    %ebx,%edi       /* arg1 */
172         movl    %edx,%edx       /* arg3 (zero extension) */
173 sysenter_dispatch:
174         cmpq    $(IA32_NR_syscalls-1),%rax
175         ja      1f
176         call    *ia32_sys_call_table(,%rax,8)
177         movq    %rax,RAX(%rsp)
178 1:
179         DISABLE_INTERRUPTS(CLBR_NONE)
180         TRACE_IRQS_OFF
181         testl   $_TIF_ALLWORK_MASK, ASM_THREAD_INFO(TI_flags, %rsp, SIZEOF_PTREGS)
182         jnz     sysexit_audit
183 sysexit_from_sys_call:
184         /*
185          * NB: SYSEXIT is not obviously safe for 64-bit kernels -- an
186          * NMI between STI and SYSEXIT has poorly specified behavior,
187          * and and NMI followed by an IRQ with usergs is fatal.  So
188          * we just pretend we're using SYSEXIT but we really use
189          * SYSRETL instead.
190          *
191          * This code path is still called 'sysexit' because it pairs
192          * with 'sysenter' and it uses the SYSENTER calling convention.
193          */
194         andl    $~TS_COMPAT,ASM_THREAD_INFO(TI_status, %rsp, SIZEOF_PTREGS)
195         movl    RIP(%rsp),%ecx          /* User %eip */
196         CFI_REGISTER rip,rcx
197         RESTORE_RSI_RDI
198         xorl    %edx,%edx               /* avoid info leaks */
199         xorq    %r8,%r8
200         xorq    %r9,%r9
201         xorq    %r10,%r10
202         movl    EFLAGS(%rsp),%r11d      /* User eflags */
203         /*CFI_RESTORE rflags*/
204         TRACE_IRQS_ON
205
206         /*
207          * SYSRETL works even on Intel CPUs.  Use it in preference to SYSEXIT,
208          * since it avoids a dicey window with interrupts enabled.
209          */
210         movl    RSP(%rsp),%esp
211
212         /*
213          * USERGS_SYSRET32 does:
214          *  gsbase = user's gs base
215          *  eip = ecx
216          *  rflags = r11
217          *  cs = __USER32_CS
218          *  ss = __USER_DS
219          *
220          * The prologue set RIP(%rsp) to VDSO32_SYSENTER_RETURN, which does:
221          *
222          *  pop %ebp
223          *  pop %edx
224          *  pop %ecx
225          *
226          * Therefore, we invoke SYSRETL with EDX and R8-R10 zeroed to
227          * avoid info leaks.  R11 ends up with VDSO32_SYSENTER_RETURN's
228          * address (already known to user code), and R12-R15 are
229          * callee-saved and therefore don't contain any interesting
230          * kernel data.
231          */
232         USERGS_SYSRET32
233
234         CFI_RESTORE_STATE
235
236 #ifdef CONFIG_AUDITSYSCALL
237         .macro auditsys_entry_common
238         movl %esi,%r8d                  /* 5th arg: 4th syscall arg */
239         movl %ecx,%r9d                  /*swap with edx*/
240         movl %edx,%ecx                  /* 4th arg: 3rd syscall arg */
241         movl %r9d,%edx                  /* 3rd arg: 2nd syscall arg */
242         movl %ebx,%esi                  /* 2nd arg: 1st syscall arg */
243         movl %eax,%edi                  /* 1st arg: syscall number */
244         call __audit_syscall_entry
245         movl ORIG_RAX(%rsp),%eax        /* reload syscall number */
246         movl %ebx,%edi                  /* reload 1st syscall arg */
247         movl RCX(%rsp),%esi     /* reload 2nd syscall arg */
248         movl RDX(%rsp),%edx     /* reload 3rd syscall arg */
249         movl RSI(%rsp),%ecx     /* reload 4th syscall arg */
250         movl RDI(%rsp),%r8d     /* reload 5th syscall arg */
251         .endm
252
253         .macro auditsys_exit exit
254         testl $(_TIF_ALLWORK_MASK & ~_TIF_SYSCALL_AUDIT), ASM_THREAD_INFO(TI_flags, %rsp, SIZEOF_PTREGS)
255         jnz ia32_ret_from_sys_call
256         TRACE_IRQS_ON
257         ENABLE_INTERRUPTS(CLBR_NONE)
258         movl %eax,%esi          /* second arg, syscall return value */
259         cmpl $-MAX_ERRNO,%eax   /* is it an error ? */
260         jbe 1f
261         movslq %eax, %rsi       /* if error sign extend to 64 bits */
262 1:      setbe %al               /* 1 if error, 0 if not */
263         movzbl %al,%edi         /* zero-extend that into %edi */
264         call __audit_syscall_exit
265         movq RAX(%rsp),%rax     /* reload syscall return value */
266         movl $(_TIF_ALLWORK_MASK & ~_TIF_SYSCALL_AUDIT),%edi
267         DISABLE_INTERRUPTS(CLBR_NONE)
268         TRACE_IRQS_OFF
269         testl %edi, ASM_THREAD_INFO(TI_flags, %rsp, SIZEOF_PTREGS)
270         jz \exit
271         CLEAR_RREGS
272         jmp int_with_check
273         .endm
274
275 sysenter_auditsys:
276         auditsys_entry_common
277         movl %ebp,%r9d                  /* reload 6th syscall arg */
278         jmp sysenter_dispatch
279
280 sysexit_audit:
281         auditsys_exit sysexit_from_sys_call
282 #endif
283
284 sysenter_fix_flags:
285         pushq_cfi $(X86_EFLAGS_IF|X86_EFLAGS_FIXED)
286         popfq_cfi
287         jmp sysenter_flags_fixed
288
289 sysenter_tracesys:
290 #ifdef CONFIG_AUDITSYSCALL
291         testl   $(_TIF_WORK_SYSCALL_ENTRY & ~_TIF_SYSCALL_AUDIT), ASM_THREAD_INFO(TI_flags, %rsp, SIZEOF_PTREGS)
292         jz      sysenter_auditsys
293 #endif
294         SAVE_EXTRA_REGS
295         CLEAR_RREGS
296         movq    %rsp,%rdi        /* &pt_regs -> arg1 */
297         call    syscall_trace_enter
298         LOAD_ARGS32  /* reload args from stack in case ptrace changed it */
299         RESTORE_EXTRA_REGS
300         jmp     sysenter_do_call
301         CFI_ENDPROC
302 ENDPROC(ia32_sysenter_target)
303
304 /*
305  * 32bit SYSCALL instruction entry.
306  *
307  * 32bit SYSCALL saves rip to rcx, clears rflags.RF, then saves rflags to r11,
308  * then loads new ss, cs, and rip from previously programmed MSRs.
309  * rflags gets masked by a value from another MSR (so CLD and CLAC
310  * are not needed). SYSCALL does not save anything on the stack
311  * and does not change rsp.
312  *
313  * Note: rflags saving+masking-with-MSR happens only in Long mode
314  * (in legacy 32bit mode, IF, RF and VM bits are cleared and that's it).
315  * Don't get confused: rflags saving+masking depends on Long Mode Active bit
316  * (EFER.LMA=1), NOT on bitness of userspace where SYSCALL executes
317  * or target CS descriptor's L bit (SYSCALL does not read segment descriptors).
318  *
319  * Arguments:
320  * eax  system call number
321  * ecx  return address
322  * ebx  arg1
323  * ebp  arg2    (note: not saved in the stack frame, should not be touched)
324  * edx  arg3
325  * esi  arg4
326  * edi  arg5
327  * esp  user stack
328  * 0(%esp) arg6
329  *
330  * This is purely a fast path. For anything complicated we use the int 0x80
331  * path below. We set up a complete hardware stack frame to share code
332  * with the int 0x80 path.
333  */
334 ENTRY(ia32_cstar_target)
335         CFI_STARTPROC32 simple
336         CFI_SIGNAL_FRAME
337         CFI_DEF_CFA     rsp,0
338         CFI_REGISTER    rip,rcx
339         /*CFI_REGISTER  rflags,r11*/
340
341         /*
342          * Interrupts are off on entry.
343          * We do not frame this tiny irq-off block with TRACE_IRQS_OFF/ON,
344          * it is too small to ever cause noticeable irq latency.
345          */
346         SWAPGS_UNSAFE_STACK
347         movl    %esp,%r8d
348         CFI_REGISTER    rsp,r8
349         movq    PER_CPU_VAR(kernel_stack),%rsp
350         ENABLE_INTERRUPTS(CLBR_NONE)
351
352         /* Zero-extending 32-bit regs, do not remove */
353         movl    %eax,%eax
354
355         /* Construct struct pt_regs on stack */
356         pushq_cfi       $__USER32_DS            /* pt_regs->ss */
357         pushq_cfi       %r8                     /* pt_regs->sp */
358         CFI_REL_OFFSET rsp,0
359         pushq_cfi       %r11                    /* pt_regs->flags */
360         pushq_cfi       $__USER32_CS            /* pt_regs->cs */
361         pushq_cfi       %rcx                    /* pt_regs->ip */
362         CFI_REL_OFFSET rip,0
363         pushq_cfi_reg   rax                     /* pt_regs->orig_ax */
364         pushq_cfi_reg   rdi                     /* pt_regs->di */
365         pushq_cfi_reg   rsi                     /* pt_regs->si */
366         pushq_cfi_reg   rdx                     /* pt_regs->dx */
367         pushq_cfi_reg   rbp                     /* pt_regs->cx */
368         movl    %ebp,%ecx
369         pushq_cfi       $-ENOSYS                /* pt_regs->ax */
370         sub     $(10*8),%rsp /* pt_regs->r8-11,bp,bx,r12-15 not saved */
371         CFI_ADJUST_CFA_OFFSET 10*8
372
373         /*
374          * no need to do an access_ok check here because r8 has been
375          * 32bit zero extended
376          */
377         ASM_STAC
378 1:      movl    (%r8),%r9d
379         _ASM_EXTABLE(1b,ia32_badarg)
380         ASM_CLAC
381         orl     $TS_COMPAT, ASM_THREAD_INFO(TI_status, %rsp, SIZEOF_PTREGS)
382         testl   $_TIF_WORK_SYSCALL_ENTRY, ASM_THREAD_INFO(TI_flags, %rsp, SIZEOF_PTREGS)
383         CFI_REMEMBER_STATE
384         jnz   cstar_tracesys
385 cstar_do_call:
386         /* 32bit syscall -> 64bit C ABI argument conversion */
387         movl    %edi,%r8d       /* arg5 */
388         /* r9 already loaded */ /* arg6 */
389         xchg    %ecx,%esi       /* rsi:arg2, rcx:arg4 */
390         movl    %ebx,%edi       /* arg1 */
391         movl    %edx,%edx       /* arg3 (zero extension) */
392 cstar_dispatch:
393         cmpq    $(IA32_NR_syscalls-1),%rax
394         ja      1f
395         call *ia32_sys_call_table(,%rax,8)
396         movq %rax,RAX(%rsp)
397 1:
398         DISABLE_INTERRUPTS(CLBR_NONE)
399         TRACE_IRQS_OFF
400         testl $_TIF_ALLWORK_MASK, ASM_THREAD_INFO(TI_flags, %rsp, SIZEOF_PTREGS)
401         jnz sysretl_audit
402 sysretl_from_sys_call:
403         andl $~TS_COMPAT, ASM_THREAD_INFO(TI_status, %rsp, SIZEOF_PTREGS)
404         RESTORE_RSI_RDI_RDX
405         movl RIP(%rsp),%ecx
406         CFI_REGISTER rip,rcx
407         movl EFLAGS(%rsp),%r11d
408         /*CFI_REGISTER rflags,r11*/
409         xorq    %r10,%r10
410         xorq    %r9,%r9
411         xorq    %r8,%r8
412         TRACE_IRQS_ON
413         movl RSP(%rsp),%esp
414         CFI_RESTORE rsp
415         /*
416          * 64bit->32bit SYSRET restores eip from ecx,
417          * eflags from r11 (but RF and VM bits are forced to 0),
418          * cs and ss are loaded from MSRs.
419          * (Note: 32bit->32bit SYSRET is different: since r11
420          * does not exist, it merely sets eflags.IF=1).
421          *
422          * NB: On AMD CPUs with the X86_BUG_SYSRET_SS_ATTRS bug, the ss
423          * descriptor is not reinitialized.  This means that we must
424          * avoid SYSRET with SS == NULL, which could happen if we schedule,
425          * exit the kernel, and re-enter using an interrupt vector.  (All
426          * interrupt entries on x86_64 set SS to NULL.)  We prevent that
427          * from happening by reloading SS in __switch_to.
428          */
429         USERGS_SYSRET32
430
431 #ifdef CONFIG_AUDITSYSCALL
432 cstar_auditsys:
433         CFI_RESTORE_STATE
434         movl %r9d,R9(%rsp)      /* register to be clobbered by call */
435         auditsys_entry_common
436         movl R9(%rsp),%r9d      /* reload 6th syscall arg */
437         jmp cstar_dispatch
438
439 sysretl_audit:
440         auditsys_exit sysretl_from_sys_call
441 #endif
442
443 cstar_tracesys:
444 #ifdef CONFIG_AUDITSYSCALL
445         testl $(_TIF_WORK_SYSCALL_ENTRY & ~_TIF_SYSCALL_AUDIT), ASM_THREAD_INFO(TI_flags, %rsp, SIZEOF_PTREGS)
446         jz cstar_auditsys
447 #endif
448         xchgl %r9d,%ebp
449         SAVE_EXTRA_REGS
450         CLEAR_RREGS r9
451         movq %rsp,%rdi        /* &pt_regs -> arg1 */
452         call syscall_trace_enter
453         LOAD_ARGS32 1   /* reload args from stack in case ptrace changed it */
454         RESTORE_EXTRA_REGS
455         xchgl %ebp,%r9d
456         jmp cstar_do_call
457 END(ia32_cstar_target)
458                                 
459 ia32_badarg:
460         ASM_CLAC
461         movq $-EFAULT,%rax
462         jmp ia32_sysret
463         CFI_ENDPROC
464
465 /*
466  * Emulated IA32 system calls via int 0x80.
467  *
468  * Arguments:
469  * eax  system call number
470  * ebx  arg1
471  * ecx  arg2
472  * edx  arg3
473  * esi  arg4
474  * edi  arg5
475  * ebp  arg6    (note: not saved in the stack frame, should not be touched)
476  *
477  * Notes:
478  * Uses the same stack frame as the x86-64 version.
479  * All registers except eax must be saved (but ptrace may violate that).
480  * Arguments are zero extended. For system calls that want sign extension and
481  * take long arguments a wrapper is needed. Most calls can just be called
482  * directly.
483  * Assumes it is only called from user space and entered with interrupts off.
484  */
485
486 ENTRY(ia32_syscall)
487         CFI_STARTPROC32 simple
488         CFI_SIGNAL_FRAME
489         CFI_DEF_CFA     rsp,5*8
490         /*CFI_REL_OFFSET        ss,4*8 */
491         CFI_REL_OFFSET  rsp,3*8
492         /*CFI_REL_OFFSET        rflags,2*8 */
493         /*CFI_REL_OFFSET        cs,1*8 */
494         CFI_REL_OFFSET  rip,0*8
495
496         /*
497          * Interrupts are off on entry.
498          * We do not frame this tiny irq-off block with TRACE_IRQS_OFF/ON,
499          * it is too small to ever cause noticeable irq latency.
500          */
501         PARAVIRT_ADJUST_EXCEPTION_FRAME
502         SWAPGS
503         ENABLE_INTERRUPTS(CLBR_NONE)
504
505         /* Zero-extending 32-bit regs, do not remove */
506         movl    %eax,%eax
507
508         /* Construct struct pt_regs on stack (iret frame is already on stack) */
509         pushq_cfi_reg   rax                     /* pt_regs->orig_ax */
510         pushq_cfi_reg   rdi                     /* pt_regs->di */
511         pushq_cfi_reg   rsi                     /* pt_regs->si */
512         pushq_cfi_reg   rdx                     /* pt_regs->dx */
513         pushq_cfi_reg   rcx                     /* pt_regs->cx */
514         pushq_cfi       $-ENOSYS                /* pt_regs->ax */
515         cld
516         sub     $(10*8),%rsp /* pt_regs->r8-11,bp,bx,r12-15 not saved */
517         CFI_ADJUST_CFA_OFFSET 10*8
518
519         orl $TS_COMPAT, ASM_THREAD_INFO(TI_status, %rsp, SIZEOF_PTREGS)
520         testl $_TIF_WORK_SYSCALL_ENTRY, ASM_THREAD_INFO(TI_flags, %rsp, SIZEOF_PTREGS)
521         jnz ia32_tracesys
522 ia32_do_call:
523         /* 32bit syscall -> 64bit C ABI argument conversion */
524         movl %edi,%r8d  /* arg5 */
525         movl %ebp,%r9d  /* arg6 */
526         xchg %ecx,%esi  /* rsi:arg2, rcx:arg4 */
527         movl %ebx,%edi  /* arg1 */
528         movl %edx,%edx  /* arg3 (zero extension) */
529         cmpq    $(IA32_NR_syscalls-1),%rax
530         ja      1f
531         call *ia32_sys_call_table(,%rax,8) # xxx: rip relative
532 ia32_sysret:
533         movq %rax,RAX(%rsp)
534 1:
535 ia32_ret_from_sys_call:
536         CLEAR_RREGS
537         jmp int_ret_from_sys_call
538
539 ia32_tracesys:
540         SAVE_EXTRA_REGS
541         CLEAR_RREGS
542         movq %rsp,%rdi        /* &pt_regs -> arg1 */
543         call syscall_trace_enter
544         LOAD_ARGS32     /* reload args from stack in case ptrace changed it */
545         RESTORE_EXTRA_REGS
546         jmp ia32_do_call
547         CFI_ENDPROC
548 END(ia32_syscall)
549
550         .macro PTREGSCALL label, func
551         ALIGN
552 GLOBAL(\label)
553         leaq \func(%rip),%rax
554         jmp  ia32_ptregs_common 
555         .endm
556
557         CFI_STARTPROC32
558
559         PTREGSCALL stub32_rt_sigreturn, sys32_rt_sigreturn
560         PTREGSCALL stub32_sigreturn, sys32_sigreturn
561         PTREGSCALL stub32_fork, sys_fork
562         PTREGSCALL stub32_vfork, sys_vfork
563
564         ALIGN
565 GLOBAL(stub32_clone)
566         leaq sys_clone(%rip),%rax
567         mov     %r8, %rcx
568         jmp  ia32_ptregs_common 
569
570         ALIGN
571 ia32_ptregs_common:
572         CFI_ENDPROC
573         CFI_STARTPROC32 simple
574         CFI_SIGNAL_FRAME
575         CFI_DEF_CFA     rsp,SIZEOF_PTREGS
576         CFI_REL_OFFSET  rax,RAX
577         CFI_REL_OFFSET  rcx,RCX
578         CFI_REL_OFFSET  rdx,RDX
579         CFI_REL_OFFSET  rsi,RSI
580         CFI_REL_OFFSET  rdi,RDI
581         CFI_REL_OFFSET  rip,RIP
582 /*      CFI_REL_OFFSET  cs,CS*/
583 /*      CFI_REL_OFFSET  rflags,EFLAGS*/
584         CFI_REL_OFFSET  rsp,RSP
585 /*      CFI_REL_OFFSET  ss,SS*/
586         SAVE_EXTRA_REGS 8
587         call *%rax
588         RESTORE_EXTRA_REGS 8
589         ret
590         CFI_ENDPROC
591 END(ia32_ptregs_common)