Merge branch 'upstream-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/ieee13...
[pandora-kernel.git] / arch / x86_64 / kernel / entry.S
index aa8d893..2802524 100644 (file)
@@ -4,8 +4,6 @@
  *  Copyright (C) 1991, 1992  Linus Torvalds
  *  Copyright (C) 2000, 2001, 2002  Andi Kleen SuSE Labs
  *  Copyright (C) 2000  Pavel Machek <pavel@suse.cz>
- * 
- *  $Id$
  */
 
 /*
  * at the top of the kernel process stack.     
  * - partial stack frame: partially saved registers upto R11.
  * - full stack frame: Like partial stack frame, but all register saved. 
- *     
- * TODO:        
- * - schedule it carefully for the final hardware.
+ *
+ * Some macro usage:
+ * - CFI macros are used to generate dwarf2 unwind information for better
+ * backtraces. They don't change any code.
+ * - SAVE_ALL/RESTORE_ALL - Save/restore all registers
+ * - SAVE_ARGS/RESTORE_ARGS - Save/restore registers that C functions modify.
+ * There are unfortunately lots of special cases where some registers
+ * not touched. The macro is a big mess that should be cleaned up.
+ * - SAVE_REST/RESTORE_REST - Handle the registers not saved by SAVE_ARGS.
+ * Gives a full stack frame.
+ * - ENTRY/END Define functions in the symbol table.
+ * - FIXUP_TOP_OF_STACK/RESTORE_TOP_OF_STACK - Fix up the hardware stack
+ * frame that is otherwise undefined after a SYSCALL
+ * - TRACE_IRQ_* - Trace hard interrupt state for lock debugging.
+ * - errorentry/paranoidentry/zeroentry - Define exception entry points.
  */
 
-#define ASSEMBLY 1
 #include <linux/linkage.h>
 #include <asm/segment.h>
-#include <asm/smp.h>
 #include <asm/cache.h>
 #include <asm/errno.h>
 #include <asm/dwarf2.h>
        .macro  CFI_DEFAULT_STACK start=1
        .if \start
        CFI_STARTPROC   simple
+       CFI_SIGNAL_FRAME
        CFI_DEF_CFA     rsp,SS+8
        .else
        CFI_DEF_CFA_OFFSET SS+8
 /* rdi:        prev */ 
 ENTRY(ret_from_fork)
        CFI_DEFAULT_STACK
+       push kernel_eflags(%rip)
+       CFI_ADJUST_CFA_OFFSET 4
+       popf                            # reset kernel eflags
+       CFI_ADJUST_CFA_OFFSET -4
        call schedule_tail
        GET_THREAD_INFO(%rcx)
        testl $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT),threadinfo_flags(%rcx)
@@ -199,6 +212,7 @@ END(ret_from_fork)
 
 ENTRY(system_call)
        CFI_STARTPROC   simple
+       CFI_SIGNAL_FRAME
        CFI_DEF_CFA     rsp,PDA_STACKOFFSET
        CFI_REGISTER    rip,rcx
        /*CFI_REGISTER  rflags,r11*/
@@ -316,6 +330,7 @@ END(system_call)
  */    
 ENTRY(int_ret_from_sys_call)
        CFI_STARTPROC   simple
+       CFI_SIGNAL_FRAME
        CFI_DEF_CFA     rsp,SS+8-ARGOFFSET
        /*CFI_REL_OFFSET        ss,SS-ARGOFFSET*/
        CFI_REL_OFFSET  rsp,RSP-ARGOFFSET
@@ -476,6 +491,7 @@ END(stub_rt_sigreturn)
  */
        .macro _frame ref
        CFI_STARTPROC simple
+       CFI_SIGNAL_FRAME
        CFI_DEF_CFA rsp,SS+8-\ref
        /*CFI_REL_OFFSET ss,SS-\ref*/
        CFI_REL_OFFSET rsp,RSP-\ref
@@ -511,7 +527,12 @@ END(stub_rt_sigreturn)
        testl $3,CS(%rdi)
        je 1f
        swapgs  
-1:     incl    %gs:pda_irqcount        # RED-PEN should check preempt count
+       /* irqcount is used to check if a CPU is already on an interrupt
+          stack or not. While this is essentially redundant with preempt_count
+          it is a little cheaper to use a separate counter in the PDA
+          (short of moving irq_enter into assembly, which would be too
+           much work) */
+1:     incl    %gs:pda_irqcount
        cmoveq %gs:pda_irqstackptr,%rsp
        push    %rbp                    # backlink for old unwinder
        /*
@@ -619,8 +640,7 @@ retint_signal:
 #ifdef CONFIG_PREEMPT
        /* Returning to kernel space. Check if we need preemption */
        /* rcx:  threadinfo. interrupts off. */
-       .p2align
-retint_kernel: 
+ENTRY(retint_kernel)
        cmpl $0,threadinfo_preempt_count(%rcx)
        jnz  retint_restore_args
        bt  $TIF_NEED_RESCHED,threadinfo_flags(%rcx)
@@ -679,7 +699,6 @@ ENTRY(call_function_interrupt)
 END(call_function_interrupt)
 #endif
 
-#ifdef CONFIG_X86_LOCAL_APIC   
 ENTRY(apic_timer_interrupt)
        apicinterrupt LOCAL_TIMER_VECTOR,smp_apic_timer_interrupt
 END(apic_timer_interrupt)
@@ -691,7 +710,6 @@ END(error_interrupt)
 ENTRY(spurious_interrupt)
        apicinterrupt SPURIOUS_APIC_VECTOR,smp_spurious_interrupt
 END(spurious_interrupt)
-#endif
                                
 /*
  * Exception entry points.
@@ -768,7 +786,9 @@ paranoid_exit\trace:
        testl $3,CS(%rsp)
        jnz   paranoid_userspace\trace
 paranoid_swapgs\trace:
+       .if \trace
        TRACE_IRQS_IRETQ 0
+       .endif
        swapgs
 paranoid_restore\trace:
        RESTORE_ALL 8
@@ -814,7 +834,7 @@ paranoid_schedule\trace:
  * Exception entry point. This expects an error code/orig_rax on the stack
  * and the exception handler in %rax.  
  */                                            
-ENTRY(error_entry)
+KPROBE_ENTRY(error_entry)
        _frame RDI
        /* rdi slot contains rax, oldrax contains error code */
        cld     
@@ -898,7 +918,7 @@ error_kernelspace:
        cmpq $gs_change,RIP(%rsp)
         je   error_swapgs
        jmp  error_sti
-END(error_entry)
+KPROBE_END(error_entry)
        
        /* Reload gs selector with exception handling */
        /* edi:  new selector */ 
@@ -1020,8 +1040,7 @@ ENDPROC(execve)
 
 KPROBE_ENTRY(page_fault)
        errorentry do_page_fault
-END(page_fault)
-       .previous .text
+KPROBE_END(page_fault)
 
 ENTRY(coprocessor_error)
        zeroentry do_coprocessor_error
@@ -1042,8 +1061,7 @@ KPROBE_ENTRY(debug)
        CFI_ADJUST_CFA_OFFSET 8         
        paranoidentry do_debug, DEBUG_STACK
        paranoidexit
-END(debug)
-       .previous .text
+KPROBE_END(debug)
 
        /* runs on exception stack */   
 KPROBE_ENTRY(nmi)
@@ -1057,8 +1075,7 @@ KPROBE_ENTRY(nmi)
        jmp paranoid_exit1
        CFI_ENDPROC
 #endif
-END(nmi)
-       .previous .text
+KPROBE_END(nmi)
 
 KPROBE_ENTRY(int3)
        INTR_FRAME
@@ -1067,8 +1084,7 @@ KPROBE_ENTRY(int3)
        paranoidentry do_int3, DEBUG_STACK
        jmp paranoid_exit1
        CFI_ENDPROC
-END(int3)
-       .previous .text
+KPROBE_END(int3)
 
 ENTRY(overflow)
        zeroentry do_overflow
@@ -1116,8 +1132,7 @@ END(stack_segment)
 
 KPROBE_ENTRY(general_protection)
        errorentry do_general_protection
-END(general_protection)
-       .previous .text
+KPROBE_END(general_protection)
 
 ENTRY(alignment_check)
        errorentry do_alignment_check