summaryrefslogtreecommitdiff
path: root/Source
diff options
context:
space:
mode:
authorJMC47 <JMC4789@gmail.com>2023-09-02 12:45:39 -0400
committerGitHub <noreply@github.com>2023-09-02 12:45:39 -0400
commitbd57d17dee609bf6100651ef1cee862bae420da5 (patch)
treea7d0ce15879a297a0dee887fe9001e1a6f3f5704 /Source
parent6beaee078baeaa80f9f1c21ce372ce28fd8273b6 (diff)
parent4131dffae92c22ed938118d196ffc94da63246e1 (diff)
Merge pull request #12079 from JosJuice/blr-no-fastmem
Jit: Allow BLR optimization without fastmem
Diffstat (limited to 'Source')
-rw-r--r--Source/Core/Common/MemoryUtil.cpp34
-rw-r--r--Source/Core/Common/MemoryUtil.h8
-rw-r--r--Source/Core/Core/Core.cpp9
-rw-r--r--Source/Core/Core/PowerPC/JitCommon/JitBase.cpp21
4 files changed, 56 insertions, 16 deletions
diff --git a/Source/Core/Common/MemoryUtil.cpp b/Source/Core/Common/MemoryUtil.cpp
index b473705411..2cd393d098 100644
--- a/Source/Core/Common/MemoryUtil.cpp
+++ b/Source/Core/Common/MemoryUtil.cpp
@@ -160,18 +160,25 @@ void* AllocateAlignedMemory(size_t size, size_t alignment)
return ptr;
}
-void FreeMemoryPages(void* ptr, size_t size)
+bool FreeMemoryPages(void* ptr, size_t size)
{
if (ptr)
{
#ifdef _WIN32
if (!VirtualFree(ptr, 0, MEM_RELEASE))
+ {
PanicAlertFmt("FreeMemoryPages failed!\nVirtualFree: {}", GetLastErrorString());
+ return false;
+ }
#else
if (munmap(ptr, size) != 0)
+ {
PanicAlertFmt("FreeMemoryPages failed!\nmunmap: {}", LastStrerrorString());
+ return false;
+ }
#endif
}
+ return true;
}
void FreeAlignedMemory(void* ptr)
@@ -186,39 +193,56 @@ void FreeAlignedMemory(void* ptr)
}
}
-void ReadProtectMemory(void* ptr, size_t size)
+bool ReadProtectMemory(void* ptr, size_t size)
{
#ifdef _WIN32
DWORD oldValue;
if (!VirtualProtect(ptr, size, PAGE_NOACCESS, &oldValue))
+ {
PanicAlertFmt("ReadProtectMemory failed!\nVirtualProtect: {}", GetLastErrorString());
+ return false;
+ }
#else
if (mprotect(ptr, size, PROT_NONE) != 0)
+ {
PanicAlertFmt("ReadProtectMemory failed!\nmprotect: {}", LastStrerrorString());
+ return false;
+ }
#endif
+ return true;
}
-void WriteProtectMemory(void* ptr, size_t size, bool allowExecute)
+bool WriteProtectMemory(void* ptr, size_t size, bool allowExecute)
{
#ifdef _WIN32
DWORD oldValue;
if (!VirtualProtect(ptr, size, allowExecute ? PAGE_EXECUTE_READ : PAGE_READONLY, &oldValue))
+ {
PanicAlertFmt("WriteProtectMemory failed!\nVirtualProtect: {}", GetLastErrorString());
+ return false;
+ }
#elif !(defined(_M_ARM_64) && defined(__APPLE__))
// MacOS 11.2 on ARM does not allow for changing the access permissions of pages
// that were marked executable, instead it uses the protections offered by MAP_JIT
// for write protection.
if (mprotect(ptr, size, allowExecute ? (PROT_READ | PROT_EXEC) : PROT_READ) != 0)
+ {
PanicAlertFmt("WriteProtectMemory failed!\nmprotect: {}", LastStrerrorString());
+ return false;
+ }
#endif
+ return true;
}
-void UnWriteProtectMemory(void* ptr, size_t size, bool allowExecute)
+bool UnWriteProtectMemory(void* ptr, size_t size, bool allowExecute)
{
#ifdef _WIN32
DWORD oldValue;
if (!VirtualProtect(ptr, size, allowExecute ? PAGE_EXECUTE_READWRITE : PAGE_READWRITE, &oldValue))
+ {
PanicAlertFmt("UnWriteProtectMemory failed!\nVirtualProtect: {}", GetLastErrorString());
+ return false;
+ }
#elif !(defined(_M_ARM_64) && defined(__APPLE__))
// MacOS 11.2 on ARM does not allow for changing the access permissions of pages
// that were marked executable, instead it uses the protections offered by MAP_JIT
@@ -227,8 +251,10 @@ void UnWriteProtectMemory(void* ptr, size_t size, bool allowExecute)
allowExecute ? (PROT_READ | PROT_WRITE | PROT_EXEC) : PROT_WRITE | PROT_READ) != 0)
{
PanicAlertFmt("UnWriteProtectMemory failed!\nmprotect: {}", LastStrerrorString());
+ return false;
}
#endif
+ return true;
}
size_t MemPhysical()
diff --git a/Source/Core/Common/MemoryUtil.h b/Source/Core/Common/MemoryUtil.h
index b6489e9546..11ee1c4cbb 100644
--- a/Source/Core/Common/MemoryUtil.h
+++ b/Source/Core/Common/MemoryUtil.h
@@ -27,12 +27,12 @@ struct ScopedJITPageWriteAndNoExecute
~ScopedJITPageWriteAndNoExecute() { JITPageWriteDisableExecuteEnable(); }
};
void* AllocateMemoryPages(size_t size);
-void FreeMemoryPages(void* ptr, size_t size);
+bool FreeMemoryPages(void* ptr, size_t size);
void* AllocateAlignedMemory(size_t size, size_t alignment);
void FreeAlignedMemory(void* ptr);
-void ReadProtectMemory(void* ptr, size_t size);
-void WriteProtectMemory(void* ptr, size_t size, bool executable = false);
-void UnWriteProtectMemory(void* ptr, size_t size, bool allowExecute = false);
+bool ReadProtectMemory(void* ptr, size_t size);
+bool WriteProtectMemory(void* ptr, size_t size, bool executable = false);
+bool UnWriteProtectMemory(void* ptr, size_t size, bool allowExecute = false);
size_t MemPhysical();
} // namespace Common
diff --git a/Source/Core/Core/Core.cpp b/Source/Core/Core/Core.cpp
index 9ca298a837..5396c8439b 100644
--- a/Source/Core/Core/Core.cpp
+++ b/Source/Core/Core/Core.cpp
@@ -391,9 +391,10 @@ static void CpuThread(const std::optional<std::string>& savestate_path, bool del
static_cast<void>(IDCache::GetEnvForThread());
#endif
- const bool fastmem_enabled = Config::Get(Config::MAIN_FASTMEM);
- if (fastmem_enabled)
- EMM::InstallExceptionHandler(); // Let's run under memory watch
+ // The JIT need to be able to intercept faults, both for fastmem and for the BLR optimization.
+ const bool exception_handler = EMM::IsExceptionHandlerSupported();
+ if (exception_handler)
+ EMM::InstallExceptionHandler();
#ifdef USE_MEMORYWATCHER
s_memory_watcher = std::make_unique<MemoryWatcher>();
@@ -441,7 +442,7 @@ static void CpuThread(const std::optional<std::string>& savestate_path, bool del
s_is_started = false;
- if (fastmem_enabled)
+ if (exception_handler)
EMM::UninstallExceptionHandler();
if (GDBStub::IsActive())
diff --git a/Source/Core/Core/PowerPC/JitCommon/JitBase.cpp b/Source/Core/Core/PowerPC/JitCommon/JitBase.cpp
index 7c9c707fbc..bcdafd9725 100644
--- a/Source/Core/Core/PowerPC/JitCommon/JitBase.cpp
+++ b/Source/Core/Core/PowerPC/JitCommon/JitBase.cpp
@@ -18,6 +18,7 @@
#include "Core/Core.h"
#include "Core/CoreTiming.h"
#include "Core/HW/CPU.h"
+#include "Core/MemTools.h"
#include "Core/PowerPC/PPCAnalyst.h"
#include "Core/PowerPC/PowerPC.h"
#include "Core/System.h"
@@ -132,7 +133,8 @@ void JitBase::RefreshConfig()
analyzer.SetDivByZeroExceptionsEnabled(m_enable_div_by_zero_exceptions);
bool any_watchpoints = m_system.GetPowerPC().GetMemChecks().HasAny();
- jo.fastmem = m_fastmem_enabled && jo.fastmem_arena && (m_ppc_state.msr.DR || !any_watchpoints);
+ jo.fastmem = m_fastmem_enabled && jo.fastmem_arena && (m_ppc_state.msr.DR || !any_watchpoints) &&
+ EMM::IsExceptionHandlerSupported();
jo.memcheck = m_system.IsMMUMode() || m_system.IsPauseOnPanicMode() || any_watchpoints;
jo.fp_exceptions = m_enable_float_exceptions;
jo.div_by_zero_exceptions = m_enable_div_by_zero_exceptions;
@@ -140,7 +142,8 @@ void JitBase::RefreshConfig()
void JitBase::InitBLROptimization()
{
- m_enable_blr_optimization = jo.enableBlocklink && m_fastmem_enabled && !m_enable_debugging;
+ m_enable_blr_optimization =
+ jo.enableBlocklink && !m_enable_debugging && EMM::IsExceptionHandlerSupported();
m_cleanup_after_stackfault = false;
}
@@ -151,7 +154,12 @@ void JitBase::ProtectStack()
#ifdef _WIN32
ULONG reserveSize = SAFE_STACK_SIZE;
- SetThreadStackGuarantee(&reserveSize);
+ if (!SetThreadStackGuarantee(&reserveSize))
+ {
+ PanicAlertFmt("Failed to set thread stack guarantee");
+ m_enable_blr_optimization = false;
+ return;
+ }
#else
auto [stack_addr, stack_size] = Common::GetCurrentThreadStack();
@@ -184,7 +192,12 @@ void JitBase::ProtectStack()
}
m_stack_guard = reinterpret_cast<u8*>(stack_guard_addr);
- Common::ReadProtectMemory(m_stack_guard, GUARD_SIZE);
+ if (!Common::ReadProtectMemory(m_stack_guard, GUARD_SIZE))
+ {
+ m_stack_guard = nullptr;
+ m_enable_blr_optimization = false;
+ return;
+ }
#endif
}