]> git.hungrycats.org Git - linux/commitdiff
[PATCH] Fix oops with nmi-watchdog=2
authorPhilippe Elie <phil.el@wanadoo.fr>
Tue, 31 Aug 2004 03:31:55 +0000 (20:31 -0700)
committerLinus Torvalds <torvalds@ppc970.osdl.org>
Tue, 31 Aug 2004 03:31:55 +0000 (20:31 -0700)
Contributions from  Zarakin <zarakin@hotpop.com>

Intel removed two msrs: MSR_P4_IQ_ESCR_0|1 (0x3ba/0x3bb), P4 model >= 3.  See
Intel documentation Vol.  3 System Programming Guide Appendix B.

nmi_watchdog=2 oopsed at boot time and oprofile at driver load.

Avoid touching them when model >= 3.

Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
arch/i386/kernel/nmi.c
arch/i386/oprofile/op_model_p4.c

index abcd993cbcd9242437d12eb7bb1303e04d94cb1d..c9dcd1f42788f1967e3a89f898c05a44184bce5e 100644 (file)
@@ -380,7 +380,13 @@ static int setup_p4_watchdog(void)
                clear_msr_range(0x3F1, 2);
        /* MSR 0x3F0 seems to have a default value of 0xFC00, but current
           docs doesn't fully define it, so leave it alone for now. */
-       clear_msr_range(0x3A0, 31);
+       if (boot_cpu_data.x86_model >= 0x3) {
+               /* MSR_P4_IQ_ESCR0/1 (0x3ba/0x3bb) removed */
+               clear_msr_range(0x3A0, 26);
+               clear_msr_range(0x3BC, 3);
+       } else {
+               clear_msr_range(0x3A0, 31);
+       }
        clear_msr_range(0x3C0, 6);
        clear_msr_range(0x3C8, 6);
        clear_msr_range(0x3E0, 2);
index e82f689068d209763216fcdfc59b6612dac7c567..661896b3bfcc102818eba90644b0acf0c942b344 100644 (file)
@@ -419,9 +419,28 @@ static void p4_fill_in_addresses(struct op_msrs * const msrs)
                msrs->controls[i].addr = addr;
        }
        
-       /* 43 ESCR registers in three discontiguous group */
+       /* 43 ESCR registers in three or four discontiguous group */
        for (addr = MSR_P4_BSU_ESCR0 + stag;
-            addr <= MSR_P4_SSU_ESCR0; ++i, addr += addr_increment()) { 
+            addr < MSR_P4_IQ_ESCR0; ++i, addr += addr_increment()) {
+               msrs->controls[i].addr = addr;
+       }
+
+       /* no IQ_ESCR0/1 on some models, we save a seconde time BSU_ESCR0/1
+        * to avoid special case in nmi_{save|restore}_registers() */
+       if (boot_cpu_data.x86_model >= 0x3) {
+               for (addr = MSR_P4_BSU_ESCR0 + stag;
+                    addr <= MSR_P4_BSU_ESCR1; ++i, addr += addr_increment()) {
+                       msrs->controls[i].addr = addr;
+               }
+       } else {
+               for (addr = MSR_P4_IQ_ESCR0 + stag;
+                    addr <= MSR_P4_IQ_ESCR1; ++i, addr += addr_increment()) {
+                       msrs->controls[i].addr = addr;
+               }
+       }
+
+       for (addr = MSR_P4_RAT_ESCR0 + stag;
+            addr <= MSR_P4_SSU_ESCR0; ++i, addr += addr_increment()) {
                msrs->controls[i].addr = addr;
        }
        
@@ -553,7 +572,18 @@ static void p4_setup_ctrs(struct op_msrs const * const msrs)
 
        /* clear all escrs (including those outside our concern) */
        for (addr = MSR_P4_BSU_ESCR0 + stag;
-            addr <= MSR_P4_SSU_ESCR0; addr += addr_increment()) { 
+            addr <  MSR_P4_IQ_ESCR0; addr += addr_increment()) {
+               wrmsr(addr, 0, 0);
+       }
+
+       /* On older models clear also MSR_P4_IQ_ESCR0/1 */
+       if (boot_cpu_data.x86_model < 0x3) {
+               wrmsr(MSR_P4_IQ_ESCR0, 0, 0);
+               wrmsr(MSR_P4_IQ_ESCR1, 0, 0);
+       }
+
+       for (addr = MSR_P4_RAT_ESCR0 + stag;
+            addr <= MSR_P4_SSU_ESCR0; ++i, addr += addr_increment()) {
                wrmsr(addr, 0, 0);
        }