summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPhilippe Elie <phil.el@wanadoo.fr>2004-08-30 20:31:55 -0700
committerLinus Torvalds <torvalds@ppc970.osdl.org>2004-08-30 20:31:55 -0700
commit5ae3fd759fcfb8ef033f2279e3f5a1515ec702c6 (patch)
tree3e22634057dadf649ae723111ad78dd4162e72b3
parent75b02c33c4b32491c1d3c8bea0945282aa05b516 (diff)
[PATCH] Fix oops with nmi-watchdog=2
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>
-rw-r--r--arch/i386/kernel/nmi.c8
-rw-r--r--arch/i386/oprofile/op_model_p4.c36
2 files changed, 40 insertions, 4 deletions
diff --git a/arch/i386/kernel/nmi.c b/arch/i386/kernel/nmi.c
index abcd993cbcd9..c9dcd1f42788 100644
--- a/arch/i386/kernel/nmi.c
+++ b/arch/i386/kernel/nmi.c
@@ -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);
diff --git a/arch/i386/oprofile/op_model_p4.c b/arch/i386/oprofile/op_model_p4.c
index e82f689068d2..661896b3bfcc 100644
--- a/arch/i386/oprofile/op_model_p4.c
+++ b/arch/i386/oprofile/op_model_p4.c
@@ -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);
}