Hi,
edge triggered interrupts wouldn't though.
The code change doesn't change anything for edge triggered
interrupts
- they work fine. Only !msi (== level) ones are broken.
apic irqs can be both edge and level triggered too ...
That re-trigger smells like you are not clearing the interrupt line
where you should. For starters try calling ahci_check_irq() after
guest writes to PORT_IRQ_STAT.
The problem happened when I had the following:
ahci irq bits = 0
<events happen>
ahci irq bits = 1 | 2
irq line trigger
guest clears 1
ahci bits = 2
<no irq line trigger, since we're still irq high>
On normal hardware, the high state of the irq line would simply
trigger another interrupt in the guest when it gets ACKed on the LAPIC.
Somehow it doesn't get triggered here. I don't see why clearing the
interrupt line would help? It's not what real hardware would do, no?
I think the guest and the ahci emulation simply disagree on whenever a
irq is pending or not. Guest thinks it has cleared the IRQ, but the
code path it has taken didn't trigger ahci_irq_lower().
It is probably related to how the per-port and global irq status play
together. It isn't covered very well in the specs :-(
If an interrupt condition happens a bit in pr->irq_stat will be set.
When the contition is enabled the port bit in irqstatus will be set,
which in turn will trigger an irq. That is the easy part.
Now the guest checks irqstatus to find the port, then checks
pr->irq_stat to find the condition, acks it by clearing the bits it has
seen in pr->irq_stat. What does happen with the port bit in irqstatus
now? Will it be cleared automatically? Must the guest clear it
explicitly? What happens in case another irq condition happened which
the guest didn't ack (yet), will the guest be able to clear the bit?
cheers,
Gerd