MCPcopy Create free account
hub / github.com/FEX-Emu/FEX / ResetToConsistentStateImpl

Function ResetToConsistentStateImpl

Source/Windows/ARM64EC/Module.cpp:729–801  ·  view source on GitHub ↗

Returns true if exception dispatch should be halted and the execution context restored to NativeContext

Source from the content-addressed store, hash-verified

727
728// Returns true if exception dispatch should be halted and the execution context restored to NativeContext
729bool ResetToConsistentStateImpl(EXCEPTION_RECORD* Exception, CONTEXT* GuestContext, ARM64_NT_CONTEXT* NativeContext) {
730 const auto CPUArea = GetCPUArea();
731 auto Thread = CPUArea.ThreadState();
732 FEXCORE_PROFILE_ACCUMULATION(Thread, AccumulatedSignalTime);
733 LogMan::Msg::DFmt("Exception: Code: {:X} Address: {:X}", Exception->ExceptionCode, reinterpret_cast<uintptr_t>(Exception->ExceptionAddress));
734
735 if (NativeContext->Pc == reinterpret_cast<uint64_t>(&ExitFunctionSuspendPoint)) {
736 // A suspend interrupt can occur in ExitFunctionEC before InSimulation is unset and set SuspendDoorbell. If this
737 // occurs then it is still our duty to cooperatively suspend with an appropriate context. To support this, after
738 // unsetting InSimulation a brk #0xCAFE instruction will be raised that we can handle here.
739 NativeContext->Pc += 4; // Skip over the brk instruction when we resume
740 *CPUArea.Area->SuspendDoorbell = 0;
741 return true;
742 }
743
744 if (Exception->ExceptionCode == EXCEPTION_ACCESS_VIOLATION) {
745 const auto FaultAddress = static_cast<uint64_t>(Exception->ExceptionInformation[1]);
746
747 if (FEX::Windows::CallRetStack::HandleAccessViolation(Thread, FaultAddress, NativeContext->X17)) {
748 return true;
749 }
750
751 std::scoped_lock Lock(ThreadCreationMutex);
752 if (InvalidationTracker && InvalidationTracker->HandleRWXAccessViolation(Thread, NativeContext->Pc, FaultAddress)) {
753 FEXCORE_PROFILE_INSTANT_INCREMENT(Thread, AccumulatedSMCCount, 1);
754 if (CTX->IsAddressInCodeBuffer(Thread, NativeContext->Pc) && !CTX->IsCurrentBlockSingleInst(CPUArea.ThreadState()) &&
755 CTX->IsAddressInCurrentBlock(Thread, FaultAddress & FEXCore::Utils::FEX_PAGE_MASK, FEXCore::Utils::FEX_PAGE_SIZE)) {
756 // 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.
757 Exception::ReconstructThreadState(Thread, *NativeContext);
758 LogMan::Msg::DFmt("Handled inline self-modifying code: pc: {:X} rip: {:X} fault: {:X}", NativeContext->Pc,
759 Thread->CurrentFrame->State.rip, FaultAddress);
760 NativeContext->Pc = CPUArea.DispatcherLoopTopEnterECFillSRA();
761 NativeContext->Sp = CPUArea.EmulatorStackBase();
762 NativeContext->X11 = 1; // Set ENTRY_FILL_SRA_SINGLE_INST_REG to force a single step
763 NativeContext->X17 = reinterpret_cast<uint64_t>(CPUArea.Area); // Set EC_ENTRY_CPUAREA_REG
764 } else {
765 LogMan::Msg::DFmt("Handled self-modifying code: pc: {:X} fault: {:X}", NativeContext->Pc, FaultAddress);
766 }
767
768 return true;
769 }
770 }
771
772 if (!CTX->IsAddressInCodeBuffer(Thread, NativeContext->Pc) && !IsDispatcherAddress(NativeContext->Pc)) {
773 LogMan::Msg::DFmt("Passing through exception");
774 return false;
775 }
776
777 if (Exception->ExceptionCode == EXCEPTION_DATATYPE_MISALIGNMENT && Exception::HandleUnalignedAccess(*NativeContext)) {
778 LogMan::Msg::DFmt("Handled unaligned atomic: new pc: {:X}", NativeContext->Pc);
779 return true;
780 }
781
782 // The JIT (in CompileBlock) emits code to check the suspend doorbell at the start of every block, and run the following instruction if it is set:
783 static constexpr uint32_t SuspendTrapMagic {0xD4395FC0}; // brk #0xCAFE
784 if (Exception->ExceptionCode == EXCEPTION_ILLEGAL_INSTRUCTION && *reinterpret_cast<uint32_t*>(NativeContext->Pc) == SuspendTrapMagic) {
785 Exception::ReconstructThreadState(Thread, *NativeContext);
786 *NativeContext = Exception::StoreStateToPackedECContext(Thread, NativeContext->Fpcr, NativeContext->Fpsr);

Callers 1

ResetToConsistentStateFunction · 0.85

Calls 14

GetCPUAreaFunction · 0.85
DFmtFunction · 0.85
HandleAccessViolationFunction · 0.85
IsEmulatorStackAddressFunction · 0.85
RethrowGuestExceptionFunction · 0.85
EFmtFunction · 0.85
ReconstructThreadStateFunction · 0.70
IsDispatcherAddressFunction · 0.70

Tested by

no test coverage detected