Kernel/Arbiters: Add stubs for 4.x SignalToAddress/WaitForAddres SVCs.
This commit is contained in:
		
							
								
								
									
										46
									
								
								src/core/hle/kernel/address_arbiter.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								src/core/hle/kernel/address_arbiter.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,46 @@ | |||||||
|  | // Copyright 2018 yuzu emulator team | ||||||
|  | // Licensed under GPLv2 or any later version | ||||||
|  | // Refer to the license.txt file included. | ||||||
|  |  | ||||||
|  | #include "common/assert.h" | ||||||
|  | #include "common/common_funcs.h" | ||||||
|  | #include "common/common_types.h" | ||||||
|  | #include "core/hle/kernel/kernel.h" | ||||||
|  | #include "core/hle/kernel/process.h" | ||||||
|  | #include "core/hle/kernel/thread.h" | ||||||
|  | #include "core/memory.h" | ||||||
|  |  | ||||||
|  | namespace Kernel { | ||||||
|  |     namespace AddressArbiter { | ||||||
|  |  | ||||||
|  |         // Signals an address being waited on. | ||||||
|  |         ResultCode SignalToAddress(VAddr address, s32 value, s32 num_to_wake) { | ||||||
|  |             // TODO | ||||||
|  |             return RESULT_SUCCESS; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         // Signals an address being waited on and increments its value if equal to the value argument. | ||||||
|  |         ResultCode IncrementAndSignalToAddressIfEqual(VAddr address, s32 value, s32 num_to_wake) { | ||||||
|  |             // TODO | ||||||
|  |             return RESULT_SUCCESS; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         // Signals an address being waited on and modifies its value based on waiting thread count if equal to the value argument. | ||||||
|  |         ResultCode ModifyByWaitingCountAndSignalToAddressIfEqual(VAddr address, s32 value, s32 num_to_wake) { | ||||||
|  |             // TODO | ||||||
|  |             return RESULT_SUCCESS; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         // Waits on an address if the value passed is less than the argument value, optionally decrementing. | ||||||
|  |         ResultCode WaitForAddressIfLessThan(VAddr address, s32 value, s64 timeout, bool should_decrement) { | ||||||
|  |             // TODO | ||||||
|  |             return RESULT_SUCCESS; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         // Waits on an address if the value passed is equal to the argument value. | ||||||
|  |         ResultCode WaitForAddressIfEqual(VAddr address, s32 value, s64 timeout) { | ||||||
|  |             // TODO | ||||||
|  |             return RESULT_SUCCESS; | ||||||
|  |         } | ||||||
|  |     } // namespace AddressArbiter | ||||||
|  | } // namespace Kernel | ||||||
							
								
								
									
										32
									
								
								src/core/hle/kernel/address_arbiter.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								src/core/hle/kernel/address_arbiter.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,32 @@ | |||||||
|  | // Copyright 2018 yuzu emulator team | ||||||
|  | // Licensed under GPLv2 or any later version | ||||||
|  | // Refer to the license.txt file included. | ||||||
|  |  | ||||||
|  | #pragma once | ||||||
|  |  | ||||||
|  | #include "core/hle/result.h" | ||||||
|  |  | ||||||
|  | namespace Kernel { | ||||||
|  |  | ||||||
|  |     namespace AddressArbiter { | ||||||
|  |         enum class ArbitrationType { | ||||||
|  |             WaitIfLessThan = 0, | ||||||
|  |             DecrementAndWaitIfLessThan = 1, | ||||||
|  |             WaitIfEqual = 2, | ||||||
|  |         }; | ||||||
|  |  | ||||||
|  |         enum class SignalType { | ||||||
|  |             Signal = 0, | ||||||
|  |             IncrementAndSignalIfEqual = 1, | ||||||
|  |             ModifyByWaitingCountAndSignalIfEqual = 2, | ||||||
|  |         }; | ||||||
|  |  | ||||||
|  |         ResultCode SignalToAddress(VAddr address, s32 value, s32 num_to_wake); | ||||||
|  |         ResultCode IncrementAndSignalToAddressIfEqual(VAddr address, s32 value, s32 num_to_wake); | ||||||
|  |         ResultCode ModifyByWaitingCountAndSignalToAddressIfEqual(VAddr address, s32 value, s32 num_to_wake); | ||||||
|  |  | ||||||
|  |         ResultCode WaitForAddressIfLessThan(VAddr address, s32 value, s64 timeout, bool should_decrement); | ||||||
|  |         ResultCode WaitForAddressIfEqual(VAddr address, s32 value, s64 timeout); | ||||||
|  |     } // namespace AddressArbiter | ||||||
|  |  | ||||||
|  | } // namespace Kernel | ||||||
| @@ -20,13 +20,15 @@ enum { | |||||||
|     MaxConnectionsReached = 52, |     MaxConnectionsReached = 52, | ||||||
|  |  | ||||||
|     // Confirmed Switch OS error codes |     // Confirmed Switch OS error codes | ||||||
|     MisalignedAddress = 102, |     InvalidAddress = 102, | ||||||
|  |     InvalidMemoryState = 106, | ||||||
|     InvalidProcessorId = 113, |     InvalidProcessorId = 113, | ||||||
|     InvalidHandle = 114, |     InvalidHandle = 114, | ||||||
|     InvalidCombination = 116, |     InvalidCombination = 116, | ||||||
|     Timeout = 117, |     Timeout = 117, | ||||||
|     SynchronizationCanceled = 118, |     SynchronizationCanceled = 118, | ||||||
|     TooLarge = 119, |     TooLarge = 119, | ||||||
|  |     InvalidEnumValue = 120, | ||||||
| }; | }; | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -39,13 +41,13 @@ constexpr ResultCode ERR_SESSION_CLOSED_BY_REMOTE(-1); | |||||||
| constexpr ResultCode ERR_PORT_NAME_TOO_LONG(-1); | constexpr ResultCode ERR_PORT_NAME_TOO_LONG(-1); | ||||||
| constexpr ResultCode ERR_WRONG_PERMISSION(-1); | constexpr ResultCode ERR_WRONG_PERMISSION(-1); | ||||||
| constexpr ResultCode ERR_MAX_CONNECTIONS_REACHED(-1); | constexpr ResultCode ERR_MAX_CONNECTIONS_REACHED(-1); | ||||||
| constexpr ResultCode ERR_INVALID_ENUM_VALUE(-1); | constexpr ResultCode ERR_INVALID_ENUM_VALUE(ErrorModule::Kernel, ErrCodes::InvalidEnumValue); | ||||||
| constexpr ResultCode ERR_INVALID_ENUM_VALUE_FND(-1); | constexpr ResultCode ERR_INVALID_ENUM_VALUE_FND(-1); | ||||||
| constexpr ResultCode ERR_INVALID_COMBINATION(-1); | constexpr ResultCode ERR_INVALID_COMBINATION(-1); | ||||||
| constexpr ResultCode ERR_INVALID_COMBINATION_KERNEL(-1); | constexpr ResultCode ERR_INVALID_COMBINATION_KERNEL(-1); | ||||||
| constexpr ResultCode ERR_OUT_OF_MEMORY(-1); | constexpr ResultCode ERR_OUT_OF_MEMORY(-1); | ||||||
| constexpr ResultCode ERR_INVALID_ADDRESS(-1); | constexpr ResultCode ERR_INVALID_ADDRESS(ErrorModule::Kernel, ErrCodes::InvalidAddress); | ||||||
| constexpr ResultCode ERR_INVALID_ADDRESS_STATE(-1); | constexpr ResultCode ERR_INVALID_ADDRESS_STATE(ErrorModule::Kernel, ErrCodes::InvalidMemoryState); | ||||||
| constexpr ResultCode ERR_INVALID_HANDLE(ErrorModule::Kernel, ErrCodes::InvalidHandle); | constexpr ResultCode ERR_INVALID_HANDLE(ErrorModule::Kernel, ErrCodes::InvalidHandle); | ||||||
| constexpr ResultCode ERR_INVALID_POINTER(-1); | constexpr ResultCode ERR_INVALID_POINTER(-1); | ||||||
| constexpr ResultCode ERR_INVALID_OBJECT_ADDR(-1); | constexpr ResultCode ERR_INVALID_OBJECT_ADDR(-1); | ||||||
|   | |||||||
| @@ -59,7 +59,7 @@ ResultCode Mutex::TryAcquire(VAddr address, Handle holding_thread_handle, | |||||||
|                              Handle requesting_thread_handle) { |                              Handle requesting_thread_handle) { | ||||||
|     // The mutex address must be 4-byte aligned |     // The mutex address must be 4-byte aligned | ||||||
|     if ((address % sizeof(u32)) != 0) { |     if ((address % sizeof(u32)) != 0) { | ||||||
|         return ResultCode(ErrorModule::Kernel, ErrCodes::MisalignedAddress); |         return ResultCode(ErrorModule::Kernel, ErrCodes::InvalidAddress); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     SharedPtr<Thread> holding_thread = g_handle_table.Get<Thread>(holding_thread_handle); |     SharedPtr<Thread> holding_thread = g_handle_table.Get<Thread>(holding_thread_handle); | ||||||
| @@ -97,7 +97,7 @@ ResultCode Mutex::TryAcquire(VAddr address, Handle holding_thread_handle, | |||||||
| ResultCode Mutex::Release(VAddr address) { | ResultCode Mutex::Release(VAddr address) { | ||||||
|     // The mutex address must be 4-byte aligned |     // The mutex address must be 4-byte aligned | ||||||
|     if ((address % sizeof(u32)) != 0) { |     if ((address % sizeof(u32)) != 0) { | ||||||
|         return ResultCode(ErrorModule::Kernel, ErrCodes::MisalignedAddress); |         return ResultCode(ErrorModule::Kernel, ErrCodes::InvalidAddress); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     auto [thread, num_waiters] = GetHighestPriorityMutexWaitingThread(GetCurrentThread(), address); |     auto [thread, num_waiters] = GetHighestPriorityMutexWaitingThread(GetCurrentThread(), address); | ||||||
|   | |||||||
| @@ -11,6 +11,7 @@ | |||||||
| #include "common/string_util.h" | #include "common/string_util.h" | ||||||
| #include "core/core.h" | #include "core/core.h" | ||||||
| #include "core/core_timing.h" | #include "core/core_timing.h" | ||||||
|  | #include "core/hle/kernel/address_arbiter.h" | ||||||
| #include "core/hle/kernel/client_port.h" | #include "core/hle/kernel/client_port.h" | ||||||
| #include "core/hle/kernel/client_session.h" | #include "core/hle/kernel/client_session.h" | ||||||
| #include "core/hle/kernel/event.h" | #include "core/hle/kernel/event.h" | ||||||
| @@ -580,7 +581,7 @@ static void SleepThread(s64 nanoseconds) { | |||||||
|     Core::System::GetInstance().PrepareReschedule(); |     Core::System::GetInstance().PrepareReschedule(); | ||||||
| } | } | ||||||
|  |  | ||||||
| /// Signal process wide key atomic | /// Wait process wide key atomic | ||||||
| static ResultCode WaitProcessWideKeyAtomic(VAddr mutex_addr, VAddr condition_variable_addr, | static ResultCode WaitProcessWideKeyAtomic(VAddr mutex_addr, VAddr condition_variable_addr, | ||||||
|                                            Handle thread_handle, s64 nano_seconds) { |                                            Handle thread_handle, s64 nano_seconds) { | ||||||
|     NGLOG_TRACE( |     NGLOG_TRACE( | ||||||
| @@ -689,6 +690,52 @@ static ResultCode SignalProcessWideKey(VAddr condition_variable_addr, s32 target | |||||||
|     return RESULT_SUCCESS; |     return RESULT_SUCCESS; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | // Wait for an address (via Address Arbiter) | ||||||
|  | static ResultCode WaitForAddress(VAddr address, u32 type, s32 value, s64 timeout) { | ||||||
|  |     // If the passed address is a kernel virtual address, return invalid memory state. | ||||||
|  |     if ((address + 0x8000000000LL) < 0x7FFFE00000LL) { | ||||||
|  |         return ERR_INVALID_ADDRESS_STATE; | ||||||
|  |     } | ||||||
|  |     // If the address is not properly aligned to 4 bytes, return invalid address. | ||||||
|  |     if (address % sizeof(u32) != 0) { | ||||||
|  |         return ERR_INVALID_ADDRESS; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     switch ((AddressArbiter::ArbitrationType)type) { | ||||||
|  |         case AddressArbiter::ArbitrationType::WaitIfLessThan: | ||||||
|  |             return AddressArbiter::WaitForAddressIfLessThan(address, value, timeout, false); | ||||||
|  |         case AddressArbiter::ArbitrationType::DecrementAndWaitIfLessThan: | ||||||
|  |             return AddressArbiter::WaitForAddressIfLessThan(address, value, timeout, true); | ||||||
|  |         case AddressArbiter::ArbitrationType::WaitIfEqual: | ||||||
|  |             return AddressArbiter::WaitForAddressIfEqual(address, value, timeout); | ||||||
|  |         default: | ||||||
|  |             return ERR_INVALID_ENUM_VALUE; | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Signals to an address (via Address Arbiter) | ||||||
|  | static ResultCode SignalToAddress(VAddr address, u32 type, s32 value, s32 num_to_wake) { | ||||||
|  |     // If the passed address is a kernel virtual address, return invalid memory state. | ||||||
|  |     if ((address + 0x8000000000LL) < 0x7FFFE00000LL) { | ||||||
|  |         return ERR_INVALID_ADDRESS_STATE; | ||||||
|  |     } | ||||||
|  |     // If the address is not properly aligned to 4 bytes, return invalid address. | ||||||
|  |     if (address % sizeof(u32) != 0) { | ||||||
|  |         return ERR_INVALID_ADDRESS; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     switch ((AddressArbiter::SignalType)type) { | ||||||
|  |         case AddressArbiter::SignalType::Signal: | ||||||
|  |             return AddressArbiter::SignalToAddress(address, value, num_to_wake); | ||||||
|  |         case AddressArbiter::SignalType::IncrementAndSignalIfEqual: | ||||||
|  |             return AddressArbiter::IncrementAndSignalToAddressIfEqual(address, value, num_to_wake); | ||||||
|  |         case AddressArbiter::SignalType::ModifyByWaitingCountAndSignalIfEqual: | ||||||
|  |             return AddressArbiter::ModifyByWaitingCountAndSignalToAddressIfEqual(address, value, num_to_wake); | ||||||
|  |         default: | ||||||
|  |             return ERR_INVALID_ENUM_VALUE; | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
| /// This returns the total CPU ticks elapsed since the CPU was powered-on | /// This returns the total CPU ticks elapsed since the CPU was powered-on | ||||||
| static u64 GetSystemTick() { | static u64 GetSystemTick() { | ||||||
|     const u64 result{CoreTiming::GetTicks()}; |     const u64 result{CoreTiming::GetTicks()}; | ||||||
| @@ -861,8 +908,8 @@ static const FunctionDef SVC_Table[] = { | |||||||
|     {0x31, nullptr, "GetResourceLimitCurrentValue"}, |     {0x31, nullptr, "GetResourceLimitCurrentValue"}, | ||||||
|     {0x32, SvcWrap<SetThreadActivity>, "SetThreadActivity"}, |     {0x32, SvcWrap<SetThreadActivity>, "SetThreadActivity"}, | ||||||
|     {0x33, SvcWrap<GetThreadContext>, "GetThreadContext"}, |     {0x33, SvcWrap<GetThreadContext>, "GetThreadContext"}, | ||||||
|     {0x34, nullptr, "WaitForAddress"}, |     {0x34, SvcWrap<WaitForAddress>, "WaitForAddress"}, | ||||||
|     {0x35, nullptr, "SignalToAddress"}, |     {0x35, SvcWrap<SignalToAddress>, "SignalToAddress"}, | ||||||
|     {0x36, nullptr, "Unknown"}, |     {0x36, nullptr, "Unknown"}, | ||||||
|     {0x37, nullptr, "Unknown"}, |     {0x37, nullptr, "Unknown"}, | ||||||
|     {0x38, nullptr, "Unknown"}, |     {0x38, nullptr, "Unknown"}, | ||||||
|   | |||||||
| @@ -179,6 +179,16 @@ void SvcWrap() { | |||||||
|     FuncReturn(retval); |     FuncReturn(retval); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | template <ResultCode func(u64, u32, s32, s64)> | ||||||
|  | void SvcWrap() { | ||||||
|  |     FuncReturn(func(PARAM(0), (u32)(PARAM(1) & 0xFFFFFFFF), (s32)(PARAM(2) & 0xFFFFFFFF), (s64)PARAM(3)).raw); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | template <ResultCode func(u64, u32, s32, s32)> | ||||||
|  | void SvcWrap() { | ||||||
|  |     FuncReturn(func(PARAM(0), (u32)(PARAM(1) & 0xFFFFFFFF), (s32)(PARAM(2) & 0xFFFFFFFF), (s32)(PARAM(3) & 0xFFFFFFFF)).raw); | ||||||
|  | } | ||||||
|  |  | ||||||
| //////////////////////////////////////////////////////////////////////////////////////////////////// | //////////////////////////////////////////////////////////////////////////////////////////////////// | ||||||
| // Function wrappers that return type u32 | // Function wrappers that return type u32 | ||||||
|  |  | ||||||
|   | |||||||
| @@ -45,6 +45,7 @@ enum ThreadStatus { | |||||||
|     THREADSTATUS_WAIT_SYNCH_ANY, ///< Waiting due to WaitSynch1 or WaitSynchN with wait_all = false |     THREADSTATUS_WAIT_SYNCH_ANY, ///< Waiting due to WaitSynch1 or WaitSynchN with wait_all = false | ||||||
|     THREADSTATUS_WAIT_SYNCH_ALL, ///< Waiting due to WaitSynchronizationN with wait_all = true |     THREADSTATUS_WAIT_SYNCH_ALL, ///< Waiting due to WaitSynchronizationN with wait_all = true | ||||||
|     THREADSTATUS_WAIT_MUTEX,     ///< Waiting due to an ArbitrateLock/WaitProcessWideKey svc |     THREADSTATUS_WAIT_MUTEX,     ///< Waiting due to an ArbitrateLock/WaitProcessWideKey svc | ||||||
|  |     THREADSTATUS_WAIT_ARB,       ///< Waiting due to a SignalToAddress/WaitForAddress svc | ||||||
|     THREADSTATUS_DORMANT,        ///< Created but not yet made ready |     THREADSTATUS_DORMANT,        ///< Created but not yet made ready | ||||||
|     THREADSTATUS_DEAD            ///< Run to completion, or forcefully terminated |     THREADSTATUS_DEAD            ///< Run to completion, or forcefully terminated | ||||||
| }; | }; | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Michael Scire
					Michael Scire