[2.BF] Synthetic silph::WorkerCtx spawn (round 18 — opt-in landing)
Adds infrastructure to synthesise the silph::WorkerCtx that AUDIT-058/059 identified as never reached by ours' static-init chain (real chain entry sits in audit-059 round 9's wrong-vtable wedge at sub_82172BA0+0x1E8). Ctx layout follows round 5's live hexdump from canary: +0x00 vtable = 0x8200A1E8 +0x04 self +0x08 intrusive list head -> self +0x0C init flag = 1 +0x10 packed byte field +0x18 2x float ~1.0 (UI rates) +0x24 flag = 1 +0x28..+0x30 3x foreign-arena pointers (left NULL — see below) +0x54..+0x84 4x X_KEVENT auto-reset, state=0 +0x94..+0xC4 4x X_KEVENT manual-reset, state=1 (pre-signaled) +0x210..+0x250 4-entry intrusive work-ring, empty Worker spawn mirrors AUDIT-048's audio-worker pattern in xaudio_register_render_driver: per-worker allocate_thread_image + state.scheduler.spawn with r3 = ctx_ptr. Trigger fires at the first dat/* VFS open (ours' earliest is dat/files.tbl), which is when canary runs the equivalent chain. ROUND 18 OUTCOME — opt-in only: With workers spawned Ready (XENIA_SILPH_SYNTH=1), boot CRASHES at cycle ~5.5M with PC=0 on hw=1, just after worker_3 (entry 0x825065B8) spawns. Per task constraints this is STOP-and-report: the ctx fields +0x28/+0x2C/+0x30 (foreign heap pointers — canary's 0x30057018, 0xBCE25640, 0xBE568F00, distinct arenas per audit-059 round 7) are left NULL, and the worker bodies plausibly dereference one of them. Synthesising those is a fresh investigation (round 19+). With workers spawned Suspended (XENIA_SILPH_SYNTH=suspend), boot completes normally (11 spawns, VdSwap=1, KeSetEvent=2, KeReleaseSemaphore=1 — matches default baseline). The ctx remains materialised in guest memory at the logged VA for downstream probing. Default (env var unset): no synth, no regression. Files: crates/xenia-kernel/src/silph_synth.rs (new, 225 LOC) crates/xenia-kernel/src/lib.rs (+1 LOC, register module) crates/xenia-kernel/src/exports.rs (+37 LOC, hook in open_vfs_file) crates/xenia-kernel/src/state.rs (+18 LOC, 4 silph_synth_* fields) Tests: cargo test --release --workspace = 765 pass / 0 fail. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -980,6 +980,43 @@ fn open_vfs_file(
|
||||
// see a null handle later and trigger `XamShowDirtyDiscErrorUI`.
|
||||
let path = crate::path::object_attributes_to_vfs_path(mem, obj_attrs_ptr)
|
||||
.unwrap_or_default();
|
||||
// AUDIT-2.BF — synthetic silph::WorkerCtx spawn. AUDIT-058/059
|
||||
// identified that ours never activates the 6-level static caller
|
||||
// ladder that ends in `sub_825070F0`, so the four worker threads
|
||||
// it would normally spawn (entries 0x82506528/58/88/B8) never run.
|
||||
// Canary's chain originally fires right after `DiscImageDevice::
|
||||
// ResolvePath("\\dat\\movie")` (audit-058); ours never opens
|
||||
// `dat/movie` because tid=13 wedges before reaching it. We
|
||||
// therefore trigger on the first `dat/*` open — the earliest
|
||||
// such open in ours is `dat/files.tbl` (immediately preceding
|
||||
// tid=12/13 spawn at audit-059 round 1).
|
||||
//
|
||||
// **Round 18 finding** (this commit): when the workers are
|
||||
// spawned runnable, they fault almost immediately (`PC=0` at
|
||||
// cycle ~5.5M on the hw thread carrying worker_3), preempting
|
||||
// ours' boot before the normal guest threads even spawn. The
|
||||
// ctx layout from audit-059 round 5 is incomplete — at least
|
||||
// one of `[+0x28]`/`[+0x2C]`/`[+0x30]` (the three foreign-
|
||||
// arena pointers) must be populated for the worker bodies to
|
||||
// run. Synthesising those is a fresh investigation (round 19+).
|
||||
//
|
||||
// Until then the synth path is **opt-in**: set
|
||||
// `XENIA_SILPH_SYNTH=1` to enable the runnable spawn (will
|
||||
// crash boot), or `XENIA_SILPH_SYNTH=suspend` to spawn but keep
|
||||
// them in `Blocked(Suspended)` (lets boot complete with the
|
||||
// ctx materialised in memory for downstream probes). Default:
|
||||
// disabled — preserves the existing boot trajectory.
|
||||
if !state.silph_synth_done && path.starts_with("dat/") {
|
||||
match std::env::var("XENIA_SILPH_SYNTH").as_deref() {
|
||||
Ok("1") | Ok("run") | Ok("runnable") => {
|
||||
let _ = crate::silph_synth::spawn_silph_workers(state, mem, false);
|
||||
}
|
||||
Ok("suspend") | Ok("suspended") => {
|
||||
let _ = crate::silph_synth::spawn_silph_workers(state, mem, true);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
if path.is_empty() && obj_attrs_ptr == 0 {
|
||||
if handle_out != 0 {
|
||||
mem.write_u32(handle_out, 0);
|
||||
|
||||
Reference in New Issue
Block a user