patch-2.4.5 linux/arch/i386/kernel/bluesmoke.c
Next file: linux/arch/i386/kernel/i386_ksyms.c
Previous file: linux/arch/i386/defconfig
Back to the patch index
Back to the overall index
- Lines: 190
- Date:
Mon May 21 12:34:50 2001
- Orig file:
v2.4.4/linux/arch/i386/kernel/bluesmoke.c
- Orig date:
Wed Apr 11 19:02:27 2001
diff -u --recursive --new-file v2.4.4/linux/arch/i386/kernel/bluesmoke.c linux/arch/i386/kernel/bluesmoke.c
@@ -1,16 +1,18 @@
-/*
- * Machine Check Handler For PII/PIII
- */
+#include <linux/init.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <asm/processor.h>
#include <asm/msr.h>
+/*
+ * Machine Check Handler For PII/PIII
+ */
+
static int banks;
-void do_machine_check(struct pt_regs * regs, long error_code)
+static void intel_machine_check(struct pt_regs * regs, long error_code)
{
int recover=1;
u32 alow, ahigh, high, low;
@@ -62,28 +64,101 @@
wrmsr(0x17a,mcgstl, mcgsth);
}
+/*
+ * Machine check handler for Pentium class Intel
+ */
+
+static void pentium_machine_check(struct pt_regs * regs, long error_code)
+{
+ u32 loaddr, hi, lotype;
+ rdmsr(0x0, loaddr, hi);
+ rdmsr(0x1, lotype, hi);
+ printk(KERN_EMERG "CPU#%d: Machine Check Exception: 0x%8X (type 0x%8X).\n", smp_processor_id(), loaddr, lotype);
+ if(lotype&(1<<5))
+ printk(KERN_EMERG "CPU#%d: Possible thermal failure (CPU on fire ?).\n", smp_processor_id());
+}
/*
- * This has to be run for each processor
+ * Machine check handler for WinChip C6
+ */
+
+static void winchip_machine_check(struct pt_regs * regs, long error_code)
+{
+ printk(KERN_EMERG "CPU#%d: Machine Check Exception.\n", smp_processor_id());
+}
+
+/*
+ * Handle unconfigured int18 (should never happen)
*/
+
+static void unexpected_machine_check(struct pt_regs * regs, long error_code)
+{
+ printk(KERN_ERR "CPU#%d: Unexpected int18 (Machine Check).\n", smp_processor_id());
+}
+
+/*
+ * Call the installed machine check handler for this CPU setup.
+ */
-void mcheck_init(struct cpuinfo_x86 *c)
+static void (*machine_check_vector)(struct pt_regs *, long error_code) = unexpected_machine_check;
+
+void do_machine_check(struct pt_regs * regs, long error_code)
+{
+ machine_check_vector(regs, error_code);
+}
+
+/*
+ * Set up machine check reporting for Intel processors
+ */
+
+void __init intel_mcheck_init(struct cpuinfo_x86 *c)
{
u32 l, h;
int i;
static int done;
-
- if( c->x86_vendor != X86_VENDOR_INTEL )
- return;
+ /*
+ * Check for MCE support
+ */
+
if( !test_bit(X86_FEATURE_MCE, &c->x86_capability) )
+ return;
+
+ /*
+ * Pentium machine check
+ */
+
+ if(c->x86 == 5)
+ {
+ machine_check_vector = pentium_machine_check;
+ wmb();
+ /* Read registers before enabling */
+ rdmsr(0x0, l, h);
+ rdmsr(0x1, l, h);
+ if(done==0)
+ printk(KERN_INFO "Intel old style machine check architecture supported.\n");
+ /* Enable MCE */
+ __asm__ __volatile__ (
+ "movl %%cr4, %%eax\n\t"
+ "orl $0x40, %%eax\n\t"
+ "movl %%eax, %%cr4\n\t" : : : "eax");
+ printk(KERN_INFO "Intel old style machine check reporting enabled on CPU#%d.\n", smp_processor_id());
return;
-
+ }
+
+
+ /*
+ * Check for PPro style MCA
+ */
+
if( !test_bit(X86_FEATURE_MCA, &c->x86_capability) )
return;
/* Ok machine check is available */
+ machine_check_vector = intel_machine_check;
+ wmb();
+
if(done==0)
printk(KERN_INFO "Intel machine check architecture supported.\n");
rdmsr(0x179, l, h);
@@ -98,10 +173,56 @@
{
wrmsr(0x401+4*i, 0x0, 0x0);
}
+ set_in_cr4(X86_CR4_MCE);
+ printk(KERN_INFO "Intel machine check reporting enabled on CPU#%d.\n", smp_processor_id());
+ done=1;
+}
+
+/*
+ * Set up machine check reporting on the Winchip C6 series
+ */
+
+static void winchip_mcheck_init(struct cpuinfo_x86 *c)
+{
+ u32 lo, hi;
+ /* Not supported on C3 */
+ if(c->x86 != 5)
+ return;
+ /* Winchip C6 */
+ machine_check_vector = winchip_machine_check;
+ wmb();
+ rdmsr(0x107, lo, hi);
+ lo|= (1<<2); /* Enable EIERRINT (int 18 MCE) */
+ lo&= ~(1<<4); /* Enable MCE */
+ wrmsr(0x107, lo, hi);
__asm__ __volatile__ (
"movl %%cr4, %%eax\n\t"
"orl $0x40, %%eax\n\t"
"movl %%eax, %%cr4\n\t" : : : "eax");
- printk(KERN_INFO "Intel machine check reporting enabled on CPU#%d.\n", smp_processor_id());
- done=1;
+ printk(KERN_INFO "Winchip machine check reporting enabled on CPU#%d.\n", smp_processor_id());
+}
+
+
+/*
+ * This has to be run for each processor
+ */
+
+void __init mcheck_init(struct cpuinfo_x86 *c)
+{
+ switch(c->x86_vendor)
+ {
+ case X86_VENDOR_AMD:
+ /*
+ * AMD K7 machine check is Intel like
+ */
+ if(c->x86 == 6)
+ intel_mcheck_init(c);
+ break;
+ case X86_VENDOR_INTEL:
+ intel_mcheck_init(c);
+ break;
+ case X86_VENDOR_CENTAUR:
+ winchip_mcheck_init(c);
+ break;
+ }
}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)