aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--xen/arch/x86/apic.c8
-rw-r--r--xen/arch/x86/i8259.c43
-rw-r--r--xen/arch/x86/irq.c14
-rw-r--r--xen/include/asm-x86/apic.h6
-rw-r--r--xen/include/asm-x86/irq.h1
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);