diff options
-rw-r--r-- | arch/x86_64/kernel/apic.c | 20 | ||||
-rw-r--r-- | include/asm-x86_64/apicdef.h | 1 |
2 files changed, 21 insertions, 0 deletions
diff --git a/arch/x86_64/kernel/apic.c b/arch/x86_64/kernel/apic.c index e5b14c57eaa0..d54620147e8e 100644 --- a/arch/x86_64/kernel/apic.c +++ b/arch/x86_64/kernel/apic.c | |||
@@ -342,6 +342,7 @@ void __init init_bsp_APIC(void) | |||
342 | void __cpuinit setup_local_APIC (void) | 342 | void __cpuinit setup_local_APIC (void) |
343 | { | 343 | { |
344 | unsigned int value, maxlvt; | 344 | unsigned int value, maxlvt; |
345 | int i, j; | ||
345 | 346 | ||
346 | value = apic_read(APIC_LVR); | 347 | value = apic_read(APIC_LVR); |
347 | 348 | ||
@@ -371,6 +372,25 @@ void __cpuinit setup_local_APIC (void) | |||
371 | apic_write(APIC_TASKPRI, value); | 372 | apic_write(APIC_TASKPRI, value); |
372 | 373 | ||
373 | /* | 374 | /* |
375 | * After a crash, we no longer service the interrupts and a pending | ||
376 | * interrupt from previous kernel might still have ISR bit set. | ||
377 | * | ||
378 | * Most probably by now CPU has serviced that pending interrupt and | ||
379 | * it might not have done the ack_APIC_irq() because it thought, | ||
380 | * interrupt came from i8259 as ExtInt. LAPIC did not get EOI so it | ||
381 | * does not clear the ISR bit and cpu thinks it has already serivced | ||
382 | * the interrupt. Hence a vector might get locked. It was noticed | ||
383 | * for timer irq (vector 0x31). Issue an extra EOI to clear ISR. | ||
384 | */ | ||
385 | for (i = APIC_ISR_NR - 1; i >= 0; i--) { | ||
386 | value = apic_read(APIC_ISR + i*0x10); | ||
387 | for (j = 31; j >= 0; j--) { | ||
388 | if (value & (1<<j)) | ||
389 | ack_APIC_irq(); | ||
390 | } | ||
391 | } | ||
392 | |||
393 | /* | ||
374 | * Now that we are all set up, enable the APIC | 394 | * Now that we are all set up, enable the APIC |
375 | */ | 395 | */ |
376 | value = apic_read(APIC_SPIV); | 396 | value = apic_read(APIC_SPIV); |
diff --git a/include/asm-x86_64/apicdef.h b/include/asm-x86_64/apicdef.h index decaa2d540e8..5a48e9bcf218 100644 --- a/include/asm-x86_64/apicdef.h +++ b/include/asm-x86_64/apicdef.h | |||
@@ -39,6 +39,7 @@ | |||
39 | #define APIC_SPIV_FOCUS_DISABLED (1<<9) | 39 | #define APIC_SPIV_FOCUS_DISABLED (1<<9) |
40 | #define APIC_SPIV_APIC_ENABLED (1<<8) | 40 | #define APIC_SPIV_APIC_ENABLED (1<<8) |
41 | #define APIC_ISR 0x100 | 41 | #define APIC_ISR 0x100 |
42 | #define APIC_ISR_NR 0x8 /* Number of 32 bit ISR registers. */ | ||
42 | #define APIC_TMR 0x180 | 43 | #define APIC_TMR 0x180 |
43 | #define APIC_IRR 0x200 | 44 | #define APIC_IRR 0x200 |
44 | #define APIC_ESR 0x280 | 45 | #define APIC_ESR 0x280 |