backend/A64: Fix SpinLockImpl not setting required memory permissions. (#9)
This commit is contained in:
parent
571c73a8f3
commit
d968f7ad81
@ -17,16 +17,6 @@
|
||||
#include "dynarmic/backend/A64/perf_map.h"
|
||||
#include "dynarmic/interface/halt_reason.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
# include <windows.h>
|
||||
#else
|
||||
# include <sys/mman.h>
|
||||
#endif
|
||||
|
||||
#ifdef __APPLE__
|
||||
# include <pthread.h>
|
||||
#endif
|
||||
|
||||
namespace Dynarmic::BackendA64 {
|
||||
|
||||
const Arm64Gen::ARM64Reg BlockOfCode::ABI_RETURN = Arm64Gen::ARM64Reg::X0;
|
||||
@ -53,23 +43,6 @@ namespace {
|
||||
constexpr size_t TOTAL_CODE_SIZE = 128 * 1024 * 1024;
|
||||
constexpr size_t FAR_CODE_OFFSET = 100 * 1024 * 1024;
|
||||
|
||||
#ifdef DYNARMIC_ENABLE_NO_EXECUTE_SUPPORT
|
||||
void ProtectMemory([[maybe_unused]] const void* base, [[maybe_unused]] size_t size, bool is_executable) {
|
||||
# if defined(_WIN32)
|
||||
DWORD oldProtect = 0;
|
||||
VirtualProtect(const_cast<void*>(base), size, is_executable ? PAGE_EXECUTE_READ : PAGE_READWRITE, &oldProtect);
|
||||
# elif defined(__APPLE__)
|
||||
pthread_jit_write_protect_np(is_executable);
|
||||
# else
|
||||
static const size_t pageSize = sysconf(_SC_PAGESIZE);
|
||||
const size_t iaddr = reinterpret_cast<size_t>(base);
|
||||
const size_t roundAddr = iaddr & ~(pageSize - static_cast<size_t>(1));
|
||||
const int mode = is_executable ? (PROT_READ | PROT_EXEC) : (PROT_READ | PROT_WRITE);
|
||||
mprotect(reinterpret_cast<void*>(roundAddr), size + (iaddr - roundAddr), mode);
|
||||
# endif
|
||||
}
|
||||
#endif
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
BlockOfCode::BlockOfCode(RunCodeCallbacks cb, JitStateInfo jsi)
|
||||
@ -91,18 +64,6 @@ void BlockOfCode::PreludeComplete() {
|
||||
DisableWriting();
|
||||
}
|
||||
|
||||
void BlockOfCode::EnableWriting() {
|
||||
#ifdef DYNARMIC_ENABLE_NO_EXECUTE_SUPPORT
|
||||
ProtectMemory(GetCodePtr(), TOTAL_CODE_SIZE, false);
|
||||
#endif
|
||||
}
|
||||
|
||||
void BlockOfCode::DisableWriting() {
|
||||
#ifdef DYNARMIC_ENABLE_NO_EXECUTE_SUPPORT
|
||||
ProtectMemory(GetCodePtr(), TOTAL_CODE_SIZE, true);
|
||||
#endif
|
||||
}
|
||||
|
||||
void BlockOfCode::ClearCache() {
|
||||
ASSERT(prelude_complete);
|
||||
in_far_code = false;
|
||||
|
@ -38,11 +38,6 @@ public:
|
||||
/// Call when external emitters have finished emitting their preludes.
|
||||
void PreludeComplete();
|
||||
|
||||
/// Change permissions to RW. This is required to support systems with W^X enforced.
|
||||
void EnableWriting();
|
||||
/// Change permissions to RX. This is required to support systems with W^X enforced.
|
||||
void DisableWriting();
|
||||
|
||||
/// Clears this block of code and resets code pointer to beginning.
|
||||
void ClearCache();
|
||||
/// Calculates how much space is remaining to use. This is the minimum of near code and far code.
|
||||
|
@ -13,6 +13,10 @@
|
||||
# include <sys/mman.h>
|
||||
#endif
|
||||
|
||||
#ifdef __APPLE__
|
||||
# include <pthread.h>
|
||||
#endif
|
||||
|
||||
#include <mcl/assert.hpp>
|
||||
#include <mcl/stdint.hpp>
|
||||
|
||||
@ -29,6 +33,23 @@ private:
|
||||
// host specific breakpoint instruction
|
||||
virtual void PoisonMemory() = 0;
|
||||
|
||||
#ifdef DYNARMIC_ENABLE_NO_EXECUTE_SUPPORT
|
||||
void ProtectMemory([[maybe_unused]] const void* base, [[maybe_unused]] size_t size, bool is_executable) {
|
||||
# if defined(_WIN32)
|
||||
DWORD oldProtect = 0;
|
||||
VirtualProtect(const_cast<void*>(base), size, is_executable ? PAGE_EXECUTE_READ : PAGE_READWRITE, &oldProtect);
|
||||
# elif defined(__APPLE__)
|
||||
pthread_jit_write_protect_np(is_executable);
|
||||
# else
|
||||
static const size_t pageSize = sysconf(_SC_PAGESIZE);
|
||||
const size_t iaddr = reinterpret_cast<size_t>(base);
|
||||
const size_t roundAddr = iaddr & ~(pageSize - static_cast<size_t>(1));
|
||||
const int mode = is_executable ? (PROT_READ | PROT_EXEC) : (PROT_READ | PROT_WRITE);
|
||||
mprotect(reinterpret_cast<void*>(roundAddr), size + (iaddr - roundAddr), mode);
|
||||
# endif
|
||||
}
|
||||
#endif
|
||||
|
||||
protected:
|
||||
u8* region = nullptr;
|
||||
// Size of region we can use.
|
||||
@ -136,5 +157,19 @@ public:
|
||||
child->ResetCodePtr();
|
||||
m_children.emplace_back(child);
|
||||
}
|
||||
|
||||
/// Change permissions to RW. This is required to support systems with W^X enforced.
|
||||
void EnableWriting() {
|
||||
#ifdef DYNARMIC_ENABLE_NO_EXECUTE_SUPPORT
|
||||
ProtectMemory(T::GetCodePtr(), total_region_size, false);
|
||||
#endif
|
||||
}
|
||||
|
||||
/// Change permissions to RX. This is required to support systems with W^X enforced.
|
||||
void DisableWriting() {
|
||||
#ifdef DYNARMIC_ENABLE_NO_EXECUTE_SUPPORT
|
||||
ProtectMemory(T::GetCodePtr(), total_region_size, true);
|
||||
#endif
|
||||
}
|
||||
};
|
||||
} // namespace Dynarmic::BackendA64
|
||||
|
@ -51,6 +51,7 @@ SpinLockImpl impl;
|
||||
|
||||
SpinLockImpl::SpinLockImpl() {
|
||||
code.AllocCodeSpace(64);
|
||||
code.EnableWriting();
|
||||
const ARM64Reg ABI_PARAM1 = BackendA64::HostLocToReg64(BackendA64::ABI_PARAM1);
|
||||
code.AlignCode16();
|
||||
lock = reinterpret_cast<void (*)(volatile int*)>(code.GetWritableCodePtr());
|
||||
@ -61,6 +62,7 @@ SpinLockImpl::SpinLockImpl() {
|
||||
unlock = reinterpret_cast<void (*)(volatile int*)>(code.GetWritableCodePtr());
|
||||
EmitSpinLockUnlock(code, ABI_PARAM1);
|
||||
code.RET();
|
||||
code.DisableWriting();
|
||||
code.FlushIcache();
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user