From 793185d0348fb22a933590231d487f73db57dac0 Mon Sep 17 00:00:00 2001 From: Mihai Parparita Date: Wed, 14 Oct 2026 17:24:13 -0700 Subject: [PATCH] macio: Keep interrupt events and CPU IRQ state consistent Apply the Grand Central fixes from dingusdev/dingusppc#240 to O'Hare, Heathrow, and Paddington; the Heathrow ERS shows that it expects to have the same behavior: - Reevaluate the CPU interrupt when either mask changes, releasing it if no pending events remain enabled in either bank (section 7.1). - Keep events latched until software writes InterruptClear, even if a device deasserts its interrupt line or repeats an assertion (sections 7.2.1 and 7.2.5). - Replace writable InterruptMask2 bits instead of ORing them, allowing sources to be disabled while preserving the read-only IntMode bit (section 7.2.6). --- devices/ioctrl/maciobase.cpp | 4 ++-- devices/ioctrl/maciotwo.cpp | 6 +++++- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/devices/ioctrl/maciobase.cpp b/devices/ioctrl/maciobase.cpp index b2bca143b8..c2f74b53fb 100644 --- a/devices/ioctrl/maciobase.cpp +++ b/devices/ioctrl/maciobase.cpp @@ -145,9 +145,9 @@ void MacIoBase::ack_int_common(uint64_t irq_id, uint8_t irq_line_state) { if ((this->int_mask & MACIO_INT_MODE) || (irq_line_state && !(this->int_levels & irq_id))) { this->int_events |= irq_id; - } else { - this->int_events &= ~irq_id; } + // Events remain latched until software writes InterruptClear. + // update IRQ line state if (irq_line_state) { this->int_levels |= irq_id; diff --git a/devices/ioctrl/maciotwo.cpp b/devices/ioctrl/maciotwo.cpp index ce9ba17366..40ced99a8d 100644 --- a/devices/ioctrl/maciotwo.cpp +++ b/devices/ioctrl/maciotwo.cpp @@ -366,7 +366,10 @@ void MacIoTwo::mio_ctrl_write(uint32_t offset, uint32_t value, int size) { switch (offset & ~3) { case MIO_INT_MASK2: - this->int_mask |= uint64_t(value & ~MACIO_INT_MODE) << 32; + // Preserve the first bank and the read-only IntMode bit. + this->int_mask = (this->int_mask & 0x80000000FFFFFFFFULL) | + (uint64_t(value & ~MACIO_INT_MODE) << 32); + this->clear_cpu_int(); this->signal_cpu_int(); break; case MIO_INT_CLEAR2: @@ -377,6 +380,7 @@ void MacIoTwo::mio_ctrl_write(uint32_t offset, uint32_t value, int size) { this->int_mask = (this->int_mask & 0x7FFFFFFF00000000ULL) | value; // copy IntMode bit to InterruptMask2 register this->int_mask |= uint64_t(this->int_mask & MACIO_INT_MODE) << 32; + this->clear_cpu_int(); this->signal_cpu_int(); break; case MIO_INT_CLEAR1: