DF-4806 / panic.txt
DF-4806 — clean evidence run (NO diagnostic probes; module = stock ppi.c +
arming.diff = the one-line `RF_ACTIVE` -> `RF_SHAREABLE` irq allocation fix
mirroring lpt.c:385; guest DragonFly 6.5-DEVELOPMENT X86_64_GENERIC, QEMU
PC-style LPT at 0x378 irq 7).
Trigger (root): ./ppi_intr_panic = open("/dev/ppi0") [registers ppiintr
with arg=cdev_t], open("/dev/io"), outb(0x37a,0x1c), outb(0x378,0x41),
strobe pulse -- the same sequence QEMU's emulated printer ACKs (8 strobes
=> 8 irq7 deliveries, cf. vmstat -i ppc0 counts in the stock run).
QEMU serial console (dfbsd-qemu/boot.log, 2026-09-24 02:09 UTC):
ppc0: <Standard parallel printer port> port 0x378-0x37f irq 7 on acpi0
ppc0: Generic chipset (NIBBLE-only) in COMPATIBLE mode
ppbus0: <Parallel port bus> on ppc0
ppi0: <Parallel I/O> on ppbus0
interrupt uses mplock: ppc0
sio2: can't drain, serial port might not exist, disabling
interrupt uses mplock: ppi0
Fatal trap 12: page fault while in kernel mode
cpuid = 1; lapic id = 1
fault virtual address = 0x0
fault code = supervisor read data, page not present
instruction pointer = 0x8:0xffffffff82604651
stack pointer = 0x10:0xfffff801187719a0
frame pointer = 0x10:0xfffff801187719d0
code segment = base 0x0, limit 0xfffff, type 0x1b
= DPL 0, pres 1, long 0, def32 0, gran 1
processor eflags = interrupt enabled, resume, IOPL = 0
current process = Idle
current thread = pri 28 (CRIT)
kernel: type 12 trap, code=0
CPU1 stopping CPUs: 0x0000003d
stopped
Stopped at ppiintr+0x41: movq (%rax),%rsi
db>
Interpretation:
- "interrupt uses mplock: ppi0": BUS_SETUP_INTR succeeded at ppiopen()
(ppi.c:266-269) with the shareable resource, registering ppiintr with
arg = the /dev/ppi0 cdev_t (the only `dev` in scope there, ppi.c:245).
- The first strobe's irq7 invoked ppiintr(cdev); the handler's first use
of its argument -- ppi_disable_intr(ppidev=(device_t)cdev) ->
device_get_parent(cdev) reads cdev+0x28 (struct cdev link.tqe_prev) ->
ppb_rctr(bogus) -> PPBUS_IO(device_get_parent(bogus)) -> movq (%rax)
with rax=0 -> supervisor read fault at 0x0.
- Trap 12 at interrupt context (current process Idle, pri CRIT) is fatal:
all CPUs stopped, DDB, guest dead. Instant unrecoverable kernel panic
from a single open() + one parallel-port interrupt.
Contrast: identical run against the STOCK module (RF_ACTIVE) survives all
strobes (stock_run.log) because the allocation fails -> no handler; and the
FIXED module (RF_SHAREABLE + ppidev arg) survives with interrupts delivered
(fix run logs in this pack).