|
|
@@ -1450,54 +1450,72 @@ static void lapic_setup_esr(void)
|
|
|
oldvalue, value);
|
|
|
}
|
|
|
|
|
|
-static void apic_pending_intr_clear(void)
|
|
|
+#define APIC_IR_REGS APIC_ISR_NR
|
|
|
+#define APIC_IR_BITS (APIC_IR_REGS * 32)
|
|
|
+#define APIC_IR_MAPSIZE (APIC_IR_BITS / BITS_PER_LONG)
|
|
|
+
|
|
|
+union apic_ir {
|
|
|
+ unsigned long map[APIC_IR_MAPSIZE];
|
|
|
+ u32 regs[APIC_IR_REGS];
|
|
|
+};
|
|
|
+
|
|
|
+static bool apic_check_and_ack(union apic_ir *irr, union apic_ir *isr)
|
|
|
{
|
|
|
- long long max_loops = cpu_khz ? cpu_khz : 1000000;
|
|
|
- unsigned long long tsc = 0, ntsc;
|
|
|
- unsigned int queued;
|
|
|
- unsigned long value;
|
|
|
- int i, j, acked = 0;
|
|
|
+ int i, bit;
|
|
|
+
|
|
|
+ /* Read the IRRs */
|
|
|
+ for (i = 0; i < APIC_IR_REGS; i++)
|
|
|
+ irr->regs[i] = apic_read(APIC_IRR + i * 0x10);
|
|
|
+
|
|
|
+ /* Read the ISRs */
|
|
|
+ for (i = 0; i < APIC_IR_REGS; i++)
|
|
|
+ isr->regs[i] = apic_read(APIC_ISR + i * 0x10);
|
|
|
|
|
|
- if (boot_cpu_has(X86_FEATURE_TSC))
|
|
|
- tsc = rdtsc();
|
|
|
/*
|
|
|
- * After a crash, we no longer service the interrupts and a pending
|
|
|
- * interrupt from previous kernel might still have ISR bit set.
|
|
|
- *
|
|
|
- * Most probably by now CPU has serviced that pending interrupt and
|
|
|
- * it might not have done the ack_APIC_irq() because it thought,
|
|
|
- * interrupt came from i8259 as ExtInt. LAPIC did not get EOI so it
|
|
|
- * does not clear the ISR bit and cpu thinks it has already serivced
|
|
|
- * the interrupt. Hence a vector might get locked. It was noticed
|
|
|
- * for timer irq (vector 0x31). Issue an extra EOI to clear ISR.
|
|
|
+ * If the ISR map is not empty. ACK the APIC and run another round
|
|
|
+ * to verify whether a pending IRR has been unblocked and turned
|
|
|
+ * into a ISR.
|
|
|
*/
|
|
|
- do {
|
|
|
- queued = 0;
|
|
|
- for (i = APIC_ISR_NR - 1; i >= 0; i--)
|
|
|
- queued |= apic_read(APIC_IRR + i*0x10);
|
|
|
-
|
|
|
- for (i = APIC_ISR_NR - 1; i >= 0; i--) {
|
|
|
- value = apic_read(APIC_ISR + i*0x10);
|
|
|
- for_each_set_bit(j, &value, 32) {
|
|
|
- ack_APIC_irq();
|
|
|
- acked++;
|
|
|
- }
|
|
|
- }
|
|
|
- if (acked > 256) {
|
|
|
- pr_err("LAPIC pending interrupts after %d EOI\n", acked);
|
|
|
- break;
|
|
|
- }
|
|
|
- if (queued) {
|
|
|
- if (boot_cpu_has(X86_FEATURE_TSC) && cpu_khz) {
|
|
|
- ntsc = rdtsc();
|
|
|
- max_loops = (long long)cpu_khz << 10;
|
|
|
- max_loops -= ntsc - tsc;
|
|
|
- } else {
|
|
|
- max_loops--;
|
|
|
- }
|
|
|
- }
|
|
|
- } while (queued && max_loops > 0);
|
|
|
- WARN_ON(max_loops <= 0);
|
|
|
+ if (!bitmap_empty(isr->map, APIC_IR_BITS)) {
|
|
|
+ /*
|
|
|
+ * There can be multiple ISR bits set when a high priority
|
|
|
+ * interrupt preempted a lower priority one. Issue an ACK
|
|
|
+ * per set bit.
|
|
|
+ */
|
|
|
+ for_each_set_bit(bit, isr->map, APIC_IR_BITS)
|
|
|
+ ack_APIC_irq();
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ return !bitmap_empty(irr->map, APIC_IR_BITS);
|
|
|
+}
|
|
|
+
|
|
|
+/*
|
|
|
+ * After a crash, we no longer service the interrupts and a pending
|
|
|
+ * interrupt from previous kernel might still have ISR bit set.
|
|
|
+ *
|
|
|
+ * Most probably by now the CPU has serviced that pending interrupt and it
|
|
|
+ * might not have done the ack_APIC_irq() because it thought, interrupt
|
|
|
+ * came from i8259 as ExtInt. LAPIC did not get EOI so it does not clear
|
|
|
+ * the ISR bit and cpu thinks it has already serivced the interrupt. Hence
|
|
|
+ * a vector might get locked. It was noticed for timer irq (vector
|
|
|
+ * 0x31). Issue an extra EOI to clear ISR.
|
|
|
+ *
|
|
|
+ * If there are pending IRR bits they turn into ISR bits after a higher
|
|
|
+ * priority ISR bit has been acked.
|
|
|
+ */
|
|
|
+static void apic_pending_intr_clear(void)
|
|
|
+{
|
|
|
+ union apic_ir irr, isr;
|
|
|
+ unsigned int i;
|
|
|
+
|
|
|
+ /* 512 loops are way oversized and give the APIC a chance to obey. */
|
|
|
+ for (i = 0; i < 512; i++) {
|
|
|
+ if (!apic_check_and_ack(&irr, &isr))
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ /* Dump the IRR/ISR content if that failed */
|
|
|
+ pr_warn("APIC: Stale IRR: %256pb ISR: %256pb\n", irr.map, isr.map);
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
@@ -1565,6 +1583,7 @@ static void setup_local_APIC(void)
|
|
|
value &= ~APIC_TPRI_MASK;
|
|
|
apic_write(APIC_TASKPRI, value);
|
|
|
|
|
|
+ /* Clear eventually stale ISR/IRR bits */
|
|
|
apic_pending_intr_clear();
|
|
|
|
|
|
/*
|