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