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, | ||||
|  | ||||
|     // Confirmed Switch OS error codes | ||||
|     MisalignedAddress = 102, | ||||
|     InvalidAddress = 102, | ||||
|     InvalidMemoryState = 106, | ||||
|     InvalidProcessorId = 113, | ||||
|     InvalidHandle = 114, | ||||
|     InvalidCombination = 116, | ||||
|     Timeout = 117, | ||||
|     SynchronizationCanceled = 118, | ||||
|     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_WRONG_PERMISSION(-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_COMBINATION(-1); | ||||
| constexpr ResultCode ERR_INVALID_COMBINATION_KERNEL(-1); | ||||
| constexpr ResultCode ERR_OUT_OF_MEMORY(-1); | ||||
| constexpr ResultCode ERR_INVALID_ADDRESS(-1); | ||||
| constexpr ResultCode ERR_INVALID_ADDRESS_STATE(-1); | ||||
| constexpr ResultCode ERR_INVALID_ADDRESS(ErrorModule::Kernel, ErrCodes::InvalidAddress); | ||||
| constexpr ResultCode ERR_INVALID_ADDRESS_STATE(ErrorModule::Kernel, ErrCodes::InvalidMemoryState); | ||||
| constexpr ResultCode ERR_INVALID_HANDLE(ErrorModule::Kernel, ErrCodes::InvalidHandle); | ||||
| constexpr ResultCode ERR_INVALID_POINTER(-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) { | ||||
|     // The mutex address must be 4-byte aligned | ||||
|     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); | ||||
| @@ -97,7 +97,7 @@ ResultCode Mutex::TryAcquire(VAddr address, Handle holding_thread_handle, | ||||
| ResultCode Mutex::Release(VAddr address) { | ||||
|     // The mutex address must be 4-byte aligned | ||||
|     if ((address % sizeof(u32)) != 0) { | ||||
|         return ResultCode(ErrorModule::Kernel, ErrCodes::MisalignedAddress); | ||||
|         return ResultCode(ErrorModule::Kernel, ErrCodes::InvalidAddress); | ||||
|     } | ||||
|  | ||||
|     auto [thread, num_waiters] = GetHighestPriorityMutexWaitingThread(GetCurrentThread(), address); | ||||
|   | ||||
| @@ -11,6 +11,7 @@ | ||||
| #include "common/string_util.h" | ||||
| #include "core/core.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_session.h" | ||||
| #include "core/hle/kernel/event.h" | ||||
| @@ -580,7 +581,7 @@ static void SleepThread(s64 nanoseconds) { | ||||
|     Core::System::GetInstance().PrepareReschedule(); | ||||
| } | ||||
|  | ||||
| /// Signal process wide key atomic | ||||
| /// Wait process wide key atomic | ||||
| static ResultCode WaitProcessWideKeyAtomic(VAddr mutex_addr, VAddr condition_variable_addr, | ||||
|                                            Handle thread_handle, s64 nano_seconds) { | ||||
|     NGLOG_TRACE( | ||||
| @@ -689,6 +690,52 @@ static ResultCode SignalProcessWideKey(VAddr condition_variable_addr, s32 target | ||||
|     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 | ||||
| static u64 GetSystemTick() { | ||||
|     const u64 result{CoreTiming::GetTicks()}; | ||||
| @@ -861,8 +908,8 @@ static const FunctionDef SVC_Table[] = { | ||||
|     {0x31, nullptr, "GetResourceLimitCurrentValue"}, | ||||
|     {0x32, SvcWrap<SetThreadActivity>, "SetThreadActivity"}, | ||||
|     {0x33, SvcWrap<GetThreadContext>, "GetThreadContext"}, | ||||
|     {0x34, nullptr, "WaitForAddress"}, | ||||
|     {0x35, nullptr, "SignalToAddress"}, | ||||
|     {0x34, SvcWrap<WaitForAddress>, "WaitForAddress"}, | ||||
|     {0x35, SvcWrap<SignalToAddress>, "SignalToAddress"}, | ||||
|     {0x36, nullptr, "Unknown"}, | ||||
|     {0x37, nullptr, "Unknown"}, | ||||
|     {0x38, nullptr, "Unknown"}, | ||||
|   | ||||
| @@ -179,6 +179,16 @@ void SvcWrap() { | ||||
|     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 | ||||
|  | ||||
|   | ||||
| @@ -45,6 +45,7 @@ enum ThreadStatus { | ||||
|     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_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_DEAD            ///< Run to completion, or forcefully terminated | ||||
| }; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Michael Scire
					Michael Scire