Files
xenia-rs/audit-runs/phase-b-state-equivalence/ours-changes.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.7 KiB
Raw Blame History

Phase B — ours changes inventory

All instrumentation is additive and cvar-gated default-off. With KernelState::phase_b_snapshot_dir == None (the default), the worker_prologue hook is one Option-tag test; the emitter module is unreached. Gate 1 verified xenia-rs check --stable-digest -n 50M produces a byte-identical digest pre/post-patch (see validation.md).

New files

  • crates/xenia-kernel/src/phase_b_snapshot.rs — emitter for all five snapshot files + manifest. Stdlib serde_json + sha2; no new transitive deps beyond what was already pulled into the workspace. ~590 LOC.
  • tools/diff-state/diff_state.py — stdlib-only Python. Reads both engines' snapshot dirs, classifies divergences by class (σ-structural, δ-content, γ-kernel-content, κ-cache, ε-host-allocator, τ-host-timing), enforces STOP gate on image_loaded_sha256/xex_entry_point/iso_sha256. ~380 LOC.
  • tools/diff-state/README.md — usage + rules reference.

Modified files

crates/xenia-app/src/main.rs

  • Around line 251: three new Exec flags — --phase-b-snapshot-dir <DIR>, --phase-b-snapshot-and-exit, --phase-b-dump-section-content.
  • Around line 420: env-var fallback (XENIA_PHASE_B_SNAPSHOT_DIR, XENIA_PHASE_B_SNAPSHOT_AND_EXIT, XENIA_PHASE_B_DUMP_SECTION_CONTENT); plumbed through cmd_exec (signature gained three trailing args).
  • Around line 945: kernel.entry_pc = entry; kernel.phase_b_snapshot_dir = …; etc. — feeds the resolved values to KernelState for the hook to read.
  • Around line 2228 (worker_prologue): single hook call into xenia_kernel::phase_b_snapshot::fire_if_entry_thread(kernel, mem, pc, current_tid), gated by kernel.phase_b_snapshot_dir.is_some() (zero-cost when None).
  • cmd_check updated to thread three None/false defaults so the golden digest path stays unaffected.

crates/xenia-kernel/src/state.rs

  • Four new public fields on KernelState: phase_b_snapshot_dir: Option<PathBuf>, phase_b_snapshot_and_exit: bool, phase_b_dump_section_content: bool, entry_pc: u32. Default-constructed None/false/0.

crates/xenia-kernel/src/lib.rs

  • Adds pub mod phase_b_snapshot; to the module list (alphabetical position after objects).

crates/xenia-kernel/Cargo.toml

  • New dependencies: serde_json (workspace), sha2 (workspace, newly added), libc = "0.2" (for _exit).

Cargo.toml (workspace)

  • New sha2 = "0.10" workspace dependency.

Snapshot mechanism

When phase_b_snapshot_dir is Some, the hook in worker_prologue calls fire_if_entry_thread exactly once. The helper:

  1. Fast-path early-returns when phase_b_snapshot_dir == None (Option-tag check).
  2. Returns if DONE is already set (subsequent slot visits).
  3. Returns if pc != entry_pc || current_tid != INITIAL_GUEST_TID (this slot visit is not the entry thread's first instruction).
  4. CAS-claims CLAIMED (one-shot guard against any race).
  5. Calls write_snapshot, which builds five serde_json::Value trees, serializes each with serialize_sorted (a deterministic walker that sorts object keys via BTreeMap-equivalent), writes each via File::create + flush + sync_all, indexes the SHA-256s into manifest.json.
  6. If phase_b_snapshot_and_exit, calls libc::_exit(0) so the snapshot is durable and the process terminates before the host scheduler or other threads can perturb on-disk state.

What's in each snapshot file (ours side)

file content
cpu_state.json pc (= entry_pc), gpr[32] (raw u64 hex), fpr[32] (raw bit-pattern hex), vr[128] + vscr (32-hex BE byte order), cr[8], xer/msr/ctr/lr/vrsave/fpscr, thread_id, stack_base/limit, tls_base, pcr_base.
memory.json regions[] — named ranges (XEX image, main stack, PCR, TLS) each with SHA-256. heaps[] — 4 heap descriptors with committed-page histograms. committed_pages_total.
kernel.json objects[] (sorted by FNV-1a stable handle_semantic_id) — type, type_code, details (per-type fields like thread_id/is_entry_thread). exports_registered_count/sha256/sample[].
vfs.json resolve_path_probes[] — canonical 10-path probe set. mounted_devices_observed_count. cache_root_listing[].
config.json xex_entry_point, xex_image_base/size, image_loaded_sha256 (the primary cross-engine invariant), cvars{}, host_ns_at_snapshot / wall_clock_iso8601 (deterministic_skip-flagged).