The xboxkrnl data export KeTimeStampBundle (ordinal 0x00AD, import slot
0x820007d0 — confirmed via sylpheed.db imports table) was set up with TWO
defects in the import-patch pass:
1. FROZEN: the block was written once at boot and never updated, so every
field stayed a constant for the whole run (observed: the guest's clock
reader sub_824AA830 = [[0x820007d0]+0x10] returned a constant
0x01d6bc0c from 5M..150M instructions).
2. WRONG LAYOUT: it stuffed the FILETIME high-dword at +0x10. The canonical
X_TIME_STAMP_BUNDLE (xenia-canary kernel_state.h) is:
+0x00 interrupt_time u64 (100ns since boot)
+0x08 system_time u64 (FILETIME 100ns since 1601)
+0x10 tick_count u32 (milliseconds since boot)
+0x14 padding
so [block+0x10] is tick_count in ms, not a FILETIME dword.
Fix (deterministic, no wall-clock):
* Initialize the block with the correct field layout (tick_count = 0 at
boot, system_time = FILETIME base, interrupt_time = 0).
* Store the block VA on KernelState::timestamp_bundle_addr during the
import patch.
* Add KernelState::update_timestamp_bundle(mem, clock) and call it every
round in BOTH the lockstep (run_execution) and parallel
(run_execution_parallel) outer loops, right where the deterministic
Scheduler::global_clock is advanced. The clock is the retired-instruction
monotonic global_clock, so every guest-visible time value stays a pure
function of guest progress (lockstep byte-reproducible).
* Cadence: 1 global_clock unit = 100ns (coherent with parse_timeout, which
divides 100ns timeouts by 100 onto the same basis), so
INSTRUCTIONS_PER_MS = 10_000. tick_count now advances 0 -> ~4999ms over
a 50M-instruction window. Also make KeQuerySystemTime read the same
100ns clock instead of a frozen FILETIME constant.
Verification: tick_count at 0x40002010 now advances (deadline arm at
0x82450d0c stores clock+66 = 0x260,0x269,...,0x51d,... advancing, vs the
frozen 0x01d6bc4e before the fix). Determinism: two cold --stable-digest
runs are byte-identical; the n50m golden is UNCHANGED (the clock-affected
counter is not in the stable digest). 672/672 tests pass.
HONEST CAVEAT — the predicted render cascade did NOT materialize on this
branch. The diagnosed consuming gate at 0x82450b10 (the clock-vs-deadline
compare in the worker-hub channel loop sub_82450A68) is unreachable here:
the loop always branches away at 0x82450b0c ([this+220] >= channel-index),
so the hub already dispatches sub_82450B68 342x in BOTH the frozen and
fixed builds. Guest trajectory (imports 339766@50M / 1738001@200M /
9212446@1B), draws (0), swaps (2) and thread topology (tid14 Ready, not
blocked on 0x109c) are identical frozen-vs-fixed. This commit is therefore
a correct latent-clock-bug fix and determinism-safe prerequisite, NOT the
render unblock. The 0x109c/tid14 starvation premise was not reproduced at
f75bc96; the next gate must be re-localized.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>