# DF-3772 — KKASSERT on hardware-fed CI/SACT consistency panics on chipset misbehavior the driver itself anticipates

File: `sys/dev/disk/ahci/ahci.c` (pass 2, GLM 5.3)

## What the bug is

`ahci_port_intr()` opens every invocation with:

```c
ci_saved = ahci_pread(ap, AHCI_PREG_SACT or AHCI_PREG_CI);   /* ahci.c:2615/2618 */
KKASSERT(!(ap->ap_sactive && ap->ap_active));                /* ahci.c:2621 */
KKASSERT((ci_saved & (ap->ap_sactive | ap->ap_active)) == ci_saved); /* ahci.c:2622 */
```

The second assertion requires the hardware CI/SACT register to be a **subset**
of the driver's software masks. DragonFly's own comments document that real
chipsets violate exactly this invariant:

- ahci.c:3117-3123: *"If we are stopped the AHCI chipset is supposed to have
  cleared CI and SACT. Did it? If it didn't we try very hard to clear the
  fields… IFS errors on (at least) AMD chipsets create this confusion."*
- ahci.c:3933-3948 (timeout path): detects `ahci_pactive() != 0` after a stop,
  prods the chip, and on failure only prints *"chipset failed to clear active
  cmds"* — i.e. the driver is designed to survive stale CI/SACT bits.
- ahci.h:1117-1122 (port_stop warning): stale CI/SACT races are expected.

But the recovery code at ahci.c:3125-3139 runs **after** the assert. Concrete
panic sequence (no other bug needed):

1. A command times out; `ahci_ata_cmd_timeout()` (ahci.c:3892) stops the port.
2. An affected chipset leaves the slot's CI bit set (the documented AMD-IFS
   behavior).
3. Timeout processing clears the software mask (ahci.c:3902/3905), restarts
   the port (3930), notices `ahci_pactive() != 0` (3940), prods, gives up with
   a kprintf (3943-3947).
4. The very next `ahci_port_intr()` (invoked by the timeout path itself at
   ahci.c:3951) re-reads CI with the stale bit set while the software mask no
   longer has it → KKASSERT at ahci.c:2622 fails → **kernel panic**.

Related asserts with the same trust model on the same error paths:
- `ahci_get_err_ccb()`: `KKASSERT(ci == 0)` (ahci.c:3351) on the hardware CI
  register read at 3346 — violated by the same stale-CI condition.
- `ahci_put_err_ccb()`: unconditional `panic("…but CI %08x != 0")`
  (ahci.c:3398-3403).

Impact: a device/chipset error condition that the driver is otherwise able to
recover from converts into a guaranteed kernel panic — denial of service.
Same attacker model as DF-1210/DF-1211 (device-fed registers), but impact is
panic, not OOB memory access → Low.

## Why not reproduced on the guest

No AHCI controller on the audit guest (see env.txt). The assert is only
reachable through a real AHCI interrupt/error path. Source-level reasoning is
line-accurate; verdict `not_reproduced` (device absent).

## Reproduce on suitable hardware

Any AHCI chipset known to leave CI/SACT dirty across a port stop during IFS
error recovery (driver comments call out AMD 880G/SB850-class parts), plus a
command timeout (hung/errored device). Alternatively a QEMU ich9-ahci
regression test that deasserts CI improperly.
