elcr_resume() is dead code (zero callers) and no resync path exists β ELCR hardware state is never restored after a reset event nor re-read after probe; divergences are structurally invisible to the kernel
Summary
The only routine that writes the full shadow back has zero callers; the shadow is read from hardware exactly once and the write path early-outs on shadow match, making the kernel shadow-authoritative with no fallback. Live-verified: a raw outb flip was invisible to elcr_read_trigger (stale shadow served while the port read differently) and calling the dead elcr_resume() repaired the hardware byte-exactly - the dead function IS the missing fix. Doubly unreachable today (pc64 suspend stubbed, icu_reinit itself dead) but load-bearing the moment resume gains callers: every level-triggered ISA IRQ (incl. ACPI SCI) would silently run edge after resume. wire-into-icu_reinit fix.
Discussion (0)
PoC verification
Evidence pack
findings/poc/DF-5654 Β· 11 files| File | Type | Description | Size | |
|---|---|---|---|---|
| elcrx.c | β | 9.6 KB | view raw | |
| Makefile | β | 78 B | β download | |
| build.sh | β | 124 B | view raw | |
| run.sh | β | 167 B | view raw | |
| build.log | β | 6.7 KB | view raw | |
| run.log | β | 2.7 KB | view raw | |
| env.txt | β | 358 B | view raw | |
| fix.diff | β | 688 B | view raw | |
| VERDICT.md | β | 3.3 KB | β raw | |
| manifest.json | β | 954 B | view raw | |
| verdict.json | β | 4.1 KB | view raw |
DF-5654 β VERDICT
Finding: elcr_resume() (elcr.c:120-126) is dead code β zero
callers in sys/ β and no other path re-reads or rewrites the ELCR after
boot. The kernel's ELCR world model is: read hardware once in
elcr_probe() (elcr.c:75), keep a shadow, write deltas. Nothing ever
repairs the hardware from the shadow.
Verdict: REPRODUCED (live): the divergence is invisible to the kernel, and the dead function is exactly the missing repair. Severity Info (unreachable on this platform today β suspend itself is stubbed β but a real latent defect for the resume path).
Live proof (run.log phase D)
-
No resync path: the harness flips irq5's bit in the hardware with one raw
outb(0x4d0, b^0x20)(SMM/firmware/VM-migration surrogate).elcr_read_trigger(5)still returnsEfrom the stale shadow while the port reads0x20β the kernel literally cannot observe the divergence; there is no re-read of the register anywhere (grep:elcr_statusis assigned only at elcr.c:75 probe and elcr.c:113 write). -
The dead function is the exact fix: calling
elcr_resume()directly from the KLD rewrote both bytes from the shadow and the hardware returned to the 0x0c00 baseline byte-exactly (D2 ... repaired=YES). Onelwkt-safe call at the right resume hook is all that is missing.
Why this matters (and why only Info here)
- Resume: on ACPI S3 the PICs are reprogrammed by the wakeup path;
the ELCR (in the southbridge) loses nothing on this QEMU rig and β
more decisively β DragonFly/pc64 suspend is currently stubbed
(
acpi_sleep_machdepno-op, acpi_wakeup.c:50-54, confirmed in the DF-5616 pass), andicu_reinit()(icu.c:127, "ICU reinitialize when ICU configuration has lost") β the natural caller β is itself dead code. So the missing wiring is doubly unreachable today. The moment either gains a caller, ELCR trigger modes silently stay whatever the firmware reset them to (all-edge), breaking every level-triggered ISA IRQ (SCI included β acpi_fadt.c:195 configures it level through this very API). - Early-out blind spot (same class):
elcr_write_trigger()skips the port write when the shadow bit already matches (elcr.c:111-112), so a "set level" request for an irq whose shadow says level is a no-op even if the hardware bit was lost β the shadow-authoritative model has no fallback. - Not attacker-reachable: no unprivileged path; the divergence sources (SMM, migration, firmware) are environmental. Info.
Fix
Wire elcr_resume() into the ICU re-init path (icu_reinit(),
icu.c:127 β its documented purpose is "ICU reinitialize when ICU
configuration has lost"; the ELCR must be restored alongside the ICW
reprogram icu_init() performs). fix.diff adds the call (plus the
elcr_var.h include). When suspend/resume lands, the wakeup path
should call icu_reinit() (or elcr_resume() directly) β the live
D2 result proves the one-liner is sufficient.
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.
Fix verification
not_testableInfo/latent-defect finding β single-fix kernel rebuild not warranted (the affected path, suspend/resume + icu_reinit, is unreachable in the current tree). fix.diff adds the elcr_found-guarded elcr_resume() call to icu_reinit() ahead of icu_init(); its behavioral delta vs the live D2 result is precisely 'the repair that had to be induced by hand now runs at the re-init hook' β verified by inspection against run.log; nothing to regression-test on this rig.
fix.diff
Confirmed kernel references
Detail
Evidence (decisive lines)
run.log D1 line: 'raw outb flipped hw bit5: hw0x4d0=0x20 but elcr_read_trigger(5)=E -> kernel serves STALE shadow (no resync path exists; elcr_status read once at probe)' ; D2 line: 'after elcr_resume(): hw=0x0c00 baseline=0x0c00 repaired=YES (the dead function is exactly the missing fix)' ; E9: 'final hw=0x0c00 ... coherent=YES ... guest HEALTHY' (state left exactly as found)
PoC changes
Harness authored from scratch (no seed). v1 wedge documented under DF-5652 (wedge_v1.log); the D phase ran in the clean v2 pass. Divergence was induced and repaired entirely within the harness (raw outb flip -> elcr_resume() rewrite), leaving the ELCR byte-exact at its 0x0c00 baseline.
Verified recommended fix
Wire elcr_resume() into icu_reinit() (guard on elcr_found) so ELCR trigger modes are restored whenever the ICU configuration is re-established (elcr.c:120, icu.c:127)
Verdict
Live-verified on the QEMU/i440fx guest: elcr_resume() (elcr.c:120-126) has ZERO callers in sys/ β and no other path ever re-reads or rewrites the ELCR after boot (elcr_status is latched once in elcr_probe() at elcr.c:75 and only ever delta-written). The harness induced a hardware-side divergence with one raw outb(0x4d0, b^0x20) (surrogate for SMM/VM-migration/firmware/S3-reset): elcr_read_trigger(5) kept serving the stale shadow value (E) while the port read 0x20 β the divergence is structurally invisible to the kernel (no resync path exists). Calling the dead elcr_resume() directly rewrote both ELCR bytes from the shadow and restored the hardware to the 0x0c00 baseline byte-exactly ('D2 ... repaired=YES') β the missing wiring, proven. Consequence when a divergence source is real: every level-triggered ISA IRQ (including ACPI SCI, configured level through this API at acpi_fadt.c:195) silently runs edge β interrupt storms/lost interrupts. Severity Info because the defect is doubly unreachable today: pc64 suspend is stubbed (acpi_sleep_machdep no-op, acpi_wakeup.c:50-54) and the natural caller icu_reinit() (icu.c:127) is itself dead code; no unprivileged reach exists.
No comments yet.