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>
107 lines
4.3 KiB
Diff
107 lines
4.3 KiB
Diff
# Phase C+7-only diff (synthesized from working tree minus cumulative C+5/C+6/C+6½/XAM changes)
|
|
#
|
|
# Full uncommitted diff is in `fix.diff` (1431 lines, includes all
|
|
# pre-existing Phase C work since HEAD).
|
|
#
|
|
# This file isolates the ~30 LOC body changes + ~160 LOC test additions
|
|
# that constitute Phase C+7.
|
|
|
|
--- a/crates/xenia-kernel/src/exports.rs (C+6½ baseline)
|
|
+++ b/crates/xenia-kernel/src/exports.rs (C+7)
|
|
|
|
# Body 1: ke_set_event — match canary's constant-1 return (xevent.cc:60-64)
|
|
|
|
-fn ke_set_event(ctx: &mut PpcContext, mem: &GuestMemory, state: &mut KernelState) {
|
|
- let h = ctx.gpr[3] as u32;
|
|
- ensure_dispatcher_object(state, mem, h);
|
|
- let previous = match state.objects.get_mut(&h) {
|
|
- Some(KernelObject::Event { signaled, .. }) => {
|
|
- let prev = *signaled;
|
|
- *signaled = true;
|
|
- prev as u32
|
|
- }
|
|
- _ => 0,
|
|
- };
|
|
- state.audit_signal(h, ctx.lr as u32, "KeSetEvent", previous as u64);
|
|
- wake_eligible_waiters(state, h);
|
|
- ctx.gpr[3] = previous as u64;
|
|
-}
|
|
+fn ke_set_event(ctx: &mut PpcContext, mem: &GuestMemory, state: &mut KernelState) {
|
|
+ let h = ctx.gpr[3] as u32;
|
|
+ ensure_dispatcher_object(state, mem, h);
|
|
+ // Canary parity (xevent.cc:60-64): `XEvent::Set` returns constant `1`
|
|
+ // on success, NOT the prior signaled state as the NT contract claims.
|
|
+ // We compute `previous` for internal bookkeeping (audit_signal,
|
|
+ // wake_eligible_waiters honor the prior-state read), but report
|
|
+ // `1` for success / `0` for "no dispatcher found" to match the
|
|
+ // canary Phase A oracle. See Phase C+7 investigation.md.
|
|
+ let (previous, found) = match state.objects.get_mut(&h) {
|
|
+ Some(KernelObject::Event { signaled, .. }) => {
|
|
+ let prev = *signaled;
|
|
+ *signaled = true;
|
|
+ (prev as u32, true)
|
|
+ }
|
|
+ _ => (0u32, false),
|
|
+ };
|
|
+ state.audit_signal(h, ctx.lr as u32, "KeSetEvent", previous as u64);
|
|
+ wake_eligible_waiters(state, h);
|
|
+ ctx.gpr[3] = if found { 1 } else { 0 };
|
|
+}
|
|
|
|
# Body 2: nt_set_event — out-pointer writes constant 1 not prior state
|
|
# (xboxkrnl_threading.cc:610-628 + xevent.cc:60-64 chain)
|
|
|
|
-fn nt_set_event(ctx: &mut PpcContext, mem: &GuestMemory, state: &mut KernelState) {
|
|
- let handle = ctx.gpr[3] as u32;
|
|
- let prev_ptr = ctx.gpr[4] as u32;
|
|
- let previous = match state.objects.get_mut(&handle) {
|
|
- Some(KernelObject::Event { signaled, .. }) => {
|
|
- let prev = *signaled;
|
|
- *signaled = true;
|
|
- prev as u32
|
|
- }
|
|
- _ => 0,
|
|
- };
|
|
- state.audit_signal(handle, ctx.lr as u32, "NtSetEvent", previous as u64);
|
|
- wake_eligible_waiters(state, handle);
|
|
- if prev_ptr != 0 {
|
|
- mem.write_u32(prev_ptr, previous);
|
|
- }
|
|
- ctx.gpr[3] = STATUS_SUCCESS;
|
|
-}
|
|
+fn nt_set_event(ctx: &mut PpcContext, mem: &GuestMemory, state: &mut KernelState) {
|
|
+ let handle = ctx.gpr[3] as u32;
|
|
+ let prev_ptr = ctx.gpr[4] as u32;
|
|
+ // Canary parity (xboxkrnl_threading.cc:610-628): the optional out-pointer
|
|
+ // is filled with `was_signalled` = `ev->Set()` = constant 1 (see
|
|
+ // xevent.cc:60-64), NOT the prior signaled state. r3 carries
|
|
+ // STATUS_SUCCESS. We retain `previous` for internal audit/wake plumbing.
|
|
+ let (previous, found) = match state.objects.get_mut(&handle) {
|
|
+ Some(KernelObject::Event { signaled, .. }) => {
|
|
+ let prev = *signaled;
|
|
+ *signaled = true;
|
|
+ (prev as u32, true)
|
|
+ }
|
|
+ _ => (0u32, false),
|
|
+ };
|
|
+ state.audit_signal(handle, ctx.lr as u32, "NtSetEvent", previous as u64);
|
|
+ wake_eligible_waiters(state, handle);
|
|
+ if prev_ptr != 0 && found {
|
|
+ mem.write_u32(prev_ptr, 1);
|
|
+ }
|
|
+ ctx.gpr[3] = STATUS_SUCCESS;
|
|
+}
|
|
|
|
# Test additions (in tests module): 6 new unit tests; see file lines 7179-7340
|
|
# - ke_set_event_returns_constant_one_on_unsignaled_auto_reset
|
|
# - ke_set_event_returns_constant_one_on_already_signaled_manual_reset
|
|
# - nt_set_event_null_prev_ptr_returns_status_success_no_write
|
|
# - nt_set_event_valid_prev_ptr_writes_constant_one_and_returns_success
|
|
# - nt_set_event_on_signaled_event_writes_one
|
|
# - ke_set_event_post_fix_still_wakes_waiter
|
|
|
|
# LOC summary (Phase C+7 only, additive on C+6½ baseline):
|
|
# body changes: ~14 net added lines across 2 functions
|
|
# test additions: ~160 lines (6 tests)
|
|
# total: ~174 LOC, 1 file
|