Re: [PATCH v4 3/6] target/m68k: Fix NMI pending for Level 7 interrupts
BALATON Zoltan <[email protected]>
| Newsgroups | org.nongnu.qemu-devel |
|---|---|
| Message-ID | <[email protected]> |
On Mon, 17 Aug 2026, 54weasels wrote: > High level description: > Level 7 interrupts are Non-Maskable Interrupts (NMI) on the M68k architecture. The hardware asserts an NMI only on the rising edge of the level 7 signal. The current QEMU implementation treats level 7 like a standard level interrupt. This patch ensures proper NMI edge-triggered semantics for level 7, which is strictly required by the Sun-3 keyboard/mouse NMI routing logic. > > Impact on existing functionality: > Corrects NMI edge-triggering for all M68k boards, adhering closely to the Motorola specifications. Existing boards will now correctly require an edge transition to trigger consecutive NMIs. > > Context: This patch was originally submitted as part of the monolithic Sun-3 Machine Emulation series (https://patchew.org/QEMU/[email protected]/) and has been split into atomic components. > --- > target/m68k/cpu.h | 1 + > target/m68k/helper.c | 6 ++++++ > target/m68k/op_helper.c | 14 ++++++-------- > 3 files changed, 13 insertions(+), 8 deletions(-) > > diff --git a/target/m68k/cpu.h b/target/m68k/cpu.h > index 7cf3791108..058777b891 100644 > --- a/target/m68k/cpu.h > +++ b/target/m68k/cpu.h > @@ -148,6 +148,7 @@ typedef struct CPUArchState { > > int pending_vector; > int pending_level; > + bool nmi_pending; What's the difference between nmi_pending and pending_level == 7? If nothing do we need a new variable for it or could just test pending_level? Regards, BALATON Zoltan > /* Fields up to this point are cleared by a CPU reset */ > struct {} end_reset_fields; > diff --git a/target/m68k/helper.c b/target/m68k/helper.c > index 68f523ea84..93739ccda7 100644 > --- a/target/m68k/helper.c > +++ b/target/m68k/helper.c > @@ -949,6 +949,12 @@ void m68k_set_irq_level(M68kCPU *cpu, int level, uint8_t vector) > CPUState *cs = CPU(cpu); > CPUM68KState *env = &cpu->env; > > + if (level == 7 && env->pending_level != 7) { > + env->nmi_pending = true; > + } else if (level != 7) { > + env->nmi_pending = false; > + } > + > env->pending_level = level; > env->pending_vector = vector; > if (level) { > diff --git a/target/m68k/op_helper.c b/target/m68k/op_helper.c > index 38f7a68981..30af4a2631 100644 > --- a/target/m68k/op_helper.c > +++ b/target/m68k/op_helper.c > @@ -522,14 +522,12 @@ bool m68k_cpu_exec_interrupt(CPUState *cs, int interrupt_request) > { > CPUM68KState *env = cpu_env(cs); > > - if (interrupt_request & CPU_INTERRUPT_HARD > - && ((env->sr & SR_I) >> SR_I_SHIFT) < env->pending_level) { > - /* > - * Real hardware gets the interrupt vector via an IACK cycle > - * at this point. Current emulated hardware doesn't rely on > - * this, so we provide/save the vector when the interrupt is > - * first signalled. > - */ > + if (env->nmi_pending) { > + env->nmi_pending = false; > + cs->exception_index = env->pending_vector; > + do_interrupt_m68k_hardirq(env); > + return true; > + } else if (((env->sr & SR_I) >> SR_I_SHIFT) < env->pending_level) { > cs->exception_index = env->pending_vector; > do_interrupt_m68k_hardirq(env); > return true; >