mirror of
https://github.com/FEX-Emu/FEX.git
synced 2026-10-28 09:00:52 +01:00
FEXCore: Implement a write+code invalidate IR op for mono SMC
This commit is contained in:
1 parent
da3b7f5a41
commit
afa1327242
6 files changed
+71
No files matched your search
@@ -260,6 +260,10 @@ public:
|
||||
|
||||
static void ThreadRemoveCodeEntryFromJit(FEXCore::Core::CpuStateFrame* Frame, uint64_t GuestRIP);
|
||||
|
||||
// This is used as a replacement for the SMC writes in the mono callsite backpatcher that avoids atomic operations
|
||||
// (safe as the invalidation mutex is locked) and manually invalidates the modified range. Allowing SMC to be detected
|
||||
// even if faulting is disabled.
|
||||
static void MonoBackpatcherWrite(FEXCore::Core::CpuStateFrame* Frame, uint8_t Size, uint64_t Address, uint64_t Value);
|
||||
|
||||
void RemoveCustomIREntrypoint(uintptr_t Entrypoint);
|
||||
|
||||
|
||||
@@ -1096,6 +1096,24 @@ void ContextImpl::RemoveCustomIREntrypoint(uintptr_t Entrypoint) {
|
||||
HasCustomIRHandlers = !CustomIRHandlers.empty();
|
||||
}
|
||||
|
||||
void ContextImpl::MonoBackpatcherWrite(FEXCore::Core::CpuStateFrame* Frame, uint8_t Size, uint64_t Address, uint64_t Value) {
|
||||
auto Thread = Frame->Thread;
|
||||
auto CTX = static_cast<ContextImpl*>(Thread->CTX);
|
||||
{
|
||||
auto lk = GuardSignalDeferringSection(CTX->CodeInvalidationMutex, Thread);
|
||||
|
||||
if (Size == 8) {
|
||||
*reinterpret_cast<uint64_t *>(Address) = Value;
|
||||
} else if (Size == 4) {
|
||||
*reinterpret_cast<uint32_t *>(Address) = Value;
|
||||
} else {
|
||||
ERROR_AND_DIE_FMT("Unexpected write size for backpatcher: {}", Size);
|
||||
}
|
||||
}
|
||||
|
||||
CTX->SyscallHandler->InvalidateGuestCodeRange(Thread, Address, Size);
|
||||
}
|
||||
|
||||
IR::AOTIRCacheEntry* ContextImpl::LoadAOTIRCacheEntry(const fextl::string& filename) {
|
||||
auto rv = IRCaptureCache.LoadAOTIRCacheEntry(filename);
|
||||
return rv;
|
||||
|
||||
@@ -639,6 +639,7 @@ Arm64JITCore::Arm64JITCore(FEXCore::Context::ContextImpl* ctx, FEXCore::Core::In
|
||||
Common.PrintValue = reinterpret_cast<uint64_t>(PrintValue);
|
||||
Common.PrintVectorValue = reinterpret_cast<uint64_t>(PrintVectorValue);
|
||||
Common.ThreadRemoveCodeEntryFromJIT = reinterpret_cast<uintptr_t>(&Context::ContextImpl::ThreadRemoveCodeEntryFromJit);
|
||||
Common.MonoBackpatcherWrite = reinterpret_cast<uint64_t>(&Context::ContextImpl::MonoBackpatcherWrite);
|
||||
Common.CPUIDObj = reinterpret_cast<uint64_t>(&CTX->CPUID);
|
||||
|
||||
{
|
||||
|
||||
@@ -286,4 +286,43 @@ DEF_OP(Yield) {
|
||||
yield();
|
||||
}
|
||||
|
||||
DEF_OP(MonoBackpatcherWrite) {
|
||||
auto Op = IROp->C<IR::IROp_MonoBackpatcherWrite>();
|
||||
|
||||
mov(ARMEmitter::Size::i64Bit, TMP3, GetReg(Op->Addr));
|
||||
mov(ARMEmitter::Size::i64Bit, TMP4, GetReg(Op->Value));
|
||||
|
||||
PushDynamicRegs(TMP1);
|
||||
SpillStaticRegs(TMP1);
|
||||
|
||||
mov(ARMEmitter::Size::i64Bit, ARMEmitter::Reg::r0, STATE.R());
|
||||
mov(ARMEmitter::Size::i64Bit, ARMEmitter::Reg::r1, IR::OpSizeToSize(Op->Size));
|
||||
|
||||
if (!TMP_ABIARGS) {
|
||||
mov(ARMEmitter::Size::i64Bit, ARMEmitter::Reg::r2, TMP3);
|
||||
mov(ARMEmitter::Size::i64Bit, ARMEmitter::Reg::r3, TMP4);
|
||||
}
|
||||
|
||||
#ifdef _M_ARM_64EC
|
||||
ldr(TMP2, ARMEmitter::XReg::x18, TEB_CPU_AREA_OFFSET);
|
||||
LoadConstant(ARMEmitter::Size::i32Bit, TMP1, 1);
|
||||
strb(TMP1.W(), TMP2, CPU_AREA_IN_SYSCALL_CALLBACK_OFFSET);
|
||||
#endif
|
||||
|
||||
ldr(ARMEmitter::XReg::x4, STATE, offsetof(FEXCore::Core::CpuStateFrame, Pointers.Common.MonoBackpatcherWrite));
|
||||
if (!CTX->Config.DisableVixlIndirectCalls) [[unlikely]] {
|
||||
GenerateIndirectRuntimeCall<void, void*, uint8_t, uint64_t, uint64_t>(ARMEmitter::Reg::r4);
|
||||
} else {
|
||||
blr(ARMEmitter::Reg::r4);
|
||||
}
|
||||
|
||||
#ifdef _M_ARM_64EC
|
||||
ldr(TMP2, ARMEmitter::XReg::x18, TEB_CPU_AREA_OFFSET);
|
||||
strb(ARMEmitter::WReg::zr, TMP2, CPU_AREA_IN_SYSCALL_CALLBACK_OFFSET);
|
||||
#endif
|
||||
|
||||
FillStaticRegs();
|
||||
PopDynamicRegs();
|
||||
}
|
||||
|
||||
} // namespace FEXCore::CPU
|
||||
@@ -291,6 +291,14 @@
|
||||
"Desc": [
|
||||
"Implement a low power wait attempting to sleep until RDTSC >= Upper:Lower.",
|
||||
"Will spuriously wake up."
|
||||
]
|
||||
},
|
||||
"MonoBackpatcherWrite OpSize:$Size, GPR:$Value, GPR:$Addr": {
|
||||
"HasSideEffects": true,
|
||||
"Desc": [ "Writes and invalidates the target address with the invalidation mutex locked. This is a fault-avoiding",
|
||||
"replacement for the atomic SMC writes used in the mono callsite backpatcher." ],
|
||||
"EmitValidation": [
|
||||
"Size == FEXCore::IR::OpSize::i32Bit || Size == FEXCore::IR::OpSize::i64Bit"
|
||||
]
|
||||
}
|
||||
},
|
||||
|
||||
@@ -305,6 +305,7 @@ struct JITPointers {
|
||||
uint64_t SyscallHandlerObj {};
|
||||
uint64_t SyscallHandlerFunc {};
|
||||
uint64_t ExitFunctionLink {};
|
||||
uint64_t MonoBackpatcherWrite {};
|
||||
|
||||
// Handles returning/calling ARM64EC code from the JIT, expects the target PC in TMP3
|
||||
uint64_t ExitFunctionEC {};
|
||||
|
||||
Reference in new issue
Block a user