# DF-4957 VERDICT — ciphy no-media attach → panic("ifmedia_set")

**Status: NOT REPRODUCED end-to-end (no Cicada/Vitesse PHY hardware on
the guest; PHY registers are not emulatable). The kernel-side sink of
the chain is PROVEN live on this exact kernel — replaying
miibus_mediainit's terminal ifmedia_set() on an EMPTY media list (what
ciphy_attach's no-media branch at ciphy.c:142-147 leads to via
mii.c:229-246) yields `ifmedia_set: no match for 0x0/0xffffffff` →
`panic("ifmedia_set")` and kills the guest (panic.txt, full trace).
Fix mechanism validated live the same boot.**

## Root cause (source trace)

- `ciphy_attach` (sys/dev/netif/mii_layer/ciphy.c:142-147): if the PHY's
  BMSR reports no 10/100 media bits AND EXTSR no gigabit bits, the
  driver prints "no media present" and **skips `mii_phy_add_media`** —
  the only routine that would populate the miibus ifmedia list.
- ciphy.c:149 still calls `MIIBUS_MEDIAINIT(sc->mii_dev)` →
  `miibus_mediainit` (sys/dev/netif/mii_layer/mii.c:229-246): walks the
  now-EMPTY `ifm_list`, `media` stays 0, calls
  `ifmedia_set(&mii->mii_media, 0)`.
- DragonFly's `ifmedia_set` (sys/net/if_media.c) has no no-match
  fallback: `ifmedia_match` returns NULL on the empty list →
  `kprintf("ifmedia_set: no match ...")` → **`panic("ifmedia_set")`**.
  (FreeBSD's ifmedia_set prints and returns; the panic is a DragonFly
  divergence.)
- No parent of a CICADA/VITESSE PHY implements the `miibus_mediainit`
  hook (in-tree hooks exist only in if_xl/if_tx/if_dc; realistic ciphy
  parents are nfe/sk/vge — none hook it).
- Secondary effect of the same branch: had the boot survived,
  `ciphy_service` dereferences `mii->mii_media.ifm_cur` (ciphy.c:156,
  164, 255) which would be NULL.

## Why the atphy (DF-4930) one-line fix does NOT apply here

ciphy sets `sc->mii_flags |= MIIF_NOISOLATE` at ciphy.c:132 BEFORE the
media branch. `mii_phy_add_media`'s IFM_NONE fallback entry is added
only `if ((sc->mii_flags & MIIF_NOISOLATE) == 0)`
(mii_physubr.c:230-232). Therefore "just call mii_phy_add_media()
unconditionally" (the atphy fix) adds NOTHING for ciphy: the list stays
empty and the panic remains. **Every MIIF_NOISOLATE mii driver with this
branch (ciphy, rgephy set NOISOLATE too, …) needs an explicit fallback
entry or the shared `miibus_mediainit` must tolerate an empty list.**

## Verification on the guest

No CS8201/VSC8601 PHY exists under QEMU and MDIO register behavior
cannot be emulated, so the ciphy_attach path itself could not be
exercised (honest not_reproduced). The kernel-side sink WAS executed
with the real kernel functions via the `ciphysink` KLD (adapted from the
DF-4930 pack; run.sh):

1. `sysctl hw.ciphysink_fixcheck=1` — replays the FIXED ciphy path
   (ifmedia_init + explicit IFM_NONE entry + ifmedia_set): **survived**,
   `ifm_cur=0xfffff8004f102640` (non-NULL, which also protects
   ciphy_service's deref).
2. `sysctl hw.ciphysink_fire=1` — replays the STOCK ciphy path
   (empty-list ifmedia_set):

```
ifmedia_set: no match for 0x0/0xffffffff
panic: ifmedia_set
ifmedia_set() at ifmedia_set+0x53
ciphysink_fire() at ciphysink_fire+0x8e
sysctl_root ... userland_sysctl ... sys___sysctl
Debugger("panic") ; guest down
```

This is byte-for-byte the terminal behavior the ciphy chain produces on
a zero-media Cicada PHY at attach (boot-time or kldload).

## Fix

`fix.diff` (ciphy.c): in the no-media branch, after the "no media
present" print, add an explicit
`ifmedia_add(&mii->mii_media, IFM_MAKEWORD(IFM_ETHER, IFM_NONE, 0,
sc->mii_inst), MII_MEDIA_NONE, NULL)` — miibus_mediainit's ifmedia_set
then finds its match, no panic, and ifm_cur is non-NULL for
ciphy_service. Mechanism validated live (fixcheck above). The
framework-level alternative (make miibus_mediainit skip/tolerate an
empty list) would fix all ~20 sibling drivers at once and is the better
long-term fix; the per-driver diff keeps this pack self-contained.

Guest was reset with-src after the panic capture (boot.log rotated);
source of the panic text: serial console capture in panic.txt.

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