Skip to content

Commit 60283df

Browse files
richardweinbergerIngo Molnar
authored andcommitted
x86/apic: Read Error Status Register correctly
Currently we do a read, a dummy write and a final read to fetch the error code. The value from the final read is taken. This is not the recommended way and leads to corrupted/lost ESR values. Intel(c) 64 and IA-32 Architectures Software Developer's Manual, Combined Volumes 1, 2ABC, 3ABC, Section 10.5.3 states: Before attempt to read from the ESR, software should first write to it. (The value written does not affect the values read subsequently; only zero may be written in x2APIC mode.) This write clears any previously logged errors and updates the ESR with any errors detected since the last write to the ESR. This write also rearms the APIC error interrupt triggering mechanism. This patch removes the first read such that we are conform with the manual. On my (very old) Pentium MMX SMP system this patch fixes the issue that APIC errors: a) are not always reported and b) are reported with false error numbers. Signed-off-by: Richard Weinberger <richard@nod.at> Cc: seiji.aguchi@hds.com Cc: rientjes@google.com Cc: konrad.wilk@oracle.com Cc: bp@alien8.de Cc: Yinghai Lu <yinghai@kernel.org> Link: http://lkml.kernel.org/r/1389685487-20872-1-git-send-email-richard@nod.at Signed-off-by: Ingo Molnar <mingo@kernel.org>
1 parent 7e22e91 commit 60283df

File tree

1 file changed

+8
-9
lines changed

1 file changed

+8
-9
lines changed

arch/x86/kernel/apic/apic.c

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1968,7 +1968,7 @@ __visible void smp_trace_spurious_interrupt(struct pt_regs *regs)
19681968
*/
19691969
static inline void __smp_error_interrupt(struct pt_regs *regs)
19701970
{
1971-
u32 v0, v1;
1971+
u32 v;
19721972
u32 i = 0;
19731973
static const char * const error_interrupt_reason[] = {
19741974
"Send CS error", /* APIC Error Bit 0 */
@@ -1982,21 +1982,20 @@ static inline void __smp_error_interrupt(struct pt_regs *regs)
19821982
};
19831983

19841984
/* First tickle the hardware, only then report what went on. -- REW */
1985-
v0 = apic_read(APIC_ESR);
19861985
apic_write(APIC_ESR, 0);
1987-
v1 = apic_read(APIC_ESR);
1986+
v = apic_read(APIC_ESR);
19881987
ack_APIC_irq();
19891988
atomic_inc(&irq_err_count);
19901989

1991-
apic_printk(APIC_DEBUG, KERN_DEBUG "APIC error on CPU%d: %02x(%02x)",
1992-
smp_processor_id(), v0 , v1);
1990+
apic_printk(APIC_DEBUG, KERN_DEBUG "APIC error on CPU%d: %02x",
1991+
smp_processor_id(), v);
19931992

1994-
v1 = v1 & 0xff;
1995-
while (v1) {
1996-
if (v1 & 0x1)
1993+
v &= 0xff;
1994+
while (v) {
1995+
if (v & 0x1)
19971996
apic_printk(APIC_DEBUG, KERN_CONT " : %s", error_interrupt_reason[i]);
19981997
i++;
1999-
v1 >>= 1;
1998+
v >>= 1;
20001999
}
20012000

20022001
apic_printk(APIC_DEBUG, KERN_CONT "\n");

0 commit comments

Comments
 (0)