# DF-3773 VERDICT — not_reproduced (no AHCI/PM hardware on guest); logic gap definite by source

## Bottom line

`ahci_beg_exclusive_access()` (ahci.c:2262-2270) spins on
`while (ap->ap_active || ap->ap_sactive)` calling only `ahci_port_intr()`. A
deferred-expired CCB — one whose timeout fired while other commands were active
(`ap->ap_expired` set, CCB *not* completed: ahci.c:3873-3884) — can never be
retired by that loop if the device never completes it, because
`ahci_port_intr()` only retires slots whose hardware CI/SACT bit cleared
(ahci.c:3152) and `ahci_check_active_timeouts()` is never called. The driver
demonstrates the correct discipline in `ahci_poll()`'s wait loop
(ahci.c:2160-2163), whose comment states the exact reason: the callout cannot
run while the port lock is held. `ahci_beg_exclusive_access()` holds the port
lock too (callers: ahci.c:938 via the state machine, run under `ap_lock` from
ahci_cam.c:888-890 / ahci_dragonfly.c:375), so the deferred timeout is
deadlocked by construction and the loop never exits.

Result: permanent wedge of the calling thread with `ap->ap_lock` held; the port
interrupt handler then deflects all port interrupts to the port thread
(ahci.c:2514-2517) which also blocks on the lock — the port is dead and one
kernel thread spins forever. DoS only (no memory unsafety). Preconditions:
port multiplier + hung target + deferred timeout + PM state-machine event.

## Not-reproduced rationale

The audit guest has no AHCI controller at all (env.txt: pciconf shows none,
root on virtio-blk, ahci static in GENERIC). The path needs real AHCI + PM
hardware misbehavior. Source reasoning is line-accurate and the asymmetry with
ahci_poll() is unambiguous.

## Recommended fix

Add timeout processing to the drain loop, mirroring `ahci_poll()`:

```c
	while (ap->ap_active || ap->ap_sactive) {
		ahci_port_intr(ap, 1);
		ahci_os_softsleep();
		ahci_check_active_timeouts(ap);	/* NEW: retire deferred-expired CCBs */
	}
```

see fix.diff (one line + comment).

## Fix status (batch validation)
Applied with the 36 sibling fix.diffs of this batch in findings/poc/_batch41/all_fixes.patch; single in-guest `make -j6 nativekernel KERNCONF=X86_64_GENERIC` completed RC=0 with zero errors under -Werror (full log: findings/poc/_batch41/fix_build8.log). Behavior A/B intentionally skipped for this Info-tier item.
