@samitouri / QOSamiQemu / commits / 79933616d9

hw/misc/lasi: derive IRR from pending and unmasked requests

The LASI interrupt request register (IRR) was latched: set when a source asserted and then never cleared or re-evaluated against the mask, so a masked or dropped request stayed set forever. The parisc core I/O dispatcher reads IRR to find its interrupt source, so the stuck bit was returned on every later interrupt as an "unexpected core I/O interrupt". On an installed HP-UX system an unacknowledged i82596 LAN interrupt latched this way and the flood wedged the boot. Derive IRR as (pending & unmasked) with IPR tracking each source's level, matching the hardware and the in-tree parisc gsc/lasi driver. Signed-off-by: Keith Monahan <keith@techtravels.org> Signed-off-by: Helge Deller <deller@gmx.de>

Keith Monahan committed Jul 1, 2026 at 17:33 UTC 79933616d9954e8be57821b73da0f0ec56722ee7
1 file changed +19 -6
hw/misc/lasi.c
+19 -6
@@ -62,7 +62,15 @@ static MemTxResult lasi_chip_read_with_attrs(void *opaque, hwaddr addr,
62
63 switch (addr) {
64 case LASI_IRR:
65 - val = s->irr;
65 + /*
66 + * The interrupt request register reports the interrupts that are both
67 + * pending and unmasked, derived live from IPR and IMR rather than
68 + * latched, so masking or deasserting a source removes it immediately.
69 + * The parisc core I/O interrupt dispatcher reads IRR; a latched bit
70 + * that never cleared would be redelivered forever as a phantom
71 + * "unexpected" interrupt.
72 + */
73 + val = s->ipr & s->imr;
74 break;
75 case LASI_IMR:
76 val = s->imr;
@@ -234,13 +242,18 @@ static void lasi_set_irq(void *opaque, int irq, int level)
242
243 if (level) {
244 s->ipr |= bit;
237 - if (bit & s->imr) {
245 + if ((bit & s->imr) && (s->icr & ICR_BUS_ERROR_BIT) == 0) {
246 uint32_t iar = s->iar;
239 - s->irr |= bit;
240 - if ((s->icr & ICR_BUS_ERROR_BIT) == 0) {
241 - stl_be_phys(&address_space_memory, iar & -32, iar & 31);
242 - }
247 + stl_be_phys(&address_space_memory, iar & -32, iar & 31);
248 }
249 + } else {
250 + /*
251 + * The interrupt sources are level triggered, so a source that drops
252 + * its request must clear its pending bit. Otherwise the bit stays set
253 + * in IPR (and hence IRR) and is redelivered as a phantom "unexpected"
254 + * core I/O interrupt on every later interrupt.
255 + */
256 + s->ipr &= ~bit;
257 }
258 }
259