Files
xenia-rs/audit-runs/phase-c6-call-name-divergence/re-validation.md
MechaCat02 ef93a4fa14 handoff: VSync/event-wedge fixes + iterate 2.A–2.BC research notes
Source changes (dormant parity infra, retained from iterate 2.AI/2.AO):
- xenia-kernel/exports.rs: nt_create_event manual_reset polarity +
  related event wiring
- xenia-gpu/mmio_region.rs: D1MODE_VBLANK_VLINE_STATUS hardcode parity

Also lands the audit-runs/ analysis notes (.md/.txt/.json digests) for the
iterate 2.x VSync/0x10e8/0x1004 wedge investigation. Raw trace dumps
(.jsonl/.gz/.csv/.stdout) and agent worktrees (.claude/) are gitignored as
regenerable local artifacts — see memory + HANDOFF for the running findings.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-05 07:19:08 +02:00

4.1 KiB

Phase C+6 — re-validation

Gate 1 — Determinism (cvar-OFF, ours)

3 fresh runs of check -n 50000000 --stable-digest:

run digest md5
1 c6d895829b4611964978990ae1cb8a6a
2 c6d895829b4611964978990ae1cb8a6a
3 c6d895829b4611964978990ae1cb8a6a
C+5 baseline (cvar-OFF) c6d895829b4611964978990ae1cb8a6a

Result: byte-identical across 3 runs and SAME as the C+5 baseline. The Phase C+6 fix is purely an emitter-framing change (cvar phase_a_event_log OFF path): the unimplemented_exports HashSet is consulted only inside the phase_a_on guard in call_export. The stub body (stub_success, which sets r3 = 0) still runs unchanged. Therefore the cvar-OFF deterministic boot trajectory is unchanged. Baseline digest preserved.

Gate 2 — Phase B image_canonical_sha256

Phase B snapshot captured to snap/ours/. image_loaded_sha256 = ea8d160e9369328a5b922258a92113efb8d7ce3e1a5c12cc521e375985c91c18 matches the Phase-A/B verify baseline. The fix touches only the kernel-export shim/emitter layer — no PE image bytes modified.

Gate 3 — Phase A matched-prefix extension (KEY METRIC)

Diffed audit-runs/phase-c6-call-name-divergence/ours.jsonl against the existing phase-c-first-divergence/phase-a/canary.jsonl.

chain C+5 (pre-C+6) C+6 (post) Δ
canary tid=6 → ours tid=1 (main) 102132 102158 +26
canary tid=4 → ours tid=11 5 5 0
canary tid=7 → ours tid=2 15 15 0
canary tid=12 → ours tid=7 2 2 0
canary tid=14 → ours tid=9 39 39 0
canary tid=15 → ours tid=10 (no div) (no div) 0

Main thread matched prefix grew from 102132 to 102158. Gate 3 .

The new first-divergence at idx=102158 is XamTaskCloseHandle return_value: canary=1, ours=0 — value divergence, NOT a call-name divergence. That's the next Phase C+N target.

Gate 4 — Build

$ cargo build --release
   Compiling xenia-kernel v0.1.0
   Compiling xenia-app v0.1.0
    Finished `release` profile [optimized] target(s) in 6.22s

One pre-existing dead-code warning (walk_committed_regions); not introduced by this fix. Canary untouched.

Gate 5 — Phase A determinism (emitter)

Two cvar-ON captures of the same engine binary on the same ISO, md5-summing only deterministic fields (excluding host_ns AND guest_cycle — both are timing-sensitive, see Stage 2's established practice):

ours.jsonl     (run 1, det-fields-only)   7312446e49fa3c3149d26424832cabf4
/tmp/c6_pa_run2.jsonl (run 2, det-fields-only) 7312446e49fa3c3149d26424832cabf4

Byte-identical.

Note: digest changes from C+5's 388d394a… because the suppression flips 3 events on/off in the deterministic-fields stream. Expected.

Gate 6 — Kernel unit tests

$ cargo test --release -p xenia-kernel --lib
test result: ok. 145 passed; 0 failed; 0 ignored; 0 measured;
                 0 filtered out

1 new test added (144 → 145):

  • register_unimplemented_export_marks_set_membership — verifies the new register_unimplemented_export API both installs the export func (so call_export finds and runs the stub) AND inserts the (module, ord) pair into unimplemented_exports (so the Phase A emitter guard suppresses events). Cross-checks the negative case: a normal register_export does NOT mark unimplemented.

Full workspace test suite (cargo test --release --workspace): no regressions.

Summary

All 6 gates pass. Phase A main matched prefix grew from 102132 to 102158 (+26 events). One class-E (Phase A coverage gap) engine bug fixed: ours's emitter injected 3 spurious events (import.call/kernel.call/kernel.return) for IoDismountVolumeByFileHandle because canary's syscall-thunk path for table-entry-only exports never reaches Trampoline and emits nothing. New register_unimplemented_export API in state.rs lets us mark such exports for Phase A suppression while keeping their stub body execution intact. Cvar-OFF inert.

Diff-tool unchanged. Canary unchanged.

Next divergence: XamTaskCloseHandle return value at tid_event_idx=102158 (canary=1, ours=0 — value divergence). Phase C+7 target.