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