From 1f86dc0454ff8dce9c82e5bcfa50683668d0dab1 Mon Sep 17 00:00:00 2001 From: "chss95cs@gmail.com" Date: Sun, 16 Apr 2023 17:34:46 -0400 Subject: [PATCH] Check for and allow null critical sections, but log them. stub XeKeysGetConsoleType Removed the breakpoints in HandleCppException and RtlRaiseException until we have a real implementation of them. Some apps can continue fine afterwards. Stub version of HalGetCurrentAVPack Implement MmIsAddressValid Implement RtlGetStackLimits --- src/xenia/kernel/xboxkrnl/xboxkrnl_crypt.cc | 10 ++++++ src/xenia/kernel/xboxkrnl/xboxkrnl_debug.cc | 8 +++-- src/xenia/kernel/xboxkrnl/xboxkrnl_hal.cc | 7 +++++ src/xenia/kernel/xboxkrnl/xboxkrnl_memory.cc | 16 ++++++++++ src/xenia/kernel/xboxkrnl/xboxkrnl_rtl.cc | 32 ++++++++++++++++++++ src/xenia/kernel/xthread.h | 11 +++++-- 6 files changed, 80 insertions(+), 4 deletions(-) diff --git a/src/xenia/kernel/xboxkrnl/xboxkrnl_crypt.cc b/src/xenia/kernel/xboxkrnl/xboxkrnl_crypt.cc index 6d98bc01d..08bd83aa9 100644 --- a/src/xenia/kernel/xboxkrnl/xboxkrnl_crypt.cc +++ b/src/xenia/kernel/xboxkrnl/xboxkrnl_crypt.cc @@ -686,6 +686,16 @@ dword_result_t XeKeysHmacShaUsingKey_entry(lpvoid_t obscured_key, } DECLARE_XBOXKRNL_EXPORT1(XeKeysHmacShaUsingKey, kNone, kImplemented); +//going off of usage in some hbrew xex +//0 and 1 appear to be devkit, 2 is retail +//we default to saying we're retail +dword_result_t XeKeysGetConsoleType_entry(lpdword_t type_out) { + *type_out = 2; + return 0; +} + +DECLARE_XBOXKRNL_EXPORT1(XeKeysGetConsoleType, kNone, kImplemented); + } // namespace xboxkrnl } // namespace kernel } // namespace xe diff --git a/src/xenia/kernel/xboxkrnl/xboxkrnl_debug.cc b/src/xenia/kernel/xboxkrnl/xboxkrnl_debug.cc index 0bc8a8f8d..cc362476a 100644 --- a/src/xenia/kernel/xboxkrnl/xboxkrnl_debug.cc +++ b/src/xenia/kernel/xboxkrnl/xboxkrnl_debug.cc @@ -120,7 +120,8 @@ void HandleCppException(pointer_t record) { kernel_memory()->TranslateVirtual( throw_info->catchable_type_array_ptr); - xe::debugging::Break(); + //xe::debugging::Break(); + XELOGE("Guest attempted to throw a C++ exception!"); } void RtlRaiseException_entry(pointer_t record) { @@ -137,7 +138,10 @@ void RtlRaiseException_entry(pointer_t record) { // TODO(benvanik): unwinding. // This is going to suck. - xe::debugging::Break(); + // xe::debugging::Break(); + + //RtlRaiseException definitely wasn't a noreturn function, we can return safe-ish + XELOGE("Guest attempted to trigger a breakpoint!"); } DECLARE_XBOXKRNL_EXPORT2(RtlRaiseException, kDebug, kStub, kImportant); diff --git a/src/xenia/kernel/xboxkrnl/xboxkrnl_hal.cc b/src/xenia/kernel/xboxkrnl/xboxkrnl_hal.cc index b173fd304..7c710bb50 100644 --- a/src/xenia/kernel/xboxkrnl/xboxkrnl_hal.cc +++ b/src/xenia/kernel/xboxkrnl/xboxkrnl_hal.cc @@ -31,6 +31,13 @@ void HalReturnToFirmware_entry(dword_t routine) { } DECLARE_XBOXKRNL_EXPORT2(HalReturnToFirmware, kNone, kStub, kImportant); +// this seems to be able to return a number of different values in the range 0 +// - 8. just returning four for now, because thats probably a better option than +// returning whatever was in r3 to begin with +dword_result_t HalGetCurrentAVPack_entry() { return 4; } + +DECLARE_XBOXKRNL_EXPORT1(HalGetCurrentAVPack, kNone, kStub); + } // namespace xboxkrnl } // namespace kernel } // namespace xe diff --git a/src/xenia/kernel/xboxkrnl/xboxkrnl_memory.cc b/src/xenia/kernel/xboxkrnl/xboxkrnl_memory.cc index 2cc317952..53f48b2b5 100644 --- a/src/xenia/kernel/xboxkrnl/xboxkrnl_memory.cc +++ b/src/xenia/kernel/xboxkrnl/xboxkrnl_memory.cc @@ -675,6 +675,22 @@ dword_result_t MmDeleteKernelStack_entry(lpvoid_t stack_base, } DECLARE_XBOXKRNL_EXPORT1(MmDeleteKernelStack, kMemory, kImplemented); +dword_result_t MmIsAddressValid_entry(dword_t address, + const ppc_context_t& ctx) { + auto kernel = ctx->kernel_state; + auto memory = kernel->memory(); + auto heap = memory->LookupHeap(address); + if (!heap) { + return 0; + } + + return heap->QueryRangeAccess(address, address) != + memory::PageAccess::kNoAccess; +} + +DECLARE_XBOXKRNL_EXPORT1(MmIsAddressValid, kMemory, kImplemented); + + } // namespace xboxkrnl } // namespace kernel } // namespace xe diff --git a/src/xenia/kernel/xboxkrnl/xboxkrnl_rtl.cc b/src/xenia/kernel/xboxkrnl/xboxkrnl_rtl.cc index 928ec780f..0e7562c50 100644 --- a/src/xenia/kernel/xboxkrnl/xboxkrnl_rtl.cc +++ b/src/xenia/kernel/xboxkrnl/xboxkrnl_rtl.cc @@ -517,6 +517,10 @@ static void CriticalSectionPrefetchW(const void* vp) { } void RtlEnterCriticalSection_entry(pointer_t cs) { + if (!cs.guest_address()) { + XELOGE("Null critical section in RtlEnterCriticalSection!"); + return; + } CriticalSectionPrefetchW(&cs->lock_count); uint32_t cur_thread = XThread::GetCurrentThread()->guest_object(); uint32_t spin_count = cs->header.absolute * 256; @@ -553,6 +557,10 @@ DECLARE_XBOXKRNL_EXPORT2(RtlEnterCriticalSection, kNone, kImplemented, dword_result_t RtlTryEnterCriticalSection_entry( pointer_t cs) { + if (!cs.guest_address()) { + XELOGE("Null critical section in RtlTryEnterCriticalSection!"); + return 1; // pretend we got the critical section. + } CriticalSectionPrefetchW(&cs->lock_count); uint32_t thread = XThread::GetCurrentThread()->guest_object(); @@ -575,6 +583,10 @@ DECLARE_XBOXKRNL_EXPORT2(RtlTryEnterCriticalSection, kNone, kImplemented, kHighFrequency); void RtlLeaveCriticalSection_entry(pointer_t cs) { + if (!cs.guest_address()) { + XELOGE("Null critical section in RtlLeaveCriticalSection!"); + return; + } assert_true(cs->owning_thread == XThread::GetCurrentThread()->guest_object()); // Drop recursion count - if it isn't zero we still have the lock. @@ -748,6 +760,26 @@ static void RtlRip_entry(const ppc_context_t& ctx) { //we should break here... not sure what to do exactly } DECLARE_XBOXKRNL_EXPORT1(RtlRip, kNone, kImportant); + +void RtlGetStackLimits_entry(lpdword_t out_end, lpdword_t out_base, + const ppc_context_t& ctx) { + auto kpcr = ctx->TranslateVirtualGPR(ctx->r[13]); + + uint32_t stack_base; + uint32_t stack_end; + + if (kpcr->use_alternative_stack) { + stack_base = kpcr->alt_stack_base_ptr; + stack_end = kpcr->alt_stack_end_ptr; + } else { + stack_base = kpcr->stack_base_ptr; + stack_end = kpcr->stack_end_ptr; + } + *out_base = stack_base; + *out_end = stack_end; +} +DECLARE_XBOXKRNL_EXPORT1(RtlGetStackLimits, kNone, kImplemented); + } // namespace xboxkrnl } // namespace kernel } // namespace xe diff --git a/src/xenia/kernel/xthread.h b/src/xenia/kernel/xthread.h index ceadd49dd..15c5d8a0e 100644 --- a/src/xenia/kernel/xthread.h +++ b/src/xenia/kernel/xthread.h @@ -73,10 +73,17 @@ struct X_KPCR { xe::be msr_mask; // 0x4 uint8_t unk_08[0x28]; // 0x8 xe::be pcr_ptr; // 0x30 - uint8_t unk_34[0x3C]; // 0x34 + uint8_t unk_34[0x38]; // 0x34 + xe::be use_alternative_stack; //0x6C xe::be stack_base_ptr; // 0x70 Stack base address (high addr) xe::be stack_end_ptr; // 0x74 Stack end (low addr) - uint8_t unk_78[0x88]; // 0x78 + + //maybe these are the stacks used in apcs? + //i know they're stacks, RtlGetStackLimits returns them if another var here is set + + xe::be alt_stack_base_ptr; // 0x78 + xe::be alt_stack_end_ptr; // 0x7C + uint8_t unk_80[0x80]; // 0x80 xe::be current_thread; // 0x100 uint8_t unk_104[0x8]; // 0x104 uint8_t current_cpu; // 0x10C