linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 00/16] last-minute patches for MCE .31
@ 2009-06-15  8:09 Hidetoshi Seto
  2009-06-15  8:18 ` [PATCH 01/16] x86, mce: don't init timer if !mce_available Hidetoshi Seto
                   ` (15 more replies)
  0 siblings, 16 replies; 25+ messages in thread
From: Hidetoshi Seto @ 2009-06-15  8:09 UTC (permalink / raw)
  To: linux-kernel; +Cc: Ingo Molnar, H. Peter Anvin, Thomas Gleixner, Andi Kleen

Here are 16 patches for bugfixes and cleanups etc.
These are against tip/x86/mce3, but today I confirmed that these
can be applied on Linus's latest, with no errors.

Please consider applying these for .31

[1] Bugfix
      x86, mce: don't init timer if !mce_available
      x86, mce: call-in should be after updating global_nwo

 These bugs are not serious, but should be fixed asap.

[2] Misc (requested by Ingo)
      x86, mce: add __read_mostly
      x86, mce: rename static variables around trigger
      x86, mce: sysfs entries for new options

 Minor improvements (cleanups), and an enhancement for a feature
 newly introduced in this merge window (i.e. run-time disablement
 of cmci).

[3] Cleanups
      x86, mce: unify mce.h
      x86, mce: make mce_disabled boolean
      x86, mce: unify smp_thermal_interrupt, prepare p4
      x86, mce: unify smp_thermal_interrupt, prepare mce_intel_64
      x86, mce: unify smp_thermal_interrupt, prepare
      x86, mce: unify smp_thermal_interrupt
      x86, mce: squash mce_intel.c into therm_throt.c
      x86, mce: remove intel_set_thermal_handler()
      x86, mce: remove therm_throt.h
      x86, mce: mce.h cleanup
      x86, mce: rename

 There are 3 goals:

 [3-1] unify mce.h
   There are 2 files named mce.h:
        arch/x86/include/asm/mce.h
        arch/x86/kernel/cpu/mcheck/mce.h
   The latter is small, and in it:
        #include <asm/mce.h>
   so we can have a unified one.

 [3-2] finish unifying thermal codes
   Now codes for thermal interrupt is distributed for multiple
   files.  We can gather them in one therm_throt.c file. 

 arch/x86/include/asm/mce.h                |   53 +++++++++------
 arch/x86/include/asm/therm_throt.h        |    9 ---
 arch/x86/kernel/cpu/mcheck/Makefile       |    7 +-
 arch/x86/kernel/cpu/mcheck/mce_intel.c    |   73 --------------------
 arch/x86/kernel/cpu/mcheck/mce_intel_64.c |   21 ------
 arch/x86/kernel/cpu/mcheck/p4.c           |   45 ------------
 arch/x86/kernel/cpu/mcheck/therm_throt.c  |  106 +++++++++++++++++++++++++++-
 7 files changed, 137 insertions(+), 177 deletions(-)
 delete mode 100644 arch/x86/include/asm/therm_throt.h
 delete mode 100644 arch/x86/kernel/cpu/mcheck/mce_intel.c

   This makes Makefile clean & simple:
   before:
     obj-y                            =  mce.o therm_throt.o
     obj-$(CONFIG_X86_MCE_P4THERMAL)  += mce_intel.o
     obj-$(CONFIG_X86_MCE_INTEL)      += mce_intel_64.o mce_intel.o
   after:
     obj-y                            =  mce.o
     obj-$(CONFIG_X86_MCE_INTEL)      += mce_intel_64.o
     obj-$(CONFIG_X86_THERMAL_VECTOR) += therm_throt.o

 [3-3] rename
   Rename files that are no longer 64bit specific:
        mce_amd_64.c    => mce_amd.c
        mce_intel_64.c  => mce_intel.c

Thanks,
H.Seto

===

Hidetoshi Seto (16):
      x86, mce: don't init timer if !mce_available
      x86, mce: call-in should be after updating global_nwo
      x86, mce: add __read_mostly
      x86, mce: rename static variables around trigger
      x86, mce: sysfs entries for new options
      x86, mce: unify mce.h
      x86, mce: make mce_disabled boolean
      x86, mce: unify smp_thermal_interrupt, prepare p4
      x86, mce: unify smp_thermal_interrupt, prepare mce_intel_64
      x86, mce: unify smp_thermal_interrupt, prepare
      x86, mce: unify smp_thermal_interrupt
      x86, mce: squash mce_intel.c into therm_throt.c
      x86, mce: remove intel_set_thermal_handler()
      x86, mce: remove therm_throt.h
      x86, mce: mce.h cleanup
      x86, mce: rename

 arch/x86/include/asm/mce.h                |   63 ++-
 arch/x86/include/asm/therm_throt.h        |    9 -
 arch/x86/kernel/cpu/mcheck/Makefile       |    9 +-
 arch/x86/kernel/cpu/mcheck/k7.c           |    3 +-
 arch/x86/kernel/cpu/mcheck/mce.c          |  216 ++++++---
 arch/x86/kernel/cpu/mcheck/mce.h          |   38 --
 arch/x86/kernel/cpu/mcheck/mce_amd.c      |  703 +++++++++++++++++++++++++++++
 arch/x86/kernel/cpu/mcheck/mce_amd_64.c   |  703 -----------------------------
 arch/x86/kernel/cpu/mcheck/mce_intel.c    |  249 ++++++++--
 arch/x86/kernel/cpu/mcheck/mce_intel_64.c |  248 ----------
 arch/x86/kernel/cpu/mcheck/non-fatal.c    |    3 +-
 arch/x86/kernel/cpu/mcheck/p4.c           |   48 +--
 arch/x86/kernel/cpu/mcheck/p5.c           |   15 +-
 arch/x86/kernel/cpu/mcheck/p6.c           |    3 +-
 arch/x86/kernel/cpu/mcheck/therm_throt.c  |  106 +++++-
 arch/x86/kernel/cpu/mcheck/winchip.c      |    3 +-
 arch/x86/kernel/traps.c                   |    3 +-
 17 files changed, 1220 insertions(+), 1202 deletions(-)
 delete mode 100644 arch/x86/include/asm/therm_throt.h
 delete mode 100644 arch/x86/kernel/cpu/mcheck/mce.h
 create mode 100644 arch/x86/kernel/cpu/mcheck/mce_amd.c
 delete mode 100644 arch/x86/kernel/cpu/mcheck/mce_amd_64.c
 delete mode 100644 arch/x86/kernel/cpu/mcheck/mce_intel_64.c


^ permalink raw reply	[flat|nested] 25+ messages in thread

* [PATCH 01/16] x86, mce: don't init timer if !mce_available
  2009-06-15  8:09 [PATCH 00/16] last-minute patches for MCE .31 Hidetoshi Seto
@ 2009-06-15  8:18 ` Hidetoshi Seto
  2009-06-15  8:19 ` [PATCH 02/16] x86, mce: call-in should be after updating global_nwo Hidetoshi Seto
                   ` (14 subsequent siblings)
  15 siblings, 0 replies; 25+ messages in thread
From: Hidetoshi Seto @ 2009-06-15  8:18 UTC (permalink / raw)
  To: linux-kernel; +Cc: Ingo Molnar, H. Peter Anvin, Thomas Gleixner, Andi Kleen

In mce_cpu_restart, mce_init_timer is called unconditionally.
If !mce_available (e.g. mce is disabled), there are no useful work
for timer.  Stop running it.

Signed-off-by: Hidetoshi Seto <seto.hidetoshi@jp.fujitsu.com>
---
 arch/x86/kernel/cpu/mcheck/mce.c |    5 +++--
 1 files changed, 3 insertions(+), 2 deletions(-)

diff --git a/arch/x86/kernel/cpu/mcheck/mce.c b/arch/x86/kernel/cpu/mcheck/mce.c
index fabba15..6f9db11 100644
--- a/arch/x86/kernel/cpu/mcheck/mce.c
+++ b/arch/x86/kernel/cpu/mcheck/mce.c
@@ -1609,8 +1609,9 @@ static int mce_resume(struct sys_device *dev)
 static void mce_cpu_restart(void *data)
 {
 	del_timer_sync(&__get_cpu_var(mce_timer));
-	if (mce_available(&current_cpu_data))
-		mce_init();
+	if (!mce_available(&current_cpu_data))
+		return;
+	mce_init();
 	mce_init_timer();
 }
 
-- 
1.6.3



^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH 02/16] x86, mce: call-in should be after updating global_nwo
  2009-06-15  8:09 [PATCH 00/16] last-minute patches for MCE .31 Hidetoshi Seto
  2009-06-15  8:18 ` [PATCH 01/16] x86, mce: don't init timer if !mce_available Hidetoshi Seto
@ 2009-06-15  8:19 ` Hidetoshi Seto
  2009-06-15  8:26   ` huang ying
  2009-06-15  8:20 ` [PATCH 03/16] x86, mce: add __read_mostly Hidetoshi Seto
                   ` (13 subsequent siblings)
  15 siblings, 1 reply; 25+ messages in thread
From: Hidetoshi Seto @ 2009-06-15  8:19 UTC (permalink / raw)
  To: linux-kernel; +Cc: Ingo Molnar, H. Peter Anvin, Thomas Gleixner, Andi Kleen

At the beginning of Monarch synchronization, processors wait until
all of them have entered the exception handler and then check the
global_nwo to determine if any of them saw a fatal event.

However since current code does call-in before updating global_nwo,
it might happen that the global_nwo does not reflect some of local
nwo at the time.  This might break printing corrected errors not
handled yet on panic.

Reported-by: Jin Dongming <jin.dongming@np.css.fujitsu.com>
Signed-off-by: Hidetoshi Seto <seto.hidetoshi@jp.fujitsu.com>
---
 arch/x86/kernel/cpu/mcheck/mce.c |   65 ++++++++++++++++++--------------------
 1 files changed, 31 insertions(+), 34 deletions(-)

diff --git a/arch/x86/kernel/cpu/mcheck/mce.c b/arch/x86/kernel/cpu/mcheck/mce.c
index 6f9db11..84b2630 100644
--- a/arch/x86/kernel/cpu/mcheck/mce.c
+++ b/arch/x86/kernel/cpu/mcheck/mce.c
@@ -691,18 +691,18 @@ static atomic_t global_nwo;
  * in the entry order.
  * TBD double check parallel CPU hotunplug
  */
-static int mce_start(int no_way_out, int *order)
+static int mce_start(int *no_way_out)
 {
-	int nwo;
+	int order;
 	int cpus = num_online_cpus();
 	u64 timeout = (u64)monarch_timeout * NSEC_PER_USEC;
 
-	if (!timeout) {
-		*order = -1;
-		return no_way_out;
-	}
+	if (!timeout)
+		return -1;
 
-	atomic_add(no_way_out, &global_nwo);
+	atomic_add(*no_way_out, &global_nwo);
+
+	order = atomic_add_return(1, &mce_callin);
 
 	/*
 	 * Wait for everyone.
@@ -710,40 +710,38 @@ static int mce_start(int no_way_out, int *order)
 	while (atomic_read(&mce_callin) != cpus) {
 		if (mce_timed_out(&timeout)) {
 			atomic_set(&global_nwo, 0);
-			*order = -1;
-			return no_way_out;
+			return -1;
 		}
 		ndelay(SPINUNIT);
 	}
 
-	/*
-	 * Cache the global no_way_out state.
-	 */
-	nwo = atomic_read(&global_nwo);
-
-	/*
-	 * Monarch starts executing now, the others wait.
-	 */
-	if (*order == 1) {
+	if (order == 1) {
+		/*
+		 * Monarch: Starts executing now, the others wait.
+		 */
 		atomic_set(&mce_executing, 1);
-		return nwo;
+	} else {
+		/*
+		 * Subject: Now start the scanning loop one by one in
+		 * the original callin order.
+		 * This way when there are any shared banks it will be
+		 * only seen by one CPU before cleared, avoiding duplicates.
+		 */
+		while (atomic_read(&mce_executing) < order) {
+			if (mce_timed_out(&timeout)) {
+				atomic_set(&global_nwo, 0);
+				return -1;
+			}
+			ndelay(SPINUNIT);
+		}
 	}
 
 	/*
-	 * Now start the scanning loop one by one
-	 * in the original callin order.
-	 * This way when there are any shared banks it will
-	 * be only seen by one CPU before cleared, avoiding duplicates.
+	 * Cache the global no_way_out state.
 	 */
-	while (atomic_read(&mce_executing) < *order) {
-		if (mce_timed_out(&timeout)) {
-			atomic_set(&global_nwo, 0);
-			*order = -1;
-			return no_way_out;
-		}
-		ndelay(SPINUNIT);
-	}
-	return nwo;
+	*no_way_out = atomic_read(&global_nwo);
+
+	return order;
 }
 
 /*
@@ -887,7 +885,6 @@ void do_machine_check(struct pt_regs *regs, long error_code)
 	if (!banks)
 		goto out;
 
-	order = atomic_add_return(1, &mce_callin);
 	mce_setup(&m);
 
 	m.mcgstatus = mce_rdmsrl(MSR_IA32_MCG_STATUS);
@@ -909,7 +906,7 @@ void do_machine_check(struct pt_regs *regs, long error_code)
 	 * This way we don't report duplicated events on shared banks
 	 * because the first one to see it will clear it.
 	 */
-	no_way_out = mce_start(no_way_out, &order);
+	order = mce_start(&no_way_out);
 	for (i = 0; i < banks; i++) {
 		__clear_bit(i, toclear);
 		if (!bank[i])
-- 
1.6.3



^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH 03/16] x86, mce: add __read_mostly
  2009-06-15  8:09 [PATCH 00/16] last-minute patches for MCE .31 Hidetoshi Seto
  2009-06-15  8:18 ` [PATCH 01/16] x86, mce: don't init timer if !mce_available Hidetoshi Seto
  2009-06-15  8:19 ` [PATCH 02/16] x86, mce: call-in should be after updating global_nwo Hidetoshi Seto
@ 2009-06-15  8:20 ` Hidetoshi Seto
  2009-06-15  8:20 ` [PATCH 04/16] x86, mce: rename static variables around trigger Hidetoshi Seto
                   ` (12 subsequent siblings)
  15 siblings, 0 replies; 25+ messages in thread
From: Hidetoshi Seto @ 2009-06-15  8:20 UTC (permalink / raw)
  To: linux-kernel; +Cc: Ingo Molnar, H. Peter Anvin, Thomas Gleixner, Andi Kleen

As recommended by Ingo Molnar.

Signed-off-by: Hidetoshi Seto <seto.hidetoshi@jp.fujitsu.com>
---
 arch/x86/kernel/cpu/mcheck/mce.c |   26 +++++++++++++-------------
 1 files changed, 13 insertions(+), 13 deletions(-)

diff --git a/arch/x86/kernel/cpu/mcheck/mce.c b/arch/x86/kernel/cpu/mcheck/mce.c
index 84b2630..d66f9f1 100644
--- a/arch/x86/kernel/cpu/mcheck/mce.c
+++ b/arch/x86/kernel/cpu/mcheck/mce.c
@@ -57,7 +57,7 @@ static void unexpected_machine_check(struct pt_regs *regs, long error_code)
 void (*machine_check_vector)(struct pt_regs *, long error_code) =
 						unexpected_machine_check;
 
-int				mce_disabled;
+int mce_disabled __read_mostly;
 
 #ifdef CONFIG_X86_NEW_MCE
 
@@ -76,19 +76,19 @@ DEFINE_PER_CPU(unsigned, mce_exception_count);
  *   2: SIGBUS or log uncorrected errors (if possible), log corrected errors
  *   3: never panic or SIGBUS, log all errors (for testing only)
  */
-static int			tolerant = 1;
-static int			banks;
-static u64			*bank;
-static unsigned long		notify_user;
-static int			rip_msr;
-static int			mce_bootlog = -1;
-static int			monarch_timeout = -1;
-static int			mce_panic_timeout;
-static int			mce_dont_log_ce;
-int				mce_cmci_disabled;
-int				mce_ignore_ce;
-int				mce_ser;
+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;
+static int			mce_panic_timeout	__read_mostly;
+static int			mce_dont_log_ce		__read_mostly;
+int				mce_cmci_disabled	__read_mostly;
+int				mce_ignore_ce		__read_mostly;
+int				mce_ser			__read_mostly;
 
+static unsigned long		notify_user;
 static char			trigger[128];
 static char			*trigger_argv[2] = { trigger, NULL };
 
-- 
1.6.3




^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH 04/16] x86, mce: rename static variables around trigger
  2009-06-15  8:09 [PATCH 00/16] last-minute patches for MCE .31 Hidetoshi Seto
                   ` (2 preceding siblings ...)
  2009-06-15  8:20 ` [PATCH 03/16] x86, mce: add __read_mostly Hidetoshi Seto
@ 2009-06-15  8:20 ` Hidetoshi Seto
  2009-06-15  8:21 ` [PATCH 05/16] x86, mce: sysfs entries for new options Hidetoshi Seto
                   ` (11 subsequent siblings)
  15 siblings, 0 replies; 25+ messages in thread
From: Hidetoshi Seto @ 2009-06-15  8:20 UTC (permalink / raw)
  To: linux-kernel; +Cc: Ingo Molnar, H. Peter Anvin, Thomas Gleixner, Andi Kleen

"trigger" is not straight forward name for valiable that holds name
of user mode helper program which triggered by machine check events.

This patch renames this valiable and kins to more recognizable names.

	trigger		=> mce_helper
	trigger_argv	=> mce_helper_argv
	notify_user	=> mce_need_notify

No functional changes.

Signed-off-by: Hidetoshi Seto <seto.hidetoshi@jp.fujitsu.com>
---
 arch/x86/kernel/cpu/mcheck/mce.c |   27 ++++++++++++++-------------
 1 files changed, 14 insertions(+), 13 deletions(-)

diff --git a/arch/x86/kernel/cpu/mcheck/mce.c b/arch/x86/kernel/cpu/mcheck/mce.c
index d66f9f1..e145229 100644
--- a/arch/x86/kernel/cpu/mcheck/mce.c
+++ b/arch/x86/kernel/cpu/mcheck/mce.c
@@ -88,9 +88,10 @@ int				mce_cmci_disabled	__read_mostly;
 int				mce_ignore_ce		__read_mostly;
 int				mce_ser			__read_mostly;
 
-static unsigned long		notify_user;
-static char			trigger[128];
-static char			*trigger_argv[2] = { trigger, NULL };
+/* 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;
 
@@ -180,7 +181,7 @@ void mce_log(struct mce *mce)
 	wmb();
 
 	mce->finished = 1;
-	set_bit(0, &notify_user);
+	set_bit(0, &mce_need_notify);
 }
 
 static void print_mce(struct mce *m)
@@ -1115,7 +1116,7 @@ static void mcheck_timer(unsigned long data)
 
 static void mce_do_trigger(struct work_struct *work)
 {
-	call_usermodehelper(trigger, trigger_argv, NULL, UMH_NO_WAIT);
+	call_usermodehelper(mce_helper, mce_helper_argv, NULL, UMH_NO_WAIT);
 }
 
 static DECLARE_WORK(mce_trigger_work, mce_do_trigger);
@@ -1132,7 +1133,7 @@ int mce_notify_irq(void)
 
 	clear_thread_flag(TIF_MCE_NOTIFY);
 
-	if (test_and_clear_bit(0, &notify_user)) {
+	if (test_and_clear_bit(0, &mce_need_notify)) {
 		wake_up_interruptible(&mce_wait);
 
 		/*
@@ -1140,7 +1141,7 @@ int mce_notify_irq(void)
 		 * work_pending is always cleared before the function is
 		 * executed.
 		 */
-		if (trigger[0] && !work_pending(&mce_trigger_work))
+		if (mce_helper[0] && !work_pending(&mce_trigger_work))
 			schedule_work(&mce_trigger_work);
 
 		if (__ratelimit(&ratelimit))
@@ -1657,9 +1658,9 @@ static ssize_t set_bank(struct sys_device *s, struct sysdev_attribute *attr,
 static ssize_t
 show_trigger(struct sys_device *s, struct sysdev_attribute *attr, char *buf)
 {
-	strcpy(buf, trigger);
+	strcpy(buf, mce_helper);
 	strcat(buf, "\n");
-	return strlen(trigger) + 1;
+	return strlen(mce_helper) + 1;
 }
 
 static ssize_t set_trigger(struct sys_device *s, struct sysdev_attribute *attr,
@@ -1668,10 +1669,10 @@ static ssize_t set_trigger(struct sys_device *s, struct sysdev_attribute *attr,
 	char *p;
 	int len;
 
-	strncpy(trigger, buf, sizeof(trigger));
-	trigger[sizeof(trigger)-1] = 0;
-	len = strlen(trigger);
-	p = strchr(trigger, '\n');
+	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)
 		*p = 0;
-- 
1.6.3



^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH 05/16] x86, mce: sysfs entries for new options
  2009-06-15  8:09 [PATCH 00/16] last-minute patches for MCE .31 Hidetoshi Seto
                   ` (3 preceding siblings ...)
  2009-06-15  8:20 ` [PATCH 04/16] x86, mce: rename static variables around trigger Hidetoshi Seto
@ 2009-06-15  8:21 ` Hidetoshi Seto
  2009-06-15  8:22 ` [PATCH 06/16] x86, mce: unify mce.h Hidetoshi Seto
                   ` (10 subsequent siblings)
  15 siblings, 0 replies; 25+ messages in thread
From: Hidetoshi Seto @ 2009-06-15  8:21 UTC (permalink / raw)
  To: linux-kernel; +Cc: Ingo Molnar, H. Peter Anvin, Thomas Gleixner, Andi Kleen

Add sysfs interface for admins who want to tweak these options without
rebooting the system.

Signed-off-by: Hidetoshi Seto <seto.hidetoshi@jp.fujitsu.com>
---
 arch/x86/kernel/cpu/mcheck/mce.c |   84 +++++++++++++++++++++++++++++++++++++-
 1 files changed, 83 insertions(+), 1 deletions(-)

diff --git a/arch/x86/kernel/cpu/mcheck/mce.c b/arch/x86/kernel/cpu/mcheck/mce.c
index e145229..6b465a6 100644
--- a/arch/x86/kernel/cpu/mcheck/mce.c
+++ b/arch/x86/kernel/cpu/mcheck/mce.c
@@ -1619,6 +1619,26 @@ static void mce_restart(void)
 	on_each_cpu(mce_cpu_restart, NULL, 1);
 }
 
+/* Toggle features for corrected errors */
+static void mce_disable_ce(void *all)
+{
+	if (!mce_available(&current_cpu_data))
+		return;
+	if (all)
+		del_timer_sync(&__get_cpu_var(mce_timer));
+	cmci_clear();
+}
+
+static void mce_enable_ce(void *all)
+{
+	if (!mce_available(&current_cpu_data))
+		return;
+	cmci_reenable();
+	cmci_recheck();
+	if (all)
+		mce_init_timer();
+}
+
 static struct sysdev_class mce_sysclass = {
 	.suspend	= mce_suspend,
 	.shutdown	= mce_shutdown,
@@ -1680,6 +1700,52 @@ static ssize_t set_trigger(struct sys_device *s, struct sysdev_attribute *attr,
 	return len;
 }
 
+static ssize_t set_ignore_ce(struct sys_device *s,
+			     struct sysdev_attribute *attr,
+			     const char *buf, size_t size)
+{
+	u64 new;
+
+	if (strict_strtoull(buf, 0, &new) < 0)
+		return -EINVAL;
+
+	if (mce_ignore_ce ^ !!new) {
+		if (new) {
+			/* disable ce features */
+			on_each_cpu(mce_disable_ce, (void *)1, 1);
+			mce_ignore_ce = 1;
+		} else {
+			/* enable ce features */
+			mce_ignore_ce = 0;
+			on_each_cpu(mce_enable_ce, (void *)1, 1);
+		}
+	}
+	return size;
+}
+
+static ssize_t set_cmci_disabled(struct sys_device *s,
+				 struct sysdev_attribute *attr,
+				 const char *buf, size_t size)
+{
+	u64 new;
+
+	if (strict_strtoull(buf, 0, &new) < 0)
+		return -EINVAL;
+
+	if (mce_cmci_disabled ^ !!new) {
+		if (new) {
+			/* disable cmci */
+			on_each_cpu(mce_disable_ce, NULL, 1);
+			mce_cmci_disabled = 1;
+		} else {
+			/* enable cmci */
+			mce_cmci_disabled = 0;
+			on_each_cpu(mce_enable_ce, NULL, 1);
+		}
+	}
+	return size;
+}
+
 static ssize_t store_int_with_restart(struct sys_device *s,
 				      struct sysdev_attribute *attr,
 				      const char *buf, size_t size)
@@ -1692,6 +1758,7 @@ static ssize_t store_int_with_restart(struct sys_device *s,
 static SYSDEV_ATTR(trigger, 0644, show_trigger, set_trigger);
 static SYSDEV_INT_ATTR(tolerant, 0644, tolerant);
 static SYSDEV_INT_ATTR(monarch_timeout, 0644, monarch_timeout);
+static SYSDEV_INT_ATTR(dont_log_ce, 0644, mce_dont_log_ce);
 
 static struct sysdev_ext_attribute attr_check_interval = {
 	_SYSDEV_ATTR(check_interval, 0644, sysdev_show_int,
@@ -1699,9 +1766,24 @@ static struct sysdev_ext_attribute attr_check_interval = {
 	&check_interval
 };
 
+static struct sysdev_ext_attribute attr_ignore_ce = {
+	_SYSDEV_ATTR(ignore_ce, 0644, sysdev_show_int, set_ignore_ce),
+	&mce_ignore_ce
+};
+
+static struct sysdev_ext_attribute attr_cmci_disabled = {
+	_SYSDEV_ATTR(ignore_ce, 0644, sysdev_show_int, set_cmci_disabled),
+	&mce_cmci_disabled
+};
+
 static struct sysdev_attribute *mce_attrs[] = {
-	&attr_tolerant.attr, &attr_check_interval.attr, &attr_trigger,
+	&attr_tolerant.attr,
+	&attr_check_interval.attr,
+	&attr_trigger,
 	&attr_monarch_timeout.attr,
+	&attr_dont_log_ce.attr,
+	&attr_ignore_ce.attr,
+	&attr_cmci_disabled.attr,
 	NULL
 };
 
-- 
1.6.3



^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH 06/16] x86, mce: unify mce.h
  2009-06-15  8:09 [PATCH 00/16] last-minute patches for MCE .31 Hidetoshi Seto
                   ` (4 preceding siblings ...)
  2009-06-15  8:21 ` [PATCH 05/16] x86, mce: sysfs entries for new options Hidetoshi Seto
@ 2009-06-15  8:22 ` Hidetoshi Seto
  2009-06-15  8:22 ` [PATCH 07/16] x86, mce: make mce_disabled boolean Hidetoshi Seto
                   ` (9 subsequent siblings)
  15 siblings, 0 replies; 25+ messages in thread
From: Hidetoshi Seto @ 2009-06-15  8:22 UTC (permalink / raw)
  To: linux-kernel; +Cc: Ingo Molnar, H. Peter Anvin, Thomas Gleixner, Andi Kleen

There are 2 headers:
	arch/x86/include/asm/mce.h
	arch/x86/kernel/cpu/mcheck/mce.h
and in the latter small header:
	#include <asm/mce.h>

This patch move all contents in the latter header into the former,
and fix all files using the latter to include the former instead.

Signed-off-by: Hidetoshi Seto <seto.hidetoshi@jp.fujitsu.com>
---
 arch/x86/include/asm/mce.h                |   36 +++++++++++++++++++++++++-
 arch/x86/kernel/cpu/mcheck/k7.c           |    3 +-
 arch/x86/kernel/cpu/mcheck/mce.c          |    1 -
 arch/x86/kernel/cpu/mcheck/mce.h          |   38 -----------------------------
 arch/x86/kernel/cpu/mcheck/mce_intel.c    |    3 +-
 arch/x86/kernel/cpu/mcheck/mce_intel_64.c |    2 -
 arch/x86/kernel/cpu/mcheck/non-fatal.c    |    3 +-
 arch/x86/kernel/cpu/mcheck/p4.c           |    3 +-
 arch/x86/kernel/cpu/mcheck/p5.c           |    3 +-
 arch/x86/kernel/cpu/mcheck/p6.c           |    3 +-
 arch/x86/kernel/cpu/mcheck/winchip.c      |    3 +-
 arch/x86/kernel/traps.c                   |    3 +-
 12 files changed, 42 insertions(+), 59 deletions(-)
 delete mode 100644 arch/x86/kernel/cpu/mcheck/mce.h

diff --git a/arch/x86/include/asm/mce.h b/arch/x86/include/asm/mce.h
index 540a466..aae6fe2 100644
--- a/arch/x86/include/asm/mce.h
+++ b/arch/x86/include/asm/mce.h
@@ -102,10 +102,42 @@ struct mce_log {
 
 #ifdef __KERNEL__
 
+#include <linux/percpu.h>
+#include <linux/init.h>
+#include <asm/atomic.h>
+
 extern int mce_disabled;
 
-#include <asm/atomic.h>
-#include <linux/percpu.h>
+#ifdef CONFIG_X86_OLD_MCE
+void amd_mcheck_init(struct cpuinfo_x86 *c);
+void intel_p4_mcheck_init(struct cpuinfo_x86 *c);
+void intel_p6_mcheck_init(struct cpuinfo_x86 *c);
+#endif
+
+#ifdef CONFIG_X86_ANCIENT_MCE
+void intel_p5_mcheck_init(struct cpuinfo_x86 *c);
+void winchip_mcheck_init(struct cpuinfo_x86 *c);
+extern int mce_p5_enable;
+static inline int mce_p5_enabled(void) { return mce_p5_enable; }
+static inline void enable_p5_mce(void) { mce_p5_enable = 1; }
+#else
+static inline void intel_p5_mcheck_init(struct cpuinfo_x86 *c) {}
+static inline void winchip_mcheck_init(struct cpuinfo_x86 *c) {}
+static inline int mce_p5_enabled(void) { return 0; }
+static inline void enable_p5_mce(void) { }
+#endif
+
+/* Call the installed machine check handler for this CPU setup. */
+extern void (*machine_check_vector)(struct pt_regs *, long error_code);
+
+#ifdef CONFIG_X86_OLD_MCE
+extern int nr_mce_banks;
+extern void intel_set_thermal_handler(void);
+#else
+static inline void intel_set_thermal_handler(void) { }
+#endif
+
+void intel_init_thermal(struct cpuinfo_x86 *c);
 
 void mce_setup(struct mce *m);
 void mce_log(struct mce *m);
diff --git a/arch/x86/kernel/cpu/mcheck/k7.c b/arch/x86/kernel/cpu/mcheck/k7.c
index 89e5104..b945d5d 100644
--- a/arch/x86/kernel/cpu/mcheck/k7.c
+++ b/arch/x86/kernel/cpu/mcheck/k7.c
@@ -10,10 +10,9 @@
 
 #include <asm/processor.h>
 #include <asm/system.h>
+#include <asm/mce.h>
 #include <asm/msr.h>
 
-#include "mce.h"
-
 /* Machine Check Handler For AMD Athlon/Duron: */
 static void k7_machine_check(struct pt_regs *regs, long error_code)
 {
diff --git a/arch/x86/kernel/cpu/mcheck/mce.c b/arch/x86/kernel/cpu/mcheck/mce.c
index 6b465a6..c184dc7 100644
--- a/arch/x86/kernel/cpu/mcheck/mce.c
+++ b/arch/x86/kernel/cpu/mcheck/mce.c
@@ -44,7 +44,6 @@
 #include <asm/msr.h>
 
 #include "mce-internal.h"
-#include "mce.h"
 
 /* Handle unconfigured int18 (should never happen) */
 static void unexpected_machine_check(struct pt_regs *regs, long error_code)
diff --git a/arch/x86/kernel/cpu/mcheck/mce.h b/arch/x86/kernel/cpu/mcheck/mce.h
deleted file mode 100644
index 84a552b..0000000
--- a/arch/x86/kernel/cpu/mcheck/mce.h
+++ /dev/null
@@ -1,38 +0,0 @@
-#include <linux/init.h>
-#include <asm/mce.h>
-
-#ifdef CONFIG_X86_OLD_MCE
-void amd_mcheck_init(struct cpuinfo_x86 *c);
-void intel_p4_mcheck_init(struct cpuinfo_x86 *c);
-void intel_p6_mcheck_init(struct cpuinfo_x86 *c);
-#endif
-
-#ifdef CONFIG_X86_ANCIENT_MCE
-void intel_p5_mcheck_init(struct cpuinfo_x86 *c);
-void winchip_mcheck_init(struct cpuinfo_x86 *c);
-extern int mce_p5_enable;
-static inline int mce_p5_enabled(void) { return mce_p5_enable; }
-static inline void enable_p5_mce(void) { mce_p5_enable = 1; }
-#else
-static inline void intel_p5_mcheck_init(struct cpuinfo_x86 *c) {}
-static inline void winchip_mcheck_init(struct cpuinfo_x86 *c) {}
-static inline int mce_p5_enabled(void) { return 0; }
-static inline void enable_p5_mce(void) { }
-#endif
-
-/* Call the installed machine check handler for this CPU setup. */
-extern void (*machine_check_vector)(struct pt_regs *, long error_code);
-
-#ifdef CONFIG_X86_OLD_MCE
-
-extern int nr_mce_banks;
-
-void intel_set_thermal_handler(void);
-
-#else
-
-static inline void intel_set_thermal_handler(void) { }
-
-#endif
-
-void intel_init_thermal(struct cpuinfo_x86 *c);
diff --git a/arch/x86/kernel/cpu/mcheck/mce_intel.c b/arch/x86/kernel/cpu/mcheck/mce_intel.c
index 2b011d2..475478b 100644
--- a/arch/x86/kernel/cpu/mcheck/mce_intel.c
+++ b/arch/x86/kernel/cpu/mcheck/mce_intel.c
@@ -11,10 +11,9 @@
 #include <asm/processor.h>
 #include <asm/system.h>
 #include <asm/apic.h>
+#include <asm/mce.h>
 #include <asm/msr.h>
 
-#include "mce.h"
-
 void intel_init_thermal(struct cpuinfo_x86 *c)
 {
 	unsigned int cpu = smp_processor_id();
diff --git a/arch/x86/kernel/cpu/mcheck/mce_intel_64.c b/arch/x86/kernel/cpu/mcheck/mce_intel_64.c
index f2ef695..c548111 100644
--- a/arch/x86/kernel/cpu/mcheck/mce_intel_64.c
+++ b/arch/x86/kernel/cpu/mcheck/mce_intel_64.c
@@ -16,8 +16,6 @@
 #include <asm/idle.h>
 #include <asm/therm_throt.h>
 
-#include "mce.h"
-
 asmlinkage void smp_thermal_interrupt(void)
 {
 	__u64 msr_val;
diff --git a/arch/x86/kernel/cpu/mcheck/non-fatal.c b/arch/x86/kernel/cpu/mcheck/non-fatal.c
index 70b7104..f5f2d6f 100644
--- a/arch/x86/kernel/cpu/mcheck/non-fatal.c
+++ b/arch/x86/kernel/cpu/mcheck/non-fatal.c
@@ -17,10 +17,9 @@
 
 #include <asm/processor.h>
 #include <asm/system.h>
+#include <asm/mce.h>
 #include <asm/msr.h>
 
-#include "mce.h"
-
 static int		firstbank;
 
 #define MCE_RATE	(15*HZ)	/* timer rate is 15s */
diff --git a/arch/x86/kernel/cpu/mcheck/p4.c b/arch/x86/kernel/cpu/mcheck/p4.c
index 82cee10..8d3e40e 100644
--- a/arch/x86/kernel/cpu/mcheck/p4.c
+++ b/arch/x86/kernel/cpu/mcheck/p4.c
@@ -12,10 +12,9 @@
 #include <asm/processor.h>
 #include <asm/system.h>
 #include <asm/apic.h>
+#include <asm/mce.h>
 #include <asm/msr.h>
 
-#include "mce.h"
-
 /* as supported by the P4/Xeon family */
 struct intel_mce_extended_msrs {
 	u32 eax;
diff --git a/arch/x86/kernel/cpu/mcheck/p5.c b/arch/x86/kernel/cpu/mcheck/p5.c
index 015f481..747853f 100644
--- a/arch/x86/kernel/cpu/mcheck/p5.c
+++ b/arch/x86/kernel/cpu/mcheck/p5.c
@@ -10,10 +10,9 @@
 
 #include <asm/processor.h>
 #include <asm/system.h>
+#include <asm/mce.h>
 #include <asm/msr.h>
 
-#include "mce.h"
-
 /* By default disabled */
 int		mce_p5_enable;
 
diff --git a/arch/x86/kernel/cpu/mcheck/p6.c b/arch/x86/kernel/cpu/mcheck/p6.c
index 43c24e6..01e4f81 100644
--- a/arch/x86/kernel/cpu/mcheck/p6.c
+++ b/arch/x86/kernel/cpu/mcheck/p6.c
@@ -10,10 +10,9 @@
 
 #include <asm/processor.h>
 #include <asm/system.h>
+#include <asm/mce.h>
 #include <asm/msr.h>
 
-#include "mce.h"
-
 /* Machine Check Handler For PII/PIII */
 static void intel_machine_check(struct pt_regs *regs, long error_code)
 {
diff --git a/arch/x86/kernel/cpu/mcheck/winchip.c b/arch/x86/kernel/cpu/mcheck/winchip.c
index 81b0248..54060f5 100644
--- a/arch/x86/kernel/cpu/mcheck/winchip.c
+++ b/arch/x86/kernel/cpu/mcheck/winchip.c
@@ -9,10 +9,9 @@
 
 #include <asm/processor.h>
 #include <asm/system.h>
+#include <asm/mce.h>
 #include <asm/msr.h>
 
-#include "mce.h"
-
 /* Machine check handler for WinChip C6: */
 static void winchip_machine_check(struct pt_regs *regs, long error_code)
 {
diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c
index 1e1e27b..71f9c74 100644
--- a/arch/x86/kernel/traps.c
+++ b/arch/x86/kernel/traps.c
@@ -53,6 +53,7 @@
 #include <asm/traps.h>
 #include <asm/desc.h>
 #include <asm/i387.h>
+#include <asm/mce.h>
 
 #include <asm/mach_traps.h>
 
@@ -64,8 +65,6 @@
 #include <asm/setup.h>
 #include <asm/traps.h>
 
-#include "cpu/mcheck/mce.h"
-
 asmlinkage int system_call(void);
 
 /* Do we ignore FPU interrupts ? */
-- 
1.6.3



^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH 07/16] x86, mce: make mce_disabled boolean
  2009-06-15  8:09 [PATCH 00/16] last-minute patches for MCE .31 Hidetoshi Seto
                   ` (5 preceding siblings ...)
  2009-06-15  8:22 ` [PATCH 06/16] x86, mce: unify mce.h Hidetoshi Seto
@ 2009-06-15  8:22 ` Hidetoshi Seto
  2009-06-15  8:23 ` [PATCH 08/16] x86, mce: unify smp_thermal_interrupt, prepare p4 Hidetoshi Seto
                   ` (8 subsequent siblings)
  15 siblings, 0 replies; 25+ messages in thread
From: Hidetoshi Seto @ 2009-06-15  8:22 UTC (permalink / raw)
  To: linux-kernel; +Cc: Ingo Molnar, H. Peter Anvin, Thomas Gleixner, Andi Kleen

The mce_disabled on 32bit is a tristate variable [1,0,-1],
while 64bit version is boolean [0,1].
This patch makes mce_disabled always boolean, and use mce_p5_enabled
to indicate the third state instead.

Signed-off-by: Hidetoshi Seto <seto.hidetoshi@jp.fujitsu.com>
---
 arch/x86/include/asm/mce.h       |    8 +++-----
 arch/x86/kernel/cpu/mcheck/mce.c |    8 +++-----
 arch/x86/kernel/cpu/mcheck/p5.c  |   12 +++++-------
 3 files changed, 11 insertions(+), 17 deletions(-)

diff --git a/arch/x86/include/asm/mce.h b/arch/x86/include/asm/mce.h
index aae6fe2..6568cde 100644
--- a/arch/x86/include/asm/mce.h
+++ b/arch/x86/include/asm/mce.h
@@ -107,6 +107,7 @@ struct mce_log {
 #include <asm/atomic.h>
 
 extern int mce_disabled;
+extern int mce_p5_enabled;
 
 #ifdef CONFIG_X86_OLD_MCE
 void amd_mcheck_init(struct cpuinfo_x86 *c);
@@ -117,14 +118,11 @@ void intel_p6_mcheck_init(struct cpuinfo_x86 *c);
 #ifdef CONFIG_X86_ANCIENT_MCE
 void intel_p5_mcheck_init(struct cpuinfo_x86 *c);
 void winchip_mcheck_init(struct cpuinfo_x86 *c);
-extern int mce_p5_enable;
-static inline int mce_p5_enabled(void) { return mce_p5_enable; }
-static inline void enable_p5_mce(void) { mce_p5_enable = 1; }
+static inline void enable_p5_mce(void) { mce_p5_enabled = 1; }
 #else
 static inline void intel_p5_mcheck_init(struct cpuinfo_x86 *c) {}
 static inline void winchip_mcheck_init(struct cpuinfo_x86 *c) {}
-static inline int mce_p5_enabled(void) { return 0; }
-static inline void enable_p5_mce(void) { }
+static inline void enable_p5_mce(void) {}
 #endif
 
 /* Call the installed machine check handler for this CPU setup. */
diff --git a/arch/x86/kernel/cpu/mcheck/mce.c b/arch/x86/kernel/cpu/mcheck/mce.c
index c184dc7..e0d5af0 100644
--- a/arch/x86/kernel/cpu/mcheck/mce.c
+++ b/arch/x86/kernel/cpu/mcheck/mce.c
@@ -1279,8 +1279,7 @@ static void __cpuinit mce_ancient_init(struct cpuinfo_x86 *c)
 		return;
 	switch (c->x86_vendor) {
 	case X86_VENDOR_INTEL:
-		if (mce_p5_enabled())
-			intel_p5_mcheck_init(c);
+		intel_p5_mcheck_init(c);
 		break;
 	case X86_VENDOR_CENTAUR:
 		winchip_mcheck_init(c);
@@ -1995,7 +1994,7 @@ EXPORT_SYMBOL_GPL(nr_mce_banks);	/* non-fatal.o */
 /* This has to be run for each processor */
 void mcheck_init(struct cpuinfo_x86 *c)
 {
-	if (mce_disabled == 1)
+	if (mce_disabled)
 		return;
 
 	switch (c->x86_vendor) {
@@ -2025,10 +2024,9 @@ void mcheck_init(struct cpuinfo_x86 *c)
 
 static int __init mcheck_enable(char *str)
 {
-	mce_disabled = -1;
+	mce_p5_enabled = 1;
 	return 1;
 }
-
 __setup("mce", mcheck_enable);
 
 #endif /* CONFIG_X86_OLD_MCE */
diff --git a/arch/x86/kernel/cpu/mcheck/p5.c b/arch/x86/kernel/cpu/mcheck/p5.c
index 747853f..5c0e653 100644
--- a/arch/x86/kernel/cpu/mcheck/p5.c
+++ b/arch/x86/kernel/cpu/mcheck/p5.c
@@ -14,7 +14,7 @@
 #include <asm/msr.h>
 
 /* By default disabled */
-int		mce_p5_enable;
+int mce_p5_enabled __read_mostly;
 
 /* Machine check handler for Pentium class Intel CPUs: */
 static void pentium_machine_check(struct pt_regs *regs, long error_code)
@@ -42,15 +42,13 @@ void intel_p5_mcheck_init(struct cpuinfo_x86 *c)
 {
 	u32 l, h;
 
-	/* Check for MCE support: */
-	if (!cpu_has(c, X86_FEATURE_MCE))
+	/* Default P5 to off as its often misconnected: */
+	if (!mce_p5_enabled)
 		return;
 
-#ifdef CONFIG_X86_OLD_MCE
-	/* Default P5 to off as its often misconnected: */
-	if (mce_disabled != -1)
+	/* Check for MCE support: */
+	if (!cpu_has(c, X86_FEATURE_MCE))
 		return;
-#endif
 
 	machine_check_vector = pentium_machine_check;
 	/* Make sure the vector pointer is visible before we enable MCEs: */
-- 
1.6.3



^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH 08/16] x86, mce: unify smp_thermal_interrupt, prepare p4
  2009-06-15  8:09 [PATCH 00/16] last-minute patches for MCE .31 Hidetoshi Seto
                   ` (6 preceding siblings ...)
  2009-06-15  8:22 ` [PATCH 07/16] x86, mce: make mce_disabled boolean Hidetoshi Seto
@ 2009-06-15  8:23 ` Hidetoshi Seto
  2009-06-15  8:24 ` [PATCH 09/16] x86, mce: unify smp_thermal_interrupt, prepare mce_intel_64 Hidetoshi Seto
                   ` (7 subsequent siblings)
  15 siblings, 0 replies; 25+ messages in thread
From: Hidetoshi Seto @ 2009-06-15  8:23 UTC (permalink / raw)
  To: linux-kernel; +Cc: Ingo Molnar, H. Peter Anvin, Thomas Gleixner, Andi Kleen

Remove unused argument regs from handlers, and use inc_irq_stat.

Signed-off-by: Hidetoshi Seto <seto.hidetoshi@jp.fujitsu.com>
---
 arch/x86/kernel/cpu/mcheck/p4.c |   11 +++++------
 1 files changed, 5 insertions(+), 6 deletions(-)

diff --git a/arch/x86/kernel/cpu/mcheck/p4.c b/arch/x86/kernel/cpu/mcheck/p4.c
index 8d3e40e..ddeed6e 100644
--- a/arch/x86/kernel/cpu/mcheck/p4.c
+++ b/arch/x86/kernel/cpu/mcheck/p4.c
@@ -35,7 +35,7 @@ static int mce_num_extended_msrs;
 
 #ifdef CONFIG_X86_MCE_P4THERMAL
 
-static void unexpected_thermal_interrupt(struct pt_regs *regs)
+static void unexpected_thermal_interrupt(void)
 {
 	printk(KERN_ERR "CPU%d: Unexpected LVT TMR interrupt!\n",
 			smp_processor_id());
@@ -43,7 +43,7 @@ static void unexpected_thermal_interrupt(struct pt_regs *regs)
 }
 
 /* P4/Xeon Thermal transition interrupt handler: */
-static void intel_thermal_interrupt(struct pt_regs *regs)
+static void intel_thermal_interrupt(void)
 {
 	__u64 msr_val;
 
@@ -54,14 +54,13 @@ static void intel_thermal_interrupt(struct pt_regs *regs)
 }
 
 /* Thermal interrupt handler for this CPU setup: */
-static void (*vendor_thermal_interrupt)(struct pt_regs *regs) =
-						unexpected_thermal_interrupt;
+static void (*vendor_thermal_interrupt)(void) = unexpected_thermal_interrupt;
 
 void smp_thermal_interrupt(struct pt_regs *regs)
 {
 	irq_enter();
-	vendor_thermal_interrupt(regs);
-	__get_cpu_var(irq_stat).irq_thermal_count++;
+	vendor_thermal_interrupt();
+	inc_irq_stat(irq_thermal_count);
 	irq_exit();
 }
 
-- 
1.6.3



^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH 09/16] x86, mce: unify smp_thermal_interrupt, prepare mce_intel_64
  2009-06-15  8:09 [PATCH 00/16] last-minute patches for MCE .31 Hidetoshi Seto
                   ` (7 preceding siblings ...)
  2009-06-15  8:23 ` [PATCH 08/16] x86, mce: unify smp_thermal_interrupt, prepare p4 Hidetoshi Seto
@ 2009-06-15  8:24 ` Hidetoshi Seto
  2009-06-15  8:24 ` [PATCH 10/16] x86, mce: unify smp_thermal_interrupt, prepare Hidetoshi Seto
                   ` (6 subsequent siblings)
  15 siblings, 0 replies; 25+ messages in thread
From: Hidetoshi Seto @ 2009-06-15  8:24 UTC (permalink / raw)
  To: linux-kernel; +Cc: Ingo Molnar, H. Peter Anvin, Thomas Gleixner, Andi Kleen

Divide it into two functions.

Signed-off-by: Hidetoshi Seto <seto.hidetoshi@jp.fujitsu.com>
---
 arch/x86/kernel/cpu/mcheck/mce_intel_64.c |   14 ++++++++------
 1 files changed, 8 insertions(+), 6 deletions(-)

diff --git a/arch/x86/kernel/cpu/mcheck/mce_intel_64.c b/arch/x86/kernel/cpu/mcheck/mce_intel_64.c
index c548111..a5232b2 100644
--- a/arch/x86/kernel/cpu/mcheck/mce_intel_64.c
+++ b/arch/x86/kernel/cpu/mcheck/mce_intel_64.c
@@ -16,19 +16,21 @@
 #include <asm/idle.h>
 #include <asm/therm_throt.h>
 
-asmlinkage void smp_thermal_interrupt(void)
+static void intel_thermal_interrupt(void)
 {
 	__u64 msr_val;
 
-	ack_APIC_irq();
-
-	exit_idle();
-	irq_enter();
-
 	rdmsrl(MSR_IA32_THERM_STATUS, msr_val);
 	if (therm_throt_process(msr_val & THERM_STATUS_PROCHOT))
 		mce_log_therm_throt_event(msr_val);
+}
 
+asmlinkage void smp_thermal_interrupt(void)
+{
+	ack_APIC_irq();
+	exit_idle();
+	irq_enter();
+	intel_thermal_interrupt();
 	inc_irq_stat(irq_thermal_count);
 	irq_exit();
 }
-- 
1.6.3



^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH 10/16] x86, mce: unify smp_thermal_interrupt, prepare
  2009-06-15  8:09 [PATCH 00/16] last-minute patches for MCE .31 Hidetoshi Seto
                   ` (8 preceding siblings ...)
  2009-06-15  8:24 ` [PATCH 09/16] x86, mce: unify smp_thermal_interrupt, prepare mce_intel_64 Hidetoshi Seto
@ 2009-06-15  8:24 ` Hidetoshi Seto
  2009-06-15  8:25 ` [PATCH 11/16] x86, mce: unify smp_thermal_interrupt Hidetoshi Seto
                   ` (5 subsequent siblings)
  15 siblings, 0 replies; 25+ messages in thread
From: Hidetoshi Seto @ 2009-06-15  8:24 UTC (permalink / raw)
  To: linux-kernel; +Cc: Ingo Molnar, H. Peter Anvin, Thomas Gleixner, Andi Kleen

Let them in same shape.

Signed-off-by: Hidetoshi Seto <seto.hidetoshi@jp.fujitsu.com>
---
 arch/x86/include/asm/mce.h                |   25 ++++++++++++++-----------
 arch/x86/kernel/cpu/mcheck/mce_intel_64.c |   20 ++++++++++++++++++--
 arch/x86/kernel/cpu/mcheck/p4.c           |   10 ++++++----
 3 files changed, 38 insertions(+), 17 deletions(-)

diff --git a/arch/x86/include/asm/mce.h b/arch/x86/include/asm/mce.h
index 6568cde..3bc827c 100644
--- a/arch/x86/include/asm/mce.h
+++ b/arch/x86/include/asm/mce.h
@@ -110,6 +110,7 @@ extern int mce_disabled;
 extern int mce_p5_enabled;
 
 #ifdef CONFIG_X86_OLD_MCE
+extern int nr_mce_banks;
 void amd_mcheck_init(struct cpuinfo_x86 *c);
 void intel_p4_mcheck_init(struct cpuinfo_x86 *c);
 void intel_p6_mcheck_init(struct cpuinfo_x86 *c);
@@ -128,15 +129,6 @@ static inline void enable_p5_mce(void) {}
 /* Call the installed machine check handler for this CPU setup. */
 extern void (*machine_check_vector)(struct pt_regs *, long error_code);
 
-#ifdef CONFIG_X86_OLD_MCE
-extern int nr_mce_banks;
-extern void intel_set_thermal_handler(void);
-#else
-static inline void intel_set_thermal_handler(void) { }
-#endif
-
-void intel_init_thermal(struct cpuinfo_x86 *c);
-
 void mce_setup(struct mce *m);
 void mce_log(struct mce *m);
 DECLARE_PER_CPU(struct sys_device, mce_dev);
@@ -175,8 +167,6 @@ int mce_available(struct cpuinfo_x86 *c);
 DECLARE_PER_CPU(unsigned, mce_exception_count);
 DECLARE_PER_CPU(unsigned, mce_poll_count);
 
-void mce_log_therm_throt_event(__u64 status);
-
 extern atomic_t mce_entry;
 
 void do_machine_check(struct pt_regs *, long);
@@ -205,5 +195,18 @@ void mcheck_init(struct cpuinfo_x86 *c);
 
 extern void (*mce_threshold_vector)(void);
 
+/*
+ * Thermal handler
+ */
+
+void intel_set_thermal_handler(void);
+void intel_init_thermal(struct cpuinfo_x86 *c);
+
+#ifdef CONFIG_X86_NEW_MCE
+void mce_log_therm_throt_event(__u64 status);
+#else
+static inline void mce_log_therm_throt_event(__u64 status) {}
+#endif
+
 #endif /* __KERNEL__ */
 #endif /* _ASM_X86_MCE_H */
diff --git a/arch/x86/kernel/cpu/mcheck/mce_intel_64.c b/arch/x86/kernel/cpu/mcheck/mce_intel_64.c
index a5232b2..922e3a4 100644
--- a/arch/x86/kernel/cpu/mcheck/mce_intel_64.c
+++ b/arch/x86/kernel/cpu/mcheck/mce_intel_64.c
@@ -16,6 +16,14 @@
 #include <asm/idle.h>
 #include <asm/therm_throt.h>
 
+static void unexpected_thermal_interrupt(void)
+{
+	printk(KERN_ERR "CPU%d: Unexpected LVT TMR interrupt!\n",
+			smp_processor_id());
+	add_taint(TAINT_MACHINE_CHECK);
+}
+
+/* P4/Xeon Thermal transition interrupt handler: */
 static void intel_thermal_interrupt(void)
 {
 	__u64 msr_val;
@@ -25,14 +33,22 @@ static void intel_thermal_interrupt(void)
 		mce_log_therm_throt_event(msr_val);
 }
 
+/* Thermal interrupt handler for this CPU setup: */
+static void (*vendor_thermal_interrupt)(void) = unexpected_thermal_interrupt;
+
 asmlinkage void smp_thermal_interrupt(void)
 {
-	ack_APIC_irq();
 	exit_idle();
 	irq_enter();
-	intel_thermal_interrupt();
 	inc_irq_stat(irq_thermal_count);
+	intel_thermal_interrupt();
 	irq_exit();
+	ack_APIC_irq();
+}
+
+void intel_set_thermal_handler(void)
+{
+	vendor_thermal_interrupt = intel_thermal_interrupt;
 }
 
 /*
diff --git a/arch/x86/kernel/cpu/mcheck/p4.c b/arch/x86/kernel/cpu/mcheck/p4.c
index ddeed6e..75313f5 100644
--- a/arch/x86/kernel/cpu/mcheck/p4.c
+++ b/arch/x86/kernel/cpu/mcheck/p4.c
@@ -12,6 +12,7 @@
 #include <asm/processor.h>
 #include <asm/system.h>
 #include <asm/apic.h>
+#include <asm/idle.h>
 #include <asm/mce.h>
 #include <asm/msr.h>
 
@@ -47,10 +48,9 @@ static void intel_thermal_interrupt(void)
 {
 	__u64 msr_val;
 
-	ack_APIC_irq();
-
 	rdmsrl(MSR_IA32_THERM_STATUS, msr_val);
-	therm_throt_process(msr_val & THERM_STATUS_PROCHOT);
+	if (therm_throt_process(msr_val & THERM_STATUS_PROCHOT))
+		mce_log_therm_throt_event(msr_val);
 }
 
 /* Thermal interrupt handler for this CPU setup: */
@@ -58,10 +58,12 @@ static void (*vendor_thermal_interrupt)(void) = unexpected_thermal_interrupt;
 
 void smp_thermal_interrupt(struct pt_regs *regs)
 {
+	exit_idle();
 	irq_enter();
-	vendor_thermal_interrupt();
 	inc_irq_stat(irq_thermal_count);
+	vendor_thermal_interrupt();
 	irq_exit();
+	ack_APIC_irq();
 }
 
 void intel_set_thermal_handler(void)
-- 
1.6.3



^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH 11/16] x86, mce: unify smp_thermal_interrupt
  2009-06-15  8:09 [PATCH 00/16] last-minute patches for MCE .31 Hidetoshi Seto
                   ` (9 preceding siblings ...)
  2009-06-15  8:24 ` [PATCH 10/16] x86, mce: unify smp_thermal_interrupt, prepare Hidetoshi Seto
@ 2009-06-15  8:25 ` Hidetoshi Seto
  2009-06-15  8:26 ` [PATCH 12/16] x86, mce: squash mce_intel.c into therm_throt.c Hidetoshi Seto
                   ` (4 subsequent siblings)
  15 siblings, 0 replies; 25+ messages in thread
From: Hidetoshi Seto @ 2009-06-15  8:25 UTC (permalink / raw)
  To: linux-kernel; +Cc: Ingo Molnar, H. Peter Anvin, Thomas Gleixner, Andi Kleen

Put common functions into therm_throt.c, modify Makefile.

	unexpected_thermal_interrupt
	intel_thermal_interrupt
	smp_thermal_interrupt
	intel_set_thermal_handler

Signed-off-by: Hidetoshi Seto <seto.hidetoshi@jp.fujitsu.com>
---
 arch/x86/kernel/cpu/mcheck/Makefile       |    7 ++--
 arch/x86/kernel/cpu/mcheck/mce_intel_64.c |   38 ------------------------
 arch/x86/kernel/cpu/mcheck/p4.c           |   45 -----------------------------
 arch/x86/kernel/cpu/mcheck/therm_throt.c  |   40 +++++++++++++++++++++++++-
 4 files changed, 43 insertions(+), 87 deletions(-)

diff --git a/arch/x86/kernel/cpu/mcheck/Makefile b/arch/x86/kernel/cpu/mcheck/Makefile
index 45004fa..53df57d 100644
--- a/arch/x86/kernel/cpu/mcheck/Makefile
+++ b/arch/x86/kernel/cpu/mcheck/Makefile
@@ -1,11 +1,12 @@
-obj-y				=  mce.o therm_throt.o
+obj-y				=  mce.o
 
 obj-$(CONFIG_X86_NEW_MCE)	+= mce-severity.o
 obj-$(CONFIG_X86_OLD_MCE)	+= k7.o p4.o p6.o
 obj-$(CONFIG_X86_ANCIENT_MCE)	+= winchip.o p5.o
-obj-$(CONFIG_X86_MCE_P4THERMAL)	+= mce_intel.o
-obj-$(CONFIG_X86_MCE_INTEL)	+= mce_intel_64.o mce_intel.o
+obj-$(CONFIG_X86_MCE_INTEL)	+= mce_intel_64.o
 obj-$(CONFIG_X86_MCE_AMD)	+= mce_amd_64.o
 obj-$(CONFIG_X86_MCE_NONFATAL)	+= non-fatal.o
 obj-$(CONFIG_X86_MCE_THRESHOLD) += threshold.o
 obj-$(CONFIG_X86_MCE_INJECT)	+= mce-inject.o
+
+obj-$(CONFIG_X86_THERMAL_VECTOR) += therm_throt.o mce_intel.o
diff --git a/arch/x86/kernel/cpu/mcheck/mce_intel_64.c b/arch/x86/kernel/cpu/mcheck/mce_intel_64.c
index 922e3a4..3b7a057 100644
--- a/arch/x86/kernel/cpu/mcheck/mce_intel_64.c
+++ b/arch/x86/kernel/cpu/mcheck/mce_intel_64.c
@@ -9,48 +9,10 @@
 #include <linux/interrupt.h>
 #include <linux/percpu.h>
 #include <asm/processor.h>
-#include <asm/apic.h>
 #include <asm/msr.h>
 #include <asm/mce.h>
-#include <asm/hw_irq.h>
-#include <asm/idle.h>
 #include <asm/therm_throt.h>
 
-static void unexpected_thermal_interrupt(void)
-{
-	printk(KERN_ERR "CPU%d: Unexpected LVT TMR interrupt!\n",
-			smp_processor_id());
-	add_taint(TAINT_MACHINE_CHECK);
-}
-
-/* P4/Xeon Thermal transition interrupt handler: */
-static void intel_thermal_interrupt(void)
-{
-	__u64 msr_val;
-
-	rdmsrl(MSR_IA32_THERM_STATUS, msr_val);
-	if (therm_throt_process(msr_val & THERM_STATUS_PROCHOT))
-		mce_log_therm_throt_event(msr_val);
-}
-
-/* Thermal interrupt handler for this CPU setup: */
-static void (*vendor_thermal_interrupt)(void) = unexpected_thermal_interrupt;
-
-asmlinkage void smp_thermal_interrupt(void)
-{
-	exit_idle();
-	irq_enter();
-	inc_irq_stat(irq_thermal_count);
-	intel_thermal_interrupt();
-	irq_exit();
-	ack_APIC_irq();
-}
-
-void intel_set_thermal_handler(void)
-{
-	vendor_thermal_interrupt = intel_thermal_interrupt;
-}
-
 /*
  * Support for Intel Correct Machine Check Interrupts. This allows
  * the CPU to raise an interrupt when a corrected machine check happened.
diff --git a/arch/x86/kernel/cpu/mcheck/p4.c b/arch/x86/kernel/cpu/mcheck/p4.c
index 75313f5..76c5f03 100644
--- a/arch/x86/kernel/cpu/mcheck/p4.c
+++ b/arch/x86/kernel/cpu/mcheck/p4.c
@@ -1,8 +1,6 @@
 /*
  * P4 specific Machine Check Exception Reporting
  */
-
-#include <linux/interrupt.h>
 #include <linux/kernel.h>
 #include <linux/types.h>
 #include <linux/init.h>
@@ -10,9 +8,6 @@
 
 #include <asm/therm_throt.h>
 #include <asm/processor.h>
-#include <asm/system.h>
-#include <asm/apic.h>
-#include <asm/idle.h>
 #include <asm/mce.h>
 #include <asm/msr.h>
 
@@ -33,46 +28,6 @@ struct intel_mce_extended_msrs {
 
 static int mce_num_extended_msrs;
 
-
-#ifdef CONFIG_X86_MCE_P4THERMAL
-
-static void unexpected_thermal_interrupt(void)
-{
-	printk(KERN_ERR "CPU%d: Unexpected LVT TMR interrupt!\n",
-			smp_processor_id());
-	add_taint(TAINT_MACHINE_CHECK);
-}
-
-/* P4/Xeon Thermal transition interrupt handler: */
-static void intel_thermal_interrupt(void)
-{
-	__u64 msr_val;
-
-	rdmsrl(MSR_IA32_THERM_STATUS, msr_val);
-	if (therm_throt_process(msr_val & THERM_STATUS_PROCHOT))
-		mce_log_therm_throt_event(msr_val);
-}
-
-/* Thermal interrupt handler for this CPU setup: */
-static void (*vendor_thermal_interrupt)(void) = unexpected_thermal_interrupt;
-
-void smp_thermal_interrupt(struct pt_regs *regs)
-{
-	exit_idle();
-	irq_enter();
-	inc_irq_stat(irq_thermal_count);
-	vendor_thermal_interrupt();
-	irq_exit();
-	ack_APIC_irq();
-}
-
-void intel_set_thermal_handler(void)
-{
-	vendor_thermal_interrupt = intel_thermal_interrupt;
-}
-
-#endif /* CONFIG_X86_MCE_P4THERMAL */
-
 /* P4/Xeon Extended MCE MSR retrieval, return 0 if unsupported */
 static void intel_get_extended_msrs(struct intel_mce_extended_msrs *r)
 {
diff --git a/arch/x86/kernel/cpu/mcheck/therm_throt.c b/arch/x86/kernel/cpu/mcheck/therm_throt.c
index 7b1ae2e..b3792b1 100644
--- a/arch/x86/kernel/cpu/mcheck/therm_throt.c
+++ b/arch/x86/kernel/cpu/mcheck/therm_throt.c
@@ -13,6 +13,7 @@
  * Credits: Adapted from Zwane Mwaikambo's original code in mce_intel.c.
  *          Inspired by Ross Biro's and Al Borchers' counter code.
  */
+#include <linux/interrupt.h>
 #include <linux/notifier.h>
 #include <linux/jiffies.h>
 #include <linux/percpu.h>
@@ -20,6 +21,8 @@
 #include <linux/cpu.h>
 
 #include <asm/therm_throt.h>
+#include <asm/idle.h>
+#include <asm/mce.h>
 
 /* How long to wait between reporting thermal events */
 #define CHECK_INTERVAL		(300 * HZ)
@@ -186,6 +189,41 @@ static __init int thermal_throttle_init_device(void)
 
 	return 0;
 }
-
 device_initcall(thermal_throttle_init_device);
+
 #endif /* CONFIG_SYSFS */
+
+/* Thermal transition interrupt handler */
+void intel_thermal_interrupt(void)
+{
+	__u64 msr_val;
+
+	rdmsrl(MSR_IA32_THERM_STATUS, msr_val);
+	if (therm_throt_process(msr_val & THERM_STATUS_PROCHOT))
+		mce_log_therm_throt_event(msr_val);
+}
+
+static void unexpected_thermal_interrupt(void)
+{
+	printk(KERN_ERR "CPU%d: Unexpected LVT TMR interrupt!\n",
+			smp_processor_id());
+	add_taint(TAINT_MACHINE_CHECK);
+}
+
+static void (*smp_thermal_vector)(void) = unexpected_thermal_interrupt;
+
+asmlinkage void smp_thermal_interrupt(struct pt_regs *regs)
+{
+	exit_idle();
+	irq_enter();
+	inc_irq_stat(irq_thermal_count);
+	smp_thermal_vector();
+	irq_exit();
+	/* Ack only at the end to avoid potential reentry */
+	ack_APIC_irq();
+}
+
+void intel_set_thermal_handler(void)
+{
+	smp_thermal_vector = intel_thermal_interrupt;
+}
-- 
1.6.3



^ permalink raw reply related	[flat|nested] 25+ messages in thread

* Re: [PATCH 02/16] x86, mce: call-in should be after updating  global_nwo
  2009-06-15  8:19 ` [PATCH 02/16] x86, mce: call-in should be after updating global_nwo Hidetoshi Seto
@ 2009-06-15  8:26   ` huang ying
  2009-06-15  8:40     ` Hidetoshi Seto
  2009-06-15  9:18     ` [PATCH] x86, mce: cleanup mce_start() Hidetoshi Seto
  0 siblings, 2 replies; 25+ messages in thread
From: huang ying @ 2009-06-15  8:26 UTC (permalink / raw)
  To: Hidetoshi Seto
  Cc: linux-kernel, Ingo Molnar, H. Peter Anvin, Thomas Gleixner,
	Andi Kleen, Huang Ying

2009/6/15 Hidetoshi Seto <seto.hidetoshi@jp.fujitsu.com>:
> At the beginning of Monarch synchronization, processors wait until
> all of them have entered the exception handler and then check the
> global_nwo to determine if any of them saw a fatal event.
>
> However since current code does call-in before updating global_nwo,
> it might happen that the global_nwo does not reflect some of local
> nwo at the time.  This might break printing corrected errors not
> handled yet on panic.

This is almost same as the patch that I just posted. I think this is
because it trigger a failure in mce-test suite, and we both find the
failure.

But your patch lacks memory barrier between mce_callin and global_nwo
updating/reading. Atomic operations does not imply memory barrier.

Best Regards,
Huang Ying

^ permalink raw reply	[flat|nested] 25+ messages in thread

* [PATCH 12/16] x86, mce: squash mce_intel.c into therm_throt.c
  2009-06-15  8:09 [PATCH 00/16] last-minute patches for MCE .31 Hidetoshi Seto
                   ` (10 preceding siblings ...)
  2009-06-15  8:25 ` [PATCH 11/16] x86, mce: unify smp_thermal_interrupt Hidetoshi Seto
@ 2009-06-15  8:26 ` Hidetoshi Seto
  2009-06-18  5:49   ` huang ying
  2009-06-15  8:26 ` [PATCH 13/16] x86, mce: remove intel_set_thermal_handler() Hidetoshi Seto
                   ` (3 subsequent siblings)
  15 siblings, 1 reply; 25+ messages in thread
From: Hidetoshi Seto @ 2009-06-15  8:26 UTC (permalink / raw)
  To: linux-kernel; +Cc: Ingo Molnar, H. Peter Anvin, Thomas Gleixner, Andi Kleen

move intel_init_thermal() into therm_throt.c

Signed-off-by: Hidetoshi Seto <seto.hidetoshi@jp.fujitsu.com>
---
 arch/x86/kernel/cpu/mcheck/Makefile      |    2 +-
 arch/x86/kernel/cpu/mcheck/mce_intel.c   |   73 ------------------------------
 arch/x86/kernel/cpu/mcheck/therm_throt.c |   66 +++++++++++++++++++++++++++
 3 files changed, 67 insertions(+), 74 deletions(-)
 delete mode 100644 arch/x86/kernel/cpu/mcheck/mce_intel.c

diff --git a/arch/x86/kernel/cpu/mcheck/Makefile b/arch/x86/kernel/cpu/mcheck/Makefile
index 53df57d..659564e 100644
--- a/arch/x86/kernel/cpu/mcheck/Makefile
+++ b/arch/x86/kernel/cpu/mcheck/Makefile
@@ -9,4 +9,4 @@ obj-$(CONFIG_X86_MCE_NONFATAL)	+= non-fatal.o
 obj-$(CONFIG_X86_MCE_THRESHOLD) += threshold.o
 obj-$(CONFIG_X86_MCE_INJECT)	+= mce-inject.o
 
-obj-$(CONFIG_X86_THERMAL_VECTOR) += therm_throt.o mce_intel.o
+obj-$(CONFIG_X86_THERMAL_VECTOR) += therm_throt.o
diff --git a/arch/x86/kernel/cpu/mcheck/mce_intel.c b/arch/x86/kernel/cpu/mcheck/mce_intel.c
deleted file mode 100644
index 475478b..0000000
--- a/arch/x86/kernel/cpu/mcheck/mce_intel.c
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * Common code for Intel machine checks
- */
-#include <linux/interrupt.h>
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/init.h>
-#include <linux/smp.h>
-
-#include <asm/therm_throt.h>
-#include <asm/processor.h>
-#include <asm/system.h>
-#include <asm/apic.h>
-#include <asm/mce.h>
-#include <asm/msr.h>
-
-void intel_init_thermal(struct cpuinfo_x86 *c)
-{
-	unsigned int cpu = smp_processor_id();
-	int tm2 = 0;
-	u32 l, h;
-
-	/* Thermal monitoring depends on ACPI and clock modulation*/
-	if (!cpu_has(c, X86_FEATURE_ACPI) || !cpu_has(c, X86_FEATURE_ACC))
-		return;
-
-	/*
-	 * First check if its enabled already, in which case there might
-	 * be some SMM goo which handles it, so we can't even put a handler
-	 * since it might be delivered via SMI already:
-	 */
-	rdmsr(MSR_IA32_MISC_ENABLE, l, h);
-	h = apic_read(APIC_LVTTHMR);
-	if ((l & MSR_IA32_MISC_ENABLE_TM1) && (h & APIC_DM_SMI)) {
-		printk(KERN_DEBUG
-		       "CPU%d: Thermal monitoring handled by SMI\n", cpu);
-		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
-		       "CPU%d: Thermal LVT vector (%#x) already installed\n",
-		       cpu, (h & APIC_VECTOR_MASK));
-		return;
-	}
-
-	/* 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);
-
-	rdmsr(MSR_IA32_THERM_INTERRUPT, l, h);
-	wrmsr(MSR_IA32_THERM_INTERRUPT,
-		l | (THERM_INT_LOW_ENABLE | THERM_INT_HIGH_ENABLE), h);
-
-	intel_set_thermal_handler();
-
-	rdmsr(MSR_IA32_MISC_ENABLE, l, h);
-	wrmsr(MSR_IA32_MISC_ENABLE, l | MSR_IA32_MISC_ENABLE_TM1, h);
-
-	/* Unmask the thermal vector: */
-	l = apic_read(APIC_LVTTHMR);
-	apic_write(APIC_LVTTHMR, l & ~APIC_LVT_MASKED);
-
-	printk(KERN_INFO "CPU%d: Thermal monitoring enabled (%s)\n",
-	       cpu, tm2 ? "TM2" : "TM1");
-
-	/* enable thermal throttle processing */
-	atomic_set(&therm_throt_en, 1);
-}
diff --git a/arch/x86/kernel/cpu/mcheck/therm_throt.c b/arch/x86/kernel/cpu/mcheck/therm_throt.c
index b3792b1..7a508aa 100644
--- a/arch/x86/kernel/cpu/mcheck/therm_throt.c
+++ b/arch/x86/kernel/cpu/mcheck/therm_throt.c
@@ -16,13 +16,21 @@
 #include <linux/interrupt.h>
 #include <linux/notifier.h>
 #include <linux/jiffies.h>
+#include <linux/kernel.h>
 #include <linux/percpu.h>
 #include <linux/sysdev.h>
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/smp.h>
 #include <linux/cpu.h>
 
 #include <asm/therm_throt.h>
+#include <asm/processor.h>
+#include <asm/system.h>
+#include <asm/apic.h>
 #include <asm/idle.h>
 #include <asm/mce.h>
+#include <asm/msr.h>
 
 /* How long to wait between reporting thermal events */
 #define CHECK_INTERVAL		(300 * HZ)
@@ -227,3 +235,61 @@ void intel_set_thermal_handler(void)
 {
 	smp_thermal_vector = intel_thermal_interrupt;
 }
+
+void intel_init_thermal(struct cpuinfo_x86 *c)
+{
+	unsigned int cpu = smp_processor_id();
+	int tm2 = 0;
+	u32 l, h;
+
+	/* Thermal monitoring depends on ACPI and clock modulation*/
+	if (!cpu_has(c, X86_FEATURE_ACPI) || !cpu_has(c, X86_FEATURE_ACC))
+		return;
+
+	/*
+	 * First check if its enabled already, in which case there might
+	 * be some SMM goo which handles it, so we can't even put a handler
+	 * since it might be delivered via SMI already:
+	 */
+	rdmsr(MSR_IA32_MISC_ENABLE, l, h);
+	h = apic_read(APIC_LVTTHMR);
+	if ((l & MSR_IA32_MISC_ENABLE_TM1) && (h & APIC_DM_SMI)) {
+		printk(KERN_DEBUG
+		       "CPU%d: Thermal monitoring handled by SMI\n", cpu);
+		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
+		       "CPU%d: Thermal LVT vector (%#x) already installed\n",
+		       cpu, (h & APIC_VECTOR_MASK));
+		return;
+	}
+
+	/* 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);
+
+	rdmsr(MSR_IA32_THERM_INTERRUPT, l, h);
+	wrmsr(MSR_IA32_THERM_INTERRUPT,
+		l | (THERM_INT_LOW_ENABLE | THERM_INT_HIGH_ENABLE), h);
+
+	intel_set_thermal_handler();
+
+	rdmsr(MSR_IA32_MISC_ENABLE, l, h);
+	wrmsr(MSR_IA32_MISC_ENABLE, l | MSR_IA32_MISC_ENABLE_TM1, h);
+
+	/* Unmask the thermal vector: */
+	l = apic_read(APIC_LVTTHMR);
+	apic_write(APIC_LVTTHMR, l & ~APIC_LVT_MASKED);
+
+	printk(KERN_INFO "CPU%d: Thermal monitoring enabled (%s)\n",
+	       cpu, tm2 ? "TM2" : "TM1");
+
+	/* enable thermal throttle processing */
+	atomic_set(&therm_throt_en, 1);
+}
-- 
1.6.3



^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH 13/16] x86, mce: remove intel_set_thermal_handler()
  2009-06-15  8:09 [PATCH 00/16] last-minute patches for MCE .31 Hidetoshi Seto
                   ` (11 preceding siblings ...)
  2009-06-15  8:26 ` [PATCH 12/16] x86, mce: squash mce_intel.c into therm_throt.c Hidetoshi Seto
@ 2009-06-15  8:26 ` Hidetoshi Seto
  2009-06-15  8:27 ` [PATCH 14/16] x86, mce: remove therm_throt.h Hidetoshi Seto
                   ` (2 subsequent siblings)
  15 siblings, 0 replies; 25+ messages in thread
From: Hidetoshi Seto @ 2009-06-15  8:26 UTC (permalink / raw)
  To: linux-kernel; +Cc: Ingo Molnar, H. Peter Anvin, Thomas Gleixner, Andi Kleen

and make intel_thermal_interrupt() static.

Signed-off-by: Hidetoshi Seto <seto.hidetoshi@jp.fujitsu.com>
---
 arch/x86/include/asm/mce.h               |    1 -
 arch/x86/kernel/cpu/mcheck/therm_throt.c |    9 ++-------
 2 files changed, 2 insertions(+), 8 deletions(-)

diff --git a/arch/x86/include/asm/mce.h b/arch/x86/include/asm/mce.h
index 3bc827c..365a594 100644
--- a/arch/x86/include/asm/mce.h
+++ b/arch/x86/include/asm/mce.h
@@ -199,7 +199,6 @@ extern void (*mce_threshold_vector)(void);
  * Thermal handler
  */
 
-void intel_set_thermal_handler(void);
 void intel_init_thermal(struct cpuinfo_x86 *c);
 
 #ifdef CONFIG_X86_NEW_MCE
diff --git a/arch/x86/kernel/cpu/mcheck/therm_throt.c b/arch/x86/kernel/cpu/mcheck/therm_throt.c
index 7a508aa..7c7944c 100644
--- a/arch/x86/kernel/cpu/mcheck/therm_throt.c
+++ b/arch/x86/kernel/cpu/mcheck/therm_throt.c
@@ -202,7 +202,7 @@ device_initcall(thermal_throttle_init_device);
 #endif /* CONFIG_SYSFS */
 
 /* Thermal transition interrupt handler */
-void intel_thermal_interrupt(void)
+static void intel_thermal_interrupt(void)
 {
 	__u64 msr_val;
 
@@ -231,11 +231,6 @@ asmlinkage void smp_thermal_interrupt(struct pt_regs *regs)
 	ack_APIC_irq();
 }
 
-void intel_set_thermal_handler(void)
-{
-	smp_thermal_vector = intel_thermal_interrupt;
-}
-
 void intel_init_thermal(struct cpuinfo_x86 *c)
 {
 	unsigned int cpu = smp_processor_id();
@@ -278,7 +273,7 @@ void intel_init_thermal(struct cpuinfo_x86 *c)
 	wrmsr(MSR_IA32_THERM_INTERRUPT,
 		l | (THERM_INT_LOW_ENABLE | THERM_INT_HIGH_ENABLE), h);
 
-	intel_set_thermal_handler();
+	smp_thermal_vector = intel_thermal_interrupt;
 
 	rdmsr(MSR_IA32_MISC_ENABLE, l, h);
 	wrmsr(MSR_IA32_MISC_ENABLE, l | MSR_IA32_MISC_ENABLE_TM1, h);
-- 
1.6.3



^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH 14/16] x86, mce: remove therm_throt.h
  2009-06-15  8:09 [PATCH 00/16] last-minute patches for MCE .31 Hidetoshi Seto
                   ` (12 preceding siblings ...)
  2009-06-15  8:26 ` [PATCH 13/16] x86, mce: remove intel_set_thermal_handler() Hidetoshi Seto
@ 2009-06-15  8:27 ` Hidetoshi Seto
  2009-06-15  8:27 ` [PATCH 15/16] x86, mce: mce.h cleanup Hidetoshi Seto
  2009-06-15  8:28 ` [PATCH 16/16] x86, mce: rename Hidetoshi Seto
  15 siblings, 0 replies; 25+ messages in thread
From: Hidetoshi Seto @ 2009-06-15  8:27 UTC (permalink / raw)
  To: linux-kernel; +Cc: Ingo Molnar, H. Peter Anvin, Thomas Gleixner, Andi Kleen

Now all symbols in the header are static.  Remove the header.

Signed-off-by: Hidetoshi Seto <seto.hidetoshi@jp.fujitsu.com>
---
 arch/x86/include/asm/therm_throt.h        |    9 ---------
 arch/x86/kernel/cpu/mcheck/mce_intel_64.c |    1 -
 arch/x86/kernel/cpu/mcheck/p4.c           |    1 -
 arch/x86/kernel/cpu/mcheck/therm_throt.c  |    5 ++---
 4 files changed, 2 insertions(+), 14 deletions(-)
 delete mode 100644 arch/x86/include/asm/therm_throt.h

diff --git a/arch/x86/include/asm/therm_throt.h b/arch/x86/include/asm/therm_throt.h
deleted file mode 100644
index c62349e..0000000
--- a/arch/x86/include/asm/therm_throt.h
+++ /dev/null
@@ -1,9 +0,0 @@
-#ifndef _ASM_X86_THERM_THROT_H
-#define _ASM_X86_THERM_THROT_H
-
-#include <asm/atomic.h>
-
-extern atomic_t therm_throt_en;
-int therm_throt_process(int curr);
-
-#endif /* _ASM_X86_THERM_THROT_H */
diff --git a/arch/x86/kernel/cpu/mcheck/mce_intel_64.c b/arch/x86/kernel/cpu/mcheck/mce_intel_64.c
index 3b7a057..663a88e 100644
--- a/arch/x86/kernel/cpu/mcheck/mce_intel_64.c
+++ b/arch/x86/kernel/cpu/mcheck/mce_intel_64.c
@@ -11,7 +11,6 @@
 #include <asm/processor.h>
 #include <asm/msr.h>
 #include <asm/mce.h>
-#include <asm/therm_throt.h>
 
 /*
  * Support for Intel Correct Machine Check Interrupts. This allows
diff --git a/arch/x86/kernel/cpu/mcheck/p4.c b/arch/x86/kernel/cpu/mcheck/p4.c
index 76c5f03..4482aea 100644
--- a/arch/x86/kernel/cpu/mcheck/p4.c
+++ b/arch/x86/kernel/cpu/mcheck/p4.c
@@ -6,7 +6,6 @@
 #include <linux/init.h>
 #include <linux/smp.h>
 
-#include <asm/therm_throt.h>
 #include <asm/processor.h>
 #include <asm/mce.h>
 #include <asm/msr.h>
diff --git a/arch/x86/kernel/cpu/mcheck/therm_throt.c b/arch/x86/kernel/cpu/mcheck/therm_throt.c
index 7c7944c..bff8dd1 100644
--- a/arch/x86/kernel/cpu/mcheck/therm_throt.c
+++ b/arch/x86/kernel/cpu/mcheck/therm_throt.c
@@ -24,7 +24,6 @@
 #include <linux/smp.h>
 #include <linux/cpu.h>
 
-#include <asm/therm_throt.h>
 #include <asm/processor.h>
 #include <asm/system.h>
 #include <asm/apic.h>
@@ -38,7 +37,7 @@
 static DEFINE_PER_CPU(__u64, next_check) = INITIAL_JIFFIES;
 static DEFINE_PER_CPU(unsigned long, thermal_throttle_count);
 
-atomic_t therm_throt_en		= ATOMIC_INIT(0);
+static atomic_t therm_throt_en		= ATOMIC_INIT(0);
 
 #ifdef CONFIG_SYSFS
 #define define_therm_throt_sysdev_one_ro(_name)				\
@@ -93,7 +92,7 @@ static struct attribute_group thermal_throttle_attr_group = {
  *          1 : Event should be logged further, and a message has been
  *              printed to the syslog.
  */
-int therm_throt_process(int curr)
+static int therm_throt_process(int curr)
 {
 	unsigned int cpu = smp_processor_id();
 	__u64 tmp_jiffs = get_jiffies_64();
-- 
1.6.3



^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH 15/16] x86, mce: mce.h cleanup
  2009-06-15  8:09 [PATCH 00/16] last-minute patches for MCE .31 Hidetoshi Seto
                   ` (13 preceding siblings ...)
  2009-06-15  8:27 ` [PATCH 14/16] x86, mce: remove therm_throt.h Hidetoshi Seto
@ 2009-06-15  8:27 ` Hidetoshi Seto
  2009-06-15  8:28 ` [PATCH 16/16] x86, mce: rename Hidetoshi Seto
  15 siblings, 0 replies; 25+ messages in thread
From: Hidetoshi Seto @ 2009-06-15  8:27 UTC (permalink / raw)
  To: linux-kernel; +Cc: Ingo Molnar, H. Peter Anvin, Thomas Gleixner, Andi Kleen

Reorder definitions.

 - static inline dummy mcheck_init() for !CONFIG_X86_MCE
 - gather defs for exception, threshold handler

Signed-off-by: Hidetoshi Seto <seto.hidetoshi@jp.fujitsu.com>
---
 arch/x86/include/asm/mce.h |   29 ++++++++++++++++++-----------
 1 files changed, 18 insertions(+), 11 deletions(-)

diff --git a/arch/x86/include/asm/mce.h b/arch/x86/include/asm/mce.h
index 365a594..5cdd8d1 100644
--- a/arch/x86/include/asm/mce.h
+++ b/arch/x86/include/asm/mce.h
@@ -109,6 +109,12 @@ struct mce_log {
 extern int mce_disabled;
 extern int mce_p5_enabled;
 
+#ifdef CONFIG_X86_MCE
+void mcheck_init(struct cpuinfo_x86 *c);
+#else
+static inline void mcheck_init(struct cpuinfo_x86 *c) {}
+#endif
+
 #ifdef CONFIG_X86_OLD_MCE
 extern int nr_mce_banks;
 void amd_mcheck_init(struct cpuinfo_x86 *c);
@@ -126,13 +132,9 @@ static inline void winchip_mcheck_init(struct cpuinfo_x86 *c) {}
 static inline void enable_p5_mce(void) {}
 #endif
 
-/* Call the installed machine check handler for this CPU setup. */
-extern void (*machine_check_vector)(struct pt_regs *, long error_code);
-
 void mce_setup(struct mce *m);
 void mce_log(struct mce *m);
 DECLARE_PER_CPU(struct sys_device, mce_dev);
-extern void (*threshold_cpu_callback)(unsigned long action, unsigned int cpu);
 
 /*
  * To support more than 128 would need to escape the predefined
@@ -169,8 +171,6 @@ DECLARE_PER_CPU(unsigned, mce_poll_count);
 
 extern atomic_t mce_entry;
 
-void do_machine_check(struct pt_regs *, long);
-
 typedef DECLARE_BITMAP(mce_banks_t, MAX_NR_BANKS);
 DECLARE_PER_CPU(mce_banks_t, mce_poll_banks);
 
@@ -187,13 +187,20 @@ void mce_notify_process(void);
 DECLARE_PER_CPU(struct mce, injectm);
 extern struct file_operations mce_chrdev_ops;
 
-#ifdef CONFIG_X86_MCE
-void mcheck_init(struct cpuinfo_x86 *c);
-#else
-#define mcheck_init(c) do { } while (0)
-#endif
+/*
+ * Exception handler
+ */
+
+/* Call the installed machine check handler for this CPU setup. */
+extern void (*machine_check_vector)(struct pt_regs *, long error_code);
+void do_machine_check(struct pt_regs *, long);
+
+/*
+ * Threshold handler
+ */
 
 extern void (*mce_threshold_vector)(void);
+extern void (*threshold_cpu_callback)(unsigned long action, unsigned int cpu);
 
 /*
  * Thermal handler
-- 
1.6.3



^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH 16/16] x86, mce: rename
  2009-06-15  8:09 [PATCH 00/16] last-minute patches for MCE .31 Hidetoshi Seto
                   ` (14 preceding siblings ...)
  2009-06-15  8:27 ` [PATCH 15/16] x86, mce: mce.h cleanup Hidetoshi Seto
@ 2009-06-15  8:28 ` Hidetoshi Seto
  15 siblings, 0 replies; 25+ messages in thread
From: Hidetoshi Seto @ 2009-06-15  8:28 UTC (permalink / raw)
  To: linux-kernel; +Cc: Ingo Molnar, H. Peter Anvin, Thomas Gleixner, Andi Kleen

Rename files that are no longer 64bit specific:
	mce_amd_64.c	=> mce_amd.c
	mce_intel_64.c	=> mce_intel.c

Signed-off-by: Hidetoshi Seto <seto.hidetoshi@jp.fujitsu.com>
---
 arch/x86/kernel/cpu/mcheck/Makefile       |    4 +-
 arch/x86/kernel/cpu/mcheck/mce_amd.c      |  703 +++++++++++++++++++++++++++++
 arch/x86/kernel/cpu/mcheck/mce_amd_64.c   |  703 -----------------------------
 arch/x86/kernel/cpu/mcheck/mce_intel.c    |  225 +++++++++
 arch/x86/kernel/cpu/mcheck/mce_intel_64.c |  225 ---------
 5 files changed, 930 insertions(+), 930 deletions(-)
 create mode 100644 arch/x86/kernel/cpu/mcheck/mce_amd.c
 delete mode 100644 arch/x86/kernel/cpu/mcheck/mce_amd_64.c
 create mode 100644 arch/x86/kernel/cpu/mcheck/mce_intel.c
 delete mode 100644 arch/x86/kernel/cpu/mcheck/mce_intel_64.c

diff --git a/arch/x86/kernel/cpu/mcheck/Makefile b/arch/x86/kernel/cpu/mcheck/Makefile
index 659564e..188a1ca 100644
--- a/arch/x86/kernel/cpu/mcheck/Makefile
+++ b/arch/x86/kernel/cpu/mcheck/Makefile
@@ -3,8 +3,8 @@ obj-y				=  mce.o
 obj-$(CONFIG_X86_NEW_MCE)	+= mce-severity.o
 obj-$(CONFIG_X86_OLD_MCE)	+= k7.o p4.o p6.o
 obj-$(CONFIG_X86_ANCIENT_MCE)	+= winchip.o p5.o
-obj-$(CONFIG_X86_MCE_INTEL)	+= mce_intel_64.o
-obj-$(CONFIG_X86_MCE_AMD)	+= mce_amd_64.o
+obj-$(CONFIG_X86_MCE_INTEL)	+= mce_intel.o
+obj-$(CONFIG_X86_MCE_AMD)	+= mce_amd.o
 obj-$(CONFIG_X86_MCE_NONFATAL)	+= non-fatal.o
 obj-$(CONFIG_X86_MCE_THRESHOLD) += threshold.o
 obj-$(CONFIG_X86_MCE_INJECT)	+= mce-inject.o
diff --git a/arch/x86/kernel/cpu/mcheck/mce_amd.c b/arch/x86/kernel/cpu/mcheck/mce_amd.c
new file mode 100644
index 0000000..ddae216
--- /dev/null
+++ b/arch/x86/kernel/cpu/mcheck/mce_amd.c
@@ -0,0 +1,703 @@
+/*
+ *  (c) 2005, 2006 Advanced Micro Devices, Inc.
+ *  Your use of this code is subject to the terms and conditions of the
+ *  GNU general public license version 2. See "COPYING" or
+ *  http://www.gnu.org/licenses/gpl.html
+ *
+ *  Written by Jacob Shin - AMD, Inc.
+ *
+ *  Support : jacob.shin@amd.com
+ *
+ *  April 2006
+ *     - added support for AMD Family 0x10 processors
+ *
+ *  All MC4_MISCi registers are shared between multi-cores
+ */
+#include <linux/interrupt.h>
+#include <linux/notifier.h>
+#include <linux/kobject.h>
+#include <linux/percpu.h>
+#include <linux/sysdev.h>
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/sysfs.h>
+#include <linux/init.h>
+#include <linux/cpu.h>
+#include <linux/smp.h>
+
+#include <asm/apic.h>
+#include <asm/idle.h>
+#include <asm/mce.h>
+#include <asm/msr.h>
+
+#define PFX               "mce_threshold: "
+#define VERSION           "version 1.1.1"
+#define NR_BANKS          6
+#define NR_BLOCKS         9
+#define THRESHOLD_MAX     0xFFF
+#define INT_TYPE_APIC     0x00020000
+#define MASK_VALID_HI     0x80000000
+#define MASK_CNTP_HI      0x40000000
+#define MASK_LOCKED_HI    0x20000000
+#define MASK_LVTOFF_HI    0x00F00000
+#define MASK_COUNT_EN_HI  0x00080000
+#define MASK_INT_TYPE_HI  0x00060000
+#define MASK_OVERFLOW_HI  0x00010000
+#define MASK_ERR_COUNT_HI 0x00000FFF
+#define MASK_BLKPTR_LO    0xFF000000
+#define MCG_XBLK_ADDR     0xC0000400
+
+struct threshold_block {
+	unsigned int		block;
+	unsigned int		bank;
+	unsigned int		cpu;
+	u32			address;
+	u16			interrupt_enable;
+	u16			threshold_limit;
+	struct kobject		kobj;
+	struct list_head	miscj;
+};
+
+/* defaults used early on boot */
+static struct threshold_block threshold_defaults = {
+	.interrupt_enable	= 0,
+	.threshold_limit	= THRESHOLD_MAX,
+};
+
+struct threshold_bank {
+	struct kobject		*kobj;
+	struct threshold_block	*blocks;
+	cpumask_var_t		cpus;
+};
+static DEFINE_PER_CPU(struct threshold_bank *, threshold_banks[NR_BANKS]);
+
+#ifdef CONFIG_SMP
+static unsigned char shared_bank[NR_BANKS] = {
+	0, 0, 0, 0, 1
+};
+#endif
+
+static DEFINE_PER_CPU(unsigned char, bank_map);	/* see which banks are on */
+
+static void amd_threshold_interrupt(void);
+
+/*
+ * CPU Initialization
+ */
+
+struct thresh_restart {
+	struct threshold_block	*b;
+	int			reset;
+	u16			old_limit;
+};
+
+/* must be called with correct cpu affinity */
+/* Called via smp_call_function_single() */
+static void threshold_restart_bank(void *_tr)
+{
+	struct thresh_restart *tr = _tr;
+	u32 mci_misc_hi, mci_misc_lo;
+
+	rdmsr(tr->b->address, mci_misc_lo, mci_misc_hi);
+
+	if (tr->b->threshold_limit < (mci_misc_hi & THRESHOLD_MAX))
+		tr->reset = 1;	/* limit cannot be lower than err count */
+
+	if (tr->reset) {		/* reset err count and overflow bit */
+		mci_misc_hi =
+		    (mci_misc_hi & ~(MASK_ERR_COUNT_HI | MASK_OVERFLOW_HI)) |
+		    (THRESHOLD_MAX - tr->b->threshold_limit);
+	} else if (tr->old_limit) {	/* change limit w/o reset */
+		int new_count = (mci_misc_hi & THRESHOLD_MAX) +
+		    (tr->old_limit - tr->b->threshold_limit);
+
+		mci_misc_hi = (mci_misc_hi & ~MASK_ERR_COUNT_HI) |
+		    (new_count & THRESHOLD_MAX);
+	}
+
+	tr->b->interrupt_enable ?
+	    (mci_misc_hi = (mci_misc_hi & ~MASK_INT_TYPE_HI) | INT_TYPE_APIC) :
+	    (mci_misc_hi &= ~MASK_INT_TYPE_HI);
+
+	mci_misc_hi |= MASK_COUNT_EN_HI;
+	wrmsr(tr->b->address, mci_misc_lo, mci_misc_hi);
+}
+
+/* cpu init entry point, called from mce.c with preempt off */
+void mce_amd_feature_init(struct cpuinfo_x86 *c)
+{
+	unsigned int cpu = smp_processor_id();
+	u32 low = 0, high = 0, address = 0;
+	unsigned int bank, block;
+	struct thresh_restart tr;
+	u8 lvt_off;
+
+	for (bank = 0; bank < NR_BANKS; ++bank) {
+		for (block = 0; block < NR_BLOCKS; ++block) {
+			if (block == 0)
+				address = MSR_IA32_MC0_MISC + bank * 4;
+			else if (block == 1) {
+				address = (low & MASK_BLKPTR_LO) >> 21;
+				if (!address)
+					break;
+				address += MCG_XBLK_ADDR;
+			} else
+				++address;
+
+			if (rdmsr_safe(address, &low, &high))
+				break;
+
+			if (!(high & MASK_VALID_HI)) {
+				if (block)
+					continue;
+				else
+					break;
+			}
+
+			if (!(high & MASK_CNTP_HI)  ||
+			     (high & MASK_LOCKED_HI))
+				continue;
+
+			if (!block)
+				per_cpu(bank_map, cpu) |= (1 << bank);
+#ifdef CONFIG_SMP
+			if (shared_bank[bank] && c->cpu_core_id)
+				break;
+#endif
+			lvt_off = setup_APIC_eilvt_mce(THRESHOLD_APIC_VECTOR,
+						       APIC_EILVT_MSG_FIX, 0);
+
+			high &= ~MASK_LVTOFF_HI;
+			high |= lvt_off << 20;
+			wrmsr(address, low, high);
+
+			threshold_defaults.address = address;
+			tr.b = &threshold_defaults;
+			tr.reset = 0;
+			tr.old_limit = 0;
+			threshold_restart_bank(&tr);
+
+			mce_threshold_vector = amd_threshold_interrupt;
+		}
+	}
+}
+
+/*
+ * APIC Interrupt Handler
+ */
+
+/*
+ * threshold interrupt handler will service THRESHOLD_APIC_VECTOR.
+ * the interrupt goes off when error_count reaches threshold_limit.
+ * the handler will simply log mcelog w/ software defined bank number.
+ */
+static void amd_threshold_interrupt(void)
+{
+	u32 low = 0, high = 0, address = 0;
+	unsigned int bank, block;
+	struct mce m;
+
+	mce_setup(&m);
+
+	/* assume first bank caused it */
+	for (bank = 0; bank < NR_BANKS; ++bank) {
+		if (!(per_cpu(bank_map, m.cpu) & (1 << bank)))
+			continue;
+		for (block = 0; block < NR_BLOCKS; ++block) {
+			if (block == 0) {
+				address = MSR_IA32_MC0_MISC + bank * 4;
+			} else if (block == 1) {
+				address = (low & MASK_BLKPTR_LO) >> 21;
+				if (!address)
+					break;
+				address += MCG_XBLK_ADDR;
+			} else {
+				++address;
+			}
+
+			if (rdmsr_safe(address, &low, &high))
+				break;
+
+			if (!(high & MASK_VALID_HI)) {
+				if (block)
+					continue;
+				else
+					break;
+			}
+
+			if (!(high & MASK_CNTP_HI)  ||
+			     (high & MASK_LOCKED_HI))
+				continue;
+
+			/*
+			 * Log the machine check that caused the threshold
+			 * event.
+			 */
+			machine_check_poll(MCP_TIMESTAMP,
+					&__get_cpu_var(mce_poll_banks));
+
+			if (high & MASK_OVERFLOW_HI) {
+				rdmsrl(address, m.misc);
+				rdmsrl(MSR_IA32_MC0_STATUS + bank * 4,
+				       m.status);
+				m.bank = K8_MCE_THRESHOLD_BASE
+				       + bank * NR_BLOCKS
+				       + block;
+				mce_log(&m);
+				return;
+			}
+		}
+	}
+}
+
+/*
+ * Sysfs Interface
+ */
+
+struct threshold_attr {
+	struct attribute attr;
+	ssize_t (*show) (struct threshold_block *, char *);
+	ssize_t (*store) (struct threshold_block *, const char *, size_t count);
+};
+
+#define SHOW_FIELDS(name)						\
+static ssize_t show_ ## name(struct threshold_block *b, char *buf)	\
+{									\
+	return sprintf(buf, "%lx\n", (unsigned long) b->name);		\
+}
+SHOW_FIELDS(interrupt_enable)
+SHOW_FIELDS(threshold_limit)
+
+static ssize_t
+store_interrupt_enable(struct threshold_block *b, const char *buf, size_t size)
+{
+	struct thresh_restart tr;
+	unsigned long new;
+
+	if (strict_strtoul(buf, 0, &new) < 0)
+		return -EINVAL;
+
+	b->interrupt_enable = !!new;
+
+	tr.b		= b;
+	tr.reset	= 0;
+	tr.old_limit	= 0;
+
+	smp_call_function_single(b->cpu, threshold_restart_bank, &tr, 1);
+
+	return size;
+}
+
+static ssize_t
+store_threshold_limit(struct threshold_block *b, const char *buf, size_t size)
+{
+	struct thresh_restart tr;
+	unsigned long new;
+
+	if (strict_strtoul(buf, 0, &new) < 0)
+		return -EINVAL;
+
+	if (new > THRESHOLD_MAX)
+		new = THRESHOLD_MAX;
+	if (new < 1)
+		new = 1;
+
+	tr.old_limit = b->threshold_limit;
+	b->threshold_limit = new;
+	tr.b = b;
+	tr.reset = 0;
+
+	smp_call_function_single(b->cpu, threshold_restart_bank, &tr, 1);
+
+	return size;
+}
+
+struct threshold_block_cross_cpu {
+	struct threshold_block	*tb;
+	long			retval;
+};
+
+static void local_error_count_handler(void *_tbcc)
+{
+	struct threshold_block_cross_cpu *tbcc = _tbcc;
+	struct threshold_block *b = tbcc->tb;
+	u32 low, high;
+
+	rdmsr(b->address, low, high);
+	tbcc->retval = (high & 0xFFF) - (THRESHOLD_MAX - b->threshold_limit);
+}
+
+static ssize_t show_error_count(struct threshold_block *b, char *buf)
+{
+	struct threshold_block_cross_cpu tbcc = { .tb = b, };
+
+	smp_call_function_single(b->cpu, local_error_count_handler, &tbcc, 1);
+	return sprintf(buf, "%lx\n", tbcc.retval);
+}
+
+static ssize_t store_error_count(struct threshold_block *b,
+				 const char *buf, size_t count)
+{
+	struct thresh_restart tr = { .b = b, .reset = 1, .old_limit = 0 };
+
+	smp_call_function_single(b->cpu, threshold_restart_bank, &tr, 1);
+	return 1;
+}
+
+#define RW_ATTR(val)							\
+static struct threshold_attr val = {					\
+	.attr	= {.name = __stringify(val), .mode = 0644 },		\
+	.show	= show_## val,						\
+	.store	= store_## val,						\
+};
+
+RW_ATTR(interrupt_enable);
+RW_ATTR(threshold_limit);
+RW_ATTR(error_count);
+
+static struct attribute *default_attrs[] = {
+	&interrupt_enable.attr,
+	&threshold_limit.attr,
+	&error_count.attr,
+	NULL
+};
+
+#define to_block(k)	container_of(k, struct threshold_block, kobj)
+#define to_attr(a)	container_of(a, struct threshold_attr, attr)
+
+static ssize_t show(struct kobject *kobj, struct attribute *attr, char *buf)
+{
+	struct threshold_block *b = to_block(kobj);
+	struct threshold_attr *a = to_attr(attr);
+	ssize_t ret;
+
+	ret = a->show ? a->show(b, buf) : -EIO;
+
+	return ret;
+}
+
+static ssize_t store(struct kobject *kobj, struct attribute *attr,
+		     const char *buf, size_t count)
+{
+	struct threshold_block *b = to_block(kobj);
+	struct threshold_attr *a = to_attr(attr);
+	ssize_t ret;
+
+	ret = a->store ? a->store(b, buf, count) : -EIO;
+
+	return ret;
+}
+
+static struct sysfs_ops threshold_ops = {
+	.show			= show,
+	.store			= store,
+};
+
+static struct kobj_type threshold_ktype = {
+	.sysfs_ops		= &threshold_ops,
+	.default_attrs		= default_attrs,
+};
+
+static __cpuinit int allocate_threshold_blocks(unsigned int cpu,
+					       unsigned int bank,
+					       unsigned int block,
+					       u32 address)
+{
+	struct threshold_block *b = NULL;
+	u32 low, high;
+	int err;
+
+	if ((bank >= NR_BANKS) || (block >= NR_BLOCKS))
+		return 0;
+
+	if (rdmsr_safe_on_cpu(cpu, address, &low, &high))
+		return 0;
+
+	if (!(high & MASK_VALID_HI)) {
+		if (block)
+			goto recurse;
+		else
+			return 0;
+	}
+
+	if (!(high & MASK_CNTP_HI)  ||
+	     (high & MASK_LOCKED_HI))
+		goto recurse;
+
+	b = kzalloc(sizeof(struct threshold_block), GFP_KERNEL);
+	if (!b)
+		return -ENOMEM;
+
+	b->block		= block;
+	b->bank			= bank;
+	b->cpu			= cpu;
+	b->address		= address;
+	b->interrupt_enable	= 0;
+	b->threshold_limit	= THRESHOLD_MAX;
+
+	INIT_LIST_HEAD(&b->miscj);
+
+	if (per_cpu(threshold_banks, cpu)[bank]->blocks) {
+		list_add(&b->miscj,
+			 &per_cpu(threshold_banks, cpu)[bank]->blocks->miscj);
+	} else {
+		per_cpu(threshold_banks, cpu)[bank]->blocks = b;
+	}
+
+	err = kobject_init_and_add(&b->kobj, &threshold_ktype,
+				   per_cpu(threshold_banks, cpu)[bank]->kobj,
+				   "misc%i", block);
+	if (err)
+		goto out_free;
+recurse:
+	if (!block) {
+		address = (low & MASK_BLKPTR_LO) >> 21;
+		if (!address)
+			return 0;
+		address += MCG_XBLK_ADDR;
+	} else {
+		++address;
+	}
+
+	err = allocate_threshold_blocks(cpu, bank, ++block, address);
+	if (err)
+		goto out_free;
+
+	if (b)
+		kobject_uevent(&b->kobj, KOBJ_ADD);
+
+	return err;
+
+out_free:
+	if (b) {
+		kobject_put(&b->kobj);
+		kfree(b);
+	}
+	return err;
+}
+
+static __cpuinit long
+local_allocate_threshold_blocks(int cpu, unsigned int bank)
+{
+	return allocate_threshold_blocks(cpu, bank, 0,
+					 MSR_IA32_MC0_MISC + bank * 4);
+}
+
+/* symlinks sibling shared banks to first core.  first core owns dir/files. */
+static __cpuinit int threshold_create_bank(unsigned int cpu, unsigned int bank)
+{
+	int i, err = 0;
+	struct threshold_bank *b = NULL;
+	char name[32];
+
+	sprintf(name, "threshold_bank%i", bank);
+
+#ifdef CONFIG_SMP
+	if (cpu_data(cpu).cpu_core_id && shared_bank[bank]) {	/* symlink */
+		i = cpumask_first(cpu_core_mask(cpu));
+
+		/* first core not up yet */
+		if (cpu_data(i).cpu_core_id)
+			goto out;
+
+		/* already linked */
+		if (per_cpu(threshold_banks, cpu)[bank])
+			goto out;
+
+		b = per_cpu(threshold_banks, i)[bank];
+
+		if (!b)
+			goto out;
+
+		err = sysfs_create_link(&per_cpu(mce_dev, cpu).kobj,
+					b->kobj, name);
+		if (err)
+			goto out;
+
+		cpumask_copy(b->cpus, cpu_core_mask(cpu));
+		per_cpu(threshold_banks, cpu)[bank] = b;
+
+		goto out;
+	}
+#endif
+
+	b = kzalloc(sizeof(struct threshold_bank), GFP_KERNEL);
+	if (!b) {
+		err = -ENOMEM;
+		goto out;
+	}
+	if (!alloc_cpumask_var(&b->cpus, GFP_KERNEL)) {
+		kfree(b);
+		err = -ENOMEM;
+		goto out;
+	}
+
+	b->kobj = kobject_create_and_add(name, &per_cpu(mce_dev, cpu).kobj);
+	if (!b->kobj)
+		goto out_free;
+
+#ifndef CONFIG_SMP
+	cpumask_setall(b->cpus);
+#else
+	cpumask_copy(b->cpus, cpu_core_mask(cpu));
+#endif
+
+	per_cpu(threshold_banks, cpu)[bank] = b;
+
+	err = local_allocate_threshold_blocks(cpu, bank);
+	if (err)
+		goto out_free;
+
+	for_each_cpu(i, b->cpus) {
+		if (i == cpu)
+			continue;
+
+		err = sysfs_create_link(&per_cpu(mce_dev, i).kobj,
+					b->kobj, name);
+		if (err)
+			goto out;
+
+		per_cpu(threshold_banks, i)[bank] = b;
+	}
+
+	goto out;
+
+out_free:
+	per_cpu(threshold_banks, cpu)[bank] = NULL;
+	free_cpumask_var(b->cpus);
+	kfree(b);
+out:
+	return err;
+}
+
+/* create dir/files for all valid threshold banks */
+static __cpuinit int threshold_create_device(unsigned int cpu)
+{
+	unsigned int bank;
+	int err = 0;
+
+	for (bank = 0; bank < NR_BANKS; ++bank) {
+		if (!(per_cpu(bank_map, cpu) & (1 << bank)))
+			continue;
+		err = threshold_create_bank(cpu, bank);
+		if (err)
+			goto out;
+	}
+out:
+	return err;
+}
+
+/*
+ * let's be hotplug friendly.
+ * in case of multiple core processors, the first core always takes ownership
+ *   of shared sysfs dir/files, and rest of the cores will be symlinked to it.
+ */
+
+static void deallocate_threshold_block(unsigned int cpu,
+						 unsigned int bank)
+{
+	struct threshold_block *pos = NULL;
+	struct threshold_block *tmp = NULL;
+	struct threshold_bank *head = per_cpu(threshold_banks, cpu)[bank];
+
+	if (!head)
+		return;
+
+	list_for_each_entry_safe(pos, tmp, &head->blocks->miscj, miscj) {
+		kobject_put(&pos->kobj);
+		list_del(&pos->miscj);
+		kfree(pos);
+	}
+
+	kfree(per_cpu(threshold_banks, cpu)[bank]->blocks);
+	per_cpu(threshold_banks, cpu)[bank]->blocks = NULL;
+}
+
+static void threshold_remove_bank(unsigned int cpu, int bank)
+{
+	struct threshold_bank *b;
+	char name[32];
+	int i = 0;
+
+	b = per_cpu(threshold_banks, cpu)[bank];
+	if (!b)
+		return;
+	if (!b->blocks)
+		goto free_out;
+
+	sprintf(name, "threshold_bank%i", bank);
+
+#ifdef CONFIG_SMP
+	/* sibling symlink */
+	if (shared_bank[bank] && b->blocks->cpu != cpu) {
+		sysfs_remove_link(&per_cpu(mce_dev, cpu).kobj, name);
+		per_cpu(threshold_banks, cpu)[bank] = NULL;
+
+		return;
+	}
+#endif
+
+	/* remove all sibling symlinks before unregistering */
+	for_each_cpu(i, b->cpus) {
+		if (i == cpu)
+			continue;
+
+		sysfs_remove_link(&per_cpu(mce_dev, i).kobj, name);
+		per_cpu(threshold_banks, i)[bank] = NULL;
+	}
+
+	deallocate_threshold_block(cpu, bank);
+
+free_out:
+	kobject_del(b->kobj);
+	kobject_put(b->kobj);
+	free_cpumask_var(b->cpus);
+	kfree(b);
+	per_cpu(threshold_banks, cpu)[bank] = NULL;
+}
+
+static void threshold_remove_device(unsigned int cpu)
+{
+	unsigned int bank;
+
+	for (bank = 0; bank < NR_BANKS; ++bank) {
+		if (!(per_cpu(bank_map, cpu) & (1 << bank)))
+			continue;
+		threshold_remove_bank(cpu, bank);
+	}
+}
+
+/* get notified when a cpu comes on/off */
+static void __cpuinit
+amd_64_threshold_cpu_callback(unsigned long action, unsigned int cpu)
+{
+	switch (action) {
+	case CPU_ONLINE:
+	case CPU_ONLINE_FROZEN:
+		threshold_create_device(cpu);
+		break;
+	case CPU_DEAD:
+	case CPU_DEAD_FROZEN:
+		threshold_remove_device(cpu);
+		break;
+	default:
+		break;
+	}
+}
+
+static __init int threshold_init_device(void)
+{
+	unsigned lcpu = 0;
+
+	/* to hit CPUs online before the notifier is up */
+	for_each_online_cpu(lcpu) {
+		int err = threshold_create_device(lcpu);
+
+		if (err)
+			return err;
+	}
+	threshold_cpu_callback = amd_64_threshold_cpu_callback;
+
+	return 0;
+}
+device_initcall(threshold_init_device);
diff --git a/arch/x86/kernel/cpu/mcheck/mce_amd_64.c b/arch/x86/kernel/cpu/mcheck/mce_amd_64.c
deleted file mode 100644
index ddae216..0000000
--- a/arch/x86/kernel/cpu/mcheck/mce_amd_64.c
+++ /dev/null
@@ -1,703 +0,0 @@
-/*
- *  (c) 2005, 2006 Advanced Micro Devices, Inc.
- *  Your use of this code is subject to the terms and conditions of the
- *  GNU general public license version 2. See "COPYING" or
- *  http://www.gnu.org/licenses/gpl.html
- *
- *  Written by Jacob Shin - AMD, Inc.
- *
- *  Support : jacob.shin@amd.com
- *
- *  April 2006
- *     - added support for AMD Family 0x10 processors
- *
- *  All MC4_MISCi registers are shared between multi-cores
- */
-#include <linux/interrupt.h>
-#include <linux/notifier.h>
-#include <linux/kobject.h>
-#include <linux/percpu.h>
-#include <linux/sysdev.h>
-#include <linux/errno.h>
-#include <linux/sched.h>
-#include <linux/sysfs.h>
-#include <linux/init.h>
-#include <linux/cpu.h>
-#include <linux/smp.h>
-
-#include <asm/apic.h>
-#include <asm/idle.h>
-#include <asm/mce.h>
-#include <asm/msr.h>
-
-#define PFX               "mce_threshold: "
-#define VERSION           "version 1.1.1"
-#define NR_BANKS          6
-#define NR_BLOCKS         9
-#define THRESHOLD_MAX     0xFFF
-#define INT_TYPE_APIC     0x00020000
-#define MASK_VALID_HI     0x80000000
-#define MASK_CNTP_HI      0x40000000
-#define MASK_LOCKED_HI    0x20000000
-#define MASK_LVTOFF_HI    0x00F00000
-#define MASK_COUNT_EN_HI  0x00080000
-#define MASK_INT_TYPE_HI  0x00060000
-#define MASK_OVERFLOW_HI  0x00010000
-#define MASK_ERR_COUNT_HI 0x00000FFF
-#define MASK_BLKPTR_LO    0xFF000000
-#define MCG_XBLK_ADDR     0xC0000400
-
-struct threshold_block {
-	unsigned int		block;
-	unsigned int		bank;
-	unsigned int		cpu;
-	u32			address;
-	u16			interrupt_enable;
-	u16			threshold_limit;
-	struct kobject		kobj;
-	struct list_head	miscj;
-};
-
-/* defaults used early on boot */
-static struct threshold_block threshold_defaults = {
-	.interrupt_enable	= 0,
-	.threshold_limit	= THRESHOLD_MAX,
-};
-
-struct threshold_bank {
-	struct kobject		*kobj;
-	struct threshold_block	*blocks;
-	cpumask_var_t		cpus;
-};
-static DEFINE_PER_CPU(struct threshold_bank *, threshold_banks[NR_BANKS]);
-
-#ifdef CONFIG_SMP
-static unsigned char shared_bank[NR_BANKS] = {
-	0, 0, 0, 0, 1
-};
-#endif
-
-static DEFINE_PER_CPU(unsigned char, bank_map);	/* see which banks are on */
-
-static void amd_threshold_interrupt(void);
-
-/*
- * CPU Initialization
- */
-
-struct thresh_restart {
-	struct threshold_block	*b;
-	int			reset;
-	u16			old_limit;
-};
-
-/* must be called with correct cpu affinity */
-/* Called via smp_call_function_single() */
-static void threshold_restart_bank(void *_tr)
-{
-	struct thresh_restart *tr = _tr;
-	u32 mci_misc_hi, mci_misc_lo;
-
-	rdmsr(tr->b->address, mci_misc_lo, mci_misc_hi);
-
-	if (tr->b->threshold_limit < (mci_misc_hi & THRESHOLD_MAX))
-		tr->reset = 1;	/* limit cannot be lower than err count */
-
-	if (tr->reset) {		/* reset err count and overflow bit */
-		mci_misc_hi =
-		    (mci_misc_hi & ~(MASK_ERR_COUNT_HI | MASK_OVERFLOW_HI)) |
-		    (THRESHOLD_MAX - tr->b->threshold_limit);
-	} else if (tr->old_limit) {	/* change limit w/o reset */
-		int new_count = (mci_misc_hi & THRESHOLD_MAX) +
-		    (tr->old_limit - tr->b->threshold_limit);
-
-		mci_misc_hi = (mci_misc_hi & ~MASK_ERR_COUNT_HI) |
-		    (new_count & THRESHOLD_MAX);
-	}
-
-	tr->b->interrupt_enable ?
-	    (mci_misc_hi = (mci_misc_hi & ~MASK_INT_TYPE_HI) | INT_TYPE_APIC) :
-	    (mci_misc_hi &= ~MASK_INT_TYPE_HI);
-
-	mci_misc_hi |= MASK_COUNT_EN_HI;
-	wrmsr(tr->b->address, mci_misc_lo, mci_misc_hi);
-}
-
-/* cpu init entry point, called from mce.c with preempt off */
-void mce_amd_feature_init(struct cpuinfo_x86 *c)
-{
-	unsigned int cpu = smp_processor_id();
-	u32 low = 0, high = 0, address = 0;
-	unsigned int bank, block;
-	struct thresh_restart tr;
-	u8 lvt_off;
-
-	for (bank = 0; bank < NR_BANKS; ++bank) {
-		for (block = 0; block < NR_BLOCKS; ++block) {
-			if (block == 0)
-				address = MSR_IA32_MC0_MISC + bank * 4;
-			else if (block == 1) {
-				address = (low & MASK_BLKPTR_LO) >> 21;
-				if (!address)
-					break;
-				address += MCG_XBLK_ADDR;
-			} else
-				++address;
-
-			if (rdmsr_safe(address, &low, &high))
-				break;
-
-			if (!(high & MASK_VALID_HI)) {
-				if (block)
-					continue;
-				else
-					break;
-			}
-
-			if (!(high & MASK_CNTP_HI)  ||
-			     (high & MASK_LOCKED_HI))
-				continue;
-
-			if (!block)
-				per_cpu(bank_map, cpu) |= (1 << bank);
-#ifdef CONFIG_SMP
-			if (shared_bank[bank] && c->cpu_core_id)
-				break;
-#endif
-			lvt_off = setup_APIC_eilvt_mce(THRESHOLD_APIC_VECTOR,
-						       APIC_EILVT_MSG_FIX, 0);
-
-			high &= ~MASK_LVTOFF_HI;
-			high |= lvt_off << 20;
-			wrmsr(address, low, high);
-
-			threshold_defaults.address = address;
-			tr.b = &threshold_defaults;
-			tr.reset = 0;
-			tr.old_limit = 0;
-			threshold_restart_bank(&tr);
-
-			mce_threshold_vector = amd_threshold_interrupt;
-		}
-	}
-}
-
-/*
- * APIC Interrupt Handler
- */
-
-/*
- * threshold interrupt handler will service THRESHOLD_APIC_VECTOR.
- * the interrupt goes off when error_count reaches threshold_limit.
- * the handler will simply log mcelog w/ software defined bank number.
- */
-static void amd_threshold_interrupt(void)
-{
-	u32 low = 0, high = 0, address = 0;
-	unsigned int bank, block;
-	struct mce m;
-
-	mce_setup(&m);
-
-	/* assume first bank caused it */
-	for (bank = 0; bank < NR_BANKS; ++bank) {
-		if (!(per_cpu(bank_map, m.cpu) & (1 << bank)))
-			continue;
-		for (block = 0; block < NR_BLOCKS; ++block) {
-			if (block == 0) {
-				address = MSR_IA32_MC0_MISC + bank * 4;
-			} else if (block == 1) {
-				address = (low & MASK_BLKPTR_LO) >> 21;
-				if (!address)
-					break;
-				address += MCG_XBLK_ADDR;
-			} else {
-				++address;
-			}
-
-			if (rdmsr_safe(address, &low, &high))
-				break;
-
-			if (!(high & MASK_VALID_HI)) {
-				if (block)
-					continue;
-				else
-					break;
-			}
-
-			if (!(high & MASK_CNTP_HI)  ||
-			     (high & MASK_LOCKED_HI))
-				continue;
-
-			/*
-			 * Log the machine check that caused the threshold
-			 * event.
-			 */
-			machine_check_poll(MCP_TIMESTAMP,
-					&__get_cpu_var(mce_poll_banks));
-
-			if (high & MASK_OVERFLOW_HI) {
-				rdmsrl(address, m.misc);
-				rdmsrl(MSR_IA32_MC0_STATUS + bank * 4,
-				       m.status);
-				m.bank = K8_MCE_THRESHOLD_BASE
-				       + bank * NR_BLOCKS
-				       + block;
-				mce_log(&m);
-				return;
-			}
-		}
-	}
-}
-
-/*
- * Sysfs Interface
- */
-
-struct threshold_attr {
-	struct attribute attr;
-	ssize_t (*show) (struct threshold_block *, char *);
-	ssize_t (*store) (struct threshold_block *, const char *, size_t count);
-};
-
-#define SHOW_FIELDS(name)						\
-static ssize_t show_ ## name(struct threshold_block *b, char *buf)	\
-{									\
-	return sprintf(buf, "%lx\n", (unsigned long) b->name);		\
-}
-SHOW_FIELDS(interrupt_enable)
-SHOW_FIELDS(threshold_limit)
-
-static ssize_t
-store_interrupt_enable(struct threshold_block *b, const char *buf, size_t size)
-{
-	struct thresh_restart tr;
-	unsigned long new;
-
-	if (strict_strtoul(buf, 0, &new) < 0)
-		return -EINVAL;
-
-	b->interrupt_enable = !!new;
-
-	tr.b		= b;
-	tr.reset	= 0;
-	tr.old_limit	= 0;
-
-	smp_call_function_single(b->cpu, threshold_restart_bank, &tr, 1);
-
-	return size;
-}
-
-static ssize_t
-store_threshold_limit(struct threshold_block *b, const char *buf, size_t size)
-{
-	struct thresh_restart tr;
-	unsigned long new;
-
-	if (strict_strtoul(buf, 0, &new) < 0)
-		return -EINVAL;
-
-	if (new > THRESHOLD_MAX)
-		new = THRESHOLD_MAX;
-	if (new < 1)
-		new = 1;
-
-	tr.old_limit = b->threshold_limit;
-	b->threshold_limit = new;
-	tr.b = b;
-	tr.reset = 0;
-
-	smp_call_function_single(b->cpu, threshold_restart_bank, &tr, 1);
-
-	return size;
-}
-
-struct threshold_block_cross_cpu {
-	struct threshold_block	*tb;
-	long			retval;
-};
-
-static void local_error_count_handler(void *_tbcc)
-{
-	struct threshold_block_cross_cpu *tbcc = _tbcc;
-	struct threshold_block *b = tbcc->tb;
-	u32 low, high;
-
-	rdmsr(b->address, low, high);
-	tbcc->retval = (high & 0xFFF) - (THRESHOLD_MAX - b->threshold_limit);
-}
-
-static ssize_t show_error_count(struct threshold_block *b, char *buf)
-{
-	struct threshold_block_cross_cpu tbcc = { .tb = b, };
-
-	smp_call_function_single(b->cpu, local_error_count_handler, &tbcc, 1);
-	return sprintf(buf, "%lx\n", tbcc.retval);
-}
-
-static ssize_t store_error_count(struct threshold_block *b,
-				 const char *buf, size_t count)
-{
-	struct thresh_restart tr = { .b = b, .reset = 1, .old_limit = 0 };
-
-	smp_call_function_single(b->cpu, threshold_restart_bank, &tr, 1);
-	return 1;
-}
-
-#define RW_ATTR(val)							\
-static struct threshold_attr val = {					\
-	.attr	= {.name = __stringify(val), .mode = 0644 },		\
-	.show	= show_## val,						\
-	.store	= store_## val,						\
-};
-
-RW_ATTR(interrupt_enable);
-RW_ATTR(threshold_limit);
-RW_ATTR(error_count);
-
-static struct attribute *default_attrs[] = {
-	&interrupt_enable.attr,
-	&threshold_limit.attr,
-	&error_count.attr,
-	NULL
-};
-
-#define to_block(k)	container_of(k, struct threshold_block, kobj)
-#define to_attr(a)	container_of(a, struct threshold_attr, attr)
-
-static ssize_t show(struct kobject *kobj, struct attribute *attr, char *buf)
-{
-	struct threshold_block *b = to_block(kobj);
-	struct threshold_attr *a = to_attr(attr);
-	ssize_t ret;
-
-	ret = a->show ? a->show(b, buf) : -EIO;
-
-	return ret;
-}
-
-static ssize_t store(struct kobject *kobj, struct attribute *attr,
-		     const char *buf, size_t count)
-{
-	struct threshold_block *b = to_block(kobj);
-	struct threshold_attr *a = to_attr(attr);
-	ssize_t ret;
-
-	ret = a->store ? a->store(b, buf, count) : -EIO;
-
-	return ret;
-}
-
-static struct sysfs_ops threshold_ops = {
-	.show			= show,
-	.store			= store,
-};
-
-static struct kobj_type threshold_ktype = {
-	.sysfs_ops		= &threshold_ops,
-	.default_attrs		= default_attrs,
-};
-
-static __cpuinit int allocate_threshold_blocks(unsigned int cpu,
-					       unsigned int bank,
-					       unsigned int block,
-					       u32 address)
-{
-	struct threshold_block *b = NULL;
-	u32 low, high;
-	int err;
-
-	if ((bank >= NR_BANKS) || (block >= NR_BLOCKS))
-		return 0;
-
-	if (rdmsr_safe_on_cpu(cpu, address, &low, &high))
-		return 0;
-
-	if (!(high & MASK_VALID_HI)) {
-		if (block)
-			goto recurse;
-		else
-			return 0;
-	}
-
-	if (!(high & MASK_CNTP_HI)  ||
-	     (high & MASK_LOCKED_HI))
-		goto recurse;
-
-	b = kzalloc(sizeof(struct threshold_block), GFP_KERNEL);
-	if (!b)
-		return -ENOMEM;
-
-	b->block		= block;
-	b->bank			= bank;
-	b->cpu			= cpu;
-	b->address		= address;
-	b->interrupt_enable	= 0;
-	b->threshold_limit	= THRESHOLD_MAX;
-
-	INIT_LIST_HEAD(&b->miscj);
-
-	if (per_cpu(threshold_banks, cpu)[bank]->blocks) {
-		list_add(&b->miscj,
-			 &per_cpu(threshold_banks, cpu)[bank]->blocks->miscj);
-	} else {
-		per_cpu(threshold_banks, cpu)[bank]->blocks = b;
-	}
-
-	err = kobject_init_and_add(&b->kobj, &threshold_ktype,
-				   per_cpu(threshold_banks, cpu)[bank]->kobj,
-				   "misc%i", block);
-	if (err)
-		goto out_free;
-recurse:
-	if (!block) {
-		address = (low & MASK_BLKPTR_LO) >> 21;
-		if (!address)
-			return 0;
-		address += MCG_XBLK_ADDR;
-	} else {
-		++address;
-	}
-
-	err = allocate_threshold_blocks(cpu, bank, ++block, address);
-	if (err)
-		goto out_free;
-
-	if (b)
-		kobject_uevent(&b->kobj, KOBJ_ADD);
-
-	return err;
-
-out_free:
-	if (b) {
-		kobject_put(&b->kobj);
-		kfree(b);
-	}
-	return err;
-}
-
-static __cpuinit long
-local_allocate_threshold_blocks(int cpu, unsigned int bank)
-{
-	return allocate_threshold_blocks(cpu, bank, 0,
-					 MSR_IA32_MC0_MISC + bank * 4);
-}
-
-/* symlinks sibling shared banks to first core.  first core owns dir/files. */
-static __cpuinit int threshold_create_bank(unsigned int cpu, unsigned int bank)
-{
-	int i, err = 0;
-	struct threshold_bank *b = NULL;
-	char name[32];
-
-	sprintf(name, "threshold_bank%i", bank);
-
-#ifdef CONFIG_SMP
-	if (cpu_data(cpu).cpu_core_id && shared_bank[bank]) {	/* symlink */
-		i = cpumask_first(cpu_core_mask(cpu));
-
-		/* first core not up yet */
-		if (cpu_data(i).cpu_core_id)
-			goto out;
-
-		/* already linked */
-		if (per_cpu(threshold_banks, cpu)[bank])
-			goto out;
-
-		b = per_cpu(threshold_banks, i)[bank];
-
-		if (!b)
-			goto out;
-
-		err = sysfs_create_link(&per_cpu(mce_dev, cpu).kobj,
-					b->kobj, name);
-		if (err)
-			goto out;
-
-		cpumask_copy(b->cpus, cpu_core_mask(cpu));
-		per_cpu(threshold_banks, cpu)[bank] = b;
-
-		goto out;
-	}
-#endif
-
-	b = kzalloc(sizeof(struct threshold_bank), GFP_KERNEL);
-	if (!b) {
-		err = -ENOMEM;
-		goto out;
-	}
-	if (!alloc_cpumask_var(&b->cpus, GFP_KERNEL)) {
-		kfree(b);
-		err = -ENOMEM;
-		goto out;
-	}
-
-	b->kobj = kobject_create_and_add(name, &per_cpu(mce_dev, cpu).kobj);
-	if (!b->kobj)
-		goto out_free;
-
-#ifndef CONFIG_SMP
-	cpumask_setall(b->cpus);
-#else
-	cpumask_copy(b->cpus, cpu_core_mask(cpu));
-#endif
-
-	per_cpu(threshold_banks, cpu)[bank] = b;
-
-	err = local_allocate_threshold_blocks(cpu, bank);
-	if (err)
-		goto out_free;
-
-	for_each_cpu(i, b->cpus) {
-		if (i == cpu)
-			continue;
-
-		err = sysfs_create_link(&per_cpu(mce_dev, i).kobj,
-					b->kobj, name);
-		if (err)
-			goto out;
-
-		per_cpu(threshold_banks, i)[bank] = b;
-	}
-
-	goto out;
-
-out_free:
-	per_cpu(threshold_banks, cpu)[bank] = NULL;
-	free_cpumask_var(b->cpus);
-	kfree(b);
-out:
-	return err;
-}
-
-/* create dir/files for all valid threshold banks */
-static __cpuinit int threshold_create_device(unsigned int cpu)
-{
-	unsigned int bank;
-	int err = 0;
-
-	for (bank = 0; bank < NR_BANKS; ++bank) {
-		if (!(per_cpu(bank_map, cpu) & (1 << bank)))
-			continue;
-		err = threshold_create_bank(cpu, bank);
-		if (err)
-			goto out;
-	}
-out:
-	return err;
-}
-
-/*
- * let's be hotplug friendly.
- * in case of multiple core processors, the first core always takes ownership
- *   of shared sysfs dir/files, and rest of the cores will be symlinked to it.
- */
-
-static void deallocate_threshold_block(unsigned int cpu,
-						 unsigned int bank)
-{
-	struct threshold_block *pos = NULL;
-	struct threshold_block *tmp = NULL;
-	struct threshold_bank *head = per_cpu(threshold_banks, cpu)[bank];
-
-	if (!head)
-		return;
-
-	list_for_each_entry_safe(pos, tmp, &head->blocks->miscj, miscj) {
-		kobject_put(&pos->kobj);
-		list_del(&pos->miscj);
-		kfree(pos);
-	}
-
-	kfree(per_cpu(threshold_banks, cpu)[bank]->blocks);
-	per_cpu(threshold_banks, cpu)[bank]->blocks = NULL;
-}
-
-static void threshold_remove_bank(unsigned int cpu, int bank)
-{
-	struct threshold_bank *b;
-	char name[32];
-	int i = 0;
-
-	b = per_cpu(threshold_banks, cpu)[bank];
-	if (!b)
-		return;
-	if (!b->blocks)
-		goto free_out;
-
-	sprintf(name, "threshold_bank%i", bank);
-
-#ifdef CONFIG_SMP
-	/* sibling symlink */
-	if (shared_bank[bank] && b->blocks->cpu != cpu) {
-		sysfs_remove_link(&per_cpu(mce_dev, cpu).kobj, name);
-		per_cpu(threshold_banks, cpu)[bank] = NULL;
-
-		return;
-	}
-#endif
-
-	/* remove all sibling symlinks before unregistering */
-	for_each_cpu(i, b->cpus) {
-		if (i == cpu)
-			continue;
-
-		sysfs_remove_link(&per_cpu(mce_dev, i).kobj, name);
-		per_cpu(threshold_banks, i)[bank] = NULL;
-	}
-
-	deallocate_threshold_block(cpu, bank);
-
-free_out:
-	kobject_del(b->kobj);
-	kobject_put(b->kobj);
-	free_cpumask_var(b->cpus);
-	kfree(b);
-	per_cpu(threshold_banks, cpu)[bank] = NULL;
-}
-
-static void threshold_remove_device(unsigned int cpu)
-{
-	unsigned int bank;
-
-	for (bank = 0; bank < NR_BANKS; ++bank) {
-		if (!(per_cpu(bank_map, cpu) & (1 << bank)))
-			continue;
-		threshold_remove_bank(cpu, bank);
-	}
-}
-
-/* get notified when a cpu comes on/off */
-static void __cpuinit
-amd_64_threshold_cpu_callback(unsigned long action, unsigned int cpu)
-{
-	switch (action) {
-	case CPU_ONLINE:
-	case CPU_ONLINE_FROZEN:
-		threshold_create_device(cpu);
-		break;
-	case CPU_DEAD:
-	case CPU_DEAD_FROZEN:
-		threshold_remove_device(cpu);
-		break;
-	default:
-		break;
-	}
-}
-
-static __init int threshold_init_device(void)
-{
-	unsigned lcpu = 0;
-
-	/* to hit CPUs online before the notifier is up */
-	for_each_online_cpu(lcpu) {
-		int err = threshold_create_device(lcpu);
-
-		if (err)
-			return err;
-	}
-	threshold_cpu_callback = amd_64_threshold_cpu_callback;
-
-	return 0;
-}
-device_initcall(threshold_init_device);
diff --git a/arch/x86/kernel/cpu/mcheck/mce_intel.c b/arch/x86/kernel/cpu/mcheck/mce_intel.c
new file mode 100644
index 0000000..663a88e
--- /dev/null
+++ b/arch/x86/kernel/cpu/mcheck/mce_intel.c
@@ -0,0 +1,225 @@
+/*
+ * Intel specific MCE features.
+ * Copyright 2004 Zwane Mwaikambo <zwane@linuxpower.ca>
+ * Copyright (C) 2008, 2009 Intel Corporation
+ * Author: Andi Kleen
+ */
+
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/percpu.h>
+#include <asm/processor.h>
+#include <asm/msr.h>
+#include <asm/mce.h>
+
+/*
+ * Support for Intel Correct Machine Check Interrupts. This allows
+ * the CPU to raise an interrupt when a corrected machine check happened.
+ * Normally we pick those up using a regular polling timer.
+ * Also supports reliable discovery of shared banks.
+ */
+
+static DEFINE_PER_CPU(mce_banks_t, mce_banks_owned);
+
+/*
+ * cmci_discover_lock protects against parallel discovery attempts
+ * which could race against each other.
+ */
+static DEFINE_SPINLOCK(cmci_discover_lock);
+
+#define CMCI_THRESHOLD 1
+
+static int cmci_supported(int *banks)
+{
+	u64 cap;
+
+	if (mce_cmci_disabled || mce_ignore_ce)
+		return 0;
+
+	/*
+	 * Vendor check is not strictly needed, but the initial
+	 * initialization is vendor keyed and this
+	 * makes sure none of the backdoors are entered otherwise.
+	 */
+	if (boot_cpu_data.x86_vendor != X86_VENDOR_INTEL)
+		return 0;
+	if (!cpu_has_apic || lapic_get_maxlvt() < 6)
+		return 0;
+	rdmsrl(MSR_IA32_MCG_CAP, cap);
+	*banks = min_t(unsigned, MAX_NR_BANKS, cap & 0xff);
+	return !!(cap & MCG_CMCI_P);
+}
+
+/*
+ * The interrupt handler. This is called on every event.
+ * Just call the poller directly to log any events.
+ * This could in theory increase the threshold under high load,
+ * but doesn't for now.
+ */
+static void intel_threshold_interrupt(void)
+{
+	machine_check_poll(MCP_TIMESTAMP, &__get_cpu_var(mce_banks_owned));
+	mce_notify_irq();
+}
+
+static void print_update(char *type, int *hdr, int num)
+{
+	if (*hdr == 0)
+		printk(KERN_INFO "CPU %d MCA banks", smp_processor_id());
+	*hdr = 1;
+	printk(KERN_CONT " %s:%d", type, num);
+}
+
+/*
+ * Enable CMCI (Corrected Machine Check Interrupt) for available MCE banks
+ * on this CPU. Use the algorithm recommended in the SDM to discover shared
+ * banks.
+ */
+static void cmci_discover(int banks, int boot)
+{
+	unsigned long *owned = (void *)&__get_cpu_var(mce_banks_owned);
+	unsigned long flags;
+	int hdr = 0;
+	int i;
+
+	spin_lock_irqsave(&cmci_discover_lock, flags);
+	for (i = 0; i < banks; i++) {
+		u64 val;
+
+		if (test_bit(i, owned))
+			continue;
+
+		rdmsrl(MSR_IA32_MC0_CTL2 + i, val);
+
+		/* Already owned by someone else? */
+		if (val & CMCI_EN) {
+			if (test_and_clear_bit(i, owned) || boot)
+				print_update("SHD", &hdr, i);
+			__clear_bit(i, __get_cpu_var(mce_poll_banks));
+			continue;
+		}
+
+		val |= CMCI_EN | CMCI_THRESHOLD;
+		wrmsrl(MSR_IA32_MC0_CTL2 + i, val);
+		rdmsrl(MSR_IA32_MC0_CTL2 + i, val);
+
+		/* Did the enable bit stick? -- the bank supports CMCI */
+		if (val & CMCI_EN) {
+			if (!test_and_set_bit(i, owned) || boot)
+				print_update("CMCI", &hdr, i);
+			__clear_bit(i, __get_cpu_var(mce_poll_banks));
+		} else {
+			WARN_ON(!test_bit(i, __get_cpu_var(mce_poll_banks)));
+		}
+	}
+	spin_unlock_irqrestore(&cmci_discover_lock, flags);
+	if (hdr)
+		printk(KERN_CONT "\n");
+}
+
+/*
+ * Just in case we missed an event during initialization check
+ * all the CMCI owned banks.
+ */
+void cmci_recheck(void)
+{
+	unsigned long flags;
+	int banks;
+
+	if (!mce_available(&current_cpu_data) || !cmci_supported(&banks))
+		return;
+	local_irq_save(flags);
+	machine_check_poll(MCP_TIMESTAMP, &__get_cpu_var(mce_banks_owned));
+	local_irq_restore(flags);
+}
+
+/*
+ * Disable CMCI on this CPU for all banks it owns when it goes down.
+ * This allows other CPUs to claim the banks on rediscovery.
+ */
+void cmci_clear(void)
+{
+	unsigned long flags;
+	int i;
+	int banks;
+	u64 val;
+
+	if (!cmci_supported(&banks))
+		return;
+	spin_lock_irqsave(&cmci_discover_lock, flags);
+	for (i = 0; i < banks; i++) {
+		if (!test_bit(i, __get_cpu_var(mce_banks_owned)))
+			continue;
+		/* Disable CMCI */
+		rdmsrl(MSR_IA32_MC0_CTL2 + i, val);
+		val &= ~(CMCI_EN|CMCI_THRESHOLD_MASK);
+		wrmsrl(MSR_IA32_MC0_CTL2 + i, val);
+		__clear_bit(i, __get_cpu_var(mce_banks_owned));
+	}
+	spin_unlock_irqrestore(&cmci_discover_lock, flags);
+}
+
+/*
+ * After a CPU went down cycle through all the others and rediscover
+ * Must run in process context.
+ */
+void cmci_rediscover(int dying)
+{
+	int banks;
+	int cpu;
+	cpumask_var_t old;
+
+	if (!cmci_supported(&banks))
+		return;
+	if (!alloc_cpumask_var(&old, GFP_KERNEL))
+		return;
+	cpumask_copy(old, &current->cpus_allowed);
+
+	for_each_online_cpu(cpu) {
+		if (cpu == dying)
+			continue;
+		if (set_cpus_allowed_ptr(current, cpumask_of(cpu)))
+			continue;
+		/* Recheck banks in case CPUs don't all have the same */
+		if (cmci_supported(&banks))
+			cmci_discover(banks, 0);
+	}
+
+	set_cpus_allowed_ptr(current, old);
+	free_cpumask_var(old);
+}
+
+/*
+ * Reenable CMCI on this CPU in case a CPU down failed.
+ */
+void cmci_reenable(void)
+{
+	int banks;
+	if (cmci_supported(&banks))
+		cmci_discover(banks, 0);
+}
+
+static void intel_init_cmci(void)
+{
+	int banks;
+
+	if (!cmci_supported(&banks))
+		return;
+
+	mce_threshold_vector = intel_threshold_interrupt;
+	cmci_discover(banks, 1);
+	/*
+	 * For CPU #0 this runs with still disabled APIC, but that's
+	 * ok because only the vector is set up. We still do another
+	 * check for the banks later for CPU #0 just to make sure
+	 * to not miss any events.
+	 */
+	apic_write(APIC_LVTCMCI, THRESHOLD_APIC_VECTOR|APIC_DM_FIXED);
+	cmci_recheck();
+}
+
+void mce_intel_feature_init(struct cpuinfo_x86 *c)
+{
+	intel_init_thermal(c);
+	intel_init_cmci();
+}
diff --git a/arch/x86/kernel/cpu/mcheck/mce_intel_64.c b/arch/x86/kernel/cpu/mcheck/mce_intel_64.c
deleted file mode 100644
index 663a88e..0000000
--- a/arch/x86/kernel/cpu/mcheck/mce_intel_64.c
+++ /dev/null
@@ -1,225 +0,0 @@
-/*
- * Intel specific MCE features.
- * Copyright 2004 Zwane Mwaikambo <zwane@linuxpower.ca>
- * Copyright (C) 2008, 2009 Intel Corporation
- * Author: Andi Kleen
- */
-
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/percpu.h>
-#include <asm/processor.h>
-#include <asm/msr.h>
-#include <asm/mce.h>
-
-/*
- * Support for Intel Correct Machine Check Interrupts. This allows
- * the CPU to raise an interrupt when a corrected machine check happened.
- * Normally we pick those up using a regular polling timer.
- * Also supports reliable discovery of shared banks.
- */
-
-static DEFINE_PER_CPU(mce_banks_t, mce_banks_owned);
-
-/*
- * cmci_discover_lock protects against parallel discovery attempts
- * which could race against each other.
- */
-static DEFINE_SPINLOCK(cmci_discover_lock);
-
-#define CMCI_THRESHOLD 1
-
-static int cmci_supported(int *banks)
-{
-	u64 cap;
-
-	if (mce_cmci_disabled || mce_ignore_ce)
-		return 0;
-
-	/*
-	 * Vendor check is not strictly needed, but the initial
-	 * initialization is vendor keyed and this
-	 * makes sure none of the backdoors are entered otherwise.
-	 */
-	if (boot_cpu_data.x86_vendor != X86_VENDOR_INTEL)
-		return 0;
-	if (!cpu_has_apic || lapic_get_maxlvt() < 6)
-		return 0;
-	rdmsrl(MSR_IA32_MCG_CAP, cap);
-	*banks = min_t(unsigned, MAX_NR_BANKS, cap & 0xff);
-	return !!(cap & MCG_CMCI_P);
-}
-
-/*
- * The interrupt handler. This is called on every event.
- * Just call the poller directly to log any events.
- * This could in theory increase the threshold under high load,
- * but doesn't for now.
- */
-static void intel_threshold_interrupt(void)
-{
-	machine_check_poll(MCP_TIMESTAMP, &__get_cpu_var(mce_banks_owned));
-	mce_notify_irq();
-}
-
-static void print_update(char *type, int *hdr, int num)
-{
-	if (*hdr == 0)
-		printk(KERN_INFO "CPU %d MCA banks", smp_processor_id());
-	*hdr = 1;
-	printk(KERN_CONT " %s:%d", type, num);
-}
-
-/*
- * Enable CMCI (Corrected Machine Check Interrupt) for available MCE banks
- * on this CPU. Use the algorithm recommended in the SDM to discover shared
- * banks.
- */
-static void cmci_discover(int banks, int boot)
-{
-	unsigned long *owned = (void *)&__get_cpu_var(mce_banks_owned);
-	unsigned long flags;
-	int hdr = 0;
-	int i;
-
-	spin_lock_irqsave(&cmci_discover_lock, flags);
-	for (i = 0; i < banks; i++) {
-		u64 val;
-
-		if (test_bit(i, owned))
-			continue;
-
-		rdmsrl(MSR_IA32_MC0_CTL2 + i, val);
-
-		/* Already owned by someone else? */
-		if (val & CMCI_EN) {
-			if (test_and_clear_bit(i, owned) || boot)
-				print_update("SHD", &hdr, i);
-			__clear_bit(i, __get_cpu_var(mce_poll_banks));
-			continue;
-		}
-
-		val |= CMCI_EN | CMCI_THRESHOLD;
-		wrmsrl(MSR_IA32_MC0_CTL2 + i, val);
-		rdmsrl(MSR_IA32_MC0_CTL2 + i, val);
-
-		/* Did the enable bit stick? -- the bank supports CMCI */
-		if (val & CMCI_EN) {
-			if (!test_and_set_bit(i, owned) || boot)
-				print_update("CMCI", &hdr, i);
-			__clear_bit(i, __get_cpu_var(mce_poll_banks));
-		} else {
-			WARN_ON(!test_bit(i, __get_cpu_var(mce_poll_banks)));
-		}
-	}
-	spin_unlock_irqrestore(&cmci_discover_lock, flags);
-	if (hdr)
-		printk(KERN_CONT "\n");
-}
-
-/*
- * Just in case we missed an event during initialization check
- * all the CMCI owned banks.
- */
-void cmci_recheck(void)
-{
-	unsigned long flags;
-	int banks;
-
-	if (!mce_available(&current_cpu_data) || !cmci_supported(&banks))
-		return;
-	local_irq_save(flags);
-	machine_check_poll(MCP_TIMESTAMP, &__get_cpu_var(mce_banks_owned));
-	local_irq_restore(flags);
-}
-
-/*
- * Disable CMCI on this CPU for all banks it owns when it goes down.
- * This allows other CPUs to claim the banks on rediscovery.
- */
-void cmci_clear(void)
-{
-	unsigned long flags;
-	int i;
-	int banks;
-	u64 val;
-
-	if (!cmci_supported(&banks))
-		return;
-	spin_lock_irqsave(&cmci_discover_lock, flags);
-	for (i = 0; i < banks; i++) {
-		if (!test_bit(i, __get_cpu_var(mce_banks_owned)))
-			continue;
-		/* Disable CMCI */
-		rdmsrl(MSR_IA32_MC0_CTL2 + i, val);
-		val &= ~(CMCI_EN|CMCI_THRESHOLD_MASK);
-		wrmsrl(MSR_IA32_MC0_CTL2 + i, val);
-		__clear_bit(i, __get_cpu_var(mce_banks_owned));
-	}
-	spin_unlock_irqrestore(&cmci_discover_lock, flags);
-}
-
-/*
- * After a CPU went down cycle through all the others and rediscover
- * Must run in process context.
- */
-void cmci_rediscover(int dying)
-{
-	int banks;
-	int cpu;
-	cpumask_var_t old;
-
-	if (!cmci_supported(&banks))
-		return;
-	if (!alloc_cpumask_var(&old, GFP_KERNEL))
-		return;
-	cpumask_copy(old, &current->cpus_allowed);
-
-	for_each_online_cpu(cpu) {
-		if (cpu == dying)
-			continue;
-		if (set_cpus_allowed_ptr(current, cpumask_of(cpu)))
-			continue;
-		/* Recheck banks in case CPUs don't all have the same */
-		if (cmci_supported(&banks))
-			cmci_discover(banks, 0);
-	}
-
-	set_cpus_allowed_ptr(current, old);
-	free_cpumask_var(old);
-}
-
-/*
- * Reenable CMCI on this CPU in case a CPU down failed.
- */
-void cmci_reenable(void)
-{
-	int banks;
-	if (cmci_supported(&banks))
-		cmci_discover(banks, 0);
-}
-
-static void intel_init_cmci(void)
-{
-	int banks;
-
-	if (!cmci_supported(&banks))
-		return;
-
-	mce_threshold_vector = intel_threshold_interrupt;
-	cmci_discover(banks, 1);
-	/*
-	 * For CPU #0 this runs with still disabled APIC, but that's
-	 * ok because only the vector is set up. We still do another
-	 * check for the banks later for CPU #0 just to make sure
-	 * to not miss any events.
-	 */
-	apic_write(APIC_LVTCMCI, THRESHOLD_APIC_VECTOR|APIC_DM_FIXED);
-	cmci_recheck();
-}
-
-void mce_intel_feature_init(struct cpuinfo_x86 *c)
-{
-	intel_init_thermal(c);
-	intel_init_cmci();
-}
-- 
1.6.3



^ permalink raw reply related	[flat|nested] 25+ messages in thread

* Re: [PATCH 02/16] x86, mce: call-in should be after updating  global_nwo
  2009-06-15  8:26   ` huang ying
@ 2009-06-15  8:40     ` Hidetoshi Seto
  2009-06-15  9:18     ` [PATCH] x86, mce: cleanup mce_start() Hidetoshi Seto
  1 sibling, 0 replies; 25+ messages in thread
From: Hidetoshi Seto @ 2009-06-15  8:40 UTC (permalink / raw)
  To: huang ying
  Cc: linux-kernel, Ingo Molnar, H. Peter Anvin, Thomas Gleixner,
	Andi Kleen, Huang Ying

huang ying wrote:
> 2009/6/15 Hidetoshi Seto <seto.hidetoshi@jp.fujitsu.com>:
>> At the beginning of Monarch synchronization, processors wait until
>> all of them have entered the exception handler and then check the
>> global_nwo to determine if any of them saw a fatal event.
>>
>> However since current code does call-in before updating global_nwo,
>> it might happen that the global_nwo does not reflect some of local
>> nwo at the time.  This might break printing corrected errors not
>> handled yet on panic.
> 
> This is almost same as the patch that I just posted. I think this is
> because it trigger a failure in mce-test suite, and we both find the
> failure.

That's right.

> But your patch lacks memory barrier between mce_callin and global_nwo
> updating/reading. Atomic operations does not imply memory barrier.

You are right.  I agree that your patch is better fix.

It seems my patch includes cleanup for mce_start(), so I'll extract it
and make another patch soon.


Thanks,
H.Seto


^ permalink raw reply	[flat|nested] 25+ messages in thread

* [PATCH] x86, mce: cleanup mce_start()
  2009-06-15  8:26   ` huang ying
  2009-06-15  8:40     ` Hidetoshi Seto
@ 2009-06-15  9:18     ` Hidetoshi Seto
  1 sibling, 0 replies; 25+ messages in thread
From: Hidetoshi Seto @ 2009-06-15  9:18 UTC (permalink / raw)
  To: huang ying
  Cc: linux-kernel, Ingo Molnar, H. Peter Anvin, Thomas Gleixner,
	Andi Kleen, Huang Ying

[ my 02/16 should be replaced by combination of Huang's fix and this cleanup ]

Simplify interface of mce_start().

-       no_way_out = mce_start(no_way_out, &order);
+       order = mce_start(&no_way_out);

Now Monarch and Subjects share same exit(return) in usual path.

Signed-off-by: Hidetoshi Seto <seto.hidetoshi@jp.fujitsu.com>
---
 arch/x86/kernel/cpu/mcheck/mce.c |   66 ++++++++++++++++++--------------------
 1 files changed, 31 insertions(+), 35 deletions(-)

diff --git a/arch/x86/kernel/cpu/mcheck/mce.c b/arch/x86/kernel/cpu/mcheck/mce.c
index dda7721..739fd7e 100644
--- a/arch/x86/kernel/cpu/mcheck/mce.c
+++ b/arch/x86/kernel/cpu/mcheck/mce.c
@@ -691,23 +691,21 @@ static atomic_t global_nwo;
  * in the entry order.
  * TBD double check parallel CPU hotunplug
  */
-static int mce_start(int no_way_out, int *order)
+static int mce_start(int *no_way_out)
 {
-	int nwo;
+	int order;
 	int cpus = num_online_cpus();
 	u64 timeout = (u64)monarch_timeout * NSEC_PER_USEC;
 
-	if (!timeout) {
-		*order = -1;
-		return no_way_out;
-	}
+	if (!timeout)
+		return -1;
 
-	atomic_add(no_way_out, &global_nwo);
+	atomic_add(*no_way_out, &global_nwo);
 	/*
 	 * global_nwo should be updated before mce_callin
 	 */
 	smp_wmb();
-	*order = atomic_add_return(1, &mce_callin);
+	order = atomic_add_return(1, &mce_callin);
 
 	/*
 	 * Wait for everyone.
@@ -715,8 +713,7 @@ static int mce_start(int no_way_out, int *order)
 	while (atomic_read(&mce_callin) != cpus) {
 		if (mce_timed_out(&timeout)) {
 			atomic_set(&global_nwo, 0);
-			*order = -1;
-			return no_way_out;
+			return -1;
 		}
 		ndelay(SPINUNIT);
 	}
@@ -725,34 +722,34 @@ static int mce_start(int no_way_out, int *order)
 	 * mce_callin should be read before global_nwo
 	 */
 	smp_rmb();
-	/*
-	 * Cache the global no_way_out state.
-	 */
-	nwo = atomic_read(&global_nwo);
 
-	/*
-	 * Monarch starts executing now, the others wait.
-	 */
-	if (*order == 1) {
+	if (order == 1) {
+		/*
+		 * Monarch: Starts executing now, the others wait.
+		 */
 		atomic_set(&mce_executing, 1);
-		return nwo;
+	} else {
+		/*
+		 * Subject: Now start the scanning loop one by one in
+		 * the original callin order.
+		 * This way when there are any shared banks it will be
+		 * only seen by one CPU before cleared, avoiding duplicates.
+		 */
+		while (atomic_read(&mce_executing) < order) {
+			if (mce_timed_out(&timeout)) {
+				atomic_set(&global_nwo, 0);
+				return -1;
+			}
+			ndelay(SPINUNIT);
+		}
 	}
 
 	/*
-	 * Now start the scanning loop one by one
-	 * in the original callin order.
-	 * This way when there are any shared banks it will
-	 * be only seen by one CPU before cleared, avoiding duplicates.
+	 * Cache the global no_way_out state.
 	 */
-	while (atomic_read(&mce_executing) < *order) {
-		if (mce_timed_out(&timeout)) {
-			atomic_set(&global_nwo, 0);
-			*order = -1;
-			return no_way_out;
-		}
-		ndelay(SPINUNIT);
-	}
-	return nwo;
+	*no_way_out = atomic_read(&global_nwo);
+
+	return order;
 }
 
 /*
@@ -871,8 +868,7 @@ void do_machine_check(struct pt_regs *regs, long error_code)
 	 * Establish sequential order between the CPUs entering the machine
 	 * check handler.
 	 */
-	int order = -1;
-
+	int order;
 	/*
 	 * If no_way_out gets set, there is no safe way to recover from this
 	 * MCE.  If tolerant is cranked up, we'll try anyway.
@@ -917,7 +913,7 @@ void do_machine_check(struct pt_regs *regs, long error_code)
 	 * This way we don't report duplicated events on shared banks
 	 * because the first one to see it will clear it.
 	 */
-	no_way_out = mce_start(no_way_out, &order);
+	order = mce_start(&no_way_out);
 	for (i = 0; i < banks; i++) {
 		__clear_bit(i, toclear);
 		if (!bank[i])
-- 
1.6.3


^ permalink raw reply related	[flat|nested] 25+ messages in thread

* Re: [PATCH 12/16] x86, mce: squash mce_intel.c into therm_throt.c
  2009-06-15  8:26 ` [PATCH 12/16] x86, mce: squash mce_intel.c into therm_throt.c Hidetoshi Seto
@ 2009-06-18  5:49   ` huang ying
  2009-06-18  7:31     ` Hidetoshi Seto
  2009-06-18 13:56     ` H. Peter Anvin
  0 siblings, 2 replies; 25+ messages in thread
From: huang ying @ 2009-06-18  5:49 UTC (permalink / raw)
  To: Hidetoshi Seto
  Cc: linux-kernel, Ingo Molnar, H. Peter Anvin, Thomas Gleixner, Andi Kleen

2009/6/15 Hidetoshi Seto <seto.hidetoshi@jp.fujitsu.com>:
> move intel_init_thermal() into therm_throt.c
>
> Signed-off-by: Hidetoshi Seto <seto.hidetoshi@jp.fujitsu.com>
> ---
>  arch/x86/kernel/cpu/mcheck/Makefile      |    2 +-
>  arch/x86/kernel/cpu/mcheck/mce_intel.c   |   73 ------------------------------
>  arch/x86/kernel/cpu/mcheck/therm_throt.c |   66 +++++++++++++++++++++++++++
>  3 files changed, 67 insertions(+), 74 deletions(-)
>  delete mode 100644 arch/x86/kernel/cpu/mcheck/mce_intel.c

Why we need this patch? I think the design principle behind MCE is to
separate vendor/cpu specific code into different files. At least
#ifdef CONFIG_X86_MCE_INTEL should be used around moved code.

Best Regards,
Huang Ying

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH 12/16] x86, mce: squash mce_intel.c into therm_throt.c
  2009-06-18  5:49   ` huang ying
@ 2009-06-18  7:31     ` Hidetoshi Seto
  2009-06-18  8:00       ` huang ying
  2009-06-18 13:56     ` H. Peter Anvin
  1 sibling, 1 reply; 25+ messages in thread
From: Hidetoshi Seto @ 2009-06-18  7:31 UTC (permalink / raw)
  To: huang ying
  Cc: linux-kernel, Ingo Molnar, H. Peter Anvin, Thomas Gleixner, Andi Kleen

huang ying wrote:
> 2009/6/15 Hidetoshi Seto <seto.hidetoshi@jp.fujitsu.com>:
>> move intel_init_thermal() into therm_throt.c
>>
>> Signed-off-by: Hidetoshi Seto <seto.hidetoshi@jp.fujitsu.com>
>> ---
>>  arch/x86/kernel/cpu/mcheck/Makefile      |    2 +-
>>  arch/x86/kernel/cpu/mcheck/mce_intel.c   |   73 ------------------------------
>>  arch/x86/kernel/cpu/mcheck/therm_throt.c |   66 +++++++++++++++++++++++++++
>>  3 files changed, 67 insertions(+), 74 deletions(-)
>>  delete mode 100644 arch/x86/kernel/cpu/mcheck/mce_intel.c
> 
> Why we need this patch? I think the design principle behind MCE is to
> separate vendor/cpu specific code into different files. At least
> #ifdef CONFIG_X86_MCE_INTEL should be used around moved code.

Because at this time there are no vendor other than Intel that uses
thermal codes here.  I don't know much about AMD, whether there are
any plan to implement AMD specific thermal codes or not, and why they
have to make such specific thing here in future (patent?).

You can pull out "codes may not be shared" from therm_throt.c and
put it again into mce_intel.c (that was mce_intel_64.c).  But I
believe it is not needed now, until another code is available.
Or you can rename therm_throt.c to thermal_intel.c or so for a while.

(BTW, now CONFIG_X86_MCE_INTEL enables both of cmci and thermal,
 are there possible option to disable thermal while cmci is on?)


Thanks.
H.Seto


^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH 12/16] x86, mce: squash mce_intel.c into therm_throt.c
  2009-06-18  7:31     ` Hidetoshi Seto
@ 2009-06-18  8:00       ` huang ying
  2009-06-18 13:59         ` H. Peter Anvin
  0 siblings, 1 reply; 25+ messages in thread
From: huang ying @ 2009-06-18  8:00 UTC (permalink / raw)
  To: Hidetoshi Seto
  Cc: linux-kernel, Ingo Molnar, H. Peter Anvin, Thomas Gleixner,
	Andi Kleen, Huang Ying

On Thu, Jun 18, 2009 at 3:31 PM, Hidetoshi
Seto<seto.hidetoshi@jp.fujitsu.com> wrote:
> huang ying wrote:
>> 2009/6/15 Hidetoshi Seto <seto.hidetoshi@jp.fujitsu.com>:
>>> move intel_init_thermal() into therm_throt.c
>>>
>>> Signed-off-by: Hidetoshi Seto <seto.hidetoshi@jp.fujitsu.com>
>>> ---
>>>  arch/x86/kernel/cpu/mcheck/Makefile      |    2 +-
>>>  arch/x86/kernel/cpu/mcheck/mce_intel.c   |   73 ------------------------------
>>>  arch/x86/kernel/cpu/mcheck/therm_throt.c |   66 +++++++++++++++++++++++++++
>>>  3 files changed, 67 insertions(+), 74 deletions(-)
>>>  delete mode 100644 arch/x86/kernel/cpu/mcheck/mce_intel.c
>>
>> Why we need this patch? I think the design principle behind MCE is to
>> separate vendor/cpu specific code into different files. At least
>> #ifdef CONFIG_X86_MCE_INTEL should be used around moved code.
>
> Because at this time there are no vendor other than Intel that uses
> thermal codes here.  I don't know much about AMD, whether there are
> any plan to implement AMD specific thermal codes or not, and why they
> have to make such specific thing here in future (patent?).
>
> You can pull out "codes may not be shared" from therm_throt.c and
> put it again into mce_intel.c (that was mce_intel_64.c).  But I
> believe it is not needed now, until another code is available.
> Or you can rename therm_throt.c to thermal_intel.c or so for a while.

I think thermal_intel.c is better.

Best Regards,
Huang Ying

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH 12/16] x86, mce: squash mce_intel.c into therm_throt.c
  2009-06-18  5:49   ` huang ying
  2009-06-18  7:31     ` Hidetoshi Seto
@ 2009-06-18 13:56     ` H. Peter Anvin
  1 sibling, 0 replies; 25+ messages in thread
From: H. Peter Anvin @ 2009-06-18 13:56 UTC (permalink / raw)
  To: huang ying
  Cc: Hidetoshi Seto, linux-kernel, Ingo Molnar, Thomas Gleixner, Andi Kleen

huang ying wrote:
> 2009/6/15 Hidetoshi Seto <seto.hidetoshi@jp.fujitsu.com>:
>> move intel_init_thermal() into therm_throt.c
>>
>> Signed-off-by: Hidetoshi Seto <seto.hidetoshi@jp.fujitsu.com>
>> ---
>>  arch/x86/kernel/cpu/mcheck/Makefile      |    2 +-
>>  arch/x86/kernel/cpu/mcheck/mce_intel.c   |   73 ------------------------------
>>  arch/x86/kernel/cpu/mcheck/therm_throt.c |   66 +++++++++++++++++++++++++++
>>  3 files changed, 67 insertions(+), 74 deletions(-)
>>  delete mode 100644 arch/x86/kernel/cpu/mcheck/mce_intel.c
> 
> Why we need this patch? I think the design principle behind MCE is to
> separate vendor/cpu specific code into different files. At least
> #ifdef CONFIG_X86_MCE_INTEL should be used around moved code.
> 

Honestly, such a design principle is pretty broken.  mce_intel.c
contained two completely orthogonal piece of functionality -- CMCI and
thermal -- that really should be in different files (and mce_intel.c
probably should be renamed cmci.c).  Furthermore, using #ifdef for
selecting specific code is considered less clean than using the Makefile
for this purpose.

	-hpa

-- 
H. Peter Anvin, Intel Open Source Technology Center
I work for Intel.  I don't speak on their behalf.


^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH 12/16] x86, mce: squash mce_intel.c into therm_throt.c
  2009-06-18  8:00       ` huang ying
@ 2009-06-18 13:59         ` H. Peter Anvin
  0 siblings, 0 replies; 25+ messages in thread
From: H. Peter Anvin @ 2009-06-18 13:59 UTC (permalink / raw)
  To: huang ying
  Cc: Hidetoshi Seto, linux-kernel, Ingo Molnar, Thomas Gleixner,
	Andi Kleen, Huang Ying

huang ying wrote:
>>
>> You can pull out "codes may not be shared" from therm_throt.c and
>> put it again into mce_intel.c (that was mce_intel_64.c).  But I
>> believe it is not needed now, until another code is available.
>> Or you can rename therm_throt.c to thermal_intel.c or so for a while.
> 
> I think thermal_intel.c is better.
> 

Actually intel_thermal.c and intel_cmci.c would probably be the right
naming.  The mce_ prefix for files in this directory is redundant; so
for vendor-specific features the vendor is the higher order organizing
factor.

	-hpa

-- 
H. Peter Anvin, Intel Open Source Technology Center
I work for Intel.  I don't speak on their behalf.


^ permalink raw reply	[flat|nested] 25+ messages in thread

end of thread, other threads:[~2009-06-18 16:30 UTC | newest]

Thread overview: 25+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-06-15  8:09 [PATCH 00/16] last-minute patches for MCE .31 Hidetoshi Seto
2009-06-15  8:18 ` [PATCH 01/16] x86, mce: don't init timer if !mce_available Hidetoshi Seto
2009-06-15  8:19 ` [PATCH 02/16] x86, mce: call-in should be after updating global_nwo Hidetoshi Seto
2009-06-15  8:26   ` huang ying
2009-06-15  8:40     ` Hidetoshi Seto
2009-06-15  9:18     ` [PATCH] x86, mce: cleanup mce_start() Hidetoshi Seto
2009-06-15  8:20 ` [PATCH 03/16] x86, mce: add __read_mostly Hidetoshi Seto
2009-06-15  8:20 ` [PATCH 04/16] x86, mce: rename static variables around trigger Hidetoshi Seto
2009-06-15  8:21 ` [PATCH 05/16] x86, mce: sysfs entries for new options Hidetoshi Seto
2009-06-15  8:22 ` [PATCH 06/16] x86, mce: unify mce.h Hidetoshi Seto
2009-06-15  8:22 ` [PATCH 07/16] x86, mce: make mce_disabled boolean Hidetoshi Seto
2009-06-15  8:23 ` [PATCH 08/16] x86, mce: unify smp_thermal_interrupt, prepare p4 Hidetoshi Seto
2009-06-15  8:24 ` [PATCH 09/16] x86, mce: unify smp_thermal_interrupt, prepare mce_intel_64 Hidetoshi Seto
2009-06-15  8:24 ` [PATCH 10/16] x86, mce: unify smp_thermal_interrupt, prepare Hidetoshi Seto
2009-06-15  8:25 ` [PATCH 11/16] x86, mce: unify smp_thermal_interrupt Hidetoshi Seto
2009-06-15  8:26 ` [PATCH 12/16] x86, mce: squash mce_intel.c into therm_throt.c Hidetoshi Seto
2009-06-18  5:49   ` huang ying
2009-06-18  7:31     ` Hidetoshi Seto
2009-06-18  8:00       ` huang ying
2009-06-18 13:59         ` H. Peter Anvin
2009-06-18 13:56     ` H. Peter Anvin
2009-06-15  8:26 ` [PATCH 13/16] x86, mce: remove intel_set_thermal_handler() Hidetoshi Seto
2009-06-15  8:27 ` [PATCH 14/16] x86, mce: remove therm_throt.h Hidetoshi Seto
2009-06-15  8:27 ` [PATCH 15/16] x86, mce: mce.h cleanup Hidetoshi Seto
2009-06-15  8:28 ` [PATCH 16/16] x86, mce: rename Hidetoshi Seto

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).