diff options
-rw-r--r-- | xen/arch/x86/apic.c | 8 | ||||
-rw-r--r-- | xen/arch/x86/i8259.c | 43 | ||||
-rw-r--r-- | xen/arch/x86/irq.c | 14 | ||||
-rw-r--r-- | xen/include/asm-x86/apic.h | 6 | ||||
-rw-r--r-- | xen/include/asm-x86/irq.h | 1 |
5 files changed, 52 insertions, 20 deletions
diff --git a/xen/arch/x86/apic.c b/xen/arch/x86/apic.c index e05dd82bb2..50430d2f39 100644 --- a/xen/arch/x86/apic.c +++ b/xen/arch/x86/apic.c @@ -1317,15 +1317,12 @@ void smp_send_state_dump(unsigned int cpu) */ void spurious_interrupt(struct cpu_user_regs *regs) { - unsigned long v; - /* * Check if this is a vectored interrupt (most likely, as this is probably * a request to dump local CPU state). Vectored interrupts are ACKed; * spurious interrupts are not. */ - v = apic_read(APIC_ISR + ((SPURIOUS_APIC_VECTOR & ~0x1f) >> 1)); - if (v & (1 << (SPURIOUS_APIC_VECTOR & 0x1f))) { + if (apic_isr_read(SPURIOUS_APIC_VECTOR)) { ack_APIC_irq(); if (this_cpu(state_dump_pending)) { this_cpu(state_dump_pending) = 0; @@ -1491,6 +1488,5 @@ enum apic_mode current_local_apic_mode(void) void check_for_unexpected_msi(unsigned int vector) { - unsigned long v = apic_read(APIC_ISR + ((vector & ~0x1f) >> 1)); - BUG_ON(v & (1 << (vector & 0x1f))); + BUG_ON(apic_isr_read(vector)); } diff --git a/xen/arch/x86/i8259.c b/xen/arch/x86/i8259.c index 2cbda3cb76..91f0bc5d46 100644 --- a/xen/arch/x86/i8259.c +++ b/xen/arch/x86/i8259.c @@ -85,7 +85,15 @@ BUILD_16_IRQS(0xc) BUILD_16_IRQS(0xd) BUILD_16_IRQS(0xe) BUILD_16_IRQS(0xf) static DEFINE_SPINLOCK(i8259A_lock); -static void mask_and_ack_8259A_irq(struct irq_desc *); +static void _mask_and_ack_8259A_irq(unsigned int irq); + +void (*__read_mostly bogus_8259A_irq)(unsigned int irq) = + _mask_and_ack_8259A_irq; + +static void mask_and_ack_8259A_irq(struct irq_desc *desc) +{ + _mask_and_ack_8259A_irq(desc->irq); +} static unsigned int startup_8259A_irq(struct irq_desc *desc) { @@ -133,20 +141,26 @@ static unsigned int cached_irq_mask = 0xffff; */ unsigned int __read_mostly io_apic_irqs; -void disable_8259A_irq(struct irq_desc *desc) +static void _disable_8259A_irq(unsigned int irq) { - unsigned int mask = 1 << desc->irq; + unsigned int mask = 1 << irq; unsigned long flags; spin_lock_irqsave(&i8259A_lock, flags); cached_irq_mask |= mask; - if (desc->irq & 8) + if (irq & 8) outb(cached_A1,0xA1); else outb(cached_21,0x21); + per_cpu(vector_irq, 0)[LEGACY_VECTOR(irq)] = -1; spin_unlock_irqrestore(&i8259A_lock, flags); } +void disable_8259A_irq(struct irq_desc *desc) +{ + _disable_8259A_irq(desc->irq); +} + void enable_8259A_irq(struct irq_desc *desc) { unsigned int mask = ~(1 << desc->irq); @@ -154,6 +168,7 @@ void enable_8259A_irq(struct irq_desc *desc) spin_lock_irqsave(&i8259A_lock, flags); cached_irq_mask &= mask; + per_cpu(vector_irq, 0)[LEGACY_VECTOR(desc->irq)] = desc->irq; if (desc->irq & 8) outb(cached_A1,0xA1); else @@ -226,9 +241,9 @@ static inline int i8259A_irq_real(unsigned int irq) * first, _then_ send the EOI, and the order of EOI * to the two 8259s is important! */ -static void mask_and_ack_8259A_irq(struct irq_desc *desc) +static void _mask_and_ack_8259A_irq(unsigned int irq) { - unsigned int irqmask = 1 << desc->irq; + unsigned int irqmask = 1 << irq; unsigned long flags; spin_lock_irqsave(&i8259A_lock, flags); @@ -252,15 +267,15 @@ static void mask_and_ack_8259A_irq(struct irq_desc *desc) cached_irq_mask |= irqmask; handle_real_irq: - if (desc->irq & 8) { + if (irq & 8) { inb(0xA1); /* DUMMY - (do we need this?) */ outb(cached_A1,0xA1); - outb(0x60 + (desc->irq & 7), 0xA0);/* 'Specific EOI' to slave */ + outb(0x60 + (irq & 7), 0xA0);/* 'Specific EOI' to slave */ outb(0x62,0x20); /* 'Specific EOI' to master-IRQ2 */ } else { inb(0x21); /* DUMMY - (do we need this?) */ outb(cached_21,0x21); - outb(0x60 + desc->irq, 0x20);/* 'Specific EOI' to master */ + outb(0x60 + irq, 0x20);/* 'Specific EOI' to master */ } spin_unlock_irqrestore(&i8259A_lock, flags); return; @@ -269,7 +284,7 @@ static void mask_and_ack_8259A_irq(struct irq_desc *desc) /* * this is the slow path - should happen rarely. */ - if (i8259A_irq_real(desc->irq)) + if (i8259A_irq_real(irq)) /* * oops, the IRQ _is_ in service according to the * 8259A - not spurious, go handle it. @@ -283,7 +298,7 @@ static void mask_and_ack_8259A_irq(struct irq_desc *desc) * lets ACK and report it. [once per IRQ] */ if (!(spurious_irq_mask & irqmask)) { - printk("spurious 8259A interrupt: IRQ%d.\n", desc->irq); + printk("spurious 8259A interrupt: IRQ%d.\n", irq); spurious_irq_mask |= irqmask; } /* @@ -352,13 +367,19 @@ void __devinit init_8259A(int auto_eoi) is to be investigated) */ if (auto_eoi) + { /* * in AEOI mode we just have to mask the interrupt * when acking. */ i8259A_irq_type.ack = disable_8259A_irq; + bogus_8259A_irq = _disable_8259A_irq; + } else + { i8259A_irq_type.ack = mask_and_ack_8259A_irq; + bogus_8259A_irq = _mask_and_ack_8259A_irq; + } udelay(100); /* wait for 8259A to initialize */ diff --git a/xen/arch/x86/irq.c b/xen/arch/x86/irq.c index 2fc676b716..496c8048ae 100644 --- a/xen/arch/x86/irq.c +++ b/xen/arch/x86/irq.c @@ -811,9 +811,17 @@ void do_IRQ(struct cpu_user_regs *regs) if (direct_apic_vector[vector] != NULL) { (*direct_apic_vector[vector])(regs); } else { - ack_APIC_irq(); - printk("%s: %d.%d No irq handler for vector (irq %d)\n", - __func__, smp_processor_id(), vector, irq); + const char *kind = ", LAPIC"; + + if ( apic_isr_read(vector) ) + ack_APIC_irq(); + else + kind = ""; + if ( vector >= FIRST_LEGACY_VECTOR && + vector <= LAST_LEGACY_VECTOR ) + bogus_8259A_irq(vector - FIRST_LEGACY_VECTOR); + printk("CPU%u: No irq handler for vector %02x (IRQ %d%s)\n", + smp_processor_id(), vector, irq, kind); TRACE_1D(TRC_HW_IRQ_UNMAPPED_VECTOR, vector); } goto out_no_unlock; diff --git a/xen/include/asm-x86/apic.h b/xen/include/asm-x86/apic.h index 36c65b43dc..4e6bea962e 100644 --- a/xen/include/asm-x86/apic.h +++ b/xen/include/asm-x86/apic.h @@ -146,6 +146,12 @@ static __inline void apic_icr_write(u32 low, u32 dest) } } +static __inline bool_t apic_isr_read(u8 vector) +{ + return (apic_read(APIC_ISR + ((vector & ~0x1f) >> 1)) >> + (vector & 0x1f)) & 1; +} + static __inline u32 get_apic_id(void) /* Get the physical APIC id */ { u32 id = apic_read(APIC_ID); diff --git a/xen/include/asm-x86/irq.h b/xen/include/asm-x86/irq.h index ffa3e8f261..ccc013e25c 100644 --- a/xen/include/asm-x86/irq.h +++ b/xen/include/asm-x86/irq.h @@ -104,6 +104,7 @@ void mask_8259A(void); void unmask_8259A(void); void init_8259A(int aeoi); void make_8259A_irq(unsigned int irq); +extern void (*bogus_8259A_irq)(unsigned int irq); int i8259A_suspend(void); int i8259A_resume(void); |