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