]> Pileus Git - ~andy/linux/commitdiff
Merge branch 'perf/nmi' into perf/core
authorIngo Molnar <mingo@elte.hu>
Thu, 5 Aug 2010 06:45:05 +0000 (08:45 +0200)
committerIngo Molnar <mingo@elte.hu>
Thu, 5 Aug 2010 06:45:05 +0000 (08:45 +0200)
Conflicts:
kernel/Makefile

Merge reason: Add the now complete topic, fix the conflict.

Signed-off-by: Ingo Molnar <mingo@elte.hu>
1  2 
Documentation/kernel-parameters.txt
arch/Kconfig
arch/x86/Kconfig
arch/x86/kernel/traps.c
include/linux/sched.h
kernel/Makefile
kernel/sysctl.c
kernel/timer.c
lib/Kconfig.debug

index 2b2407d9a6d025a8451605b104a35daa7da59b47,dfe8d1c226c640a699bd48732930dd511e43d2a4..c45a3548537a9e23b326e5d529fbd2ab5adaabca
@@@ -58,7 -58,6 +58,7 @@@ parameter is applicable
        ISAPNP  ISA PnP code is enabled.
        ISDN    Appropriate ISDN support is enabled.
        JOY     Appropriate joystick support is enabled.
 +      KGDB    Kernel debugger support is enabled.
        KVM     Kernel Virtual Machine support is enabled.
        LIBATA  Libata driver is enabled
        LP      Printer support is enabled.
        SWSUSP  Software suspend (hibernation) is enabled.
        SUSPEND System suspend states are enabled.
        FTRACE  Function tracing enabled.
 +      TPM     TPM drivers are enabled.
        TS      Appropriate touchscreen support is enabled.
        UMS     USB Mass Storage support is enabled.
        USB     USB support is enabled.
@@@ -145,14 -143,14 +145,14 @@@ and is between 256 and 4096 characters
  
        acpi=           [HW,ACPI,X86]
                        Advanced Configuration and Power Interface
 -                      Format: { force | off | ht | strict | noirq | rsdt }
 +                      Format: { force | off | strict | noirq | rsdt }
                        force -- enable ACPI if default was off
                        off -- disable ACPI if default was on
                        noirq -- do not use ACPI for IRQ routing
 -                      ht -- run only enough ACPI to enable Hyper Threading
                        strict -- Be less tolerant of platforms that are not
                                strictly ACPI specification compliant.
                        rsdt -- prefer RSDT over (default) XSDT
 +                      copy_dsdt -- copy DSDT to memory
  
                        See also Documentation/power/pm.txt, pci=noacpi
  
                        control method, with respect to putting devices into
                        low power states, to be enforced (the ACPI 2.0 ordering
                        of _PTS is used by default).
 -                      s4_nonvs prevents the kernel from saving/restoring the
 -                      ACPI NVS memory during hibernation.
 +                      nonvs prevents the kernel from saving/restoring the
 +                      ACPI NVS memory during suspend/hibernation and resume.
                        sci_force_enable causes the kernel to set SCI_EN directly
                        on resume from S1/S3 (which is against the ACPI spec,
                        but some broken systems don't work without it).
        advansys=       [HW,SCSI]
                        See header of drivers/scsi/advansys.c.
  
 -      advwdt=         [HW,WDT] Advantech WDT
 -                      Format: <iostart>,<iostop>
 -
        aedsp16=        [HW,OSS] Audio Excel DSP 16
                        Format: <io>,<irq>,<dma>,<mss_io>,<mpu_io>,<mpu_irq>
                        See also header of sound/oss/aedsp16.c.
                                    they are unmapped. Otherwise they are
                                    flushed before they will be reused, which
                                    is a lot of faster
 +                      off       - do not initialize any AMD IOMMU found in
 +                                  the system
  
        amijoy.map=     [HW,JOY] Amiga joystick support
                        Map of devices attached to JOY0DAT and JOY1DAT
                        The VGA output is eventually overwritten by the real
                        console.
  
 +      ekgdboc=        [X86,KGDB] Allow early kernel console debugging
 +                      ekgdboc=kbd
 +
 +                      This is desgined to be used in conjunction with
 +                      the boot argument: earlyprintk=vga
 +
        eata=           [HW,SCSI]
  
        edd=            [EDD]
                        Default value is 0.
                        Value can be changed at runtime via /selinux/enforce.
  
 +      erst_disable    [ACPI]
 +                      Disable Error Record Serialization Table (ERST)
 +                      support.
 +
        ether=          [HW,NET] Ethernet cards parameters
                        This option is obsoleted by the "netdev=" option, which
                        has equivalent usage. See its documentation for details.
  
 -      eurwdt=         [HW,WDT] Eurotech CPU-1220/1410 onboard watchdog.
 -                      Format: <io>[,<irq>]
 -
        failslab=
        fail_page_alloc=
        fail_make_request=[KNL]
                        as early as possible in order to facilitate early
                        boot debugging.
  
 -      ftrace_dump_on_oops
 +      ftrace_dump_on_oops[=orig_cpu]
                        [FTRACE] will dump the trace buffers on oops.
 +                      If no parameter is passed, ftrace will dump
 +                      buffers of all CPUs, but if you pass orig_cpu, it will
 +                      dump only the buffer of the CPU that triggered the
 +                      oops.
  
        ftrace_filter=[function-list]
                        [FTRACE] Limit the functions traced by the function
        hd=             [EIDE] (E)IDE hard drive subsystem geometry
                        Format: <cyl>,<head>,<sect>
  
 +      hest_disable    [ACPI]
 +                      Disable Hardware Error Source Table (HEST) support;
 +                      corresponding firmware-first mode error processing
 +                      logic will be disabled.
 +
        highmem=nn[KMG] [KNL,BOOT] forces the highmem zone to have an exact
                        size of <nn>. This works even on boxes that have no
                        highmem otherwise. This also works to reduce highmem
                        use the HighMem zone if it exists, and the Normal
                        zone if it does not.
  
 -      kgdboc=         [HW] kgdb over consoles.
 -                      Requires a tty driver that supports console polling.
 -                      (only serial supported for now)
 -                      Format: <serial_device>[,baud]
 +      kgdbdbgp=       [KGDB,HW] kgdb over EHCI usb debug port.
 +                      Format: <Controller#>[,poll interval]
 +                      The controller # is the number of the ehci usb debug
 +                      port as it is probed via PCI.  The poll interval is
 +                      optional and is the number seconds in between
 +                      each poll cycle to the debug port in case you need
 +                      the functionality for interrupting the kernel with
 +                      gdb or control-c on the dbgp connection.  When
 +                      not using this parameter you use sysrq-g to break into
 +                      the kernel debugger.
 +
 +      kgdboc=         [KGDB,HW] kgdb over consoles.
 +                      Requires a tty driver that supports console polling,
 +                      or a supported polling keyboard driver (non-usb).
 +                      Serial only format: <serial_device>[,baud]
 +                      keyboard only format: kbd
 +                      keyboard and serial format: kbd,<serial_device>[,baud]
 +
 +      kgdbwait        [KGDB] Stop kernel execution and enter the
 +                      kernel debugger at the earliest opportunity.
  
        kmac=           [MIPS] korina ethernet MAC address.
                        Configure the RouterBoard 532 series on-chip
                        * nohrst, nosrst, norst: suppress hard, soft
                            and both resets.
  
 +                      * dump_id: dump IDENTIFY data.
 +
                        If there are multiple matching configurations changing
                        the same attribute, the last one is used.
  
 -      lmb=debug       [KNL] Enable lmb debug messages.
 +      memblock=debug  [KNL] Enable memblock debug messages.
  
        load_ramdisk=   [RAM] List of ramdisks to load from floppy
                        See Documentation/blockdev/ramdisk.txt.
  
        nousb           [USB] Disable the USB subsystem
  
+       nowatchdog      [KNL] Disable the lockup detector.
        nowb            [ARM]
  
        nox2apic        [X86-64,APIC] Do not enable x2APIC mode.
                        WARNING: Forcing ASPM on may cause system lockups.
  
        pcie_pme=       [PCIE,PM] Native PCIe PME signaling options:
 -              off     Do not use native PCIe PME signaling.
 +                      Format: {auto|force}[,nomsi]
 +              auto    Use native PCIe PME signaling if the BIOS allows the
 +                      kernel to control PCIe config registers of root ports.
                force   Use native PCIe PME signaling even if the BIOS refuses
                        to allow the kernel to control the relevant PCIe config
                        registers.
  
        sched_debug     [KNL] Enables verbose scheduler debug messages.
  
 -      sc1200wdt=      [HW,WDT] SC1200 WDT (watchdog) driver
 -                      Format: <io>[,<timeout>[,<isapnp>]]
 -
        scsi_debug_*=   [SCSI]
                        See drivers/scsi/scsi_debug.c.
  
  
        tp720=          [HW,PS2]
  
 +      tpm_suspend_pcr=[HW,TPM]
 +                      Format: integer pcr id
 +                      Specify that at suspend time, the tpm driver
 +                      should extend the specified pcr with zeros,
 +                      as a workaround for some chips which fail to
 +                      flush the last written pcr on TPM_SaveState.
 +                      This will guarantee that all the other pcrs
 +                      are saved.
 +
        trace_buf_size=nn[KMG]
                        [FTRACE] will set tracing buffer size.
  
        wd7000=         [HW,SCSI]
                        See header of drivers/scsi/wd7000.c.
  
 -      wdt=            [WDT] Watchdog
 -                      See Documentation/watchdog/wdt.txt.
 +      watchdog timers [HW,WDT] For information on watchdog timers,
 +                      see Documentation/watchdog/watchdog-parameters.txt
 +                      or other driver-specific files in the
 +                      Documentation/watchdog/ directory.
  
        x2apic_phys     [X86-64,APIC] Use x2apic physical mode instead of
                        default x2apic cluster mode on platforms
diff --combined arch/Kconfig
index acda512da2e21b52a972bb4255404fab3fce7015,35084f280087fa86daddaedfc97bdb6dec0dbb23..4877a8c8ee1697599289f35107824f95ba8daf84
@@@ -42,10 -42,15 +42,10 @@@ config KPROBE
          If in doubt, say "N".
  
  config OPTPROBES
 -      bool "Kprobes jump optimization support (EXPERIMENTAL)"
 -      default y
 -      depends on KPROBES
 +      def_bool y
 +      depends on KPROBES && HAVE_OPTPROBES
        depends on !PREEMPT
 -      depends on HAVE_OPTPROBES
        select KALLSYMS_ALL
 -      help
 -        This option will allow kprobes to optimize breakpoint to
 -        a jump for reducing its overhead.
  
  config HAVE_EFFICIENT_UNALIGNED_ACCESS
        bool
@@@ -137,18 -142,14 +137,25 @@@ config HAVE_HW_BREAKPOIN
        bool
        depends on PERF_EVENTS
  
 +config HAVE_MIXED_BREAKPOINTS_REGS
 +      bool
 +      depends on HAVE_HW_BREAKPOINT
 +      help
 +        Depending on the arch implementation of hardware breakpoints,
 +        some of them have separate registers for data and instruction
 +        breakpoints addresses, others have mixed registers to store
 +        them but define the access type in a control register.
 +        Select this option if your arch implements breakpoints under the
 +        latter fashion.
 +
  config HAVE_USER_RETURN_NOTIFIER
        bool
  
+ config HAVE_PERF_EVENTS_NMI
+       bool
+       help
+         System hardware can generate an NMI using the perf event
+         subsystem.  Also has support for calculating CPU cycle events
+         to determine how many clock cycles in a given period.
  source "kernel/gcov/Kconfig"
diff --combined arch/x86/Kconfig
index dcb0593b4a66348a204a44fee3366c5da0848ad1,3cb5bb02172bcc14ac6834c590b6d061c2e48026..6f77afa6bca92203a338badf7e25a3fe01ab4e57
@@@ -53,15 -53,12 +53,16 @@@ config X8
        select HAVE_KERNEL_LZMA
        select HAVE_KERNEL_LZO
        select HAVE_HW_BREAKPOINT
 +      select HAVE_MIXED_BREAKPOINTS_REGS
        select PERF_EVENTS
+       select HAVE_PERF_EVENTS_NMI
        select ANON_INODES
        select HAVE_ARCH_KMEMCHECK
        select HAVE_USER_RETURN_NOTIFIER
  
 +config INSTRUCTION_DECODER
 +      def_bool (KPROBES || PERF_EVENTS)
 +
  config OUTPUT_FORMAT
        string
        default "elf32-i386" if X86_32
@@@ -109,9 -106,6 +110,9 @@@ config SBU
  config NEED_DMA_MAP_STATE
         def_bool (X86_64 || DMAR || DMA_API_DEBUG)
  
 +config NEED_SG_DMA_LENGTH
 +      def_bool y
 +
  config GENERIC_ISA_DMA
        def_bool y
  
@@@ -204,17 -198,20 +205,17 @@@ config HAVE_INTEL_TX
  
  # Use the generic interrupt handling code in kernel/irq/:
  config GENERIC_HARDIRQS
 -      bool
 -      default y
 +      def_bool y
  
  config GENERIC_HARDIRQS_NO__DO_IRQ
         def_bool y
  
  config GENERIC_IRQ_PROBE
 -      bool
 -      default y
 +      def_bool y
  
  config GENERIC_PENDING_IRQ
 -      bool
 +      def_bool y
        depends on GENERIC_HARDIRQS && SMP
 -      default y
  
  config USE_GENERIC_SMP_HELPERS
        def_bool y
@@@ -229,22 -226,19 +230,22 @@@ config X86_64_SM
        depends on X86_64 && SMP
  
  config X86_HT
 -      bool
 +      def_bool y
        depends on SMP
 -      default y
  
  config X86_TRAMPOLINE
 -      bool
 +      def_bool y
        depends on SMP || (64BIT && ACPI_SLEEP)
 -      default y
  
  config X86_32_LAZY_GS
        def_bool y
        depends on X86_32 && !CC_STACKPROTECTOR
  
 +config ARCH_HWEIGHT_CFLAGS
 +      string
 +      default "-fcall-saved-ecx -fcall-saved-edx" if X86_32
 +      default "-fcall-saved-rdi -fcall-saved-rsi -fcall-saved-rdx -fcall-saved-rcx -fcall-saved-r8 -fcall-saved-r9 -fcall-saved-r10 -fcall-saved-r11" if X86_64
 +
  config KTIME_SCALAR
        def_bool X86_32
  source "init/Kconfig"
@@@ -454,7 -448,7 +455,7 @@@ config X86_NUMA
          firmware with - send email to <Martin.Bligh@us.ibm.com>.
  
  config X86_SUPPORTS_MEMORY_FAILURE
 -      bool
 +      def_bool y
        # MCE code calls memory_failure():
        depends on X86_MCE
        # On 32-bit this adds too big of NODES_SHIFT and we run out of page flags:
        # On 32-bit SPARSEMEM adds too big of SECTIONS_WIDTH:
        depends on X86_64 || !SPARSEMEM
        select ARCH_SUPPORTS_MEMORY_FAILURE
 -      default y
  
  config X86_VISWS
        bool "SGI 320/540 (Visual Workstation)"
@@@ -576,6 -571,7 +577,6 @@@ config PARAVIRT_SPINLOCK
  
  config PARAVIRT_CLOCK
        bool
 -      default n
  
  endif
  
@@@ -754,6 -750,7 +755,6 @@@ config MAXSM
        bool "Configure Maximum number of SMP Processors and NUMA Nodes"
        depends on X86_64 && SMP && DEBUG_KERNEL && EXPERIMENTAL
        select CPUMASK_OFFSTACK
 -      default n
        ---help---
          Configure maximum number of CPUS and NUMA Nodes for this architecture.
          If unsure, say N.
@@@ -833,6 -830,7 +834,6 @@@ config X86_VISWS_API
  
  config X86_REROUTE_FOR_BROKEN_BOOT_IRQS
        bool "Reroute for broken boot IRQs"
 -      default n
        depends on X86_IO_APIC
        ---help---
          This option enables a workaround that fixes a source of
@@@ -879,8 -877,9 +880,8 @@@ config X86_MCE_AM
           the DRAM Error Threshold.
  
  config X86_ANCIENT_MCE
 -      def_bool n
 +      bool "Support for old Pentium 5 / WinChip machine checks"
        depends on X86_32 && X86_MCE
 -      prompt "Support for old Pentium 5 / WinChip machine checks"
        ---help---
          Include support for machine check handling on old Pentium 5 or WinChip
          systems. These typically need to be enabled explicitely on the command
  
  config X86_MCE_THRESHOLD
        depends on X86_MCE_AMD || X86_MCE_INTEL
 -      bool
 -      default y
 +      def_bool y
  
  config X86_MCE_INJECT
        depends on X86_MCE
@@@ -1027,8 -1027,8 +1028,8 @@@ config X86_CPUI
  
  choice
        prompt "High Memory Support"
 -      default HIGHMEM4G if !X86_NUMAQ
        default HIGHMEM64G if X86_NUMAQ
 +      default HIGHMEM4G
        depends on X86_32
  
  config NOHIGHMEM
@@@ -1286,7 -1286,7 +1287,7 @@@ source "mm/Kconfig
  
  config HIGHPTE
        bool "Allocate 3rd-level pagetables from highmem"
 -      depends on X86_32 && (HIGHMEM4G || HIGHMEM64G)
 +      depends on HIGHMEM
        ---help---
          The VM uses one page table entry for each page of physical memory.
          For systems with a lot of RAM, this can be wasteful of precious
@@@ -1370,7 -1370,8 +1371,7 @@@ config MATH_EMULATIO
          kernel, it won't hurt.
  
  config MTRR
 -      bool
 -      default y
 +      def_bool y
        prompt "MTRR (Memory Type Range Register) support" if EMBEDDED
        ---help---
          On Intel P6 family processors (Pentium Pro, Pentium II and later)
@@@ -1436,7 -1437,8 +1437,7 @@@ config MTRR_SANITIZER_SPARE_REG_NR_DEFA
          mtrr_spare_reg_nr=N on the kernel command line.
  
  config X86_PAT
 -      bool
 -      default y
 +      def_bool y
        prompt "x86 PAT support" if EMBEDDED
        depends on MTRR
        ---help---
@@@ -1604,7 -1606,8 +1605,7 @@@ config X86_NEED_RELOC
        depends on X86_32 && RELOCATABLE
  
  config PHYSICAL_ALIGN
 -      hex
 -      prompt "Alignment value to which kernel should be aligned" if X86_32
 +      hex "Alignment value to which kernel should be aligned" if X86_32
        default "0x1000000"
        range 0x2000 0x1000000
        ---help---
@@@ -1651,6 -1654,7 +1652,6 @@@ config COMPAT_VDS
  
  config CMDLINE_BOOL
        bool "Built-in kernel command line"
 -      default n
        ---help---
          Allow for specifying boot arguments to the kernel at
          build time.  On some systems (e.g. embedded ones), it is
@@@ -1684,6 -1688,7 +1685,6 @@@ config CMDLIN
  
  config CMDLINE_OVERRIDE
        bool "Built-in command line overrides boot loader arguments"
 -      default n
        depends on CMDLINE_BOOL
        ---help---
          Set this option to 'Y' to have the kernel ignore the boot loader
@@@ -1706,10 -1711,6 +1707,10 @@@ config HAVE_ARCH_EARLY_PFN_TO_NI
        def_bool X86_64
        depends on NUMA
  
 +config USE_PERCPU_NUMA_NODE_ID
 +      def_bool X86_64
 +      depends on NUMA
 +
  menu "Power management and ACPI options"
  
  config ARCH_HIBERNATION_HEADER
@@@ -1723,7 -1724,8 +1724,7 @@@ source "drivers/acpi/Kconfig
  source "drivers/sfi/Kconfig"
  
  config X86_APM_BOOT
 -      bool
 -      default y
 +      def_bool y
        depends on APM || APM_MODULE
  
  menuconfig APM
@@@ -1930,14 -1932,6 +1931,14 @@@ config PCI_MMCONFI
        bool "Support mmconfig PCI config space access"
        depends on X86_64 && PCI && ACPI
  
 +config PCI_CNB20LE_QUIRK
 +      bool "Read CNB20LE Host Bridge Windows"
 +      depends on PCI
 +      help
 +        Read the PCI windows out of the CNB20LE host bridge. This allows
 +        PCI hotplug to work on systems with the CNB20LE chipset which do
 +        not have ACPI.
 +
  config DMAR
        bool "Support for DMA Remapping Devices (EXPERIMENTAL)"
        depends on PCI_MSI && ACPI && EXPERIMENTAL
@@@ -1960,7 -1954,8 +1961,7 @@@ config DMAR_DEFAULT_O
          experimental.
  
  config DMAR_BROKEN_GFX_WA
 -      def_bool n
 -      prompt "Workaround broken graphics drivers (going away soon)"
 +      bool "Workaround broken graphics drivers (going away soon)"
        depends on DMAR && BROKEN
        ---help---
          Current Graphics drivers tend to use physical address
@@@ -2058,6 -2053,7 +2059,6 @@@ config SCx200HR_TIME
  config OLPC
        bool "One Laptop Per Child support"
        select GPIOLIB
 -      default n
        ---help---
          Add support for detecting the unique features of the OLPC
          XO hardware.
diff --combined arch/x86/kernel/traps.c
index 725ef4d17cd5922289b24e515c8b030e86cf6c18,bd347c2b34dc6b53f2b5d9e0293f534446ba271e..60788dee0f8a74f53d547c462d5694201b6d609d
@@@ -15,7 -15,6 +15,7 @@@
  #include <linux/kprobes.h>
  #include <linux/uaccess.h>
  #include <linux/kdebug.h>
 +#include <linux/kgdb.h>
  #include <linux/kernel.h>
  #include <linux/module.h>
  #include <linux/ptrace.h>
@@@ -109,6 -108,15 +109,6 @@@ static inline void preempt_conditional_
        dec_preempt_count();
  }
  
 -#ifdef CONFIG_X86_32
 -static inline void
 -die_if_kernel(const char *str, struct pt_regs *regs, long err)
 -{
 -      if (!user_mode_vm(regs))
 -              die(str, regs, err);
 -}
 -#endif
 -
  static void __kprobes
  do_trap(int trapnr, int signr, char *str, struct pt_regs *regs,
        long error_code, siginfo_t *info)
@@@ -392,7 -400,13 +392,13 @@@ static notrace __kprobes void default_d
                if (notify_die(DIE_NMI_IPI, "nmi_ipi", regs, reason, 2, SIGINT)
                                                                == NOTIFY_STOP)
                        return;
  #ifdef CONFIG_X86_LOCAL_APIC
+               if (notify_die(DIE_NMI, "nmi", regs, reason, 2, SIGINT)
+                                                       == NOTIFY_STOP)
+                       return;
+ #ifndef CONFIG_LOCKUP_DETECTOR
                /*
                 * Ok, so this is none of the documented NMI sources,
                 * so it must be the NMI watchdog.
                if (nmi_watchdog_tick(regs, reason))
                        return;
                if (!do_nmi_callback(regs, cpu))
+ #endif /* !CONFIG_LOCKUP_DETECTOR */
                        unknown_nmi_error(reason, regs);
  #else
                unknown_nmi_error(reason, regs);
@@@ -452,11 -467,6 +459,11 @@@ void restart_nmi(void
  /* May run on IST stack. */
  dotraplinkage void __kprobes do_int3(struct pt_regs *regs, long error_code)
  {
 +#ifdef CONFIG_KGDB_LOW_LEVEL_TRAP
 +      if (kgdb_ll_trap(DIE_INT3, "int3", regs, error_code, 3, SIGTRAP)
 +                      == 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)
@@@ -526,7 -536,6 +533,7 @@@ asmlinkage __kprobes struct pt_regs *sy
  dotraplinkage void __kprobes do_debug(struct pt_regs *regs, long error_code)
  {
        struct task_struct *tsk = current;
 +      int user_icebp = 0;
        unsigned long dr6;
        int si_code;
  
        /* Filter out all the reserved bits which are preset to 1 */
        dr6 &= ~DR6_RESERVED;
  
 +      /*
 +       * If dr6 has no reason to give us about the origin of this trap,
 +       * then it's very likely the result of an icebp/int01 trap.
 +       * User wants a sigtrap for that.
 +       */
 +      if (!dr6 && user_mode(regs))
 +              user_icebp = 1;
 +
        /* Catch kmemcheck conditions first of all! */
        if ((dr6 & DR_STEP) && kmemcheck_trap(regs))
                return;
  
        /* DR6 may or may not be cleared by the CPU */
        set_debugreg(0, 6);
 +
        /*
         * The processor cleared BTF, so don't mark that we need it set.
         */
 -      clear_tsk_thread_flag(tsk, TIF_DEBUGCTLMSR);
 -      tsk->thread.debugctlmsr = 0;
 +      clear_tsk_thread_flag(tsk, TIF_BLOCKSTEP);
  
        /* Store the virtualized DR6 value */
        tsk->thread.debugreg6 = dr6;
                regs->flags &= ~X86_EFLAGS_TF;
        }
        si_code = get_si_code(tsk->thread.debugreg6);
 -      if (tsk->thread.debugreg6 & (DR_STEP | DR_TRAP_BITS))
 +      if (tsk->thread.debugreg6 & (DR_STEP | DR_TRAP_BITS) || user_icebp)
                send_sigtrap(tsk, regs, error_code, si_code);
        preempt_conditional_cli(regs);
  
        return;
  }
  
 -#ifdef CONFIG_X86_64
 -static int kernel_math_error(struct pt_regs *regs, const char *str, int trapnr)
 -{
 -      if (fixup_exception(regs))
 -              return 1;
 -
 -      notify_die(DIE_GPF, str, regs, 0, trapnr, SIGFPE);
 -      /* Illegal floating point operation in the kernel */
 -      current->thread.trap_no = trapnr;
 -      die(str, regs, 0);
 -      return 0;
 -}
 -#endif
 -
  /*
   * Note that we play around with the 'TS' bit in an attempt to get
   * the correct behaviour even in the presence of the asynchronous
   * IRQ13 behaviour
   */
 -void math_error(void __user *ip)
 +void math_error(struct pt_regs *regs, int error_code, int trapnr)
  {
 -      struct task_struct *task;
 +      struct task_struct *task = current;
        siginfo_t info;
 -      unsigned short cwd, swd, err;
 +      unsigned short err;
 +      char *str = (trapnr == 16) ? "fpu exception" : "simd exception";
 +
 +      if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, SIGFPE) == NOTIFY_STOP)
 +              return;
 +      conditional_sti(regs);
 +
 +      if (!user_mode_vm(regs))
 +      {
 +              if (!fixup_exception(regs)) {
 +                      task->thread.error_code = error_code;
 +                      task->thread.trap_no = trapnr;
 +                      die(str, regs, error_code);
 +              }
 +              return;
 +      }
  
        /*
         * Save the info for the exception handler and clear the error.
         */
 -      task = current;
        save_init_fpu(task);
 -      task->thread.trap_no = 16;
 -      task->thread.error_code = 0;
 +      task->thread.trap_no = trapnr;
 +      task->thread.error_code = error_code;
        info.si_signo = SIGFPE;
        info.si_errno = 0;
 -      info.si_addr = ip;
 -      /*
 -       * (~cwd & swd) will mask out exceptions that are not set to unmasked
 -       * status.  0x3f is the exception bits in these regs, 0x200 is the
 -       * C1 reg you need in case of a stack fault, 0x040 is the stack
 -       * fault bit.  We should only be taking one exception at a time,
 -       * so if this combination doesn't produce any single exception,
 -       * then we have a bad program that isn't synchronizing its FPU usage
 -       * and it will suffer the consequences since we won't be able to
 -       * fully reproduce the context of the exception
 -       */
 -      cwd = get_fpu_cwd(task);
 -      swd = get_fpu_swd(task);
 +      info.si_addr = (void __user *)regs->ip;
 +      if (trapnr == 16) {
 +              unsigned short cwd, swd;
 +              /*
 +               * (~cwd & swd) will mask out exceptions that are not set to unmasked
 +               * status.  0x3f is the exception bits in these regs, 0x200 is the
 +               * C1 reg you need in case of a stack fault, 0x040 is the stack
 +               * fault bit.  We should only be taking one exception at a time,
 +               * so if this combination doesn't produce any single exception,
 +               * then we have a bad program that isn't synchronizing its FPU usage
 +               * and it will suffer the consequences since we won't be able to
 +               * fully reproduce the context of the exception
 +               */
 +              cwd = get_fpu_cwd(task);
 +              swd = get_fpu_swd(task);
  
 -      err = swd & ~cwd;
 +              err = swd & ~cwd;
 +      } else {
 +              /*
 +               * The SIMD FPU exceptions are handled a little differently, as there
 +               * is only a single status/control register.  Thus, to determine which
 +               * unmasked exception was caught we must mask the exception mask bits
 +               * at 0x1f80, and then use these to mask the exception bits at 0x3f.
 +               */
 +              unsigned short mxcsr = get_fpu_mxcsr(task);
 +              err = ~(mxcsr >> 7) & mxcsr;
 +      }
  
        if (err & 0x001) {      /* Invalid op */
                /*
  
  dotraplinkage void do_coprocessor_error(struct pt_regs *regs, long error_code)
  {
 -      conditional_sti(regs);
 -
  #ifdef CONFIG_X86_32
        ignore_fpu_irq = 1;
 -#else
 -      if (!user_mode(regs) &&
 -          kernel_math_error(regs, "kernel x87 math error", 16))
 -              return;
  #endif
  
 -      math_error((void __user *)regs->ip);
 -}
 -
 -static void simd_math_error(void __user *ip)
 -{
 -      struct task_struct *task;
 -      siginfo_t info;
 -      unsigned short mxcsr;
 -
 -      /*
 -       * Save the info for the exception handler and clear the error.
 -       */
 -      task = current;
 -      save_init_fpu(task);
 -      task->thread.trap_no = 19;
 -      task->thread.error_code = 0;
 -      info.si_signo = SIGFPE;
 -      info.si_errno = 0;
 -      info.si_code = __SI_FAULT;
 -      info.si_addr = ip;
 -      /*
 -       * The SIMD FPU exceptions are handled a little differently, as there
 -       * is only a single status/control register.  Thus, to determine which
 -       * unmasked exception was caught we must mask the exception mask bits
 -       * at 0x1f80, and then use these to mask the exception bits at 0x3f.
 -       */
 -      mxcsr = get_fpu_mxcsr(task);
 -      switch (~((mxcsr & 0x1f80) >> 7) & (mxcsr & 0x3f)) {
 -      case 0x000:
 -      default:
 -              break;
 -      case 0x001: /* Invalid Op */
 -              info.si_code = FPE_FLTINV;
 -              break;
 -      case 0x002: /* Denormalize */
 -      case 0x010: /* Underflow */
 -              info.si_code = FPE_FLTUND;
 -              break;
 -      case 0x004: /* Zero Divide */
 -              info.si_code = FPE_FLTDIV;
 -              break;
 -      case 0x008: /* Overflow */
 -              info.si_code = FPE_FLTOVF;
 -              break;
 -      case 0x020: /* Precision */
 -              info.si_code = FPE_FLTRES;
 -              break;
 -      }
 -      force_sig_info(SIGFPE, &info, task);
 +      math_error(regs, error_code, 16);
  }
  
  dotraplinkage void
  do_simd_coprocessor_error(struct pt_regs *regs, long error_code)
  {
 -      conditional_sti(regs);
 -
 -#ifdef CONFIG_X86_32
 -      if (cpu_has_xmm) {
 -              /* Handle SIMD FPU exceptions on PIII+ processors. */
 -              ignore_fpu_irq = 1;
 -              simd_math_error((void __user *)regs->ip);
 -              return;
 -      }
 -      /*
 -       * Handle strange cache flush from user space exception
 -       * in all other cases.  This is undocumented behaviour.
 -       */
 -      if (regs->flags & X86_VM_MASK) {
 -              handle_vm86_fault((struct kernel_vm86_regs *)regs, error_code);
 -              return;
 -      }
 -      current->thread.trap_no = 19;
 -      current->thread.error_code = error_code;
 -      die_if_kernel("cache flush denied", regs, error_code);
 -      force_sig(SIGSEGV, current);
 -#else
 -      if (!user_mode(regs) &&
 -                      kernel_math_error(regs, "kernel simd math error", 19))
 -              return;
 -      simd_math_error((void __user *)regs->ip);
 -#endif
 +      math_error(regs, error_code, 19);
  }
  
  dotraplinkage void
@@@ -817,16 -886,6 +824,16 @@@ dotraplinkage void do_iret_error(struc
  }
  #endif
  
 +/* Set of traps needed for early debugging. */
 +void __init early_trap_init(void)
 +{
 +      set_intr_gate_ist(1, &debug, DEBUG_STACK);
 +      /* int3 can be called from all */
 +      set_system_intr_gate_ist(3, &int3, DEBUG_STACK);
 +      set_intr_gate(14, &page_fault);
 +      load_idt(&idt_descr);
 +}
 +
  void __init trap_init(void)
  {
        int i;
  #endif
  
        set_intr_gate(0, &divide_error);
 -      set_intr_gate_ist(1, &debug, DEBUG_STACK);
        set_intr_gate_ist(2, &nmi, NMI_STACK);
 -      /* int3 can be called from all */
 -      set_system_intr_gate_ist(3, &int3, DEBUG_STACK);
        /* int4 can be called from all */
        set_system_intr_gate(4, &overflow);
        set_intr_gate(5, &bounds);
        set_intr_gate(11, &segment_not_present);
        set_intr_gate_ist(12, &stack_segment, STACKFAULT_STACK);
        set_intr_gate(13, &general_protection);
 -      set_intr_gate(14, &page_fault);
        set_intr_gate(15, &spurious_interrupt_bug);
        set_intr_gate(16, &coprocessor_error);
        set_intr_gate(17, &alignment_check);
diff --combined include/linux/sched.h
index 7b6ec63cb74fa7f7d83520b2712b772a09c89ecf,3958e0cd24f70dea00c5f088725674ad64d1db1f..3992f50de6145927a39f72c46dcf8279a16f57ab
@@@ -99,6 -99,7 +99,6 @@@ struct futex_pi_state
  struct robust_list_head;
  struct bio_list;
  struct fs_struct;
 -struct bts_context;
  struct perf_event_context;
  
  /*
@@@ -139,7 -140,7 +139,7 @@@ extern int nr_processes(void)
  extern unsigned long nr_running(void);
  extern unsigned long nr_uninterruptible(void);
  extern unsigned long nr_iowait(void);
 -extern unsigned long nr_iowait_cpu(void);
 +extern unsigned long nr_iowait_cpu(int cpu);
  extern unsigned long this_cpu_load(void);
  
  
@@@ -214,7 -215,6 +214,7 @@@ extern char ___assert_task_state[1 - 2*
  
  #define task_is_traced(task)  ((task->state & __TASK_TRACED) != 0)
  #define task_is_stopped(task) ((task->state & __TASK_STOPPED) != 0)
 +#define task_is_dead(task)    ((task)->exit_state != 0)
  #define task_is_stopped_or_traced(task)       \
                        ((task->state & (__TASK_STOPPED | __TASK_TRACED)) != 0)
  #define task_contributes_to_load(task)        \
@@@ -269,22 -269,17 +269,22 @@@ extern void init_idle(struct task_struc
  extern void init_idle_bootup_task(struct task_struct *idle);
  
  extern int runqueue_is_locked(int cpu);
 -extern void task_rq_unlock_wait(struct task_struct *p);
  
  extern cpumask_var_t nohz_cpu_mask;
  #if defined(CONFIG_SMP) && defined(CONFIG_NO_HZ)
  extern int select_nohz_load_balancer(int cpu);
  extern int get_nohz_load_balancer(void);
 +extern int nohz_ratelimit(int cpu);
  #else
  static inline int select_nohz_load_balancer(int cpu)
  {
        return 0;
  }
 +
 +static inline int nohz_ratelimit(int cpu)
 +{
 +      return 0;
 +}
  #endif
  
  /*
@@@ -316,20 -311,16 +316,16 @@@ extern void scheduler_tick(void)
  
  extern void sched_show_task(struct task_struct *p);
  
- #ifdef CONFIG_DETECT_SOFTLOCKUP
- extern void softlockup_tick(void);
+ #ifdef CONFIG_LOCKUP_DETECTOR
  extern void touch_softlockup_watchdog(void);
  extern void touch_softlockup_watchdog_sync(void);
  extern void touch_all_softlockup_watchdogs(void);
- extern int proc_dosoftlockup_thresh(struct ctl_table *table, int write,
-                                   void __user *buffer,
-                                   size_t *lenp, loff_t *ppos);
+ extern int proc_dowatchdog_thresh(struct ctl_table *table, int write,
+                                 void __user *buffer,
+                                 size_t *lenp, loff_t *ppos);
  extern unsigned int  softlockup_panic;
  extern int softlockup_thresh;
  #else
- static inline void softlockup_tick(void)
- {
- }
  static inline void touch_softlockup_watchdog(void)
  {
  }
@@@ -384,7 -375,7 +380,7 @@@ struct user_namespace
   * 1-3 now and depends on arch. We use "5" as safe margin, here.
   */
  #define MAPCOUNT_ELF_CORE_MARGIN      (5)
 -#define DEFAULT_MAX_MAP_COUNT (USHORT_MAX - MAPCOUNT_ELF_CORE_MARGIN)
 +#define DEFAULT_MAX_MAP_COUNT (USHRT_MAX - MAPCOUNT_ELF_CORE_MARGIN)
  
  extern int sysctl_max_map_count;
  
@@@ -527,9 -518,8 +523,9 @@@ struct thread_group_cputimer 
   * the locking of signal_struct.
   */
  struct signal_struct {
 -      atomic_t                count;
 +      atomic_t                sigcnt;
        atomic_t                live;
 +      int                     nr_threads;
  
        wait_queue_head_t       wait_chldexit;  /* for wait4() */
  
@@@ -960,7 -950,6 +956,7 @@@ struct sched_domain 
        char *name;
  #endif
  
 +      unsigned int span_weight;
        /*
         * Span of all CPUs in this domain.
         *
@@@ -1033,17 -1022,12 +1029,17 @@@ struct sched_domain
  #define WF_SYNC               0x01            /* waker goes to sleep after wakup */
  #define WF_FORK               0x02            /* child wakeup after fork */
  
 +#define ENQUEUE_WAKEUP                1
 +#define ENQUEUE_WAKING                2
 +#define ENQUEUE_HEAD          4
 +
 +#define DEQUEUE_SLEEP         1
 +
  struct sched_class {
        const struct sched_class *next;
  
 -      void (*enqueue_task) (struct rq *rq, struct task_struct *p, int wakeup,
 -                            bool head);
 -      void (*dequeue_task) (struct rq *rq, struct task_struct *p, int sleep);
 +      void (*enqueue_task) (struct rq *rq, struct task_struct *p, int flags);
 +      void (*dequeue_task) (struct rq *rq, struct task_struct *p, int flags);
        void (*yield_task) (struct rq *rq);
  
        void (*check_preempt_curr) (struct rq *rq, struct task_struct *p, int flags);
        void (*put_prev_task) (struct rq *rq, struct task_struct *p);
  
  #ifdef CONFIG_SMP
 -      int  (*select_task_rq)(struct task_struct *p, int sd_flag, int flags);
 +      int  (*select_task_rq)(struct rq *rq, struct task_struct *p,
 +                             int sd_flag, int flags);
  
        void (*pre_schedule) (struct rq *this_rq, struct task_struct *task);
        void (*post_schedule) (struct rq *this_rq);
@@@ -1090,8 -1073,36 +1086,8 @@@ struct load_weight 
        unsigned long weight, inv_weight;
  };
  
 -/*
 - * CFS stats for a schedulable entity (task, task-group etc)
 - *
 - * Current field usage histogram:
 - *
 - *     4 se->block_start
 - *     4 se->run_node
 - *     4 se->sleep_start
 - *     6 se->load.weight
 - */
 -struct sched_entity {
 -      struct load_weight      load;           /* for load-balancing */
 -      struct rb_node          run_node;
 -      struct list_head        group_node;
 -      unsigned int            on_rq;
 -
 -      u64                     exec_start;
 -      u64                     sum_exec_runtime;
 -      u64                     vruntime;
 -      u64                     prev_sum_exec_runtime;
 -
 -      u64                     last_wakeup;
 -      u64                     avg_overlap;
 -
 -      u64                     nr_migrations;
 -
 -      u64                     start_runtime;
 -      u64                     avg_wakeup;
 -
  #ifdef CONFIG_SCHEDSTATS
 +struct sched_statistics {
        u64                     wait_start;
        u64                     wait_max;
        u64                     wait_count;
        u64                     nr_wakeups_affine_attempts;
        u64                     nr_wakeups_passive;
        u64                     nr_wakeups_idle;
 +};
 +#endif
 +
 +struct sched_entity {
 +      struct load_weight      load;           /* for load-balancing */
 +      struct rb_node          run_node;
 +      struct list_head        group_node;
 +      unsigned int            on_rq;
 +
 +      u64                     exec_start;
 +      u64                     sum_exec_runtime;
 +      u64                     vruntime;
 +      u64                     prev_sum_exec_runtime;
 +
 +      u64                     nr_migrations;
 +
 +#ifdef CONFIG_SCHEDSTATS
 +      struct sched_statistics statistics;
  #endif
  
  #ifdef CONFIG_FAIR_GROUP_SCHED
@@@ -1275,6 -1268,12 +1271,6 @@@ struct task_struct 
        struct list_head ptraced;
        struct list_head ptrace_entry;
  
 -      /*
 -       * This is the tracer handle for the ptrace BTS extension.
 -       * This field actually belongs to the ptracer task.
 -       */
 -      struct bts_context *bts;
 -
        /* PID/PID hash table linkage. */
        struct pid_link pids[PIDTYPE_MAX];
        struct list_head thread_group;
  #endif
  #ifdef CONFIG_CPUSETS
        nodemask_t mems_allowed;        /* Protected by alloc_lock */
 +      int mems_allowed_change_disable;
        int cpuset_mem_spread_rotor;
 +      int cpuset_slab_spread_rotor;
  #endif
  #ifdef CONFIG_CGROUPS
        /* Control Group info protected by css_set_lock */
        /* bitmask of trace recursion */
        unsigned long trace_recursion;
  #endif /* CONFIG_TRACING */
 -      unsigned long stack_start;
  #ifdef CONFIG_CGROUP_MEM_RES_CTLR /* memcg uses this to do batch job */
        struct memcg_batch_info {
                int do_batch;   /* incremented when batch uncharge started */
@@@ -1845,7 -1843,6 +1841,7 @@@ extern void sched_clock_idle_sleep_even
  extern void sched_clock_idle_wakeup_event(u64 delta_ns);
  
  #ifdef CONFIG_HOTPLUG_CPU
 +extern void move_task_off_dead_cpu(int dead_cpu, struct task_struct *p);
  extern void idle_task_exit(void);
  #else
  static inline void idle_task_exit(void) {}
@@@ -2037,7 -2034,7 +2033,7 @@@ extern int do_notify_parent(struct task
  extern void __wake_up_parent(struct task_struct *p, struct task_struct *parent);
  extern void force_sig(int, struct task_struct *);
  extern int send_sig(int, struct task_struct *, int);
 -extern void zap_other_threads(struct task_struct *p);
 +extern int zap_other_threads(struct task_struct *p);
  extern struct sigqueue *sigqueue_alloc(void);
  extern void sigqueue_free(struct sigqueue *);
  extern int send_sigqueue(struct sigqueue *,  struct task_struct *, int group);
@@@ -2102,6 -2099,7 +2098,6 @@@ extern void flush_thread(void)
  extern void exit_thread(void);
  
  extern void exit_files(struct task_struct *);
 -extern void __cleanup_signal(struct signal_struct *);
  extern void __cleanup_sighand(struct sighand_struct *);
  
  extern void exit_itimers(struct signal_struct *);
@@@ -2121,8 -2119,10 +2117,8 @@@ extern void set_task_comm(struct task_s
  extern char *get_task_comm(char *to, struct task_struct *tsk);
  
  #ifdef CONFIG_SMP
 -extern void wait_task_context_switch(struct task_struct *p);
  extern unsigned long wait_task_inactive(struct task_struct *, long match_state);
  #else
 -static inline void wait_task_context_switch(struct task_struct *p) {}
  static inline unsigned long wait_task_inactive(struct task_struct *p,
                                               long match_state)
  {
@@@ -2148,11 -2148,6 +2144,11 @@@ extern bool current_is_single_threaded(
  #define while_each_thread(g, t) \
        while ((t = next_thread(t)) != g)
  
 +static inline int get_nr_threads(struct task_struct *tsk)
 +{
 +      return tsk->signal->nr_threads;
 +}
 +
  /* de_thread depends on thread_group_leader not being a pid based check */
  #define thread_group_leader(p)        (p == p->group_leader)
  
@@@ -2399,6 -2394,10 +2395,6 @@@ static inline void thread_group_cputime
        spin_lock_init(&sig->cputimer.lock);
  }
  
 -static inline void thread_group_cputime_free(struct signal_struct *sig)
 -{
 -}
 -
  /*
   * Reevaluate whether the task has signals pending delivery.
   * Wake the task if so.
@@@ -2435,6 -2434,18 +2431,6 @@@ static inline void set_task_cpu(struct 
  
  #endif /* CONFIG_SMP */
  
 -#ifdef CONFIG_TRACING
 -extern void
 -__trace_special(void *__tr, void *__data,
 -              unsigned long arg1, unsigned long arg2, unsigned long arg3);
 -#else
 -static inline void
 -__trace_special(void *__tr, void *__data,
 -              unsigned long arg1, unsigned long arg2, unsigned long arg3)
 -{
 -}
 -#endif
 -
  extern long sched_setaffinity(pid_t pid, const struct cpumask *new_mask);
  extern long sched_getaffinity(pid_t pid, struct cpumask *mask);
  
diff --combined kernel/Makefile
index 057472fbc272eed8b64f23c16f55b49217aa9043,6adeafc3e2598c26fd5e03070e7307a1b1052a77..ce53fb2bd1d90669caab50084cfac710c620c946
@@@ -68,16 -68,16 +68,16 @@@ obj-$(CONFIG_USER_NS) += user_namespace
  obj-$(CONFIG_PID_NS) += pid_namespace.o
  obj-$(CONFIG_IKCONFIG) += configs.o
  obj-$(CONFIG_RESOURCE_COUNTERS) += res_counter.o
 -obj-$(CONFIG_STOP_MACHINE) += stop_machine.o
 +obj-$(CONFIG_SMP) += stop_machine.o
  obj-$(CONFIG_KPROBES_SANITY_TEST) += test_kprobes.o
  obj-$(CONFIG_AUDIT) += audit.o auditfilter.o audit_watch.o
  obj-$(CONFIG_AUDITSYSCALL) += auditsc.o
  obj-$(CONFIG_GCOV_KERNEL) += gcov/
  obj-$(CONFIG_AUDIT_TREE) += audit_tree.o
  obj-$(CONFIG_KPROBES) += kprobes.o
 -obj-$(CONFIG_KGDB) += kgdb.o
 +obj-$(CONFIG_KGDB) += debug/
- obj-$(CONFIG_DETECT_SOFTLOCKUP) += softlockup.o
  obj-$(CONFIG_DETECT_HUNG_TASK) += hung_task.o
+ obj-$(CONFIG_LOCKUP_DETECTOR) += watchdog.o
  obj-$(CONFIG_GENERIC_HARDIRQS) += irq/
  obj-$(CONFIG_SECCOMP) += seccomp.o
  obj-$(CONFIG_RCU_TORTURE_TEST) += rcutorture.o
diff --combined kernel/sysctl.c
index d24f761f48769d925692efcbb233a276dad01905,04bcd8abe09ca6da9fce6fe7bfc85a79863b36b0..6f79c7f81c960a3da9d6b3832a92f4deaad9c7d0
@@@ -37,7 -37,6 +37,7 @@@
  #include <linux/highuid.h>
  #include <linux/writeback.h>
  #include <linux/ratelimit.h>
 +#include <linux/compaction.h>
  #include <linux/hugetlb.h>
  #include <linux/initrd.h>
  #include <linux/key.h>
@@@ -53,7 -52,6 +53,7 @@@
  #include <linux/slow-work.h>
  #include <linux/perf_event.h>
  #include <linux/kprobes.h>
 +#include <linux/pipe_fs_i.h>
  
  #include <asm/uaccess.h>
  #include <asm/processor.h>
  #include <scsi/sg.h>
  #endif
  
+ #ifdef CONFIG_LOCKUP_DETECTOR
+ #include <linux/nmi.h>
+ #endif
  
  #if defined(CONFIG_SYSCTL)
  
@@@ -106,7 -108,7 +110,7 @@@ extern int blk_iopoll_enabled
  #endif
  
  /* Constants used for minimum and  maximum */
- #ifdef CONFIG_DETECT_SOFTLOCKUP
+ #ifdef CONFIG_LOCKUP_DETECTOR
  static int sixty = 60;
  static int neg_one = -1;
  #endif
@@@ -165,27 -167,6 +169,27 @@@ static int proc_taint(struct ctl_table 
                               void __user *buffer, size_t *lenp, loff_t *ppos);
  #endif
  
 +#ifdef CONFIG_MAGIC_SYSRQ
 +static int __sysrq_enabled; /* Note: sysrq code ises it's own private copy */
 +
 +static int sysrq_sysctl_handler(ctl_table *table, int write,
 +                              void __user *buffer, size_t *lenp,
 +                              loff_t *ppos)
 +{
 +      int error;
 +
 +      error = proc_dointvec(table, write, buffer, lenp, ppos);
 +      if (error)
 +              return error;
 +
 +      if (write)
 +              sysrq_toggle_support(__sysrq_enabled);
 +
 +      return 0;
 +}
 +
 +#endif
 +
  static struct ctl_table root_table[];
  static struct ctl_table_root sysctl_table_root;
  static struct ctl_table_header root_table_header = {
@@@ -263,11 -244,6 +267,11 @@@ static int min_sched_shares_ratelimit 
  static int max_sched_shares_ratelimit = NSEC_PER_SEC; /* 1 second */
  #endif
  
 +#ifdef CONFIG_COMPACTION
 +static int min_extfrag_threshold;
 +static int max_extfrag_threshold = 1000;
 +#endif
 +
  static struct ctl_table kern_table[] = {
        {
                .procname       = "sched_child_runs_first",
                .data           = &__sysrq_enabled,
                .maxlen         = sizeof (int),
                .mode           = 0644,
 -              .proc_handler   = proc_dointvec,
 +              .proc_handler   = sysrq_sysctl_handler,
        },
  #endif
  #ifdef CONFIG_PROC_SYSCTL
  #endif
        {
                .procname       = "userprocess_debug",
 -              .data           = &sysctl_userprocess_debug,
 +              .data           = &show_unhandled_signals,
                .maxlen         = sizeof(int),
                .mode           = 0644,
                .proc_handler   = proc_dointvec,
                .mode           = 0444,
                .proc_handler   = proc_dointvec,
        },
- #if defined(CONFIG_X86_LOCAL_APIC) && defined(CONFIG_X86)
+ #if defined(CONFIG_LOCKUP_DETECTOR)
+       {
+               .procname       = "watchdog",
+               .data           = &watchdog_enabled,
+               .maxlen         = sizeof (int),
+               .mode           = 0644,
+               .proc_handler   = proc_dowatchdog_enabled,
+       },
+       {
+               .procname       = "watchdog_thresh",
+               .data           = &softlockup_thresh,
+               .maxlen         = sizeof(int),
+               .mode           = 0644,
+               .proc_handler   = proc_dowatchdog_thresh,
+               .extra1         = &neg_one,
+               .extra2         = &sixty,
+       },
+       {
+               .procname       = "softlockup_panic",
+               .data           = &softlockup_panic,
+               .maxlen         = sizeof(int),
+               .mode           = 0644,
+               .proc_handler   = proc_dointvec_minmax,
+               .extra1         = &zero,
+               .extra2         = &one,
+       },
+ #endif
+ #if defined(CONFIG_X86_LOCAL_APIC) && defined(CONFIG_X86) && !defined(CONFIG_LOCKUP_DETECTOR)
        {
                .procname       = "unknown_nmi_panic",
                .data           = &unknown_nmi_panic,
                .proc_handler   = proc_dointvec,
        },
  #endif
- #ifdef CONFIG_DETECT_SOFTLOCKUP
-       {
-               .procname       = "softlockup_panic",
-               .data           = &softlockup_panic,
-               .maxlen         = sizeof(int),
-               .mode           = 0644,
-               .proc_handler   = proc_dointvec_minmax,
-               .extra1         = &zero,
-               .extra2         = &one,
-       },
-       {
-               .procname       = "softlockup_thresh",
-               .data           = &softlockup_thresh,
-               .maxlen         = sizeof(int),
-               .mode           = 0644,
-               .proc_handler   = proc_dosoftlockup_thresh,
-               .extra1         = &neg_one,
-               .extra2         = &sixty,
-       },
- #endif
  #ifdef CONFIG_DETECT_HUNG_TASK
        {
                .procname       = "hung_task_panic",
@@@ -1127,25 -1110,6 +1138,25 @@@ static struct ctl_table vm_table[] = 
                .mode           = 0644,
                .proc_handler   = drop_caches_sysctl_handler,
        },
 +#ifdef CONFIG_COMPACTION
 +      {
 +              .procname       = "compact_memory",
 +              .data           = &sysctl_compact_memory,
 +              .maxlen         = sizeof(int),
 +              .mode           = 0200,
 +              .proc_handler   = sysctl_compaction_handler,
 +      },
 +      {
 +              .procname       = "extfrag_threshold",
 +              .data           = &sysctl_extfrag_threshold,
 +              .maxlen         = sizeof(int),
 +              .mode           = 0644,
 +              .proc_handler   = sysctl_extfrag_handler,
 +              .extra1         = &min_extfrag_threshold,
 +              .extra2         = &max_extfrag_threshold,
 +      },
 +
 +#endif /* CONFIG_COMPACTION */
        {
                .procname       = "min_free_kbytes",
                .data           = &min_free_kbytes,
@@@ -1470,14 -1434,6 +1481,14 @@@ static struct ctl_table fs_table[] = 
                .child          = binfmt_misc_table,
        },
  #endif
 +      {
 +              .procname       = "pipe-max-size",
 +              .data           = &pipe_max_size,
 +              .maxlen         = sizeof(int),
 +              .mode           = 0644,
 +              .proc_handler   = &pipe_proc_fn,
 +              .extra1         = &pipe_min_size,
 +      },
  /*
   * NOTE: do not add new entries to this table unless you have read
   * Documentation/sysctl/ctl_unnumbered.txt
  };
  
  static struct ctl_table debug_table[] = {
 -#if defined(CONFIG_X86) || defined(CONFIG_PPC) || defined(CONFIG_SPARC)
 +#if defined(CONFIG_X86) || defined(CONFIG_PPC) || defined(CONFIG_SPARC) || \
 +    defined(CONFIG_S390)
        {
                .procname       = "exception-trace",
                .data           = &show_unhandled_signals,
@@@ -2096,132 -2051,8 +2107,132 @@@ int proc_dostring(struct ctl_table *tab
                               buffer, lenp, ppos);
  }
  
 +static size_t proc_skip_spaces(char **buf)
 +{
 +      size_t ret;
 +      char *tmp = skip_spaces(*buf);
 +      ret = tmp - *buf;
 +      *buf = tmp;
 +      return ret;
 +}
 +
 +static void proc_skip_char(char **buf, size_t *size, const char v)
 +{
 +      while (*size) {
 +              if (**buf != v)
 +                      break;
 +              (*size)--;
 +              (*buf)++;
 +      }
 +}
 +
 +#define TMPBUFLEN 22
 +/**
 + * proc_get_long - reads an ASCII formatted integer from a user buffer
 + *
 + * @buf: a kernel buffer
 + * @size: size of the kernel buffer
 + * @val: this is where the number will be stored
 + * @neg: set to %TRUE if number is negative
 + * @perm_tr: a vector which contains the allowed trailers
 + * @perm_tr_len: size of the perm_tr vector
 + * @tr: pointer to store the trailer character
 + *
 + * In case of success %0 is returned and @buf and @size are updated with
 + * the amount of bytes read. If @tr is non-NULL and a trailing
 + * character exists (size is non-zero after returning from this
 + * function), @tr is updated with the trailing character.
 + */
 +static int proc_get_long(char **buf, size_t *size,
 +                        unsigned long *val, bool *neg,
 +                        const char *perm_tr, unsigned perm_tr_len, char *tr)
 +{
 +      int len;
 +      char *p, tmp[TMPBUFLEN];
 +
 +      if (!*size)
 +              return -EINVAL;
 +
 +      len = *size;
 +      if (len > TMPBUFLEN - 1)
 +              len = TMPBUFLEN - 1;
 +
 +      memcpy(tmp, *buf, len);
 +
 +      tmp[len] = 0;
 +      p = tmp;
 +      if (*p == '-' && *size > 1) {
 +              *neg = true;
 +              p++;
 +      } else
 +              *neg = false;
 +      if (!isdigit(*p))
 +              return -EINVAL;
 +
 +      *val = simple_strtoul(p, &p, 0);
 +
 +      len = p - tmp;
 +
 +      /* We don't know if the next char is whitespace thus we may accept
 +       * invalid integers (e.g. 1234...a) or two integers instead of one
 +       * (e.g. 123...1). So lets not allow such large numbers. */
 +      if (len == TMPBUFLEN - 1)
 +              return -EINVAL;
 +
 +      if (len < *size && perm_tr_len && !memchr(perm_tr, *p, perm_tr_len))
 +              return -EINVAL;
 +
 +      if (tr && (len < *size))
 +              *tr = *p;
 +
 +      *buf += len;
 +      *size -= len;
 +
 +      return 0;
 +}
 +
 +/**
 + * proc_put_long - converts an integer to a decimal ASCII formatted string
 + *
 + * @buf: the user buffer
 + * @size: the size of the user buffer
 + * @val: the integer to be converted
 + * @neg: sign of the number, %TRUE for negative
 + *
 + * In case of success %0 is returned and @buf and @size are updated with
 + * the amount of bytes written.
 + */
 +static int proc_put_long(void __user **buf, size_t *size, unsigned long val,
 +                        bool neg)
 +{
 +      int len;
 +      char tmp[TMPBUFLEN], *p = tmp;
 +
 +      sprintf(p, "%s%lu", neg ? "-" : "", val);
 +      len = strlen(tmp);
 +      if (len > *size)
 +              len = *size;
 +      if (copy_to_user(*buf, tmp, len))
 +              return -EFAULT;
 +      *size -= len;
 +      *buf += len;
 +      return 0;
 +}
 +#undef TMPBUFLEN
 +
 +static int proc_put_char(void __user **buf, size_t *size, char c)
 +{
 +      if (*size) {
 +              char __user **buffer = (char __user **)buf;
 +              if (put_user(c, *buffer))
 +                      return -EFAULT;
 +              (*size)--, (*buffer)++;
 +              *buf = *buffer;
 +      }
 +      return 0;
 +}
  
 -static int do_proc_dointvec_conv(int *negp, unsigned long *lvalp,
 +static int do_proc_dointvec_conv(bool *negp, unsigned long *lvalp,
                                 int *valp,
                                 int write, void *data)
  {
        } else {
                int val = *valp;
                if (val < 0) {
 -                      *negp = -1;
 +                      *negp = true;
                        *lvalp = (unsigned long)-val;
                } else {
 -                      *negp = 0;
 +                      *negp = false;
                        *lvalp = (unsigned long)val;
                }
        }
        return 0;
  }
  
 +static const char proc_wspace_sep[] = { ' ', '\t', '\n' };
 +
  static int __do_proc_dointvec(void *tbl_data, struct ctl_table *table,
                  int write, void __user *buffer,
                  size_t *lenp, loff_t *ppos,
 -                int (*conv)(int *negp, unsigned long *lvalp, int *valp,
 +                int (*conv)(bool *negp, unsigned long *lvalp, int *valp,
                              int write, void *data),
                  void *data)
  {
 -#define TMPBUFLEN 21
 -      int *i, vleft, first = 1, neg;
 -      unsigned long lval;
 -      size_t left, len;
 +      int *i, vleft, first = 1, err = 0;
 +      unsigned long page = 0;
 +      size_t left;
 +      char *kbuf;
        
 -      char buf[TMPBUFLEN], *p;
 -      char __user *s = buffer;
 -      
 -      if (!tbl_data || !table->maxlen || !*lenp ||
 -          (*ppos && !write)) {
 +      if (!tbl_data || !table->maxlen || !*lenp || (*ppos && !write)) {
                *lenp = 0;
                return 0;
        }
        if (!conv)
                conv = do_proc_dointvec_conv;
  
 +      if (write) {
 +              if (left > PAGE_SIZE - 1)
 +                      left = PAGE_SIZE - 1;
 +              page = __get_free_page(GFP_TEMPORARY);
 +              kbuf = (char *) page;
 +              if (!kbuf)
 +                      return -ENOMEM;
 +              if (copy_from_user(kbuf, buffer, left)) {
 +                      err = -EFAULT;
 +                      goto free;
 +              }
 +              kbuf[left] = 0;
 +      }
 +
        for (; left && vleft--; i++, first=0) {
 +              unsigned long lval;
 +              bool neg;
 +
                if (write) {
 -                      while (left) {
 -                              char c;
 -                              if (get_user(c, s))
 -                                      return -EFAULT;
 -                              if (!isspace(c))
 -                                      break;
 -                              left--;
 -                              s++;
 -                      }
 +                      left -= proc_skip_spaces(&kbuf);
 +
                        if (!left)
                                break;
 -                      neg = 0;
 -                      len = left;
 -                      if (len > sizeof(buf) - 1)
 -                              len = sizeof(buf) - 1;
 -                      if (copy_from_user(buf, s, len))
 -                              return -EFAULT;
 -                      buf[len] = 0;
 -                      p = buf;
 -                      if (*p == '-' && left > 1) {
 -                              neg = 1;
 -                              p++;
 -                      }
 -                      if (*p < '0' || *p > '9')
 +                      err = proc_get_long(&kbuf, &left, &lval, &neg,
 +                                           proc_wspace_sep,
 +                                           sizeof(proc_wspace_sep), NULL);
 +                      if (err)
                                break;
 -
 -                      lval = simple_strtoul(p, &p, 0);
 -
 -                      len = p-buf;
 -                      if ((len < left) && *p && !isspace(*p))
 -                              break;
 -                      s += len;
 -                      left -= len;
 -
 -                      if (conv(&neg, &lval, i, 1, data))
 +                      if (conv(&neg, &lval, i, 1, data)) {
 +                              err = -EINVAL;
                                break;
 +                      }
                } else {
 -                      p = buf;
 +                      if (conv(&neg, &lval, i, 0, data)) {
 +                              err = -EINVAL;
 +                              break;
 +                      }
                        if (!first)
 -                              *p++ = '\t';
 -      
 -                      if (conv(&neg, &lval, i, 0, data))
 +                              err = proc_put_char(&buffer, &left, '\t');
 +                      if (err)
 +                              break;
 +                      err = proc_put_long(&buffer, &left, lval, neg);
 +                      if (err)
                                break;
 -
 -                      sprintf(p, "%s%lu", neg ? "-" : "", lval);
 -                      len = strlen(buf);
 -                      if (len > left)
 -                              len = left;
 -                      if(copy_to_user(s, buf, len))
 -                              return -EFAULT;
 -                      left -= len;
 -                      s += len;
                }
        }
  
 -      if (!write && !first && left) {
 -              if(put_user('\n', s))
 -                      return -EFAULT;
 -              left--, s++;
 -      }
 +      if (!write && !first && left && !err)
 +              err = proc_put_char(&buffer, &left, '\n');
 +      if (write && !err && left)
 +              left -= proc_skip_spaces(&kbuf);
 +free:
        if (write) {
 -              while (left) {
 -                      char c;
 -                      if (get_user(c, s++))
 -                              return -EFAULT;
 -                      if (!isspace(c))
 -                              break;
 -                      left--;
 -              }
 +              free_page(page);
 +              if (first)
 +                      return err ? : -EINVAL;
        }
 -      if (write && first)
 -              return -EINVAL;
        *lenp -= left;
        *ppos += *lenp;
 -      return 0;
 -#undef TMPBUFLEN
 +      return err;
  }
  
  static int do_proc_dointvec(struct ctl_table *table, int write,
                  void __user *buffer, size_t *lenp, loff_t *ppos,
 -                int (*conv)(int *negp, unsigned long *lvalp, int *valp,
 +                int (*conv)(bool *negp, unsigned long *lvalp, int *valp,
                              int write, void *data),
                  void *data)
  {
@@@ -2398,8 -2249,8 +2409,8 @@@ struct do_proc_dointvec_minmax_conv_par
        int *max;
  };
  
 -static int do_proc_dointvec_minmax_conv(int *negp, unsigned long *lvalp, 
 -                                      int *valp, 
 +static int do_proc_dointvec_minmax_conv(bool *negp, unsigned long *lvalp,
 +                                      int *valp,
                                        int write, void *data)
  {
        struct do_proc_dointvec_minmax_conv_param *param = data;
        } else {
                int val = *valp;
                if (val < 0) {
 -                      *negp = -1;
 +                      *negp = true;
                        *lvalp = (unsigned long)-val;
                } else {
 -                      *negp = 0;
 +                      *negp = false;
                        *lvalp = (unsigned long)val;
                }
        }
@@@ -2455,78 -2306,102 +2466,78 @@@ static int __do_proc_doulongvec_minmax(
                                     unsigned long convmul,
                                     unsigned long convdiv)
  {
 -#define TMPBUFLEN 21
 -      unsigned long *i, *min, *max, val;
 -      int vleft, first=1, neg;
 -      size_t len, left;
 -      char buf[TMPBUFLEN], *p;
 -      char __user *s = buffer;
 -      
 -      if (!data || !table->maxlen || !*lenp ||
 -          (*ppos && !write)) {
 +      unsigned long *i, *min, *max;
 +      int vleft, first = 1, err = 0;
 +      unsigned long page = 0;
 +      size_t left;
 +      char *kbuf;
 +
 +      if (!data || !table->maxlen || !*lenp || (*ppos && !write)) {
                *lenp = 0;
                return 0;
        }
 -      
 +
        i = (unsigned long *) data;
        min = (unsigned long *) table->extra1;
        max = (unsigned long *) table->extra2;
        vleft = table->maxlen / sizeof(unsigned long);
        left = *lenp;
 -      
 +
 +      if (write) {
 +              if (left > PAGE_SIZE - 1)
 +                      left = PAGE_SIZE - 1;
 +              page = __get_free_page(GFP_TEMPORARY);
 +              kbuf = (char *) page;
 +              if (!kbuf)
 +                      return -ENOMEM;
 +              if (copy_from_user(kbuf, buffer, left)) {
 +                      err = -EFAULT;
 +                      goto free;
 +              }
 +              kbuf[left] = 0;
 +      }
 +
        for (; left && vleft--; i++, min++, max++, first=0) {
 +              unsigned long val;
 +
                if (write) {
 -                      while (left) {
 -                              char c;
 -                              if (get_user(c, s))
 -                                      return -EFAULT;
 -                              if (!isspace(c))
 -                                      break;
 -                              left--;
 -                              s++;
 -                      }
 -                      if (!left)
 -                              break;
 -                      neg = 0;
 -                      len = left;
 -                      if (len > TMPBUFLEN-1)
 -                              len = TMPBUFLEN-1;
 -                      if (copy_from_user(buf, s, len))
 -                              return -EFAULT;
 -                      buf[len] = 0;
 -                      p = buf;
 -                      if (*p == '-' && left > 1) {
 -                              neg = 1;
 -                              p++;
 -                      }
 -                      if (*p < '0' || *p > '9')
 -                              break;
 -                      val = simple_strtoul(p, &p, 0) * convmul / convdiv ;
 -                      len = p-buf;
 -                      if ((len < left) && *p && !isspace(*p))
 +                      bool neg;
 +
 +                      left -= proc_skip_spaces(&kbuf);
 +
 +                      err = proc_get_long(&kbuf, &left, &val, &neg,
 +                                           proc_wspace_sep,
 +                                           sizeof(proc_wspace_sep), NULL);
 +                      if (err)
                                break;
                        if (neg)
 -                              val = -val;
 -                      s += len;
 -                      left -= len;
 -
 -                      if(neg)
                                continue;
                        if ((min && val < *min) || (max && val > *max))
                                continue;
                        *i = val;
                } else {
 -                      p = buf;
 +                      val = convdiv * (*i) / convmul;
                        if (!first)
 -                              *p++ = '\t';
 -                      sprintf(p, "%lu", convdiv * (*i) / convmul);
 -                      len = strlen(buf);
 -                      if (len > left)
 -                              len = left;
 -                      if(copy_to_user(s, buf, len))
 -                              return -EFAULT;
 -                      left -= len;
 -                      s += len;
 +                              err = proc_put_char(&buffer, &left, '\t');
 +                      err = proc_put_long(&buffer, &left, val, false);
 +                      if (err)
 +                              break;
                }
        }
  
 -      if (!write && !first && left) {
 -              if(put_user('\n', s))
 -                      return -EFAULT;
 -              left--, s++;
 -      }
 +      if (!write && !first && left && !err)
 +              err = proc_put_char(&buffer, &left, '\n');
 +      if (write && !err)
 +              left -= proc_skip_spaces(&kbuf);
 +free:
        if (write) {
 -              while (left) {
 -                      char c;
 -                      if (get_user(c, s++))
 -                              return -EFAULT;
 -                      if (!isspace(c))
 -                              break;
 -                      left--;
 -              }
 +              free_page(page);
 +              if (first)
 +                      return err ? : -EINVAL;
        }
 -      if (write && first)
 -              return -EINVAL;
        *lenp -= left;
        *ppos += *lenp;
 -      return 0;
 -#undef TMPBUFLEN
 +      return err;
  }
  
  static int do_proc_doulongvec_minmax(struct ctl_table *table, int write,
@@@ -2587,7 -2462,7 +2598,7 @@@ int proc_doulongvec_ms_jiffies_minmax(s
  }
  
  
 -static int do_proc_dointvec_jiffies_conv(int *negp, unsigned long *lvalp,
 +static int do_proc_dointvec_jiffies_conv(bool *negp, unsigned long *lvalp,
                                         int *valp,
                                         int write, void *data)
  {
                int val = *valp;
                unsigned long lval;
                if (val < 0) {
 -                      *negp = -1;
 +                      *negp = true;
                        lval = (unsigned long)-val;
                } else {
 -                      *negp = 0;
 +                      *negp = false;
                        lval = (unsigned long)val;
                }
                *lvalp = lval / HZ;
        return 0;
  }
  
 -static int do_proc_dointvec_userhz_jiffies_conv(int *negp, unsigned long *lvalp,
 +static int do_proc_dointvec_userhz_jiffies_conv(bool *negp, unsigned long *lvalp,
                                                int *valp,
                                                int write, void *data)
  {
                int val = *valp;
                unsigned long lval;
                if (val < 0) {
 -                      *negp = -1;
 +                      *negp = true;
                        lval = (unsigned long)-val;
                } else {
 -                      *negp = 0;
 +                      *negp = false;
                        lval = (unsigned long)val;
                }
                *lvalp = jiffies_to_clock_t(lval);
        return 0;
  }
  
 -static int do_proc_dointvec_ms_jiffies_conv(int *negp, unsigned long *lvalp,
 +static int do_proc_dointvec_ms_jiffies_conv(bool *negp, unsigned long *lvalp,
                                            int *valp,
                                            int write, void *data)
  {
                int val = *valp;
                unsigned long lval;
                if (val < 0) {
 -                      *negp = -1;
 +                      *negp = true;
                        lval = (unsigned long)-val;
                } else {
 -                      *negp = 0;
 +                      *negp = false;
                        lval = (unsigned long)val;
                }
                *lvalp = jiffies_to_msecs(lval);
@@@ -2743,157 -2618,6 +2754,157 @@@ static int proc_do_cad_pid(struct ctl_t
        return 0;
  }
  
 +/**
 + * proc_do_large_bitmap - read/write from/to a large bitmap
 + * @table: the sysctl table
 + * @write: %TRUE if this is a write to the sysctl file
 + * @buffer: the user buffer
 + * @lenp: the size of the user buffer
 + * @ppos: file position
 + *
 + * The bitmap is stored at table->data and the bitmap length (in bits)
 + * in table->maxlen.
 + *
 + * We use a range comma separated format (e.g. 1,3-4,10-10) so that
 + * large bitmaps may be represented in a compact manner. Writing into
 + * the file will clear the bitmap then update it with the given input.
 + *
 + * Returns 0 on success.
 + */
 +int proc_do_large_bitmap(struct ctl_table *table, int write,
 +                       void __user *buffer, size_t *lenp, loff_t *ppos)
 +{
 +      int err = 0;
 +      bool first = 1;
 +      size_t left = *lenp;
 +      unsigned long bitmap_len = table->maxlen;
 +      unsigned long *bitmap = (unsigned long *) table->data;
 +      unsigned long *tmp_bitmap = NULL;
 +      char tr_a[] = { '-', ',', '\n' }, tr_b[] = { ',', '\n', 0 }, c;
 +
 +      if (!bitmap_len || !left || (*ppos && !write)) {
 +              *lenp = 0;
 +              return 0;
 +      }
 +
 +      if (write) {
 +              unsigned long page = 0;
 +              char *kbuf;
 +
 +              if (left > PAGE_SIZE - 1)
 +                      left = PAGE_SIZE - 1;
 +
 +              page = __get_free_page(GFP_TEMPORARY);
 +              kbuf = (char *) page;
 +              if (!kbuf)
 +                      return -ENOMEM;
 +              if (copy_from_user(kbuf, buffer, left)) {
 +                      free_page(page);
 +                      return -EFAULT;
 +                }
 +              kbuf[left] = 0;
 +
 +              tmp_bitmap = kzalloc(BITS_TO_LONGS(bitmap_len) * sizeof(unsigned long),
 +                                   GFP_KERNEL);
 +              if (!tmp_bitmap) {
 +                      free_page(page);
 +                      return -ENOMEM;
 +              }
 +              proc_skip_char(&kbuf, &left, '\n');
 +              while (!err && left) {
 +                      unsigned long val_a, val_b;
 +                      bool neg;
 +
 +                      err = proc_get_long(&kbuf, &left, &val_a, &neg, tr_a,
 +                                           sizeof(tr_a), &c);
 +                      if (err)
 +                              break;
 +                      if (val_a >= bitmap_len || neg) {
 +                              err = -EINVAL;
 +                              break;
 +                      }
 +
 +                      val_b = val_a;
 +                      if (left) {
 +                              kbuf++;
 +                              left--;
 +                      }
 +
 +                      if (c == '-') {
 +                              err = proc_get_long(&kbuf, &left, &val_b,
 +                                                   &neg, tr_b, sizeof(tr_b),
 +                                                   &c);
 +                              if (err)
 +                                      break;
 +                              if (val_b >= bitmap_len || neg ||
 +                                  val_a > val_b) {
 +                                      err = -EINVAL;
 +                                      break;
 +                              }
 +                              if (left) {
 +                                      kbuf++;
 +                                      left--;
 +                              }
 +                      }
 +
 +                      while (val_a <= val_b)
 +                              set_bit(val_a++, tmp_bitmap);
 +
 +                      first = 0;
 +                      proc_skip_char(&kbuf, &left, '\n');
 +              }
 +              free_page(page);
 +      } else {
 +              unsigned long bit_a, bit_b = 0;
 +
 +              while (left) {
 +                      bit_a = find_next_bit(bitmap, bitmap_len, bit_b);
 +                      if (bit_a >= bitmap_len)
 +                              break;
 +                      bit_b = find_next_zero_bit(bitmap, bitmap_len,
 +                                                 bit_a + 1) - 1;
 +
 +                      if (!first) {
 +                              err = proc_put_char(&buffer, &left, ',');
 +                              if (err)
 +                                      break;
 +                      }
 +                      err = proc_put_long(&buffer, &left, bit_a, false);
 +                      if (err)
 +                              break;
 +                      if (bit_a != bit_b) {
 +                              err = proc_put_char(&buffer, &left, '-');
 +                              if (err)
 +                                      break;
 +                              err = proc_put_long(&buffer, &left, bit_b, false);
 +                              if (err)
 +                                      break;
 +                      }
 +
 +                      first = 0; bit_b++;
 +              }
 +              if (!err)
 +                      err = proc_put_char(&buffer, &left, '\n');
 +      }
 +
 +      if (!err) {
 +              if (write) {
 +                      if (*ppos)
 +                              bitmap_or(bitmap, bitmap, tmp_bitmap, bitmap_len);
 +                      else
 +                              memcpy(bitmap, tmp_bitmap,
 +                                      BITS_TO_LONGS(bitmap_len) * sizeof(unsigned long));
 +              }
 +              kfree(tmp_bitmap);
 +              *lenp -= left;
 +              *ppos += *lenp;
 +              return 0;
 +      } else {
 +              kfree(tmp_bitmap);
 +              return err;
 +      }
 +}
 +
  #else /* CONFIG_PROC_FS */
  
  int proc_dostring(struct ctl_table *table, int write,
diff --combined kernel/timer.c
index ee305c8d4e18eb038a54f0f9aea8eb2f353b1f44,e8de5eb07a02d8586321a89d05383c7b87ffb3d8..c29e2d4d2a665f921b3c3b5bf1177462962770e3
@@@ -319,24 -319,6 +319,24 @@@ unsigned long round_jiffies_up_relative
  }
  EXPORT_SYMBOL_GPL(round_jiffies_up_relative);
  
 +/**
 + * set_timer_slack - set the allowed slack for a timer
 + * @slack_hz: the amount of time (in jiffies) allowed for rounding
 + *
 + * Set the amount of time, in jiffies, that a certain timer has
 + * in terms of slack. By setting this value, the timer subsystem
 + * will schedule the actual timer somewhere between
 + * the time mod_timer() asks for, and that time plus the slack.
 + *
 + * By setting the slack to -1, a percentage of the delay is used
 + * instead.
 + */
 +void set_timer_slack(struct timer_list *timer, int slack_hz)
 +{
 +      timer->slack = slack_hz;
 +}
 +EXPORT_SYMBOL_GPL(set_timer_slack);
 +
  
  static inline void set_running_timer(struct tvec_base *base,
                                        struct timer_list *timer)
@@@ -568,7 -550,6 +568,7 @@@ static void __init_timer(struct timer_l
  {
        timer->entry.next = NULL;
        timer->base = __raw_get_cpu_var(tvec_bases);
 +      timer->slack = -1;
  #ifdef CONFIG_TIMER_STATS
        timer->start_site = NULL;
        timer->start_pid = -1;
@@@ -734,46 -715,6 +734,46 @@@ int mod_timer_pending(struct timer_lis
  }
  EXPORT_SYMBOL(mod_timer_pending);
  
 +/*
 + * Decide where to put the timer while taking the slack into account
 + *
 + * Algorithm:
 + *   1) calculate the maximum (absolute) time
 + *   2) calculate the highest bit where the expires and new max are different
 + *   3) use this bit to make a mask
 + *   4) use the bitmask to round down the maximum time, so that all last
 + *      bits are zeros
 + */
 +static inline
 +unsigned long apply_slack(struct timer_list *timer, unsigned long expires)
 +{
 +      unsigned long expires_limit, mask;
 +      int bit;
 +
 +      expires_limit = expires;
 +
 +      if (timer->slack >= 0) {
 +              expires_limit = expires + timer->slack;
 +      } else {
 +              unsigned long now = jiffies;
 +
 +              /* No slack, if already expired else auto slack 0.4% */
 +              if (time_after(expires, now))
 +                      expires_limit = expires + (expires - now)/256;
 +      }
 +      mask = expires ^ expires_limit;
 +      if (mask == 0)
 +              return expires;
 +
 +      bit = find_last_bit(&mask, BITS_PER_LONG);
 +
 +      mask = (1 << bit) - 1;
 +
 +      expires_limit = expires_limit & ~(mask);
 +
 +      return expires_limit;
 +}
 +
  /**
   * mod_timer - modify a timer's timeout
   * @timer: the timer to be modified
@@@ -804,8 -745,6 +804,8 @@@ int mod_timer(struct timer_list *timer
        if (timer_pending(timer) && timer->expires == expires)
                return 1;
  
 +      expires = apply_slack(timer, expires);
 +
        return __mod_timer(timer, expires, false, TIMER_NOT_PINNED);
  }
  EXPORT_SYMBOL(mod_timer);
@@@ -1016,47 -955,6 +1016,47 @@@ static int cascade(struct tvec_base *ba
        return index;
  }
  
 +static void call_timer_fn(struct timer_list *timer, void (*fn)(unsigned long),
 +                        unsigned long data)
 +{
 +      int preempt_count = preempt_count();
 +
 +#ifdef CONFIG_LOCKDEP
 +      /*
 +       * It is permissible to free the timer from inside the
 +       * function that is called from it, this we need to take into
 +       * account for lockdep too. To avoid bogus "held lock freed"
 +       * warnings as well as problems when looking into
 +       * timer->lockdep_map, make a copy and use that here.
 +       */
 +      struct lockdep_map lockdep_map = timer->lockdep_map;
 +#endif
 +      /*
 +       * Couple the lock chain with the lock chain at
 +       * del_timer_sync() by acquiring the lock_map around the fn()
 +       * call here and in del_timer_sync().
 +       */
 +      lock_map_acquire(&lockdep_map);
 +
 +      trace_timer_expire_entry(timer);
 +      fn(data);
 +      trace_timer_expire_exit(timer);
 +
 +      lock_map_release(&lockdep_map);
 +
 +      if (preempt_count != preempt_count()) {
 +              WARN_ONCE(1, "timer: %pF preempt leak: %08x -> %08x\n",
 +                        fn, preempt_count, preempt_count());
 +              /*
 +               * Restore the preempt count. That gives us a decent
 +               * chance to survive and extract information. If the
 +               * callback kept a lock held, bad luck, but not worse
 +               * than the BUG() we had.
 +               */
 +              preempt_count() = preempt_count;
 +      }
 +}
 +
  #define INDEX(N) ((base->timer_jiffies >> (TVR_BITS + (N) * TVN_BITS)) & TVN_MASK)
  
  /**
@@@ -1100,7 -998,45 +1100,7 @@@ static inline void __run_timers(struct 
                        detach_timer(timer, 1);
  
                        spin_unlock_irq(&base->lock);
 -                      {
 -                              int preempt_count = preempt_count();
 -
 -#ifdef CONFIG_LOCKDEP
 -                              /*
 -                               * It is permissible to free the timer from
 -                               * inside the function that is called from
 -                               * it, this we need to take into account for
 -                               * lockdep too. To avoid bogus "held lock
 -                               * freed" warnings as well as problems when
 -                               * looking into timer->lockdep_map, make a
 -                               * copy and use that here.
 -                               */
 -                              struct lockdep_map lockdep_map =
 -                                      timer->lockdep_map;
 -#endif
 -                              /*
 -                               * Couple the lock chain with the lock chain at
 -                               * del_timer_sync() by acquiring the lock_map
 -                               * around the fn() call here and in
 -                               * del_timer_sync().
 -                               */
 -                              lock_map_acquire(&lockdep_map);
 -
 -                              trace_timer_expire_entry(timer);
 -                              fn(data);
 -                              trace_timer_expire_exit(timer);
 -
 -                              lock_map_release(&lockdep_map);
 -
 -                              if (preempt_count != preempt_count()) {
 -                                      printk(KERN_ERR "huh, entered %p "
 -                                             "with preempt_count %08x, exited"
 -                                             " with %08x?\n",
 -                                             fn, preempt_count,
 -                                             preempt_count());
 -                                      BUG();
 -                              }
 -                      }
 +                      call_timer_fn(timer, fn, data);
                        spin_lock_irq(&base->lock);
                }
        }
@@@ -1289,7 -1225,6 +1289,6 @@@ void run_local_timers(void
  {
        hrtimer_run_queues();
        raise_softirq(TIMER_SOFTIRQ);
-       softlockup_tick();
  }
  
  /*
@@@ -1684,14 -1619,11 +1683,14 @@@ static int __cpuinit timer_cpu_notify(s
                                unsigned long action, void *hcpu)
  {
        long cpu = (long)hcpu;
 +      int err;
 +
        switch(action) {
        case CPU_UP_PREPARE:
        case CPU_UP_PREPARE_FROZEN:
 -              if (init_timers_cpu(cpu) < 0)
 -                      return NOTIFY_BAD;
 +              err = init_timers_cpu(cpu);
 +              if (err < 0)
 +                      return notifier_from_errno(err);
                break;
  #ifdef CONFIG_HOTPLUG_CPU
        case CPU_DEAD:
@@@ -1717,7 -1649,7 +1716,7 @@@ void __init init_timers(void
  
        init_timer_stats();
  
 -      BUG_ON(err == NOTIFY_BAD);
 +      BUG_ON(err != NOTIFY_OK);
        register_cpu_notifier(&timers_nb);
        open_softirq(TIMER_SOFTIRQ, run_timer_softirq);
  }
diff --combined lib/Kconfig.debug
index e722e9d62221d40560176b5f8d2cabdcf74a5e2d,63968a968443acee62a05c6ded68f5d9a1cc0b83..e2cd7fbf31c05cf6e6bed6a54781e2ad1c99c70b
@@@ -152,28 -152,33 +152,33 @@@ config DEBUG_SHIR
          Drivers ought to be able to handle interrupts coming in at those
          points; some don't and need to be caught.
  
- config DETECT_SOFTLOCKUP
-       bool "Detect Soft Lockups"
+ config LOCKUP_DETECTOR
+       bool "Detect Hard and Soft Lockups"
        depends on DEBUG_KERNEL && !S390
-       default y
        help
-         Say Y here to enable the kernel to detect "soft lockups",
-         which are bugs that cause the kernel to loop in kernel
+         Say Y here to enable the kernel to act as a watchdog to detect
+         hard and soft lockups.
+         Softlockups are bugs that cause the kernel to loop in kernel
          mode for more than 60 seconds, without giving other tasks a
-         chance to run.
+         chance to run.  The current stack trace is displayed upon
+         detection and the system will stay locked up.
+         Hardlockups are bugs that cause the CPU to loop in kernel mode
+         for more than 60 seconds, without letting other interrupts have a
+         chance to run.  The current stack trace is displayed upon detection
+         and the system will stay locked up.
  
-         When a soft-lockup is detected, the kernel will print the
-         current stack trace (which you should report), but the
-         system will stay locked up. This feature has negligible
-         overhead.
+         The overhead should be minimal.  A periodic hrtimer runs to
+         generate interrupts and kick the watchdog task every 10-12 seconds.
+         An NMI is generated every 60 seconds or so to check for hardlockups.
  
-         (Note that "hard lockups" are separate type of bugs that
-          can be detected via the NMI-watchdog, on platforms that
-          support it.)
+ config HARDLOCKUP_DETECTOR
+       def_bool LOCKUP_DETECTOR && PERF_EVENTS && HAVE_PERF_EVENTS_NMI
  
  config BOOTPARAM_SOFTLOCKUP_PANIC
        bool "Panic (Reboot) On Soft Lockups"
-       depends on DETECT_SOFTLOCKUP
+       depends on LOCKUP_DETECTOR
        help
          Say Y here to enable the kernel to panic on "soft lockups",
          which are bugs that cause the kernel to loop in kernel
  
  config BOOTPARAM_SOFTLOCKUP_PANIC_VALUE
        int
-       depends on DETECT_SOFTLOCKUP
+       depends on LOCKUP_DETECTOR
        range 0 1
        default 0 if !BOOTPARAM_SOFTLOCKUP_PANIC
        default 1 if BOOTPARAM_SOFTLOCKUP_PANIC
@@@ -512,18 -517,6 +517,18 @@@ config PROVE_RC
  
         Say N if you are unsure.
  
 +config PROVE_RCU_REPEATEDLY
 +      bool "RCU debugging: don't disable PROVE_RCU on first splat"
 +      depends on PROVE_RCU
 +      default n
 +      help
 +       By itself, PROVE_RCU will disable checking upon issuing the
 +       first warning (or "splat").  This feature prevents such
 +       disabling, allowing multiple RCU-lockdep warnings to be printed
 +       on a single reboot.
 +
 +       Say N if you are unsure.
 +
  config LOCKDEP
        bool
        depends on DEBUG_KERNEL && TRACE_IRQFLAGS_SUPPORT && STACKTRACE_SUPPORT && LOCKDEP_SUPPORT
@@@ -805,7 -798,7 +810,7 @@@ config RCU_CPU_STALL_DETECTO
  config RCU_CPU_STALL_VERBOSE
        bool "Print additional per-task information for RCU_CPU_STALL_DETECTOR"
        depends on RCU_CPU_STALL_DETECTOR && TREE_PREEMPT_RCU
 -      default n
 +      default y
        help
          This option causes RCU to printk detailed per-task information
          for any tasks that are stalling the current RCU grace period.
@@@ -898,18 -891,6 +903,18 @@@ config LKDT
        Documentation on how to use the module can be found in
        Documentation/fault-injection/provoke-crashes.txt
  
 +config CPU_NOTIFIER_ERROR_INJECT
 +      tristate "CPU notifier error injection module"
 +      depends on HOTPLUG_CPU && DEBUG_KERNEL
 +      help
 +        This option provides a kernel module that can be used to test
 +        the error handling of the cpu notifiers
 +
 +        To compile this code as a module, choose M here: the module will
 +        be called cpu-notifier-error-inject.
 +
 +        If unsure, say N.
 +
  config FAULT_INJECTION
        bool "Fault-injection framework"
        depends on DEBUG_KERNEL
@@@ -1051,10 -1032,10 +1056,10 @@@ config DYNAMIC_DEBU
  
          Usage:
  
 -        Dynamic debugging is controlled via the 'dynamic_debug/ddebug' file,
 +        Dynamic debugging is controlled via the 'dynamic_debug/control' file,
          which is contained in the 'debugfs' filesystem. Thus, the debugfs
          filesystem must first be mounted before making use of this feature.
 -        We refer the control file as: <debugfs>/dynamic_debug/ddebug. This
 +        We refer the control file as: <debugfs>/dynamic_debug/control. This
          file contains a list of the debug statements that can be enabled. The
          format for each line of the file is:
  
  
          From a live system:
  
 -              nullarbor:~ # cat <debugfs>/dynamic_debug/ddebug
 +              nullarbor:~ # cat <debugfs>/dynamic_debug/control
                # filename:lineno [module]function flags format
                fs/aio.c:222 [aio]__put_ioctx - "__put_ioctx:\040freeing\040%p\012"
                fs/aio.c:248 [aio]ioctx_alloc - "ENOMEM:\040nr_events\040too\040high\012"
  
                // enable the message at line 1603 of file svcsock.c
                nullarbor:~ # echo -n 'file svcsock.c line 1603 +p' >
 -                                              <debugfs>/dynamic_debug/ddebug
 +                                              <debugfs>/dynamic_debug/control
  
                // enable all the messages in file svcsock.c
                nullarbor:~ # echo -n 'file svcsock.c +p' >
 -                                              <debugfs>/dynamic_debug/ddebug
 +                                              <debugfs>/dynamic_debug/control
  
                // enable all the messages in the NFS server module
                nullarbor:~ # echo -n 'module nfsd +p' >
 -                                              <debugfs>/dynamic_debug/ddebug
 +                                              <debugfs>/dynamic_debug/control
  
                // enable all 12 messages in the function svc_process()
                nullarbor:~ # echo -n 'func svc_process +p' >
 -                                              <debugfs>/dynamic_debug/ddebug
 +                                              <debugfs>/dynamic_debug/control
  
                // disable all 12 messages in the function svc_process()
                nullarbor:~ # echo -n 'func svc_process -p' >
 -                                              <debugfs>/dynamic_debug/ddebug
 +                                              <debugfs>/dynamic_debug/control
  
          See Documentation/dynamic-debug-howto.txt for additional information.
  
@@@ -1110,13 -1091,6 +1115,13 @@@ config DMA_API_DEBU
          This option causes a performance degredation.  Use only if you want
          to debug device drivers. If unsure, say N.
  
 +config ATOMIC64_SELFTEST
 +      bool "Perform an atomic64_t self-test at boot"
 +      help
 +        Enable this option to test the atomic64_t functions at boot.
 +
 +        If unsure, say N.
 +
  source "samples/Kconfig"
  
  source "lib/Kconfig.kgdb"