diff --git a/src/xenia/cpu/processor.cc b/src/xenia/cpu/processor.cc index c5cea7411..21512acbb 100644 --- a/src/xenia/cpu/processor.cc +++ b/src/xenia/cpu/processor.cc @@ -135,6 +135,17 @@ uint64_t Processor::Execute( return context->r[3]; } +Irql Processor::RaiseIrql(Irql new_value) { + return static_cast( + poly::atomic_exchange(static_cast(new_value), + reinterpret_cast(&irql_))); +} + +void Processor::LowerIrql(Irql old_value) { + poly::atomic_exchange(static_cast(old_value), + reinterpret_cast(&irql_)); +} + uint64_t Processor::ExecuteInterrupt( uint32_t cpu, uint64_t address, uint64_t args[], size_t arg_count) { SCOPE_profile_cpu_f("cpu"); diff --git a/src/xenia/cpu/processor.h b/src/xenia/cpu/processor.h index f13587ef5..d5e79b0f8 100644 --- a/src/xenia/cpu/processor.h +++ b/src/xenia/cpu/processor.h @@ -27,6 +27,14 @@ namespace xe { namespace cpu { +enum class Irql : uint32_t { + PASSIVE = 0, + APC = 1, + DISPATCH = 2, + DPC = 3, +}; + + class Processor { public: Processor(Emulator* emulator); @@ -44,6 +52,9 @@ public: XenonThreadState* thread_state, uint64_t address, uint64_t args[], size_t arg_count); + Irql RaiseIrql(Irql new_value); + void LowerIrql(Irql old_value); + uint64_t ExecuteInterrupt( uint32_t cpu, uint64_t address, uint64_t args[], size_t arg_count); @@ -54,6 +65,7 @@ private: XenonRuntime* runtime_; Memory* memory_; + Irql irql_; xe_mutex_t* interrupt_thread_lock_; XenonThreadState* interrupt_thread_state_; uint64_t interrupt_thread_block_; diff --git a/src/xenia/kernel/xboxkrnl_threading.cc b/src/xenia/kernel/xboxkrnl_threading.cc index 17991b47a..0078dbfc7 100644 --- a/src/xenia/kernel/xboxkrnl_threading.cc +++ b/src/xenia/kernel/xboxkrnl_threading.cc @@ -9,6 +9,7 @@ #include +#include #include #include #include @@ -1275,9 +1276,9 @@ SHIM_CALL KfAcquireSpinLock_shim( PPCContext* ppc_state, KernelState* state) { uint32_t lock_ptr = SHIM_GET_ARG_32(0); - XELOGD( - "KfAcquireSpinLock(%.8X)", - lock_ptr); + // XELOGD( + // "KfAcquireSpinLock(%.8X)", + // lock_ptr); auto lock = reinterpret_cast(SHIM_MEM_ADDR(lock_ptr)); uint32_t old_irql = xeKfAcquireSpinLock(lock); @@ -1301,10 +1302,10 @@ SHIM_CALL KfReleaseSpinLock_shim( 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); + // XELOGD( + // "KfReleaseSpinLock(%.8X, %d)", + // lock_ptr, + // old_irql); xeKfReleaseSpinLock(reinterpret_cast(SHIM_MEM_ADDR(lock_ptr)), old_irql); @@ -1315,9 +1316,9 @@ SHIM_CALL KeAcquireSpinLockAtRaisedIrql_shim( PPCContext* ppc_state, KernelState* state) { uint32_t lock_ptr = SHIM_GET_ARG_32(0); - XELOGD( - "KeAcquireSpinLockAtRaisedIrql(%.8X)", - lock_ptr); + // XELOGD( + // "KeAcquireSpinLockAtRaisedIrql(%.8X)", + // lock_ptr); // Lock. auto lock = reinterpret_cast(SHIM_MEM_ADDR(lock_ptr)); @@ -1332,9 +1333,9 @@ SHIM_CALL KeReleaseSpinLockFromRaisedIrql_shim( PPCContext* ppc_state, KernelState* state) { uint32_t lock_ptr = SHIM_GET_ARG_32(0); - XELOGD( - "KeReleaseSpinLockFromRaisedIrql(%.8X)", - lock_ptr); + // XELOGD( + // "KeReleaseSpinLockFromRaisedIrql(%.8X)", + // lock_ptr); // Unlock. auto lock = reinterpret_cast(SHIM_MEM_ADDR(lock_ptr)); @@ -1349,8 +1350,8 @@ void xeKeEnterCriticalRegion() { SHIM_CALL KeEnterCriticalRegion_shim( PPCContext* ppc_state, KernelState* state) { - XELOGD( - "KeEnterCriticalRegion()"); + // XELOGD( + // "KeEnterCriticalRegion()"); xeKeEnterCriticalRegion(); } @@ -1362,12 +1363,31 @@ void xeKeLeaveCriticalRegion() { SHIM_CALL KeLeaveCriticalRegion_shim( PPCContext* ppc_state, KernelState* state) { - XELOGD( - "KeLeaveCriticalRegion()"); + // XELOGD( + // "KeLeaveCriticalRegion()"); xeKeLeaveCriticalRegion(); } +SHIM_CALL KeRaiseIrqlToDpcLevel_shim( + PPCContext* ppc_state, KernelState* state) { + // XELOGD( + // "KeRaiseIrqlToDpcLevel()"); + auto old_value = state->processor()->RaiseIrql(cpu::Irql::DPC); + SHIM_SET_RETURN_32(old_value); +} + + +SHIM_CALL KfLowerIrql_shim( + PPCContext* ppc_state, KernelState* state) { + uint32_t old_value = SHIM_GET_ARG_32(0); + // XELOGD( + // "KfLowerIrql(%d)", + // old_value); + state->processor()->LowerIrql(static_cast(old_value)); +} + + SHIM_CALL NtQueueApcThread_shim( PPCContext* ppc_state, KernelState* state) { uint32_t thread_handle = SHIM_GET_ARG_32(0); @@ -1673,6 +1693,9 @@ void xe::kernel::xboxkrnl::RegisterThreadingExports( 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);