[Kernel] Move xboxkrnl_threading to new shim convention.

This commit is contained in:
gibbed 2018-11-20 15:49:06 -06:00
parent d7fc74d788
commit 5b776b99da
1 changed files with 209 additions and 392 deletions

View File

@ -93,20 +93,11 @@ object_ref<T> LookupNamedObject(KernelState* kernel_state,
return nullptr; return nullptr;
} }
SHIM_CALL ExCreateThread_shim(PPCContext* ppc_context, dword_result_t ExCreateThread(lpdword_t handle_ptr, dword_t stack_size,
KernelState* kernel_state) { lpdword_t thread_id_ptr,
uint32_t handle_ptr = SHIM_GET_ARG_32(0); dword_t xapi_thread_startup,
uint32_t stack_size = SHIM_GET_ARG_32(1); lpvoid_t start_address, lpvoid_t start_context,
uint32_t thread_id_ptr = SHIM_GET_ARG_32(2); dword_t creation_flags) {
uint32_t xapi_thread_startup = SHIM_GET_ARG_32(3);
uint32_t start_address = SHIM_GET_ARG_32(4);
uint32_t start_context = SHIM_GET_ARG_32(5);
uint32_t creation_flags = SHIM_GET_ARG_32(6);
XELOGD("ExCreateThread(%.8X, %d, %.8X, %.8X, %.8X, %.8X, %.8X)", handle_ptr,
stack_size, thread_id_ptr, xapi_thread_startup, start_address,
start_context, creation_flags);
// http://jafile.com/uploads/scoop/main.cpp.txt // http://jafile.com/uploads/scoop/main.cpp.txt
// DWORD // DWORD
// LPHANDLE Handle, // LPHANDLE Handle,
@ -118,103 +109,86 @@ SHIM_CALL ExCreateThread_shim(PPCContext* ppc_context,
// DWORD CreationFlags // 0x80? // DWORD CreationFlags // 0x80?
// Inherit default stack size // Inherit default stack size
if (stack_size == 0) { uint32_t actual_stack_size = stack_size;
stack_size = kernel_state->GetExecutableModule()->stack_size();
if (actual_stack_size == 0) {
actual_stack_size = kernel_state()->GetExecutableModule()->stack_size();
} }
// Stack must be aligned to 16kb pages // Stack must be aligned to 16kb pages
stack_size = std::max((uint32_t)0x4000, ((stack_size + 0xFFF) & 0xFFFFF000)); actual_stack_size =
std::max((uint32_t)0x4000, ((actual_stack_size + 0xFFF) & 0xFFFFF000));
auto thread = object_ref<XThread>( auto thread = object_ref<XThread>(
new XThread(kernel_state, stack_size, xapi_thread_startup, start_address, new XThread(kernel_state(), actual_stack_size, xapi_thread_startup,
start_context, creation_flags, true)); start_address.guest_address(), start_context.guest_address(),
creation_flags, true));
X_STATUS result = thread->Create(); X_STATUS result = thread->Create();
if (XFAILED(result)) { if (XFAILED(result)) {
// Failed! // Failed!
XELOGE("Thread creation failed: %.8X", result); XELOGE("Thread creation failed: %.8X", result);
SHIM_SET_RETURN_32(result); return result;
return;
} }
if (XSUCCEEDED(result)) { if (XSUCCEEDED(result)) {
if (handle_ptr) { if (handle_ptr) {
if (creation_flags & 0x80) { if (creation_flags & 0x80) {
SHIM_SET_MEM_32(handle_ptr, thread->guest_object()); *handle_ptr = thread->guest_object();
} else { } else {
SHIM_SET_MEM_32(handle_ptr, thread->handle()); *handle_ptr = thread->handle();
} }
} }
if (thread_id_ptr) { if (thread_id_ptr) {
SHIM_SET_MEM_32(thread_id_ptr, thread->thread_id()); *thread_id_ptr = thread->thread_id();
} }
} }
SHIM_SET_RETURN_32(result); return result;
} }
DECLARE_XBOXKRNL_EXPORT1(ExCreateThread, kThreading, kImplemented);
SHIM_CALL ExTerminateThread_shim(PPCContext* ppc_context, dword_result_t ExTerminateThread(dword_t exit_code) {
KernelState* kernel_state) {
uint32_t exit_code = SHIM_GET_ARG_32(0);
XELOGD("ExTerminateThread(%d)", exit_code);
XThread* thread = XThread::GetCurrentThread(); XThread* thread = XThread::GetCurrentThread();
// NOTE: this kills us right now. We won't return from it. // NOTE: this kills us right now. We won't return from it.
X_STATUS result = thread->Exit(exit_code); return thread->Exit(exit_code);
SHIM_SET_RETURN_32(result);
} }
DECLARE_XBOXKRNL_EXPORT1(ExTerminateThread, kThreading, kImplemented);
SHIM_CALL NtResumeThread_shim(PPCContext* ppc_context, dword_result_t NtResumeThread(dword_t handle, lpdword_t suspend_count_ptr) {
KernelState* kernel_state) {
uint32_t handle = SHIM_GET_ARG_32(0);
uint32_t suspend_count_ptr = SHIM_GET_ARG_32(1);
XELOGD("NtResumeThread(%.8X, %.8X)", handle, suspend_count_ptr);
X_RESULT result = X_STATUS_INVALID_HANDLE; X_RESULT result = X_STATUS_INVALID_HANDLE;
uint32_t suspend_count = 0; uint32_t suspend_count = 0;
auto thread = kernel_state->object_table()->LookupObject<XThread>(handle); auto thread = kernel_state()->object_table()->LookupObject<XThread>(handle);
if (thread) { if (thread) {
result = thread->Resume(&suspend_count); result = thread->Resume(&suspend_count);
} }
if (suspend_count_ptr) { if (suspend_count_ptr) {
SHIM_SET_MEM_32(suspend_count_ptr, suspend_count); *suspend_count_ptr = suspend_count;
} }
SHIM_SET_RETURN_32(result); return result;
} }
DECLARE_XBOXKRNL_EXPORT1(NtResumeThread, kThreading, kImplemented);
SHIM_CALL KeResumeThread_shim(PPCContext* ppc_context, dword_result_t KeResumeThread(lpvoid_t thread_ptr) {
KernelState* kernel_state) {
uint32_t thread_ptr = SHIM_GET_ARG_32(0);
XELOGD("KeResumeThread(%.8X)", thread_ptr);
X_STATUS result = X_STATUS_SUCCESS; X_STATUS result = X_STATUS_SUCCESS;
auto thread = XObject::GetNativeObject<XThread>(kernel_state, auto thread = XObject::GetNativeObject<XThread>(kernel_state(), thread_ptr);
SHIM_MEM_ADDR(thread_ptr));
if (thread) { if (thread) {
result = thread->Resume(); result = thread->Resume();
} else { } else {
result = X_STATUS_INVALID_HANDLE; result = X_STATUS_INVALID_HANDLE;
} }
SHIM_SET_RETURN_32(result); return result;
} }
DECLARE_XBOXKRNL_EXPORT1(KeResumeThread, kThreading, kImplemented);
SHIM_CALL NtSuspendThread_shim(PPCContext* ppc_context, dword_result_t NtSuspendThread(dword_t handle, lpdword_t suspend_count_ptr) {
KernelState* kernel_state) {
uint32_t handle = SHIM_GET_ARG_32(0);
uint32_t suspend_count_ptr = SHIM_GET_ARG_32(1);
XELOGD("NtSuspendThread(%.8X, %.8X)", handle, suspend_count_ptr);
X_RESULT result = X_STATUS_SUCCESS; X_RESULT result = X_STATUS_SUCCESS;
uint32_t suspend_count = 0; uint32_t suspend_count = 0;
auto thread = kernel_state->object_table()->LookupObject<XThread>(handle); auto thread = kernel_state()->object_table()->LookupObject<XThread>(handle);
if (thread) { if (thread) {
result = thread->Suspend(&suspend_count); result = thread->Suspend(&suspend_count);
} else { } else {
@ -222,11 +196,12 @@ SHIM_CALL NtSuspendThread_shim(PPCContext* ppc_context,
} }
if (suspend_count_ptr) { if (suspend_count_ptr) {
SHIM_SET_MEM_32(suspend_count_ptr, suspend_count); *suspend_count_ptr = suspend_count;
} }
SHIM_SET_RETURN_32(result); return result;
} }
DECLARE_XBOXKRNL_EXPORT1(NtSuspendThread, kThreading, kImplemented);
void KeSetCurrentStackPointers(lpvoid_t stack_ptr, void KeSetCurrentStackPointers(lpvoid_t stack_ptr,
pointer_t<X_KTHREAD> cur_thread, pointer_t<X_KTHREAD> cur_thread,
@ -245,104 +220,72 @@ void KeSetCurrentStackPointers(lpvoid_t stack_ptr,
} }
DECLARE_XBOXKRNL_EXPORT1(KeSetCurrentStackPointers, kThreading, kImplemented); DECLARE_XBOXKRNL_EXPORT1(KeSetCurrentStackPointers, kThreading, kImplemented);
SHIM_CALL KeSetAffinityThread_shim(PPCContext* ppc_context, dword_result_t KeSetAffinityThread(lpvoid_t thread_ptr, dword_t affinity) {
KernelState* kernel_state) { auto thread = XObject::GetNativeObject<XThread>(kernel_state(), thread_ptr);
uint32_t thread_ptr = SHIM_GET_ARG_32(0);
uint32_t affinity = SHIM_GET_ARG_32(1);
XELOGD("KeSetAffinityThread(%.8X, %.8X)", thread_ptr, affinity);
auto thread = XObject::GetNativeObject<XThread>(kernel_state,
SHIM_MEM_ADDR(thread_ptr));
if (thread) { if (thread) {
thread->SetAffinity(affinity); thread->SetAffinity(affinity);
} }
SHIM_SET_RETURN_32(affinity); return (uint32_t)affinity;
} }
DECLARE_XBOXKRNL_EXPORT1(KeSetAffinityThread, kThreading, kImplemented);
SHIM_CALL KeQueryBasePriorityThread_shim(PPCContext* ppc_context, dword_result_t KeQueryBasePriorityThread(lpvoid_t thread_ptr) {
KernelState* kernel_state) {
uint32_t thread_ptr = SHIM_GET_ARG_32(0);
XELOGD("KeQueryBasePriorityThread(%.8X)", thread_ptr);
int32_t priority = 0; int32_t priority = 0;
auto thread = XObject::GetNativeObject<XThread>(kernel_state, auto thread = XObject::GetNativeObject<XThread>(kernel_state(), thread_ptr);
SHIM_MEM_ADDR(thread_ptr));
if (thread) { if (thread) {
priority = thread->QueryPriority(); priority = thread->QueryPriority();
} }
SHIM_SET_RETURN_32(priority); return priority;
} }
DECLARE_XBOXKRNL_EXPORT1(KeQueryBasePriorityThread, kThreading, kImplemented);
SHIM_CALL KeSetBasePriorityThread_shim(PPCContext* ppc_context, dword_result_t KeSetBasePriorityThread(lpvoid_t thread_ptr, dword_t increment) {
KernelState* kernel_state) {
uint32_t thread_ptr = SHIM_GET_ARG_32(0);
uint32_t increment = SHIM_GET_ARG_32(1);
XELOGD("KeSetBasePriorityThread(%.8X, %.8X)", thread_ptr, increment);
int32_t prev_priority = 0; int32_t prev_priority = 0;
auto thread = XObject::GetNativeObject<XThread>(kernel_state, auto thread = XObject::GetNativeObject<XThread>(kernel_state(), thread_ptr);
SHIM_MEM_ADDR(thread_ptr));
if (thread) { if (thread) {
prev_priority = thread->QueryPriority(); prev_priority = thread->QueryPriority();
thread->SetPriority(increment); thread->SetPriority(increment);
} }
SHIM_SET_RETURN_32(prev_priority); return prev_priority;
} }
DECLARE_XBOXKRNL_EXPORT1(KeSetBasePriorityThread, kThreading, kImplemented);
SHIM_CALL KeSetDisableBoostThread_shim(PPCContext* ppc_context, dword_result_t KeSetDisableBoostThread(lpvoid_t thread_ptr, dword_t disabled) {
KernelState* kernel_state) { auto thread = XObject::GetNativeObject<XThread>(kernel_state(), thread_ptr);
uint32_t thread_ptr = SHIM_GET_ARG_32(0);
uint32_t disabled = SHIM_GET_ARG_32(1);
XELOGD("KeSetDisableBoostThread(%.8X, %.8X)", thread_ptr, disabled);
auto thread = XObject::GetNativeObject<XThread>(kernel_state,
SHIM_MEM_ADDR(thread_ptr));
if (thread) { if (thread) {
// Uhm? // Uhm?
} }
SHIM_SET_RETURN_32(0); return 0;
} }
DECLARE_XBOXKRNL_EXPORT1(KeSetDisableBoostThread, kThreading, kImplemented);
SHIM_CALL KeGetCurrentProcessType_shim(PPCContext* ppc_context, dword_result_t KeGetCurrentProcessType() {
KernelState* kernel_state) { return kernel_state()->process_type();
// XELOGD(
// "KeGetCurrentProcessType()");
// DWORD
SHIM_SET_RETURN_32(kernel_state->process_type());
} }
DECLARE_XBOXKRNL_EXPORT2(KeGetCurrentProcessType, kThreading, kImplemented,
kHighFrequency);
SHIM_CALL KeSetCurrentProcessType_shim(PPCContext* ppc_context, void KeSetCurrentProcessType(dword_t type) {
KernelState* kernel_state) {
uint32_t type = SHIM_GET_ARG_32(0);
// One of X_PROCTYPE_? // One of X_PROCTYPE_?
XELOGD("KeSetCurrentProcessType(%d)", type);
assert_true(type <= 2); assert_true(type <= 2);
kernel_state->set_process_type(type); kernel_state()->set_process_type(type);
} }
DECLARE_XBOXKRNL_EXPORT1(KeSetCurrentProcessType, kThreading, kImplemented);
SHIM_CALL KeQueryPerformanceFrequency_shim(PPCContext* ppc_context, dword_result_t KeQueryPerformanceFrequency() {
KernelState* kernel_state) {
// XELOGD(
// "KeQueryPerformanceFrequency()");
uint64_t result = Clock::guest_tick_frequency(); uint64_t result = Clock::guest_tick_frequency();
SHIM_SET_RETURN_32(result); return static_cast<uint32_t>(result);
} }
DECLARE_XBOXKRNL_EXPORT2(KeQueryPerformanceFrequency, kThreading, kImplemented,
kHighFrequency);
dword_result_t KeDelayExecutionThread(dword_t processor_mode, dword_t alertable, dword_result_t KeDelayExecutionThread(dword_t processor_mode, dword_t alertable,
lpqword_t interval_ptr) { lpqword_t interval_ptr) {
@ -354,25 +297,21 @@ dword_result_t KeDelayExecutionThread(dword_t processor_mode, dword_t alertable,
DECLARE_XBOXKRNL_EXPORT3(KeDelayExecutionThread, kThreading, kImplemented, DECLARE_XBOXKRNL_EXPORT3(KeDelayExecutionThread, kThreading, kImplemented,
kBlocking, kHighFrequency); kBlocking, kHighFrequency);
SHIM_CALL NtYieldExecution_shim(PPCContext* ppc_context, dword_result_t NtYieldExecution() {
KernelState* kernel_state) {
// XELOGD("NtYieldExecution()");
auto thread = XThread::GetCurrentThread(); auto thread = XThread::GetCurrentThread();
thread->Delay(0, 0, 0); thread->Delay(0, 0, 0);
SHIM_SET_RETURN_32(0); return 0;
} }
DECLARE_XBOXKRNL_EXPORT2(NtYieldExecution, kThreading, kImplemented,
kHighFrequency);
SHIM_CALL KeQuerySystemTime_shim(PPCContext* ppc_context, void KeQuerySystemTime(lpqword_t time_ptr) {
KernelState* kernel_state) {
uint32_t time_ptr = SHIM_GET_ARG_32(0);
XELOGD("KeQuerySystemTime(%.8X)", time_ptr);
uint64_t time = Clock::QueryGuestSystemTime(); uint64_t time = Clock::QueryGuestSystemTime();
if (time_ptr) { if (time_ptr) {
SHIM_SET_MEM_64(time_ptr, time); *time_ptr = time;
} }
} }
DECLARE_XBOXKRNL_EXPORT1(KeQuerySystemTime, kThreading, kImplemented);
// http://msdn.microsoft.com/en-us/library/ms686801 // http://msdn.microsoft.com/en-us/library/ms686801
dword_result_t KeTlsAlloc() { dword_result_t KeTlsAlloc() {
@ -586,34 +525,26 @@ dword_result_t KeReleaseSemaphore(pointer_t<X_KSEMAPHORE> semaphore_ptr,
} }
DECLARE_XBOXKRNL_EXPORT1(KeReleaseSemaphore, kThreading, kImplemented); DECLARE_XBOXKRNL_EXPORT1(KeReleaseSemaphore, kThreading, kImplemented);
SHIM_CALL NtCreateSemaphore_shim(PPCContext* ppc_context, dword_result_t NtCreateSemaphore(lpdword_t handle_ptr,
KernelState* kernel_state) { lpvoid_t obj_attributes_ptr, dword_t count,
uint32_t handle_ptr = SHIM_GET_ARG_32(0); dword_t limit) {
uint32_t obj_attributes_ptr = SHIM_GET_ARG_32(1);
int32_t count = SHIM_GET_ARG_32(2);
int32_t limit = SHIM_GET_ARG_32(3);
XELOGD("NtCreateSemaphore(%.8X, %.8X, %d, %d)", handle_ptr,
obj_attributes_ptr, count, limit);
// Check for an existing timer with the same name. // Check for an existing timer with the same name.
auto existing_object = auto existing_object =
LookupNamedObject<XSemaphore>(kernel_state, obj_attributes_ptr); LookupNamedObject<XSemaphore>(kernel_state(), obj_attributes_ptr);
if (existing_object) { if (existing_object) {
if (existing_object->type() == XObject::kTypeSemaphore) { if (existing_object->type() == XObject::kTypeSemaphore) {
if (handle_ptr) { if (handle_ptr) {
existing_object->RetainHandle(); existing_object->RetainHandle();
SHIM_SET_MEM_32(handle_ptr, existing_object->handle()); *handle_ptr = existing_object->handle();
} }
SHIM_SET_RETURN_32(X_STATUS_SUCCESS); return X_STATUS_SUCCESS;
} else { } else {
SHIM_SET_RETURN_32(X_STATUS_INVALID_HANDLE); return X_STATUS_INVALID_HANDLE;
} }
return;
} }
auto sem = object_ref<XSemaphore>(new XSemaphore(kernel_state)); auto sem = object_ref<XSemaphore>(new XSemaphore(kernel_state()));
sem->Initialize(count, limit); sem->Initialize((int32_t)count, (int32_t)limit);
// obj_attributes may have a name inside of it, if != NULL. // obj_attributes may have a name inside of it, if != NULL.
if (obj_attributes_ptr) { if (obj_attributes_ptr) {
@ -621,36 +552,32 @@ SHIM_CALL NtCreateSemaphore_shim(PPCContext* ppc_context,
} }
if (handle_ptr) { if (handle_ptr) {
SHIM_SET_MEM_32(handle_ptr, sem->handle()); *handle_ptr = sem->handle();
} }
SHIM_SET_RETURN_32(X_STATUS_SUCCESS); return X_STATUS_SUCCESS;
} }
DECLARE_XBOXKRNL_EXPORT1(NtCreateSemaphore, kThreading, kImplemented);
SHIM_CALL NtReleaseSemaphore_shim(PPCContext* ppc_context, dword_result_t NtReleaseSemaphore(dword_t sem_handle, dword_t release_count,
KernelState* kernel_state) { lpdword_t previous_count_ptr) {
uint32_t sem_handle = SHIM_GET_ARG_32(0);
int32_t release_count = SHIM_GET_ARG_32(1);
int32_t previous_count_ptr = SHIM_GET_ARG_32(2);
XELOGD("NtReleaseSemaphore(%.8X, %d, %.8X)", sem_handle, release_count,
previous_count_ptr);
X_STATUS result = X_STATUS_SUCCESS; X_STATUS result = X_STATUS_SUCCESS;
int32_t previous_count = 0; int32_t previous_count = 0;
auto sem = kernel_state->object_table()->LookupObject<XSemaphore>(sem_handle); auto sem =
kernel_state()->object_table()->LookupObject<XSemaphore>(sem_handle);
if (sem) { if (sem) {
previous_count = sem->ReleaseSemaphore(release_count); previous_count = sem->ReleaseSemaphore((int32_t)release_count);
} else { } else {
result = X_STATUS_INVALID_HANDLE; result = X_STATUS_INVALID_HANDLE;
} }
if (previous_count_ptr) { if (previous_count_ptr) {
SHIM_SET_MEM_32(previous_count_ptr, previous_count); *previous_count_ptr = (uint32_t)previous_count;
} }
SHIM_SET_RETURN_32(result); return result;
} }
DECLARE_XBOXKRNL_EXPORT1(NtReleaseSemaphore, kThreading, kImplemented);
dword_result_t NtCreateMutant(lpdword_t handle_out, dword_result_t NtCreateMutant(lpdword_t handle_out,
pointer_t<X_OBJECT_ATTRIBUTES> obj_attributes, pointer_t<X_OBJECT_ATTRIBUTES> obj_attributes,
@ -686,10 +613,7 @@ dword_result_t NtCreateMutant(lpdword_t handle_out,
} }
DECLARE_XBOXKRNL_EXPORT1(NtCreateMutant, kThreading, kImplemented); DECLARE_XBOXKRNL_EXPORT1(NtCreateMutant, kThreading, kImplemented);
SHIM_CALL NtReleaseMutant_shim(PPCContext* ppc_context, dword_result_t NtReleaseMutant(dword_t mutant_handle, dword_t unknown) {
KernelState* kernel_state) {
uint32_t mutant_handle = SHIM_GET_ARG_32(0);
int32_t unknown = SHIM_GET_ARG_32(1);
// This doesn't seem to be supported. // This doesn't seem to be supported.
// int32_t previous_count_ptr = SHIM_GET_ARG_32(2); // int32_t previous_count_ptr = SHIM_GET_ARG_32(2);
@ -706,44 +630,37 @@ SHIM_CALL NtReleaseMutant_shim(PPCContext* ppc_context,
X_STATUS result = X_STATUS_SUCCESS; X_STATUS result = X_STATUS_SUCCESS;
auto mutant = auto mutant =
kernel_state->object_table()->LookupObject<XMutant>(mutant_handle); kernel_state()->object_table()->LookupObject<XMutant>(mutant_handle);
if (mutant) { if (mutant) {
result = mutant->ReleaseMutant(priority_increment, abandon, wait); result = mutant->ReleaseMutant(priority_increment, abandon, wait);
} else { } else {
result = X_STATUS_INVALID_HANDLE; result = X_STATUS_INVALID_HANDLE;
} }
SHIM_SET_RETURN_32(result); return result;
} }
DECLARE_XBOXKRNL_EXPORT1(NtReleaseMutant, kThreading, kImplemented);
SHIM_CALL NtCreateTimer_shim(PPCContext* ppc_context, dword_result_t NtCreateTimer(lpdword_t handle_ptr, lpvoid_t obj_attributes_ptr,
KernelState* kernel_state) { dword_t timer_type) {
uint32_t handle_ptr = SHIM_GET_ARG_32(0);
uint32_t obj_attributes_ptr = SHIM_GET_ARG_32(1);
uint32_t timer_type = SHIM_GET_ARG_32(2);
// timer_type = NotificationTimer (0) or SynchronizationTimer (1) // timer_type = NotificationTimer (0) or SynchronizationTimer (1)
XELOGD("NtCreateTimer(%.8X, %.8X, %.1X)", handle_ptr, obj_attributes_ptr,
timer_type);
// Check for an existing timer with the same name. // Check for an existing timer with the same name.
auto existing_object = auto existing_object =
LookupNamedObject<XTimer>(kernel_state, obj_attributes_ptr); LookupNamedObject<XTimer>(kernel_state(), obj_attributes_ptr);
if (existing_object) { if (existing_object) {
if (existing_object->type() == XObject::kTypeTimer) { if (existing_object->type() == XObject::kTypeTimer) {
if (handle_ptr) { if (handle_ptr) {
existing_object->RetainHandle(); existing_object->RetainHandle();
SHIM_SET_MEM_32(handle_ptr, existing_object->handle()); *handle_ptr = existing_object->handle();
} }
SHIM_SET_RETURN_32(X_STATUS_SUCCESS); return X_STATUS_SUCCESS;
} else { } else {
SHIM_SET_RETURN_32(X_STATUS_INVALID_HANDLE); return X_STATUS_INVALID_HANDLE;
} }
return;
} }
auto timer = object_ref<XTimer>(new XTimer(kernel_state)); auto timer = object_ref<XTimer>(new XTimer(kernel_state()));
timer->Initialize(timer_type); timer->Initialize(timer_type);
// obj_attributes may have a name inside of it, if != NULL. // obj_attributes may have a name inside of it, if != NULL.
@ -752,66 +669,57 @@ SHIM_CALL NtCreateTimer_shim(PPCContext* ppc_context,
} }
if (handle_ptr) { if (handle_ptr) {
SHIM_SET_MEM_32(handle_ptr, timer->handle()); *handle_ptr = timer->handle();
} }
SHIM_SET_RETURN_32(X_STATUS_SUCCESS); return X_STATUS_SUCCESS;
} }
DECLARE_XBOXKRNL_EXPORT1(NtCreateTimer, kThreading, kImplemented);
SHIM_CALL NtSetTimerEx_shim(PPCContext* ppc_context, dword_result_t NtSetTimerEx(dword_t timer_handle, lpqword_t due_time_ptr,
KernelState* kernel_state) { lpvoid_t routine_ptr /*PTIMERAPCROUTINE*/,
uint32_t timer_handle = SHIM_GET_ARG_32(0); dword_t unk_one, lpvoid_t routine_arg,
uint32_t due_time_ptr = SHIM_GET_ARG_32(1); dword_t resume, dword_t period_ms,
uint32_t routine = SHIM_GET_ARG_32(2); // PTIMERAPCROUTINE dword_t unk_zero) {
uint32_t unk_one = SHIM_GET_ARG_32(3);
uint32_t routine_arg = SHIM_GET_ARG_32(4);
uint32_t resume = SHIM_GET_ARG_32(5);
uint32_t period_ms = SHIM_GET_ARG_32(6);
uint32_t unk_zero = SHIM_GET_ARG_32(7);
assert_true(unk_one == 1); assert_true(unk_one == 1);
assert_true(unk_zero == 0); assert_true(unk_zero == 0);
uint64_t due_time = SHIM_MEM_64(due_time_ptr); uint64_t due_time = *due_time_ptr;
XELOGD("NtSetTimerEx(%.8X, %.8X(%lld), %.8X, %.8X, %.8X, %.1X, %d, %.8X)",
timer_handle, due_time_ptr, due_time, routine, unk_one, routine_arg,
resume, period_ms, unk_zero);
X_STATUS result = X_STATUS_SUCCESS; X_STATUS result = X_STATUS_SUCCESS;
auto timer = kernel_state->object_table()->LookupObject<XTimer>(timer_handle); auto timer =
kernel_state()->object_table()->LookupObject<XTimer>(timer_handle);
if (timer) { if (timer) {
result = timer->SetTimer(due_time, period_ms, routine, routine_arg, result =
resume ? true : false); timer->SetTimer(due_time, period_ms, routine_ptr.guest_address(),
routine_arg.guest_address(), resume ? true : false);
} else { } else {
result = X_STATUS_INVALID_HANDLE; result = X_STATUS_INVALID_HANDLE;
} }
SHIM_SET_RETURN_32(result); return result;
} }
DECLARE_XBOXKRNL_EXPORT1(NtSetTimerEx, kThreading, kImplemented);
SHIM_CALL NtCancelTimer_shim(PPCContext* ppc_context, dword_result_t NtCancelTimer(dword_t timer_handle,
KernelState* kernel_state) { lpdword_t current_state_ptr) {
uint32_t timer_handle = SHIM_GET_ARG_32(0);
uint32_t current_state_ptr = SHIM_GET_ARG_32(1);
XELOGD("NtCancelTimer(%.8X, %.8X)", timer_handle, current_state_ptr);
X_STATUS result = X_STATUS_SUCCESS; X_STATUS result = X_STATUS_SUCCESS;
auto timer = kernel_state->object_table()->LookupObject<XTimer>(timer_handle); auto timer =
kernel_state()->object_table()->LookupObject<XTimer>(timer_handle);
if (timer) { if (timer) {
result = timer->Cancel(); result = timer->Cancel();
} else { } else {
result = X_STATUS_INVALID_HANDLE; result = X_STATUS_INVALID_HANDLE;
} }
if (current_state_ptr) { if (current_state_ptr) {
SHIM_SET_MEM_32(current_state_ptr, 0); *current_state_ptr = 0;
} }
SHIM_SET_RETURN_32(result); return result;
} }
DECLARE_XBOXKRNL_EXPORT1(NtCancelTimer, kThreading, kImplemented);
dword_result_t KeWaitForSingleObject(lpvoid_t object_ptr, dword_t wait_reason, dword_result_t KeWaitForSingleObject(lpvoid_t object_ptr, dword_t wait_reason,
dword_t processor_mode, dword_t alertable, dword_t processor_mode, dword_t alertable,
@ -991,96 +899,63 @@ void KeReleaseSpinLockFromRaisedIrql(lpdword_t lock_ptr) {
DECLARE_XBOXKRNL_EXPORT2(KeReleaseSpinLockFromRaisedIrql, kThreading, DECLARE_XBOXKRNL_EXPORT2(KeReleaseSpinLockFromRaisedIrql, kThreading,
kImplemented, kHighFrequency); kImplemented, kHighFrequency);
SHIM_CALL KeEnterCriticalRegion_shim(PPCContext* ppc_context, void KeEnterCriticalRegion() { XThread::EnterCriticalRegion(); }
KernelState* kernel_state) { DECLARE_XBOXKRNL_EXPORT2(KeEnterCriticalRegion, kThreading, kImplemented,
// XELOGD( kHighFrequency);
// "KeEnterCriticalRegion()");
XThread::EnterCriticalRegion();
}
SHIM_CALL KeLeaveCriticalRegion_shim(PPCContext* ppc_context, void KeLeaveCriticalRegion() {
KernelState* kernel_state) {
// XELOGD(
// "KeLeaveCriticalRegion()");
XThread::LeaveCriticalRegion(); XThread::LeaveCriticalRegion();
XThread::GetCurrentThread()->CheckApcs(); XThread::GetCurrentThread()->CheckApcs();
} }
DECLARE_XBOXKRNL_EXPORT2(KeLeaveCriticalRegion, kThreading, kImplemented,
kHighFrequency);
SHIM_CALL KeRaiseIrqlToDpcLevel_shim(PPCContext* ppc_context, dword_result_t KeRaiseIrqlToDpcLevel() {
KernelState* kernel_state) { auto old_value = kernel_state()->processor()->RaiseIrql(cpu::Irql::DPC);
// XELOGD( return (uint32_t)old_value;
// "KeRaiseIrqlToDpcLevel()");
auto old_value = kernel_state->processor()->RaiseIrql(cpu::Irql::DPC);
SHIM_SET_RETURN_32(old_value);
} }
DECLARE_XBOXKRNL_EXPORT2(KeRaiseIrqlToDpcLevel, kThreading, kImplemented,
kHighFrequency);
SHIM_CALL KfLowerIrql_shim(PPCContext* ppc_context, KernelState* kernel_state) { void KfLowerIrql(dword_t old_value) {
uint32_t old_value = SHIM_GET_ARG_32(0); kernel_state()->processor()->LowerIrql(
// XELOGD( static_cast<cpu::Irql>((uint32_t)old_value));
// "KfLowerIrql(%d)",
// old_value);
kernel_state->processor()->LowerIrql(static_cast<cpu::Irql>(old_value));
XThread::GetCurrentThread()->CheckApcs(); XThread::GetCurrentThread()->CheckApcs();
} }
DECLARE_XBOXKRNL_EXPORT2(KfLowerIrql, kThreading, kImplemented, kHighFrequency);
SHIM_CALL NtQueueApcThread_shim(PPCContext* ppc_context, void NtQueueApcThread(dword_t thread_handle, lpvoid_t apc_routine,
KernelState* kernel_state) { lpvoid_t arg1, lpvoid_t arg2, lpvoid_t arg3) {
uint32_t thread_handle = SHIM_GET_ARG_32(0);
uint32_t apc_routine = SHIM_GET_ARG_32(1);
uint32_t arg1 = SHIM_GET_ARG_32(2);
uint32_t arg2 = SHIM_GET_ARG_32(3);
uint32_t arg3 = SHIM_GET_ARG_32(4); // ?
XELOGD("NtQueueApcThread(%.8X, %.8X, %.8X, %.8X, %.8X)", thread_handle,
apc_routine, arg1, arg2, arg3);
// Alloc APC object (from somewhere) and insert. // Alloc APC object (from somewhere) and insert.
assert_always("not implemented"); assert_always("not implemented");
} }
// DECLARE_XBOXKRNL_EXPORT1(NtQueueApcThread, kThreading, kStub);
SHIM_CALL KeInitializeApc_shim(PPCContext* ppc_context, void KeInitializeApc(pointer_t<XAPC> apc, lpvoid_t thread_ptr,
KernelState* kernel_state) { lpvoid_t kernel_routine, lpvoid_t rundown_routine,
uint32_t apc_ptr = SHIM_GET_ARG_32(0); lpvoid_t normal_routine, dword_t processor_mode,
uint32_t thread = SHIM_GET_ARG_32(1); lpvoid_t normal_context) {
uint32_t kernel_routine = SHIM_GET_ARG_32(2);
uint32_t rundown_routine = SHIM_GET_ARG_32(3);
uint32_t normal_routine = SHIM_GET_ARG_32(4);
uint32_t processor_mode = SHIM_GET_ARG_32(5);
uint32_t normal_context = SHIM_GET_ARG_32(6);
XELOGD("KeInitializeApc(%.8X, %.8X, %.8X, %.8X, %.8X, %.8X, %.8X)", apc_ptr,
thread, kernel_routine, rundown_routine, normal_routine,
processor_mode, normal_context);
auto apc = SHIM_STRUCT(XAPC, apc_ptr);
apc->Initialize(); apc->Initialize();
apc->processor_mode = processor_mode; apc->processor_mode = processor_mode;
apc->thread_ptr = thread; apc->thread_ptr = thread_ptr.guest_address();
apc->kernel_routine = kernel_routine; apc->kernel_routine = kernel_routine.guest_address();
apc->rundown_routine = rundown_routine; apc->rundown_routine = rundown_routine.guest_address();
apc->normal_routine = normal_routine; apc->normal_routine = normal_routine.guest_address();
apc->normal_context = normal_routine ? normal_context : 0; apc->normal_context =
normal_routine.guest_address() ? normal_context.guest_address() : 0;
} }
DECLARE_XBOXKRNL_EXPORT1(KeInitializeApc, kThreading, kImplemented);
SHIM_CALL KeInsertQueueApc_shim(PPCContext* ppc_context, dword_result_t KeInsertQueueApc(pointer_t<XAPC> apc, lpvoid_t arg1,
KernelState* kernel_state) { lpvoid_t arg2, dword_t priority_increment) {
uint32_t apc_ptr = SHIM_GET_ARG_32(0);
uint32_t arg1 = SHIM_GET_ARG_32(1);
uint32_t arg2 = SHIM_GET_ARG_32(2);
uint32_t priority_increment = SHIM_GET_ARG_32(3);
XELOGD("KeInsertQueueApc(%.8X, %.8X, %.8X, %.8X)", apc_ptr, arg1, arg2,
priority_increment);
auto apc = SHIM_STRUCT(XAPC, apc_ptr);
auto thread = XObject::GetNativeObject<XThread>( auto thread = XObject::GetNativeObject<XThread>(
kernel_state, SHIM_MEM_ADDR(apc->thread_ptr)); kernel_state(),
kernel_state()->memory()->TranslateVirtual(apc->thread_ptr));
if (!thread) { if (!thread) {
SHIM_SET_RETURN_32(0); return 0;
return;
} }
// Lock thread. // Lock thread.
@ -1089,53 +964,45 @@ SHIM_CALL KeInsertQueueApc_shim(PPCContext* ppc_context,
// Fail if already inserted. // Fail if already inserted.
if (apc->enqueued) { if (apc->enqueued) {
thread->UnlockApc(false); thread->UnlockApc(false);
SHIM_SET_RETURN_32(0); return 0;
return;
} }
// Prep APC. // Prep APC.
apc->arg1 = arg1; apc->arg1 = arg1.guest_address();
apc->arg2 = arg2; apc->arg2 = arg2.guest_address();
apc->enqueued = 1; apc->enqueued = 1;
auto apc_list = thread->apc_list(); auto apc_list = thread->apc_list();
uint32_t list_entry_ptr = apc_ptr + 8; uint32_t list_entry_ptr = apc.guest_address() + 8;
apc_list->Insert(list_entry_ptr); apc_list->Insert(list_entry_ptr);
// Unlock thread. // Unlock thread.
thread->UnlockApc(true); thread->UnlockApc(true);
SHIM_SET_RETURN_32(1); return 1;
} }
DECLARE_XBOXKRNL_EXPORT1(KeInsertQueueApc, kThreading, kImplemented);
SHIM_CALL KeRemoveQueueApc_shim(PPCContext* ppc_context, dword_result_t KeRemoveQueueApc(pointer_t<XAPC> apc) {
KernelState* kernel_state) {
uint32_t apc_ptr = SHIM_GET_ARG_32(0);
XELOGD("KeRemoveQueueApc(%.8X)", apc_ptr);
bool result = false; bool result = false;
auto apc = SHIM_STRUCT(XAPC, apc_ptr);
auto thread = XObject::GetNativeObject<XThread>( auto thread = XObject::GetNativeObject<XThread>(
kernel_state, SHIM_MEM_ADDR(apc->thread_ptr)); kernel_state(),
kernel_state()->memory()->TranslateVirtual(apc->thread_ptr));
if (!thread) { if (!thread) {
SHIM_SET_RETURN_32(0); return 0;
return;
} }
thread->LockApc(); thread->LockApc();
if (!apc->enqueued) { if (!apc->enqueued) {
thread->UnlockApc(false); thread->UnlockApc(false);
SHIM_SET_RETURN_32(0); return 0;
return;
} }
auto apc_list = thread->apc_list(); auto apc_list = thread->apc_list();
uint32_t list_entry_ptr = apc_ptr + 8; uint32_t list_entry_ptr = apc.guest_address() + 8;
if (apc_list->IsQueued(list_entry_ptr)) { if (apc_list->IsQueued(list_entry_ptr)) {
apc_list->Remove(list_entry_ptr); apc_list->Remove(list_entry_ptr);
result = true; result = true;
@ -1143,90 +1010,81 @@ SHIM_CALL KeRemoveQueueApc_shim(PPCContext* ppc_context,
thread->UnlockApc(true); thread->UnlockApc(true);
SHIM_SET_RETURN_32(result ? 1 : 0); return result ? 1 : 0;
} }
DECLARE_XBOXKRNL_EXPORT1(KeRemoveQueueApc, kThreading, kImplemented);
SHIM_CALL KiApcNormalRoutineNop_shim(PPCContext* ppc_context, dword_result_t KiApcNormalRoutineNop(dword_t unk0 /* output? */,
KernelState* kernel_state) { dword_t unk1 /* 0x13 */) {
uint32_t unk0 = SHIM_GET_ARG_32(0); // output? return 0;
uint32_t unk1 = SHIM_GET_ARG_32(1); // 0x13
XELOGD("KiApcNormalRoutineNop(%.8X, %.8X)", unk0, unk1);
SHIM_SET_RETURN_32(0);
} }
DECLARE_XBOXKRNL_EXPORT1(KiApcNormalRoutineNop, kThreading, kStub);
SHIM_CALL KeInitializeDpc_shim(PPCContext* ppc_context, typedef struct {
KernelState* kernel_state) { xe::be<uint32_t> unknown;
uint32_t dpc_ptr = SHIM_GET_ARG_32(0); xe::be<uint32_t> flink;
uint32_t routine = SHIM_GET_ARG_32(1); xe::be<uint32_t> blink;
uint32_t context = SHIM_GET_ARG_32(2); xe::be<uint32_t> routine;
xe::be<uint32_t> context;
XELOGD("KeInitializeDpc(%.8X, %.8X, %.8X)", dpc_ptr, routine, context); xe::be<uint32_t> arg1;
xe::be<uint32_t> arg2;
} XDPC;
void KeInitializeDpc(pointer_t<XDPC> dpc, lpvoid_t routine, lpvoid_t context) {
// KDPC (maybe) 0x18 bytes? // KDPC (maybe) 0x18 bytes?
uint32_t type = 19; // DpcObject uint32_t type = 19; // DpcObject
uint32_t importance = 0; uint32_t importance = 0;
uint32_t number = 0; // ? uint32_t number = 0; // ?
SHIM_SET_MEM_32(dpc_ptr + 0, (type << 24) | (importance << 16) | (number)); dpc->unknown = (type << 24) | (importance << 16) | (number);
SHIM_SET_MEM_32(dpc_ptr + 4, 0); // flink dpc->flink = 0;
SHIM_SET_MEM_32(dpc_ptr + 8, 0); // blink dpc->blink = 0;
SHIM_SET_MEM_32(dpc_ptr + 12, routine); dpc->routine = routine.guest_address();
SHIM_SET_MEM_32(dpc_ptr + 16, context); dpc->context = context.guest_address();
SHIM_SET_MEM_32(dpc_ptr + 20, 0); // arg1 dpc->arg1 = 0;
SHIM_SET_MEM_32(dpc_ptr + 24, 0); // arg2 dpc->arg2 = 0;
} }
DECLARE_XBOXKRNL_EXPORT2(KeInitializeDpc, kThreading, kImplemented, kSketchy);
SHIM_CALL KeInsertQueueDpc_shim(PPCContext* ppc_context, dword_result_t KeInsertQueueDpc(pointer_t<XDPC> dpc, dword_t arg1,
KernelState* kernel_state) { dword_t arg2) {
uint32_t dpc_ptr = SHIM_GET_ARG_32(0);
uint32_t arg1 = SHIM_GET_ARG_32(1);
uint32_t arg2 = SHIM_GET_ARG_32(2);
assert_always("DPC does not dispatch yet; going to hang!"); assert_always("DPC does not dispatch yet; going to hang!");
XELOGD("KeInsertQueueDpc(%.8X, %.8X, %.8X)", dpc_ptr, arg1, arg2); uint32_t list_entry_ptr = dpc.guest_address() + 4;
uint32_t list_entry_ptr = dpc_ptr + 4;
// Lock dispatcher. // Lock dispatcher.
auto global_lock = xe::global_critical_region::AcquireDirect(); auto global_lock = xe::global_critical_region::AcquireDirect();
auto dpc_list = kernel_state->dpc_list(); auto dpc_list = kernel_state()->dpc_list();
// If already in a queue, abort. // If already in a queue, abort.
if (dpc_list->IsQueued(list_entry_ptr)) { if (dpc_list->IsQueued(list_entry_ptr)) {
SHIM_SET_RETURN_32(0); return 0;
return;
} }
// Prep DPC. // Prep DPC.
SHIM_SET_MEM_32(dpc_ptr + 20, arg1); dpc->arg1 = (uint32_t)arg1;
SHIM_SET_MEM_32(dpc_ptr + 24, arg2); dpc->arg2 = (uint32_t)arg2;
dpc_list->Insert(list_entry_ptr); dpc_list->Insert(list_entry_ptr);
SHIM_SET_RETURN_32(1); return 1;
} }
DECLARE_XBOXKRNL_EXPORT2(KeInsertQueueDpc, kThreading, kStub, kSketchy);
SHIM_CALL KeRemoveQueueDpc_shim(PPCContext* ppc_context, dword_result_t KeRemoveQueueDpc(pointer_t<XDPC> dpc) {
KernelState* kernel_state) {
uint32_t dpc_ptr = SHIM_GET_ARG_32(0);
XELOGD("KeRemoveQueueDpc(%.8X)", dpc_ptr);
bool result = false; bool result = false;
uint32_t list_entry_ptr = dpc_ptr + 4; uint32_t list_entry_ptr = dpc.guest_address() + 4;
auto global_lock = xe::global_critical_region::AcquireDirect(); auto global_lock = xe::global_critical_region::AcquireDirect();
auto dpc_list = kernel_state->dpc_list(); auto dpc_list = kernel_state()->dpc_list();
if (dpc_list->IsQueued(list_entry_ptr)) { if (dpc_list->IsQueued(list_entry_ptr)) {
dpc_list->Remove(list_entry_ptr); dpc_list->Remove(list_entry_ptr);
result = true; result = true;
} }
SHIM_SET_RETURN_32(result ? 1 : 0); return result ? 1 : 0;
} }
DECLARE_XBOXKRNL_EXPORT1(KeRemoveQueueDpc, kThreading, kImplemented);
// https://github.com/Cxbx-Reloaded/Cxbx-Reloaded/blob/51e4dfcaacfdbd1a9692272931a436371492f72d/import/OpenXDK/include/xboxkrnl/xboxkrnl.h#L1372 // https://github.com/Cxbx-Reloaded/Cxbx-Reloaded/blob/51e4dfcaacfdbd1a9692272931a436371492f72d/import/OpenXDK/include/xboxkrnl/xboxkrnl.h#L1372
struct X_ERWLOCK { struct X_ERWLOCK {
@ -1324,47 +1182,6 @@ DECLARE_XBOXKRNL_EXPORT1(InterlockedFlushSList, kThreading, kImplemented);
void RegisterThreadingExports(xe::cpu::ExportResolver* export_resolver, void RegisterThreadingExports(xe::cpu::ExportResolver* export_resolver,
KernelState* kernel_state) { KernelState* kernel_state) {
SHIM_SET_MAPPING("xboxkrnl.exe", ExCreateThread, state);
SHIM_SET_MAPPING("xboxkrnl.exe", ExTerminateThread, state);
SHIM_SET_MAPPING("xboxkrnl.exe", NtResumeThread, state);
SHIM_SET_MAPPING("xboxkrnl.exe", KeResumeThread, state);
SHIM_SET_MAPPING("xboxkrnl.exe", NtSuspendThread, state);
SHIM_SET_MAPPING("xboxkrnl.exe", KeSetAffinityThread, state);
SHIM_SET_MAPPING("xboxkrnl.exe", KeQueryBasePriorityThread, state);
SHIM_SET_MAPPING("xboxkrnl.exe", KeSetBasePriorityThread, state);
SHIM_SET_MAPPING("xboxkrnl.exe", KeSetDisableBoostThread, state);
SHIM_SET_MAPPING("xboxkrnl.exe", KeGetCurrentProcessType, state);
SHIM_SET_MAPPING("xboxkrnl.exe", KeSetCurrentProcessType, state);
SHIM_SET_MAPPING("xboxkrnl.exe", KeQueryPerformanceFrequency, state);
SHIM_SET_MAPPING("xboxkrnl.exe", NtYieldExecution, state);
SHIM_SET_MAPPING("xboxkrnl.exe", KeQuerySystemTime, state);
SHIM_SET_MAPPING("xboxkrnl.exe", NtCreateSemaphore, state);
SHIM_SET_MAPPING("xboxkrnl.exe", NtReleaseSemaphore, state);
SHIM_SET_MAPPING("xboxkrnl.exe", NtReleaseMutant, state);
SHIM_SET_MAPPING("xboxkrnl.exe", NtCreateTimer, state);
SHIM_SET_MAPPING("xboxkrnl.exe", NtSetTimerEx, state);
SHIM_SET_MAPPING("xboxkrnl.exe", NtCancelTimer, state);
SHIM_SET_MAPPING("xboxkrnl.exe", KeEnterCriticalRegion, state);
SHIM_SET_MAPPING("xboxkrnl.exe", KeLeaveCriticalRegion, state);
SHIM_SET_MAPPING("xboxkrnl.exe", KeRaiseIrqlToDpcLevel, state);
SHIM_SET_MAPPING("xboxkrnl.exe", KfLowerIrql, state);
// SHIM_SET_MAPPING("xboxkrnl.exe", NtQueueApcThread, state);
SHIM_SET_MAPPING("xboxkrnl.exe", KeInitializeApc, state);
SHIM_SET_MAPPING("xboxkrnl.exe", KeInsertQueueApc, state);
SHIM_SET_MAPPING("xboxkrnl.exe", KeRemoveQueueApc, state);
SHIM_SET_MAPPING("xboxkrnl.exe", KiApcNormalRoutineNop, state);
SHIM_SET_MAPPING("xboxkrnl.exe", KeInitializeDpc, state);
SHIM_SET_MAPPING("xboxkrnl.exe", KeInsertQueueDpc, state);
SHIM_SET_MAPPING("xboxkrnl.exe", KeRemoveQueueDpc, state);
} }
} // namespace xboxkrnl } // namespace xboxkrnl