sk_marv_miibus_writereg(): inverted YU_SMICR_BUSY check aborts the SMI write-completion wait the moment the write starts (vs correct msk_phy_writereg sibling)
Summary
The completion wait breaks as soon as BUSY is SET - i.e. when the write has just started - and otherwise burns the full 1000xDELAY(1) when idle; the wait never waits. Back-to-back SMI writes can hit the one-op-at-a-time SMI engine while the previous write is in flight and be silently dropped -> intermittent PHY misconfiguration/link flaps on Yukon hardware. Two-token inverted condition vs the in-tree correct msk sibling for the same PHY family. Hardware-gated; one-token fix.
Discussion (0)
PoC verification
Evidence pack
findings/poc/DF-3905 Β· 4 files| File | Type | Description | Size | |
|---|---|---|---|---|
| README.md | β | 2.5 KB | β raw | |
| fix.diff | β | 650 B | view raw | |
| manifest.json | β | 932 B | view raw | |
| verdict.json | β | 2.7 KB | view raw |
DF-3905 β sk_marv_miibus_writereg(): inverted BUSY check aborts the SMI
write-completion wait the moment the write starts
File: sys/dev/netif/sk/if_sk.c (pass 2, GLM 5.3)
Hardware-gated: Yukon (SK_YUKON*) PHY writes only happen on real
Marvell/SysKonnect hardware; the audit guest has none. Source-certain via
comparison with the sibling driver and FreeBSD/OpenBSD lineage.
The bug (source)
sk_marv_miibus_writereg() (sys/dev/netif/sk/if_sk.c:507-529) issues an
SMI (MII management) write and then tries to wait for completion:
SK_YU_WRITE_2(sc_if, YUKON_SMICR, ... | YU_SMICR_OP_WRITE); /* :515-517 */
for (i = 0; i < SK_TIMEOUT; i++) { /* :519 */
DELAY(1);
if (SK_YU_READ_2(sc_if, YUKON_SMICR) & YU_SMICR_BUSY) /* :521-522 */
break; /* WRONG */
}
The condition is inverted: it breaks the wait as soon as BUSY is set β i.e. exactly when the write has started β and otherwise burns the full 1000ΓDELAY(1) loop when the PHY is idle. The correct protocol (wait while BUSY is set, proceed when it clears) is what the sibling driver implements for the same hardware family:
msk_phy_writereg()βsys/dev/netif/msk/if_msk.c:417-428:if ((GMAC_READ_2(...GM_SMI_CTRL) & GM_SMI_CT_BUSY) == 0) break;
So under if_sk.c the "wait for write completion" never waits for the
completion. Consequences on Yukon hardware: the caller (miibus layer,
sk_init_yukon, mii_mediachg from the 1 Hz tick / media ioctls) can
issue the next SMI operation while the previous PHY write is still in
flight; Marvell SMI executes one operation at a time, so back-to-back
writes can be silently dropped β PHY configuration (aneg restart, power
state, media override) intermittently not taking effect. This is a
functional-correctness bug (media/PHY state machine misconfiguration, link
flaps), not memory corruption.
Lineage
The inverted form is a DFly-carried transcription bug (present since the
driver import); FreeBSD if_sk.c historically waits with
(SMICR & BUSY) == 0.
Why not runtime-verified
No Yukon silicon on the audit guest (YUKON_SMICR MMIO unreachable);
the defect is a two-token logic inversion proven by source diff against
the in-tree sibling driver handling the same PHY. status inconclusive
per family convention for hardware-gated findings.
Fix
fix.diff: invert the break condition to (... & YU_SMICR_BUSY) == 0,
matching msk_phy_writereg() exactly.
Fix verification
inconclusiveTwo-token condition inversion, byte-identical in shape to the proven-correct msk_phy_writereg sibling. Not runnable on this guest (no Yukon NIC).
findings/poc/DF-3905/fix.diff
Confirmed kernel references
Detail
Evidence (decisive lines)
findings/poc/DF-3905/README.md (side-by-side with the msk sibling); findings/poc/DF-3905/fix.diff (condition inversion)
PoC changes
No seed PoC; no runnable trigger exists without Yukon silicon (YUKON_SMICR MMIO). The proof is the source diff against the in-tree sibling driver for the same PHY.
Verified recommended fix
Invert the break condition in sk_marv_miibus_writereg to (... & YU_SMICR_BUSY) == 0, mirroring msk_phy_writereg.
Verdict
Source-certain logic inversion, hardware-gated (no Yukon silicon on the audit guest) -> inconclusive per family convention. sk_marv_miibus_writereg (sys/dev/netif/sk/if_sk.c:519-523) breaks its SMI write-completion wait as soon as YU_SMICR_BUSY is SET - i.e. the moment the write starts - and otherwise spins the full SK_TIMEOUT when the PHY is idle: the wait-for-completion never waits. The sibling driver for the same hardware implements the correct protocol: msk_phy_writereg (sys/dev/netif/msk/if_msk.c:417-428) breaks on (GM_SMI_CT_BUSY) == 0. Consequence on Yukon hardware: back-to-back SMI writes (miibus config, sk_init_yukon, mii_mediachg from the 1 Hz tick/media ioctls) can be issued while the previous PHY write is still in flight and silently dropped by the one-op-at-a-time SMI engine - intermittent PHY misconfiguration/link flaps. Functional-correctness bug, not memory corruption; severity Low. fix.diff inverts the condition to match msk_phy_writereg.
No comments yet.