diff --git a/src/xenia/kernel/kernel_state.cc b/src/xenia/kernel/kernel_state.cc index 99a4380be..ebff0ebf0 100644 --- a/src/xenia/kernel/kernel_state.cc +++ b/src/xenia/kernel/kernel_state.cc @@ -1527,15 +1527,17 @@ void KernelState::InitializeKernelGuestGlobals() { SetProcessTLSVars(system_process, 32, 0, 0); uint32_t oddobject_offset = - kernel_guest_globals_ + offsetof(KernelGuestGlobals, OddObj); + kernel_guest_globals_ + + offsetof(KernelGuestGlobals, XboxKernelDefaultObject); // init unknown object - block->OddObj.field0 = 0x1000000; - block->OddObj.field4 = 1; - block->OddObj.points_to_self = - oddobject_offset + offsetof(X_UNKNOWN_TYPE_REFED, points_to_self); - block->OddObj.points_to_prior = block->OddObj.points_to_self; + block->XboxKernelDefaultObject.type = DISPATCHER_AUTO_RESET_EVENT; + block->XboxKernelDefaultObject.signal_state = 1; + block->XboxKernelDefaultObject.wait_list.flink_ptr = + oddobject_offset + offsetof(X_DISPATCH_HEADER, wait_list.flink_ptr); + block->XboxKernelDefaultObject.wait_list.blink_ptr = + block->XboxKernelDefaultObject.wait_list.flink_ptr; // init thread object block->ExThreadObjectType.pool_tag = 0x65726854; diff --git a/src/xenia/kernel/kernel_state.h b/src/xenia/kernel/kernel_state.h index da8cb9066..096948de5 100644 --- a/src/xenia/kernel/kernel_state.h +++ b/src/xenia/kernel/kernel_state.h @@ -96,21 +96,13 @@ struct TerminateNotification { // a bit like the timers on KUSER_SHARED on normal win32 // https://www.geoffchappell.com/studies/windows/km/ntoskrnl/inc/api/ntexapi_x/kuser_shared_data/index.htm struct X_TIME_STAMP_BUNDLE { + // according to Nukernl these are BE uint64_t interrupt_time; // i assume system_time is in 100 ns intervals like on win32 uint64_t system_time; uint32_t tick_count; uint32_t padding; }; -struct X_UNKNOWN_TYPE_REFED { - xe::be field0; - xe::be field4; - // this is definitely a LIST_ENTRY? - xe::be points_to_self; // this field points to itself - xe::be - points_to_prior; // points to the previous field, which points to itself -}; -static_assert_size(X_UNKNOWN_TYPE_REFED, 16); struct KernelGuestGlobals { X_OBJECT_TYPE ExThreadObjectType; @@ -125,7 +117,7 @@ struct KernelGuestGlobals { X_OBJECT_TYPE ObSymbolicLinkObjectType; // a constant buffer that some object types' "unknown_size_or_object" field // points to - X_UNKNOWN_TYPE_REFED OddObj; + X_DISPATCH_HEADER XboxKernelDefaultObject; X_KPROCESS idle_process; // X_PROCTYPE_IDLE. runs in interrupt contexts. is // also the context the kernel starts in? X_KPROCESS title_process; // X_PROCTYPE_TITLE diff --git a/src/xenia/kernel/xboxkrnl/xboxkrnl_memory.cc b/src/xenia/kernel/xboxkrnl/xboxkrnl_memory.cc index dbeeb22a1..dc417f48e 100644 --- a/src/xenia/kernel/xboxkrnl/xboxkrnl_memory.cc +++ b/src/xenia/kernel/xboxkrnl/xboxkrnl_memory.cc @@ -676,7 +676,7 @@ struct X_POOL_ALLOC_HEADER { }; uint32_t xeAllocatePoolTypeWithTag(PPCContext* context, uint32_t size, - uint32_t tag, uint32_t zero) { + uint32_t tag, uint32_t pool_selector) { if (size <= 0xFD8) { uint32_t adjusted_size = size + sizeof(X_POOL_ALLOC_HEADER); @@ -694,9 +694,9 @@ uint32_t xeAllocatePoolTypeWithTag(PPCContext* context, uint32_t size, } dword_result_t ExAllocatePoolTypeWithTag_entry(dword_t size, dword_t tag, - dword_t zero, + dword_t pool_selector, const ppc_context_t& context) { - return xeAllocatePoolTypeWithTag(context, size, tag, zero); + return xeAllocatePoolTypeWithTag(context, size, tag, pool_selector); } DECLARE_XBOXKRNL_EXPORT1(ExAllocatePoolTypeWithTag, kMemory, kImplemented); diff --git a/src/xenia/kernel/xboxkrnl/xboxkrnl_memory.h b/src/xenia/kernel/xboxkrnl/xboxkrnl_memory.h index b25795f73..d1e3fb238 100644 --- a/src/xenia/kernel/xboxkrnl/xboxkrnl_memory.h +++ b/src/xenia/kernel/xboxkrnl/xboxkrnl_memory.h @@ -50,7 +50,7 @@ uint32_t xeMmAllocatePhysicalMemoryEx(uint32_t flags, uint32_t region_size, dword_result_t xeMmQueryStatistics( pointer_t stats_ptr); uint32_t xeAllocatePoolTypeWithTag(PPCContext* context, uint32_t size, - uint32_t tag, uint32_t zero); + uint32_t tag, uint32_t pool_selector); void xeFreePool(PPCContext* context, uint32_t base_address); diff --git a/src/xenia/kernel/xboxkrnl/xboxkrnl_rtl.cc b/src/xenia/kernel/xboxkrnl/xboxkrnl_rtl.cc index 67bfa3322..543b5bc61 100644 --- a/src/xenia/kernel/xboxkrnl/xboxkrnl_rtl.cc +++ b/src/xenia/kernel/xboxkrnl/xboxkrnl_rtl.cc @@ -544,7 +544,7 @@ static_assert_size(X_RTL_CRITICAL_SECTION, 28); void xeRtlInitializeCriticalSection(X_RTL_CRITICAL_SECTION* cs, uint32_t cs_ptr) { - cs->header.type = 1; // EventSynchronizationObject (auto reset) + cs->header.type = X_DISPATCHER_FLAGS::DISPATCHER_AUTO_RESET_EVENT; cs->header.absolute = 0; // spin count div 256 cs->header.signal_state = 0; cs->lock_count = -1; @@ -567,7 +567,7 @@ X_STATUS xeRtlInitializeCriticalSectionAndSpinCount(X_RTL_CRITICAL_SECTION* cs, spin_count_div_256 = 255; } - cs->header.type = 1; // EventSynchronizationObject (auto reset) + cs->header.type = X_DISPATCHER_FLAGS::DISPATCHER_AUTO_RESET_EVENT; cs->header.absolute = spin_count_div_256; cs->header.signal_state = 0; cs->lock_count = -1; diff --git a/src/xenia/kernel/xboxkrnl/xboxkrnl_threading.cc b/src/xenia/kernel/xboxkrnl/xboxkrnl_threading.cc index ebbf25534..86ed64a46 100644 --- a/src/xenia/kernel/xboxkrnl/xboxkrnl_threading.cc +++ b/src/xenia/kernel/xboxkrnl/xboxkrnl_threading.cc @@ -692,12 +692,12 @@ DECLARE_XBOXKRNL_EXPORT2(NtClearEvent, kThreading, kImplemented, // https://msdn.microsoft.com/en-us/library/windows/hardware/ff552150(v=vs.85).aspx void KeInitializeSemaphore_entry(pointer_t semaphore_ptr, dword_t count, dword_t limit) { - semaphore_ptr->header.type = 5; // SemaphoreObject + semaphore_ptr->header.type = X_DISPATCHER_FLAGS::DISPATCHER_SEMAPHORE; semaphore_ptr->header.signal_state = (uint32_t)count; semaphore_ptr->limit = (uint32_t)limit; - auto sem = XObject::GetNativeObject(kernel_state(), semaphore_ptr, - 5 /* SemaphoreObject */); + auto sem = XObject::GetNativeObject( + kernel_state(), semaphore_ptr, X_DISPATCHER_FLAGS::DISPATCHER_SEMAPHORE); if (!sem) { assert_always(); return; @@ -1014,7 +1014,7 @@ dword_result_t KeWaitForMultipleObjects_entry( dword_t count, lpdword_t objects_ptr, dword_t wait_type, dword_t wait_reason, dword_t processor_mode, dword_t alertable, lpqword_t timeout_ptr, lpvoid_t wait_block_array_ptr) { - assert_true(wait_type <= 1); + assert_true(wait_type <= X_KWAIT_REASON::WaitAny); assert_true(count <= 64); object_ref objects[64]; @@ -1049,7 +1049,7 @@ uint32_t xeNtWaitForMultipleObjectsEx(uint32_t count, xe::be* handles, uint32_t wait_type, uint32_t wait_mode, uint32_t alertable, uint64_t* timeout_ptr) { - assert_true(wait_type <= 1); + assert_true(wait_type <= X_KWAIT_REASON::WaitAny); assert_true(count <= 64); object_ref objects[64]; @@ -1091,7 +1091,8 @@ dword_result_t NtWaitForMultipleObjectsEx_entry( dword_t count, lpdword_t handles, dword_t wait_type, dword_t wait_mode, dword_t alertable, lpqword_t timeout_ptr) { uint64_t timeout = timeout_ptr ? static_cast(*timeout_ptr) : 0u; - if (!count || count > 64 || (wait_type != 1 && wait_type)) { + if (!count || count > 64 || + (wait_type != X_KWAIT_REASON::WaitAny && wait_type)) { return X_STATUS_INVALID_PARAMETER; } return xeNtWaitForMultipleObjectsEx(count, handles, wait_type, wait_mode, @@ -1871,7 +1872,7 @@ dword_result_t KeSetPriorityThread_entry(pointer_t thread_ptr, return 0; } - if (thread_ptr->header.type != 6) { + if (thread_ptr->header.type != X_DISPATCHER_FLAGS::DISPATCHER_THREAD) { XELOGW("{}: Invalid object type: {}", __func__, thread_ptr->header.type); } diff --git a/src/xenia/kernel/xobject.h b/src/xenia/kernel/xobject.h index d9e8cdc32..9d9e0ba0f 100644 --- a/src/xenia/kernel/xobject.h +++ b/src/xenia/kernel/xobject.h @@ -34,10 +34,21 @@ class KernelState; template class object_ref; +enum X_DISPATCHER_FLAGS : uint8_t { + DISPATCHER_MANUAL_RESET_EVENT = 0, + DISPATCHER_AUTO_RESET_EVENT = 1, // EventSynchronizationObject + DISPATCHER_MUTANT = 2, + DISPATCHER_QUEUE = 4, + DISPATCHER_SEMAPHORE = 5, // SemaphoreObject + DISPATCHER_THREAD = 6, + DISPATCHER_MANUAL_RESET_TIMER = 8, + DISPATCHER_AUTO_RESET_TIMER = 9, +}; + // https://www.nirsoft.net/kernel_struct/vista/DISPATCHER_HEADER.html typedef struct { struct { - uint8_t type; + uint8_t type; // X_DISPATCHER_FLAGS union { uint8_t abandoned; diff --git a/src/xenia/kernel/xthread.cc b/src/xenia/kernel/xthread.cc index 08478ab90..33610bfb3 100644 --- a/src/xenia/kernel/xthread.cc +++ b/src/xenia/kernel/xthread.cc @@ -180,21 +180,25 @@ static uint8_t GetFakeCpuNumber(uint8_t proc_mask) { void XThread::InitializeGuestObject() { auto guest_thread = guest_object(); auto thread_guest_ptr = guest_object(); - guest_thread->header.type = 6; + guest_thread->header.type = X_DISPATCHER_FLAGS::DISPATCHER_THREAD; guest_thread->suspend_count = (creation_params_.creation_flags & X_CREATE_SUSPENDED) ? 1 : 0; - guest_thread->unk_10 = (thread_guest_ptr + 0x10); - guest_thread->unk_14 = (thread_guest_ptr + 0x10); + guest_thread->mutants_list.flink_ptr = (thread_guest_ptr + 0x10); + guest_thread->mutants_list.blink_ptr = (thread_guest_ptr + 0x10); + + auto timer_wait_header_list_entry = memory()->HostToGuestVirtual( + &guest_thread->wait_timeout_timer.header.wait_list); guest_thread->wait_timeout_block.wait_list_entry.flink_ptr = - thread_guest_ptr + 0x20; + timer_wait_header_list_entry; guest_thread->wait_timeout_block.wait_list_entry.blink_ptr = - thread_guest_ptr + 0x20; + timer_wait_header_list_entry; guest_thread->wait_timeout_block.thread = thread_guest_ptr; - uint32_t v6 = thread_guest_ptr + 0x18; - guest_thread->wait_timeout_block.wait_result_xstatus = 0x0100; - guest_thread->wait_timeout_block.wait_type = 0x0201; - guest_thread->wait_timeout_block.object = v6; + guest_thread->wait_timeout_block.object = + memory()->HostToGuestVirtual(&guest_thread->wait_timeout_timer); + guest_thread->wait_timeout_block.wait_result_xstatus = X_STATUS_TIMEOUT; + guest_thread->wait_timeout_block.wait_type = X_KWAIT_REASON::WaitAny; + guest_thread->stack_base = (this->stack_base_); guest_thread->stack_limit = (this->stack_limit_); guest_thread->stack_kernel = (this->stack_base_ - 240); diff --git a/src/xenia/kernel/xthread.h b/src/xenia/kernel/xthread.h index a40fe3b64..2c1e75856 100644 --- a/src/xenia/kernel/xthread.h +++ b/src/xenia/kernel/xthread.h @@ -48,17 +48,6 @@ enum IRQL_FLAGS : uint8_t { IRQL_HIGHEST = 124 }; -enum X_DISPATCHER_FLAGS { - DISPATCHER_MANUAL_RESET_EVENT = 0, - DISPATCHER_AUTO_RESET_EVENT = 1, - DISPATCHER_MUTANT = 2, - DISPATCHER_QUEUE = 4, - DISPATCHER_SEMAPHORE = 5, - DISPATCHER_THREAD = 6, - DISPATCHER_MANUAL_RESET_TIMER = 8, - DISPATCHER_AUTO_RESET_TIMER = 9, -}; - // https://www.geoffchappell.com/studies/windows/km/ntoskrnl/inc/ntos/ke/kthread_state.htm enum X_KTHREAD_STATE_FLAGS : uint8_t { KTHREAD_STATE_INITIALIZED = 0, @@ -222,12 +211,22 @@ struct X_KPCR { uint8_t unk_2AC[0x2C]; // 0x2AC }; -#ifdef WAIT_ANY -#undef WAIT_ANY -#endif -enum : uint16_t { - WAIT_ALL = 0, - WAIT_ANY = 1, +struct X_KMUTANT { + X_DISPATCH_HEADER header; // 0x0 + X_LIST_ENTRY unk_list; // 0x10 + TypedGuestPointer owner; // 0x18 + bool abandoned; // 0x1C + // these might just be padding + uint8_t unk_1D; // 0x1D + uint8_t unk_1E; // 0x1E + uint8_t unk_1F; // 0x1F +}; +static_assert_size(X_KMUTANT, 0x20); + +enum X_KWAIT_REASON : uint16_t { + WaitAll = 0, + WaitAny = 1, + WaitUnk3 = 3, }; // https://www.geoffchappell.com/studies/windows/km/ntoskrnl/inc/ntos/ke_x/kwait_block.htm @@ -243,7 +242,7 @@ struct X_KWAIT_BLOCK { // is satisfied xe::be wait_result_xstatus; // WAIT_ALL or WAIT_ANY - xe::be wait_type; + xe::be wait_type; }; static_assert_size(X_KWAIT_BLOCK, 0x18); @@ -258,9 +257,9 @@ struct X_KTIMER { static_assert_size(X_KTIMER, 0x28); struct X_KTHREAD { - X_DISPATCH_HEADER header; // 0x0 - xe::be unk_10; // 0x10 - xe::be unk_14; // 0x14 + X_DISPATCH_HEADER header; // 0x0 + util::X_TYPED_LIST + mutants_list; // 0x10 X_KTIMER wait_timeout_timer; // 0x18 X_KWAIT_BLOCK wait_timeout_block; // 0x40 uint8_t unk_58[0x4]; // 0x58 @@ -295,7 +294,11 @@ struct X_KTHREAD { xe::be msr_mask; // 0x9C xe::be wait_result; // 0xA0 uint8_t wait_irql; // 0xA4 - uint8_t unk_A5[0xB]; // 0xA5 + uint8_t processor_mode; // 0xA5 + uint8_t wait_next; // 0xA6 + uint8_t wait_reason; // 0xA7 + TypedGuestPointer wait_blocks; // 0xA8 + uint8_t unk_AC[4]; // 0xAC int32_t apc_disable_count; // 0xB0 xe::be quantum; // 0xB4 uint8_t saturation_increment; // 0xB8