[AUDIT-059 R-D2] Phase D auto-signal POC confirms audit-049 wedge diagnosis
Hook NtCreateEvent for the silph::UImpl tid=13 chain (entry=0x821748F0, start_context=0x4024a840, frame-1 LR=0x821CB15C inside sub_821CB030+0x128) and auto-signal the resulting handle after XENIA_SILPH_UI_AUTOSIGNAL_DELAY instructions. Env-gated; default off. SR4 verdict B (partial unwedge): - handle 0x1078 signal_attempts 0->1 - tid=13 Blocked(WaitAny[0x1078]) -> Ready pc=0x824a9108 - ExCreateThread 10 -> 12 (new silph::UImpl tid=14, worker tid=15) - New downstream wedges 0x1084 + 0x1088 - cxx_throw runtime_error on tid=5 inside R26 dispatcher (BST not-registered instance lhs=0x715a7af0) - VdSwap stays 1; no draws (POC is diagnostic, not final fix) Confirms Phase C diagnosis end-to-end. The real signaler must (a) drive NtSetEvent on the silph KEVENT AND (b) register the dispatcher's BST instance upstream; this POC only does (a). Reading-error class #20: ctx.lr at kernel export entry is the thunk wrapper's return slot, NOT the guest caller's post-bl PC. Walk back-chain 1 step to get frames[1].lr. Reading-error class #21: --parallel and lockstep have SEPARATE outer loops in main.rs (run_execution_parallel line 2928 vs run_execution line 2706). Per-round hooks must be wired in BOTH paths. Files: - crates/xenia-cpu/src/scheduler.rs: GuestThread.start_entry/start_context fields + spawn() population + current_thread_entry_and_ctx() helper - crates/xenia-kernel/src/state.rs: AutoSignalPending struct, env-parsed silph_autosignal_delay, pending Vec, last_cycle_hint, set_now_cycle_hint, maybe_register_silph_autosignal (walks back-chain), fire_due_silph_autosignals - crates/xenia-kernel/src/exports.rs: hook in nt_create_event - crates/xenia-app/src/main.rs: fire-site + cycle hint in both outer loops - audit-runs/audit-059-handle-disambiguation/round-D2-autosignal-poc/FINDINGS.md Tests 655/655 green. Default behavior byte-identical when env unset. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -117,6 +117,14 @@ pub struct GuestThread {
|
||||
/// Axis 3 instruction budget. Decremented per retired step on this
|
||||
/// thread; on zero, slot rotates within same-priority tier.
|
||||
pub quantum_remaining: u32,
|
||||
/// SpawnParams.entry — the BL target the trampoline jumped to.
|
||||
/// Persisted so kernel exports can filter syscalls by spawning
|
||||
/// chain (e.g. the silph UI auto-signal POC). 0 for the initial
|
||||
/// thread (uses `install_initial_thread`, not `spawn`).
|
||||
pub start_entry: u32,
|
||||
/// SpawnParams.start_context — initial r3 at spawn. Persisted for
|
||||
/// the same filtering reason as `start_entry`.
|
||||
pub start_context: u32,
|
||||
}
|
||||
|
||||
impl GuestThread {
|
||||
@@ -136,6 +144,8 @@ impl GuestThread {
|
||||
affinity_mask: 0xFF,
|
||||
ideal_processor: None,
|
||||
quantum_remaining: QUANTUM_DEFAULT,
|
||||
start_entry: 0,
|
||||
start_context: 0,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -500,6 +510,17 @@ impl Scheduler {
|
||||
self.current.expect("no current thread")
|
||||
}
|
||||
|
||||
/// `(start_entry, start_context)` of the currently-running thread.
|
||||
/// Returns None if there is no current thread or its ref is stale.
|
||||
/// Used by `KernelState::maybe_register_silph_autosignal` to filter
|
||||
/// `NtCreateEvent` calls by spawning chain.
|
||||
pub fn current_thread_entry_and_ctx(&self) -> Option<(u32, u32)> {
|
||||
let r = self.current?;
|
||||
let slot = self.slots.get(r.hw_id as usize)?;
|
||||
let t = slot.runqueue.get(r.idx as usize)?;
|
||||
Some((t.start_entry, t.start_context))
|
||||
}
|
||||
|
||||
// ----- Guest-thread lookup -----
|
||||
|
||||
/// Find the `ThreadRef` of the (non-Exited) thread with `tid`.
|
||||
@@ -614,6 +635,8 @@ impl Scheduler {
|
||||
t.priority = params.priority;
|
||||
t.affinity_mask = mask;
|
||||
t.ideal_processor = params.ideal_processor;
|
||||
t.start_entry = params.entry;
|
||||
t.start_context = params.start_context;
|
||||
// M3.7 — populate the inter-thread reservation handle + slot id
|
||||
// so the interpreter can route lwarx/stwcx through the table.
|
||||
t.ctx.hw_id = slot_id;
|
||||
|
||||
Reference in New Issue
Block a user