[PATCH] x86_64: Clean up execve path
[linux-2.6/linux-acpi-2.6/ibm-acpi-2.6.git] / arch / x86_64 / kernel / entry.S
blob10ec27b607f180f42b3cf3beafca0569c854fed6
1 /*
2  *  linux/arch/x86_64/entry.S
3  *
4  *  Copyright (C) 1991, 1992  Linus Torvalds
5  *  Copyright (C) 2000, 2001, 2002  Andi Kleen SuSE Labs
6  *  Copyright (C) 2000  Pavel Machek <pavel@suse.cz>
7  * 
8  *  $Id$
9  */
12  * entry.S contains the system-call and fault low-level handling routines.
13  *
14  * NOTE: This code handles signal-recognition, which happens every time
15  * after an interrupt and after each system call.
16  * 
17  * Normal syscalls and interrupts don't save a full stack frame, this is 
18  * only done for syscall tracing, signals or fork/exec et.al.
19  * 
20  * A note on terminology:        
21  * - top of stack: Architecture defined interrupt frame from SS to RIP 
22  * at the top of the kernel process stack.      
23  * - partial stack frame: partially saved registers upto R11.
24  * - full stack frame: Like partial stack frame, but all register saved. 
25  *      
26  * TODO:         
27  * - schedule it carefully for the final hardware.
28  */
30 #define ASSEMBLY 1
31 #include <linux/config.h>
32 #include <linux/linkage.h>
33 #include <asm/segment.h>
34 #include <asm/smp.h>
35 #include <asm/cache.h>
36 #include <asm/errno.h>
37 #include <asm/dwarf2.h>
38 #include <asm/calling.h>
39 #include <asm/asm-offsets.h>
40 #include <asm/msr.h>
41 #include <asm/unistd.h>
42 #include <asm/thread_info.h>
43 #include <asm/hw_irq.h>
44 #include <asm/page.h>
46         .code64
48 #ifndef CONFIG_PREEMPT
49 #define retint_kernel retint_restore_args
50 #endif  
51         
53  * C code is not supposed to know about undefined top of stack. Every time 
54  * a C function with an pt_regs argument is called from the SYSCALL based 
55  * fast path FIXUP_TOP_OF_STACK is needed.
56  * RESTORE_TOP_OF_STACK syncs the syscall state after any possible ptregs
57  * manipulation.
58  */             
59                 
60         /* %rsp:at FRAMEEND */ 
61         .macro FIXUP_TOP_OF_STACK tmp
62         movq    %gs:pda_oldrsp,\tmp
63         movq    \tmp,RSP(%rsp)
64         movq    $__USER_DS,SS(%rsp)
65         movq    $__USER_CS,CS(%rsp)
66         movq    $-1,RCX(%rsp)
67         movq    R11(%rsp),\tmp  /* get eflags */
68         movq    \tmp,EFLAGS(%rsp)
69         .endm
71         .macro RESTORE_TOP_OF_STACK tmp,offset=0
72         movq   RSP-\offset(%rsp),\tmp
73         movq   \tmp,%gs:pda_oldrsp
74         movq   EFLAGS-\offset(%rsp),\tmp
75         movq   \tmp,R11-\offset(%rsp)
76         .endm
78         .macro FAKE_STACK_FRAME child_rip
79         /* push in order ss, rsp, eflags, cs, rip */
80         xorl %eax, %eax
81         pushq %rax /* ss */
82         CFI_ADJUST_CFA_OFFSET   8
83         /*CFI_REL_OFFSET        ss,0*/
84         pushq %rax /* rsp */
85         CFI_ADJUST_CFA_OFFSET   8
86         CFI_REL_OFFSET  rsp,0
87         pushq $(1<<9) /* eflags - interrupts on */
88         CFI_ADJUST_CFA_OFFSET   8
89         /*CFI_REL_OFFSET        rflags,0*/
90         pushq $__KERNEL_CS /* cs */
91         CFI_ADJUST_CFA_OFFSET   8
92         /*CFI_REL_OFFSET        cs,0*/
93         pushq \child_rip /* rip */
94         CFI_ADJUST_CFA_OFFSET   8
95         CFI_REL_OFFSET  rip,0
96         pushq   %rax /* orig rax */
97         CFI_ADJUST_CFA_OFFSET   8
98         .endm
100         .macro UNFAKE_STACK_FRAME
101         addq $8*6, %rsp
102         CFI_ADJUST_CFA_OFFSET   -(6*8)
103         .endm
105         .macro  CFI_DEFAULT_STACK start=1
106         .if \start
107         CFI_STARTPROC   simple
108         CFI_DEF_CFA     rsp,SS+8
109         .else
110         CFI_DEF_CFA_OFFSET SS+8
111         .endif
112         CFI_REL_OFFSET  r15,R15
113         CFI_REL_OFFSET  r14,R14
114         CFI_REL_OFFSET  r13,R13
115         CFI_REL_OFFSET  r12,R12
116         CFI_REL_OFFSET  rbp,RBP
117         CFI_REL_OFFSET  rbx,RBX
118         CFI_REL_OFFSET  r11,R11
119         CFI_REL_OFFSET  r10,R10
120         CFI_REL_OFFSET  r9,R9
121         CFI_REL_OFFSET  r8,R8
122         CFI_REL_OFFSET  rax,RAX
123         CFI_REL_OFFSET  rcx,RCX
124         CFI_REL_OFFSET  rdx,RDX
125         CFI_REL_OFFSET  rsi,RSI
126         CFI_REL_OFFSET  rdi,RDI
127         CFI_REL_OFFSET  rip,RIP
128         /*CFI_REL_OFFSET        cs,CS*/
129         /*CFI_REL_OFFSET        rflags,EFLAGS*/
130         CFI_REL_OFFSET  rsp,RSP
131         /*CFI_REL_OFFSET        ss,SS*/
132         .endm
134  * A newly forked process directly context switches into this.
135  */     
136 /* rdi: prev */ 
137 ENTRY(ret_from_fork)
138         CFI_DEFAULT_STACK
139         call schedule_tail
140         GET_THREAD_INFO(%rcx)
141         testl $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT),threadinfo_flags(%rcx)
142         jnz rff_trace
143 rff_action:     
144         RESTORE_REST
145         testl $3,CS-ARGOFFSET(%rsp)     # from kernel_thread?
146         je   int_ret_from_sys_call
147         testl $_TIF_IA32,threadinfo_flags(%rcx)
148         jnz  int_ret_from_sys_call
149         RESTORE_TOP_OF_STACK %rdi,ARGOFFSET
150         jmp ret_from_sys_call
151 rff_trace:
152         movq %rsp,%rdi
153         call syscall_trace_leave
154         GET_THREAD_INFO(%rcx)   
155         jmp rff_action
156         CFI_ENDPROC
159  * System call entry. Upto 6 arguments in registers are supported.
161  * SYSCALL does not save anything on the stack and does not change the
162  * stack pointer.
163  */
164                 
166  * Register setup:      
167  * rax  system call number
168  * rdi  arg0
169  * rcx  return address for syscall/sysret, C arg3 
170  * rsi  arg1
171  * rdx  arg2    
172  * r10  arg3    (--> moved to rcx for C)
173  * r8   arg4
174  * r9   arg5
175  * r11  eflags for syscall/sysret, temporary for C
176  * r12-r15,rbp,rbx saved by C code, not touched.                
177  * 
178  * Interrupts are off on entry.
179  * Only called from user space.
181  * XXX  if we had a free scratch register we could save the RSP into the stack frame
182  *      and report it properly in ps. Unfortunately we haven't.
183  */                                     
185 ENTRY(system_call)
186         CFI_STARTPROC   simple
187         CFI_DEF_CFA     rsp,0
188         CFI_REGISTER    rip,rcx
189         /*CFI_REGISTER  rflags,r11*/
190         swapgs
191         movq    %rsp,%gs:pda_oldrsp 
192         movq    %gs:pda_kernelstack,%rsp
193         sti                                     
194         SAVE_ARGS 8,1
195         movq  %rax,ORIG_RAX-ARGOFFSET(%rsp) 
196         movq  %rcx,RIP-ARGOFFSET(%rsp)
197         CFI_REL_OFFSET rip,RIP-ARGOFFSET
198         GET_THREAD_INFO(%rcx)
199         testl $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SECCOMP),threadinfo_flags(%rcx)
200         CFI_REMEMBER_STATE
201         jnz tracesys
202         cmpq $__NR_syscall_max,%rax
203         ja badsys
204         movq %r10,%rcx
205         call *sys_call_table(,%rax,8)  # XXX:    rip relative
206         movq %rax,RAX-ARGOFFSET(%rsp)
208  * Syscall return path ending with SYSRET (fast path)
209  * Has incomplete stack frame and undefined top of stack. 
210  */             
211         .globl ret_from_sys_call
212 ret_from_sys_call:
213         movl $_TIF_ALLWORK_MASK,%edi
214         /* edi: flagmask */
215 sysret_check:           
216         GET_THREAD_INFO(%rcx)
217         cli
218         movl threadinfo_flags(%rcx),%edx
219         andl %edi,%edx
220         CFI_REMEMBER_STATE
221         jnz  sysret_careful 
222         movq RIP-ARGOFFSET(%rsp),%rcx
223         CFI_REGISTER    rip,rcx
224         RESTORE_ARGS 0,-ARG_SKIP,1
225         /*CFI_REGISTER  rflags,r11*/
226         movq    %gs:pda_oldrsp,%rsp
227         swapgs
228         sysretq
230         /* Handle reschedules */
231         /* edx: work, edi: workmask */  
232 sysret_careful:
233         CFI_RESTORE_STATE
234         bt $TIF_NEED_RESCHED,%edx
235         jnc sysret_signal
236         sti
237         pushq %rdi
238         CFI_ADJUST_CFA_OFFSET 8
239         call schedule
240         popq  %rdi
241         CFI_ADJUST_CFA_OFFSET -8
242         jmp sysret_check
244         /* Handle a signal */ 
245 sysret_signal:
246         sti
247         testl $(_TIF_SIGPENDING|_TIF_NOTIFY_RESUME|_TIF_SINGLESTEP),%edx
248         jz    1f
250         /* Really a signal */
251         /* edx: work flags (arg3) */
252         leaq do_notify_resume(%rip),%rax
253         leaq -ARGOFFSET(%rsp),%rdi # &pt_regs -> arg1
254         xorl %esi,%esi # oldset -> arg2
255         call ptregscall_common
256 1:      movl $_TIF_NEED_RESCHED,%edi
257         jmp sysret_check
258         
259 badsys:
260         movq $-ENOSYS,RAX-ARGOFFSET(%rsp)
261         jmp ret_from_sys_call
263         /* Do syscall tracing */
264 tracesys:                        
265         CFI_RESTORE_STATE
266         SAVE_REST
267         movq $-ENOSYS,RAX(%rsp)
268         FIXUP_TOP_OF_STACK %rdi
269         movq %rsp,%rdi
270         call syscall_trace_enter
271         LOAD_ARGS ARGOFFSET  /* reload args from stack in case ptrace changed it */
272         RESTORE_REST
273         cmpq $__NR_syscall_max,%rax
274         ja  1f
275         movq %r10,%rcx  /* fixup for C */
276         call *sys_call_table(,%rax,8)
277         movq %rax,RAX-ARGOFFSET(%rsp)
278 1:      SAVE_REST
279         movq %rsp,%rdi
280         call syscall_trace_leave
281         RESTORE_TOP_OF_STACK %rbx
282         RESTORE_REST
283         jmp ret_from_sys_call
284         CFI_ENDPROC
285                 
286 /* 
287  * Syscall return path ending with IRET.
288  * Has correct top of stack, but partial stack frame.
289  */     
290 ENTRY(int_ret_from_sys_call)
291         CFI_STARTPROC   simple
292         CFI_DEF_CFA     rsp,SS+8-ARGOFFSET
293         /*CFI_REL_OFFSET        ss,SS-ARGOFFSET*/
294         CFI_REL_OFFSET  rsp,RSP-ARGOFFSET
295         /*CFI_REL_OFFSET        rflags,EFLAGS-ARGOFFSET*/
296         /*CFI_REL_OFFSET        cs,CS-ARGOFFSET*/
297         CFI_REL_OFFSET  rip,RIP-ARGOFFSET
298         CFI_REL_OFFSET  rdx,RDX-ARGOFFSET
299         CFI_REL_OFFSET  rcx,RCX-ARGOFFSET
300         CFI_REL_OFFSET  rax,RAX-ARGOFFSET
301         CFI_REL_OFFSET  rdi,RDI-ARGOFFSET
302         CFI_REL_OFFSET  rsi,RSI-ARGOFFSET
303         CFI_REL_OFFSET  r8,R8-ARGOFFSET
304         CFI_REL_OFFSET  r9,R9-ARGOFFSET
305         CFI_REL_OFFSET  r10,R10-ARGOFFSET
306         CFI_REL_OFFSET  r11,R11-ARGOFFSET
307         cli
308         testl $3,CS-ARGOFFSET(%rsp)
309         je retint_restore_args
310         movl $_TIF_ALLWORK_MASK,%edi
311         /* edi: mask to check */
312 int_with_check:
313         GET_THREAD_INFO(%rcx)
314         movl threadinfo_flags(%rcx),%edx
315         andl %edi,%edx
316         jnz   int_careful
317         andl    $~TS_COMPAT,threadinfo_status(%rcx)
318         jmp   retint_swapgs
320         /* Either reschedule or signal or syscall exit tracking needed. */
321         /* First do a reschedule test. */
322         /* edx: work, edi: workmask */
323 int_careful:
324         bt $TIF_NEED_RESCHED,%edx
325         jnc  int_very_careful
326         sti
327         pushq %rdi
328         CFI_ADJUST_CFA_OFFSET 8
329         call schedule
330         popq %rdi
331         CFI_ADJUST_CFA_OFFSET -8
332         cli
333         jmp int_with_check
335         /* handle signals and tracing -- both require a full stack frame */
336 int_very_careful:
337         sti
338         SAVE_REST
339         /* Check for syscall exit trace */      
340         testl $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SINGLESTEP),%edx
341         jz int_signal
342         pushq %rdi
343         CFI_ADJUST_CFA_OFFSET 8
344         leaq 8(%rsp),%rdi       # &ptregs -> arg1       
345         call syscall_trace_leave
346         popq %rdi
347         CFI_ADJUST_CFA_OFFSET -8
348         andl $~(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SINGLESTEP),%edi
349         cli
350         jmp int_restore_rest
351         
352 int_signal:
353         testl $(_TIF_NOTIFY_RESUME|_TIF_SIGPENDING|_TIF_SINGLESTEP),%edx
354         jz 1f
355         movq %rsp,%rdi          # &ptregs -> arg1
356         xorl %esi,%esi          # oldset -> arg2
357         call do_notify_resume
358 1:      movl $_TIF_NEED_RESCHED,%edi    
359 int_restore_rest:
360         RESTORE_REST
361         cli
362         jmp int_with_check
363         CFI_ENDPROC
364                 
365 /* 
366  * Certain special system calls that need to save a complete full stack frame.
367  */                                                             
368         
369         .macro PTREGSCALL label,func,arg
370         .globl \label
371 \label:
372         leaq    \func(%rip),%rax
373         leaq    -ARGOFFSET+8(%rsp),\arg /* 8 for return address */
374         jmp     ptregscall_common
375         .endm
377         CFI_STARTPROC
379         PTREGSCALL stub_clone, sys_clone, %r8
380         PTREGSCALL stub_fork, sys_fork, %rdi
381         PTREGSCALL stub_vfork, sys_vfork, %rdi
382         PTREGSCALL stub_rt_sigsuspend, sys_rt_sigsuspend, %rdx
383         PTREGSCALL stub_sigaltstack, sys_sigaltstack, %rdx
384         PTREGSCALL stub_iopl, sys_iopl, %rsi
386 ENTRY(ptregscall_common)
387         popq %r11
388         CFI_ADJUST_CFA_OFFSET -8
389         CFI_REGISTER rip, r11
390         SAVE_REST
391         movq %r11, %r15
392         CFI_REGISTER rip, r15
393         FIXUP_TOP_OF_STACK %r11
394         call *%rax
395         RESTORE_TOP_OF_STACK %r11
396         movq %r15, %r11
397         CFI_REGISTER rip, r11
398         RESTORE_REST
399         pushq %r11
400         CFI_ADJUST_CFA_OFFSET 8
401         CFI_REL_OFFSET rip, 0
402         ret
403         CFI_ENDPROC
404         
405 ENTRY(stub_execve)
406         CFI_STARTPROC
407         popq %r11
408         CFI_ADJUST_CFA_OFFSET -8
409         CFI_REGISTER rip, r11
410         SAVE_REST
411         FIXUP_TOP_OF_STACK %r11
412         call sys_execve
413         RESTORE_TOP_OF_STACK %r11
414         movq %rax,RAX(%rsp)
415         RESTORE_REST
416         jmp int_ret_from_sys_call
417         CFI_ENDPROC
418         
420  * sigreturn is special because it needs to restore all registers on return.
421  * This cannot be done with SYSRET, so use the IRET return path instead.
422  */                
423 ENTRY(stub_rt_sigreturn)
424         CFI_STARTPROC
425         addq $8, %rsp
426         CFI_ADJUST_CFA_OFFSET   -8
427         SAVE_REST
428         movq %rsp,%rdi
429         FIXUP_TOP_OF_STACK %r11
430         call sys_rt_sigreturn
431         movq %rax,RAX(%rsp) # fixme, this could be done at the higher layer
432         RESTORE_REST
433         jmp int_ret_from_sys_call
434         CFI_ENDPROC
437  * initial frame state for interrupts and exceptions
438  */
439         .macro _frame ref
440         CFI_STARTPROC simple
441         CFI_DEF_CFA rsp,SS+8-\ref
442         /*CFI_REL_OFFSET ss,SS-\ref*/
443         CFI_REL_OFFSET rsp,RSP-\ref
444         /*CFI_REL_OFFSET rflags,EFLAGS-\ref*/
445         /*CFI_REL_OFFSET cs,CS-\ref*/
446         CFI_REL_OFFSET rip,RIP-\ref
447         .endm
449 /* initial frame state for interrupts (and exceptions without error code) */
450 #define INTR_FRAME _frame RIP
451 /* initial frame state for exceptions with error code (and interrupts with
452    vector already pushed) */
453 #define XCPT_FRAME _frame ORIG_RAX
455 /* 
456  * Interrupt entry/exit.
458  * Interrupt entry points save only callee clobbered registers in fast path.
459  *      
460  * Entry runs with interrupts off.      
461  */ 
463 /* 0(%rsp): interrupt number */ 
464         .macro interrupt func
465         cld
466 #ifdef CONFIG_DEBUG_INFO
467         SAVE_ALL        
468         movq %rsp,%rdi
469         /*
470          * Setup a stack frame pointer.  This allows gdb to trace
471          * back to the original stack.
472          */
473         movq %rsp,%rbp
474         CFI_DEF_CFA_REGISTER    rbp
475 #else           
476         SAVE_ARGS
477         leaq -ARGOFFSET(%rsp),%rdi      # arg1 for handler
478 #endif  
479         testl $3,CS(%rdi)
480         je 1f
481         swapgs  
482 1:      incl    %gs:pda_irqcount        # RED-PEN should check preempt count
483         movq %gs:pda_irqstackptr,%rax
484         cmoveq %rax,%rsp /*todo This needs CFI annotation! */
485         pushq %rdi                      # save old stack        
486 #ifndef CONFIG_DEBUG_INFO
487         CFI_ADJUST_CFA_OFFSET   8
488 #endif
489         call \func
490         .endm
492 ENTRY(common_interrupt)
493         XCPT_FRAME
494         interrupt do_IRQ
495         /* 0(%rsp): oldrsp-ARGOFFSET */
496 ret_from_intr:
497         popq  %rdi
498 #ifndef CONFIG_DEBUG_INFO
499         CFI_ADJUST_CFA_OFFSET   -8
500 #endif
501         cli     
502         decl %gs:pda_irqcount
503 #ifdef CONFIG_DEBUG_INFO
504         movq RBP(%rdi),%rbp
505         CFI_DEF_CFA_REGISTER    rsp
506 #endif
507         leaq ARGOFFSET(%rdi),%rsp /*todo This needs CFI annotation! */
508 exit_intr:
509         GET_THREAD_INFO(%rcx)
510         testl $3,CS-ARGOFFSET(%rsp)
511         je retint_kernel
512         
513         /* Interrupt came from user space */
514         /*
515          * Has a correct top of stack, but a partial stack frame
516          * %rcx: thread info. Interrupts off.
517          */             
518 retint_with_reschedule:
519         movl $_TIF_WORK_MASK,%edi
520 retint_check:
521         movl threadinfo_flags(%rcx),%edx
522         andl %edi,%edx
523         CFI_REMEMBER_STATE
524         jnz  retint_careful
525 retint_swapgs:          
526         swapgs 
527 retint_restore_args:                            
528         cli
529         RESTORE_ARGS 0,8,0                                              
530 iret_label:     
531         iretq
533         .section __ex_table,"a"
534         .quad iret_label,bad_iret       
535         .previous
536         .section .fixup,"ax"
537         /* force a signal here? this matches i386 behaviour */
538         /* running with kernel gs */
539 bad_iret:
540         movq $11,%rdi   /* SIGSEGV */
541         sti
542         jmp do_exit                     
543         .previous       
544         
545         /* edi: workmask, edx: work */
546 retint_careful:
547         CFI_RESTORE_STATE
548         bt    $TIF_NEED_RESCHED,%edx
549         jnc   retint_signal
550         sti
551         pushq %rdi
552         CFI_ADJUST_CFA_OFFSET   8
553         call  schedule
554         popq %rdi               
555         CFI_ADJUST_CFA_OFFSET   -8
556         GET_THREAD_INFO(%rcx)
557         cli
558         jmp retint_check
559         
560 retint_signal:
561         testl $(_TIF_SIGPENDING|_TIF_NOTIFY_RESUME|_TIF_SINGLESTEP),%edx
562         jz    retint_swapgs
563         sti
564         SAVE_REST
565         movq $-1,ORIG_RAX(%rsp)                         
566         xorl %esi,%esi          # oldset
567         movq %rsp,%rdi          # &pt_regs
568         call do_notify_resume
569         RESTORE_REST
570         cli
571         movl $_TIF_NEED_RESCHED,%edi
572         GET_THREAD_INFO(%rcx)
573         jmp retint_check
575 #ifdef CONFIG_PREEMPT
576         /* Returning to kernel space. Check if we need preemption */
577         /* rcx:  threadinfo. interrupts off. */
578         .p2align
579 retint_kernel:  
580         cmpl $0,threadinfo_preempt_count(%rcx)
581         jnz  retint_restore_args
582         bt  $TIF_NEED_RESCHED,threadinfo_flags(%rcx)
583         jnc  retint_restore_args
584         bt   $9,EFLAGS-ARGOFFSET(%rsp)  /* interrupts off? */
585         jnc  retint_restore_args
586         call preempt_schedule_irq
587         jmp exit_intr
588 #endif  
589         CFI_ENDPROC
590         
592  * APIC interrupts.
593  */             
594         .macro apicinterrupt num,func
595         INTR_FRAME
596         pushq $\num-256
597         CFI_ADJUST_CFA_OFFSET 8
598         interrupt \func
599         jmp ret_from_intr
600         CFI_ENDPROC
601         .endm
603 ENTRY(thermal_interrupt)
604         apicinterrupt THERMAL_APIC_VECTOR,smp_thermal_interrupt
606 ENTRY(threshold_interrupt)
607         apicinterrupt THRESHOLD_APIC_VECTOR,mce_threshold_interrupt
609 #ifdef CONFIG_SMP       
610 ENTRY(reschedule_interrupt)
611         apicinterrupt RESCHEDULE_VECTOR,smp_reschedule_interrupt
613         .macro INVALIDATE_ENTRY num
614 ENTRY(invalidate_interrupt\num)
615         apicinterrupt INVALIDATE_TLB_VECTOR_START+\num,smp_invalidate_interrupt 
616         .endm
618         INVALIDATE_ENTRY 0
619         INVALIDATE_ENTRY 1
620         INVALIDATE_ENTRY 2
621         INVALIDATE_ENTRY 3
622         INVALIDATE_ENTRY 4
623         INVALIDATE_ENTRY 5
624         INVALIDATE_ENTRY 6
625         INVALIDATE_ENTRY 7
627 ENTRY(call_function_interrupt)
628         apicinterrupt CALL_FUNCTION_VECTOR,smp_call_function_interrupt
629 #endif
631 #ifdef CONFIG_X86_LOCAL_APIC    
632 ENTRY(apic_timer_interrupt)
633         apicinterrupt LOCAL_TIMER_VECTOR,smp_apic_timer_interrupt
635 ENTRY(error_interrupt)
636         apicinterrupt ERROR_APIC_VECTOR,smp_error_interrupt
638 ENTRY(spurious_interrupt)
639         apicinterrupt SPURIOUS_APIC_VECTOR,smp_spurious_interrupt
640 #endif
641                                 
643  * Exception entry points.
644  */             
645         .macro zeroentry sym
646         INTR_FRAME
647         pushq $0        /* push error code/oldrax */ 
648         CFI_ADJUST_CFA_OFFSET 8
649         pushq %rax      /* push real oldrax to the rdi slot */ 
650         CFI_ADJUST_CFA_OFFSET 8
651         leaq  \sym(%rip),%rax
652         jmp error_entry
653         CFI_ENDPROC
654         .endm   
656         .macro errorentry sym
657         XCPT_FRAME
658         pushq %rax
659         CFI_ADJUST_CFA_OFFSET 8
660         leaq  \sym(%rip),%rax
661         jmp error_entry
662         CFI_ENDPROC
663         .endm
665         /* error code is on the stack already */
666         /* handle NMI like exceptions that can happen everywhere */
667         .macro paranoidentry sym, ist=0
668         SAVE_ALL
669         cld
670         movl $1,%ebx
671         movl  $MSR_GS_BASE,%ecx
672         rdmsr
673         testl %edx,%edx
674         js    1f
675         swapgs
676         xorl  %ebx,%ebx
678         .if \ist
679         movq    %gs:pda_data_offset, %rbp
680         .endif
681         movq %rsp,%rdi
682         movq ORIG_RAX(%rsp),%rsi
683         movq $-1,ORIG_RAX(%rsp)
684         .if \ist
685         subq    $EXCEPTION_STKSZ, per_cpu__init_tss + TSS_ist + (\ist - 1) * 8(%rbp)
686         .endif
687         call \sym
688         .if \ist
689         addq    $EXCEPTION_STKSZ, per_cpu__init_tss + TSS_ist + (\ist - 1) * 8(%rbp)
690         .endif
691         cli
692         .endm
693         
695  * Exception entry point. This expects an error code/orig_rax on the stack
696  * and the exception handler in %rax.   
697  */                                             
698 ENTRY(error_entry)
699         _frame RDI
700         /* rdi slot contains rax, oldrax contains error code */
701         cld     
702         subq  $14*8,%rsp
703         CFI_ADJUST_CFA_OFFSET   (14*8)
704         movq %rsi,13*8(%rsp)
705         CFI_REL_OFFSET  rsi,RSI
706         movq 14*8(%rsp),%rsi    /* load rax from rdi slot */
707         movq %rdx,12*8(%rsp)
708         CFI_REL_OFFSET  rdx,RDX
709         movq %rcx,11*8(%rsp)
710         CFI_REL_OFFSET  rcx,RCX
711         movq %rsi,10*8(%rsp)    /* store rax */ 
712         CFI_REL_OFFSET  rax,RAX
713         movq %r8, 9*8(%rsp)
714         CFI_REL_OFFSET  r8,R8
715         movq %r9, 8*8(%rsp)
716         CFI_REL_OFFSET  r9,R9
717         movq %r10,7*8(%rsp)
718         CFI_REL_OFFSET  r10,R10
719         movq %r11,6*8(%rsp)
720         CFI_REL_OFFSET  r11,R11
721         movq %rbx,5*8(%rsp) 
722         CFI_REL_OFFSET  rbx,RBX
723         movq %rbp,4*8(%rsp) 
724         CFI_REL_OFFSET  rbp,RBP
725         movq %r12,3*8(%rsp) 
726         CFI_REL_OFFSET  r12,R12
727         movq %r13,2*8(%rsp) 
728         CFI_REL_OFFSET  r13,R13
729         movq %r14,1*8(%rsp) 
730         CFI_REL_OFFSET  r14,R14
731         movq %r15,(%rsp) 
732         CFI_REL_OFFSET  r15,R15
733         xorl %ebx,%ebx  
734         testl $3,CS(%rsp)
735         je  error_kernelspace
736 error_swapgs:   
737         swapgs
738 error_sti:      
739         movq %rdi,RDI(%rsp)     
740         movq %rsp,%rdi
741         movq ORIG_RAX(%rsp),%rsi        /* get error code */ 
742         movq $-1,ORIG_RAX(%rsp)
743         call *%rax
744         /* ebx: no swapgs flag (1: don't need swapgs, 0: need it) */     
745 error_exit:             
746         movl %ebx,%eax          
747         RESTORE_REST
748         cli
749         GET_THREAD_INFO(%rcx)   
750         testl %eax,%eax
751         jne  retint_kernel
752         movl  threadinfo_flags(%rcx),%edx
753         movl  $_TIF_WORK_MASK,%edi
754         andl  %edi,%edx
755         jnz  retint_careful
756         swapgs 
757         RESTORE_ARGS 0,8,0                                              
758         jmp iret_label
759         CFI_ENDPROC
761 error_kernelspace:
762         incl %ebx
763        /* There are two places in the kernel that can potentially fault with
764           usergs. Handle them here. The exception handlers after
765            iret run with kernel gs again, so don't set the user space flag.
766            B stepping K8s sometimes report an truncated RIP for IRET 
767            exceptions returning to compat mode. Check for these here too. */
768         leaq iret_label(%rip),%rbp
769         cmpq %rbp,RIP(%rsp) 
770         je   error_swapgs
771         movl %ebp,%ebp  /* zero extend */
772         cmpq %rbp,RIP(%rsp) 
773         je   error_swapgs
774         cmpq $gs_change,RIP(%rsp)
775         je   error_swapgs
776         jmp  error_sti
777         
778        /* Reload gs selector with exception handling */
779        /* edi:  new selector */ 
780 ENTRY(load_gs_index)
781         CFI_STARTPROC
782         pushf
783         CFI_ADJUST_CFA_OFFSET 8
784         cli
785         swapgs
786 gs_change:     
787         movl %edi,%gs   
788 2:      mfence          /* workaround */
789         swapgs
790         popf
791         CFI_ADJUST_CFA_OFFSET -8
792         ret
793         CFI_ENDPROC
794        
795         .section __ex_table,"a"
796         .align 8
797         .quad gs_change,bad_gs
798         .previous
799         .section .fixup,"ax"
800         /* running with kernelgs */
801 bad_gs: 
802         swapgs                  /* switch back to user gs */
803         xorl %eax,%eax
804         movl %eax,%gs
805         jmp  2b
806         .previous       
807         
809  * Create a kernel thread.
811  * C extern interface:
812  *      extern long kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
814  * asm input arguments:
815  *      rdi: fn, rsi: arg, rdx: flags
816  */
817 ENTRY(kernel_thread)
818         CFI_STARTPROC
819         FAKE_STACK_FRAME $child_rip
820         SAVE_ALL
822         # rdi: flags, rsi: usp, rdx: will be &pt_regs
823         movq %rdx,%rdi
824         orq  kernel_thread_flags(%rip),%rdi
825         movq $-1, %rsi
826         movq %rsp, %rdx
828         xorl %r8d,%r8d
829         xorl %r9d,%r9d
830         
831         # clone now
832         call do_fork
833         movq %rax,RAX(%rsp)
834         xorl %edi,%edi
836         /*
837          * It isn't worth to check for reschedule here,
838          * so internally to the x86_64 port you can rely on kernel_thread()
839          * not to reschedule the child before returning, this avoids the need
840          * of hacks for example to fork off the per-CPU idle tasks.
841          * [Hopefully no generic code relies on the reschedule -AK]     
842          */
843         RESTORE_ALL
844         UNFAKE_STACK_FRAME
845         ret
846         CFI_ENDPROC
848         
849 child_rip:
850         /*
851          * Here we are in the child and the registers are set as they were
852          * at kernel_thread() invocation in the parent.
853          */
854         movq %rdi, %rax
855         movq %rsi, %rdi
856         call *%rax
857         # exit
858         xorl %edi, %edi
859         call do_exit
862  * execve(). This function needs to use IRET, not SYSRET, to set up all state properly.
864  * C extern interface:
865  *       extern long execve(char *name, char **argv, char **envp)
867  * asm input arguments:
868  *      rdi: name, rsi: argv, rdx: envp
870  * We want to fallback into:
871  *      extern long sys_execve(char *name, char **argv,char **envp, struct pt_regs regs)
873  * do_sys_execve asm fallback arguments:
874  *      rdi: name, rsi: argv, rdx: envp, fake frame on the stack
875  */
876 ENTRY(execve)
877         CFI_STARTPROC
878         FAKE_STACK_FRAME $0
879         SAVE_ALL        
880         call sys_execve
881         movq %rax, RAX(%rsp)    
882         RESTORE_REST
883         testq %rax,%rax
884         je int_ret_from_sys_call
885         RESTORE_ARGS
886         UNFAKE_STACK_FRAME
887         ret
888         CFI_ENDPROC
890 KPROBE_ENTRY(page_fault)
891         errorentry do_page_fault
892         .previous .text
894 ENTRY(coprocessor_error)
895         zeroentry do_coprocessor_error
897 ENTRY(simd_coprocessor_error)
898         zeroentry do_simd_coprocessor_error     
900 ENTRY(device_not_available)
901         zeroentry math_state_restore
903         /* runs on exception stack */
904 KPROBE_ENTRY(debug)
905         INTR_FRAME
906         pushq $0
907         CFI_ADJUST_CFA_OFFSET 8         
908         paranoidentry do_debug, DEBUG_STACK
909         jmp paranoid_exit
910         CFI_ENDPROC
911         .previous .text
913         /* runs on exception stack */   
914 KPROBE_ENTRY(nmi)
915         INTR_FRAME
916         pushq $-1
917         CFI_ADJUST_CFA_OFFSET 8
918         paranoidentry do_nmi
919         /*
920          * "Paranoid" exit path from exception stack.
921          * Paranoid because this is used by NMIs and cannot take
922          * any kernel state for granted.
923          * We don't do kernel preemption checks here, because only
924          * NMI should be common and it does not enable IRQs and
925          * cannot get reschedule ticks.
926          */
927         /* ebx: no swapgs flag */
928 paranoid_exit:
929         testl %ebx,%ebx                         /* swapgs needed? */
930         jnz paranoid_restore
931         testl $3,CS(%rsp)
932         jnz   paranoid_userspace
933 paranoid_swapgs:        
934         swapgs
935 paranoid_restore:       
936         RESTORE_ALL 8
937         iretq
938 paranoid_userspace:     
939         GET_THREAD_INFO(%rcx)
940         movl threadinfo_flags(%rcx),%ebx
941         andl $_TIF_WORK_MASK,%ebx
942         jz paranoid_swapgs
943         movq %rsp,%rdi                  /* &pt_regs */
944         call sync_regs
945         movq %rax,%rsp                  /* switch stack for scheduling */
946         testl $_TIF_NEED_RESCHED,%ebx
947         jnz paranoid_schedule
948         movl %ebx,%edx                  /* arg3: thread flags */
949         sti
950         xorl %esi,%esi                  /* arg2: oldset */
951         movq %rsp,%rdi                  /* arg1: &pt_regs */
952         call do_notify_resume
953         cli
954         jmp paranoid_userspace
955 paranoid_schedule:
956         sti
957         call schedule
958         cli
959         jmp paranoid_userspace
960         CFI_ENDPROC
961         .previous .text
963 KPROBE_ENTRY(int3)
964         INTR_FRAME
965         pushq $0
966         CFI_ADJUST_CFA_OFFSET 8
967         paranoidentry do_int3, DEBUG_STACK
968         jmp paranoid_exit
969         CFI_ENDPROC
970         .previous .text
972 ENTRY(overflow)
973         zeroentry do_overflow
975 ENTRY(bounds)
976         zeroentry do_bounds
978 ENTRY(invalid_op)
979         zeroentry do_invalid_op 
981 ENTRY(coprocessor_segment_overrun)
982         zeroentry do_coprocessor_segment_overrun
984 ENTRY(reserved)
985         zeroentry do_reserved
987         /* runs on exception stack */
988 ENTRY(double_fault)
989         XCPT_FRAME
990         paranoidentry do_double_fault
991         jmp paranoid_exit
992         CFI_ENDPROC
994 ENTRY(invalid_TSS)
995         errorentry do_invalid_TSS
997 ENTRY(segment_not_present)
998         errorentry do_segment_not_present
1000         /* runs on exception stack */
1001 ENTRY(stack_segment)
1002         XCPT_FRAME
1003         paranoidentry do_stack_segment
1004         jmp paranoid_exit
1005         CFI_ENDPROC
1007 KPROBE_ENTRY(general_protection)
1008         errorentry do_general_protection
1009         .previous .text
1011 ENTRY(alignment_check)
1012         errorentry do_alignment_check
1014 ENTRY(divide_error)
1015         zeroentry do_divide_error
1017 ENTRY(spurious_interrupt_bug)
1018         zeroentry do_spurious_interrupt_bug
1020 #ifdef CONFIG_X86_MCE
1021         /* runs on exception stack */
1022 ENTRY(machine_check)
1023         INTR_FRAME
1024         pushq $0
1025         CFI_ADJUST_CFA_OFFSET 8 
1026         paranoidentry do_machine_check
1027         jmp paranoid_exit
1028         CFI_ENDPROC
1029 #endif
1031 ENTRY(call_softirq)
1032         CFI_STARTPROC
1033         movq %gs:pda_irqstackptr,%rax
1034         movq %rsp,%rdx
1035         CFI_DEF_CFA_REGISTER    rdx
1036         incl %gs:pda_irqcount
1037         cmove %rax,%rsp
1038         pushq %rdx
1039         /*todo CFI_DEF_CFA_EXPRESSION ...*/
1040         call __do_softirq
1041         popq %rsp
1042         CFI_DEF_CFA_REGISTER    rsp
1043         decl %gs:pda_irqcount
1044         ret
1045         CFI_ENDPROC