Merge branch 'x86-mce-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git...
Linus Torvalds [Fri, 18 Sep 2009 04:07:08 +0000 (21:07 -0700)]
* 'x86-mce-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip: (21 commits)
  x86, mce: Fix compilation with !CONFIG_DEBUG_FS in mce-severity.c
  x86, mce: CE in last bank prevents panic by unknown MCE
  x86, mce: Fake panic support for MCE testing
  x86, mce: Move debugfs mce dir creating to mce.c
  x86, mce: Support specifying raise mode for software MCE injection
  x86, mce: Support specifying context for software mce injection
  x86, mce: fix reporting of Thermal Monitoring mechanism enabled
  x86, mce: remove never executed code
  x86, mce: add missing __cpuinit tags
  x86, mce: fix "mce" boot option handling for CONFIG_X86_NEW_MCE
  x86, mce: don't log boot MCEs on Pentium M (model == 13) CPUs
  x86: mce: Lower maximum number of banks to architecture limit
  x86: mce: macros to compute banks MSRs
  x86: mce: Move per bank data in a single datastructure
  x86: mce: Move code in mce.c
  x86: mce: Rename CONFIG_X86_NEW_MCE to CONFIG_X86_MCE
  x86: mce: Remove old i386 machine check code
  x86: mce: Update X86_MCE description in x86/Kconfig
  x86: mce: Make CONFIG_X86_ANCIENT_MCE dependent on CONFIG_X86_MCE
  x86, mce: use atomic_inc_return() instead of add by 1
  ...

Manually fixed up trivial conflicts:
Documentation/feature-removal-schedule.txt
arch/x86/kernel/cpu/mcheck/mce.c

1  2 
Documentation/feature-removal-schedule.txt
arch/x86/Kconfig
arch/x86/include/asm/msr-index.h
arch/x86/kernel/apic/nmi.c
arch/x86/kernel/cpu/mcheck/mce.c
arch/x86/kernel/cpu/mcheck/therm_throt.c
arch/x86/kernel/irqinit.c
arch/x86/kernel/signal.c

@@@ -6,49 -6,6 +6,49 @@@ be removed from this file
  
  ---------------------------
  
 +What: PRISM54
 +When: 2.6.34
 +
 +Why:  prism54 FullMAC PCI / Cardbus devices used to be supported only by the
 +      prism54 wireless driver. After Intersil stopped selling these
 +      devices in preference for the newer more flexible SoftMAC devices
 +      a SoftMAC device driver was required and prism54 did not support
 +      them. The p54pci driver now exists and has been present in the kernel for
 +      a while. This driver supports both SoftMAC devices and FullMAC devices.
 +      The main difference between these devices was the amount of memory which
 +      could be used for the firmware. The SoftMAC devices support a smaller
 +      amount of memory. Because of this the SoftMAC firmware fits into FullMAC
 +      devices's memory. p54pci supports not only PCI / Cardbus but also USB
 +      and SPI. Since p54pci supports all devices prism54 supports
 +      you will have a conflict. I'm not quite sure how distributions are
 +      handling this conflict right now. prism54 was kept around due to
 +      claims users may experience issues when using the SoftMAC driver.
 +      Time has passed users have not reported issues. If you use prism54
 +      and for whatever reason you cannot use p54pci please let us know!
 +      E-mail us at: linux-wireless@vger.kernel.org
 +
 +      For more information see the p54 wiki page:
 +
 +      http://wireless.kernel.org/en/users/Drivers/p54
 +
 +Who:  Luis R. Rodriguez <lrodriguez@atheros.com>
 +
 +---------------------------
 +
 +What: IRQF_SAMPLE_RANDOM
 +Check:        IRQF_SAMPLE_RANDOM
 +When: July 2009
 +
 +Why:  Many of IRQF_SAMPLE_RANDOM users are technically bogus as entropy
 +      sources in the kernel's current entropy model. To resolve this, every
 +      input point to the kernel's entropy pool needs to better document the
 +      type of entropy source it actually is. This will be replaced with
 +      additional add_*_randomness functions in drivers/char/random.c
 +
 +Who:  Robin Getz <rgetz@blackfin.uclinux.org> & Matt Mackall <mpm@selenic.com>
 +
 +---------------------------
 +
  What: The ieee80211_regdom module parameter
  When: March 2010 / desktop catchup
  
@@@ -235,6 -192,24 +235,6 @@@ Who:      Len Brown <len.brown@intel.com
  
  ---------------------------
  
 -What: libata spindown skipping and warning
 -When: Dec 2008
 -Why:  Some halt(8) implementations synchronize caches for and spin
 -      down libata disks because libata didn't use to spin down disk on
 -      system halt (only synchronized caches).
 -      Spin down on system halt is now implemented.  sysfs node
 -      /sys/class/scsi_disk/h:c:i:l/manage_start_stop is present if
 -      spin down support is available.
 -      Because issuing spin down command to an already spun down disk
 -      makes some disks spin up just to spin down again, libata tracks
 -      device spindown status to skip the extra spindown command and
 -      warn about it.
 -      This is to give userspace tools the time to get updated and will
 -      be removed after userspace is reasonably updated.
 -Who:  Tejun Heo <htejun@gmail.com>
 -
 ----------------------------
 -
  What: i386/x86_64 bzImage symlinks
  When: April 2010
  
@@@ -246,6 -221,31 +246,6 @@@ Who:      Thomas Gleixner <tglx@linutronix.d
  ---------------------------
  
  What (Why):
 -      - include/linux/netfilter_ipv4/ipt_TOS.h ipt_tos.h header files
 -        (superseded by xt_TOS/xt_tos target & match)
 -
 -      - "forwarding" header files like ipt_mac.h in
 -        include/linux/netfilter_ipv4/ and include/linux/netfilter_ipv6/
 -
 -      - xt_CONNMARK match revision 0
 -        (superseded by xt_CONNMARK match revision 1)
 -
 -      - xt_MARK target revisions 0 and 1
 -        (superseded by xt_MARK match revision 2)
 -
 -      - xt_connmark match revision 0
 -        (superseded by xt_connmark match revision 1)
 -
 -      - xt_conntrack match revision 0
 -        (superseded by xt_conntrack match revision 1)
 -
 -      - xt_iprange match revision 0,
 -        include/linux/netfilter_ipv4/ipt_iprange.h
 -        (superseded by xt_iprange match revision 1)
 -
 -      - xt_mark match revision 0
 -        (superseded by xt_mark match revision 1)
 -
        - xt_recent: the old ipt_recent proc dir
          (superseded by /proc/net/xt_recent)
  
@@@ -354,6 -354,16 +354,6 @@@ Who:  Krzysztof Piotr Oledzki <ole@ans.
  
  ---------------------------
  
 -What: i2c_attach_client(), i2c_detach_client(), i2c_driver->detach_client(),
 -      i2c_adapter->client_register(), i2c_adapter->client_unregister
 -When: 2.6.30
 -Check:        i2c_attach_client i2c_detach_client
 -Why:  Deprecated by the new (standard) device driver binding model. Use
 -      i2c_driver->probe() and ->remove() instead.
 -Who:  Jean Delvare <khali@linux-fr.org>
 -
 ----------------------------
 -
  What: fscher and fscpos drivers
  When: June 2009
  Why:  Deprecated by the new fschmd driver.
@@@ -380,6 -390,15 +380,6 @@@ Who:      Thomas Gleixner <tglx@linutronix.d
  
  -----------------------------
  
 -What: obsolete generic irq defines and typedefs
 -When: 2.6.30
 -Why:  The defines and typedefs (hw_interrupt_type, no_irq_type, irq_desc_t)
 -      have been kept around for migration reasons. After more than two years
 -      it's time to remove them finally
 -Who:  Thomas Gleixner <tglx@linutronix.de>
 -
 ----------------------------
 -
  What: fakephp and associated sysfs files in /sys/bus/pci/slots/
  When: 2011
  Why:  In 2.6.27, the semantics of /sys/bus/pci/slots was redefined to
@@@ -425,47 -444,3 +425,37 @@@ What:    CONFIG_RFKILL_INPU
  When: 2.6.33
  Why:  Should be implemented in userspace, policy daemon.
  Who:  Johannes Berg <johannes@sipsolutions.net>
 +
 +----------------------------
 +
- What: CONFIG_X86_OLD_MCE
- When: 2.6.32
- Why:  Remove the old legacy 32bit machine check code. This has been
-       superseded by the newer machine check code from the 64bit port,
-       but the old version has been kept around for easier testing. Note this
-       doesn't impact the old P5 and WinChip machine check handlers.
- Who:  Andi Kleen <andi@firstfloor.org>
- ----------------------------
 +What: lock_policy_rwsem_* and unlock_policy_rwsem_* will not be
 +      exported interface anymore.
 +When: 2.6.33
 +Why:  cpu_policy_rwsem has a new cleaner definition making it local to
 +      cpufreq core and contained inside cpufreq.c. Other dependent
 +      drivers should not use it in order to safely avoid lockdep issues.
 +Who:  Venkatesh Pallipadi <venkatesh.pallipadi@intel.com>
 +
 +----------------------------
 +
 +What: sound-slot/service-* module aliases and related clutters in
 +      sound/sound_core.c
 +When: August 2010
 +Why:  OSS sound_core grabs all legacy minors (0-255) of SOUND_MAJOR
 +      (14) and requests modules using custom sound-slot/service-*
 +      module aliases.  The only benefit of doing this is allowing
 +      use of custom module aliases which might as well be considered
 +      a bug at this point.  This preemptive claiming prevents
 +      alternative OSS implementations.
 +
 +      Till the feature is removed, the kernel will be requesting
 +      both sound-slot/service-* and the standard char-major-* module
 +      aliases and allow turning off the pre-claiming selectively via
 +      CONFIG_SOUND_OSS_CORE_PRECLAIM and soundcore.preclaim_oss
 +      kernel parameter.
 +
 +      After the transition phase is complete, both the custom module
 +      aliases and switches to disable it will go away.  This removal
 +      will also allow making ALSA OSS emulation independent of
 +      sound_core.  The dependency will be broken then too.
 +Who:  Tejun Heo <tj@kernel.org>
diff --combined arch/x86/Kconfig
@@@ -24,21 -24,18 +24,21 @@@ config X8
        select HAVE_UNSTABLE_SCHED_CLOCK
        select HAVE_IDE
        select HAVE_OPROFILE
 +      select HAVE_PERF_COUNTERS if (!M386 && !M486)
        select HAVE_IOREMAP_PROT
        select HAVE_KPROBES
        select ARCH_WANT_OPTIONAL_GPIOLIB
        select ARCH_WANT_FRAME_POINTERS
 +      select HAVE_DMA_ATTRS
        select HAVE_KRETPROBES
        select HAVE_FTRACE_MCOUNT_RECORD
        select HAVE_DYNAMIC_FTRACE
        select HAVE_FUNCTION_TRACER
        select HAVE_FUNCTION_GRAPH_TRACER
 +      select HAVE_FUNCTION_GRAPH_FP_TEST
        select HAVE_FUNCTION_TRACE_MCOUNT_TEST
        select HAVE_FTRACE_NMI_ENTER if DYNAMIC_FTRACE
 -      select HAVE_FTRACE_SYSCALLS
 +      select HAVE_SYSCALL_TRACEPOINTS
        select HAVE_KVM
        select HAVE_ARCH_KGDB
        select HAVE_ARCH_TRACEHOOK
@@@ -49,7 -46,6 +49,7 @@@
        select HAVE_KERNEL_GZIP
        select HAVE_KERNEL_BZIP2
        select HAVE_KERNEL_LZMA
 +      select HAVE_ARCH_KMEMCHECK
  
  config OUTPUT_FORMAT
        string
@@@ -150,10 -146,7 +150,10 @@@ config ARCH_HAS_CACHE_LINE_SIZ
  config HAVE_SETUP_PER_CPU_AREA
        def_bool y
  
 -config HAVE_DYNAMIC_PER_CPU_AREA
 +config NEED_PER_CPU_EMBED_FIRST_CHUNK
 +      def_bool y
 +
 +config NEED_PER_CPU_PAGE_FIRST_CHUNK
        def_bool y
  
  config HAVE_CPUMASK_OF_CPU_MAP
@@@ -182,10 -175,6 +182,10 @@@ config ARCH_SUPPORTS_OPTIMIZED_INLININ
  config ARCH_SUPPORTS_DEBUG_PAGEALLOC
        def_bool y
  
 +config HAVE_INTEL_TXT
 +      def_bool y
 +      depends on EXPERIMENTAL && DMAR && ACPI
 +
  # Use the generic interrupt handling code in kernel/irq/:
  config GENERIC_HARDIRQS
        bool
@@@ -593,6 -582,7 +593,6 @@@ config GART_IOMM
        bool "GART IOMMU support" if EMBEDDED
        default y
        select SWIOTLB
 -      select AGP
        depends on X86_64 && PCI
        ---help---
          Support for full DMA access of devices with 32bit memory access only
@@@ -749,6 -739,7 +749,6 @@@ config X86_UP_IOAPI
  config X86_LOCAL_APIC
        def_bool y
        depends on X86_64 || SMP || X86_32_NON_STANDARD || X86_UP_APIC
 -      select HAVE_PERF_COUNTERS if (!M386 && !M486)
  
  config X86_IO_APIC
        def_bool y
@@@ -783,41 -774,17 +783,17 @@@ config X86_REROUTE_FOR_BROKEN_BOOT_IRQ
          increased on these systems.
  
  config X86_MCE
-       bool "Machine Check Exception"
+       bool "Machine Check / overheating reporting"
        ---help---
-         Machine Check Exception support allows the processor to notify the
-         kernel if it detects a problem (e.g. overheating, component failure).
+         Machine Check support allows the processor to notify the
+         kernel if it detects a problem (e.g. overheating, data corruption).
          The action the kernel takes depends on the severity of the problem,
-         ranging from a warning message on the console, to halting the machine.
-         Your processor must be a Pentium or newer to support this - check the
-         flags in /proc/cpuinfo for mce.  Note that some older Pentium systems
-         have a design flaw which leads to false MCE events - hence MCE is
-         disabled on all P5 processors, unless explicitly enabled with "mce"
-         as a boot argument.  Similarly, if MCE is built in and creates a
-         problem on some new non-standard machine, you can boot with "nomce"
-         to disable it.  MCE support simply ignores non-MCE processors like
-         the 386 and 486, so nearly everyone can say Y here.
- config X86_OLD_MCE
-       depends on X86_32 && X86_MCE
-       bool "Use legacy machine check code (will go away)"
-       default n
-       select X86_ANCIENT_MCE
-       ---help---
-         Use the old i386 machine check code. This is merely intended for
-         testing in a transition period. Try this if you run into any machine
-         check related software problems, but report the problem to
-         linux-kernel.  When in doubt say no.
- config X86_NEW_MCE
-       depends on X86_MCE
-       bool
-       default y if (!X86_OLD_MCE && X86_32) || X86_64
+         ranging from warning messages to halting the machine.
  
  config X86_MCE_INTEL
        def_bool y
        prompt "Intel MCE features"
-       depends on X86_NEW_MCE && X86_LOCAL_APIC
+       depends on X86_MCE && X86_LOCAL_APIC
        ---help---
           Additional support for intel specific MCE features such as
           the thermal monitor.
  config X86_MCE_AMD
        def_bool y
        prompt "AMD MCE features"
-       depends on X86_NEW_MCE && X86_LOCAL_APIC
+       depends on X86_MCE && X86_LOCAL_APIC
        ---help---
           Additional support for AMD specific MCE features such as
           the DRAM Error Threshold.
  
  config X86_ANCIENT_MCE
        def_bool n
-       depends on X86_32
+       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
@@@ -845,36 -812,16 +821,16 @@@ config X86_MCE_THRESHOL
        default y
  
  config X86_MCE_INJECT
-       depends on X86_NEW_MCE
+       depends on X86_MCE
        tristate "Machine check injector support"
        ---help---
          Provide support for injecting machine checks for testing purposes.
          If you don't know what a machine check is and you don't do kernel
          QA it is safe to say n.
  
- config X86_MCE_NONFATAL
-       tristate "Check for non-fatal errors on AMD Athlon/Duron / Intel Pentium 4"
-       depends on X86_OLD_MCE
-       ---help---
-         Enabling this feature starts a timer that triggers every 5 seconds which
-         will look at the machine check registers to see if anything happened.
-         Non-fatal problems automatically get corrected (but still logged).
-         Disable this if you don't want to see these messages.
-         Seeing the messages this option prints out may be indicative of dying
-         or out-of-spec (ie, overclocked) hardware.
-         This option only does something on certain CPUs.
-         (AMD Athlon/Duron and Intel Pentium 4)
- config X86_MCE_P4THERMAL
-       bool "check for P4 thermal throttling interrupt."
-       depends on X86_OLD_MCE && X86_MCE && (X86_UP_APIC || SMP)
-       ---help---
-         Enabling this feature will cause a message to be printed when the P4
-         enters thermal throttling.
  config X86_THERMAL_VECTOR
        def_bool y
-       depends on X86_MCE_P4THERMAL || X86_MCE_INTEL
+       depends on X86_MCE_INTEL
  
  config VM86
        bool "Enable VM86 support" if EMBEDDED
@@@ -1420,10 -1367,6 +1376,10 @@@ config X86_PA
  
          If unsure, say Y.
  
 +config ARCH_USES_PG_UNCACHED
 +      def_bool y
 +      depends on X86_PAT
 +
  config EFI
        bool "EFI runtime service support"
        depends on ACPI
@@@ -1923,26 -1866,25 +1879,26 @@@ config DMAR_DEFAULT_O
          recommended you say N here while the DMAR code remains
          experimental.
  
 -config DMAR_GFX_WA
 -      def_bool y
 -      prompt "Support for Graphics workaround"
 +config DMAR_BROKEN_GFX_WA
 +      def_bool n
 +      prompt "Workaround broken graphics drivers (going away soon)"
        depends on DMAR
        ---help---
          Current Graphics drivers tend to use physical address
          for DMA and avoid using DMA APIs. Setting this config
          option permits the IOMMU driver to set a unity map for
          all the OS-visible memory. Hence the driver can continue
 -        to use physical addresses for DMA.
 +        to use physical addresses for DMA, at least until this
 +        option is removed in the 2.6.32 kernel.
  
  config DMAR_FLOPPY_WA
        def_bool y
        depends on DMAR
        ---help---
 -        Floppy disk drivers are know to bypass DMA API calls
 +        Floppy disk drivers are known to bypass DMA API calls
          thereby failing to work when IOMMU is enabled. This
          workaround will setup a 1:1 mapping for the first
 -        16M to make floppy (an ISA device) work.
 +        16MiB to make floppy (an ISA device) work.
  
  config INTR_REMAP
        bool "Support for Interrupt Remapping (EXPERIMENTAL)"
  #define MSR_IA32_MC0_ADDR             0x00000402
  #define MSR_IA32_MC0_MISC             0x00000403
  
+ #define MSR_IA32_MCx_CTL(x)           (MSR_IA32_MC0_CTL + 4*(x))
+ #define MSR_IA32_MCx_STATUS(x)                (MSR_IA32_MC0_STATUS + 4*(x))
+ #define MSR_IA32_MCx_ADDR(x)          (MSR_IA32_MC0_ADDR + 4*(x))
+ #define MSR_IA32_MCx_MISC(x)          (MSR_IA32_MC0_MISC + 4*(x))
  /* These are consecutive and not in the normal 4er MCE bank block */
  #define MSR_IA32_MC0_CTL2             0x00000280
+ #define MSR_IA32_MCx_CTL2(x)          (MSR_IA32_MC0_CTL2 + (x))
  #define CMCI_EN                       (1ULL << 30)
  #define CMCI_THRESHOLD_MASK           0xffffULL
  
  
  #define THERM_STATUS_PROCHOT          (1 << 0)
  
+ #define MSR_THERM2_CTL                        0x0000019d
+ #define MSR_THERM2_CTL_TM_SELECT      (1ULL << 16)
  #define MSR_IA32_MISC_ENABLE          0x000001a0
  
  /* MISC_ENABLE bits: architectural */
  #define MSR_IA32_MISC_ENABLE_TURBO_DISABLE    (1ULL << 38)
  #define MSR_IA32_MISC_ENABLE_IP_PREF_DISABLE  (1ULL << 39)
  
 -/* Intel Model 6 */
 -#define MSR_P6_EVNTSEL0                       0x00000186
 -#define MSR_P6_EVNTSEL1                       0x00000187
 -
  /* P4/Xeon+ specific */
  #define MSR_IA32_MCG_EAX              0x00000180
  #define MSR_IA32_MCG_EBX              0x00000181
  /* AMD-V MSRs */
  
  #define MSR_VM_CR                       0xc0010114
 +#define MSR_VM_IGNNE                    0xc0010115
  #define MSR_VM_HSAVE_PA                 0xc0010117
  
  #endif /* _ASM_X86_MSR_INDEX_H */
@@@ -39,7 -39,7 +39,7 @@@
  int unknown_nmi_panic;
  int nmi_watchdog_enabled;
  
 -static cpumask_var_t backtrace_mask;
 +static cpumask_t backtrace_mask __read_mostly;
  
  /* nmi_active:
   * >0: the lapic NMI watchdog is active, but can be disabled
@@@ -66,7 -66,7 +66,7 @@@ static inline unsigned int get_nmi_coun
  
  static inline int mce_in_progress(void)
  {
- #if defined(CONFIG_X86_NEW_MCE)
+ #if defined(CONFIG_X86_MCE)
        return atomic_read(&mce_entry) > 0;
  #endif
        return 0;
@@@ -138,6 -138,7 +138,6 @@@ int __init check_nmi_watchdog(void
        if (!prev_nmi_count)
                goto error;
  
 -      alloc_cpumask_var(&backtrace_mask, GFP_KERNEL|__GFP_ZERO);
        printk(KERN_INFO "Testing NMI watchdog ... ");
  
  #ifdef CONFIG_SMP
@@@ -414,17 -415,14 +414,17 @@@ nmi_watchdog_tick(struct pt_regs *regs
        }
  
        /* We can be called before check_nmi_watchdog, hence NULL check. */
 -      if (backtrace_mask != NULL && cpumask_test_cpu(cpu, backtrace_mask)) {
 +      if (cpumask_test_cpu(cpu, &backtrace_mask)) {
                static DEFINE_SPINLOCK(lock);   /* Serialise the printks */
  
                spin_lock(&lock);
                printk(KERN_WARNING "NMI backtrace for cpu %d\n", cpu);
 +              show_regs(regs);
                dump_stack();
                spin_unlock(&lock);
 -              cpumask_clear_cpu(cpu, backtrace_mask);
 +              cpumask_clear_cpu(cpu, &backtrace_mask);
 +
 +              rc = 1;
        }
  
        /* Could check oops_in_progress here too, but it's safer not to */
@@@ -554,18 -552,14 +554,18 @@@ int do_nmi_callback(struct pt_regs *reg
        return 0;
  }
  
 -void __trigger_all_cpu_backtrace(void)
 +void arch_trigger_all_cpu_backtrace(void)
  {
        int i;
  
 -      cpumask_copy(backtrace_mask, cpu_online_mask);
 +      cpumask_copy(&backtrace_mask, cpu_online_mask);
 +
 +      printk(KERN_INFO "sending NMI to all CPUs:\n");
 +      apic->send_IPI_all(NMI_VECTOR);
 +
        /* Wait for up to 10 seconds for all CPUs to do the backtrace */
        for (i = 0; i < 10 * 1000; i++) {
 -              if (cpumask_empty(backtrace_mask))
 +              if (cpumask_empty(&backtrace_mask))
                        break;
                mdelay(1);
        }
@@@ -34,6 -34,7 +34,7 @@@
  #include <linux/smp.h>
  #include <linux/fs.h>
  #include <linux/mm.h>
+ #include <linux/debugfs.h>
  
  #include <asm/processor.h>
  #include <asm/hw_irq.h>
  
  #include "mce-internal.h"
  
- /* Handle unconfigured int18 (should never happen) */
- static void unexpected_machine_check(struct pt_regs *regs, long error_code)
- {
-       printk(KERN_ERR "CPU#%d: Unexpected int18 (Machine Check).\n",
-              smp_processor_id());
- }
- /* Call the installed machine check handler for this CPU setup. */
- void (*machine_check_vector)(struct pt_regs *, long error_code) =
-                                               unexpected_machine_check;
  int mce_disabled __read_mostly;
  
- #ifdef CONFIG_X86_NEW_MCE
  #define MISC_MCELOG_MINOR     227
  
  #define SPINUNIT 100  /* 100ns */
@@@ -77,7 -65,6 +65,6 @@@ DEFINE_PER_CPU(unsigned, mce_exception_
   */
  static int                    tolerant                __read_mostly = 1;
  static int                    banks                   __read_mostly;
- static u64                    *bank                   __read_mostly;
  static int                    rip_msr                 __read_mostly;
  static int                    mce_bootlog             __read_mostly = -1;
  static int                    monarch_timeout         __read_mostly = -1;
@@@ -87,13 -74,13 +74,13 @@@ int                                mce_cmci_disabled       __read_mostly
  int                           mce_ignore_ce           __read_mostly;
  int                           mce_ser                 __read_mostly;
  
+ struct mce_bank                *mce_banks             __read_mostly;
  /* User mode helper program triggered by machine check event */
  static unsigned long          mce_need_notify;
  static char                   mce_helper[128];
  static char                   *mce_helper_argv[2] = { mce_helper, NULL };
  
- static unsigned long          dont_init_banks;
  static DECLARE_WAIT_QUEUE_HEAD(mce_wait);
  static DEFINE_PER_CPU(struct mce, mces_seen);
  static int                    cpu_missing;
@@@ -104,11 -91,6 +91,6 @@@ DEFINE_PER_CPU(mce_banks_t, mce_poll_ba
        [0 ... BITS_TO_LONGS(MAX_NR_BANKS)-1] = ~0UL
  };
  
- static inline int skip_bank_init(int i)
- {
-       return i < BITS_PER_LONG && test_bit(i, &dont_init_banks);
- }
  static DEFINE_PER_CPU(struct work_struct, mce_work);
  
  /* Do initial initialization of a struct mce */
@@@ -183,11 -165,6 +165,11 @@@ void mce_log(struct mce *mce
        set_bit(0, &mce_need_notify);
  }
  
 +void __weak decode_mce(struct mce *m)
 +{
 +      return;
 +}
 +
  static void print_mce(struct mce *m)
  {
        printk(KERN_EMERG
                       m->cs, m->ip);
                if (m->cs == __KERNEL_CS)
                        print_symbol("{%s}", m->ip);
 -              printk("\n");
 +              printk(KERN_CONT "\n");
        }
        printk(KERN_EMERG "TSC %llx ", m->tsc);
        if (m->addr)
 -              printk("ADDR %llx ", m->addr);
 +              printk(KERN_CONT "ADDR %llx ", m->addr);
        if (m->misc)
 -              printk("MISC %llx ", m->misc);
 -      printk("\n");
 +              printk(KERN_CONT "MISC %llx ", m->misc);
 +      printk(KERN_CONT "\n");
        printk(KERN_EMERG "PROCESSOR %u:%x TIME %llu SOCKET %u APIC %x\n",
                        m->cpuvendor, m->cpuid, m->time, m->socketid,
                        m->apicid);
 +
 +      decode_mce(m);
  }
  
  static void print_mce_head(void)
  {
 -      printk(KERN_EMERG "\n" KERN_EMERG "HARDWARE ERROR\n");
 +      printk(KERN_EMERG "\nHARDWARE ERROR\n");
  }
  
  static void print_mce_tail(void)
  {
        printk(KERN_EMERG "This is not a software problem!\n"
 -             KERN_EMERG "Run through mcelog --ascii to decode and contact your hardware vendor\n");
 +#if (!defined(CONFIG_EDAC) || !defined(CONFIG_CPU_SUP_AMD))
 +             "Run through mcelog --ascii to decode and contact your hardware vendor\n"
 +#endif
 +             );
  }
  
  #define PANIC_TIMEOUT 5 /* 5 seconds */
  
  static atomic_t mce_paniced;
  
+ static int fake_panic;
+ static atomic_t mce_fake_paniced;
  /* Panic in progress. Enable interrupts and wait for final IPI */
  static void wait_for_panic(void)
  {
@@@ -249,15 -224,21 +234,21 @@@ static void mce_panic(char *msg, struc
  {
        int i;
  
-       /*
-        * Make sure only one CPU runs in machine check panic
-        */
-       if (atomic_add_return(1, &mce_paniced) > 1)
-               wait_for_panic();
-       barrier();
+       if (!fake_panic) {
+               /*
+                * Make sure only one CPU runs in machine check panic
+                */
+               if (atomic_inc_return(&mce_paniced) > 1)
+                       wait_for_panic();
+               barrier();
  
-       bust_spinlocks(1);
-       console_verbose();
+               bust_spinlocks(1);
+               console_verbose();
+       } else {
+               /* Don't log too much for fake panic */
+               if (atomic_inc_return(&mce_fake_paniced) > 1)
+                       return;
+       }
        print_mce_head();
        /* First print corrected ones that are still unlogged */
        for (i = 0; i < MCE_LOG_LEN; i++) {
        print_mce_tail();
        if (exp)
                printk(KERN_EMERG "Machine check: %s\n", exp);
-       if (panic_timeout == 0)
-               panic_timeout = mce_panic_timeout;
-       panic(msg);
+       if (!fake_panic) {
+               if (panic_timeout == 0)
+                       panic_timeout = mce_panic_timeout;
+               panic(msg);
+       } else
+               printk(KERN_EMERG "Fake kernel panic: %s\n", msg);
  }
  
  /* Support code for software error injection */
@@@ -296,11 -280,11 +290,11 @@@ static int msr_to_offset(u32 msr
        unsigned bank = __get_cpu_var(injectm.bank);
        if (msr == rip_msr)
                return offsetof(struct mce, ip);
-       if (msr == MSR_IA32_MC0_STATUS + bank*4)
+       if (msr == MSR_IA32_MCx_STATUS(bank))
                return offsetof(struct mce, status);
-       if (msr == MSR_IA32_MC0_ADDR + bank*4)
+       if (msr == MSR_IA32_MCx_ADDR(bank))
                return offsetof(struct mce, addr);
-       if (msr == MSR_IA32_MC0_MISC + bank*4)
+       if (msr == MSR_IA32_MCx_MISC(bank))
                return offsetof(struct mce, misc);
        if (msr == MSR_IA32_MCG_STATUS)
                return offsetof(struct mce, mcgstatus);
@@@ -505,7 -489,7 +499,7 @@@ void machine_check_poll(enum mcp_flags 
  
        m.mcgstatus = mce_rdmsrl(MSR_IA32_MCG_STATUS);
        for (i = 0; i < banks; i++) {
-               if (!bank[i] || !test_bit(i, *b))
+               if (!mce_banks[i].ctl || !test_bit(i, *b))
                        continue;
  
                m.misc = 0;
                m.tsc = 0;
  
                barrier();
-               m.status = mce_rdmsrl(MSR_IA32_MC0_STATUS + i*4);
+               m.status = mce_rdmsrl(MSR_IA32_MCx_STATUS(i));
                if (!(m.status & MCI_STATUS_VAL))
                        continue;
  
                        continue;
  
                if (m.status & MCI_STATUS_MISCV)
-                       m.misc = mce_rdmsrl(MSR_IA32_MC0_MISC + i*4);
+                       m.misc = mce_rdmsrl(MSR_IA32_MCx_MISC(i));
                if (m.status & MCI_STATUS_ADDRV)
-                       m.addr = mce_rdmsrl(MSR_IA32_MC0_ADDR + i*4);
+                       m.addr = mce_rdmsrl(MSR_IA32_MCx_ADDR(i));
  
                if (!(flags & MCP_TIMESTAMP))
                        m.tsc = 0;
                /*
                 * Clear state for this bank.
                 */
-               mce_wrmsrl(MSR_IA32_MC0_STATUS+4*i, 0);
+               mce_wrmsrl(MSR_IA32_MCx_STATUS(i), 0);
        }
  
        /*
@@@ -568,7 -552,7 +562,7 @@@ static int mce_no_way_out(struct mce *m
        int i;
  
        for (i = 0; i < banks; i++) {
-               m->status = mce_rdmsrl(MSR_IA32_MC0_STATUS + i*4);
+               m->status = mce_rdmsrl(MSR_IA32_MCx_STATUS(i));
                if (mce_severity(m, tolerant, msg) >= MCE_PANIC_SEVERITY)
                        return 1;
        }
@@@ -628,7 -612,7 +622,7 @@@ out
   * This way we prevent any potential data corruption in a unrecoverable case
   * and also makes sure always all CPU's errors are examined.
   *
-  * Also this detects the case of an machine check event coming from outer
+  * Also this detects the case of a machine check event coming from outer
   * space (not detected by any CPUs) In this case some external agent wants
   * us to shut down, so panic too.
   *
@@@ -681,7 -665,7 +675,7 @@@ static void mce_reign(void
         * No machine check event found. Must be some external
         * source or one CPU is hung. Panic.
         */
-       if (!m && tolerant < 3)
+       if (global_worst <= MCE_KEEP_SEVERITY && tolerant < 3)
                mce_panic("Machine check from unknown source", NULL, NULL);
  
        /*
@@@ -715,7 -699,7 +709,7 @@@ static int mce_start(int *no_way_out
         * global_nwo should be updated before mce_callin
         */
        smp_wmb();
-       order = atomic_add_return(1, &mce_callin);
+       order = atomic_inc_return(&mce_callin);
  
        /*
         * Wait for everyone.
@@@ -852,7 -836,7 +846,7 @@@ static void mce_clear_state(unsigned lo
  
        for (i = 0; i < banks; i++) {
                if (test_bit(i, toclear))
-                       mce_wrmsrl(MSR_IA32_MC0_STATUS+4*i, 0);
+                       mce_wrmsrl(MSR_IA32_MCx_STATUS(i), 0);
        }
  }
  
@@@ -905,11 -889,11 +899,11 @@@ void do_machine_check(struct pt_regs *r
        mce_setup(&m);
  
        m.mcgstatus = mce_rdmsrl(MSR_IA32_MCG_STATUS);
        final = &__get_cpu_var(mces_seen);
        *final = m;
  
+       no_way_out = mce_no_way_out(&m, &msg);
        barrier();
  
        /*
        order = mce_start(&no_way_out);
        for (i = 0; i < banks; i++) {
                __clear_bit(i, toclear);
-               if (!bank[i])
+               if (!mce_banks[i].ctl)
                        continue;
  
                m.misc = 0;
                m.addr = 0;
                m.bank = i;
  
-               m.status = mce_rdmsrl(MSR_IA32_MC0_STATUS + i*4);
+               m.status = mce_rdmsrl(MSR_IA32_MCx_STATUS(i));
                if ((m.status & MCI_STATUS_VAL) == 0)
                        continue;
  
                        kill_it = 1;
  
                if (m.status & MCI_STATUS_MISCV)
-                       m.misc = mce_rdmsrl(MSR_IA32_MC0_MISC + i*4);
+                       m.misc = mce_rdmsrl(MSR_IA32_MCx_MISC(i));
                if (m.status & MCI_STATUS_ADDRV)
-                       m.addr = mce_rdmsrl(MSR_IA32_MC0_ADDR + i*4);
+                       m.addr = mce_rdmsrl(MSR_IA32_MCx_ADDR(i));
  
                /*
                 * Action optional error. Queue address for later processing.
@@@ -1101,7 -1085,7 +1095,7 @@@ void mce_log_therm_throt_event(__u64 st
   */
  static int check_interval = 5 * 60; /* 5 minutes */
  
 -static DEFINE_PER_CPU(int, next_interval); /* in jiffies */
 +static DEFINE_PER_CPU(int, mce_next_interval); /* in jiffies */
  static DEFINE_PER_CPU(struct timer_list, mce_timer);
  
  static void mcheck_timer(unsigned long data)
         * Alert userspace if needed.  If we logged an MCE, reduce the
         * polling interval, otherwise increase the polling interval.
         */
 -      n = &__get_cpu_var(next_interval);
 +      n = &__get_cpu_var(mce_next_interval);
        if (mce_notify_irq())
                *n = max(*n/2, HZ/100);
        else
                *n = min(*n*2, (int)round_jiffies_relative(check_interval*HZ));
  
        t->expires = jiffies + *n;
 -      add_timer(t);
 +      add_timer_on(t, smp_processor_id());
  }
  
  static void mce_do_trigger(struct work_struct *work)
@@@ -1169,10 -1153,25 +1163,25 @@@ int mce_notify_irq(void
  }
  EXPORT_SYMBOL_GPL(mce_notify_irq);
  
+ static int mce_banks_init(void)
+ {
+       int i;
+       mce_banks = kzalloc(banks * sizeof(struct mce_bank), GFP_KERNEL);
+       if (!mce_banks)
+               return -ENOMEM;
+       for (i = 0; i < banks; i++) {
+               struct mce_bank *b = &mce_banks[i];
+               b->ctl = -1ULL;
+               b->init = 1;
+       }
+       return 0;
+ }
  /*
   * Initialize Machine Checks for a CPU.
   */
- static int mce_cap_init(void)
+ static int __cpuinit mce_cap_init(void)
  {
        unsigned b;
        u64 cap;
        /* Don't support asymmetric configurations today */
        WARN_ON(banks != 0 && b != banks);
        banks = b;
-       if (!bank) {
-               bank = kmalloc(banks * sizeof(u64), GFP_KERNEL);
-               if (!bank)
-                       return -ENOMEM;
-               memset(bank, 0xff, banks * sizeof(u64));
+       if (!mce_banks) {
+               int err = mce_banks_init();
+               if (err)
+                       return err;
        }
  
        /* Use accurate RIP reporting if available. */
@@@ -1228,21 -1226,17 +1236,22 @@@ static void mce_init(void
                wrmsr(MSR_IA32_MCG_CTL, 0xffffffff, 0xffffffff);
  
        for (i = 0; i < banks; i++) {
-               if (skip_bank_init(i))
+               struct mce_bank *b = &mce_banks[i];
+               if (!b->init)
                        continue;
-               wrmsrl(MSR_IA32_MC0_CTL+4*i, bank[i]);
-               wrmsrl(MSR_IA32_MC0_STATUS+4*i, 0);
+               wrmsrl(MSR_IA32_MCx_CTL(i), b->ctl);
+               wrmsrl(MSR_IA32_MCx_STATUS(i), 0);
        }
  }
  
  /* Add per CPU specific workarounds here */
- static int mce_cpu_quirks(struct cpuinfo_x86 *c)
 -static void __cpuinit mce_cpu_quirks(struct cpuinfo_x86 *c)
++static int __cpuinit mce_cpu_quirks(struct cpuinfo_x86 *c)
  {
 +      if (c->x86_vendor == X86_VENDOR_UNKNOWN) {
 +              pr_info("MCE: unknown CPU type - not enabling MCE support.\n");
 +              return -EOPNOTSUPP;
 +      }
 +
        /* This should be disabled by the BIOS, but isn't always */
        if (c->x86_vendor == X86_VENDOR_AMD) {
                if (c->x86 == 15 && banks > 4) {
                         * trips off incorrectly with the IOMMU & 3ware
                         * & Cerberus:
                         */
-                       clear_bit(10, (unsigned long *)&bank[4]);
+                       clear_bit(10, (unsigned long *)&mce_banks[4].ctl);
                }
                if (c->x86 <= 17 && mce_bootlog < 0) {
                        /*
                 * by default.
                 */
                 if (c->x86 == 6 && banks > 0)
-                       bank[0] = 0;
+                       mce_banks[0].ctl = 0;
        }
  
        if (c->x86_vendor == X86_VENDOR_INTEL) {
                 * valid event later, merely don't write CTL0.
                 */
  
-               if (c->x86 == 6 && c->x86_model < 0x1A)
-                       __set_bit(0, &dont_init_banks);
+               if (c->x86 == 6 && c->x86_model < 0x1A && banks > 0)
+                       mce_banks[0].init = 0;
  
                /*
                 * All newer Intel systems support MCE broadcasting. Enable
                        monarch_timeout < 0)
                        monarch_timeout = USEC_PER_SEC;
  
 -              /* There are also broken BIOSes on some Pentium M systems. */
 -              if (c->x86 == 6 && c->x86_model == 13 && mce_bootlog < 0)
 +              /*
 +               * There are also broken BIOSes on some Pentium M and
 +               * earlier systems:
 +               */
 +              if (c->x86 == 6 && c->x86_model <= 13 && mce_bootlog < 0)
                        mce_bootlog = 0;
        }
        if (monarch_timeout < 0)
                monarch_timeout = 0;
        if (mce_bootlog != 0)
                mce_panic_timeout = 30;
 +
 +      return 0;
  }
  
  static void __cpuinit mce_ancient_init(struct cpuinfo_x86 *c)
@@@ -1335,7 -1324,7 +1344,7 @@@ static void mce_cpu_features(struct cpu
  static void mce_init_timer(void)
  {
        struct timer_list *t = &__get_cpu_var(mce_timer);
 -      int *n = &__get_cpu_var(next_interval);
 +      int *n = &__get_cpu_var(mce_next_interval);
  
        if (mce_ignore_ce)
                return;
                return;
        setup_timer(t, mcheck_timer, smp_processor_id());
        t->expires = round_jiffies(jiffies + *n);
 -      add_timer(t);
 +      add_timer_on(t, smp_processor_id());
  }
  
+ /* Handle unconfigured int18 (should never happen) */
+ static void unexpected_machine_check(struct pt_regs *regs, long error_code)
+ {
+       printk(KERN_ERR "CPU#%d: Unexpected int18 (Machine Check).\n",
+              smp_processor_id());
+ }
+ /* Call the installed machine check handler for this CPU setup. */
+ void (*machine_check_vector)(struct pt_regs *, long error_code) =
+                                               unexpected_machine_check;
  /*
   * Called for each booted CPU to set up machine checks.
   * Must be called with preempt off:
@@@ -1362,10 -1362,11 +1382,10 @@@ void __cpuinit mcheck_init(struct cpuin
        if (!mce_available(c))
                return;
  
 -      if (mce_cap_init() < 0) {
 +      if (mce_cap_init() < 0 || mce_cpu_quirks(c) < 0) {
                mce_disabled = 1;
                return;
        }
 -      mce_cpu_quirks(c);
  
        machine_check_vector = do_machine_check;
  
@@@ -1561,8 -1562,10 +1581,10 @@@ static struct miscdevice mce_log_devic
   */
  static int __init mcheck_enable(char *str)
  {
-       if (*str == 0)
+       if (*str == 0) {
                enable_p5_mce();
+               return 1;
+       }
        if (*str == '=')
                str++;
        if (!strcmp(str, "off"))
@@@ -1603,8 -1606,9 +1625,9 @@@ static int mce_disable(void
        int i;
  
        for (i = 0; i < banks; i++) {
-               if (!skip_bank_init(i))
-                       wrmsrl(MSR_IA32_MC0_CTL + i*4, 0);
+               struct mce_bank *b = &mce_banks[i];
+               if (b->init)
+                       wrmsrl(MSR_IA32_MCx_CTL(i), 0);
        }
        return 0;
  }
@@@ -1679,14 -1683,15 +1702,15 @@@ DEFINE_PER_CPU(struct sys_device, mce_d
  __cpuinitdata
  void (*threshold_cpu_callback)(unsigned long action, unsigned int cpu);
  
- static struct sysdev_attribute *bank_attrs;
+ static inline struct mce_bank *attr_to_bank(struct sysdev_attribute *attr)
+ {
+       return container_of(attr, struct mce_bank, attr);
+ }
  
  static ssize_t show_bank(struct sys_device *s, struct sysdev_attribute *attr,
                         char *buf)
  {
-       u64 b = bank[attr - bank_attrs];
-       return sprintf(buf, "%llx\n", b);
+       return sprintf(buf, "%llx\n", attr_to_bank(attr)->ctl);
  }
  
  static ssize_t set_bank(struct sys_device *s, struct sysdev_attribute *attr,
        if (strict_strtoull(buf, 0, &new) < 0)
                return -EINVAL;
  
-       bank[attr - bank_attrs] = new;
+       attr_to_bank(attr)->ctl = new;
        mce_restart();
  
        return size;
@@@ -1715,15 -1720,17 +1739,15 @@@ static ssize_t set_trigger(struct sys_d
                                const char *buf, size_t siz)
  {
        char *p;
  
        strncpy(mce_helper, buf, sizeof(mce_helper));
        mce_helper[sizeof(mce_helper)-1] = 0;
 -      len = strlen(mce_helper);
        p = strchr(mce_helper, '\n');
  
 -      if (*p)
 +      if (p)
                *p = 0;
  
 -      return len;
 +      return strlen(mce_helper) + !!p;
  }
  
  static ssize_t set_ignore_ce(struct sys_device *s,
@@@ -1839,7 -1846,7 +1863,7 @@@ static __cpuinit int mce_create_device(
        }
        for (j = 0; j < banks; j++) {
                err = sysdev_create_file(&per_cpu(mce_dev, cpu),
-                                       &bank_attrs[j]);
+                                       &mce_banks[j].attr);
                if (err)
                        goto error2;
        }
        return 0;
  error2:
        while (--j >= 0)
-               sysdev_remove_file(&per_cpu(mce_dev, cpu), &bank_attrs[j]);
+               sysdev_remove_file(&per_cpu(mce_dev, cpu), &mce_banks[j].attr);
  error:
        while (--i >= 0)
-               sysdev_remove_file(&per_cpu(mce_dev, cpu), mce_attrs[i]);
+               sysdev_remove_file(&per_cpu(mce_dev, cpu), &mce_banks[i].attr);
  
        sysdev_unregister(&per_cpu(mce_dev, cpu));
  
@@@ -1869,7 -1876,7 +1893,7 @@@ static __cpuinit void mce_remove_device
                sysdev_remove_file(&per_cpu(mce_dev, cpu), mce_attrs[i]);
  
        for (i = 0; i < banks; i++)
-               sysdev_remove_file(&per_cpu(mce_dev, cpu), &bank_attrs[i]);
+               sysdev_remove_file(&per_cpu(mce_dev, cpu), &mce_banks[i].attr);
  
        sysdev_unregister(&per_cpu(mce_dev, cpu));
        cpumask_clear_cpu(cpu, mce_dev_initialized);
@@@ -1886,8 -1893,9 +1910,9 @@@ static void mce_disable_cpu(void *h
        if (!(action & CPU_TASKS_FROZEN))
                cmci_clear();
        for (i = 0; i < banks; i++) {
-               if (!skip_bank_init(i))
-                       wrmsrl(MSR_IA32_MC0_CTL + i*4, 0);
+               struct mce_bank *b = &mce_banks[i];
+               if (b->init)
+                       wrmsrl(MSR_IA32_MCx_CTL(i), 0);
        }
  }
  
@@@ -1902,8 -1910,9 +1927,9 @@@ static void mce_reenable_cpu(void *h
        if (!(action & CPU_TASKS_FROZEN))
                cmci_reenable();
        for (i = 0; i < banks; i++) {
-               if (!skip_bank_init(i))
-                       wrmsrl(MSR_IA32_MC0_CTL + i*4, bank[i]);
+               struct mce_bank *b = &mce_banks[i];
+               if (b->init)
+                       wrmsrl(MSR_IA32_MCx_CTL(i), b->ctl);
        }
  }
  
@@@ -1935,7 -1944,7 +1961,7 @@@ mce_cpu_callback(struct notifier_block 
        case CPU_DOWN_FAILED:
        case CPU_DOWN_FAILED_FROZEN:
                t->expires = round_jiffies(jiffies +
 -                                              __get_cpu_var(next_interval));
 +                                         __get_cpu_var(mce_next_interval));
                add_timer_on(t, cpu);
                smp_call_function_single(cpu, mce_reenable_cpu, &action, 1);
                break;
@@@ -1951,35 -1960,21 +1977,21 @@@ static struct notifier_block mce_cpu_no
        .notifier_call = mce_cpu_callback,
  };
  
- static __init int mce_init_banks(void)
+ static __init void mce_init_banks(void)
  {
        int i;
  
-       bank_attrs = kzalloc(sizeof(struct sysdev_attribute) * banks,
-                               GFP_KERNEL);
-       if (!bank_attrs)
-               return -ENOMEM;
        for (i = 0; i < banks; i++) {
-               struct sysdev_attribute *a = &bank_attrs[i];
+               struct mce_bank *b = &mce_banks[i];
+               struct sysdev_attribute *a = &b->attr;
  
-               a->attr.name    = kasprintf(GFP_KERNEL, "bank%d", i);
-               if (!a->attr.name)
-                       goto nomem;
+               a->attr.name    = b->attrname;
+               snprintf(b->attrname, ATTR_LEN, "bank%d", i);
  
                a->attr.mode    = 0644;
                a->show         = show_bank;
                a->store        = set_bank;
        }
-       return 0;
- nomem:
-       while (--i >= 0)
-               kfree(bank_attrs[i].attr.name);
-       kfree(bank_attrs);
-       bank_attrs = NULL;
-       return -ENOMEM;
  }
  
  static __init int mce_init_device(void)
  
        zalloc_cpumask_var(&mce_dev_initialized, GFP_KERNEL);
  
-       err = mce_init_banks();
-       if (err)
-               return err;
+       mce_init_banks();
  
        err = sysdev_class_register(&mce_sysclass);
        if (err)
  
  device_initcall(mce_init_device);
  
- #else /* CONFIG_X86_OLD_MCE: */
- int nr_mce_banks;
- EXPORT_SYMBOL_GPL(nr_mce_banks);      /* non-fatal.o */
+ /*
+  * Old style boot options parsing. Only for compatibility.
+  */
+ static int __init mcheck_disable(char *str)
+ {
+       mce_disabled = 1;
+       return 1;
+ }
+ __setup("nomce", mcheck_disable);
  
- /* This has to be run for each processor */
- void mcheck_init(struct cpuinfo_x86 *c)
+ #ifdef CONFIG_DEBUG_FS
+ struct dentry *mce_get_debugfs_dir(void)
  {
-       if (mce_disabled)
-               return;
+       static struct dentry *dmce;
  
-       switch (c->x86_vendor) {
-       case X86_VENDOR_AMD:
-               amd_mcheck_init(c);
-               break;
+       if (!dmce)
+               dmce = debugfs_create_dir("mce", NULL);
  
-       case X86_VENDOR_INTEL:
-               if (c->x86 == 5)
-                       intel_p5_mcheck_init(c);
-               if (c->x86 == 6)
-                       intel_p6_mcheck_init(c);
-               if (c->x86 == 15)
-                       intel_p4_mcheck_init(c);
-               break;
+       return dmce;
+ }
  
-       case X86_VENDOR_CENTAUR:
-               if (c->x86 == 5)
-                       winchip_mcheck_init(c);
-               break;
+ static void mce_reset(void)
+ {
+       cpu_missing = 0;
+       atomic_set(&mce_fake_paniced, 0);
+       atomic_set(&mce_executing, 0);
+       atomic_set(&mce_callin, 0);
+       atomic_set(&global_nwo, 0);
+ }
  
-       default:
-               break;
-       }
-       printk(KERN_INFO "mce: CPU supports %d MCE banks\n", nr_mce_banks);
+ static int fake_panic_get(void *data, u64 *val)
+ {
+       *val = fake_panic;
+       return 0;
  }
  
- static int __init mcheck_enable(char *str)
+ static int fake_panic_set(void *data, u64 val)
  {
-       mce_p5_enabled = 1;
-       return 1;
+       mce_reset();
+       fake_panic = val;
+       return 0;
  }
- __setup("mce", mcheck_enable);
  
- #endif /* CONFIG_X86_OLD_MCE */
+ DEFINE_SIMPLE_ATTRIBUTE(fake_panic_fops, fake_panic_get,
+                       fake_panic_set, "%llu\n");
  
- /*
-  * Old style boot options parsing. Only for compatibility.
-  */
- static int __init mcheck_disable(char *str)
+ static int __init mce_debugfs_init(void)
  {
-       mce_disabled = 1;
-       return 1;
+       struct dentry *dmce, *ffake_panic;
+       dmce = mce_get_debugfs_dir();
+       if (!dmce)
+               return -ENOMEM;
+       ffake_panic = debugfs_create_file("fake_panic", 0444, dmce, NULL,
+                                         &fake_panic_fops);
+       if (!ffake_panic)
+               return -ENOMEM;
+       return 0;
  }
- __setup("nomce", mcheck_disable);
+ late_initcall(mce_debugfs_init);
+ #endif
@@@ -36,7 -36,6 +36,7 @@@
  
  static DEFINE_PER_CPU(__u64, next_check) = INITIAL_JIFFIES;
  static DEFINE_PER_CPU(unsigned long, thermal_throttle_count);
 +static DEFINE_PER_CPU(bool, thermal_throttle_active);
  
  static atomic_t therm_throt_en                = ATOMIC_INIT(0);
  
@@@ -97,33 -96,27 +97,33 @@@ static int therm_throt_process(int curr
  {
        unsigned int cpu = smp_processor_id();
        __u64 tmp_jiffs = get_jiffies_64();
 +      bool was_throttled = __get_cpu_var(thermal_throttle_active);
 +      bool is_throttled = __get_cpu_var(thermal_throttle_active) = curr;
  
 -      if (curr)
 +      if (is_throttled)
                __get_cpu_var(thermal_throttle_count)++;
  
 -      if (time_before64(tmp_jiffs, __get_cpu_var(next_check)))
 +      if (!(was_throttled ^ is_throttled) &&
 +          time_before64(tmp_jiffs, __get_cpu_var(next_check)))
                return 0;
  
        __get_cpu_var(next_check) = tmp_jiffs + CHECK_INTERVAL;
  
        /* if we just entered the thermal event */
 -      if (curr) {
 +      if (is_throttled) {
                printk(KERN_CRIT "CPU%d: Temperature above threshold, "
 -                     "cpu clock throttled (total events = %lu)\n", cpu,
 -                     __get_cpu_var(thermal_throttle_count));
 +                     "cpu clock throttled (total events = %lu)\n",
 +                     cpu, __get_cpu_var(thermal_throttle_count));
  
                add_taint(TAINT_MACHINE_CHECK);
 -      } else {
 -              printk(KERN_CRIT "CPU%d: Temperature/speed normal\n", cpu);
 +              return 1;
 +      }
 +      if (was_throttled) {
 +              printk(KERN_INFO "CPU%d: Temperature/speed normal\n", cpu);
 +              return 1;
        }
  
 -      return 1;
 +      return 0;
  }
  
  #ifdef CONFIG_SYSFS
@@@ -260,9 -253,6 +260,6 @@@ void intel_init_thermal(struct cpuinfo_
                return;
        }
  
-       if (cpu_has(c, X86_FEATURE_TM2) && (l & MSR_IA32_MISC_ENABLE_TM2))
-               tm2 = 1;
        /* Check whether a vector already exists */
        if (h & APIC_VECTOR_MASK) {
                printk(KERN_DEBUG
                return;
        }
  
+       /* early Pentium M models use different method for enabling TM2 */
+       if (cpu_has(c, X86_FEATURE_TM2)) {
+               if (c->x86 == 6 && (c->x86_model == 9 || c->x86_model == 13)) {
+                       rdmsr(MSR_THERM2_CTL, l, h);
+                       if (l & MSR_THERM2_CTL_TM_SELECT)
+                               tm2 = 1;
+               } else if (l & MSR_IA32_MISC_ENABLE_TM2)
+                       tm2 = 1;
+       }
        /* We'll mask the thermal vector in the lapic till we're ready: */
        h = THERMAL_APIC_VECTOR | APIC_DM_FIXED | APIC_LVT_MASKED;
        apic_write(APIC_LVTTHMR, h);
@@@ -187,10 -187,10 +187,10 @@@ static void __init apic_intr_init(void
  #ifdef CONFIG_X86_THERMAL_VECTOR
        alloc_intr_gate(THERMAL_APIC_VECTOR, thermal_interrupt);
  #endif
 -#ifdef CONFIG_X86_THRESHOLD
 +#ifdef CONFIG_X86_MCE_THRESHOLD
        alloc_intr_gate(THRESHOLD_APIC_VECTOR, threshold_interrupt);
  #endif
- #if defined(CONFIG_X86_NEW_MCE) && defined(CONFIG_X86_LOCAL_APIC)
+ #if defined(CONFIG_X86_MCE) && defined(CONFIG_X86_LOCAL_APIC)
        alloc_intr_gate(MCE_SELF_VECTOR, mce_self_interrupt);
  #endif
  
diff --combined arch/x86/kernel/signal.c
@@@ -856,7 -856,7 +856,7 @@@ static void do_signal(struct pt_regs *r
  void
  do_notify_resume(struct pt_regs *regs, void *unused, __u32 thread_info_flags)
  {
- #ifdef CONFIG_X86_NEW_MCE
+ #ifdef CONFIG_X86_MCE
        /* notify userspace of pending MCEs */
        if (thread_info_flags & _TIF_MCE_NOTIFY)
                mce_notify_process();
        if (thread_info_flags & _TIF_NOTIFY_RESUME) {
                clear_thread_flag(TIF_NOTIFY_RESUME);
                tracehook_notify_resume(regs);
 +              if (current->replacement_session_keyring)
 +                      key_replace_session_keyring();
        }
  
  #ifdef CONFIG_X86_32