Export kBlocking tag

This commit is contained in:
Dr. Chat 2015-11-28 14:24:43 -06:00 committed by Ben Vanik
parent db8eb83057
commit 87cdce1440
2 changed files with 85 additions and 135 deletions

View File

@ -32,6 +32,8 @@ struct ExportTag {
static const type kHighFrequency = 1u << 3; static const type kHighFrequency = 1u << 3;
// Export is important and should always be logged. // Export is important and should always be logged.
static const type kImportant = 1u << 4; static const type kImportant = 1u << 4;
// Export blocks the calling thread
static const type kBlocking = 1u << 5;
static const type kThreading = 1u << 10; static const type kThreading = 1u << 10;
static const type kInput = 1u << 11; static const type kInput = 1u << 11;

View File

@ -345,22 +345,16 @@ SHIM_CALL KeQueryPerformanceFrequency_shim(PPCContext* ppc_context,
SHIM_SET_RETURN_32(result); SHIM_SET_RETURN_32(result);
} }
SHIM_CALL KeDelayExecutionThread_shim(PPCContext* ppc_context, dword_result_t KeDelayExecutionThread(dword_t processor_mode, dword_t alertable,
KernelState* kernel_state) { lpqword_t interval_ptr) {
uint32_t processor_mode = SHIM_GET_ARG_32(0);
uint32_t alertable = SHIM_GET_ARG_32(1);
uint32_t interval_ptr = SHIM_GET_ARG_32(2);
uint64_t interval = SHIM_MEM_64(interval_ptr);
// XELOGD(
// "KeDelayExecutionThread(%.8X, %d, %.8X(%.16llX)",
// processor_mode, alertable, interval_ptr, interval);
XThread* thread = XThread::GetCurrentThread(); XThread* thread = XThread::GetCurrentThread();
X_STATUS result = thread->Delay(processor_mode, alertable, interval); X_STATUS result = thread->Delay(processor_mode, alertable, *interval_ptr);
SHIM_SET_RETURN_32(result); return result;
} }
DECLARE_XBOXKRNL_EXPORT(KeDelayExecutionThread,
ExportTag::kImplemented | ExportTag::kThreading |
ExportTag::kHighFrequency | ExportTag::kBlocking);
SHIM_CALL NtYieldExecution_shim(PPCContext* ppc_context, SHIM_CALL NtYieldExecution_shim(PPCContext* ppc_context,
KernelState* kernel_state) { KernelState* kernel_state) {
@ -853,104 +847,87 @@ SHIM_CALL NtCancelTimer_shim(PPCContext* ppc_context,
SHIM_SET_RETURN_32(result); SHIM_SET_RETURN_32(result);
} }
SHIM_CALL KeWaitForSingleObject_shim(PPCContext* ppc_context, dword_result_t KeWaitForSingleObject(lpvoid_t object_ptr, dword_t wait_reason,
KernelState* kernel_state) { dword_t processor_mode, dword_t alertable,
uint32_t object_ptr = SHIM_GET_ARG_32(0); lpqword_t timeout_ptr) {
uint32_t wait_reason = SHIM_GET_ARG_32(1); auto object = XObject::GetNativeObject<XObject>(kernel_state(), object_ptr);
uint32_t processor_mode = SHIM_GET_ARG_32(2);
uint32_t alertable = SHIM_GET_ARG_32(3);
uint32_t timeout_ptr = SHIM_GET_ARG_32(4);
XELOGD("KeWaitForSingleObject(%.8X, %.8X, %.8X, %.1X, %.8X)", object_ptr,
wait_reason, processor_mode, alertable, timeout_ptr);
auto object = XObject::GetNativeObject<XObject>(kernel_state,
SHIM_MEM_ADDR(object_ptr));
if (!object) { if (!object) {
// The only kind-of failure code. // The only kind-of failure code (though this should never happen)
SHIM_SET_RETURN_32(X_STATUS_ABANDONED_WAIT_0); assert_always();
return; return X_STATUS_ABANDONED_WAIT_0;
} }
uint64_t timeout = timeout_ptr ? SHIM_MEM_64(timeout_ptr) : 0; uint64_t timeout = timeout_ptr ? *timeout_ptr : 0;
X_STATUS result = object->Wait(wait_reason, processor_mode, alertable, X_STATUS result = object->Wait(wait_reason, processor_mode, alertable,
timeout_ptr ? &timeout : nullptr); timeout_ptr ? &timeout : nullptr);
SHIM_SET_RETURN_32(result); return result;
} }
DECLARE_XBOXKRNL_EXPORT(KeWaitForSingleObject, ExportTag::kImplemented |
ExportTag::kThreading |
ExportTag::kBlocking);
SHIM_CALL NtWaitForSingleObjectEx_shim(PPCContext* ppc_context, dword_result_t NtWaitForSingleObjectEx(dword_t object_handle, dword_t wait_mode,
KernelState* kernel_state) { dword_t alertable,
uint32_t object_handle = SHIM_GET_ARG_32(0); lpqword_t timeout_ptr) {
uint8_t wait_mode = SHIM_GET_ARG_8(1);
uint32_t alertable = SHIM_GET_ARG_32(2);
uint32_t timeout_ptr = SHIM_GET_ARG_32(3);
XELOGD("NtWaitForSingleObjectEx(%.8X, %u, %.1X, %.8X)", object_handle,
(uint32_t)wait_mode, alertable, timeout_ptr);
X_STATUS result = X_STATUS_SUCCESS; X_STATUS result = X_STATUS_SUCCESS;
auto object = auto object =
kernel_state->object_table()->LookupObject<XObject>(object_handle); kernel_state()->object_table()->LookupObject<XObject>(object_handle);
if (object) { if (object) {
uint64_t timeout = timeout_ptr ? SHIM_MEM_64(timeout_ptr) : 0; uint64_t timeout = timeout_ptr ? *timeout_ptr : 0;
result = result =
object->Wait(3, wait_mode, alertable, timeout_ptr ? &timeout : nullptr); object->Wait(3, wait_mode, alertable, timeout_ptr ? &timeout : nullptr);
} else { } else {
result = X_STATUS_INVALID_HANDLE; result = X_STATUS_INVALID_HANDLE;
} }
SHIM_SET_RETURN_32(result); return result;
} }
DECLARE_XBOXKRNL_EXPORT(NtWaitForSingleObjectEx, ExportTag::kImplemented |
ExportTag::kThreading |
ExportTag::kBlocking);
SHIM_CALL KeWaitForMultipleObjects_shim(PPCContext* ppc_context, dword_result_t KeWaitForMultipleObjects(dword_t count, lpdword_t objects_ptr,
KernelState* kernel_state) { dword_t wait_type, dword_t wait_reason,
uint32_t count = SHIM_GET_ARG_32(0); dword_t processor_mode,
uint32_t objects_ptr = SHIM_GET_ARG_32(1); dword_t alertable,
uint32_t wait_type = SHIM_GET_ARG_32(2); lpqword_t timeout_ptr,
uint32_t wait_reason = SHIM_GET_ARG_32(3); lpvoid_t wait_block_array_ptr) {
uint32_t processor_mode = SHIM_GET_ARG_32(4);
uint32_t alertable = SHIM_GET_ARG_32(5);
uint32_t timeout_ptr = SHIM_GET_ARG_32(6);
uint32_t wait_block_array_ptr = SHIM_GET_ARG_32(7);
XELOGD(
"KeWaitForMultipleObjects(%d, %.8X, %.8X, %.8X, %.8X, %.1X, %.8X, %.8X)",
count, objects_ptr, wait_type, wait_reason, processor_mode, alertable,
timeout_ptr, wait_block_array_ptr);
assert_true(wait_type <= 1); assert_true(wait_type <= 1);
X_STATUS result = X_STATUS_SUCCESS; X_STATUS result = X_STATUS_SUCCESS;
std::vector<object_ref<XObject>> objects; std::vector<object_ref<XObject>> objects;
for (uint32_t n = 0; n < count; n++) { for (uint32_t n = 0; n < count; n++) {
uint32_t object_ptr_ptr = SHIM_MEM_32(objects_ptr + n * 4); auto object_ptr = kernel_memory()->TranslateVirtual(objects_ptr[n]);
void* object_ptr = SHIM_MEM_ADDR(object_ptr_ptr);
auto object_ref = auto object_ref =
XObject::GetNativeObject<XObject>(kernel_state, object_ptr); XObject::GetNativeObject<XObject>(kernel_state(), object_ptr);
if (!object_ref) { if (!object_ref) {
SHIM_SET_RETURN_32(X_STATUS_INVALID_PARAMETER); return X_STATUS_INVALID_PARAMETER;
return;
} }
objects.push_back(std::move(object_ref)); objects.push_back(std::move(object_ref));
} }
uint64_t timeout = timeout_ptr ? SHIM_MEM_64(timeout_ptr) : 0; uint64_t timeout = timeout_ptr ? *timeout_ptr : 0;
result = XObject::WaitMultiple(uint32_t(objects.size()), result = XObject::WaitMultiple(uint32_t(objects.size()),
reinterpret_cast<XObject**>(objects.data()), reinterpret_cast<XObject**>(objects.data()),
wait_type, wait_reason, processor_mode, wait_type, wait_reason, processor_mode,
alertable, timeout_ptr ? &timeout : nullptr); alertable, timeout_ptr ? &timeout : nullptr);
SHIM_SET_RETURN_32(result); return result;
} }
DECLARE_XBOXKRNL_EXPORT(KeWaitForMultipleObjects, ExportTag::kImplemented |
ExportTag::kThreading |
ExportTag::kBlocking);
dword_result_t NtWaitForMultipleObjectsEx( dword_result_t NtWaitForMultipleObjectsEx(dword_t count,
dword_t count, pointer_t<xe::be<uint32_t>> handles, dword_t wait_type, pointer_t<xe::be<uint32_t>> handles,
dword_t wait_mode, dword_t alertable, dword_t wait_type, dword_t wait_mode,
pointer_t<xe::be<uint64_t>> timeout_ptr) { dword_t alertable,
lpqword_t timeout_ptr) {
assert_true(wait_type <= 1); assert_true(wait_type <= 1);
X_STATUS result = X_STATUS_SUCCESS; X_STATUS result = X_STATUS_SUCCESS;
@ -972,28 +949,22 @@ dword_result_t NtWaitForMultipleObjectsEx(
return result; return result;
} }
DECLARE_XBOXKRNL_EXPORT(NtWaitForMultipleObjectsEx, DECLARE_XBOXKRNL_EXPORT(NtWaitForMultipleObjectsEx, ExportTag::kImplemented |
ExportTag::kImplemented | ExportTag::kThreading); ExportTag::kThreading |
ExportTag::kBlocking);
SHIM_CALL NtSignalAndWaitForSingleObjectEx_shim(PPCContext* ppc_context,
KernelState* kernel_state) {
uint32_t signal_handle = SHIM_GET_ARG_32(0);
uint32_t wait_handle = SHIM_GET_ARG_32(1);
uint32_t alertable = SHIM_GET_ARG_32(2);
uint32_t unk_3 = SHIM_GET_ARG_32(3);
uint32_t timeout_ptr = SHIM_GET_ARG_32(4);
XELOGD("NtSignalAndWaitForSingleObjectEx(%.8X, %.8X, %.1X, %.8X, %.8X)",
signal_handle, wait_handle, alertable, unk_3, timeout_ptr);
dword_result_t NtSignalAndWaitForSingleObjectEx(dword_t signal_handle,
dword_t wait_handle,
dword_t alertable, dword_t r6,
lpqword_t timeout_ptr) {
X_STATUS result = X_STATUS_SUCCESS; X_STATUS result = X_STATUS_SUCCESS;
auto signal_object = auto signal_object =
kernel_state->object_table()->LookupObject<XObject>(signal_handle); kernel_state()->object_table()->LookupObject<XObject>(signal_handle);
auto wait_object = auto wait_object =
kernel_state->object_table()->LookupObject<XObject>(wait_handle); kernel_state()->object_table()->LookupObject<XObject>(wait_handle);
if (signal_object && wait_object) { if (signal_object && wait_object) {
uint64_t timeout = timeout_ptr ? SHIM_MEM_64(timeout_ptr) : 0; uint64_t timeout = timeout_ptr ? *timeout_ptr : 0;
result = result =
XObject::SignalAndWait(signal_object.get(), wait_object.get(), 3, 1, XObject::SignalAndWait(signal_object.get(), wait_object.get(), 3, 1,
alertable, timeout_ptr ? &timeout : nullptr); alertable, timeout_ptr ? &timeout : nullptr);
@ -1001,19 +972,19 @@ SHIM_CALL NtSignalAndWaitForSingleObjectEx_shim(PPCContext* ppc_context,
result = X_STATUS_INVALID_HANDLE; result = X_STATUS_INVALID_HANDLE;
} }
SHIM_SET_RETURN_32(result); return result;
} }
DECLARE_XBOXKRNL_EXPORT(NtSignalAndWaitForSingleObjectEx,
ExportTag::kImplemented | ExportTag::kThreading |
ExportTag::kBlocking);
SHIM_CALL KfAcquireSpinLock_shim(PPCContext* ppc_context, dword_result_t KfAcquireSpinLock(lpdword_t lock_ptr) {
KernelState* kernel_state) {
uint32_t lock_ptr = SHIM_GET_ARG_32(0);
// XELOGD( // XELOGD(
// "KfAcquireSpinLock(%.8X)", // "KfAcquireSpinLock(%.8X)",
// lock_ptr); // lock_ptr);
// Lock. // Lock.
auto lock = reinterpret_cast<uint32_t*>(SHIM_MEM_ADDR(lock_ptr)); auto lock = reinterpret_cast<uint32_t*>(lock_ptr.host_address());
while (!xe::atomic_cas(0, 1, lock)) { while (!xe::atomic_cas(0, 1, lock)) {
// Spin! // Spin!
// TODO(benvanik): error on deadlock? // TODO(benvanik): error on deadlock?
@ -1024,56 +995,45 @@ SHIM_CALL KfAcquireSpinLock_shim(PPCContext* ppc_context,
XThread* thread = XThread::GetCurrentThread(); XThread* thread = XThread::GetCurrentThread();
auto old_irql = thread->RaiseIrql(2); auto old_irql = thread->RaiseIrql(2);
SHIM_SET_RETURN_32(old_irql); return old_irql;
} }
DECLARE_XBOXKRNL_EXPORT(KfAcquireSpinLock,
ExportTag::kImplemented | ExportTag::kThreading |
ExportTag::kHighFrequency | ExportTag::kBlocking);
SHIM_CALL KfReleaseSpinLock_shim(PPCContext* ppc_context, void KfReleaseSpinLock(lpdword_t lock_ptr, dword_t old_irql) {
KernelState* kernel_state) {
uint32_t lock_ptr = SHIM_GET_ARG_32(0);
uint32_t old_irql = SHIM_GET_ARG_32(1);
// XELOGD(
// "KfReleaseSpinLock(%.8X, %d)",
// lock_ptr,
// old_irql);
// Restore IRQL. // Restore IRQL.
XThread* thread = XThread::GetCurrentThread(); XThread* thread = XThread::GetCurrentThread();
thread->LowerIrql(old_irql); thread->LowerIrql(old_irql);
// Unlock. // Unlock.
auto lock = reinterpret_cast<uint32_t*>(SHIM_MEM_ADDR(lock_ptr)); auto lock = reinterpret_cast<uint32_t*>(lock_ptr.host_address());
xe::atomic_dec(lock); xe::atomic_dec(lock);
} }
DECLARE_XBOXKRNL_EXPORT(KfReleaseSpinLock, ExportTag::kImplemented |
ExportTag::kThreading |
ExportTag::kHighFrequency);
SHIM_CALL KeAcquireSpinLockAtRaisedIrql_shim(PPCContext* ppc_context, void KeAcquireSpinLockAtRaisedIrql(lpdword_t lock_ptr) {
KernelState* kernel_state) {
uint32_t lock_ptr = SHIM_GET_ARG_32(0);
// XELOGD(
// "KeAcquireSpinLockAtRaisedIrql(%.8X)",
// lock_ptr);
// Lock. // Lock.
auto lock = reinterpret_cast<uint32_t*>(SHIM_MEM_ADDR(lock_ptr)); auto lock = reinterpret_cast<uint32_t*>(lock_ptr.host_address());
while (!xe::atomic_cas(0, 1, lock)) { while (!xe::atomic_cas(0, 1, lock)) {
// Spin! // Spin!
// TODO(benvanik): error on deadlock? // TODO(benvanik): error on deadlock?
} }
} }
DECLARE_XBOXKRNL_EXPORT(KeAcquireSpinLockAtRaisedIrql,
ExportTag::kImplemented | ExportTag::kThreading |
ExportTag::kHighFrequency | ExportTag::kBlocking);
SHIM_CALL KeReleaseSpinLockFromRaisedIrql_shim(PPCContext* ppc_context, void KeReleaseSpinLockFromRaisedIrql(lpdword_t lock_ptr) {
KernelState* kernel_state) {
uint32_t lock_ptr = SHIM_GET_ARG_32(0);
// XELOGD(
// "KeReleaseSpinLockFromRaisedIrql(%.8X)",
// lock_ptr);
// Unlock. // Unlock.
auto lock = reinterpret_cast<uint32_t*>(SHIM_MEM_ADDR(lock_ptr)); auto lock = reinterpret_cast<uint32_t*>(lock_ptr.host_address());
xe::atomic_dec(lock); xe::atomic_dec(lock);
} }
DECLARE_XBOXKRNL_EXPORT(KeReleaseSpinLockFromRaisedIrql,
ExportTag::kImplemented | ExportTag::kThreading |
ExportTag::kHighFrequency);
SHIM_CALL KeEnterCriticalRegion_shim(PPCContext* ppc_context, SHIM_CALL KeEnterCriticalRegion_shim(PPCContext* ppc_context,
KernelState* kernel_state) { KernelState* kernel_state) {
@ -1409,7 +1369,6 @@ void RegisterThreadingExports(xe::cpu::ExportResolver* export_resolver,
SHIM_SET_MAPPING("xboxkrnl.exe", KeSetCurrentProcessType, state); SHIM_SET_MAPPING("xboxkrnl.exe", KeSetCurrentProcessType, state);
SHIM_SET_MAPPING("xboxkrnl.exe", KeQueryPerformanceFrequency, state); SHIM_SET_MAPPING("xboxkrnl.exe", KeQueryPerformanceFrequency, state);
SHIM_SET_MAPPING("xboxkrnl.exe", KeDelayExecutionThread, state);
SHIM_SET_MAPPING("xboxkrnl.exe", NtYieldExecution, state); SHIM_SET_MAPPING("xboxkrnl.exe", NtYieldExecution, state);
SHIM_SET_MAPPING("xboxkrnl.exe", KeQuerySystemTime, state); SHIM_SET_MAPPING("xboxkrnl.exe", KeQuerySystemTime, state);
@ -1427,17 +1386,6 @@ void RegisterThreadingExports(xe::cpu::ExportResolver* export_resolver,
SHIM_SET_MAPPING("xboxkrnl.exe", NtSetTimerEx, state); SHIM_SET_MAPPING("xboxkrnl.exe", NtSetTimerEx, state);
SHIM_SET_MAPPING("xboxkrnl.exe", NtCancelTimer, state); SHIM_SET_MAPPING("xboxkrnl.exe", NtCancelTimer, state);
SHIM_SET_MAPPING("xboxkrnl.exe", KeWaitForSingleObject, state);
SHIM_SET_MAPPING("xboxkrnl.exe", NtWaitForSingleObjectEx, state);
SHIM_SET_MAPPING("xboxkrnl.exe", KeWaitForMultipleObjects, state);
SHIM_SET_MAPPING("xboxkrnl.exe", NtSignalAndWaitForSingleObjectEx, state);
SHIM_SET_MAPPING("xboxkrnl.exe", KfAcquireSpinLock, state);
SHIM_SET_MAPPING("xboxkrnl.exe", KfReleaseSpinLock, state);
SHIM_SET_MAPPING("xboxkrnl.exe", KeAcquireSpinLockAtRaisedIrql, state);
SHIM_SET_MAPPING("xboxkrnl.exe", KeReleaseSpinLockFromRaisedIrql, state);
SHIM_SET_MAPPING("xboxkrnl.exe", KeEnterCriticalRegion, state); SHIM_SET_MAPPING("xboxkrnl.exe", KeEnterCriticalRegion, state);
SHIM_SET_MAPPING("xboxkrnl.exe", KeLeaveCriticalRegion, state); SHIM_SET_MAPPING("xboxkrnl.exe", KeLeaveCriticalRegion, state);