From 573d0858ac0acc04ec9f5ff5f10452c4041507fa Mon Sep 17 00:00:00 2001 From: Billy Laws Date: Tue, 22 Jul 2025 19:04:12 +0100 Subject: [PATCH] ARM64EC: Fix inline SMC handling for writes in the same page as the current block Consider a page with two blocks in it, A and B. Block A performs SMC on B then A. With the previous logic, the SMC write of B would unprotect the page and then the inline SMC touching A would not be detected and a single-step would not be forced. --- Source/Windows/ARM64EC/Module.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Source/Windows/ARM64EC/Module.cpp b/Source/Windows/ARM64EC/Module.cpp index 69c482c4b..0d1fdd4bc 100644 --- a/Source/Windows/ARM64EC/Module.cpp +++ b/Source/Windows/ARM64EC/Module.cpp @@ -709,8 +709,8 @@ bool ResetToConsistentStateImpl(EXCEPTION_RECORD* Exception, CONTEXT* GuestConte if (InvalidationTracker && InvalidationTracker->HandleRWXAccessViolation(FaultAddress)) { FEXCORE_PROFILE_INSTANT_INCREMENT(Thread, AccumulatedSMCCount, 1); if (CTX->IsAddressInCodeBuffer(Thread, NativeContext->Pc) && !CTX->IsCurrentBlockSingleInst(CPUArea.ThreadState()) && - CTX->IsAddressInCurrentBlock(Thread, FaultAddress, 8)) { - // If we are not patching ourself (single inst block case) and patching the current block, this is inline SMC. Reconstruct the current context (before the SMC write) then single step the write to reduce it to regular SMC. + CTX->IsAddressInCurrentBlock(Thread, FaultAddress & FEXCore::Utils::FEX_PAGE_MASK, FEXCore::Utils::FEX_PAGE_SIZE)) { + // If we are not patching ourself (single inst block case) and potentially patching the current block, this is inline SMC. Reconstruct the current context (before the SMC write) then single step the write to reduce it to regular SMC. Exception::ReconstructThreadState(Thread, *NativeContext); LogMan::Msg::DFmt("Handled inline self-modifying code: pc: {:X} rip: {:X} fault: {:X}", NativeContext->Pc, Thread->CurrentFrame->State.rip, FaultAddress);