From bca8916cea9c437d82509f8350fa3b858720f90e Mon Sep 17 00:00:00 2001 From: Subv Date: Thu, 20 Jul 2017 23:52:50 -0500 Subject: [PATCH 1/2] Kernel/HLE: Use a mutex to synchronize access to the HLE kernel state between the cpu thread and any other possible threads that might touch the kernel (network thread, etc). This mutex is acquired in SVC::CallSVC, ie, as soon as the guest application enters the HLE kernel, and should be acquired by the aforementioned threads before modifying kernel structures. --- src/core/CMakeLists.txt | 2 ++ src/core/hle/kernel/kernel.h | 2 +- src/core/hle/lock.cpp | 11 +++++++++++ src/core/hle/lock.h | 18 ++++++++++++++++++ src/core/hle/svc.cpp | 8 ++++++-- 5 files changed, 38 insertions(+), 3 deletions(-) create mode 100644 src/core/hle/lock.cpp create mode 100644 src/core/hle/lock.h diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 360f407f3..14027e182 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -60,6 +60,7 @@ set(SRCS hle/kernel/timer.cpp hle/kernel/vm_manager.cpp hle/kernel/wait_object.cpp + hle/lock.cpp hle/romfs.cpp hle/service/ac/ac.cpp hle/service/ac/ac_i.cpp @@ -258,6 +259,7 @@ set(HEADERS hle/kernel/timer.h hle/kernel/vm_manager.h hle/kernel/wait_object.h + hle/lock.h hle/result.h hle/romfs.h hle/service/ac/ac.h diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h index 9cf288b08..255cda359 100644 --- a/src/core/hle/kernel/kernel.h +++ b/src/core/hle/kernel/kernel.h @@ -129,4 +129,4 @@ void Init(u32 system_mode); /// Shutdown the kernel void Shutdown(); -} // namespace +} // namespace Kernel diff --git a/src/core/hle/lock.cpp b/src/core/hle/lock.cpp new file mode 100644 index 000000000..082f689c8 --- /dev/null +++ b/src/core/hle/lock.cpp @@ -0,0 +1,11 @@ +// Copyright 2017 Citra Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include + +namespace HLE { +std::mutex g_hle_lock; +} diff --git a/src/core/hle/lock.h b/src/core/hle/lock.h new file mode 100644 index 000000000..8265621e1 --- /dev/null +++ b/src/core/hle/lock.h @@ -0,0 +1,18 @@ +// Copyright 2017 Citra Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include + +namespace HLE { +/* + * Synchronizes access to the internal HLE kernel structures, it is acquired when a guest + * application thread performs a syscall. It should be acquired by any host threads that read or + * modify the HLE kernel state. Note: Any operation that directly or indirectly reads from or writes + * to the emulated memory is not protected by this mutex, and should be avoided in any threads other + * than the CPU thread. + */ +extern std::mutex g_hle_lock; +} // namespace HLE diff --git a/src/core/hle/svc.cpp b/src/core/hle/svc.cpp index e4b803046..b98938cb4 100644 --- a/src/core/hle/svc.cpp +++ b/src/core/hle/svc.cpp @@ -31,6 +31,7 @@ #include "core/hle/kernel/timer.h" #include "core/hle/kernel/vm_manager.h" #include "core/hle/kernel/wait_object.h" +#include "core/hle/lock.h" #include "core/hle/result.h" #include "core/hle/service/service.h" @@ -1188,7 +1189,7 @@ struct FunctionDef { Func* func; const char* name; }; -} +} // namespace static const FunctionDef SVC_Table[] = { {0x00, nullptr, "Unknown"}, @@ -1332,6 +1333,9 @@ MICROPROFILE_DEFINE(Kernel_SVC, "Kernel", "SVC", MP_RGB(70, 200, 70)); void CallSVC(u32 immediate) { MICROPROFILE_SCOPE(Kernel_SVC); + // Lock the global kernel mutex when we enter the kernel HLE. + std::lock_guard lock(HLE::g_hle_lock); + const FunctionDef* info = GetSVCInfo(immediate); if (info) { if (info->func) { @@ -1342,4 +1346,4 @@ void CallSVC(u32 immediate) { } } -} // namespace +} // namespace SVC From f484927ed03a1943a83f8781e598e07c056cc82a Mon Sep 17 00:00:00 2001 From: Subv Date: Fri, 21 Jul 2017 00:34:47 -0500 Subject: [PATCH 2/2] Kernel/Memory: Acquire the global HLE lock when a memory read/write operation falls outside of the fast path, for it might perform an MMIO operation. --- src/core/memory.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/core/memory.cpp b/src/core/memory.cpp index 9024f4922..72cbf2ec7 100644 --- a/src/core/memory.cpp +++ b/src/core/memory.cpp @@ -9,6 +9,7 @@ #include "common/logging/log.h" #include "common/swap.h" #include "core/hle/kernel/process.h" +#include "core/hle/lock.h" #include "core/memory.h" #include "core/memory_setup.h" #include "core/mmio.h" @@ -187,6 +188,9 @@ T Read(const VAddr vaddr) { return value; } + // The memory access might do an MMIO or cached access, so we have to lock the HLE kernel state + std::lock_guard lock(HLE::g_hle_lock); + PageType type = current_page_table->attributes[vaddr >> PAGE_BITS]; switch (type) { case PageType::Unmapped: @@ -226,6 +230,9 @@ void Write(const VAddr vaddr, const T data) { return; } + // The memory access might do an MMIO or cached access, so we have to lock the HLE kernel state + std::lock_guard lock(HLE::g_hle_lock); + PageType type = current_page_table->attributes[vaddr >> PAGE_BITS]; switch (type) { case PageType::Unmapped: @@ -722,4 +729,4 @@ VAddr PhysicalToVirtualAddress(const PAddr addr) { return addr | 0x80000000; } -} // namespace +} // namespace Memory