mirror of
https://github.com/hrydgard/ppsspp.git
synced 2025-03-03 03:27:19 +00:00
riscv: Implement basic crash handler.
Tested by letting it recover non-guest crashes.
This commit is contained in:
parent
f6c26ecac0
commit
4fa071e78a
@ -168,6 +168,17 @@ typedef sigcontext SContext;
|
||||
#define CTX_PC arm_pc
|
||||
#define CTX_REG(x) regs[x]
|
||||
|
||||
#elif PPSSPP_ARCH(RISCV64)
|
||||
|
||||
#include <ucontext.h>
|
||||
typedef mcontext_t SContext;
|
||||
|
||||
#define MACHINE_CONTEXT_SUPPORTED
|
||||
|
||||
#define CTX_REG(x) __gregs[x]
|
||||
#define CTX_PC CTX_REG(0)
|
||||
#define CTX_SP CTX_REG(2)
|
||||
|
||||
#else
|
||||
|
||||
// No context definition for architecture
|
||||
|
@ -172,6 +172,68 @@ bool HandleFault(uintptr_t hostAddress, void *ctx) {
|
||||
// To ignore the access, we need to disassemble the instruction and modify context->CTX_PC
|
||||
ArmLSInstructionInfo info{};
|
||||
success = ArmAnalyzeLoadStore((uint32_t)codePtr, word, &info);
|
||||
#elif PPSSPP_ARCH(RISCV64)
|
||||
// TODO: Put in a disassembler.
|
||||
struct RiscVLSInstructionInfo {
|
||||
int instructionSize;
|
||||
bool isIntegerLoadStore;
|
||||
bool isFPLoadStore;
|
||||
int size;
|
||||
bool isMemoryWrite;
|
||||
};
|
||||
|
||||
uint32_t word;
|
||||
memcpy(&word, codePtr, 4);
|
||||
|
||||
RiscVLSInstructionInfo info{};
|
||||
// Compressed instructions have low bits 00, 01, or 10.
|
||||
info.instructionSize = (word & 3) == 3 ? 4 : 2;
|
||||
instructionSize = info.instructionSize;
|
||||
|
||||
success = true;
|
||||
switch (word & 0x7F) {
|
||||
case 3:
|
||||
info.isIntegerLoadStore = true;
|
||||
info.size = 1 << ((word >> 12) & 3);
|
||||
break;
|
||||
case 7:
|
||||
info.isFPLoadStore = true;
|
||||
info.size = 1 << ((word >> 12) & 3);
|
||||
break;
|
||||
case 35:
|
||||
info.isIntegerLoadStore = true;
|
||||
info.isMemoryWrite = true;
|
||||
info.size = 1 << ((word >> 12) & 3);
|
||||
break;
|
||||
case 39:
|
||||
info.isFPLoadStore = true;
|
||||
info.isMemoryWrite = true;
|
||||
info.size = 1 << ((word >> 12) & 3);
|
||||
break;
|
||||
default:
|
||||
// Compressed instruction.
|
||||
switch (word & 0x6003) {
|
||||
case 0x4000:
|
||||
case 0x4002:
|
||||
case 0x6000:
|
||||
case 0x6002:
|
||||
info.isIntegerLoadStore = true;
|
||||
info.size = (word & 0x2000) != 0 ? 8 : 4;
|
||||
info.isMemoryWrite = (word & 0x8000) != 0;
|
||||
break;
|
||||
case 0x2000:
|
||||
case 0x2002:
|
||||
info.isFPLoadStore = true;
|
||||
info.size = 8;
|
||||
info.isMemoryWrite = (word & 0x8000) != 0;
|
||||
break;
|
||||
default:
|
||||
// Not a read or a write.
|
||||
success = false;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
std::string disassembly;
|
||||
@ -204,6 +266,7 @@ bool HandleFault(uintptr_t hostAddress, void *ctx) {
|
||||
|
||||
g_lastMemoryExceptionType = type;
|
||||
|
||||
bool handled = true;
|
||||
if (success && (g_Config.bIgnoreBadMemAccess || g_ignoredAddresses.find(codePtr) != g_ignoredAddresses.end())) {
|
||||
if (!info.isMemoryWrite) {
|
||||
// It was a read. Fill the destination register with 0.
|
||||
@ -224,12 +287,15 @@ bool HandleFault(uintptr_t hostAddress, void *ctx) {
|
||||
g_lastCrashAddress = codePtr;
|
||||
|
||||
// Redirect execution to a crash handler that will switch to CoreState::CORE_RUNTIME_ERROR immediately.
|
||||
context->CTX_PC = (uintptr_t)MIPSComp::jit->GetCrashHandler();
|
||||
if (MIPSComp::jit)
|
||||
context->CTX_PC = (uintptr_t)MIPSComp::jit->GetCrashHandler();
|
||||
else
|
||||
handled = false;
|
||||
ERROR_LOG(MEMMAP, "Bad memory access detected! %08x (%p) Stopping emulation. Info:\n%s", guestAddress, (void *)hostAddress, infoString.c_str());
|
||||
}
|
||||
|
||||
inCrashHandler = false;
|
||||
return true;
|
||||
return handled;
|
||||
}
|
||||
|
||||
#else
|
||||
|
Loading…
x
Reference in New Issue
Block a user