This is forwardport of Alan's 2.2.17/18 Machine Check Architecture
support for PII/PIII. It's based on 2.2.18p6. Works ok on mine Mendocino.

--
Bartlomiej Zolnierkiewicz
<[EMAIL PROTECTED]>
--- linux-2.4.0-test8/arch/i386/kernel/Makefile         Sat Aug 26 00:01:34 2000
+++ linux/arch/i386/kernel/Makefile                     Thu Sep 14 20:17:09 2000
@@ -18,7 +18,7 @@
 
 obj-y  := process.o semaphore.o signal.o entry.o traps.o irq.o vm86.o \
                ptrace.o i8259.o ioport.o ldt.o setup.o time.o sys_i386.o \
-               pci-dma.o i386_ksyms.o i387.o
+               pci-dma.o i386_ksyms.o i387.o bluesmoke.o
 
 
 ifdef CONFIG_PCI
--- linux-2.4.0-test8/arch/i386/kernel/bluesmoke.c      Thu Sep 14 20:27:41 2000
+++ linux/arch/i386/kernel/bluesmoke.c                  Thu Sep 14 20:13:11 2000
@@ -0,0 +1,110 @@
+/*
+ *     Machine Check Handler For PII/PIII
+ */
+
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <asm/processor.h> 
+#include <asm/msr.h>
+
+static int banks = 0;
+
+void mcheck_fault(void)
+{
+       int recover=1;
+       u32 alow, ahigh, high, low;
+       u32 mcgstl, mcgsth;
+       int i;
+
+       rdmsr(0x17a, mcgstl, mcgsth);
+       if(mcgstl&(1<<0))       /* Recoverable ? */
+               recover=0;
+
+       printk(KERN_EMERG "CPU %d: Machine Check Exception: %08x%08x\n", 
+smp_processor_id(), mcgsth, mcgstl);
+
+       for(i=0;i<banks;i++)
+       {
+               rdmsr(0x401+i*4,low, high);
+               if(high&(1<<31))
+               {
+                       if(high&(1<<29))
+                               recover|=1;
+                       if(high&(1<<25))
+                               recover|=2;
+                       printk(KERN_EMERG "Bank %d: %08x%08x", i, high, low);
+                       high&=~(1<<31);
+                       if(high&(1<<27))
+                       {
+                               rdmsr(0x402+i*4, alow, ahigh);
+                               printk("[%08x%08x]", alow, ahigh);
+                       }
+                       if(high&(1<<26))
+                       {
+                               rdmsr(0x402+i*4, alow, ahigh);
+                               printk(" at %08x%08x",
+                                       high, low);
+                       }
+                       /* Clear it */
+                       wrmsr(0x401+i*4, 0UL, 0UL);
+                       /* Serialize */
+                       wmb();
+               }
+       }
+
+       if(recover&2)
+               panic("CPU context corrupt");
+       if(recover&1)
+               panic("Unable to continue");
+       printk(KERN_EMERG "Attempting to continue.\n");
+       mcgstl&=~(1<<2);
+       wrmsr(0x17a,mcgstl, mcgsth);
+}
+
+
+/*
+ *     This has to be run for each processor
+ */
+ 
+void mcheck_init(void)
+{
+       u32 l, h;
+       int i;
+       struct cpuinfo_x86 *c;
+       static int done=0;
+
+       c=cpu_data+smp_processor_id();
+
+       if(c->x86_vendor!=X86_VENDOR_INTEL)
+               return;
+
+       if(!(c->x86_capability&X86_FEATURE_MCE))
+               return;
+
+       if(!(c->x86_capability&X86_FEATURE_MCA))
+               return;
+
+       /* Ok machine check is available */
+
+       if(done==0)
+               printk(KERN_INFO "Intel machine check architecture supported.\n");
+       rdmsr(0x179, l, h);
+       if(l&(1<<8))
+               wrmsr(0x17b, 0xffffffff, 0xffffffff);
+       banks = l&0xff;
+       for(i=1;i<banks;i++)
+       {
+               wrmsr(0x400+4*i, 0xffffffff, 0xffffffff); 
+       }
+       for(i=0;i<banks;i++)
+       {
+               wrmsr(0x401+4*i, 0x0, 0x0); 
+       }
+       __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;
+}
--- linux-2.4.0-test8/arch/i386/kernel/entry.S          Sat Aug 26 00:09:04 2000
+++ linux/arch/i386/kernel/entry.S                      Thu Sep 14 20:21:17 2000
@@ -414,6 +414,11 @@
        pushl $ SYMBOL_NAME(do_page_fault)
        jmp error_code
 
+ENTRY(machine_check)
+       pushl $0
+       pushl $ SYMBOL_NAME(mcheck_fault)
+       jmp error_code
+
 ENTRY(spurious_interrupt_bug)
        pushl $0
        pushl $ SYMBOL_NAME(do_spurious_interrupt_bug)
--- linux-2.4.0-test8/arch/i386/kernel/setup.c          Sun Sep 10 12:54:35 2000
+++ linux/arch/i386/kernel/setup.c                      Thu Sep 14 20:26:09 2000
@@ -1439,6 +1439,7 @@
 {
        int i=0;
        char *p = NULL;
+       extern void mcheck_init(void);
 
        c->loops_per_sec = loops_per_sec;
        c->x86_cache_size = -1;
@@ -1475,9 +1476,10 @@
                        return;
 
                case X86_VENDOR_INTEL:
-                       
+
                        squash_the_stupid_serial_number(c);
-                       
+                       mcheck_init();
+
                        if (c->cpuid_level > 1) {
                                /* supports eax=2  call */
                                int edx, dummy;

Reply via email to