Merge branch 'perf-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git...
Linus Torvalds [Sun, 15 Jan 2012 19:26:35 +0000 (11:26 -0800)]
* 'perf-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (39 commits)
  perf tools: Fix compile error on x86_64 Ubuntu
  perf report: Fix --stdio output alignment when --showcpuutilization used
  perf annotate: Get rid of field_sep check
  perf annotate: Fix usage string
  perf kmem: Fix a memory leak
  perf kmem: Add missing closedir() calls
  perf top: Add error message for EMFILE
  perf test: Change type of '-v' option to INCR
  perf script: Add missing closedir() calls
  tracing: Fix compile error when static ftrace is enabled
  recordmcount: Fix handling of elf64 big-endian objects.
  perf tools: Add const.h to MANIFEST to make perf-tar-src-pkg work again
  perf tools: Add support for guest/host-only profiling
  perf kvm: Do guest-only counting by default
  perf top: Don't update total_period on process_sample
  perf hists: Stop using 'self' for struct hist_entry
  perf hists: Rename total_session to total_period
  x86: Add counter when debug stack is used with interrupts enabled
  x86: Allow NMIs to hit breakpoints in i386
  x86: Keep current stack in NMI breakpoints
  ...

1  2 
Documentation/kernel-parameters.txt
arch/x86/kernel/cpu/common.c
arch/x86/kernel/entry_64.S
arch/x86/kernel/traps.c

@@@ -329,11 -329,6 +329,11 @@@ bytes respectively. Such letter suffixe
                                    is a lot of faster
                        off       - do not initialize any AMD IOMMU found in
                                    the system
 +                      force_isolation - Force device isolation for all
 +                                        devices. The IOMMU driver is not
 +                                        allowed anymore to lift isolation
 +                                        requirements as needed. This option
 +                                        does not override iommu=pt
  
        amijoy.map=     [HW,JOY] Amiga joystick support
                        Map of devices attached to JOY0DAT and JOY1DAT
        no_debug_objects
                        [KNL] Disable object debugging
  
 +      debug_guardpage_minorder=
 +                      [KNL] When CONFIG_DEBUG_PAGEALLOC is set, this
 +                      parameter allows control of the order of pages that will
 +                      be intentionally kept free (and hence protected) by the
 +                      buddy allocator. Bigger value increase the probability
 +                      of catching random memory corruption, but reduce the
 +                      amount of memory for normal system use. The maximum
 +                      possible value is MAX_ORDER/2.  Setting this parameter
 +                      to 1 or 2 should be enough to identify most random
 +                      memory corruption problems caused by bugs in kernel or
 +                      driver code when a CPU writes to (or reads from) a
 +                      random memory location. Note that there exists a class
 +                      of memory corruptions problems caused by buggy H/W or
 +                      F/W or by drivers badly programing DMA (basically when
 +                      memory is written at bus level and the CPU MMU is
 +                      bypassed) which are not detectable by
 +                      CONFIG_DEBUG_PAGEALLOC, hence this option will not help
 +                      tracking down these problems.
 +
        debugpat        [X86] Enable PAT debugging
  
        decnet.addr=    [HW,NET]
                nomerge
                forcesac
                soft
 -              pt      [x86, IA-64]
 +              pt              [x86, IA-64]
 +              group_mf        [x86, IA-64]
 +
  
        io7=            [HW] IO7 for Marvel based alpha systems
                        See comment before marvel_specify_io7 in
        kvm.ignore_msrs=[KVM] Ignore guest accesses to unhandled MSRs.
                        Default is 0 (don't ignore, but inject #GP)
  
 -      kvm.oos_shadow= [KVM] Disable out-of-sync shadow paging.
 -                      Default is 1 (enabled)
 -
        kvm.mmu_audit=  [KVM] This is a R/W parameter which allows audit
                        KVM MMU at runtime.
                        Default is 0 (off)
                        The default is to return 64-bit inode numbers.
  
        nfs.nfs4_disable_idmapping=
 -                      [NFSv4] When set, this option disables the NFSv4
 -                      idmapper on the client, but only if the mount
 -                      is using the 'sec=sys' security flavour. This may
 -                      make migration from legacy NFSv2/v3 systems easier
 -                      provided that the server has the appropriate support.
 -                      The default is to always enable NFSv4 idmapping.
 +                      [NFSv4] When set to the default of '1', this option
 +                      ensures that both the RPC level authentication
 +                      scheme and the NFS level operations agree to use
 +                      numeric uids/gids if the mount is using the
 +                      'sec=sys' security flavour. In effect it is
 +                      disabling idmapping, which can make migration from
 +                      legacy NFSv2/v3 systems to NFSv4 easier.
 +                      Servers that do not support this mode of operation
 +                      will be autodetected by the client, and it will fall
 +                      back to using the idmapper.
 +                      To turn off this behaviour, set the value to '0'.
  
        nmi_debug=      [KNL,AVR32,SH] Specify one or more actions to take
                        when a NMI is triggered.
        nomfgpt         [X86-32] Disable Multi-Function General Purpose
                        Timer usage (for AMD Geode machines).
  
 +      nonmi_ipi       [X86] Disable using NMI IPIs during panic/reboot to
 +                      shutdown the other cpus.  Instead use the REBOOT_VECTOR
 +                      irq.
 +
        nopat           [X86] Disable PAT (page attribute table extension of
                        pagetables) support.
  
  
        slram=          [HW,MTD]
  
 +      slab_max_order= [MM, SLAB]
 +                      Determines the maximum allowed order for slabs.
 +                      A high setting may cause OOMs due to memory
 +                      fragmentation.  Defaults to 1 for systems with
 +                      more than 32MB of RAM, 0 otherwise.
 +
        slub_debug[=options[,slabs]]    [MM, SLUB]
                        Enabling slub_debug allows one to determine the
                        culprit if slab objects become corrupted. Enabling
        stacktrace      [FTRACE]
                        Enabled the stack tracer on boot up.
  
+       stacktrace_filter=[function-list]
+                       [FTRACE] Limit the functions that the stack tracer
+                       will trace at boot up. function-list is a comma separated
+                       list of functions. This list can be changed at run
+                       time by the stack_trace_filter file in the debugfs
+                       tracing directory. Note, this enables stack tracing
+                       and the stacktrace above is not needed.
        sti=            [PARISC,HW]
                        Format: <num>
                        Set the STI (builtin display/keyboard on the HP-PARISC
                        [USB] Start with the old device initialization
                        scheme (default 0 = off).
  
 +      usbcore.usbfs_memory_mb=
 +                      [USB] Memory limit (in MB) for buffers allocated by
 +                      usbfs (default = 16, 0 = max = 2047).
 +
        usbcore.use_both_schemes=
                        [USB] Try the other device initialization scheme
                        if the first one fails (default 1 = enabled).
                        functions are at fixed addresses, they make nice
                        targets for exploits that can control RIP.
  
 -                      emulate     Vsyscalls turn into traps and are emulated
 -                                  reasonably safely.
 +                      emulate     [default] Vsyscalls turn into traps and are
 +                                  emulated reasonably safely.
  
 -                      native      [default] Vsyscalls are native syscall
 -                                  instructions.
 +                      native      Vsyscalls are native syscall instructions.
                                    This is a little bit faster than trapping
                                    and makes a few dynamic recompilers work
                                    better than they would in emulation mode.
@@@ -676,7 -676,9 +676,7 @@@ static void __init early_identify_cpu(s
        if (this_cpu->c_early_init)
                this_cpu->c_early_init(c);
  
 -#ifdef CONFIG_SMP
        c->cpu_index = 0;
 -#endif
        filter_cpuid_features(c, false);
  
        setup_smep(c);
@@@ -762,7 -764,10 +762,7 @@@ static void __cpuinit generic_identify(
                c->apicid = c->initial_apicid;
  # endif
  #endif
 -
 -#ifdef CONFIG_X86_HT
                c->phys_proc_id = c->initial_apicid;
 -#endif
        }
  
        setup_smep(c);
@@@ -1021,6 -1026,8 +1021,8 @@@ __setup("clearcpuid=", setup_disablecpu
  
  #ifdef CONFIG_X86_64
  struct desc_ptr idt_descr = { NR_VECTORS * 16 - 1, (unsigned long) idt_table };
+ struct desc_ptr nmi_idt_descr = { NR_VECTORS * 16 - 1,
+                                   (unsigned long) nmi_idt_table };
  
  DEFINE_PER_CPU_FIRST(union irq_stack_union,
                     irq_stack_union) __aligned(PAGE_SIZE);
@@@ -1085,6 -1092,26 +1087,26 @@@ unsigned long kernel_eflags
   */
  DEFINE_PER_CPU(struct orig_ist, orig_ist);
  
+ static DEFINE_PER_CPU(unsigned long, debug_stack_addr);
+ DEFINE_PER_CPU(int, debug_stack_usage);
+ int is_debug_stack(unsigned long addr)
+ {
+       return __get_cpu_var(debug_stack_usage) ||
+               (addr <= __get_cpu_var(debug_stack_addr) &&
+                addr > (__get_cpu_var(debug_stack_addr) - DEBUG_STKSZ));
+ }
+ void debug_stack_set_zero(void)
+ {
+       load_idt((const struct desc_ptr *)&nmi_idt_descr);
+ }
+ void debug_stack_reset(void)
+ {
+       load_idt((const struct desc_ptr *)&idt_descr);
+ }
  #else /* CONFIG_X86_64 */
  
  DEFINE_PER_CPU(struct task_struct *, current_task) = &init_task;
@@@ -1136,15 -1163,6 +1158,15 @@@ static void dbg_restore_debug_regs(void
  #endif /* ! CONFIG_KGDB */
  
  /*
 + * Prints an error where the NUMA and configured core-number mismatch and the
 + * platform didn't override this to fix it up
 + */
 +void __cpuinit x86_default_fixup_cpu_id(struct cpuinfo_x86 *c, int node)
 +{
 +      pr_err("NUMA core number %d differs from configured core number %d\n", node, c->phys_proc_id);
 +}
 +
 +/*
   * cpu_init() initializes state that is per-CPU. Some data is already
   * initialized (naturally) in the bootstrap process, such as the GDT
   * and IDT. We reload them nevertheless, this function acts as a
@@@ -1212,6 -1230,8 +1234,8 @@@ void __cpuinit cpu_init(void
                        estacks += exception_stack_sizes[v];
                        oist->ist[v] = t->x86_tss.ist[v] =
                                        (unsigned long)estacks;
+                       if (v == DEBUG_STACK-1)
+                               per_cpu(debug_stack_addr, cpu) = (unsigned long)estacks;
                }
        }
  
@@@ -221,7 -221,7 +221,7 @@@ ENDPROC(native_usergs_sysret64
        /*CFI_REL_OFFSET        ss,0*/
        pushq_cfi %rax /* rsp */
        CFI_REL_OFFSET  rsp,0
 -      pushq_cfi $X86_EFLAGS_IF /* eflags - interrupts on */
 +      pushq_cfi $(X86_EFLAGS_IF|X86_EFLAGS_BIT1) /* eflags - interrupts on */
        /*CFI_REL_OFFSET        rflags,0*/
        pushq_cfi $__KERNEL_CS /* cs */
        /*CFI_REL_OFFSET        cs,0*/
@@@ -411,7 -411,7 +411,7 @@@ ENTRY(ret_from_fork
        RESTORE_REST
  
        testl $3, CS-ARGOFFSET(%rsp)            # from kernel_thread?
 -      je   int_ret_from_sys_call
 +      jz   retint_restore_args
  
        testl $_TIF_IA32, TI_flags(%rcx)        # 32-bit compat task needs IRET
        jnz  int_ret_from_sys_call
@@@ -465,7 -465,7 +465,7 @@@ ENTRY(system_call
         * after the swapgs, so that it can do the swapgs
         * for the guest and jump here on syscall.
         */
 -ENTRY(system_call_after_swapgs)
 +GLOBAL(system_call_after_swapgs)
  
        movq    %rsp,PER_CPU_VAR(old_rsp)
        movq    PER_CPU_VAR(kernel_stack),%rsp
        movq  %rax,ORIG_RAX-ARGOFFSET(%rsp)
        movq  %rcx,RIP-ARGOFFSET(%rsp)
        CFI_REL_OFFSET rip,RIP-ARGOFFSET
 -      GET_THREAD_INFO(%rcx)
 -      testl $_TIF_WORK_SYSCALL_ENTRY,TI_flags(%rcx)
 +      testl $_TIF_WORK_SYSCALL_ENTRY,TI_flags+THREAD_INFO(%rsp,RIP-ARGOFFSET)
        jnz tracesys
  system_call_fastpath:
        cmpq $__NR_syscall_max,%rax
@@@ -495,9 -496,10 +495,9 @@@ ret_from_sys_call
        /* edi: flagmask */
  sysret_check:
        LOCKDEP_SYS_EXIT
 -      GET_THREAD_INFO(%rcx)
        DISABLE_INTERRUPTS(CLBR_NONE)
        TRACE_IRQS_OFF
 -      movl TI_flags(%rcx),%edx
 +      movl TI_flags+THREAD_INFO(%rsp,RIP-ARGOFFSET),%edx
        andl %edi,%edx
        jnz  sysret_careful
        CFI_REMEMBER_STATE
@@@ -581,7 -583,7 +581,7 @@@ sysret_audit
        /* Do syscall tracing */
  tracesys:
  #ifdef CONFIG_AUDITSYSCALL
 -      testl $(_TIF_WORK_SYSCALL_ENTRY & ~_TIF_SYSCALL_AUDIT),TI_flags(%rcx)
 +      testl $(_TIF_WORK_SYSCALL_ENTRY & ~_TIF_SYSCALL_AUDIT),TI_flags+THREAD_INFO(%rsp,RIP-ARGOFFSET)
        jz auditsys
  #endif
        SAVE_REST
  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 */
  GLOBAL(int_with_check)
@@@ -949,7 -953,6 +949,7 @@@ END(common_interrupt
  ENTRY(\sym)
        INTR_FRAME
        pushq_cfi $~(\num)
 +.Lcommon_\sym:
        interrupt \do_sym
        jmp ret_from_intr
        CFI_ENDPROC
@@@ -973,21 -976,13 +973,21 @@@ apicinterrupt X86_PLATFORM_IPI_VECTOR 
        x86_platform_ipi smp_x86_platform_ipi
  
  #ifdef CONFIG_SMP
 -.irp idx,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, \
 +      ALIGN
 +      INTR_FRAME
 +.irp idx,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, \
        16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31
  .if NUM_INVALIDATE_TLB_VECTORS > \idx
 -apicinterrupt (INVALIDATE_TLB_VECTOR_START)+\idx \
 -      invalidate_interrupt\idx smp_invalidate_interrupt
 +ENTRY(invalidate_interrupt\idx)
 +      pushq_cfi $~(INVALIDATE_TLB_VECTOR_START+\idx)
 +      jmp .Lcommon_invalidate_interrupt0
 +      CFI_ADJUST_CFA_OFFSET -8
 +END(invalidate_interrupt\idx)
  .endif
  .endr
 +      CFI_ENDPROC
 +apicinterrupt INVALIDATE_TLB_VECTOR_START, \
 +      invalidate_interrupt0, smp_invalidate_interrupt
  #endif
  
  apicinterrupt THRESHOLD_APIC_VECTOR \
@@@ -1480,62 -1475,214 +1480,214 @@@ ENTRY(error_exit
        CFI_ENDPROC
  END(error_exit)
  
+ /*
+  * Test if a given stack is an NMI stack or not.
+  */
+       .macro test_in_nmi reg stack nmi_ret normal_ret
+       cmpq %\reg, \stack
+       ja \normal_ret
+       subq $EXCEPTION_STKSZ, %\reg
+       cmpq %\reg, \stack
+       jb \normal_ret
+       jmp \nmi_ret
+       .endm
  
        /* runs on exception stack */
  ENTRY(nmi)
        INTR_FRAME
        PARAVIRT_ADJUST_EXCEPTION_FRAME
-       pushq_cfi $-1
+       /*
+        * We allow breakpoints in NMIs. If a breakpoint occurs, then
+        * the iretq it performs will take us out of NMI context.
+        * This means that we can have nested NMIs where the next
+        * NMI is using the top of the stack of the previous NMI. We
+        * can't let it execute because the nested NMI will corrupt the
+        * stack of the previous NMI. NMI handlers are not re-entrant
+        * anyway.
+        *
+        * To handle this case we do the following:
+        *  Check the a special location on the stack that contains
+        *  a variable that is set when NMIs are executing.
+        *  The interrupted task's stack is also checked to see if it
+        *  is an NMI stack.
+        *  If the variable is not set and the stack is not the NMI
+        *  stack then:
+        *    o Set the special variable on the stack
+        *    o Copy the interrupt frame into a "saved" location on the stack
+        *    o Copy the interrupt frame into a "copy" location on the stack
+        *    o Continue processing the NMI
+        *  If the variable is set or the previous stack is the NMI stack:
+        *    o Modify the "copy" location to jump to the repeate_nmi
+        *    o return back to the first NMI
+        *
+        * Now on exit of the first NMI, we first clear the stack variable
+        * The NMI stack will tell any nested NMIs at that point that it is
+        * nested. Then we pop the stack normally with iret, and if there was
+        * a nested NMI that updated the copy interrupt stack frame, a
+        * jump will be made to the repeat_nmi code that will handle the second
+        * NMI.
+        */
+       /* Use %rdx as out temp variable throughout */
+       pushq_cfi %rdx
+       /*
+        * Check the special variable on the stack to see if NMIs are
+        * executing.
+        */
+       cmp $1, -8(%rsp)
+       je nested_nmi
+       /*
+        * Now test if the previous stack was an NMI stack.
+        * We need the double check. We check the NMI stack to satisfy the
+        * race when the first NMI clears the variable before returning.
+        * We check the variable because the first NMI could be in a
+        * breakpoint routine using a breakpoint stack.
+        */
+       lea 6*8(%rsp), %rdx
+       test_in_nmi rdx, 4*8(%rsp), nested_nmi, first_nmi
+ nested_nmi:
+       /*
+        * Do nothing if we interrupted the fixup in repeat_nmi.
+        * It's about to repeat the NMI handler, so we are fine
+        * with ignoring this one.
+        */
+       movq $repeat_nmi, %rdx
+       cmpq 8(%rsp), %rdx
+       ja 1f
+       movq $end_repeat_nmi, %rdx
+       cmpq 8(%rsp), %rdx
+       ja nested_nmi_out
+ 1:
+       /* Set up the interrupted NMIs stack to jump to repeat_nmi */
+       leaq -6*8(%rsp), %rdx
+       movq %rdx, %rsp
+       CFI_ADJUST_CFA_OFFSET 6*8
+       pushq_cfi $__KERNEL_DS
+       pushq_cfi %rdx
+       pushfq_cfi
+       pushq_cfi $__KERNEL_CS
+       pushq_cfi $repeat_nmi
+       /* Put stack back */
+       addq $(11*8), %rsp
+       CFI_ADJUST_CFA_OFFSET -11*8
+ nested_nmi_out:
+       popq_cfi %rdx
+       /* No need to check faults here */
+       INTERRUPT_RETURN
+ first_nmi:
+       /*
+        * Because nested NMIs will use the pushed location that we
+        * stored in rdx, we must keep that space available.
+        * Here's what our stack frame will look like:
+        * +-------------------------+
+        * | original SS             |
+        * | original Return RSP     |
+        * | original RFLAGS         |
+        * | original CS             |
+        * | original RIP            |
+        * +-------------------------+
+        * | temp storage for rdx    |
+        * +-------------------------+
+        * | NMI executing variable  |
+        * +-------------------------+
+        * | Saved SS                |
+        * | Saved Return RSP        |
+        * | Saved RFLAGS            |
+        * | Saved CS                |
+        * | Saved RIP               |
+        * +-------------------------+
+        * | copied SS               |
+        * | copied Return RSP       |
+        * | copied RFLAGS           |
+        * | copied CS               |
+        * | copied RIP              |
+        * +-------------------------+
+        * | pt_regs                 |
+        * +-------------------------+
+        *
+        * The saved RIP is used to fix up the copied RIP that a nested
+        * NMI may zero out. The original stack frame and the temp storage
+        * is also used by nested NMIs and can not be trusted on exit.
+        */
+       /* Set the NMI executing variable on the stack. */
+       pushq_cfi $1
+       /* Copy the stack frame to the Saved frame */
+       .rept 5
+       pushq_cfi 6*8(%rsp)
+       .endr
+       /* Make another copy, this one may be modified by nested NMIs */
+       .rept 5
+       pushq_cfi 4*8(%rsp)
+       .endr
+       /* Do not pop rdx, nested NMIs will corrupt it */
+       movq 11*8(%rsp), %rdx
+       /*
+        * Everything below this point can be preempted by a nested
+        * NMI if the first NMI took an exception. Repeated NMIs
+        * caused by an exception and nested NMI will start here, and
+        * can still be preempted by another NMI.
+        */
+ restart_nmi:
+       pushq_cfi $-1           /* ORIG_RAX: no syscall to restart */
        subq $ORIG_RAX-R15, %rsp
        CFI_ADJUST_CFA_OFFSET ORIG_RAX-R15
+       /*
+        * Use save_paranoid to handle SWAPGS, but no need to use paranoid_exit
+        * as we should not be calling schedule in NMI context.
+        * Even with normal interrupts enabled. An NMI should not be
+        * setting NEED_RESCHED or anything that normal interrupts and
+        * exceptions might do.
+        */
        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
+       /* Clear the NMI executing stack variable */
+       movq $0, 10*8(%rsp)
        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)
  
+       /*
+        * If an NMI hit an iret because of an exception or breakpoint,
+        * it can lose its NMI context, and a nested NMI may come in.
+        * In that case, the nested NMI will change the preempted NMI's
+        * stack to jump to here when it does the final iret.
+        */
+ repeat_nmi:
+       INTR_FRAME
+       /* Update the stack variable to say we are still in NMI */
+       movq $1, 5*8(%rsp)
+       /* copy the saved stack back to copy stack */
+       .rept 5
+       pushq_cfi 4*8(%rsp)
+       .endr
+       jmp restart_nmi
+       CFI_ENDPROC
+ end_repeat_nmi:
  ENTRY(ignore_sysret)
        CFI_STARTPROC
        mov $-ENOSYS,%eax
diff --combined arch/x86/kernel/traps.c
@@@ -306,14 -306,25 +306,20 @@@ dotraplinkage void __kprobes do_int3(st
                        == NOTIFY_STOP)
                return;
  #endif /* CONFIG_KGDB_LOW_LEVEL_TRAP */
 -#ifdef CONFIG_KPROBES
 +
        if (notify_die(DIE_INT3, "int3", regs, error_code, 3, SIGTRAP)
                        == NOTIFY_STOP)
                return;
 -#else
 -      if (notify_die(DIE_TRAP, "int3", regs, error_code, 3, SIGTRAP)
 -                      == NOTIFY_STOP)
 -              return;
 -#endif
  
+       /*
+        * Let others (NMI) know that the debug stack is in use
+        * as we may switch to the interrupt stack.
+        */
+       debug_stack_usage_inc();
        preempt_conditional_sti(regs);
        do_trap(3, SIGTRAP, "int3", regs, error_code, NULL);
        preempt_conditional_cli(regs);
+       debug_stack_usage_dec();
  }
  
  #ifdef CONFIG_X86_64
@@@ -406,6 -417,12 +412,12 @@@ dotraplinkage void __kprobes do_debug(s
                                                        SIGTRAP) == NOTIFY_STOP)
                return;
  
+       /*
+        * Let others (NMI) know that the debug stack is in use
+        * as we may switch to the interrupt stack.
+        */
+       debug_stack_usage_inc();
        /* It's safe to allow irq's after DR6 has been saved */
        preempt_conditional_sti(regs);
  
                handle_vm86_trap((struct kernel_vm86_regs *) regs,
                                error_code, 1);
                preempt_conditional_cli(regs);
+               debug_stack_usage_dec();
                return;
        }
  
        if (tsk->thread.debugreg6 & (DR_STEP | DR_TRAP_BITS) || user_icebp)
                send_sigtrap(tsk, regs, error_code, si_code);
        preempt_conditional_cli(regs);
+       debug_stack_usage_dec();
  
        return;
  }
@@@ -718,4 -737,10 +732,10 @@@ void __init trap_init(void
        cpu_init();
  
        x86_init.irqs.trap_init();
+ #ifdef CONFIG_X86_64
+       memcpy(&nmi_idt_table, &idt_table, IDT_ENTRIES * 16);
+       set_nmi_gate(1, &debug);
+       set_nmi_gate(3, &int3);
+ #endif
  }