On Wed, Jul 02, 2014 at 05:14:26PM -0400, Gabriel L. Somlo wrote: > On Wed, Jul 02, 2014 at 11:02:30PM +0200, Alexander Graf wrote: > > > > On 02.07.14 22:49, Gabriel L. Somlo wrote: > > >So it turns out everything I thought I knew (which was little indeed) > > >was more or less wrong. The problem, as far as I'm observing it now, > > >is that on PIIX, the OS X guest obsessively reads the ICR in a tight > > >loop. It reads the injected LSC (and probably discards it) before > > >unmasking the corresponding interrupt bit; later on, when it unmasks > > >LSC, giving the emulated e1000 hardware a chance to raise the irq > > >line, the actual LSC event has been flushed from the ICR, and the > > >driver does not detect the link coming up. > > > > > > [...] > > > > > >Any clue as to why ICR gets read like that on PIIX, but not Q35 ? > > > > Either way, why does the bit get cleared even though it hasn't been raised? > > What does real hardware do with interrupts that have been masked? > > The e1000 manual says ICR bits are cleared on read. It also says PCI > interrupts are only generated if the corresponding bit in *both* ICR > and IMS registers is 1. ICR bits are still cleared if read, even if > masked and no actual interrupt is raised. > > > Maybe it's using MSI on q35? :) > > Maybe we also share the same IRQ line with another device on PIIX that gets > > polled all the time? IDE maybe? > > Even if that were the case, how come it's reading precisely our > device's ICR register ? Isn't that too much of a coincidence ?
Unless some other device on a shared IRQ line generated the interrupt, and our e1000 driver then checked ICR. Although if that happened, our driver should happily acknowledge the link-up event (I checked, and it does NOT read IMS, so it has no way of knowing it's masked). Except it does -- it knows the last thing it did was set_imc(0xFFFFFFFF), and that it hasn't yet set_ims(anything) yet... And I think you're right: (qemu) info pci Bus 0, device 0, function 0: Host bridge: PCI device 8086:1237 id "" Bus 0, device 1, function 0: ISA bridge: PCI device 8086:7000 id "" Bus 0, device 1, function 1: IDE controller: PCI device 8086:7010 BAR4: I/O at 0xc080 [0xc08f]. id "" Bus 0, device 1, function 2: USB controller: PCI device 8086:7020 IRQ 11. BAR4: I/O at 0xc040 [0xc05f]. id "" Bus 0, device 1, function 3: Bridge: PCI device 8086:7113 IRQ 9. id "" Bus 0, device 2, function 0: VGA controller: PCI device 1013:00b8 BAR0: 32 bit prefetchable memory at 0xfc000000 [0xfdffffff]. BAR1: 32 bit memory at 0xfebf0000 [0xfebf0fff]. BAR6: 32 bit memory at 0xffffffffffffffff [0x0000fffe]. id "" Bus 0, device 3, function 0: SATA controller: PCI device 8086:2922 IRQ 11. BAR4: I/O at 0xc060 [0xc07f]. BAR5: 32 bit memory at 0xfebf1000 [0xfebf1fff]. id "ide" Bus 0, device 4, function 0: Ethernet controller: PCI device 8086:100f IRQ 11. BAR0: 32 bit memory at 0xfebc0000 [0xfebdffff]. BAR1: I/O at 0xffffffffffffffff [0x003e]. BAR6: 32 bit memory at 0xffffffffffffffff [0x0003fffe]. id "vnet0" so Ethernet, SATA, and USB, all sharing IRQ 11. Is there an easy way to force one of those to use a different IRQ ?