kern: implement SvcSignalToAddress, SvcWaitForAddress

This commit is contained in:
Michael Scire 2020-07-16 19:06:48 -07:00 committed by SciresM
parent a0cc22302c
commit 8d507aa5a1
7 changed files with 292 additions and 16 deletions

View file

@ -149,6 +149,26 @@ namespace ams::kern::arch::arm64::cpu {
return true;
}
ALWAYS_INLINE bool CanAccessAtomic(KProcessAddress addr, bool privileged = false) {
const uintptr_t va = GetInteger(addr);
u64 phys_addr;
if (privileged) {
__asm__ __volatile__("at s1e1w, %[va]" :: [va]"r"(va) : "memory");
} else {
__asm__ __volatile__("at s1e0w, %[va]" :: [va]"r"(va) : "memory");
}
InstructionMemoryBarrier();
u64 par = GetParEl1();
if (par & 0x1) {
return false;
}
return (par >> BITSIZEOF(par) - BITSIZEOF(u8)) == 0xFF;
}
/* Synchronization helpers. */
NOINLINE void SynchronizeAllCores();

View file

@ -39,6 +39,9 @@ namespace ams::kern::arch::arm64 {
static bool ClearMemoryAligned64Bit(void *dst, size_t size);
static bool ClearMemorySize32Bit(void *dst);
static bool UpdateIfEqualAtomic(s32 *out, s32 *address, s32 compare_value, s32 new_value);
static bool DecrementIfLessThanAtomic(s32 *out, s32 *address, s32 compare);
static bool StoreDataCache(uintptr_t start, uintptr_t end);
static bool FlushDataCache(uintptr_t start, uintptr_t end);
static bool InvalidateDataCache(uintptr_t start, uintptr_t end);

View file

@ -20,6 +20,8 @@
namespace ams::kern {
extern KThread g_cv_arbiter_compare_thread;
class KConditionVariable {
public:
using ThreadTree = typename KThread::ConditionVariableThreadTreeType;

View file

@ -147,7 +147,7 @@ namespace ams::kern {
KLightLock *waiting_lock{};
uintptr_t condvar_key{};
uintptr_t entrypoint{};
KProcessAddress arbiter_key{};
KProcessAddress address_key{};
KProcess *parent{};
void *kernel_stack_top{};
u32 *light_ipc_data{};
@ -175,7 +175,7 @@ namespace ams::kern {
KThread *lock_owner{};
ConditionVariableThreadTree *condvar_tree{};
uintptr_t debug_params[3]{};
u32 arbiter_value{};
u32 address_key_value{};
u32 suspend_request_flags{};
u32 suspend_allowed_flags{};
Result wait_result;
@ -304,6 +304,7 @@ namespace ams::kern {
NOINLINE KThreadContext *GetContextForSchedulerLoop();
constexpr uintptr_t GetConditionVariableKey() const { return this->condvar_key; }
constexpr uintptr_t GetAddressArbiterKey() const { return this->condvar_key; }
constexpr void SetupForConditionVariableCompare(uintptr_t cv_key, int priority) {
this->condvar_key = cv_key;
@ -314,6 +315,11 @@ namespace ams::kern {
this->condvar_tree = nullptr;
}
constexpr void SetupForAddressArbiterCompare(uintptr_t address, int priority) {
this->condvar_key = address;
this->priority = priority;
}
constexpr void SetAddressArbiter(ConditionVariableThreadTree *tree, uintptr_t address) {
this->condvar_tree = tree;
this->condvar_key = address;
@ -349,10 +355,10 @@ namespace ams::kern {
void RemoveWaiter(KThread *thread);
KThread *RemoveWaiterByKey(s32 *out_num_waiters, KProcessAddress key);
constexpr KProcessAddress GetAddressKey() const { return this->arbiter_key; }
constexpr u32 GetAddressKeyValue() const { return this->arbiter_value; }
constexpr void SetAddressKey(KProcessAddress key) { this->arbiter_key = key; }
constexpr void SetAddressKey(KProcessAddress key, u32 val) { this->arbiter_key = key; this->arbiter_value = val; }
constexpr KProcessAddress GetAddressKey() const { return this->address_key; }
constexpr u32 GetAddressKeyValue() const { return this->address_key_value; }
constexpr void SetAddressKey(KProcessAddress key) { this->address_key = key; }
constexpr void SetAddressKey(KProcessAddress key, u32 val) { this->address_key = key; this->address_key_value = val; }
constexpr void SetLockOwner(KThread *owner) { this->lock_owner = owner; }
constexpr KThread *GetLockOwner() const { return this->lock_owner; }