[PATCH] x86_64: fix apic error on bootup
authorSiddha, Suresh B <suresh.b.siddha@intel.com>
Mon, 26 Jun 2006 11:59:53 +0000 (13:59 +0200)
committerLinus Torvalds <torvalds@g5.osdl.org>
Mon, 26 Jun 2006 17:48:22 +0000 (10:48 -0700)
Appended patch fixes the "APIC error on CPUX: 00(40)" observed during bootup.

From SDM Vol-3A "Valid Interrupt Vectors" section:
"When an illegal vector value (0-15) is written to an LVT entry
and the delivery mode is Fixed, the APIC may signal an illegal
vector error, with out regard to whether the mask bit is set
or whether an interrupt is actually seen on input."

Signed-off-by: Suresh Siddha <suresh.b.siddha@intel.com>
Signed-off-by: Andi Kleen <ak@suse.de>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
arch/i386/kernel/apic.c
arch/x86_64/kernel/apic.c

index 5f197e197c55b5a14e8fa81344073e243c64fdd4..7ce09492fc0ca0bee5fdac224a38d4e509df6c20 100644 (file)
@@ -157,7 +157,7 @@ void clear_local_APIC(void)
        maxlvt = get_maxlvt();
 
        /*
-        * Masking an LVT entry on a P6 can trigger a local APIC error
+        * Masking an LVT entry can trigger a local APIC error
         * if the vector is zero. Mask LVTERR first to prevent this.
         */
        if (maxlvt >= 3) {
@@ -1118,7 +1118,18 @@ void disable_APIC_timer(void)
                unsigned long v;
 
                v = apic_read(APIC_LVTT);
-               apic_write_around(APIC_LVTT, v | APIC_LVT_MASKED);
+               /*
+                * When an illegal vector value (0-15) is written to an LVT
+                * entry and delivery mode is Fixed, the APIC may signal an
+                * illegal vector error, with out regard to whether the mask
+                * bit is set or whether an interrupt is actually seen on input.
+                *
+                * Boot sequence might call this function when the LVTT has
+                * '0' vector value. So make sure vector field is set to
+                * valid value.
+                */
+               v |= (APIC_LVT_MASKED | LOCAL_TIMER_VECTOR);
+               apic_write_around(APIC_LVTT, v);
        }
 }
 
index 396e125cb212c547c8cc16b73fbe07121ea8cd42..b2ead91df218b0e68e9d1cb056981eb0e491896b 100644 (file)
@@ -100,7 +100,7 @@ void clear_local_APIC(void)
        maxlvt = get_maxlvt();
 
        /*
-        * Masking an LVT entry on a P6 can trigger a local APIC error
+        * Masking an LVT entry can trigger a local APIC error
         * if the vector is zero. Mask LVTERR first to prevent this.
         */
        if (maxlvt >= 3) {
@@ -851,7 +851,18 @@ void disable_APIC_timer(void)
                unsigned long v;
 
                v = apic_read(APIC_LVTT);
-               apic_write(APIC_LVTT, v | APIC_LVT_MASKED);
+               /*
+                * When an illegal vector value (0-15) is written to an LVT
+                * entry and delivery mode is Fixed, the APIC may signal an
+                * illegal vector error, with out regard to whether the mask
+                * bit is set or whether an interrupt is actually seen on input.
+                *
+                * Boot sequence might call this function when the LVTT has
+                * '0' vector value. So make sure vector field is set to
+                * valid value.
+                */
+               v |= (APIC_LVT_MASKED | LOCAL_TIMER_VECTOR);
+               apic_write(APIC_LVTT, v);
        }
 }