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