]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - arch/x86_64/kernel/mce_amd.c
[MIPS] Add #include <linux/profile.h> to arch/mips/kernel/time.c
[linux-2.6-omap-h63xx.git] / arch / x86_64 / kernel / mce_amd.c
index 93c707257637cdea3b40eb472e7ab7baa442245f..2f8a7f18b0fea31d9e9c90b829de6f1548b6b584 100644 (file)
@@ -37,6 +37,8 @@
 #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
@@ -122,14 +124,17 @@ void __cpuinit mce_amd_feature_init(struct cpuinfo_x86 *c)
                for (block = 0; block < NR_BLOCKS; ++block) {
                        if (block == 0)
                                address = MSR_IA32_MC0_MISC + bank * 4;
-                       else if (block == 1)
-                               address = MCG_XBLK_ADDR
-                                       + ((low & MASK_BLKPTR_LO) >> 21);
+                       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))
-                               continue;
+                               break;
 
                        if (!(high & MASK_VALID_HI)) {
                                if (block)
@@ -138,8 +143,8 @@ void __cpuinit mce_amd_feature_init(struct cpuinfo_x86 *c)
                                        break;
                        }
 
-                       if (!(high & MASK_VALID_HI >> 1)  ||
-                            (high & MASK_VALID_HI >> 2))
+                       if (!(high & MASK_CNTP_HI)  ||
+                            (high & MASK_LOCKED_HI))
                                continue;
 
                        if (!block)
@@ -152,9 +157,9 @@ void __cpuinit mce_amd_feature_init(struct cpuinfo_x86 *c)
                        high |= K8_APIC_EXT_LVT_ENTRY_THRESHOLD << 20;
                        wrmsr(address, low, high);
 
-                       setup_APIC_extened_lvt(K8_APIC_EXT_LVT_ENTRY_THRESHOLD,
-                                              THRESHOLD_APIC_VECTOR,
-                                              K8_APIC_EXT_INT_MSG_FIX, 0);
+                       setup_APIC_extended_lvt(K8_APIC_EXT_LVT_ENTRY_THRESHOLD,
+                                               THRESHOLD_APIC_VECTOR,
+                                               K8_APIC_EXT_INT_MSG_FIX, 0);
 
                        threshold_defaults.address = address;
                        threshold_restart_bank(&threshold_defaults, 0, 0);
@@ -187,17 +192,22 @@ asmlinkage void mce_threshold_interrupt(void)
 
        /* 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 = MCG_XBLK_ADDR
-                                       + ((low & MASK_BLKPTR_LO) >> 21);
+                       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))
-                               continue;
+                               break;
 
                        if (!(high & MASK_VALID_HI)) {
                                if (block)
@@ -206,10 +216,14 @@ asmlinkage void mce_threshold_interrupt(void)
                                        break;
                        }
 
-                       if (!(high & MASK_VALID_HI >> 1)  ||
-                            (high & MASK_VALID_HI >> 2))
+                       if (!(high & MASK_CNTP_HI)  ||
+                            (high & MASK_LOCKED_HI))
                                continue;
 
+                       /* Log the machine check that caused the threshold
+                          event. */
+                       do_machine_check(NULL, 0);
+
                        if (high & MASK_OVERFLOW_HI) {
                                rdmsrl(address, m.misc);
                                rdmsrl(MSR_IA32_MC0_STATUS + bank * 4,
@@ -385,7 +399,7 @@ static __cpuinit int allocate_threshold_blocks(unsigned int cpu,
                return 0;
 
        if (rdmsr_safe(address, &low, &high))
-               goto recurse;
+               return 0;
 
        if (!(high & MASK_VALID_HI)) {
                if (block)
@@ -394,8 +408,8 @@ static __cpuinit int allocate_threshold_blocks(unsigned int cpu,
                        return 0;
        }
 
-       if (!(high & MASK_VALID_HI >> 1)  ||
-            (high & MASK_VALID_HI >> 2))
+       if (!(high & MASK_CNTP_HI)  ||
+            (high & MASK_LOCKED_HI))
                goto recurse;
 
        b = kzalloc(sizeof(struct threshold_block), GFP_KERNEL);
@@ -640,9 +654,11 @@ static int threshold_cpu_callback(struct notifier_block *nfb,
 
        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: