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