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>
This commit is contained in:
@@ -0,0 +1,97 @@
|
||||
# Phase C+23 — Cold-vs-cold verification
|
||||
|
||||
**Date:** 2026-05-26
|
||||
**Mode:** Engine modified (`vd_query_video_flags` constant return).
|
||||
Cold-vs-cold protocol: fresh `xrs-c23` cold runs vs archived canary
|
||||
jitter set.
|
||||
|
||||
## Methodology
|
||||
|
||||
- ours-cold jsonls: `/tmp/ours-c23-vd-cold-{1,2,3}.jsonl` (28.7 MB
|
||||
each, 108,507 events on tid=1). Captured under
|
||||
`XENIA_CACHE_WIPE=1` with the freshly built `xrs-c23` binary
|
||||
(release, post-fix).
|
||||
- canary jitter set: 3 archived cold runs `canary-jitter-{1,2,3}.jsonl`
|
||||
(4.4 / 3.5 / 3.7 GB) from
|
||||
`xenia-canary/build-cross/bin/Windows/Debug/`. Same reference
|
||||
jitter set used in C+20, C+21, C+22, Phase D Stage 0..4.
|
||||
- tid map: `--tid-map 6=1` (canary main thread → ours main thread).
|
||||
|
||||
## Pre-C+23 baseline (post-C+22)
|
||||
|
||||
```
|
||||
matched=105,138 across all 3 jitters
|
||||
first divergence: kernel.return VdQueryVideoFlags
|
||||
canary=3 ours=0
|
||||
at idx 105,138 (tid=6→1)
|
||||
```
|
||||
|
||||
## Post-C+23 (3-jitter table)
|
||||
|
||||
| jitter | matched | first divergence at | first-divergence kind / payload |
|
||||
|---|---|---|---|
|
||||
| 1 | **105,286** | 105,286 | `import.call VdGetCurrentDisplayGamma` (canary) vs `import.call KeAcquireSpinLockAtRaisedIrql` (ours) |
|
||||
| 2 | **105,286** | 105,286 | (same) |
|
||||
| 3 | **105,286** | 105,286 | (same) |
|
||||
|
||||
Delta vs baseline: **+148 events** in main matched-prefix on all
|
||||
three jitters. The new first divergence (`VdGetCurrentDisplayGamma`
|
||||
vs `KeAcquireSpinLockAtRaisedIrql`) is genuine and identical across
|
||||
all three jitters.
|
||||
|
||||
## Absorber counters (sanity)
|
||||
|
||||
| jitter | floating_create (c/o) | floating_wait (c/o) |
|
||||
|---|---|---|
|
||||
| 1 | 0 / 0 | 1 / 0 |
|
||||
| 2 | 0 / 0 | 0 / 0 |
|
||||
| 3 | 1 / 0 | 3 / 0 |
|
||||
|
||||
Within the expected scheduling-jitter window. Matched-prefix
|
||||
stable at 105,286 across all three.
|
||||
|
||||
## Sister chains
|
||||
|
||||
No sister chain regressions: the diff report lists only the main
|
||||
`tid=6 → tid=1` chain (no sister chains exercised in the new
|
||||
window). All previously matched sister chains
|
||||
(11, 32, 4, 41, 16) remain unaffected because they fire outside
|
||||
the 105,138–105,286 window.
|
||||
|
||||
## Determinism (3 cold runs)
|
||||
|
||||
| run | md5 | matched-prefix vs jitter-1 | ours_total |
|
||||
|---|---|---|---|
|
||||
| cold-1 | `4e2e781ff0609f3a0a08f573dee4be4e` | 105,286 | 108,507 |
|
||||
| cold-2 | `b195d82a1b61e87d6f54a2ac2b3e091b` | 105,286 | 108,507 |
|
||||
| cold-3 | `e6b94d4dc151007c924b81bbc5c9faf5` | 105,286 | 108,507 |
|
||||
|
||||
The byte-level md5 differs (host_ns/guest_cycle wall-time jitter,
|
||||
expected) but the logical semantic state — matched-prefix,
|
||||
ours_total, first-divergence index, divergent payloads — is
|
||||
bit-identical across all 3 runs.
|
||||
|
||||
New cold baseline digest (representative cold-1):
|
||||
**`4e2e781ff0609f3a0a08f573dee4be4e`**.
|
||||
|
||||
## Phase B `image_canonical_sha256`
|
||||
|
||||
Pinned hash `ea8d160e…` UNCHANGED. No XEX loader changes; only
|
||||
kernel export logic modified.
|
||||
|
||||
## Test suite
|
||||
|
||||
xenia-kernel: **226 PASS** (was 224 + 2 new).
|
||||
|
||||
## Conclusion
|
||||
|
||||
Phase C+23 advances main matched-prefix from 105,138 → 105,286
|
||||
across all three canary jitter cold runs (+148 events,
|
||||
+0.0311% of canary total). The next divergence is a real
|
||||
post-VdSwap control-flow mismatch unrelated to video flags.
|
||||
|
||||
Engine MODIFIED (~50 LOC: 1 registration edit + 6 LOC function
|
||||
body + 40 LOC tests). Diff tool UNCHANGED. Phase B
|
||||
`image_loaded_sha256` ε class boundary UNCHANGED.
|
||||
|
||||
Tripstones 1, 2, 3, 4, 5, 6 honored.
|
||||
50
audit-runs/phase-c23-VdQueryVideoFlags/diff-jitter-1.md
Normal file
50
audit-runs/phase-c23-VdQueryVideoFlags/diff-jitter-1.md
Normal file
@@ -0,0 +1,50 @@
|
||||
# Phase A diff report
|
||||
|
||||
**This report is the output of Phase A's diff harness. Divergences
|
||||
shown here are INPUT for Phase B (first-divergence localization),
|
||||
not findings of Phase A.** Phase A's job is to make the harness
|
||||
itself correct, not to analyze what it surfaces.
|
||||
|
||||
## Summary
|
||||
|
||||
| canary_tid | ours_tid | matched | canary_total | ours_total | first_divergence_at | floating_create (c/o) | floating_wait (c/o) |
|
||||
|---|---|---|---|---|---|---|---|
|
||||
| 6 | 1 | 105286 | 476943 | 108507 | 105286 | 0/0 | 1/0 |
|
||||
|
||||
*`floating_create (c/o)` counts shared-global `handle.create` events absorbed by Phase C+18 cross-tid SID matching. `floating_wait (c/o)` counts `wait.begin` events on shared-global dispatchers absorbed by Phase C+21 (scheduling-jitter window — canary's contention slow path may fire while ours fast-paths or vice versa). See schema-v1.md §"Shared-global SIDs" and §"Wait-begin floating absorb".*
|
||||
|
||||
## canary_tid=6 → ours_tid=1
|
||||
|
||||
First divergence at `tid_event_idx=105286`: payload.ord: canary=441 ours=77
|
||||
|
||||
**Pre-context (last 5 matching events):**
|
||||
```
|
||||
canary: [105288] kernel.call VdGetSystemCommandBuffer
|
||||
ours: [105281] kernel.call VdGetSystemCommandBuffer
|
||||
canary: [105289] kernel.return VdGetSystemCommandBuffer
|
||||
ours: [105282] kernel.return VdGetSystemCommandBuffer
|
||||
canary: [105290] import.call VdSwap
|
||||
ours: [105283] import.call VdSwap
|
||||
canary: [105291] kernel.call VdSwap
|
||||
ours: [105284] kernel.call VdSwap
|
||||
canary: [105292] kernel.return VdSwap
|
||||
ours: [105285] kernel.return VdSwap
|
||||
```
|
||||
|
||||
**Divergent event:**
|
||||
```
|
||||
canary: [105293] import.call VdGetCurrentDisplayGamma
|
||||
ours: [105286] import.call KeAcquireSpinLockAtRaisedIrql
|
||||
```
|
||||
|
||||
**Next event after the divergence (if any):**
|
||||
```
|
||||
canary: [105294] kernel.call VdGetCurrentDisplayGamma
|
||||
ours: [105287] kernel.call KeAcquireSpinLockAtRaisedIrql
|
||||
```
|
||||
|
||||
**Raw events (JSON):**
|
||||
```json
|
||||
{"deterministic": true, "engine": "canary", "guest_cycle": 0, "host_ns": 1650661700, "kind": "import.call", "payload": {"module": "xboxkrnl.exe", "name": "VdGetCurrentDisplayGamma", "ord": 441}, "schema_version": 1, "tid": 6, "tid_event_idx": 105293}
|
||||
{"deterministic": true, "engine": "ours", "guest_cycle": 5584999, "host_ns": 1437632028, "kind": "import.call", "payload": {"module": "xboxkrnl.exe", "name": "KeAcquireSpinLockAtRaisedIrql", "ord": 77}, "schema_version": 1, "tid": 1, "tid_event_idx": 105286}
|
||||
```
|
||||
50
audit-runs/phase-c23-VdQueryVideoFlags/diff-jitter-2.md
Normal file
50
audit-runs/phase-c23-VdQueryVideoFlags/diff-jitter-2.md
Normal file
@@ -0,0 +1,50 @@
|
||||
# Phase A diff report
|
||||
|
||||
**This report is the output of Phase A's diff harness. Divergences
|
||||
shown here are INPUT for Phase B (first-divergence localization),
|
||||
not findings of Phase A.** Phase A's job is to make the harness
|
||||
itself correct, not to analyze what it surfaces.
|
||||
|
||||
## Summary
|
||||
|
||||
| canary_tid | ours_tid | matched | canary_total | ours_total | first_divergence_at | floating_create (c/o) | floating_wait (c/o) |
|
||||
|---|---|---|---|---|---|---|---|
|
||||
| 6 | 1 | 105286 | 441027 | 108507 | 105286 | 0/0 | 0/0 |
|
||||
|
||||
*`floating_create (c/o)` counts shared-global `handle.create` events absorbed by Phase C+18 cross-tid SID matching. `floating_wait (c/o)` counts `wait.begin` events on shared-global dispatchers absorbed by Phase C+21 (scheduling-jitter window — canary's contention slow path may fire while ours fast-paths or vice versa). See schema-v1.md §"Shared-global SIDs" and §"Wait-begin floating absorb".*
|
||||
|
||||
## canary_tid=6 → ours_tid=1
|
||||
|
||||
First divergence at `tid_event_idx=105286`: payload.ord: canary=441 ours=77
|
||||
|
||||
**Pre-context (last 5 matching events):**
|
||||
```
|
||||
canary: [105287] kernel.call VdGetSystemCommandBuffer
|
||||
ours: [105281] kernel.call VdGetSystemCommandBuffer
|
||||
canary: [105288] kernel.return VdGetSystemCommandBuffer
|
||||
ours: [105282] kernel.return VdGetSystemCommandBuffer
|
||||
canary: [105289] import.call VdSwap
|
||||
ours: [105283] import.call VdSwap
|
||||
canary: [105290] kernel.call VdSwap
|
||||
ours: [105284] kernel.call VdSwap
|
||||
canary: [105291] kernel.return VdSwap
|
||||
ours: [105285] kernel.return VdSwap
|
||||
```
|
||||
|
||||
**Divergent event:**
|
||||
```
|
||||
canary: [105292] import.call VdGetCurrentDisplayGamma
|
||||
ours: [105286] import.call KeAcquireSpinLockAtRaisedIrql
|
||||
```
|
||||
|
||||
**Next event after the divergence (if any):**
|
||||
```
|
||||
canary: [105293] kernel.call VdGetCurrentDisplayGamma
|
||||
ours: [105287] kernel.call KeAcquireSpinLockAtRaisedIrql
|
||||
```
|
||||
|
||||
**Raw events (JSON):**
|
||||
```json
|
||||
{"deterministic": true, "engine": "canary", "guest_cycle": 0, "host_ns": 1666583800, "kind": "import.call", "payload": {"module": "xboxkrnl.exe", "name": "VdGetCurrentDisplayGamma", "ord": 441}, "schema_version": 1, "tid": 6, "tid_event_idx": 105292}
|
||||
{"deterministic": true, "engine": "ours", "guest_cycle": 5584999, "host_ns": 1437632028, "kind": "import.call", "payload": {"module": "xboxkrnl.exe", "name": "KeAcquireSpinLockAtRaisedIrql", "ord": 77}, "schema_version": 1, "tid": 1, "tid_event_idx": 105286}
|
||||
```
|
||||
50
audit-runs/phase-c23-VdQueryVideoFlags/diff-jitter-3.md
Normal file
50
audit-runs/phase-c23-VdQueryVideoFlags/diff-jitter-3.md
Normal file
@@ -0,0 +1,50 @@
|
||||
# Phase A diff report
|
||||
|
||||
**This report is the output of Phase A's diff harness. Divergences
|
||||
shown here are INPUT for Phase B (first-divergence localization),
|
||||
not findings of Phase A.** Phase A's job is to make the harness
|
||||
itself correct, not to analyze what it surfaces.
|
||||
|
||||
## Summary
|
||||
|
||||
| canary_tid | ours_tid | matched | canary_total | ours_total | first_divergence_at | floating_create (c/o) | floating_wait (c/o) |
|
||||
|---|---|---|---|---|---|---|---|
|
||||
| 6 | 1 | 105286 | 445578 | 108507 | 105286 | 1/0 | 3/0 |
|
||||
|
||||
*`floating_create (c/o)` counts shared-global `handle.create` events absorbed by Phase C+18 cross-tid SID matching. `floating_wait (c/o)` counts `wait.begin` events on shared-global dispatchers absorbed by Phase C+21 (scheduling-jitter window — canary's contention slow path may fire while ours fast-paths or vice versa). See schema-v1.md §"Shared-global SIDs" and §"Wait-begin floating absorb".*
|
||||
|
||||
## canary_tid=6 → ours_tid=1
|
||||
|
||||
First divergence at `tid_event_idx=105286`: payload.ord: canary=441 ours=77
|
||||
|
||||
**Pre-context (last 5 matching events):**
|
||||
```
|
||||
canary: [105291] kernel.call VdGetSystemCommandBuffer
|
||||
ours: [105281] kernel.call VdGetSystemCommandBuffer
|
||||
canary: [105292] kernel.return VdGetSystemCommandBuffer
|
||||
ours: [105282] kernel.return VdGetSystemCommandBuffer
|
||||
canary: [105293] import.call VdSwap
|
||||
ours: [105283] import.call VdSwap
|
||||
canary: [105294] kernel.call VdSwap
|
||||
ours: [105284] kernel.call VdSwap
|
||||
canary: [105295] kernel.return VdSwap
|
||||
ours: [105285] kernel.return VdSwap
|
||||
```
|
||||
|
||||
**Divergent event:**
|
||||
```
|
||||
canary: [105296] import.call VdGetCurrentDisplayGamma
|
||||
ours: [105286] import.call KeAcquireSpinLockAtRaisedIrql
|
||||
```
|
||||
|
||||
**Next event after the divergence (if any):**
|
||||
```
|
||||
canary: [105297] kernel.call VdGetCurrentDisplayGamma
|
||||
ours: [105287] kernel.call KeAcquireSpinLockAtRaisedIrql
|
||||
```
|
||||
|
||||
**Raw events (JSON):**
|
||||
```json
|
||||
{"deterministic": true, "engine": "canary", "guest_cycle": 0, "host_ns": 1651635600, "kind": "import.call", "payload": {"module": "xboxkrnl.exe", "name": "VdGetCurrentDisplayGamma", "ord": 441}, "schema_version": 1, "tid": 6, "tid_event_idx": 105296}
|
||||
{"deterministic": true, "engine": "ours", "guest_cycle": 5584999, "host_ns": 1437632028, "kind": "import.call", "payload": {"module": "xboxkrnl.exe", "name": "KeAcquireSpinLockAtRaisedIrql", "ord": 77}, "schema_version": 1, "tid": 1, "tid_event_idx": 105286}
|
||||
```
|
||||
201
audit-runs/phase-c23-VdQueryVideoFlags/investigation.md
Normal file
201
audit-runs/phase-c23-VdQueryVideoFlags/investigation.md
Normal file
@@ -0,0 +1,201 @@
|
||||
# Phase C+23 — `VdQueryVideoFlags` constant return
|
||||
|
||||
**Date:** 2026-05-26
|
||||
**Mode:** WRITE — engine change (~5 LOC functional + ~2 LOC registration
|
||||
edit + ~40 LOC tests). Diff tool UNCHANGED.
|
||||
**Status:** LANDED. Main matched-prefix 105,138 → 105,286 (+148).
|
||||
|
||||
## TL;DR
|
||||
|
||||
The post-C+22 first divergence at canary tid=6 ↔ ours tid=1 idx 105,138
|
||||
is `kernel.return VdQueryVideoFlags`:
|
||||
|
||||
```
|
||||
canary: kernel.return VdQueryVideoFlags { return_value: 3, status: "0x00000003" }
|
||||
ours: kernel.return VdQueryVideoFlags { return_value: 0, status: "0x00000000" }
|
||||
```
|
||||
|
||||
Canary's `VdQueryVideoFlags_entry`
|
||||
(`xenia-canary/src/xenia/kernel/xboxkrnl/xboxkrnl_video.cc:231-241`)
|
||||
computes a bitmask from the queried video mode:
|
||||
|
||||
```cpp
|
||||
dword_result_t VdQueryVideoFlags_entry() {
|
||||
X_VIDEO_MODE mode;
|
||||
VdQueryVideoMode(&mode, false);
|
||||
uint32_t flags = 0;
|
||||
flags |= mode.is_widescreen ? 1 : 0;
|
||||
flags |= mode.display_width >= 1280 ? 2 : 0;
|
||||
flags |= mode.display_width >= 1920 ? 4 : 0;
|
||||
return flags;
|
||||
}
|
||||
```
|
||||
|
||||
Under canary's shipping defaults (`cvars::widescreen=true` from
|
||||
`xboxkrnl_video.cc:31`; `cvars::internal_display_resolution=8` from
|
||||
`graphics_system.cc:26` → `{1280, 720}` from
|
||||
`graphics_system.h:38-54`), the computed value is:
|
||||
|
||||
```
|
||||
is_widescreen=1 → +1
|
||||
display_width=1280 ≥ 1280 → +2
|
||||
display_width=1280 ≥ 1920 → +0
|
||||
= 3
|
||||
```
|
||||
|
||||
Ours's previous registration mapped the export to `stub_return_zero`
|
||||
(`exports.rs:215` pre-change), which placed `0` in `r3`. The fix is a
|
||||
1:1 mirror of canary's semantics under the same defaults that
|
||||
ours's `vd_query_video_mode` already reports (width=1280,
|
||||
is_widescreen=1).
|
||||
|
||||
## Why a constant works (no infrastructure needed)
|
||||
|
||||
Ours's `vd_query_video_mode`
|
||||
(`exports.rs:3986-3996` pre-change, now :3997-4007 in the new file)
|
||||
hard-codes `display_width=1280, is_widescreen=1, refresh_rate=60`
|
||||
— it has no cvar plumbing. As long as `vd_query_video_mode`'s
|
||||
payload is itself fixed, the bitmask is also fixed. Implementing a
|
||||
cvar-driven flags path would require first introducing a
|
||||
`widescreen` / `internal_display_resolution` cvar machinery; out of
|
||||
scope per the escalation rule.
|
||||
|
||||
A unit test (`vd_query_video_flags_matches_vd_query_video_mode_payload`)
|
||||
ties the return value to the *actual* payload `vd_query_video_mode`
|
||||
writes, so the two functions stay in sync if the mode payload is
|
||||
ever updated to actual cvar-driven values.
|
||||
|
||||
## The fix
|
||||
|
||||
```rust
|
||||
// exports.rs:215 (registration)
|
||||
state.register_export(Xboxkrnl, 0x01C9, "VdQueryVideoFlags", vd_query_video_flags);
|
||||
|
||||
// exports.rs:3998-4023 (new function)
|
||||
fn vd_query_video_flags(ctx: &mut PpcContext, _mem: &GuestMemory, _state: &mut KernelState) {
|
||||
// is_widescreen=1, display_width=1280 → bits 0 + 1 = 3
|
||||
ctx.gpr[3] = 0x3;
|
||||
}
|
||||
```
|
||||
|
||||
Total: 1 export-table line change + ~6 lines of function (with
|
||||
doc comment) + ~40 lines of unit tests = ~50 LOC.
|
||||
|
||||
## Tests
|
||||
|
||||
2 new tests in `exports.rs`:
|
||||
|
||||
1. `vd_query_video_flags_returns_three` — sentinel-overwrite +
|
||||
pinned return value `0x3`.
|
||||
2. `vd_query_video_flags_matches_vd_query_video_mode_payload` —
|
||||
computes the canary bitmask formula over `vd_query_video_mode`'s
|
||||
actual written payload and asserts equality with the
|
||||
`vd_query_video_flags` return. Catches drift if either function
|
||||
is updated without the other.
|
||||
|
||||
Total: previous 224 + 2 new = **226 tests, all PASS**.
|
||||
|
||||
## Cold-vs-cold verification (3-jitter table)
|
||||
|
||||
ours cold-1 jsonl: `/tmp/ours-c23-vd-cold-1.jsonl` (28.7 MB,
|
||||
108,507 events on tid=1). Captured under `XENIA_CACHE_WIPE=1` with
|
||||
the freshly built `xrs-c23` binary.
|
||||
|
||||
| jitter | matched | first divergence at | first-divergence kind / payload |
|
||||
|---|---|---|---|
|
||||
| 1 | **105,286** | 105,286 | `import.call VdGetCurrentDisplayGamma` (canary) vs `import.call KeAcquireSpinLockAtRaisedIrql` (ours) |
|
||||
| 2 | **105,286** | 105,286 | (same) |
|
||||
| 3 | **105,286** | 105,286 | (same) |
|
||||
|
||||
Delta vs C+22 baseline (105,138): **+148 events** in main matched-
|
||||
prefix, on all three jitters. The new first divergence is genuine
|
||||
and identical across all three jitters.
|
||||
|
||||
## Absorber counters (sanity)
|
||||
|
||||
| jitter | floating_create (c/o) | floating_wait (c/o) |
|
||||
|---|---|---|
|
||||
| 1 | 0 / 0 | 1 / 0 |
|
||||
| 2 | 0 / 0 | 0 / 0 |
|
||||
| 3 | 1 / 0 | 3 / 0 |
|
||||
|
||||
Jitter-to-jitter variance in absorber counts is the expected
|
||||
scheduling-jitter window. Matched-prefix stable at 105,286 across
|
||||
all three.
|
||||
|
||||
## Sister chains
|
||||
|
||||
No sister chains exercised in the 105,138–105,286 window. The 148
|
||||
absorbed events are all on the main `tid=6 → tid=1` chain. The diff
|
||||
report lists only the main chain row, confirming no regressions on
|
||||
any sister chain.
|
||||
|
||||
## Determinism (3 cold runs)
|
||||
|
||||
| run | md5 | matched-prefix vs jitter-1 |
|
||||
|---|---|---|
|
||||
| cold-1 | `4e2e781ff0609f3a0a08f573dee4be4e` | 105,286 |
|
||||
| cold-2 | `b195d82a1b61e87d6f54a2ac2b3e091b` | 105,286 |
|
||||
| cold-3 | `e6b94d4dc151007c924b81bbc5c9faf5` | 105,286 |
|
||||
|
||||
Byte-level digests differ across the 3 cold runs because of
|
||||
`host_ns` / `guest_cycle` wall-time jitter (unchanged from
|
||||
pre-C+23 behavior). Logical semantic state — matched-prefix,
|
||||
ours_total=108,507, first-divergence index — is bit-stable across
|
||||
all 3 runs.
|
||||
|
||||
## Files touched
|
||||
|
||||
- `xenia-rs/crates/xenia-kernel/src/exports.rs`:
|
||||
- Line 215: registration `stub_return_zero` → `vd_query_video_flags`.
|
||||
- Lines ~3998-4023: new `vd_query_video_flags` function with
|
||||
full doc comment.
|
||||
- Lines ~9750-9803: 2 new unit tests in the `tests` module.
|
||||
|
||||
NO Phase B loader changes. NO diff-tool changes. NO new cvars.
|
||||
NO refactor of video state model.
|
||||
|
||||
## Phase B `image_canonical_sha256`
|
||||
|
||||
Pinned hash `ea8d160e…` UNCHANGED — only kernel-export logic
|
||||
modified; XEX loader path untouched.
|
||||
|
||||
## Cascade
|
||||
|
||||
- A (verify canary return): **PASS** — canary returns 3 under
|
||||
shipping defaults; verified by direct source read of
|
||||
`xboxkrnl_video.cc:231-241` + `graphics_system.cc:26` +
|
||||
`graphics_system.h:38-54`. Confidence HIGH.
|
||||
- B (implement + tests): **PASS** — 2 new tests, 226 total PASS,
|
||||
release build clean (1 pre-existing dead-code warning on
|
||||
`walk_committed_regions` — unrelated).
|
||||
- C (3-jitter verification): **PASS** — all three jitters advance
|
||||
105,138 → 105,286 (+148), same downstream divergence.
|
||||
- D (determinism + sister chains): **PASS** — 3 cold runs converge
|
||||
to identical matched-prefix=105,286 against jitter-1. No sister
|
||||
chain regressions.
|
||||
- E (canary caches unchanged): **PASS** — archived jitter set used,
|
||||
no fresh canary run made (per C+22 precedent), `cache/` and
|
||||
`cache_host/` directories unchanged from session start.
|
||||
|
||||
## Next divergence (C+24 candidate)
|
||||
|
||||
`import.call VdGetCurrentDisplayGamma` at canary idx 105,293 vs
|
||||
`import.call KeAcquireSpinLockAtRaisedIrql` at ours idx 105,286.
|
||||
Both engines just exited a `VdSwap` (5 matching prior events
|
||||
ending in `kernel.return VdSwap`). The two engines then take
|
||||
different code paths inside the post-VdSwap return path.
|
||||
|
||||
Possible interpretations:
|
||||
- Different control flow inside a Vd post-swap hook on the canary
|
||||
side (canary calls `VdGetCurrentDisplayGamma` after `VdSwap`;
|
||||
ours doesn't).
|
||||
- Different scheduler interleaving: ours main thread re-enters a
|
||||
spinlock-protected section that canary's post-VdSwap walk avoids.
|
||||
|
||||
Investigation should start by looking at the canary `VdSwap`
|
||||
post-handler to see if canary unconditionally calls
|
||||
`VdGetCurrentDisplayGamma` (and if so, whether ours stubs it out)
|
||||
or if this is a game-code branch driven by guest memory state.
|
||||
|
||||
Out of scope for C+23.
|
||||
Reference in New Issue
Block a user