* [PATCH] avoid redeliver of edge interrupt before next edge
@ 2009-07-05 13:46 Gleb Natapov
0 siblings, 0 replies; only message in thread
From: Gleb Natapov @ 2009-07-05 13:46 UTC (permalink / raw)
To: avi; +Cc: kvm
The check for an edge is broken in current ioapic code. ioapic->irr is
cleared on each edge interrupt by ioapic_service() and this makes
old_irr != ioapic->irr condition in kvm_ioapic_set_irq() to be always
true. The patch fixes the code to properly recognise edge.
Signed-off-by: Gleb Natapov <gleb@redhat.com>
diff --git a/virt/kvm/ioapic.c b/virt/kvm/ioapic.c
index 124ecf7..74c4b5f 100644
--- a/virt/kvm/ioapic.c
+++ b/virt/kvm/ioapic.c
@@ -95,8 +95,6 @@ static int ioapic_service(struct kvm_ioapic *ioapic, unsigned int idx)
if (injected && pent->fields.trig_mode == IOAPIC_LEVEL_TRIG)
pent->fields.remote_irr = 1;
}
- if (!pent->fields.trig_mode)
- ioapic->irr &= ~(1 << idx);
return injected;
}
@@ -118,28 +116,34 @@ static void ioapic_write_indirect(struct kvm_ioapic *ioapic, u32 val)
case IOAPIC_REG_ARB_ID:
break;
- default:
+ default: {
+ union kvm_ioapic_redirect_entry *e;
+
index = (ioapic->ioregsel - 0x10) >> 1;
ioapic_debug("change redir index %x val %x\n", index, val);
if (index >= IOAPIC_NUM_PINS)
return;
- mask_before = ioapic->redirtbl[index].fields.mask;
+
+ e = &ioapic->redirtbl[index];
+ mask_before = e->fields.mask;
if (ioapic->ioregsel & 1) {
- ioapic->redirtbl[index].bits &= 0xffffffff;
- ioapic->redirtbl[index].bits |= (u64) val << 32;
+ e->bits &= 0xffffffff;
+ e->bits |= (u64) val << 32;
} else {
- ioapic->redirtbl[index].bits &= ~0xffffffffULL;
- ioapic->redirtbl[index].bits |= (u32) val;
- ioapic->redirtbl[index].fields.remote_irr = 0;
+ e->bits &= ~0xffffffffULL;
+ e->bits |= (u32) val;
+ e->fields.remote_irr = 0;
}
- mask_after = ioapic->redirtbl[index].fields.mask;
+ mask_after = e->fields.mask;
if (mask_before != mask_after)
kvm_fire_mask_notifiers(ioapic->kvm, index, mask_after);
- if (ioapic->irr & (1 << index))
+ if (e->fields.trig_mode == IOAPIC_LEVEL_TRIG &&
+ (ioapic->irr & (1 << index)))
ioapic_service(ioapic, index);
break;
}
+ }
}
static int ioapic_deliver(struct kvm_ioapic *ioapic, int irq)
@@ -186,9 +190,10 @@ int kvm_ioapic_set_irq(struct kvm_ioapic *ioapic, int irq, int level)
if (!level)
ioapic->irr &= ~mask;
else {
+ int edge = (entry.fields.trig_mode == IOAPIC_EDGE_TRIG);
ioapic->irr |= mask;
- if ((!entry.fields.trig_mode && old_irr != ioapic->irr)
- || !entry.fields.remote_irr)
+ if ((edge && old_irr != ioapic->irr) ||
+ (!edge && !entry.fields.remote_irr))
ret = ioapic_service(ioapic, irq);
}
}
--
Gleb.
^ permalink raw reply related [flat|nested] only message in thread
only message in thread, other threads:[~2009-07-05 13:46 UTC | newest]
Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2009-07-05 13:46 [PATCH] avoid redeliver of edge interrupt before next edge Gleb Natapov
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.