Message ID | 53B575D0.7080700@suse.de |
---|---|
State | New |
Headers | show |
Il 03/07/2014 17:25, Alexander Graf ha scritto: > > Maybe the IRQ line is simply never shared on real Macs :). That's most likely the case, or else it uses MSI. Consider that QEMU only uses 2 GSIs for the four PCI interrupts (10 11), while real PIIX-era hardware used 4 (5 9 10 11, I think). Paolo
On Thu, Jul 03, 2014 at 05:25:04PM +0200, Alexander Graf wrote: > Maybe the IRQ line is simply never shared on real Macs :). Who knows. > > Does this (untested!) patch make it work for you? Yep, it works. Doesn't break OSX on q35, Linux (F20) or windows (7) either :) Thanks, --Gabriel > diff --git a/hw/net/e1000.c b/hw/net/e1000.c > index 0fc29a0..7db0538 100644 > --- a/hw/net/e1000.c > +++ b/hw/net/e1000.c > @@ -1090,9 +1090,24 @@ static uint32_t > mac_icr_read(E1000State *s, int index) > { > uint32_t ret = s->mac_reg[ICR]; > + uint32_t new_icr = 0; > > DBGOUT(INTERRUPT, "ICR read: %x\n", ret); > - set_interrupt_cause(s, 0, 0); > + > + /* > + * Mac OS X reads ICR on every interrupt. When the IRQ line is shared, > + * this may result in a race where LSC is not interpreted yet, but > + * already gets cleared. > + * > + * The easiest fix is to delay LSC events until after they have been > + * property unmasked, so let's just claim we never saw any here. > + */ > + if ((ret & E1000_ICS_LSC) && !(s->mac_reg[IMS] & E1000_ICS_LSC)) { > + ret &= ~E1000_ICS_LSC; > + new_icr |= E1000_ICS_LSC; > + } > + > + set_interrupt_cause(s, 0, new_icr); > return ret; > } >
On 03.07.14 18:43, Gabriel L. Somlo wrote: > On Thu, Jul 03, 2014 at 05:25:04PM +0200, Alexander Graf wrote: >> Maybe the IRQ line is simply never shared on real Macs :). Who knows. >> >> Does this (untested!) patch make it work for you? > Yep, it works. Doesn't break OSX on q35, Linux (F20) or windows (7) > either :) Ok, I'll post it as a real patch then :). Alex
diff --git a/hw/net/e1000.c b/hw/net/e1000.c index 0fc29a0..7db0538 100644 --- a/hw/net/e1000.c +++ b/hw/net/e1000.c @@ -1090,9 +1090,24 @@ static uint32_t mac_icr_read(E1000State *s, int index) { uint32_t ret = s->mac_reg[ICR]; + uint32_t new_icr = 0; DBGOUT(INTERRUPT, "ICR read: %x\n", ret); - set_interrupt_cause(s, 0, 0); + + /* + * Mac OS X reads ICR on every interrupt. When the IRQ line is shared, + * this may result in a race where LSC is not interpreted yet, but + * already gets cleared. + * + * The easiest fix is to delay LSC events until after they have been + * property unmasked, so let's just claim we never saw any here. + */ + if ((ret & E1000_ICS_LSC) && !(s->mac_reg[IMS] & E1000_ICS_LSC)) { + ret &= ~E1000_ICS_LSC; + new_icr |= E1000_ICS_LSC; + } + + set_interrupt_cause(s, 0, new_icr); return ret; }