diff options
| author | 2018-06-21 00:49:43 -0600 | |
|---|---|---|
| committer | 2018-06-21 00:49:43 -0600 | |
| commit | 7e191dccc184ae85ce5ade2bca913ab331002481 (patch) | |
| tree | 184b0444e9d0cd3bfaea3ebf8c2742802753f58b /src/core/hle/kernel | |
| parent | Merge pull request #576 from Subv/warnings1 (diff) | |
| download | yuzu-7e191dccc184ae85ce5ade2bca913ab331002481.tar.gz yuzu-7e191dccc184ae85ce5ade2bca913ab331002481.tar.xz yuzu-7e191dccc184ae85ce5ade2bca913ab331002481.zip | |
Kernel/Arbiters: Add stubs for 4.x SignalToAddress/WaitForAddres SVCs.
Diffstat (limited to 'src/core/hle/kernel')
| -rw-r--r-- | src/core/hle/kernel/address_arbiter.cpp | 46 | ||||
| -rw-r--r-- | src/core/hle/kernel/address_arbiter.h | 32 | ||||
| -rw-r--r-- | src/core/hle/kernel/errors.h | 10 | ||||
| -rw-r--r-- | src/core/hle/kernel/mutex.cpp | 4 | ||||
| -rw-r--r-- | src/core/hle/kernel/svc.cpp | 53 | ||||
| -rw-r--r-- | src/core/hle/kernel/svc_wrap.h | 10 | ||||
| -rw-r--r-- | src/core/hle/kernel/thread.h | 1 |
7 files changed, 147 insertions, 9 deletions
diff --git a/src/core/hle/kernel/address_arbiter.cpp b/src/core/hle/kernel/address_arbiter.cpp new file mode 100644 index 000000000..cfd2c1590 --- /dev/null +++ b/src/core/hle/kernel/address_arbiter.cpp | |||
| @@ -0,0 +1,46 @@ | |||
| 1 | // Copyright 2018 yuzu emulator team | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include "common/assert.h" | ||
| 6 | #include "common/common_funcs.h" | ||
| 7 | #include "common/common_types.h" | ||
| 8 | #include "core/hle/kernel/kernel.h" | ||
| 9 | #include "core/hle/kernel/process.h" | ||
| 10 | #include "core/hle/kernel/thread.h" | ||
| 11 | #include "core/memory.h" | ||
| 12 | |||
| 13 | namespace Kernel { | ||
| 14 | namespace AddressArbiter { | ||
| 15 | |||
| 16 | // Signals an address being waited on. | ||
| 17 | ResultCode SignalToAddress(VAddr address, s32 value, s32 num_to_wake) { | ||
| 18 | // TODO | ||
| 19 | return RESULT_SUCCESS; | ||
| 20 | } | ||
| 21 | |||
| 22 | // Signals an address being waited on and increments its value if equal to the value argument. | ||
| 23 | ResultCode IncrementAndSignalToAddressIfEqual(VAddr address, s32 value, s32 num_to_wake) { | ||
| 24 | // TODO | ||
| 25 | return RESULT_SUCCESS; | ||
| 26 | } | ||
| 27 | |||
| 28 | // Signals an address being waited on and modifies its value based on waiting thread count if equal to the value argument. | ||
| 29 | ResultCode ModifyByWaitingCountAndSignalToAddressIfEqual(VAddr address, s32 value, s32 num_to_wake) { | ||
| 30 | // TODO | ||
| 31 | return RESULT_SUCCESS; | ||
| 32 | } | ||
| 33 | |||
| 34 | // Waits on an address if the value passed is less than the argument value, optionally decrementing. | ||
| 35 | ResultCode WaitForAddressIfLessThan(VAddr address, s32 value, s64 timeout, bool should_decrement) { | ||
| 36 | // TODO | ||
| 37 | return RESULT_SUCCESS; | ||
| 38 | } | ||
| 39 | |||
| 40 | // Waits on an address if the value passed is equal to the argument value. | ||
| 41 | ResultCode WaitForAddressIfEqual(VAddr address, s32 value, s64 timeout) { | ||
| 42 | // TODO | ||
| 43 | return RESULT_SUCCESS; | ||
| 44 | } | ||
| 45 | } // namespace AddressArbiter | ||
| 46 | } // namespace Kernel \ No newline at end of file | ||
diff --git a/src/core/hle/kernel/address_arbiter.h b/src/core/hle/kernel/address_arbiter.h new file mode 100644 index 000000000..3eba103dd --- /dev/null +++ b/src/core/hle/kernel/address_arbiter.h | |||
| @@ -0,0 +1,32 @@ | |||
| 1 | // Copyright 2018 yuzu emulator team | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #pragma once | ||
| 6 | |||
| 7 | #include "core/hle/result.h" | ||
| 8 | |||
| 9 | namespace Kernel { | ||
| 10 | |||
| 11 | namespace AddressArbiter { | ||
| 12 | enum class ArbitrationType { | ||
| 13 | WaitIfLessThan = 0, | ||
| 14 | DecrementAndWaitIfLessThan = 1, | ||
| 15 | WaitIfEqual = 2, | ||
| 16 | }; | ||
| 17 | |||
| 18 | enum class SignalType { | ||
| 19 | Signal = 0, | ||
| 20 | IncrementAndSignalIfEqual = 1, | ||
| 21 | ModifyByWaitingCountAndSignalIfEqual = 2, | ||
| 22 | }; | ||
| 23 | |||
| 24 | ResultCode SignalToAddress(VAddr address, s32 value, s32 num_to_wake); | ||
| 25 | ResultCode IncrementAndSignalToAddressIfEqual(VAddr address, s32 value, s32 num_to_wake); | ||
| 26 | ResultCode ModifyByWaitingCountAndSignalToAddressIfEqual(VAddr address, s32 value, s32 num_to_wake); | ||
| 27 | |||
| 28 | ResultCode WaitForAddressIfLessThan(VAddr address, s32 value, s64 timeout, bool should_decrement); | ||
| 29 | ResultCode WaitForAddressIfEqual(VAddr address, s32 value, s64 timeout); | ||
| 30 | } // namespace AddressArbiter | ||
| 31 | |||
| 32 | } // namespace Kernel \ No newline at end of file | ||
diff --git a/src/core/hle/kernel/errors.h b/src/core/hle/kernel/errors.h index e1b5430bf..7ac960042 100644 --- a/src/core/hle/kernel/errors.h +++ b/src/core/hle/kernel/errors.h | |||
| @@ -20,13 +20,15 @@ enum { | |||
| 20 | MaxConnectionsReached = 52, | 20 | MaxConnectionsReached = 52, |
| 21 | 21 | ||
| 22 | // Confirmed Switch OS error codes | 22 | // Confirmed Switch OS error codes |
| 23 | MisalignedAddress = 102, | 23 | InvalidAddress = 102, |
| 24 | InvalidMemoryState = 106, | ||
| 24 | InvalidProcessorId = 113, | 25 | InvalidProcessorId = 113, |
| 25 | InvalidHandle = 114, | 26 | InvalidHandle = 114, |
| 26 | InvalidCombination = 116, | 27 | InvalidCombination = 116, |
| 27 | Timeout = 117, | 28 | Timeout = 117, |
| 28 | SynchronizationCanceled = 118, | 29 | SynchronizationCanceled = 118, |
| 29 | TooLarge = 119, | 30 | TooLarge = 119, |
| 31 | InvalidEnumValue = 120, | ||
| 30 | }; | 32 | }; |
| 31 | } | 33 | } |
| 32 | 34 | ||
| @@ -39,13 +41,13 @@ constexpr ResultCode ERR_SESSION_CLOSED_BY_REMOTE(-1); | |||
| 39 | constexpr ResultCode ERR_PORT_NAME_TOO_LONG(-1); | 41 | constexpr ResultCode ERR_PORT_NAME_TOO_LONG(-1); |
| 40 | constexpr ResultCode ERR_WRONG_PERMISSION(-1); | 42 | constexpr ResultCode ERR_WRONG_PERMISSION(-1); |
| 41 | constexpr ResultCode ERR_MAX_CONNECTIONS_REACHED(-1); | 43 | constexpr ResultCode ERR_MAX_CONNECTIONS_REACHED(-1); |
| 42 | constexpr ResultCode ERR_INVALID_ENUM_VALUE(-1); | 44 | constexpr ResultCode ERR_INVALID_ENUM_VALUE(ErrorModule::Kernel, ErrCodes::InvalidEnumValue); |
| 43 | constexpr ResultCode ERR_INVALID_ENUM_VALUE_FND(-1); | 45 | constexpr ResultCode ERR_INVALID_ENUM_VALUE_FND(-1); |
| 44 | constexpr ResultCode ERR_INVALID_COMBINATION(-1); | 46 | constexpr ResultCode ERR_INVALID_COMBINATION(-1); |
| 45 | constexpr ResultCode ERR_INVALID_COMBINATION_KERNEL(-1); | 47 | constexpr ResultCode ERR_INVALID_COMBINATION_KERNEL(-1); |
| 46 | constexpr ResultCode ERR_OUT_OF_MEMORY(-1); | 48 | constexpr ResultCode ERR_OUT_OF_MEMORY(-1); |
| 47 | constexpr ResultCode ERR_INVALID_ADDRESS(-1); | 49 | constexpr ResultCode ERR_INVALID_ADDRESS(ErrorModule::Kernel, ErrCodes::InvalidAddress); |
| 48 | constexpr ResultCode ERR_INVALID_ADDRESS_STATE(-1); | 50 | constexpr ResultCode ERR_INVALID_ADDRESS_STATE(ErrorModule::Kernel, ErrCodes::InvalidMemoryState); |
| 49 | constexpr ResultCode ERR_INVALID_HANDLE(ErrorModule::Kernel, ErrCodes::InvalidHandle); | 51 | constexpr ResultCode ERR_INVALID_HANDLE(ErrorModule::Kernel, ErrCodes::InvalidHandle); |
| 50 | constexpr ResultCode ERR_INVALID_POINTER(-1); | 52 | constexpr ResultCode ERR_INVALID_POINTER(-1); |
| 51 | constexpr ResultCode ERR_INVALID_OBJECT_ADDR(-1); | 53 | constexpr ResultCode ERR_INVALID_OBJECT_ADDR(-1); |
diff --git a/src/core/hle/kernel/mutex.cpp b/src/core/hle/kernel/mutex.cpp index bc144f3de..65560226d 100644 --- a/src/core/hle/kernel/mutex.cpp +++ b/src/core/hle/kernel/mutex.cpp | |||
| @@ -59,7 +59,7 @@ ResultCode Mutex::TryAcquire(VAddr address, Handle holding_thread_handle, | |||
| 59 | Handle requesting_thread_handle) { | 59 | Handle requesting_thread_handle) { |
| 60 | // The mutex address must be 4-byte aligned | 60 | // The mutex address must be 4-byte aligned |
| 61 | if ((address % sizeof(u32)) != 0) { | 61 | if ((address % sizeof(u32)) != 0) { |
| 62 | return ResultCode(ErrorModule::Kernel, ErrCodes::MisalignedAddress); | 62 | return ResultCode(ErrorModule::Kernel, ErrCodes::InvalidAddress); |
| 63 | } | 63 | } |
| 64 | 64 | ||
| 65 | SharedPtr<Thread> holding_thread = g_handle_table.Get<Thread>(holding_thread_handle); | 65 | 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, | |||
| 97 | ResultCode Mutex::Release(VAddr address) { | 97 | ResultCode Mutex::Release(VAddr address) { |
| 98 | // The mutex address must be 4-byte aligned | 98 | // The mutex address must be 4-byte aligned |
| 99 | if ((address % sizeof(u32)) != 0) { | 99 | if ((address % sizeof(u32)) != 0) { |
| 100 | return ResultCode(ErrorModule::Kernel, ErrCodes::MisalignedAddress); | 100 | return ResultCode(ErrorModule::Kernel, ErrCodes::InvalidAddress); |
| 101 | } | 101 | } |
| 102 | 102 | ||
| 103 | auto [thread, num_waiters] = GetHighestPriorityMutexWaitingThread(GetCurrentThread(), address); | 103 | auto [thread, num_waiters] = GetHighestPriorityMutexWaitingThread(GetCurrentThread(), address); |
diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp index 69ba7b777..4b4831c08 100644 --- a/src/core/hle/kernel/svc.cpp +++ b/src/core/hle/kernel/svc.cpp | |||
| @@ -11,6 +11,7 @@ | |||
| 11 | #include "common/string_util.h" | 11 | #include "common/string_util.h" |
| 12 | #include "core/core.h" | 12 | #include "core/core.h" |
| 13 | #include "core/core_timing.h" | 13 | #include "core/core_timing.h" |
| 14 | #include "core/hle/kernel/address_arbiter.h" | ||
| 14 | #include "core/hle/kernel/client_port.h" | 15 | #include "core/hle/kernel/client_port.h" |
| 15 | #include "core/hle/kernel/client_session.h" | 16 | #include "core/hle/kernel/client_session.h" |
| 16 | #include "core/hle/kernel/event.h" | 17 | #include "core/hle/kernel/event.h" |
| @@ -580,7 +581,7 @@ static void SleepThread(s64 nanoseconds) { | |||
| 580 | Core::System::GetInstance().PrepareReschedule(); | 581 | Core::System::GetInstance().PrepareReschedule(); |
| 581 | } | 582 | } |
| 582 | 583 | ||
| 583 | /// Signal process wide key atomic | 584 | /// Wait process wide key atomic |
| 584 | static ResultCode WaitProcessWideKeyAtomic(VAddr mutex_addr, VAddr condition_variable_addr, | 585 | static ResultCode WaitProcessWideKeyAtomic(VAddr mutex_addr, VAddr condition_variable_addr, |
| 585 | Handle thread_handle, s64 nano_seconds) { | 586 | Handle thread_handle, s64 nano_seconds) { |
| 586 | NGLOG_TRACE( | 587 | NGLOG_TRACE( |
| @@ -689,6 +690,52 @@ static ResultCode SignalProcessWideKey(VAddr condition_variable_addr, s32 target | |||
| 689 | return RESULT_SUCCESS; | 690 | return RESULT_SUCCESS; |
| 690 | } | 691 | } |
| 691 | 692 | ||
| 693 | // Wait for an address (via Address Arbiter) | ||
| 694 | static ResultCode WaitForAddress(VAddr address, u32 type, s32 value, s64 timeout) { | ||
| 695 | // If the passed address is a kernel virtual address, return invalid memory state. | ||
| 696 | if ((address + 0x8000000000LL) < 0x7FFFE00000LL) { | ||
| 697 | return ERR_INVALID_ADDRESS_STATE; | ||
| 698 | } | ||
| 699 | // If the address is not properly aligned to 4 bytes, return invalid address. | ||
| 700 | if (address % sizeof(u32) != 0) { | ||
| 701 | return ERR_INVALID_ADDRESS; | ||
| 702 | } | ||
| 703 | |||
| 704 | switch ((AddressArbiter::ArbitrationType)type) { | ||
| 705 | case AddressArbiter::ArbitrationType::WaitIfLessThan: | ||
| 706 | return AddressArbiter::WaitForAddressIfLessThan(address, value, timeout, false); | ||
| 707 | case AddressArbiter::ArbitrationType::DecrementAndWaitIfLessThan: | ||
| 708 | return AddressArbiter::WaitForAddressIfLessThan(address, value, timeout, true); | ||
| 709 | case AddressArbiter::ArbitrationType::WaitIfEqual: | ||
| 710 | return AddressArbiter::WaitForAddressIfEqual(address, value, timeout); | ||
| 711 | default: | ||
| 712 | return ERR_INVALID_ENUM_VALUE; | ||
| 713 | } | ||
| 714 | } | ||
| 715 | |||
| 716 | // Signals to an address (via Address Arbiter) | ||
| 717 | static ResultCode SignalToAddress(VAddr address, u32 type, s32 value, s32 num_to_wake) { | ||
| 718 | // If the passed address is a kernel virtual address, return invalid memory state. | ||
| 719 | if ((address + 0x8000000000LL) < 0x7FFFE00000LL) { | ||
| 720 | return ERR_INVALID_ADDRESS_STATE; | ||
| 721 | } | ||
| 722 | // If the address is not properly aligned to 4 bytes, return invalid address. | ||
| 723 | if (address % sizeof(u32) != 0) { | ||
| 724 | return ERR_INVALID_ADDRESS; | ||
| 725 | } | ||
| 726 | |||
| 727 | switch ((AddressArbiter::SignalType)type) { | ||
| 728 | case AddressArbiter::SignalType::Signal: | ||
| 729 | return AddressArbiter::SignalToAddress(address, value, num_to_wake); | ||
| 730 | case AddressArbiter::SignalType::IncrementAndSignalIfEqual: | ||
| 731 | return AddressArbiter::IncrementAndSignalToAddressIfEqual(address, value, num_to_wake); | ||
| 732 | case AddressArbiter::SignalType::ModifyByWaitingCountAndSignalIfEqual: | ||
| 733 | return AddressArbiter::ModifyByWaitingCountAndSignalToAddressIfEqual(address, value, num_to_wake); | ||
| 734 | default: | ||
| 735 | return ERR_INVALID_ENUM_VALUE; | ||
| 736 | } | ||
| 737 | } | ||
| 738 | |||
| 692 | /// This returns the total CPU ticks elapsed since the CPU was powered-on | 739 | /// This returns the total CPU ticks elapsed since the CPU was powered-on |
| 693 | static u64 GetSystemTick() { | 740 | static u64 GetSystemTick() { |
| 694 | const u64 result{CoreTiming::GetTicks()}; | 741 | const u64 result{CoreTiming::GetTicks()}; |
| @@ -861,8 +908,8 @@ static const FunctionDef SVC_Table[] = { | |||
| 861 | {0x31, nullptr, "GetResourceLimitCurrentValue"}, | 908 | {0x31, nullptr, "GetResourceLimitCurrentValue"}, |
| 862 | {0x32, SvcWrap<SetThreadActivity>, "SetThreadActivity"}, | 909 | {0x32, SvcWrap<SetThreadActivity>, "SetThreadActivity"}, |
| 863 | {0x33, SvcWrap<GetThreadContext>, "GetThreadContext"}, | 910 | {0x33, SvcWrap<GetThreadContext>, "GetThreadContext"}, |
| 864 | {0x34, nullptr, "WaitForAddress"}, | 911 | {0x34, SvcWrap<WaitForAddress>, "WaitForAddress"}, |
| 865 | {0x35, nullptr, "SignalToAddress"}, | 912 | {0x35, SvcWrap<SignalToAddress>, "SignalToAddress"}, |
| 866 | {0x36, nullptr, "Unknown"}, | 913 | {0x36, nullptr, "Unknown"}, |
| 867 | {0x37, nullptr, "Unknown"}, | 914 | {0x37, nullptr, "Unknown"}, |
| 868 | {0x38, nullptr, "Unknown"}, | 915 | {0x38, nullptr, "Unknown"}, |
diff --git a/src/core/hle/kernel/svc_wrap.h b/src/core/hle/kernel/svc_wrap.h index 40aa88cc1..efae4fdfe 100644 --- a/src/core/hle/kernel/svc_wrap.h +++ b/src/core/hle/kernel/svc_wrap.h | |||
| @@ -179,6 +179,16 @@ void SvcWrap() { | |||
| 179 | FuncReturn(retval); | 179 | FuncReturn(retval); |
| 180 | } | 180 | } |
| 181 | 181 | ||
| 182 | template <ResultCode func(u64, u32, s32, s64)> | ||
| 183 | void SvcWrap() { | ||
| 184 | FuncReturn(func(PARAM(0), (u32)(PARAM(1) & 0xFFFFFFFF), (s32)(PARAM(2) & 0xFFFFFFFF), (s64)PARAM(3)).raw); | ||
| 185 | } | ||
| 186 | |||
| 187 | template <ResultCode func(u64, u32, s32, s32)> | ||
| 188 | void SvcWrap() { | ||
| 189 | FuncReturn(func(PARAM(0), (u32)(PARAM(1) & 0xFFFFFFFF), (s32)(PARAM(2) & 0xFFFFFFFF), (s32)(PARAM(3) & 0xFFFFFFFF)).raw); | ||
| 190 | } | ||
| 191 | |||
| 182 | //////////////////////////////////////////////////////////////////////////////////////////////////// | 192 | //////////////////////////////////////////////////////////////////////////////////////////////////// |
| 183 | // Function wrappers that return type u32 | 193 | // Function wrappers that return type u32 |
| 184 | 194 | ||
diff --git a/src/core/hle/kernel/thread.h b/src/core/hle/kernel/thread.h index 1d2da6d50..023c9dbe9 100644 --- a/src/core/hle/kernel/thread.h +++ b/src/core/hle/kernel/thread.h | |||
| @@ -45,6 +45,7 @@ enum ThreadStatus { | |||
| 45 | THREADSTATUS_WAIT_SYNCH_ANY, ///< Waiting due to WaitSynch1 or WaitSynchN with wait_all = false | 45 | THREADSTATUS_WAIT_SYNCH_ANY, ///< Waiting due to WaitSynch1 or WaitSynchN with wait_all = false |
| 46 | THREADSTATUS_WAIT_SYNCH_ALL, ///< Waiting due to WaitSynchronizationN with wait_all = true | 46 | THREADSTATUS_WAIT_SYNCH_ALL, ///< Waiting due to WaitSynchronizationN with wait_all = true |
| 47 | THREADSTATUS_WAIT_MUTEX, ///< Waiting due to an ArbitrateLock/WaitProcessWideKey svc | 47 | THREADSTATUS_WAIT_MUTEX, ///< Waiting due to an ArbitrateLock/WaitProcessWideKey svc |
| 48 | THREADSTATUS_WAIT_ARB, ///< Waiting due to a SignalToAddress/WaitForAddress svc | ||
| 48 | THREADSTATUS_DORMANT, ///< Created but not yet made ready | 49 | THREADSTATUS_DORMANT, ///< Created but not yet made ready |
| 49 | THREADSTATUS_DEAD ///< Run to completion, or forcefully terminated | 50 | THREADSTATUS_DEAD ///< Run to completion, or forcefully terminated |
| 50 | }; | 51 | }; |