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