Adds a 41-LOC cvar-gated probe (audit_handle_lifecycle) that emits a one-shot
0x300-byte hexdump of the silph::WorkerCtx context the first time KeSetEvent
fires into the silph UI PKEVENT cluster (0xBCE25200..0xBCE25300 in current
builds). Recovers ctx_base by anchoring on the canonical layout (events at
ctx+0x54/+0x64/+0x74/+0x84 with 16-byte stride; ctx_base = ev_addr - (ev_addr
- 0xBCE251C0)). Also emits an explicit per-slot summary of the 8 candidate
KEVENT headers at +0x54..+0xC4 for sanity.
Produces 48 DUMP rows + 8 slot rows in canary.log on the first triggering
KeSetEvent. Guarded by std::atomic_bool so subsequent fires are silent. Used
by iterate 2.BF context-replication in ours: we need the live [ctx+0] vtable
pointer and the 4 quiet/4 active KEVENT slot config to synthesize a matching
WorkerCtx and spawn the four sub_82506xxx entries.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Extend the AUDIT-HLC probes with guest LR capture:
- NtCreateEvent, NtSetEvent, KeSetEvent: log immediate guest LR
(cpu::ThreadState::Get()->context()->lr) so callers can be
attributed to specific guest functions.
- NtWaitForSingleObjectEx entry + _done: also walk one PPC stack
frame up to recover the guest_lr of the wait wrapper's caller
(Xbox 360 EABI: saved LR at [prev_sp - 8], see xenia-rs's
walk_guest_back_chain). lr_enter alone gives only the kernel
wait wrapper return address (e.g. 0x824AC578); guest_lr surfaces
the actual call site.
Still cvar-gated on audit_handle_lifecycle. Used in audit-059 round 4
to map canary handles F8000xxx to ours' 0x12xx wedges via guest LR
matching against silph::UImpl/GamePart cluster.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
New cvar `audit_handle_lifecycle` (Auditing group, default false).
When enabled, emits one-line XELOGKERNEL traces tagged AUDIT-HLC at:
NtCreateEvent return, NtSetEvent entry, KeSetEvent entry,
NtWaitForSingleObjectEx entry + completion,
EmulateCPInterruptDPC entry.
Observation-only: zero-overhead when cvar off (single branch + flag
read). Intended for handle disambiguation between xenia-rs and
canary under the Wine cross-build oracle.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Change OddObj to X_DISPATCH_HEADER
- Add unknown X_KWAIT_REASON flag
- Fixed InitializeGuestObject mistake
- Replaces unknowns in kthread using nukernel as reference
If the guest-supplied thread pointer doesn't resolve to an XThread,
we previously returned STATUS_SUCCESS without setting the affinity
or writing previous_affinity_ptr, leaving callers believing the call
succeeded. Real NT kernel would crash on a bad pointer, but that's not
easy for us to replicate so return STATUS_INVALID_HANDLE instead and
log the pointer value so the condition is visible rather than silent.
Previous global TLS bitmap was shared across all processes. Now
per-process TLS bitmaps stored X_KPROCESS structures which should
better match Xbox360 architecture.
When a thread wakes from a kernel wait, the Xenon scheduler boosts its
effective priority by the increment passed to the signaling call
(KeSetEvent, KeReleaseSemaphore, KeReleaseMutant). The boost is clamped
to the per-thread max_dynamic_priority cap, respects the guest
boost_disabled flag, and is drained on the next quantum expiry.
Guest KTHREAD priority fields are now initialized from parent process
defaults, and the previously unknown fields involved have been renamed
to match their identified purpose.
And default ignore_thread_priorities to false.
Map Xenon's 0-31 priority range across all 5 host priority levels
instead of collapsing 0-17 into kNormal.
Use timer-driven quantum decay (~20ms period) matching Xenon's
60-quantum / 3-per-tick cycle to prevent starvation by gradually lowering
effective priority for non-real-time threads (< 18), piggybacking on the
existing 1ms timestamp timer.
Spinlock acquire now checks if the lock holder shares the same guest
CPU and yields more aggressively (Sleep(0)) when contending on the
same Xenon HW thread, which should better approximate real kernel's
implicit serialization.
Child threads without an explicit affinity mask now inherit the
parent's guest CPU assignment instead of round-robining, so the
spinlock check correctly identifies parent-child co-location.
Most non-Windows code paths use standard POSIX APIs (sockets, signals,
dlopen, threading) that work on any POSIX platform. Change Linux-specific
guards to !WIN32 or #else where the code is portable. Linux-specific
APIs (SIGRTMIN, Vulkan/X11, fontconfig/GTK) remain Linux-guarded.
std::ctype<char16_t> is a non-standard extension that's not available
on all platforms. Neither this nor the original technically match the
Windows kernel's fixed Unicode table approach and can produce different
results based on system locale.