From 7e191dccc184ae85ce5ade2bca913ab331002481 Mon Sep 17 00:00:00 2001 From: Michael Scire Date: Thu, 21 Jun 2018 00:49:43 -0600 Subject: Kernel/Arbiters: Add stubs for 4.x SignalToAddress/WaitForAddres SVCs. --- src/core/hle/kernel/svc.cpp | 53 ++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 50 insertions(+), 3 deletions(-) (limited to 'src/core/hle/kernel/svc.cpp') 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 @@ #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"}, {0x33, SvcWrap, "GetThreadContext"}, - {0x34, nullptr, "WaitForAddress"}, - {0x35, nullptr, "SignalToAddress"}, + {0x34, SvcWrap, "WaitForAddress"}, + {0x35, SvcWrap, "SignalToAddress"}, {0x36, nullptr, "Unknown"}, {0x37, nullptr, "Unknown"}, {0x38, nullptr, "Unknown"}, -- cgit v1.2.3 From 4f81bc4e1bd12e4df7410c6790ba818d8dbba9c0 Mon Sep 17 00:00:00 2001 From: Michael Scire Date: Thu, 21 Jun 2018 04:07:03 -0600 Subject: Kernel/Arbiters: Mostly implement SignalToAddress --- src/core/hle/kernel/svc.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/core/hle/kernel/svc.cpp') diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp index 4b4831c08..24dd50938 100644 --- a/src/core/hle/kernel/svc.cpp +++ b/src/core/hle/kernel/svc.cpp @@ -726,7 +726,7 @@ static ResultCode SignalToAddress(VAddr address, u32 type, s32 value, s32 num_to switch ((AddressArbiter::SignalType)type) { case AddressArbiter::SignalType::Signal: - return AddressArbiter::SignalToAddress(address, value, num_to_wake); + return AddressArbiter::SignalToAddress(address, num_to_wake); case AddressArbiter::SignalType::IncrementAndSignalIfEqual: return AddressArbiter::IncrementAndSignalToAddressIfEqual(address, value, num_to_wake); case AddressArbiter::SignalType::ModifyByWaitingCountAndSignalIfEqual: -- cgit v1.2.3 From 8f8fe62a19060a7c4529c4e0870412e9cd97e841 Mon Sep 17 00:00:00 2001 From: Michael Scire Date: Thu, 21 Jun 2018 05:13:06 -0600 Subject: Kernel/Arbiters: Initialize arb_wait_address in thread struct. --- src/core/hle/kernel/svc.cpp | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src/core/hle/kernel/svc.cpp') diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp index 24dd50938..2d8fa6070 100644 --- a/src/core/hle/kernel/svc.cpp +++ b/src/core/hle/kernel/svc.cpp @@ -692,6 +692,8 @@ static ResultCode SignalProcessWideKey(VAddr condition_variable_addr, s32 target // Wait for an address (via Address Arbiter) static ResultCode WaitForAddress(VAddr address, u32 type, s32 value, s64 timeout) { + NGLOG_WARNING(Kernel_SVC, "called, address=0x{:X}, type=0x{:X}, value=0x{:X}, timeout={}", + address, type, value, timeout); // If the passed address is a kernel virtual address, return invalid memory state. if ((address + 0x8000000000LL) < 0x7FFFE00000LL) { return ERR_INVALID_ADDRESS_STATE; @@ -715,6 +717,8 @@ static ResultCode WaitForAddress(VAddr address, u32 type, s32 value, s64 timeout // Signals to an address (via Address Arbiter) static ResultCode SignalToAddress(VAddr address, u32 type, s32 value, s32 num_to_wake) { + NGLOG_WARNING(Kernel_SVC, "called, address=0x{:X}, type=0x{:X}, value=0x{:X}, num_to_wake=0x{:X}", + address, type, value, 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; -- cgit v1.2.3 From 5f8aa02584eb8a5fdba583a192d551a2db707fb7 Mon Sep 17 00:00:00 2001 From: Michael Scire Date: Thu, 21 Jun 2018 21:09:51 -0600 Subject: Add additional missing format. --- src/core/hle/kernel/svc.cpp | 40 +++++++++++++++++++++------------------- 1 file changed, 21 insertions(+), 19 deletions(-) (limited to 'src/core/hle/kernel/svc.cpp') diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp index 2d8fa6070..95ce2205a 100644 --- a/src/core/hle/kernel/svc.cpp +++ b/src/core/hle/kernel/svc.cpp @@ -693,7 +693,7 @@ static ResultCode SignalProcessWideKey(VAddr condition_variable_addr, s32 target // Wait for an address (via Address Arbiter) static ResultCode WaitForAddress(VAddr address, u32 type, s32 value, s64 timeout) { NGLOG_WARNING(Kernel_SVC, "called, address=0x{:X}, type=0x{:X}, value=0x{:X}, timeout={}", - address, type, value, timeout); + address, type, value, timeout); // If the passed address is a kernel virtual address, return invalid memory state. if ((address + 0x8000000000LL) < 0x7FFFE00000LL) { return ERR_INVALID_ADDRESS_STATE; @@ -704,21 +704,22 @@ static ResultCode WaitForAddress(VAddr address, u32 type, s32 value, s64 timeout } 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; + 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) { - NGLOG_WARNING(Kernel_SVC, "called, address=0x{:X}, type=0x{:X}, value=0x{:X}, num_to_wake=0x{:X}", - address, type, value, num_to_wake); + NGLOG_WARNING(Kernel_SVC, + "called, address=0x{:X}, type=0x{:X}, value=0x{:X}, num_to_wake=0x{:X}", address, + type, value, 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; @@ -729,14 +730,15 @@ static ResultCode SignalToAddress(VAddr address, u32 type, s32 value, s32 num_to } switch ((AddressArbiter::SignalType)type) { - case AddressArbiter::SignalType::Signal: - return AddressArbiter::SignalToAddress(address, 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; + case AddressArbiter::SignalType::Signal: + return AddressArbiter::SignalToAddress(address, 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; } } -- cgit v1.2.3 From 067ac434ba90084359babef1638970e849a5f2ce Mon Sep 17 00:00:00 2001 From: Michael Scire Date: Fri, 22 Jun 2018 00:47:59 -0600 Subject: Kernel/Arbiters: Fix casts, cleanup comments/magic numbers --- src/core/hle/kernel/svc.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'src/core/hle/kernel/svc.cpp') diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp index 95ce2205a..1a36e0d02 100644 --- a/src/core/hle/kernel/svc.cpp +++ b/src/core/hle/kernel/svc.cpp @@ -695,7 +695,7 @@ static ResultCode WaitForAddress(VAddr address, u32 type, s32 value, s64 timeout NGLOG_WARNING(Kernel_SVC, "called, address=0x{:X}, type=0x{:X}, value=0x{:X}, timeout={}", address, type, value, timeout); // If the passed address is a kernel virtual address, return invalid memory state. - if ((address + 0x8000000000LL) < 0x7FFFE00000LL) { + if (Memory::IsKernelVirtualAddress(address)) { return ERR_INVALID_ADDRESS_STATE; } // If the address is not properly aligned to 4 bytes, return invalid address. @@ -703,7 +703,7 @@ static ResultCode WaitForAddress(VAddr address, u32 type, s32 value, s64 timeout return ERR_INVALID_ADDRESS; } - switch ((AddressArbiter::ArbitrationType)type) { + switch (static_cast(type)) { case AddressArbiter::ArbitrationType::WaitIfLessThan: return AddressArbiter::WaitForAddressIfLessThan(address, value, timeout, false); case AddressArbiter::ArbitrationType::DecrementAndWaitIfLessThan: @@ -721,7 +721,7 @@ static ResultCode SignalToAddress(VAddr address, u32 type, s32 value, s32 num_to "called, address=0x{:X}, type=0x{:X}, value=0x{:X}, num_to_wake=0x{:X}", address, type, value, num_to_wake); // If the passed address is a kernel virtual address, return invalid memory state. - if ((address + 0x8000000000LL) < 0x7FFFE00000LL) { + if (Memory::IsKernelVirtualAddress(address)) { return ERR_INVALID_ADDRESS_STATE; } // If the address is not properly aligned to 4 bytes, return invalid address. @@ -729,7 +729,7 @@ static ResultCode SignalToAddress(VAddr address, u32 type, s32 value, s32 num_to return ERR_INVALID_ADDRESS; } - switch ((AddressArbiter::SignalType)type) { + switch (static_cast(type)) { case AddressArbiter::SignalType::Signal: return AddressArbiter::SignalToAddress(address, num_to_wake); case AddressArbiter::SignalType::IncrementAndSignalIfEqual: -- cgit v1.2.3