Merge branches 'pm-cpufreq', 'pm-cpuidle', 'pm-devfreq', 'pm-opp' and 'pm-tools'
[linux-drm-fsl-dcu.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         .macro IA32_ARG_FIXUP noebp=0
34         movl    %edi,%r8d
35         .if \noebp
36         .else
37         movl    %ebp,%r9d
38         .endif
39         xchg    %ecx,%esi
40         movl    %ebx,%edi
41         movl    %edx,%edx       /* zero extension */
42         .endm 
43
44         /* clobbers %eax */     
45         .macro  CLEAR_RREGS offset=0, _r9=rax
46         xorl    %eax,%eax
47         movq    %rax,\offset+R11(%rsp)
48         movq    %rax,\offset+R10(%rsp)
49         movq    %\_r9,\offset+R9(%rsp)
50         movq    %rax,\offset+R8(%rsp)
51         .endm
52
53         /*
54          * Reload arg registers from stack in case ptrace changed them.
55          * We don't reload %eax because syscall_trace_enter() returned
56          * the %rax value we should see.  Instead, we just truncate that
57          * value to 32 bits again as we did on entry from user mode.
58          * If it's a new value set by user_regset during entry tracing,
59          * this matches the normal truncation of the user-mode value.
60          * If it's -1 to make us punt the syscall, then (u32)-1 is still
61          * an appropriately invalid value.
62          */
63         .macro LOAD_ARGS32 offset, _r9=0
64         .if \_r9
65         movl \offset+16(%rsp),%r9d
66         .endif
67         movl \offset+40(%rsp),%ecx
68         movl \offset+48(%rsp),%edx
69         movl \offset+56(%rsp),%esi
70         movl \offset+64(%rsp),%edi
71         movl %eax,%eax                  /* zero extension */
72         .endm
73         
74         .macro CFI_STARTPROC32 simple
75         CFI_STARTPROC   \simple
76         CFI_UNDEFINED   r8
77         CFI_UNDEFINED   r9
78         CFI_UNDEFINED   r10
79         CFI_UNDEFINED   r11
80         CFI_UNDEFINED   r12
81         CFI_UNDEFINED   r13
82         CFI_UNDEFINED   r14
83         CFI_UNDEFINED   r15
84         .endm
85
86 #ifdef CONFIG_PARAVIRT
87 ENTRY(native_usergs_sysret32)
88         swapgs
89         sysretl
90 ENDPROC(native_usergs_sysret32)
91
92 ENTRY(native_irq_enable_sysexit)
93         swapgs
94         sti
95         sysexit
96 ENDPROC(native_irq_enable_sysexit)
97 #endif
98
99 /*
100  * 32bit SYSENTER instruction entry.
101  *
102  * Arguments:
103  * %eax System call number.
104  * %ebx Arg1
105  * %ecx Arg2
106  * %edx Arg3
107  * %esi Arg4
108  * %edi Arg5
109  * %ebp user stack
110  * 0(%ebp) Arg6 
111  *      
112  * Interrupts off.
113  *      
114  * This is purely a fast path. For anything complicated we use the int 0x80
115  * path below.  Set up a complete hardware stack frame to share code
116  * with the int 0x80 path.
117  */     
118 ENTRY(ia32_sysenter_target)
119         CFI_STARTPROC32 simple
120         CFI_SIGNAL_FRAME
121         CFI_DEF_CFA     rsp,0
122         CFI_REGISTER    rsp,rbp
123         SWAPGS_UNSAFE_STACK
124         movq    PER_CPU_VAR(kernel_stack), %rsp
125         addq    $(KERNEL_STACK_OFFSET),%rsp
126         /*
127          * No need to follow this irqs on/off section: the syscall
128          * disabled irqs, here we enable it straight after entry:
129          */
130         ENABLE_INTERRUPTS(CLBR_NONE)
131         movl    %ebp,%ebp               /* zero extension */
132         pushq_cfi $__USER32_DS
133         /*CFI_REL_OFFSET ss,0*/
134         pushq_cfi %rbp
135         CFI_REL_OFFSET rsp,0
136         pushfq_cfi
137         /*CFI_REL_OFFSET rflags,0*/
138         movl    TI_sysenter_return+THREAD_INFO(%rsp,3*8-KERNEL_STACK_OFFSET),%r10d
139         CFI_REGISTER rip,r10
140         pushq_cfi $__USER32_CS
141         /*CFI_REL_OFFSET cs,0*/
142         movl    %eax, %eax
143         pushq_cfi %r10
144         CFI_REL_OFFSET rip,0
145         pushq_cfi %rax
146         cld
147         SAVE_ARGS 0,1,0
148         /* no need to do an access_ok check here because rbp has been
149            32bit zero extended */ 
150         ASM_STAC
151 1:      movl    (%rbp),%ebp
152         _ASM_EXTABLE(1b,ia32_badarg)
153         ASM_CLAC
154
155         /*
156          * Sysenter doesn't filter flags, so we need to clear NT
157          * ourselves.  To save a few cycles, we can check whether
158          * NT was set instead of doing an unconditional popfq.
159          */
160         testl $X86_EFLAGS_NT,EFLAGS-ARGOFFSET(%rsp)
161         jnz sysenter_fix_flags
162 sysenter_flags_fixed:
163
164         orl     $TS_COMPAT,TI_status+THREAD_INFO(%rsp,RIP-ARGOFFSET)
165         testl   $_TIF_WORK_SYSCALL_ENTRY,TI_flags+THREAD_INFO(%rsp,RIP-ARGOFFSET)
166         CFI_REMEMBER_STATE
167         jnz  sysenter_tracesys
168         cmpq    $(IA32_NR_syscalls-1),%rax
169         ja      ia32_badsys
170 sysenter_do_call:
171         IA32_ARG_FIXUP
172 sysenter_dispatch:
173         call    *ia32_sys_call_table(,%rax,8)
174         movq    %rax,RAX-ARGOFFSET(%rsp)
175         DISABLE_INTERRUPTS(CLBR_NONE)
176         TRACE_IRQS_OFF
177         testl   $_TIF_ALLWORK_MASK,TI_flags+THREAD_INFO(%rsp,RIP-ARGOFFSET)
178         jnz     sysexit_audit
179 sysexit_from_sys_call:
180         andl    $~TS_COMPAT,TI_status+THREAD_INFO(%rsp,RIP-ARGOFFSET)
181         /* clear IF, that popfq doesn't enable interrupts early */
182         andl    $~0x200,EFLAGS-ARGOFFSET(%rsp)
183         movl    RIP-ARGOFFSET(%rsp),%edx                /* User %eip */
184         CFI_REGISTER rip,rdx
185         RESTORE_ARGS 0,24,0,0,0,0
186         xorq    %r8,%r8
187         xorq    %r9,%r9
188         xorq    %r10,%r10
189         xorq    %r11,%r11
190         popfq_cfi
191         /*CFI_RESTORE rflags*/
192         popq_cfi %rcx                           /* User %esp */
193         CFI_REGISTER rsp,rcx
194         TRACE_IRQS_ON
195         ENABLE_INTERRUPTS_SYSEXIT32
196
197         CFI_RESTORE_STATE
198
199 #ifdef CONFIG_AUDITSYSCALL
200         .macro auditsys_entry_common
201         movl %esi,%r8d                  /* 5th arg: 4th syscall arg */
202         movl %ecx,%r9d                  /*swap with edx*/
203         movl %edx,%ecx                  /* 4th arg: 3rd syscall arg */
204         movl %r9d,%edx                  /* 3rd arg: 2nd syscall arg */
205         movl %ebx,%esi                  /* 2nd arg: 1st syscall arg */
206         movl %eax,%edi                  /* 1st arg: syscall number */
207         call __audit_syscall_entry
208         movl RAX-ARGOFFSET(%rsp),%eax   /* reload syscall number */
209         cmpq $(IA32_NR_syscalls-1),%rax
210         ja ia32_badsys
211         movl %ebx,%edi                  /* reload 1st syscall arg */
212         movl RCX-ARGOFFSET(%rsp),%esi   /* reload 2nd syscall arg */
213         movl RDX-ARGOFFSET(%rsp),%edx   /* reload 3rd syscall arg */
214         movl RSI-ARGOFFSET(%rsp),%ecx   /* reload 4th syscall arg */
215         movl RDI-ARGOFFSET(%rsp),%r8d   /* reload 5th syscall arg */
216         .endm
217
218         .macro auditsys_exit exit
219         testl $(_TIF_ALLWORK_MASK & ~_TIF_SYSCALL_AUDIT),TI_flags+THREAD_INFO(%rsp,RIP-ARGOFFSET)
220         jnz ia32_ret_from_sys_call
221         TRACE_IRQS_ON
222         ENABLE_INTERRUPTS(CLBR_NONE)
223         movl %eax,%esi          /* second arg, syscall return value */
224         cmpl $-MAX_ERRNO,%eax   /* is it an error ? */
225         jbe 1f
226         movslq %eax, %rsi       /* if error sign extend to 64 bits */
227 1:      setbe %al               /* 1 if error, 0 if not */
228         movzbl %al,%edi         /* zero-extend that into %edi */
229         call __audit_syscall_exit
230         movq RAX-ARGOFFSET(%rsp),%rax   /* reload syscall return value */
231         movl $(_TIF_ALLWORK_MASK & ~_TIF_SYSCALL_AUDIT),%edi
232         DISABLE_INTERRUPTS(CLBR_NONE)
233         TRACE_IRQS_OFF
234         testl %edi,TI_flags+THREAD_INFO(%rsp,RIP-ARGOFFSET)
235         jz \exit
236         CLEAR_RREGS -ARGOFFSET
237         jmp int_with_check
238         .endm
239
240 sysenter_auditsys:
241         auditsys_entry_common
242         movl %ebp,%r9d                  /* reload 6th syscall arg */
243         jmp sysenter_dispatch
244
245 sysexit_audit:
246         auditsys_exit sysexit_from_sys_call
247 #endif
248
249 sysenter_fix_flags:
250         pushq_cfi $(X86_EFLAGS_IF|X86_EFLAGS_FIXED)
251         popfq_cfi
252         jmp sysenter_flags_fixed
253
254 sysenter_tracesys:
255 #ifdef CONFIG_AUDITSYSCALL
256         testl   $(_TIF_WORK_SYSCALL_ENTRY & ~_TIF_SYSCALL_AUDIT),TI_flags+THREAD_INFO(%rsp,RIP-ARGOFFSET)
257         jz      sysenter_auditsys
258 #endif
259         SAVE_REST
260         CLEAR_RREGS
261         movq    $-ENOSYS,RAX(%rsp)/* ptrace can change this for a bad syscall */
262         movq    %rsp,%rdi        /* &pt_regs -> arg1 */
263         call    syscall_trace_enter
264         LOAD_ARGS32 ARGOFFSET  /* reload args from stack in case ptrace changed it */
265         RESTORE_REST
266         cmpq    $(IA32_NR_syscalls-1),%rax
267         ja      int_ret_from_sys_call /* sysenter_tracesys has set RAX(%rsp) */
268         jmp     sysenter_do_call
269         CFI_ENDPROC
270 ENDPROC(ia32_sysenter_target)
271
272 /*
273  * 32bit SYSCALL instruction entry.
274  *
275  * Arguments:
276  * %eax System call number.
277  * %ebx Arg1
278  * %ecx return EIP 
279  * %edx Arg3
280  * %esi Arg4
281  * %edi Arg5
282  * %ebp Arg2    [note: not saved in the stack frame, should not be touched]
283  * %esp user stack 
284  * 0(%esp) Arg6
285  *      
286  * Interrupts off.
287  *      
288  * This is purely a fast path. For anything complicated we use the int 0x80
289  * path below.  Set up a complete hardware stack frame to share code
290  * with the int 0x80 path.      
291  */     
292 ENTRY(ia32_cstar_target)
293         CFI_STARTPROC32 simple
294         CFI_SIGNAL_FRAME
295         CFI_DEF_CFA     rsp,KERNEL_STACK_OFFSET
296         CFI_REGISTER    rip,rcx
297         /*CFI_REGISTER  rflags,r11*/
298         SWAPGS_UNSAFE_STACK
299         movl    %esp,%r8d
300         CFI_REGISTER    rsp,r8
301         movq    PER_CPU_VAR(kernel_stack),%rsp
302         /*
303          * No need to follow this irqs on/off section: the syscall
304          * disabled irqs and here we enable it straight after entry:
305          */
306         ENABLE_INTERRUPTS(CLBR_NONE)
307         SAVE_ARGS 8,0,0
308         movl    %eax,%eax       /* zero extension */
309         movq    %rax,ORIG_RAX-ARGOFFSET(%rsp)
310         movq    %rcx,RIP-ARGOFFSET(%rsp)
311         CFI_REL_OFFSET rip,RIP-ARGOFFSET
312         movq    %rbp,RCX-ARGOFFSET(%rsp) /* this lies slightly to ptrace */
313         movl    %ebp,%ecx
314         movq    $__USER32_CS,CS-ARGOFFSET(%rsp)
315         movq    $__USER32_DS,SS-ARGOFFSET(%rsp)
316         movq    %r11,EFLAGS-ARGOFFSET(%rsp)
317         /*CFI_REL_OFFSET rflags,EFLAGS-ARGOFFSET*/
318         movq    %r8,RSP-ARGOFFSET(%rsp) 
319         CFI_REL_OFFSET rsp,RSP-ARGOFFSET
320         /* no need to do an access_ok check here because r8 has been
321            32bit zero extended */ 
322         /* hardware stack frame is complete now */      
323         ASM_STAC
324 1:      movl    (%r8),%r9d
325         _ASM_EXTABLE(1b,ia32_badarg)
326         ASM_CLAC
327         orl     $TS_COMPAT,TI_status+THREAD_INFO(%rsp,RIP-ARGOFFSET)
328         testl   $_TIF_WORK_SYSCALL_ENTRY,TI_flags+THREAD_INFO(%rsp,RIP-ARGOFFSET)
329         CFI_REMEMBER_STATE
330         jnz   cstar_tracesys
331         cmpq $IA32_NR_syscalls-1,%rax
332         ja  ia32_badsys
333 cstar_do_call:
334         IA32_ARG_FIXUP 1
335 cstar_dispatch:
336         call *ia32_sys_call_table(,%rax,8)
337         movq %rax,RAX-ARGOFFSET(%rsp)
338         DISABLE_INTERRUPTS(CLBR_NONE)
339         TRACE_IRQS_OFF
340         testl $_TIF_ALLWORK_MASK,TI_flags+THREAD_INFO(%rsp,RIP-ARGOFFSET)
341         jnz sysretl_audit
342 sysretl_from_sys_call:
343         andl $~TS_COMPAT,TI_status+THREAD_INFO(%rsp,RIP-ARGOFFSET)
344         RESTORE_ARGS 0,-ARG_SKIP,0,0,0
345         movl RIP-ARGOFFSET(%rsp),%ecx
346         CFI_REGISTER rip,rcx
347         movl EFLAGS-ARGOFFSET(%rsp),%r11d       
348         /*CFI_REGISTER rflags,r11*/
349         xorq    %r10,%r10
350         xorq    %r9,%r9
351         xorq    %r8,%r8
352         TRACE_IRQS_ON
353         movl RSP-ARGOFFSET(%rsp),%esp
354         CFI_RESTORE rsp
355         USERGS_SYSRET32
356         
357 #ifdef CONFIG_AUDITSYSCALL
358 cstar_auditsys:
359         CFI_RESTORE_STATE
360         movl %r9d,R9-ARGOFFSET(%rsp)    /* register to be clobbered by call */
361         auditsys_entry_common
362         movl R9-ARGOFFSET(%rsp),%r9d    /* reload 6th syscall arg */
363         jmp cstar_dispatch
364
365 sysretl_audit:
366         auditsys_exit sysretl_from_sys_call
367 #endif
368
369 cstar_tracesys:
370 #ifdef CONFIG_AUDITSYSCALL
371         testl $(_TIF_WORK_SYSCALL_ENTRY & ~_TIF_SYSCALL_AUDIT),TI_flags+THREAD_INFO(%rsp,RIP-ARGOFFSET)
372         jz cstar_auditsys
373 #endif
374         xchgl %r9d,%ebp
375         SAVE_REST
376         CLEAR_RREGS 0, r9
377         movq $-ENOSYS,RAX(%rsp) /* ptrace can change this for a bad syscall */
378         movq %rsp,%rdi        /* &pt_regs -> arg1 */
379         call syscall_trace_enter
380         LOAD_ARGS32 ARGOFFSET, 1  /* reload args from stack in case ptrace changed it */
381         RESTORE_REST
382         xchgl %ebp,%r9d
383         cmpq $(IA32_NR_syscalls-1),%rax
384         ja int_ret_from_sys_call /* cstar_tracesys has set RAX(%rsp) */
385         jmp cstar_do_call
386 END(ia32_cstar_target)
387                                 
388 ia32_badarg:
389         ASM_CLAC
390         movq $-EFAULT,%rax
391         jmp ia32_sysret
392         CFI_ENDPROC
393
394 /* 
395  * Emulated IA32 system calls via int 0x80. 
396  *
397  * Arguments:    
398  * %eax System call number.
399  * %ebx Arg1
400  * %ecx Arg2
401  * %edx Arg3
402  * %esi Arg4
403  * %edi Arg5
404  * %ebp Arg6    [note: not saved in the stack frame, should not be touched]
405  *
406  * Notes:
407  * Uses the same stack frame as the x86-64 version.     
408  * All registers except %eax must be saved (but ptrace may violate that)
409  * Arguments are zero extended. For system calls that want sign extension and
410  * take long arguments a wrapper is needed. Most calls can just be called
411  * directly.
412  * Assumes it is only called from user space and entered with interrupts off.   
413  */                             
414
415 ENTRY(ia32_syscall)
416         CFI_STARTPROC32 simple
417         CFI_SIGNAL_FRAME
418         CFI_DEF_CFA     rsp,SS+8-RIP
419         /*CFI_REL_OFFSET        ss,SS-RIP*/
420         CFI_REL_OFFSET  rsp,RSP-RIP
421         /*CFI_REL_OFFSET        rflags,EFLAGS-RIP*/
422         /*CFI_REL_OFFSET        cs,CS-RIP*/
423         CFI_REL_OFFSET  rip,RIP-RIP
424         PARAVIRT_ADJUST_EXCEPTION_FRAME
425         SWAPGS
426         /*
427          * No need to follow this irqs on/off section: the syscall
428          * disabled irqs and here we enable it straight after entry:
429          */
430         ENABLE_INTERRUPTS(CLBR_NONE)
431         movl %eax,%eax
432         pushq_cfi %rax
433         cld
434         /* note the registers are not zero extended to the sf.
435            this could be a problem. */
436         SAVE_ARGS 0,1,0
437         orl $TS_COMPAT,TI_status+THREAD_INFO(%rsp,RIP-ARGOFFSET)
438         testl $_TIF_WORK_SYSCALL_ENTRY,TI_flags+THREAD_INFO(%rsp,RIP-ARGOFFSET)
439         jnz ia32_tracesys
440         cmpq $(IA32_NR_syscalls-1),%rax
441         ja ia32_badsys
442 ia32_do_call:
443         IA32_ARG_FIXUP
444         call *ia32_sys_call_table(,%rax,8) # xxx: rip relative
445 ia32_sysret:
446         movq %rax,RAX-ARGOFFSET(%rsp)
447 ia32_ret_from_sys_call:
448         CLEAR_RREGS -ARGOFFSET
449         jmp int_ret_from_sys_call 
450
451 ia32_tracesys:                   
452         SAVE_REST
453         CLEAR_RREGS
454         movq $-ENOSYS,RAX(%rsp) /* ptrace can change this for a bad syscall */
455         movq %rsp,%rdi        /* &pt_regs -> arg1 */
456         call syscall_trace_enter
457         LOAD_ARGS32 ARGOFFSET  /* reload args from stack in case ptrace changed it */
458         RESTORE_REST
459         cmpq $(IA32_NR_syscalls-1),%rax
460         ja  int_ret_from_sys_call       /* ia32_tracesys has set RAX(%rsp) */
461         jmp ia32_do_call
462 END(ia32_syscall)
463
464 ia32_badsys:
465         movq $0,ORIG_RAX-ARGOFFSET(%rsp)
466         movq $-ENOSYS,%rax
467         jmp ia32_sysret
468
469         CFI_ENDPROC
470         
471         .macro PTREGSCALL label, func
472         ALIGN
473 GLOBAL(\label)
474         leaq \func(%rip),%rax
475         jmp  ia32_ptregs_common 
476         .endm
477
478         CFI_STARTPROC32
479
480         PTREGSCALL stub32_rt_sigreturn, sys32_rt_sigreturn
481         PTREGSCALL stub32_sigreturn, sys32_sigreturn
482         PTREGSCALL stub32_execve, compat_sys_execve
483         PTREGSCALL stub32_execveat, compat_sys_execveat
484         PTREGSCALL stub32_fork, sys_fork
485         PTREGSCALL stub32_vfork, sys_vfork
486
487         ALIGN
488 GLOBAL(stub32_clone)
489         leaq sys_clone(%rip),%rax
490         mov     %r8, %rcx
491         jmp  ia32_ptregs_common 
492
493         ALIGN
494 ia32_ptregs_common:
495         popq %r11
496         CFI_ENDPROC
497         CFI_STARTPROC32 simple
498         CFI_SIGNAL_FRAME
499         CFI_DEF_CFA     rsp,SS+8-ARGOFFSET
500         CFI_REL_OFFSET  rax,RAX-ARGOFFSET
501         CFI_REL_OFFSET  rcx,RCX-ARGOFFSET
502         CFI_REL_OFFSET  rdx,RDX-ARGOFFSET
503         CFI_REL_OFFSET  rsi,RSI-ARGOFFSET
504         CFI_REL_OFFSET  rdi,RDI-ARGOFFSET
505         CFI_REL_OFFSET  rip,RIP-ARGOFFSET
506 /*      CFI_REL_OFFSET  cs,CS-ARGOFFSET*/
507 /*      CFI_REL_OFFSET  rflags,EFLAGS-ARGOFFSET*/
508         CFI_REL_OFFSET  rsp,RSP-ARGOFFSET
509 /*      CFI_REL_OFFSET  ss,SS-ARGOFFSET*/
510         SAVE_REST
511         call *%rax
512         RESTORE_REST
513         jmp  ia32_sysret        /* misbalances the return cache */
514         CFI_ENDPROC
515 END(ia32_ptregs_common)