DF-3829 / nmi_ddb_evidence.txt
NMI delivery evidence (captured live from the serial console before the
guest was rebooted; boot.log.vmx was truncated by the restart).
Trial: `nvmm_drive spin 24 6` (6 vCPUs spinning in VMX non-root) with
three QEMU-monitor `nmi` injections at ~12s, ~15s, ~18s.
Result: the guest dropped into DDB:
CPU0 stopping CPUs: 0x0000003e
stopped
Stopped at vmx_vcpu_run+0x522: movl %dr0,%edx
db> 3
Interpretation
--------------
The NMI that froze the CPU landed while the CPU was executing nvmm's
*host-side* run loop (`vmx_vcpu_run+0x522` is in the DR-register
save/restore region, `x86_get_dr0()` inside `vmx_vcpu_guest_dbregs_leave`,
nvmm_x86_vmx.c:2131). With `machdep.ddb_on_nmi=1` (default), that NMI was
delivered to DragonFly's trap() handler -> DDB.
=> NMIs arriving while the CPU is in the host-side part of the run loop
ARE delivered normally. The swallow window of DF-3829 is only the
non-root residency: an NMI that arrives while the vCPU is executing
the guest causes VMCS exit reason 0 (EXC_NMI) with EXIT_INTR_INFO
type=NMI, which `vmx_exit_exc_nmi()` (nvmm_x86_vmx.c:1252-1271)
classifies as NVMM_VCPU_EXIT_NONE and re-enters the guest -- the NMI
is never dispatched to the host.
Why the differential cannot be isolated on this guest: QEMU's monitor
`nmi` injects an NMI on *all* 6 vCPUs simultaneously; with 6 CPUs the
probability that at least one NMI lands in a host-side window (and thus
DDB-freezes the machine, masking the swallow) is overwhelming. On real
hardware, or with a per-CPU NMI source, the differential would be:
control (no vCPU resident) -> "NMI ... going to debugger"; vCPU resident
-> nothing, run loop continues.
verdict for DF-3829: status=inconclusive (live), root-cause established
by code reading (NetBSD added nmi_dispatch() upstream for exactly this).