Skip to content

Commit

Permalink
Apple M1: RAII Wrapper for JITPageWrite*Execute*()
Browse files Browse the repository at this point in the history
Added RAII wrapper around the the JITPageWriteEnableExecuteDisable() and
JITPageWriteDisableExecuteEnable() to make it so that it is harder to forget to
pair the calls in all code branches as suggested by leoetlino.
  • Loading branch information
skylersaleh committed May 22, 2021
1 parent 76130d8 commit 76ed931
Show file tree
Hide file tree
Showing 6 changed files with 20 additions and 15 deletions.
13 changes: 13 additions & 0 deletions Source/Core/Common/MemoryUtil.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,23 @@
namespace Common
{
void* AllocateExecutableMemory(size_t size);

// These two functions control the executable/writable state of the W^X memory
// allocations. More detailed documentation about them is in the .cpp file.
// In general where applicable the ScopedJITPageWriteAndNoExecute wrapper
// should be used to prevent bugs from not pairing up the calls properly.

// Allows a thread to write to executable memory, but not execute the data.
void JITPageWriteEnableExecuteDisable();
// Allows a thread to execute memory allocated for execution, but not write to it.
void JITPageWriteDisableExecuteEnable();
// RAII Wrapper around JITPageWrite*Execute*(). When this is in scope the thread can
// write to executable memory but not execute it.
struct ScopedJITPageWriteAndNoExecute
{
ScopedJITPageWriteAndNoExecute() { JITPageWriteEnableExecuteDisable(); }
~ScopedJITPageWriteAndNoExecute() { JITPageWriteDisableExecuteEnable(); }
};
void* AllocateMemoryPages(size_t size);
void FreeMemoryPages(void* ptr, size_t size);
void* AllocateAlignedMemory(size_t size, size_t alignment);
Expand Down
7 changes: 2 additions & 5 deletions Source/Core/Core/PowerPC/JitArm64/Jit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -127,13 +127,12 @@ void JitArm64::ClearCache()
m_handler_to_loc.clear();

blocks.Clear();
Common::JITPageWriteEnableExecuteDisable();
const Common::ScopedJITPageWriteAndNoExecute enable_jit_page_writes;
ClearCodeSpace();
farcode.ClearCodeSpace();
UpdateMemoryOptions();

GenerateAsm();
Common::JITPageWriteDisableExecuteEnable();
}

void JitArm64::Shutdown()
Expand Down Expand Up @@ -601,7 +600,7 @@ void JitArm64::Jit(u32)
{
ClearCache();
}
Common::JITPageWriteEnableExecuteDisable();
const Common::ScopedJITPageWriteAndNoExecute enable_jit_page_writes;

std::size_t block_size = m_code_buffer.size();
const u32 em_address = PowerPC::ppcState.pc;
Expand All @@ -623,15 +622,13 @@ void JitArm64::Jit(u32)
NPC = nextPC;
PowerPC::ppcState.Exceptions |= EXCEPTION_ISI;
PowerPC::CheckExceptions();
Common::JITPageWriteDisableExecuteEnable();
WARN_LOG_FMT(POWERPC, "ISI exception at {:#010x}", nextPC);
return;
}

JitBlock* b = blocks.AllocateBlock(em_address);
DoJit(em_address, b, nextPC);
blocks.FinalizeBlock(*b, jo.enableBlocklink, code_block.m_physical_addresses);
Common::JITPageWriteDisableExecuteEnable();
}

void JitArm64::DoJit(u32 em_address, JitBlock* b, u32 nextPC)
Expand Down
6 changes: 2 additions & 4 deletions Source/Core/Core/PowerPC/JitArm64/JitArm64Cache.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -59,22 +59,20 @@ void JitArm64BlockCache::WriteLinkBlock(Arm64Gen::ARM64XEmitter& emit,

void JitArm64BlockCache::WriteLinkBlock(const JitBlock::LinkData& source, const JitBlock* dest)
{
Common::JITPageWriteEnableExecuteDisable();
const Common::ScopedJITPageWriteAndNoExecute enable_jit_page_writes;
u8* location = source.exitPtrs;
ARM64XEmitter emit(location);

WriteLinkBlock(emit, source, dest);
Common::JITPageWriteDisableExecuteEnable();
emit.FlushIcache();
}

void JitArm64BlockCache::WriteDestroyBlock(const JitBlock& block)
{
// Only clear the entry points as we might still be within this block.
ARM64XEmitter emit(block.checkedEntry);
Common::JITPageWriteEnableExecuteDisable();
const Common::ScopedJITPageWriteAndNoExecute enable_jit_page_writes;
while (emit.GetWritableCodePtr() <= block.normalEntry)
emit.BRK(0x123);
Common::JITPageWriteDisableExecuteEnable();
emit.FlushIcache();
}
3 changes: 1 addition & 2 deletions Source/Core/Core/PowerPC/JitArm64/JitArm64_BackPatch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -289,7 +289,7 @@ bool JitArm64::HandleFastmemFault(uintptr_t access_address, SContext* ctx)
if ((const u8*)ctx->CTX_PC - fault_location > fastmem_area_length)
return false;

Common::JITPageWriteEnableExecuteDisable();
const Common::ScopedJITPageWriteAndNoExecute enable_jit_page_writes;
ARM64XEmitter emitter((u8*)fault_location);

emitter.BL(slow_handler_iter->second.slowmem_code);
Expand All @@ -301,7 +301,6 @@ bool JitArm64::HandleFastmemFault(uintptr_t access_address, SContext* ctx)
m_fault_to_handler.erase(slow_handler_iter);

emitter.FlushIcache();
Common::JITPageWriteDisableExecuteEnable();

ctx->CTX_PC = reinterpret_cast<std::uintptr_t>(fault_location);
return true;
Expand Down
3 changes: 1 addition & 2 deletions Source/Core/Core/PowerPC/JitArm64/JitAsm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ using namespace Arm64Gen;

void JitArm64::GenerateAsm()
{
Common::JITPageWriteEnableExecuteDisable();
const Common::ScopedJITPageWriteAndNoExecute enable_jit_page_writes;

// This value is all of the callee saved registers that we are required to save.
// According to the AACPS64 we need to save R19 ~ R30 and Q8 ~ Q15.
Expand Down Expand Up @@ -199,7 +199,6 @@ void JitArm64::GenerateAsm()
GenerateCommonAsm();

FlushIcache();
Common::JITPageWriteDisableExecuteEnable();
}

void JitArm64::GenerateCommonAsm()
Expand Down
3 changes: 1 addition & 2 deletions Source/Core/VideoCommon/VertexLoaderARM64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,10 +54,9 @@ VertexLoaderARM64::VertexLoaderARM64(const TVtxDesc& vtx_desc, const VAT& vtx_at
: VertexLoaderBase(vtx_desc, vtx_att), m_float_emit(this)
{
AllocCodeSpace(4096);
Common::JITPageWriteEnableExecuteDisable();
const Common::ScopedJITPageWriteAndNoExecute enable_jit_page_writes;
ClearCodeSpace();
GenerateVertexLoader();
Common::JITPageWriteDisableExecuteEnable();
WriteProtect();
}

Expand Down

0 comments on commit 76ed931

Please sign in to comment.