# DF-3772 VERDICT — not_reproduced (no AHCI hardware on guest); panic path certain by source

## Bottom line

`ahci_port_intr()` asserts that the hardware-fed CI/SACT register snapshot is a
subset of the driver's software slot masks (ahci.c:2621-2622). The driver's own
comments and recovery code (ahci.c:3117-3139, 3933-3948) document that real
chipsets — specifically AMD parts after IFS errors — leave stale CI/SACT bits
after a port stop, and the driver is written to survive that condition. The
KKASSERT runs before any of that recovery on every interrupt, so the documented
misbehavior is turned into a guaranteed `panic()` instead of the intended
recovery. The same pattern exists as `KKASSERT(ci == 0)` on a hardware read in
`ahci_get_err_ccb()` (ahci.c:3346-3351) and as an explicit
`panic("…but CI %08x != 0")` in `ahci_put_err_ccb()` (ahci.c:3397-3403).

## Chain (why the assert fires despite the "recovery")

- ahci.c:3890-3907 — timeout: read CI/SACT, stop port, clear software masks for
  expired slots.
- ahci.c:3930 — restart port.
- ahci.c:3940-3948 — detect stale hardware bits (`ahci_pactive() != 0`), prod,
  then give up with a *warning only* ("what do we do now?" — ahci.c:3137).
- ahci.c:3951 — call `ahci_port_intr(ap, 0)`; at ahci.c:2615/2618 the stale
  bits are read into `ci_saved`; software masks were cleared at 3902/3905;
  KKASSERT at 2622 fails → panic.

No memory corruption — the subsequent walks are properly masked by software
bits (checked: ahci.c:3080 `ci_masked = ci_saved & *active & ~ap->ap_expired`,
ahci.c:3152 `ci_masked = ~ci_saved & *active`). The defect is purely the
assert's contradiction with the driver's own hardware-behavior assumptions.
CWE-617 (reachable assertion) → DoS only → Low.

## Not-reproduced rationale

The guest has zero AHCI hardware (env.txt: pciconf empty, virtio-blk root, ahci
static in GENERIC). The assert lives on the AHCI interrupt path and cannot be
entered. No amount of guest setup short of a different QEMU machine config
(vm.sh is fixed to virtio-blk) can instantiate it.

## Recommended fix

Replace the hardware-subset KKASSERT at ahci.c:2622 with mask-and-warn (keep
the software-only invariant assert at 2621), downgrade `ahci_get_err_ccb()`'s
KKASSERT (ahci.c:3351) to a warning + CI register clear, and replace
`ahci_put_err_ccb()`'s `panic()` (ahci.c:3398) with a kprintf + register clear.
fix.diff generated from a scratch worktree and verified to apply cleanly
against the pristine tree.

## 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.
