[PATCH] via-rhine: zero pad short packets on Rhine I ethernet cards
[linux-2.6/linux-acpi-2.6/ibm-acpi-2.6.git] / arch / x86_64 / kernel / entry.S
blobc946e4fe67a7937ab15eba697246602c7dc67dbd
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.
184  * When user can change the frames always force IRET. That is because
185  * it deals with uncanonical addresses better. SYSRET has trouble
186  * with them due to bugs in both AMD and Intel CPUs.
187  */                                     
189 ENTRY(system_call)
190         CFI_STARTPROC   simple
191         CFI_DEF_CFA     rsp,0
192         CFI_REGISTER    rip,rcx
193         /*CFI_REGISTER  rflags,r11*/
194         swapgs
195         movq    %rsp,%gs:pda_oldrsp 
196         movq    %gs:pda_kernelstack,%rsp
197         sti                                     
198         SAVE_ARGS 8,1
199         movq  %rax,ORIG_RAX-ARGOFFSET(%rsp) 
200         movq  %rcx,RIP-ARGOFFSET(%rsp)
201         CFI_REL_OFFSET rip,RIP-ARGOFFSET
202         GET_THREAD_INFO(%rcx)
203         testl $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SECCOMP),threadinfo_flags(%rcx)
204         CFI_REMEMBER_STATE
205         jnz tracesys
206         cmpq $__NR_syscall_max,%rax
207         ja badsys
208         movq %r10,%rcx
209         call *sys_call_table(,%rax,8)  # XXX:    rip relative
210         movq %rax,RAX-ARGOFFSET(%rsp)
212  * Syscall return path ending with SYSRET (fast path)
213  * Has incomplete stack frame and undefined top of stack. 
214  */             
215         .globl ret_from_sys_call
216 ret_from_sys_call:
217         movl $_TIF_ALLWORK_MASK,%edi
218         /* edi: flagmask */
219 sysret_check:           
220         GET_THREAD_INFO(%rcx)
221         cli
222         movl threadinfo_flags(%rcx),%edx
223         andl %edi,%edx
224         CFI_REMEMBER_STATE
225         jnz  sysret_careful 
226         movq RIP-ARGOFFSET(%rsp),%rcx
227         CFI_REGISTER    rip,rcx
228         RESTORE_ARGS 0,-ARG_SKIP,1
229         /*CFI_REGISTER  rflags,r11*/
230         movq    %gs:pda_oldrsp,%rsp
231         swapgs
232         sysretq
234         /* Handle reschedules */
235         /* edx: work, edi: workmask */  
236 sysret_careful:
237         CFI_RESTORE_STATE
238         bt $TIF_NEED_RESCHED,%edx
239         jnc sysret_signal
240         sti
241         pushq %rdi
242         CFI_ADJUST_CFA_OFFSET 8
243         call schedule
244         popq  %rdi
245         CFI_ADJUST_CFA_OFFSET -8
246         jmp sysret_check
248         /* Handle a signal */ 
249 sysret_signal:
250         sti
251         testl $(_TIF_SIGPENDING|_TIF_NOTIFY_RESUME|_TIF_SINGLESTEP),%edx
252         jz    1f
254         /* Really a signal */
255         /* edx: work flags (arg3) */
256         leaq do_notify_resume(%rip),%rax
257         leaq -ARGOFFSET(%rsp),%rdi # &pt_regs -> arg1
258         xorl %esi,%esi # oldset -> arg2
259         call ptregscall_common
260 1:      movl $_TIF_NEED_RESCHED,%edi
261         /* Use IRET because user could have changed frame. This
262            works because ptregscall_common has called FIXUP_TOP_OF_STACK. */
263         cli
264         jmp int_with_check
265         
266 badsys:
267         movq $-ENOSYS,RAX-ARGOFFSET(%rsp)
268         jmp ret_from_sys_call
270         /* Do syscall tracing */
271 tracesys:                        
272         CFI_RESTORE_STATE
273         SAVE_REST
274         movq $-ENOSYS,RAX(%rsp)
275         FIXUP_TOP_OF_STACK %rdi
276         movq %rsp,%rdi
277         call syscall_trace_enter
278         LOAD_ARGS ARGOFFSET  /* reload args from stack in case ptrace changed it */
279         RESTORE_REST
280         cmpq $__NR_syscall_max,%rax
281         ja  1f
282         movq %r10,%rcx  /* fixup for C */
283         call *sys_call_table(,%rax,8)
284         movq %rax,RAX-ARGOFFSET(%rsp)
285 1:      SAVE_REST
286         movq %rsp,%rdi
287         call syscall_trace_leave
288         RESTORE_TOP_OF_STACK %rbx
289         RESTORE_REST
290         /* Use IRET because user could have changed frame */
291         jmp int_ret_from_sys_call
292         CFI_ENDPROC
293                 
294 /* 
295  * Syscall return path ending with IRET.
296  * Has correct top of stack, but partial stack frame.
297  */     
298 ENTRY(int_ret_from_sys_call)
299         CFI_STARTPROC   simple
300         CFI_DEF_CFA     rsp,SS+8-ARGOFFSET
301         /*CFI_REL_OFFSET        ss,SS-ARGOFFSET*/
302         CFI_REL_OFFSET  rsp,RSP-ARGOFFSET
303         /*CFI_REL_OFFSET        rflags,EFLAGS-ARGOFFSET*/
304         /*CFI_REL_OFFSET        cs,CS-ARGOFFSET*/
305         CFI_REL_OFFSET  rip,RIP-ARGOFFSET
306         CFI_REL_OFFSET  rdx,RDX-ARGOFFSET
307         CFI_REL_OFFSET  rcx,RCX-ARGOFFSET
308         CFI_REL_OFFSET  rax,RAX-ARGOFFSET
309         CFI_REL_OFFSET  rdi,RDI-ARGOFFSET
310         CFI_REL_OFFSET  rsi,RSI-ARGOFFSET
311         CFI_REL_OFFSET  r8,R8-ARGOFFSET
312         CFI_REL_OFFSET  r9,R9-ARGOFFSET
313         CFI_REL_OFFSET  r10,R10-ARGOFFSET
314         CFI_REL_OFFSET  r11,R11-ARGOFFSET
315         cli
316         testl $3,CS-ARGOFFSET(%rsp)
317         je retint_restore_args
318         movl $_TIF_ALLWORK_MASK,%edi
319         /* edi: mask to check */
320 int_with_check:
321         GET_THREAD_INFO(%rcx)
322         movl threadinfo_flags(%rcx),%edx
323         andl %edi,%edx
324         jnz   int_careful
325         andl    $~TS_COMPAT,threadinfo_status(%rcx)
326         jmp   retint_swapgs
328         /* Either reschedule or signal or syscall exit tracking needed. */
329         /* First do a reschedule test. */
330         /* edx: work, edi: workmask */
331 int_careful:
332         bt $TIF_NEED_RESCHED,%edx
333         jnc  int_very_careful
334         sti
335         pushq %rdi
336         CFI_ADJUST_CFA_OFFSET 8
337         call schedule
338         popq %rdi
339         CFI_ADJUST_CFA_OFFSET -8
340         cli
341         jmp int_with_check
343         /* handle signals and tracing -- both require a full stack frame */
344 int_very_careful:
345         sti
346         SAVE_REST
347         /* Check for syscall exit trace */      
348         testl $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SINGLESTEP),%edx
349         jz int_signal
350         pushq %rdi
351         CFI_ADJUST_CFA_OFFSET 8
352         leaq 8(%rsp),%rdi       # &ptregs -> arg1       
353         call syscall_trace_leave
354         popq %rdi
355         CFI_ADJUST_CFA_OFFSET -8
356         andl $~(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SINGLESTEP),%edi
357         cli
358         jmp int_restore_rest
359         
360 int_signal:
361         testl $(_TIF_NOTIFY_RESUME|_TIF_SIGPENDING|_TIF_SINGLESTEP),%edx
362         jz 1f
363         movq %rsp,%rdi          # &ptregs -> arg1
364         xorl %esi,%esi          # oldset -> arg2
365         call do_notify_resume
366 1:      movl $_TIF_NEED_RESCHED,%edi    
367 int_restore_rest:
368         RESTORE_REST
369         cli
370         jmp int_with_check
371         CFI_ENDPROC
372                 
373 /* 
374  * Certain special system calls that need to save a complete full stack frame.
375  */                                                             
376         
377         .macro PTREGSCALL label,func,arg
378         .globl \label
379 \label:
380         leaq    \func(%rip),%rax
381         leaq    -ARGOFFSET+8(%rsp),\arg /* 8 for return address */
382         jmp     ptregscall_common
383         .endm
385         CFI_STARTPROC
387         PTREGSCALL stub_clone, sys_clone, %r8
388         PTREGSCALL stub_fork, sys_fork, %rdi
389         PTREGSCALL stub_vfork, sys_vfork, %rdi
390         PTREGSCALL stub_rt_sigsuspend, sys_rt_sigsuspend, %rdx
391         PTREGSCALL stub_sigaltstack, sys_sigaltstack, %rdx
392         PTREGSCALL stub_iopl, sys_iopl, %rsi
394 ENTRY(ptregscall_common)
395         popq %r11
396         CFI_ADJUST_CFA_OFFSET -8
397         CFI_REGISTER rip, r11
398         SAVE_REST
399         movq %r11, %r15
400         CFI_REGISTER rip, r15
401         FIXUP_TOP_OF_STACK %r11
402         call *%rax
403         RESTORE_TOP_OF_STACK %r11
404         movq %r15, %r11
405         CFI_REGISTER rip, r11
406         RESTORE_REST
407         pushq %r11
408         CFI_ADJUST_CFA_OFFSET 8
409         CFI_REL_OFFSET rip, 0
410         ret
411         CFI_ENDPROC
412         
413 ENTRY(stub_execve)
414         CFI_STARTPROC
415         popq %r11
416         CFI_ADJUST_CFA_OFFSET -8
417         CFI_REGISTER rip, r11
418         SAVE_REST
419         FIXUP_TOP_OF_STACK %r11
420         call sys_execve
421         RESTORE_TOP_OF_STACK %r11
422         movq %rax,RAX(%rsp)
423         RESTORE_REST
424         jmp int_ret_from_sys_call
425         CFI_ENDPROC
426         
428  * sigreturn is special because it needs to restore all registers on return.
429  * This cannot be done with SYSRET, so use the IRET return path instead.
430  */                
431 ENTRY(stub_rt_sigreturn)
432         CFI_STARTPROC
433         addq $8, %rsp
434         CFI_ADJUST_CFA_OFFSET   -8
435         SAVE_REST
436         movq %rsp,%rdi
437         FIXUP_TOP_OF_STACK %r11
438         call sys_rt_sigreturn
439         movq %rax,RAX(%rsp) # fixme, this could be done at the higher layer
440         RESTORE_REST
441         jmp int_ret_from_sys_call
442         CFI_ENDPROC
445  * initial frame state for interrupts and exceptions
446  */
447         .macro _frame ref
448         CFI_STARTPROC simple
449         CFI_DEF_CFA rsp,SS+8-\ref
450         /*CFI_REL_OFFSET ss,SS-\ref*/
451         CFI_REL_OFFSET rsp,RSP-\ref
452         /*CFI_REL_OFFSET rflags,EFLAGS-\ref*/
453         /*CFI_REL_OFFSET cs,CS-\ref*/
454         CFI_REL_OFFSET rip,RIP-\ref
455         .endm
457 /* initial frame state for interrupts (and exceptions without error code) */
458 #define INTR_FRAME _frame RIP
459 /* initial frame state for exceptions with error code (and interrupts with
460    vector already pushed) */
461 #define XCPT_FRAME _frame ORIG_RAX
463 /* 
464  * Interrupt entry/exit.
466  * Interrupt entry points save only callee clobbered registers in fast path.
467  *      
468  * Entry runs with interrupts off.      
469  */ 
471 /* 0(%rsp): interrupt number */ 
472         .macro interrupt func
473         cld
474 #ifdef CONFIG_DEBUG_INFO
475         SAVE_ALL        
476         movq %rsp,%rdi
477         /*
478          * Setup a stack frame pointer.  This allows gdb to trace
479          * back to the original stack.
480          */
481         movq %rsp,%rbp
482         CFI_DEF_CFA_REGISTER    rbp
483 #else           
484         SAVE_ARGS
485         leaq -ARGOFFSET(%rsp),%rdi      # arg1 for handler
486 #endif  
487         testl $3,CS(%rdi)
488         je 1f
489         swapgs  
490 1:      incl    %gs:pda_irqcount        # RED-PEN should check preempt count
491         movq %gs:pda_irqstackptr,%rax
492         cmoveq %rax,%rsp /*todo This needs CFI annotation! */
493         pushq %rdi                      # save old stack        
494 #ifndef CONFIG_DEBUG_INFO
495         CFI_ADJUST_CFA_OFFSET   8
496 #endif
497         call \func
498         .endm
500 ENTRY(common_interrupt)
501         XCPT_FRAME
502         interrupt do_IRQ
503         /* 0(%rsp): oldrsp-ARGOFFSET */
504 ret_from_intr:
505         popq  %rdi
506 #ifndef CONFIG_DEBUG_INFO
507         CFI_ADJUST_CFA_OFFSET   -8
508 #endif
509         cli     
510         decl %gs:pda_irqcount
511 #ifdef CONFIG_DEBUG_INFO
512         movq RBP(%rdi),%rbp
513         CFI_DEF_CFA_REGISTER    rsp
514 #endif
515         leaq ARGOFFSET(%rdi),%rsp /*todo This needs CFI annotation! */
516 exit_intr:
517         GET_THREAD_INFO(%rcx)
518         testl $3,CS-ARGOFFSET(%rsp)
519         je retint_kernel
520         
521         /* Interrupt came from user space */
522         /*
523          * Has a correct top of stack, but a partial stack frame
524          * %rcx: thread info. Interrupts off.
525          */             
526 retint_with_reschedule:
527         movl $_TIF_WORK_MASK,%edi
528 retint_check:
529         movl threadinfo_flags(%rcx),%edx
530         andl %edi,%edx
531         CFI_REMEMBER_STATE
532         jnz  retint_careful
533 retint_swapgs:          
534         swapgs 
535 retint_restore_args:                            
536         cli
537         RESTORE_ARGS 0,8,0                                              
538 iret_label:     
539         iretq
541         .section __ex_table,"a"
542         .quad iret_label,bad_iret       
543         .previous
544         .section .fixup,"ax"
545         /* force a signal here? this matches i386 behaviour */
546         /* running with kernel gs */
547 bad_iret:
548         movq $11,%rdi   /* SIGSEGV */
549         sti
550         jmp do_exit                     
551         .previous       
552         
553         /* edi: workmask, edx: work */
554 retint_careful:
555         CFI_RESTORE_STATE
556         bt    $TIF_NEED_RESCHED,%edx
557         jnc   retint_signal
558         sti
559         pushq %rdi
560         CFI_ADJUST_CFA_OFFSET   8
561         call  schedule
562         popq %rdi               
563         CFI_ADJUST_CFA_OFFSET   -8
564         GET_THREAD_INFO(%rcx)
565         cli
566         jmp retint_check
567         
568 retint_signal:
569         testl $(_TIF_SIGPENDING|_TIF_NOTIFY_RESUME|_TIF_SINGLESTEP),%edx
570         jz    retint_swapgs
571         sti
572         SAVE_REST
573         movq $-1,ORIG_RAX(%rsp)                         
574         xorl %esi,%esi          # oldset
575         movq %rsp,%rdi          # &pt_regs
576         call do_notify_resume
577         RESTORE_REST
578         cli
579         movl $_TIF_NEED_RESCHED,%edi
580         GET_THREAD_INFO(%rcx)
581         jmp retint_check
583 #ifdef CONFIG_PREEMPT
584         /* Returning to kernel space. Check if we need preemption */
585         /* rcx:  threadinfo. interrupts off. */
586         .p2align
587 retint_kernel:  
588         cmpl $0,threadinfo_preempt_count(%rcx)
589         jnz  retint_restore_args
590         bt  $TIF_NEED_RESCHED,threadinfo_flags(%rcx)
591         jnc  retint_restore_args
592         bt   $9,EFLAGS-ARGOFFSET(%rsp)  /* interrupts off? */
593         jnc  retint_restore_args
594         call preempt_schedule_irq
595         jmp exit_intr
596 #endif  
597         CFI_ENDPROC
598         
600  * APIC interrupts.
601  */             
602         .macro apicinterrupt num,func
603         INTR_FRAME
604         pushq $\num-256
605         CFI_ADJUST_CFA_OFFSET 8
606         interrupt \func
607         jmp ret_from_intr
608         CFI_ENDPROC
609         .endm
611 ENTRY(thermal_interrupt)
612         apicinterrupt THERMAL_APIC_VECTOR,smp_thermal_interrupt
614 ENTRY(threshold_interrupt)
615         apicinterrupt THRESHOLD_APIC_VECTOR,mce_threshold_interrupt
617 #ifdef CONFIG_SMP       
618 ENTRY(reschedule_interrupt)
619         apicinterrupt RESCHEDULE_VECTOR,smp_reschedule_interrupt
621         .macro INVALIDATE_ENTRY num
622 ENTRY(invalidate_interrupt\num)
623         apicinterrupt INVALIDATE_TLB_VECTOR_START+\num,smp_invalidate_interrupt 
624         .endm
626         INVALIDATE_ENTRY 0
627         INVALIDATE_ENTRY 1
628         INVALIDATE_ENTRY 2
629         INVALIDATE_ENTRY 3
630         INVALIDATE_ENTRY 4
631         INVALIDATE_ENTRY 5
632         INVALIDATE_ENTRY 6
633         INVALIDATE_ENTRY 7
635 ENTRY(call_function_interrupt)
636         apicinterrupt CALL_FUNCTION_VECTOR,smp_call_function_interrupt
637 #endif
639 #ifdef CONFIG_X86_LOCAL_APIC    
640 ENTRY(apic_timer_interrupt)
641         apicinterrupt LOCAL_TIMER_VECTOR,smp_apic_timer_interrupt
643 ENTRY(error_interrupt)
644         apicinterrupt ERROR_APIC_VECTOR,smp_error_interrupt
646 ENTRY(spurious_interrupt)
647         apicinterrupt SPURIOUS_APIC_VECTOR,smp_spurious_interrupt
648 #endif
649                                 
651  * Exception entry points.
652  */             
653         .macro zeroentry sym
654         INTR_FRAME
655         pushq $0        /* push error code/oldrax */ 
656         CFI_ADJUST_CFA_OFFSET 8
657         pushq %rax      /* push real oldrax to the rdi slot */ 
658         CFI_ADJUST_CFA_OFFSET 8
659         leaq  \sym(%rip),%rax
660         jmp error_entry
661         CFI_ENDPROC
662         .endm   
664         .macro errorentry sym
665         XCPT_FRAME
666         pushq %rax
667         CFI_ADJUST_CFA_OFFSET 8
668         leaq  \sym(%rip),%rax
669         jmp error_entry
670         CFI_ENDPROC
671         .endm
673         /* error code is on the stack already */
674         /* handle NMI like exceptions that can happen everywhere */
675         .macro paranoidentry sym, ist=0
676         SAVE_ALL
677         cld
678         movl $1,%ebx
679         movl  $MSR_GS_BASE,%ecx
680         rdmsr
681         testl %edx,%edx
682         js    1f
683         swapgs
684         xorl  %ebx,%ebx
686         .if \ist
687         movq    %gs:pda_data_offset, %rbp
688         .endif
689         movq %rsp,%rdi
690         movq ORIG_RAX(%rsp),%rsi
691         movq $-1,ORIG_RAX(%rsp)
692         .if \ist
693         subq    $EXCEPTION_STKSZ, per_cpu__init_tss + TSS_ist + (\ist - 1) * 8(%rbp)
694         .endif
695         call \sym
696         .if \ist
697         addq    $EXCEPTION_STKSZ, per_cpu__init_tss + TSS_ist + (\ist - 1) * 8(%rbp)
698         .endif
699         cli
700         .endm
701         
703  * Exception entry point. This expects an error code/orig_rax on the stack
704  * and the exception handler in %rax.   
705  */                                             
706 ENTRY(error_entry)
707         _frame RDI
708         /* rdi slot contains rax, oldrax contains error code */
709         cld     
710         subq  $14*8,%rsp
711         CFI_ADJUST_CFA_OFFSET   (14*8)
712         movq %rsi,13*8(%rsp)
713         CFI_REL_OFFSET  rsi,RSI
714         movq 14*8(%rsp),%rsi    /* load rax from rdi slot */
715         movq %rdx,12*8(%rsp)
716         CFI_REL_OFFSET  rdx,RDX
717         movq %rcx,11*8(%rsp)
718         CFI_REL_OFFSET  rcx,RCX
719         movq %rsi,10*8(%rsp)    /* store rax */ 
720         CFI_REL_OFFSET  rax,RAX
721         movq %r8, 9*8(%rsp)
722         CFI_REL_OFFSET  r8,R8
723         movq %r9, 8*8(%rsp)
724         CFI_REL_OFFSET  r9,R9
725         movq %r10,7*8(%rsp)
726         CFI_REL_OFFSET  r10,R10
727         movq %r11,6*8(%rsp)
728         CFI_REL_OFFSET  r11,R11
729         movq %rbx,5*8(%rsp) 
730         CFI_REL_OFFSET  rbx,RBX
731         movq %rbp,4*8(%rsp) 
732         CFI_REL_OFFSET  rbp,RBP
733         movq %r12,3*8(%rsp) 
734         CFI_REL_OFFSET  r12,R12
735         movq %r13,2*8(%rsp) 
736         CFI_REL_OFFSET  r13,R13
737         movq %r14,1*8(%rsp) 
738         CFI_REL_OFFSET  r14,R14
739         movq %r15,(%rsp) 
740         CFI_REL_OFFSET  r15,R15
741         xorl %ebx,%ebx  
742         testl $3,CS(%rsp)
743         je  error_kernelspace
744 error_swapgs:   
745         swapgs
746 error_sti:      
747         movq %rdi,RDI(%rsp)     
748         movq %rsp,%rdi
749         movq ORIG_RAX(%rsp),%rsi        /* get error code */ 
750         movq $-1,ORIG_RAX(%rsp)
751         call *%rax
752         /* ebx: no swapgs flag (1: don't need swapgs, 0: need it) */     
753 error_exit:             
754         movl %ebx,%eax          
755         RESTORE_REST
756         cli
757         GET_THREAD_INFO(%rcx)   
758         testl %eax,%eax
759         jne  retint_kernel
760         movl  threadinfo_flags(%rcx),%edx
761         movl  $_TIF_WORK_MASK,%edi
762         andl  %edi,%edx
763         jnz  retint_careful
764         swapgs 
765         RESTORE_ARGS 0,8,0                                              
766         jmp iret_label
767         CFI_ENDPROC
769 error_kernelspace:
770         incl %ebx
771        /* There are two places in the kernel that can potentially fault with
772           usergs. Handle them here. The exception handlers after
773            iret run with kernel gs again, so don't set the user space flag.
774            B stepping K8s sometimes report an truncated RIP for IRET 
775            exceptions returning to compat mode. Check for these here too. */
776         leaq iret_label(%rip),%rbp
777         cmpq %rbp,RIP(%rsp) 
778         je   error_swapgs
779         movl %ebp,%ebp  /* zero extend */
780         cmpq %rbp,RIP(%rsp) 
781         je   error_swapgs
782         cmpq $gs_change,RIP(%rsp)
783         je   error_swapgs
784         jmp  error_sti
785         
786        /* Reload gs selector with exception handling */
787        /* edi:  new selector */ 
788 ENTRY(load_gs_index)
789         CFI_STARTPROC
790         pushf
791         CFI_ADJUST_CFA_OFFSET 8
792         cli
793         swapgs
794 gs_change:     
795         movl %edi,%gs   
796 2:      mfence          /* workaround */
797         swapgs
798         popf
799         CFI_ADJUST_CFA_OFFSET -8
800         ret
801         CFI_ENDPROC
802        
803         .section __ex_table,"a"
804         .align 8
805         .quad gs_change,bad_gs
806         .previous
807         .section .fixup,"ax"
808         /* running with kernelgs */
809 bad_gs: 
810         swapgs                  /* switch back to user gs */
811         xorl %eax,%eax
812         movl %eax,%gs
813         jmp  2b
814         .previous       
815         
817  * Create a kernel thread.
819  * C extern interface:
820  *      extern long kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
822  * asm input arguments:
823  *      rdi: fn, rsi: arg, rdx: flags
824  */
825 ENTRY(kernel_thread)
826         CFI_STARTPROC
827         FAKE_STACK_FRAME $child_rip
828         SAVE_ALL
830         # rdi: flags, rsi: usp, rdx: will be &pt_regs
831         movq %rdx,%rdi
832         orq  kernel_thread_flags(%rip),%rdi
833         movq $-1, %rsi
834         movq %rsp, %rdx
836         xorl %r8d,%r8d
837         xorl %r9d,%r9d
838         
839         # clone now
840         call do_fork
841         movq %rax,RAX(%rsp)
842         xorl %edi,%edi
844         /*
845          * It isn't worth to check for reschedule here,
846          * so internally to the x86_64 port you can rely on kernel_thread()
847          * not to reschedule the child before returning, this avoids the need
848          * of hacks for example to fork off the per-CPU idle tasks.
849          * [Hopefully no generic code relies on the reschedule -AK]     
850          */
851         RESTORE_ALL
852         UNFAKE_STACK_FRAME
853         ret
854         CFI_ENDPROC
856         
857 child_rip:
858         /*
859          * Here we are in the child and the registers are set as they were
860          * at kernel_thread() invocation in the parent.
861          */
862         movq %rdi, %rax
863         movq %rsi, %rdi
864         call *%rax
865         # exit
866         xorl %edi, %edi
867         call do_exit
870  * execve(). This function needs to use IRET, not SYSRET, to set up all state properly.
872  * C extern interface:
873  *       extern long execve(char *name, char **argv, char **envp)
875  * asm input arguments:
876  *      rdi: name, rsi: argv, rdx: envp
878  * We want to fallback into:
879  *      extern long sys_execve(char *name, char **argv,char **envp, struct pt_regs regs)
881  * do_sys_execve asm fallback arguments:
882  *      rdi: name, rsi: argv, rdx: envp, fake frame on the stack
883  */
884 ENTRY(execve)
885         CFI_STARTPROC
886         FAKE_STACK_FRAME $0
887         SAVE_ALL        
888         call sys_execve
889         movq %rax, RAX(%rsp)    
890         RESTORE_REST
891         testq %rax,%rax
892         je int_ret_from_sys_call
893         RESTORE_ARGS
894         UNFAKE_STACK_FRAME
895         ret
896         CFI_ENDPROC
898 KPROBE_ENTRY(page_fault)
899         errorentry do_page_fault
900         .previous .text
902 ENTRY(coprocessor_error)
903         zeroentry do_coprocessor_error
905 ENTRY(simd_coprocessor_error)
906         zeroentry do_simd_coprocessor_error     
908 ENTRY(device_not_available)
909         zeroentry math_state_restore
911         /* runs on exception stack */
912 KPROBE_ENTRY(debug)
913         INTR_FRAME
914         pushq $0
915         CFI_ADJUST_CFA_OFFSET 8         
916         paranoidentry do_debug, DEBUG_STACK
917         jmp paranoid_exit
918         CFI_ENDPROC
919         .previous .text
921         /* runs on exception stack */   
922 KPROBE_ENTRY(nmi)
923         INTR_FRAME
924         pushq $-1
925         CFI_ADJUST_CFA_OFFSET 8
926         paranoidentry do_nmi
927         /*
928          * "Paranoid" exit path from exception stack.
929          * Paranoid because this is used by NMIs and cannot take
930          * any kernel state for granted.
931          * We don't do kernel preemption checks here, because only
932          * NMI should be common and it does not enable IRQs and
933          * cannot get reschedule ticks.
934          */
935         /* ebx: no swapgs flag */
936 paranoid_exit:
937         testl %ebx,%ebx                         /* swapgs needed? */
938         jnz paranoid_restore
939         testl $3,CS(%rsp)
940         jnz   paranoid_userspace
941 paranoid_swapgs:        
942         swapgs
943 paranoid_restore:       
944         RESTORE_ALL 8
945         iretq
946 paranoid_userspace:     
947         GET_THREAD_INFO(%rcx)
948         movl threadinfo_flags(%rcx),%ebx
949         andl $_TIF_WORK_MASK,%ebx
950         jz paranoid_swapgs
951         movq %rsp,%rdi                  /* &pt_regs */
952         call sync_regs
953         movq %rax,%rsp                  /* switch stack for scheduling */
954         testl $_TIF_NEED_RESCHED,%ebx
955         jnz paranoid_schedule
956         movl %ebx,%edx                  /* arg3: thread flags */
957         sti
958         xorl %esi,%esi                  /* arg2: oldset */
959         movq %rsp,%rdi                  /* arg1: &pt_regs */
960         call do_notify_resume
961         cli
962         jmp paranoid_userspace
963 paranoid_schedule:
964         sti
965         call schedule
966         cli
967         jmp paranoid_userspace
968         CFI_ENDPROC
969         .previous .text
971 KPROBE_ENTRY(int3)
972         INTR_FRAME
973         pushq $0
974         CFI_ADJUST_CFA_OFFSET 8
975         paranoidentry do_int3, DEBUG_STACK
976         jmp paranoid_exit
977         CFI_ENDPROC
978         .previous .text
980 ENTRY(overflow)
981         zeroentry do_overflow
983 ENTRY(bounds)
984         zeroentry do_bounds
986 ENTRY(invalid_op)
987         zeroentry do_invalid_op 
989 ENTRY(coprocessor_segment_overrun)
990         zeroentry do_coprocessor_segment_overrun
992 ENTRY(reserved)
993         zeroentry do_reserved
995         /* runs on exception stack */
996 ENTRY(double_fault)
997         XCPT_FRAME
998         paranoidentry do_double_fault
999         jmp paranoid_exit
1000         CFI_ENDPROC
1002 ENTRY(invalid_TSS)
1003         errorentry do_invalid_TSS
1005 ENTRY(segment_not_present)
1006         errorentry do_segment_not_present
1008         /* runs on exception stack */
1009 ENTRY(stack_segment)
1010         XCPT_FRAME
1011         paranoidentry do_stack_segment
1012         jmp paranoid_exit
1013         CFI_ENDPROC
1015 KPROBE_ENTRY(general_protection)
1016         errorentry do_general_protection
1017         .previous .text
1019 ENTRY(alignment_check)
1020         errorentry do_alignment_check
1022 ENTRY(divide_error)
1023         zeroentry do_divide_error
1025 ENTRY(spurious_interrupt_bug)
1026         zeroentry do_spurious_interrupt_bug
1028 #ifdef CONFIG_X86_MCE
1029         /* runs on exception stack */
1030 ENTRY(machine_check)
1031         INTR_FRAME
1032         pushq $0
1033         CFI_ADJUST_CFA_OFFSET 8 
1034         paranoidentry do_machine_check
1035         jmp paranoid_exit
1036         CFI_ENDPROC
1037 #endif
1039 ENTRY(call_softirq)
1040         CFI_STARTPROC
1041         movq %gs:pda_irqstackptr,%rax
1042         movq %rsp,%rdx
1043         CFI_DEF_CFA_REGISTER    rdx
1044         incl %gs:pda_irqcount
1045         cmove %rax,%rsp
1046         pushq %rdx
1047         /*todo CFI_DEF_CFA_EXPRESSION ...*/
1048         call __do_softirq
1049         popq %rsp
1050         CFI_DEF_CFA_REGISTER    rsp
1051         decl %gs:pda_irqcount
1052         ret
1053         CFI_ENDPROC