JitArm64: Handle stack faults.
This commit is contained in:
parent
40b7cc9252
commit
4d3883a756
|
@ -13,6 +13,7 @@
|
|||
|
||||
#include "Core/ConfigManager.h"
|
||||
#include "Core/Core.h"
|
||||
#include "Core/CoreTiming.h"
|
||||
#include "Core/HLE/HLE.h"
|
||||
#include "Core/HW/GPFifo.h"
|
||||
#include "Core/HW/Memmap.h"
|
||||
|
@ -62,7 +63,10 @@ void JitArm64::Init()
|
|||
analyzer.SetOption(PPCAnalyst::PPCAnalyzer::OPTION_CONDITIONAL_CONTINUE);
|
||||
analyzer.SetOption(PPCAnalyst::PPCAnalyzer::OPTION_CARRY_MERGE);
|
||||
analyzer.SetOption(PPCAnalyst::PPCAnalyzer::OPTION_BRANCH_FOLLOW);
|
||||
m_enable_blr_optimization = true;
|
||||
|
||||
m_enable_blr_optimization = jo.enableBlocklink && SConfig::GetInstance().bFastmem &&
|
||||
!SConfig::GetInstance().bEnableDebugging;
|
||||
m_cleanup_after_stackfault = false;
|
||||
|
||||
AllocStack();
|
||||
GenerateAsm();
|
||||
|
@ -70,6 +74,53 @@ void JitArm64::Init()
|
|||
m_supports_cycle_counter = HasCycleCounters();
|
||||
}
|
||||
|
||||
bool JitArm64::HandleFault(uintptr_t access_address, SContext* ctx)
|
||||
{
|
||||
// We can't handle any fault from other threads.
|
||||
if (!Core::IsCPUThread())
|
||||
{
|
||||
ERROR_LOG(DYNA_REC, "Exception handler - Not on CPU thread");
|
||||
DoBacktrace(access_address, ctx);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool success = false;
|
||||
|
||||
// Handle BLR stack faults, may happen in C++ code.
|
||||
uintptr_t stack = (uintptr_t)m_stack_base;
|
||||
uintptr_t diff = access_address - stack;
|
||||
if (diff >= GUARD_OFFSET && diff < GUARD_OFFSET + GUARD_SIZE)
|
||||
success = HandleStackFault();
|
||||
|
||||
// If the fault is in JIT code space, look for fastmem areas.
|
||||
if (!success && IsInSpace((u8*)ctx->CTX_PC))
|
||||
success = HandleFastmemFault(access_address, ctx);
|
||||
|
||||
if (!success)
|
||||
{
|
||||
ERROR_LOG(DYNA_REC, "Exception handler - Unhandled fault");
|
||||
DoBacktrace(access_address, ctx);
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
bool JitArm64::HandleStackFault()
|
||||
{
|
||||
if (!m_enable_blr_optimization)
|
||||
return false;
|
||||
|
||||
ERROR_LOG(POWERPC, "BLR cache disabled due to excessive BL in the emulated program.");
|
||||
m_enable_blr_optimization = false;
|
||||
#ifndef _WIN32
|
||||
Common::UnWriteProtectMemory(m_stack_base + GUARD_OFFSET, GUARD_SIZE);
|
||||
#endif
|
||||
GetBlockCache()->InvalidateICache(0, 0xffffffff, true);
|
||||
CoreTiming::ForceExceptionCheck(0);
|
||||
m_cleanup_after_stackfault = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void JitArm64::ClearCache()
|
||||
{
|
||||
m_fault_to_handler.clear();
|
||||
|
@ -550,6 +601,16 @@ void JitArm64::SingleStep()
|
|||
|
||||
void JitArm64::Jit(u32)
|
||||
{
|
||||
if (m_cleanup_after_stackfault)
|
||||
{
|
||||
ClearCache();
|
||||
m_cleanup_after_stackfault = false;
|
||||
#ifdef _WIN32
|
||||
// The stack is in an invalid state with no guard page, reset it.
|
||||
_resetstkoflw();
|
||||
#endif
|
||||
}
|
||||
|
||||
if (IsAlmostFull() || farcode.IsAlmostFull() || SConfig::GetInstance().bJITNoBlockCache)
|
||||
{
|
||||
ClearCache();
|
||||
|
|
|
@ -29,6 +29,9 @@ public:
|
|||
JitBaseBlockCache* GetBlockCache() override { return &blocks; }
|
||||
bool IsInCodeSpace(const u8* ptr) const { return IsInSpace(ptr); }
|
||||
bool HandleFault(uintptr_t access_address, SContext* ctx) override;
|
||||
void DoBacktrace(uintptr_t access_address, SContext* ctx);
|
||||
bool HandleStackFault() override;
|
||||
bool HandleFastmemFault(uintptr_t access_address, SContext* ctx);
|
||||
|
||||
void ClearCache() override;
|
||||
|
||||
|
@ -188,6 +191,7 @@ private:
|
|||
bool m_supports_cycle_counter;
|
||||
|
||||
bool m_enable_blr_optimization;
|
||||
bool m_cleanup_after_stackfault = false;
|
||||
u8* m_stack_base = nullptr;
|
||||
u8* m_stack_pointer = nullptr;
|
||||
u8* m_saved_stack_pointer = nullptr;
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
|
||||
using namespace Arm64Gen;
|
||||
|
||||
static void DoBacktrace(uintptr_t access_address, SContext* ctx)
|
||||
void JitArm64::DoBacktrace(uintptr_t access_address, SContext* ctx)
|
||||
{
|
||||
for (int i = 0; i < 30; i += 2)
|
||||
ERROR_LOG(DYNA_REC, "R%d: 0x%016llx\tR%d: 0x%016llx", i, ctx->CTX_REG(i), i + 1,
|
||||
|
@ -283,17 +283,8 @@ void JitArm64::EmitBackpatchRoutine(u32 flags, bool fastmem, bool do_farcode, AR
|
|||
}
|
||||
}
|
||||
|
||||
bool JitArm64::HandleFault(uintptr_t access_address, SContext* ctx)
|
||||
bool JitArm64::HandleFastmemFault(uintptr_t access_address, SContext* ctx)
|
||||
{
|
||||
if (!IsInSpace((u8*)ctx->CTX_PC))
|
||||
{
|
||||
ERROR_LOG(DYNA_REC, "Backpatch location not within codespace 0x%016llx(0x%08x)", ctx->CTX_PC,
|
||||
Common::swap32(*(u32*)ctx->CTX_PC));
|
||||
|
||||
DoBacktrace(access_address, ctx);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!(access_address >= (uintptr_t)Memory::physical_base &&
|
||||
access_address < (uintptr_t)Memory::physical_base + 0x100010000) &&
|
||||
!(access_address >= (uintptr_t)Memory::logical_base &&
|
||||
|
@ -302,8 +293,6 @@ bool JitArm64::HandleFault(uintptr_t access_address, SContext* ctx)
|
|||
ERROR_LOG(DYNA_REC,
|
||||
"Exception handler - access below memory space. PC: 0x%016llx 0x%016lx < 0x%016lx",
|
||||
ctx->CTX_PC, access_address, (uintptr_t)Memory::physical_base);
|
||||
|
||||
DoBacktrace(access_address, ctx);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue