drm/radeon/kms: clear confusion in GART init/deinit path
[safe/jmp/linux-2.6] / arch / x86 / kernel / entry_64.S
index f2d546e..c251be7 100644 (file)
 #include <asm/unistd.h>
 #include <asm/thread_info.h>
 #include <asm/hw_irq.h>
-#include <asm/page.h>
+#include <asm/page_types.h>
 #include <asm/irqflags.h>
 #include <asm/paravirt.h>
 #include <asm/ftrace.h>
+#include <asm/percpu.h>
 
 /* Avoid __ASSEMBLER__'ifying <linux/audit.h> just for this.  */
 #include <linux/elf-em.h>
@@ -67,57 +68,50 @@ ENTRY(mcount)
 END(mcount)
 
 ENTRY(ftrace_caller)
+       cmpl $0, function_trace_stop
+       jne  ftrace_stub
 
-       /* taken from glibc */
-       subq $0x38, %rsp
-       movq %rax, (%rsp)
-       movq %rcx, 8(%rsp)
-       movq %rdx, 16(%rsp)
-       movq %rsi, 24(%rsp)
-       movq %rdi, 32(%rsp)
-       movq %r8, 40(%rsp)
-       movq %r9, 48(%rsp)
+       MCOUNT_SAVE_FRAME
 
        movq 0x38(%rsp), %rdi
        movq 8(%rbp), %rsi
        subq $MCOUNT_INSN_SIZE, %rdi
 
-.globl ftrace_call
-ftrace_call:
+GLOBAL(ftrace_call)
        call ftrace_stub
 
-       movq 48(%rsp), %r9
-       movq 40(%rsp), %r8
-       movq 32(%rsp), %rdi
-       movq 24(%rsp), %rsi
-       movq 16(%rsp), %rdx
-       movq 8(%rsp), %rcx
-       movq (%rsp), %rax
-       addq $0x38, %rsp
+       MCOUNT_RESTORE_FRAME
 
-.globl ftrace_stub
-ftrace_stub:
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+GLOBAL(ftrace_graph_call)
+       jmp ftrace_stub
+#endif
+
+GLOBAL(ftrace_stub)
        retq
 END(ftrace_caller)
 
 #else /* ! CONFIG_DYNAMIC_FTRACE */
 ENTRY(mcount)
+       cmpl $0, function_trace_stop
+       jne  ftrace_stub
+
        cmpq $ftrace_stub, ftrace_trace_function
        jnz trace
-.globl ftrace_stub
-ftrace_stub:
+
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+       cmpq $ftrace_stub, ftrace_graph_return
+       jnz ftrace_graph_caller
+
+       cmpq $ftrace_graph_entry_stub, ftrace_graph_entry
+       jnz ftrace_graph_caller
+#endif
+
+GLOBAL(ftrace_stub)
        retq
 
 trace:
-       /* taken from glibc */
-       subq $0x38, %rsp
-       movq %rax, (%rsp)
-       movq %rcx, 8(%rsp)
-       movq %rdx, 16(%rsp)
-       movq %rsi, 24(%rsp)
-       movq %rdi, 32(%rsp)
-       movq %r8, 40(%rsp)
-       movq %r9, 48(%rsp)
+       MCOUNT_SAVE_FRAME
 
        movq 0x38(%rsp), %rdi
        movq 8(%rbp), %rsi
@@ -125,20 +119,50 @@ trace:
 
        call   *ftrace_trace_function
 
-       movq 48(%rsp), %r9
-       movq 40(%rsp), %r8
-       movq 32(%rsp), %rdi
-       movq 24(%rsp), %rsi
-       movq 16(%rsp), %rdx
-       movq 8(%rsp), %rcx
-       movq (%rsp), %rax
-       addq $0x38, %rsp
+       MCOUNT_RESTORE_FRAME
 
        jmp ftrace_stub
 END(mcount)
 #endif /* CONFIG_DYNAMIC_FTRACE */
 #endif /* CONFIG_FUNCTION_TRACER */
 
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+ENTRY(ftrace_graph_caller)
+       cmpl $0, function_trace_stop
+       jne ftrace_stub
+
+       MCOUNT_SAVE_FRAME
+
+       leaq 8(%rbp), %rdi
+       movq 0x38(%rsp), %rsi
+       movq (%rbp), %rdx
+       subq $MCOUNT_INSN_SIZE, %rsi
+
+       call    prepare_ftrace_return
+
+       MCOUNT_RESTORE_FRAME
+
+       retq
+END(ftrace_graph_caller)
+
+GLOBAL(return_to_handler)
+       subq  $80, %rsp
+
+       /* Save the return values */
+       movq %rax, (%rsp)
+       movq %rdx, 8(%rsp)
+       movq %rbp, %rdi
+
+       call ftrace_return_to_handler
+
+       movq %rax, 72(%rsp)
+       movq 8(%rsp), %rdx
+       movq (%rsp), %rax
+       addq $72, %rsp
+       retq
+#endif
+
+
 #ifndef CONFIG_PREEMPT
 #define retint_kernel retint_restore_args
 #endif
@@ -147,6 +171,7 @@ END(mcount)
 ENTRY(native_usergs_sysret64)
        swapgs
        sysretq
+ENDPROC(native_usergs_sysret64)
 #endif /* CONFIG_PARAVIRT */
 
 
@@ -169,7 +194,7 @@ ENTRY(native_usergs_sysret64)
 
        /* %rsp:at FRAMEEND */
        .macro FIXUP_TOP_OF_STACK tmp offset=0
-       movq %gs:pda_oldrsp,\tmp
+       movq PER_CPU_VAR(old_rsp),\tmp
        movq \tmp,RSP+\offset(%rsp)
        movq $__USER_DS,SS+\offset(%rsp)
        movq $__USER_CS,CS+\offset(%rsp)
@@ -180,7 +205,7 @@ ENTRY(native_usergs_sysret64)
 
        .macro RESTORE_TOP_OF_STACK tmp offset=0
        movq RSP+\offset(%rsp),\tmp
-       movq \tmp,%gs:pda_oldrsp
+       movq \tmp,PER_CPU_VAR(old_rsp)
        movq EFLAGS+\offset(%rsp),\tmp
        movq \tmp,R11+\offset(%rsp)
        .endm
@@ -194,7 +219,7 @@ ENTRY(native_usergs_sysret64)
        pushq %rax /* rsp */
        CFI_ADJUST_CFA_OFFSET   8
        CFI_REL_OFFSET  rsp,0
-       pushq $(1<<9) /* eflags - interrupts on */
+       pushq $X86_EFLAGS_IF /* eflags - interrupts on */
        CFI_ADJUST_CFA_OFFSET   8
        /*CFI_REL_OFFSET        rflags,0*/
        pushq $__KERNEL_CS /* cs */
@@ -296,16 +321,17 @@ ENTRY(save_args)
        je 1f
        SWAPGS
        /*
-        * irqcount is used to check if a CPU is already on an interrupt stack
+        * irq_count 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
+1:     incl PER_CPU_VAR(irq_count)
        jne 2f
        popq_cfi %rax                   /* move return address... */
-       mov %gs:pda_irqstackptr,%rsp
+       mov PER_CPU_VAR(irq_stack_ptr),%rsp
        EMPTY_FRAME 0
+       pushq_cfi %rbp                  /* backlink for unwinder */
        pushq_cfi %rax                  /* ... to the new stack */
        /*
         * We entered an interrupt context - irqs are off:
@@ -331,6 +357,7 @@ ENTRY(save_rest)
 END(save_rest)
 
 /* save complete stack frame */
+       .pushsection .kprobes.text, "ax"
 ENTRY(save_paranoid)
        XCPT_FRAME 1 RDI+8
        cld
@@ -359,34 +386,38 @@ ENTRY(save_paranoid)
 1:     ret
        CFI_ENDPROC
 END(save_paranoid)
+       .popsection
 
 /*
- * A newly forked process directly context switches into this.
+ * A newly forked process directly context switches into this address.
+ *
+ * rdi: prev task we switched from
  */
-/* rdi:        prev */
 ENTRY(ret_from_fork)
        DEFAULT_FRAME
+
+       LOCK ; btr $TIF_FORK,TI_flags(%r8)
+
        push kernel_eflags(%rip)
        CFI_ADJUST_CFA_OFFSET 8
-       popf                            # reset kernel eflags
+       popf                                    # reset kernel eflags
        CFI_ADJUST_CFA_OFFSET -8
-       call schedule_tail
+
+       call schedule_tail                      # rdi: 'prev' task parameter
+
        GET_THREAD_INFO(%rcx)
-       testl $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT),TI_flags(%rcx)
-       jnz rff_trace
-rff_action:
+
        RESTORE_REST
-       testl $3,CS-ARGOFFSET(%rsp)     # from kernel_thread?
+
+       testl $3, CS-ARGOFFSET(%rsp)            # from kernel_thread?
        je   int_ret_from_sys_call
-       testl $_TIF_IA32,TI_flags(%rcx)
+
+       testl $_TIF_IA32, TI_flags(%rcx)        # 32-bit compat task needs IRET
        jnz  int_ret_from_sys_call
+
        RESTORE_TOP_OF_STACK %rdi, -ARGOFFSET
-       jmp ret_from_sys_call
-rff_trace:
-       movq %rsp,%rdi
-       call syscall_trace_leave
-       GET_THREAD_INFO(%rcx)
-       jmp rff_action
+       jmp ret_from_sys_call                   # go to the SYSRET fastpath
+
        CFI_ENDPROC
 END(ret_from_fork)
 
@@ -424,7 +455,7 @@ END(ret_from_fork)
 ENTRY(system_call)
        CFI_STARTPROC   simple
        CFI_SIGNAL_FRAME
-       CFI_DEF_CFA     rsp,PDA_STACKOFFSET
+       CFI_DEF_CFA     rsp,KERNEL_STACK_OFFSET
        CFI_REGISTER    rip,rcx
        /*CFI_REGISTER  rflags,r11*/
        SWAPGS_UNSAFE_STACK
@@ -435,8 +466,8 @@ ENTRY(system_call)
         */
 ENTRY(system_call_after_swapgs)
 
-       movq    %rsp,%gs:pda_oldrsp
-       movq    %gs:pda_kernelstack,%rsp
+       movq    %rsp,PER_CPU_VAR(old_rsp)
+       movq    PER_CPU_VAR(kernel_stack),%rsp
        /*
         * No need to follow this irqs off/on section - it's straight
         * and short:
@@ -479,7 +510,7 @@ sysret_check:
        CFI_REGISTER    rip,rcx
        RESTORE_ARGS 0,-ARG_SKIP,1
        /*CFI_REGISTER  rflags,r11*/
-       movq    %gs:pda_oldrsp, %rsp
+       movq    PER_CPU_VAR(old_rsp), %rsp
        USERGS_SYSRET64
 
        CFI_RESTORE_STATE
@@ -586,16 +617,14 @@ tracesys:
  * Syscall return path ending with IRET.
  * Has correct top of stack, but partial stack frame.
  */
-       .globl int_ret_from_sys_call
-       .globl int_with_check
-int_ret_from_sys_call:
+GLOBAL(int_ret_from_sys_call)
        DISABLE_INTERRUPTS(CLBR_NONE)
        TRACE_IRQS_OFF
        testl $3,CS-ARGOFFSET(%rsp)
        je retint_restore_args
        movl $_TIF_ALLWORK_MASK,%edi
        /* edi: mask to check */
-int_with_check:
+GLOBAL(int_with_check)
        LOCKDEP_SYS_EXIT_IRQ
        GET_THREAD_INFO(%rcx)
        movl TI_flags(%rcx),%edx
@@ -789,11 +818,11 @@ common_interrupt:
        XCPT_FRAME
        addq $-0x80,(%rsp)              /* Adjust vector to [-256,-1] range */
        interrupt do_IRQ
-       /* 0(%rsp): oldrsp-ARGOFFSET */
+       /* 0(%rsp): old_rsp-ARGOFFSET */
 ret_from_intr:
        DISABLE_INTERRUPTS(CLBR_NONE)
        TRACE_IRQS_OFF
-       decl %gs:pda_irqcount
+       decl PER_CPU_VAR(irq_count)
        leaveq
        CFI_DEF_CFA_REGISTER    rsp
        CFI_ADJUST_CFA_OFFSET   -8
@@ -936,12 +965,18 @@ END(\sym)
 #ifdef CONFIG_SMP
 apicinterrupt IRQ_MOVE_CLEANUP_VECTOR \
        irq_move_cleanup_interrupt smp_irq_move_cleanup_interrupt
+apicinterrupt REBOOT_VECTOR \
+       reboot_interrupt smp_reboot_interrupt
 #endif
 
-apicinterrupt 220 \
+#ifdef CONFIG_X86_UV
+apicinterrupt UV_BAU_MESSAGE \
        uv_bau_message_intr1 uv_bau_message_interrupt
+#endif
 apicinterrupt LOCAL_TIMER_VECTOR \
        apic_timer_interrupt smp_apic_timer_interrupt
+apicinterrupt GENERIC_INTERRUPT_VECTOR \
+       generic_interrupt smp_generic_interrupt
 
 #ifdef CONFIG_SMP
 apicinterrupt INVALIDATE_TLB_VECTOR_START+0 \
@@ -963,10 +998,15 @@ apicinterrupt INVALIDATE_TLB_VECTOR_START+7 \
 #endif
 
 apicinterrupt THRESHOLD_APIC_VECTOR \
-       threshold_interrupt mce_threshold_interrupt
+       threshold_interrupt smp_threshold_interrupt
 apicinterrupt THERMAL_APIC_VECTOR \
        thermal_interrupt smp_thermal_interrupt
 
+#ifdef CONFIG_X86_MCE
+apicinterrupt MCE_SELF_VECTOR \
+       mce_self_interrupt smp_mce_self_interrupt
+#endif
+
 #ifdef CONFIG_SMP
 apicinterrupt CALL_FUNCTION_SINGLE_VECTOR \
        call_function_single_interrupt smp_call_function_single_interrupt
@@ -981,6 +1021,11 @@ apicinterrupt ERROR_APIC_VECTOR \
 apicinterrupt SPURIOUS_APIC_VECTOR \
        spurious_interrupt smp_spurious_interrupt
 
+#ifdef CONFIG_PERF_COUNTERS
+apicinterrupt LOCAL_PENDING_VECTOR \
+       perf_pending_interrupt smp_perf_pending_interrupt
+#endif
+
 /*
  * Exception entry points.
  */
@@ -1002,7 +1047,7 @@ END(\sym)
 .endm
 
 .macro paranoidzeroentry sym do_sym
-KPROBE_ENTRY(\sym)
+ENTRY(\sym)
        INTR_FRAME
        PARAVIRT_ADJUST_EXCEPTION_FRAME
        pushq $-1               /* ORIG_RAX: no syscall to restart */
@@ -1015,12 +1060,12 @@ KPROBE_ENTRY(\sym)
        call \do_sym
        jmp paranoid_exit       /* %ebx: no swapgs flag */
        CFI_ENDPROC
-KPROBE_END(\sym)
+END(\sym)
 .endm
 
 .macro paranoidzeroentry_ist sym do_sym ist
-KPROBE_ENTRY(\sym)
-       INTR_FRAME
+ENTRY(\sym)
+       INTR_FRAME
        PARAVIRT_ADJUST_EXCEPTION_FRAME
        pushq $-1               /* ORIG_RAX: no syscall to restart */
        CFI_ADJUST_CFA_OFFSET 8
@@ -1029,21 +1074,17 @@ KPROBE_ENTRY(\sym)
        TRACE_IRQS_OFF
        movq %rsp,%rdi          /* pt_regs pointer */
        xorl %esi,%esi          /* no error code */
-       movq %gs:pda_data_offset, %rbp
-       subq $EXCEPTION_STKSZ, per_cpu__init_tss + TSS_ist + (\ist - 1) * 8(%rbp)
+       PER_CPU(init_tss, %rbp)
+       subq $EXCEPTION_STKSZ, TSS_ist + (\ist - 1) * 8(%rbp)
        call \do_sym
-       addq $EXCEPTION_STKSZ, per_cpu__init_tss + TSS_ist + (\ist - 1) * 8(%rbp)
+       addq $EXCEPTION_STKSZ, TSS_ist + (\ist - 1) * 8(%rbp)
        jmp paranoid_exit       /* %ebx: no swapgs flag */
        CFI_ENDPROC
-KPROBE_END(\sym)
+END(\sym)
 .endm
 
-.macro errorentry sym do_sym entry=0
-.if \entry
-KPROBE_ENTRY(\sym)
-.else
+.macro errorentry sym do_sym
 ENTRY(\sym)
-.endif
        XCPT_FRAME
        PARAVIRT_ADJUST_EXCEPTION_FRAME
        subq $15*8,%rsp
@@ -1056,20 +1097,12 @@ ENTRY(\sym)
        call \do_sym
        jmp error_exit                  /* %ebx: no swapgs flag */
        CFI_ENDPROC
-.if \entry
-KPROBE_END(\sym)
-.else
 END(\sym)
-.endif
 .endm
 
        /* error code is on the stack already */
-.macro paranoiderrorentry sym do_sym entry=1
-.if \entry
-KPROBE_ENTRY(\sym)
-.else
+.macro paranoiderrorentry sym do_sym
 ENTRY(\sym)
-.endif
        XCPT_FRAME
        PARAVIRT_ADJUST_EXCEPTION_FRAME
        subq $15*8,%rsp
@@ -1083,196 +1116,53 @@ ENTRY(\sym)
        call \do_sym
        jmp paranoid_exit               /* %ebx: no swapgs flag */
        CFI_ENDPROC
-.if \entry
-KPROBE_END(\sym)
-.else
 END(\sym)
-.endif
 .endm
 
 zeroentry divide_error do_divide_error
-paranoidzeroentry_ist debug do_debug DEBUG_STACK
-paranoidzeroentry_ist int3 do_int3 DEBUG_STACK
 zeroentry overflow do_overflow
 zeroentry bounds do_bounds
 zeroentry invalid_op do_invalid_op
 zeroentry device_not_available do_device_not_available
-paranoiderrorentry double_fault do_double_fault 0
+paranoiderrorentry double_fault do_double_fault
 zeroentry coprocessor_segment_overrun do_coprocessor_segment_overrun
 errorentry invalid_TSS do_invalid_TSS
 errorentry segment_not_present do_segment_not_present
-paranoiderrorentry stack_segment do_stack_segment
-errorentry general_protection do_general_protection 1
-errorentry page_fault do_page_fault 1
 zeroentry spurious_interrupt_bug do_spurious_interrupt_bug
 zeroentry coprocessor_error do_coprocessor_error
 errorentry alignment_check do_alignment_check
-#ifdef CONFIG_X86_MCE
-paranoidzeroentry machine_check do_machine_check
-#endif
 zeroentry simd_coprocessor_error do_simd_coprocessor_error
 
-       /*
-        * "Paranoid" exit path from exception stack.
-        * Paranoid because this is used by NMIs and cannot take
-        * any kernel state for granted.
-        * We don't do kernel preemption checks here, because only
-        * NMI should be common and it does not enable IRQs and
-        * cannot get reschedule ticks.
-        *
-        * "trace" is 0 for the NMI handler only, because irq-tracing
-        * is fundamentally NMI-unsafe. (we cannot change the soft and
-        * hard flags at once, atomically)
-        */
-
-       /* ebx: no swapgs flag */
-KPROBE_ENTRY(paranoid_exit)
-       INTR_FRAME
-       DISABLE_INTERRUPTS(CLBR_NONE)
-       TRACE_IRQS_OFF
-       testl %ebx,%ebx                         /* swapgs needed? */
-       jnz paranoid_restore
-       testl $3,CS(%rsp)
-       jnz   paranoid_userspace
-paranoid_swapgs:
-       TRACE_IRQS_IRETQ 0
-       SWAPGS_UNSAFE_STACK
-paranoid_restore:
-       RESTORE_ALL 8
-       jmp irq_return
-paranoid_userspace:
-       GET_THREAD_INFO(%rcx)
-       movl TI_flags(%rcx),%ebx
-       andl $_TIF_WORK_MASK,%ebx
-       jz paranoid_swapgs
-       movq %rsp,%rdi                  /* &pt_regs */
-       call sync_regs
-       movq %rax,%rsp                  /* switch stack for scheduling */
-       testl $_TIF_NEED_RESCHED,%ebx
-       jnz paranoid_schedule
-       movl %ebx,%edx                  /* arg3: thread flags */
-       TRACE_IRQS_ON
-       ENABLE_INTERRUPTS(CLBR_NONE)
-       xorl %esi,%esi                  /* arg2: oldset */
-       movq %rsp,%rdi                  /* arg1: &pt_regs */
-       call do_notify_resume
-       DISABLE_INTERRUPTS(CLBR_NONE)
-       TRACE_IRQS_OFF
-       jmp paranoid_userspace
-paranoid_schedule:
-       TRACE_IRQS_ON
-       ENABLE_INTERRUPTS(CLBR_ANY)
-       call schedule
-       DISABLE_INTERRUPTS(CLBR_ANY)
-       TRACE_IRQS_OFF
-       jmp paranoid_userspace
-       CFI_ENDPROC
-KPROBE_END(paranoid_exit)
-
-/*
- * Exception entry point. This expects an error code/orig_rax on the stack.
- * returns in "no swapgs flag" in %ebx.
- */
-KPROBE_ENTRY(error_entry)
-       XCPT_FRAME
-       CFI_ADJUST_CFA_OFFSET 15*8
-       /* oldrax contains error code */
-       cld
-       movq_cfi rdi, RDI+8
-       movq_cfi rsi, RSI+8
-       movq_cfi rdx, RDX+8
-       movq_cfi rcx, RCX+8
-       movq_cfi rax, RAX+8
-       movq_cfi  r8,  R8+8
-       movq_cfi  r9,  R9+8
-       movq_cfi r10, R10+8
-       movq_cfi r11, R11+8
-       movq_cfi rbx, RBX+8
-       movq_cfi rbp, RBP+8
-       movq_cfi r12, R12+8
-       movq_cfi r13, R13+8
-       movq_cfi r14, R14+8
-       movq_cfi r15, R15+8
-       xorl %ebx,%ebx
-       testl $3,CS+8(%rsp)
-       je error_kernelspace
-error_swapgs:
-       SWAPGS
-error_sti:
-       TRACE_IRQS_OFF
-       ret
-       CFI_ENDPROC
-
-/*
- * There are two places in the kernel that can potentially fault with
- * usergs. Handle them here. The exception handlers after iret run with
- * kernel gs again, so don't set the user space flag. B stepping K8s
- * sometimes report an truncated RIP for IRET exceptions returning to
- * compat mode. Check for these here too.
- */
-error_kernelspace:
-       incl %ebx
-       leaq irq_return(%rip),%rcx
-       cmpq %rcx,RIP+8(%rsp)
-       je error_swapgs
-       movl %ecx,%ecx  /* zero extend */
-       cmpq %rcx,RIP+8(%rsp)
-       je error_swapgs
-       cmpq $gs_change,RIP+8(%rsp)
-        je error_swapgs
-       jmp error_sti
-KPROBE_END(error_entry)
-
-
-/* ebx:        no swapgs flag (1: don't need swapgs, 0: need it) */
-KPROBE_ENTRY(error_exit)
-       DEFAULT_FRAME
-       movl %ebx,%eax
-       RESTORE_REST
-       DISABLE_INTERRUPTS(CLBR_NONE)
-       TRACE_IRQS_OFF
-       GET_THREAD_INFO(%rcx)
-       testl %eax,%eax
-       jne retint_kernel
-       LOCKDEP_SYS_EXIT_IRQ
-       movl TI_flags(%rcx),%edx
-       movl $_TIF_WORK_MASK,%edi
-       andl %edi,%edx
-       jnz retint_careful
-       jmp retint_swapgs
-       CFI_ENDPROC
-KPROBE_END(error_exit)
-
-       /* Reload gs selector with exception handling */
-       /* edi:  new selector */
+       /* Reload gs selector with exception handling */
+       /* edi:  new selector */
 ENTRY(native_load_gs_index)
        CFI_STARTPROC
        pushf
        CFI_ADJUST_CFA_OFFSET 8
-       DISABLE_INTERRUPTS(CLBR_ANY | ~(CLBR_RDI))
-        SWAPGS
+       DISABLE_INTERRUPTS(CLBR_ANY & ~CLBR_RDI)
+       SWAPGS
 gs_change:
-        movl %edi,%gs
+       movl %edi,%gs
 2:     mfence          /* workaround */
        SWAPGS
-        popf
+       popf
        CFI_ADJUST_CFA_OFFSET -8
-        ret
+       ret
        CFI_ENDPROC
 END(native_load_gs_index)
 
-        .section __ex_table,"a"
-        .align 8
-        .quad gs_change,bad_gs
-        .previous
-        .section .fixup,"ax"
+       .section __ex_table,"a"
+       .align 8
+       .quad gs_change,bad_gs
+       .previous
+       .section .fixup,"ax"
        /* running with kernelgs */
 bad_gs:
        SWAPGS                  /* switch back to user gs */
        xorl %eax,%eax
-        movl %eax,%gs
-        jmp  2b
-        .previous
+       movl %eax,%gs
+       jmp  2b
+       .previous
 
 /*
  * Create a kernel thread.
@@ -1307,7 +1197,7 @@ ENTRY(kernel_thread)
         * so internally to the x86_64 port you can rely on kernel_thread()
         * not to reschedule the child before returning, this avoids the need
         * of hacks for example to fork off the per-CPU idle tasks.
-         * [Hopefully no generic code relies on the reschedule -AK]
+        * [Hopefully no generic code relies on the reschedule -AK]
         */
        RESTORE_ALL
        UNFAKE_STACK_FRAME
@@ -1315,7 +1205,7 @@ ENTRY(kernel_thread)
        CFI_ENDPROC
 END(kernel_thread)
 
-child_rip:
+ENTRY(child_rip)
        pushq $0                # fake return address
        CFI_STARTPROC
        /*
@@ -1328,6 +1218,7 @@ child_rip:
        # exit
        mov %eax, %edi
        call do_exit
+       ud2                     # padding for call trace
        CFI_ENDPROC
 END(child_rip)
 
@@ -1362,61 +1253,6 @@ ENTRY(kernel_execve)
        CFI_ENDPROC
 END(kernel_execve)
 
-       /* runs on exception stack */
-KPROBE_ENTRY(nmi)
-       INTR_FRAME
-       PARAVIRT_ADJUST_EXCEPTION_FRAME
-       pushq_cfi $-1
-       subq $15*8, %rsp
-       CFI_ADJUST_CFA_OFFSET 15*8
-       call save_paranoid
-       DEFAULT_FRAME 0
-       /* paranoidentry do_nmi, 0; without TRACE_IRQS_OFF */
-       movq %rsp,%rdi
-       movq $-1,%rsi
-       call do_nmi
-#ifdef CONFIG_TRACE_IRQFLAGS
-       /* paranoidexit; without TRACE_IRQS_OFF */
-       /* ebx: no swapgs flag */
-       DISABLE_INTERRUPTS(CLBR_NONE)
-       testl %ebx,%ebx                         /* swapgs needed? */
-       jnz nmi_restore
-       testl $3,CS(%rsp)
-       jnz nmi_userspace
-nmi_swapgs:
-       SWAPGS_UNSAFE_STACK
-nmi_restore:
-       RESTORE_ALL 8
-       jmp irq_return
-nmi_userspace:
-       GET_THREAD_INFO(%rcx)
-       movl TI_flags(%rcx),%ebx
-       andl $_TIF_WORK_MASK,%ebx
-       jz nmi_swapgs
-       movq %rsp,%rdi                  /* &pt_regs */
-       call sync_regs
-       movq %rax,%rsp                  /* switch stack for scheduling */
-       testl $_TIF_NEED_RESCHED,%ebx
-       jnz nmi_schedule
-       movl %ebx,%edx                  /* arg3: thread flags */
-       ENABLE_INTERRUPTS(CLBR_NONE)
-       xorl %esi,%esi                  /* arg2: oldset */
-       movq %rsp,%rdi                  /* arg1: &pt_regs */
-       call do_notify_resume
-       DISABLE_INTERRUPTS(CLBR_NONE)
-       jmp nmi_userspace
-nmi_schedule:
-       ENABLE_INTERRUPTS(CLBR_ANY)
-       call schedule
-       DISABLE_INTERRUPTS(CLBR_ANY)
-       jmp nmi_userspace
-       CFI_ENDPROC
-#else
-       jmp paranoid_exit
-       CFI_ENDPROC
-#endif
-KPROBE_END(nmi)
-
 /* Call softirq on interrupt stack. Interrupts are off. */
 ENTRY(call_softirq)
        CFI_STARTPROC
@@ -1425,74 +1261,69 @@ ENTRY(call_softirq)
        CFI_REL_OFFSET rbp,0
        mov  %rsp,%rbp
        CFI_DEF_CFA_REGISTER rbp
-       incl %gs:pda_irqcount
-       cmove %gs:pda_irqstackptr,%rsp
+       incl PER_CPU_VAR(irq_count)
+       cmove PER_CPU_VAR(irq_stack_ptr),%rsp
        push  %rbp                      # backlink for old unwinder
        call __do_softirq
        leaveq
        CFI_DEF_CFA_REGISTER    rsp
        CFI_ADJUST_CFA_OFFSET   -8
-       decl %gs:pda_irqcount
+       decl PER_CPU_VAR(irq_count)
        ret
        CFI_ENDPROC
 END(call_softirq)
 
-KPROBE_ENTRY(ignore_sysret)
-       CFI_STARTPROC
-       mov $-ENOSYS,%eax
-       sysret
-       CFI_ENDPROC
-KPROBE_END(ignore_sysret)
-
 #ifdef CONFIG_XEN
 zeroentry xen_hypervisor_callback xen_do_hypervisor_callback
 
 /*
-# A note on the "critical region" in our callback handler.
-# We want to avoid stacking callback handlers due to events occurring
-# during handling of the last event. To do this, we keep events disabled
-# until we've done all processing. HOWEVER, we must enable events before
-# popping the stack frame (can't be done atomically) and so it would still
-# be possible to get enough handler activations to overflow the stack.
-# Although unlikely, bugs of that kind are hard to track down, so we'd
-# like to avoid the possibility.
-# So, on entry to the handler we detect whether we interrupted an
-# existing activation in its critical region -- if so, we pop the current
-# activation and restart the handler using the previous one.
-*/
+ * A note on the "critical region" in our callback handler.
+ * We want to avoid stacking callback handlers due to events occurring
+ * during handling of the last event. To do this, we keep events disabled
+ * until we've done all processing. HOWEVER, we must enable events before
+ * popping the stack frame (can't be done atomically) and so it would still
+ * be possible to get enough handler activations to overflow the stack.
+ * Although unlikely, bugs of that kind are hard to track down, so we'd
+ * like to avoid the possibility.
+ * So, on entry to the handler we detect whether we interrupted an
+ * existing activation in its critical region -- if so, we pop the current
+ * activation and restart the handler using the previous one.
+ */
 ENTRY(xen_do_hypervisor_callback)   # do_hypervisor_callback(struct *pt_regs)
        CFI_STARTPROC
-/* Since we don't modify %rdi, evtchn_do_upall(struct *pt_regs) will
-   see the correct pointer to the pt_regs */
+/*
+ * Since we don't modify %rdi, evtchn_do_upall(struct *pt_regs) will
+ * see the correct pointer to the pt_regs
+ */
        movq %rdi, %rsp            # we don't return, adjust the stack frame
        CFI_ENDPROC
        DEFAULT_FRAME
-11:    incl %gs:pda_irqcount
+11:    incl PER_CPU_VAR(irq_count)
        movq %rsp,%rbp
        CFI_DEF_CFA_REGISTER rbp
-       cmovzq %gs:pda_irqstackptr,%rsp
+       cmovzq PER_CPU_VAR(irq_stack_ptr),%rsp
        pushq %rbp                      # backlink for old unwinder
        call xen_evtchn_do_upcall
        popq %rsp
        CFI_DEF_CFA_REGISTER rsp
-       decl %gs:pda_irqcount
+       decl PER_CPU_VAR(irq_count)
        jmp  error_exit
        CFI_ENDPROC
 END(do_hypervisor_callback)
 
 /*
-# Hypervisor uses this for application faults while it executes.
-# We get here for two reasons:
-#  1. Fault while reloading DS, ES, FS or GS
-#  2. Fault while executing IRET
-# Category 1 we do not need to fix up as Xen has already reloaded all segment
-# registers that could be reloaded and zeroed the others.
-# Category 2 we fix up by killing the current process. We cannot use the
-# normal Linux return path in this case because if we use the IRET hypercall
-# to pop the stack frame we end up in an infinite loop of failsafe callbacks.
-# We distinguish between categories by comparing each saved segment register
-# with its current contents: any discrepancy means we in category 1.
-*/
+ * Hypervisor uses this for application faults while it executes.
+ * We get here for two reasons:
+ *  1. Fault while reloading DS, ES, FS or GS
+ *  2. Fault while executing IRET
+ * Category 1 we do not need to fix up as Xen has already reloaded all segment
+ * registers that could be reloaded and zeroed the others.
+ * Category 2 we fix up by killing the current process. We cannot use the
+ * normal Linux return path in this case because if we use the IRET hypercall
+ * to pop the stack frame we end up in an infinite loop of failsafe callbacks.
+ * We distinguish between categories by comparing each saved segment register
+ * with its current contents: any discrepancy means we in category 1.
+ */
 ENTRY(xen_failsafe_callback)
        INTR_FRAME 1 (6*8)
        /*CFI_REL_OFFSET gs,GS*/
@@ -1540,3 +1371,224 @@ ENTRY(xen_failsafe_callback)
 END(xen_failsafe_callback)
 
 #endif /* CONFIG_XEN */
+
+/*
+ * Some functions should be protected against kprobes
+ */
+       .pushsection .kprobes.text, "ax"
+
+paranoidzeroentry_ist debug do_debug DEBUG_STACK
+paranoidzeroentry_ist int3 do_int3 DEBUG_STACK
+paranoiderrorentry stack_segment do_stack_segment
+#ifdef CONFIG_XEN
+zeroentry xen_debug do_debug
+zeroentry xen_int3 do_int3
+errorentry xen_stack_segment do_stack_segment
+#endif
+errorentry general_protection do_general_protection
+errorentry page_fault do_page_fault
+#ifdef CONFIG_X86_MCE
+paranoidzeroentry machine_check *machine_check_vector(%rip)
+#endif
+
+       /*
+        * "Paranoid" exit path from exception stack.
+        * Paranoid because this is used by NMIs and cannot take
+        * any kernel state for granted.
+        * We don't do kernel preemption checks here, because only
+        * NMI should be common and it does not enable IRQs and
+        * cannot get reschedule ticks.
+        *
+        * "trace" is 0 for the NMI handler only, because irq-tracing
+        * is fundamentally NMI-unsafe. (we cannot change the soft and
+        * hard flags at once, atomically)
+        */
+
+       /* ebx: no swapgs flag */
+ENTRY(paranoid_exit)
+       INTR_FRAME
+       DISABLE_INTERRUPTS(CLBR_NONE)
+       TRACE_IRQS_OFF
+       testl %ebx,%ebx                         /* swapgs needed? */
+       jnz paranoid_restore
+       testl $3,CS(%rsp)
+       jnz   paranoid_userspace
+paranoid_swapgs:
+       TRACE_IRQS_IRETQ 0
+       SWAPGS_UNSAFE_STACK
+       RESTORE_ALL 8
+       jmp irq_return
+paranoid_restore:
+       TRACE_IRQS_IRETQ 0
+       RESTORE_ALL 8
+       jmp irq_return
+paranoid_userspace:
+       GET_THREAD_INFO(%rcx)
+       movl TI_flags(%rcx),%ebx
+       andl $_TIF_WORK_MASK,%ebx
+       jz paranoid_swapgs
+       movq %rsp,%rdi                  /* &pt_regs */
+       call sync_regs
+       movq %rax,%rsp                  /* switch stack for scheduling */
+       testl $_TIF_NEED_RESCHED,%ebx
+       jnz paranoid_schedule
+       movl %ebx,%edx                  /* arg3: thread flags */
+       TRACE_IRQS_ON
+       ENABLE_INTERRUPTS(CLBR_NONE)
+       xorl %esi,%esi                  /* arg2: oldset */
+       movq %rsp,%rdi                  /* arg1: &pt_regs */
+       call do_notify_resume
+       DISABLE_INTERRUPTS(CLBR_NONE)
+       TRACE_IRQS_OFF
+       jmp paranoid_userspace
+paranoid_schedule:
+       TRACE_IRQS_ON
+       ENABLE_INTERRUPTS(CLBR_ANY)
+       call schedule
+       DISABLE_INTERRUPTS(CLBR_ANY)
+       TRACE_IRQS_OFF
+       jmp paranoid_userspace
+       CFI_ENDPROC
+END(paranoid_exit)
+
+/*
+ * Exception entry point. This expects an error code/orig_rax on the stack.
+ * returns in "no swapgs flag" in %ebx.
+ */
+ENTRY(error_entry)
+       XCPT_FRAME
+       CFI_ADJUST_CFA_OFFSET 15*8
+       /* oldrax contains error code */
+       cld
+       movq_cfi rdi, RDI+8
+       movq_cfi rsi, RSI+8
+       movq_cfi rdx, RDX+8
+       movq_cfi rcx, RCX+8
+       movq_cfi rax, RAX+8
+       movq_cfi  r8,  R8+8
+       movq_cfi  r9,  R9+8
+       movq_cfi r10, R10+8
+       movq_cfi r11, R11+8
+       movq_cfi rbx, RBX+8
+       movq_cfi rbp, RBP+8
+       movq_cfi r12, R12+8
+       movq_cfi r13, R13+8
+       movq_cfi r14, R14+8
+       movq_cfi r15, R15+8
+       xorl %ebx,%ebx
+       testl $3,CS+8(%rsp)
+       je error_kernelspace
+error_swapgs:
+       SWAPGS
+error_sti:
+       TRACE_IRQS_OFF
+       ret
+       CFI_ENDPROC
+
+/*
+ * There are two places in the kernel that can potentially fault with
+ * usergs. Handle them here. The exception handlers after iret run with
+ * kernel gs again, so don't set the user space flag. B stepping K8s
+ * sometimes report an truncated RIP for IRET exceptions returning to
+ * compat mode. Check for these here too.
+ */
+error_kernelspace:
+       incl %ebx
+       leaq irq_return(%rip),%rcx
+       cmpq %rcx,RIP+8(%rsp)
+       je error_swapgs
+       movl %ecx,%ecx  /* zero extend */
+       cmpq %rcx,RIP+8(%rsp)
+       je error_swapgs
+       cmpq $gs_change,RIP+8(%rsp)
+       je error_swapgs
+       jmp error_sti
+END(error_entry)
+
+
+/* ebx:        no swapgs flag (1: don't need swapgs, 0: need it) */
+ENTRY(error_exit)
+       DEFAULT_FRAME
+       movl %ebx,%eax
+       RESTORE_REST
+       DISABLE_INTERRUPTS(CLBR_NONE)
+       TRACE_IRQS_OFF
+       GET_THREAD_INFO(%rcx)
+       testl %eax,%eax
+       jne retint_kernel
+       LOCKDEP_SYS_EXIT_IRQ
+       movl TI_flags(%rcx),%edx
+       movl $_TIF_WORK_MASK,%edi
+       andl %edi,%edx
+       jnz retint_careful
+       jmp retint_swapgs
+       CFI_ENDPROC
+END(error_exit)
+
+
+       /* runs on exception stack */
+ENTRY(nmi)
+       INTR_FRAME
+       PARAVIRT_ADJUST_EXCEPTION_FRAME
+       pushq_cfi $-1
+       subq $15*8, %rsp
+       CFI_ADJUST_CFA_OFFSET 15*8
+       call save_paranoid
+       DEFAULT_FRAME 0
+       /* paranoidentry do_nmi, 0; without TRACE_IRQS_OFF */
+       movq %rsp,%rdi
+       movq $-1,%rsi
+       call do_nmi
+#ifdef CONFIG_TRACE_IRQFLAGS
+       /* paranoidexit; without TRACE_IRQS_OFF */
+       /* ebx: no swapgs flag */
+       DISABLE_INTERRUPTS(CLBR_NONE)
+       testl %ebx,%ebx                         /* swapgs needed? */
+       jnz nmi_restore
+       testl $3,CS(%rsp)
+       jnz nmi_userspace
+nmi_swapgs:
+       SWAPGS_UNSAFE_STACK
+nmi_restore:
+       RESTORE_ALL 8
+       jmp irq_return
+nmi_userspace:
+       GET_THREAD_INFO(%rcx)
+       movl TI_flags(%rcx),%ebx
+       andl $_TIF_WORK_MASK,%ebx
+       jz nmi_swapgs
+       movq %rsp,%rdi                  /* &pt_regs */
+       call sync_regs
+       movq %rax,%rsp                  /* switch stack for scheduling */
+       testl $_TIF_NEED_RESCHED,%ebx
+       jnz nmi_schedule
+       movl %ebx,%edx                  /* arg3: thread flags */
+       ENABLE_INTERRUPTS(CLBR_NONE)
+       xorl %esi,%esi                  /* arg2: oldset */
+       movq %rsp,%rdi                  /* arg1: &pt_regs */
+       call do_notify_resume
+       DISABLE_INTERRUPTS(CLBR_NONE)
+       jmp nmi_userspace
+nmi_schedule:
+       ENABLE_INTERRUPTS(CLBR_ANY)
+       call schedule
+       DISABLE_INTERRUPTS(CLBR_ANY)
+       jmp nmi_userspace
+       CFI_ENDPROC
+#else
+       jmp paranoid_exit
+       CFI_ENDPROC
+#endif
+END(nmi)
+
+ENTRY(ignore_sysret)
+       CFI_STARTPROC
+       mov $-ENOSYS,%eax
+       sysret
+       CFI_ENDPROC
+END(ignore_sysret)
+
+/*
+ * End of kprobes section
+ */
+       .popsection