Page MenuHomeFreeBSD

D28238.diff
No OneTemporary

D28238.diff

diff --git a/sys/amd64/vmm/io/vioapic.c b/sys/amd64/vmm/io/vioapic.c
--- a/sys/amd64/vmm/io/vioapic.c
+++ b/sys/amd64/vmm/io/vioapic.c
@@ -122,8 +122,14 @@
phys = ((low & IOART_DESTMOD) == IOART_DESTPHY);
delmode = low & IOART_DELMOD;
level = low & IOART_TRGRLVL ? true : false;
- if (level)
+ if (level) {
+ if ((low & IOART_REM_IRR) != 0) {
+ VIOAPIC_CTR1(vioapic, "ioapic pin%d: irr pending",
+ pin);
+ return;
+ }
vioapic->rtbl[pin].reg |= IOART_REM_IRR;
+ }
vector = low & IOART_INTVEC;
dest = high >> APIC_ID_SHIFT;
@@ -342,6 +348,16 @@
vioapic->rtbl[pin].reg &= ~mask64 | RTBL_RO_BITS;
vioapic->rtbl[pin].reg |= data64 & ~RTBL_RO_BITS;
+ /*
+ * Switching from level to edge triggering will clear the IRR
+ * bit. This is what FreeBSD will do in order to EOI an
+ * interrupt when the IO-APIC doesn't support targeted EOI (see
+ * _ioapic_eoi_source).
+ */
+ if ((vioapic->rtbl[pin].reg & IOART_TRGRMOD) == IOART_TRGREDG &&
+ (vioapic->rtbl[pin].reg & IOART_REM_IRR) != 0)
+ vioapic->rtbl[pin].reg &= ~IOART_REM_IRR;
+
VIOAPIC_CTR2(vioapic, "ioapic pin%d: redir table entry %#lx",
pin, vioapic->rtbl[pin].reg);
@@ -363,12 +379,10 @@
/*
* Generate an interrupt if the following conditions are met:
- * - previous interrupt has been EOIed
* - pin trigger mode is level
* - pin level is asserted
*/
- if ((vioapic->rtbl[pin].reg & IOART_REM_IRR) == 0 &&
- (vioapic->rtbl[pin].reg & IOART_TRGRMOD) == IOART_TRGRLVL &&
+ if ((vioapic->rtbl[pin].reg & IOART_TRGRMOD) == IOART_TRGRLVL &&
(vioapic->rtbl[pin].acnt > 0)) {
VIOAPIC_CTR2(vioapic, "ioapic pin%d: asserted at rtbl "
"write, acnt %d", pin, vioapic->rtbl[pin].acnt);

File Metadata

Mime Type
text/plain
Expires
Tue, Apr 29, 7:36 AM (18 h, 19 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
17838505
Default Alt Text
D28238.diff (1 KB)

Event Timeline