From da630cc1596af8ed27c87bd66869eb71c514b3e6 Mon Sep 17 00:00:00 2001 From: Ben Vanik Date: Sat, 16 May 2015 16:34:14 -0700 Subject: [PATCH] Starting to clean up thread state. --- .../cpu/frontend/test/xe-cpu-ppc-test.cc | 4 +- src/xenia/cpu/thread_state.cc | 6 +-- src/xenia/cpu/thread_state.h | 6 +-- src/xenia/kernel/objects/xthread.cc | 47 +++++++++++-------- src/xenia/kernel/objects/xthread.h | 2 + 5 files changed, 37 insertions(+), 28 deletions(-) diff --git a/src/xenia/cpu/frontend/test/xe-cpu-ppc-test.cc b/src/xenia/cpu/frontend/test/xe-cpu-ppc-test.cc index a357ef6f6..26e602e45 100644 --- a/src/xenia/cpu/frontend/test/xe-cpu-ppc-test.cc +++ b/src/xenia/cpu/frontend/test/xe-cpu-ppc-test.cc @@ -197,9 +197,9 @@ class TestRunner { // Simulate a thread. uint32_t stack_size = 64 * 1024; uint32_t stack_address = START_ADDRESS - stack_size; - uint32_t thread_state_address = stack_address - 0x1000; + uint32_t pcr_address = stack_address - 0x1000; thread_state.reset(new ThreadState(processor.get(), 0x100, stack_address, - stack_size, thread_state_address)); + stack_size, pcr_address)); return true; } diff --git a/src/xenia/cpu/thread_state.cc b/src/xenia/cpu/thread_state.cc index 0ba1b2b0f..76fa8e555 100644 --- a/src/xenia/cpu/thread_state.cc +++ b/src/xenia/cpu/thread_state.cc @@ -28,14 +28,14 @@ thread_local ThreadState* thread_state_ = nullptr; ThreadState::ThreadState(Processor* processor, uint32_t thread_id, uint32_t stack_address, uint32_t stack_size, - uint32_t thread_state_address) + uint32_t pcr_address) : processor_(processor), memory_(processor->memory()), thread_id_(thread_id), name_(""), backend_data_(0), stack_size_(stack_size), - thread_state_address_(thread_state_address) { + pcr_address_(pcr_address) { if (thread_id_ == UINT_MAX) { // System thread. Assign the system thread ID with a high bit // set so people know what's up. @@ -87,7 +87,7 @@ ThreadState::ThreadState(Processor* processor, uint32_t thread_id, // Set initial registers. context_->r[1] = stack_position; - context_->r[13] = thread_state_address_; + context_->r[13] = pcr_address_; // Pad out stack a bit, as some games seem to overwrite the caller by about // 16 to 32b. diff --git a/src/xenia/cpu/thread_state.h b/src/xenia/cpu/thread_state.h index 542ea4638..a56a2bfc4 100644 --- a/src/xenia/cpu/thread_state.h +++ b/src/xenia/cpu/thread_state.h @@ -22,7 +22,7 @@ class Processor; class ThreadState { public: ThreadState(Processor* processor, uint32_t thread_id, uint32_t stack_address, - uint32_t stack_size, uint32_t thread_state_address); + uint32_t stack_size, uint32_t pcr_address); ~ThreadState(); Processor* processor() const { return processor_; } @@ -33,7 +33,7 @@ class ThreadState { void* backend_data() const { return backend_data_; } uint32_t stack_address() const { return stack_address_; } uint32_t stack_size() const { return stack_size_; } - uint32_t thread_state_address() const { return thread_state_address_; } + uint32_t pcr_address() const { return pcr_address_; } xe::cpu::frontend::PPCContext* context() const { return context_; } bool Suspend() { return Suspend(~0); } @@ -53,7 +53,7 @@ class ThreadState { uint32_t stack_address_; bool stack_allocated_; uint32_t stack_size_; - uint32_t thread_state_address_; + uint32_t pcr_address_; // NOTE: must be 64b aligned for SSE ops. xe::cpu::frontend::PPCContext* context_; diff --git a/src/xenia/kernel/objects/xthread.cc b/src/xenia/kernel/objects/xthread.cc index c945970da..11e6e7032 100644 --- a/src/xenia/kernel/objects/xthread.cc +++ b/src/xenia/kernel/objects/xthread.cc @@ -34,6 +34,7 @@ XThread::XThread(KernelState* kernel_state, uint32_t stack_size, : XObject(kernel_state, kTypeThread), thread_id_(++next_xthread_id), thread_handle_(0), + pcr_address_(0), thread_state_address_(0), thread_state_(0), event_(NULL), @@ -76,7 +77,7 @@ XThread::~XThread() { } kernel_state()->memory()->SystemHeapFree(scratch_address_); kernel_state()->memory()->SystemHeapFree(tls_address_); - kernel_state()->memory()->SystemHeapFree(thread_state_address_); + kernel_state()->memory()->SystemHeapFree(pcr_address_); if (thread_handle_) { // TODO(benvanik): platform kill @@ -137,7 +138,8 @@ X_STATUS XThread::Create() { // 0x160: last error // So, at offset 0x100 we have a 4b pointer to offset 200, then have the // structure. - thread_state_address_ = memory()->SystemHeapAlloc(0xAB0); + pcr_address_ = memory()->SystemHeapAlloc(0x2D8 + 0xAB0); + thread_state_address_ = pcr_address_ + 0x2D8; if (!thread_state_address_) { XELOGW("Unable to allocate thread state block"); return X_STATUS_NO_MEMORY; @@ -167,6 +169,23 @@ X_STATUS XThread::Create() { // TODO(benvanik): is this correct? memory()->Copy(tls_address_, header->tls_info.raw_data_address, tls_size); + // Allocate processor thread state. + // This is thread safe. + thread_state_ = new ThreadState(kernel_state()->processor(), thread_id_, 0, + creation_params_.stack_size, pcr_address_); + XELOGI("XThread%04X (%X) Stack: %.8X-%.8X", handle(), + thread_state_->thread_id(), thread_state_->stack_address(), + thread_state_->stack_address() + thread_state_->stack_size()); + + uint8_t* pcr = memory()->TranslateVirtual(pcr_address_); + xe::store_and_swap(pcr + 0x000, tls_address_); + xe::store_and_swap(pcr + 0x030, pcr_address_); + xe::store_and_swap(pcr + 0x070, thread_state_->stack_address() + + thread_state_->stack_size()); + xe::store_and_swap(pcr + 0x074, thread_state_->stack_address()); + xe::store_and_swap(pcr + 0x100, thread_state_address_); + xe::store_and_swap(pcr + 0x150, 0); // DPC active bool? + // Setup the thread state block (last error/etc). uint8_t* p = memory()->TranslateVirtual(thread_state_address_); xe::store_and_swap(p + 0x000, 6); @@ -180,6 +199,9 @@ X_STATUS XThread::Create() { xe::store_and_swap(p + 0x04C, thread_state_address_ + 0x018); xe::store_and_swap(p + 0x054, 0x102); xe::store_and_swap(p + 0x056, 1); + xe::store_and_swap( + p + 0x05C, thread_state_->stack_address() + thread_state_->stack_size()); + xe::store_and_swap(p + 0x060, thread_state_->stack_address()); xe::store_and_swap(p + 0x068, tls_address_); xe::store_and_swap(p + 0x06C, 0); xe::store_and_swap(p + 0x074, thread_state_address_ + 0x074); @@ -192,7 +214,8 @@ X_STATUS XThread::Create() { // A88 = APC // 18 = timer xe::store_and_swap(p + 0x09C, 0xFDFFD7FF); - xe::store_and_swap(p + 0x100, thread_state_address_); + xe::store_and_swap( + p + 0x0D0, thread_state_->stack_address() + thread_state_->stack_size()); FILETIME t; GetSystemTimeAsFileTime(&t); xe::store_and_swap( @@ -200,29 +223,13 @@ X_STATUS XThread::Create() { xe::store_and_swap(p + 0x144, thread_state_address_ + 0x144); xe::store_and_swap(p + 0x148, thread_state_address_ + 0x144); xe::store_and_swap(p + 0x14C, thread_id_); - // TODO(benvanik): figure out why RtlGetLastError changes on this: - // xe::store_and_swap(p + 0x150, creation_params_.start_address); + xe::store_and_swap(p + 0x150, creation_params_.start_address); xe::store_and_swap(p + 0x154, thread_state_address_ + 0x154); xe::store_and_swap(p + 0x158, thread_state_address_ + 0x154); xe::store_and_swap(p + 0x160, 0); // last error xe::store_and_swap(p + 0x16C, creation_params_.creation_flags); xe::store_and_swap(p + 0x17C, 1); - // Allocate processor thread state. - // This is thread safe. - thread_state_ = - new ThreadState(kernel_state()->processor(), thread_id_, 0, - creation_params_.stack_size, thread_state_address_); - XELOGI("XThread%04X (%X) Stack: %.8X-%.8X", handle(), - thread_state_->thread_id(), thread_state_->stack_address(), - thread_state_->stack_address() + thread_state_->stack_size()); - - xe::store_and_swap( - p + 0x05C, thread_state_->stack_address() + thread_state_->stack_size()); - xe::store_and_swap(p + 0x060, thread_state_->stack_address()); - xe::store_and_swap( - p + 0x0D0, thread_state_->stack_address() + thread_state_->stack_size()); - SetNativePointer(thread_state_address_); X_STATUS return_code = PlatformCreate(); diff --git a/src/xenia/kernel/objects/xthread.h b/src/xenia/kernel/objects/xthread.h index d210d7edd..e8d6456fb 100644 --- a/src/xenia/kernel/objects/xthread.h +++ b/src/xenia/kernel/objects/xthread.h @@ -35,6 +35,7 @@ class XThread : public XObject { static uint32_t GetCurrentThreadHandle(); static uint32_t GetCurrentThreadId(const uint8_t* thread_state_block); + uint32_t pcr_ptr() const { return pcr_address_; } uint32_t thread_state_ptr() const { return thread_state_address_; } cpu::ThreadState* thread_state() const { return thread_state_; } uint32_t thread_id() const { return thread_id_; } @@ -89,6 +90,7 @@ class XThread : public XObject { uint32_t scratch_address_; uint32_t scratch_size_; uint32_t tls_address_; + uint32_t pcr_address_; uint32_t thread_state_address_; cpu::ThreadState* thread_state_;