From e44415050634dfa73a2492ea4722915583df5191 Mon Sep 17 00:00:00 2001 From: Jan Vorlicek Date: Thu, 21 Jul 2022 18:09:34 -0700 Subject: [PATCH 1/3] Fix x64 and x86 emulation on arm64 Windows The runtime was hanging or crashing when running on x64 and x86 emulation on Windows ARM64. Most of these failures were caused by missing cache flushes after code updates where the emulator kept executing arm64 code that it has jitted from the previous state of the code. There were also two CONTEXT related issues. One was that we were assuming that AVX state is always supported. However, the emulator doesn't support it, so SetXStateFeaturesMask(pCtx, XSTATE_MASK_AVX) was failing and we have considered that a failure to capture thread context. The other one was that we have assumed that the CONTEXT we get in Thread::RedirectCurrentThreadAtHandledJITCase is CONTEXT_COMPLETE, but with the emulation, we one get CONTEXT_FULL, that means CONTEXT_COMPLETE without the debug registers. There were also two CoreCLR tests issues that caused failures under the emulation, I have fixed those. --- src/coreclr/vm/amd64/cgenamd64.cpp | 3 ++- src/coreclr/vm/amd64/jitinterfaceamd64.cpp | 1 + src/coreclr/vm/comcallablewrapper.cpp | 1 + src/coreclr/vm/i386/cgenx86.cpp | 4 +-- src/coreclr/vm/i386/jitinterfacex86.cpp | 26 +++++++++++++++---- src/coreclr/vm/jitinterface.cpp | 2 +- src/coreclr/vm/threadsuspend.cpp | 4 +-- .../HardwareIntrinsics/X86/X86Base/CpuId.cs | 5 ++-- .../JitBlue/Runtime_34587/Runtime_34587.cs | 4 +-- 9 files changed, 35 insertions(+), 15 deletions(-) diff --git a/src/coreclr/vm/amd64/cgenamd64.cpp b/src/coreclr/vm/amd64/cgenamd64.cpp index ec0f890071c7ac..bee362d140451b 100644 --- a/src/coreclr/vm/amd64/cgenamd64.cpp +++ b/src/coreclr/vm/amd64/cgenamd64.cpp @@ -548,6 +548,7 @@ void UMEntryThunkCode::Encode(UMEntryThunkCode *pEntryThunkCodeRX, BYTE* pTarget m_jmpRAX[2] = 0xE0; _ASSERTE(DbgIsExecutable(&pEntryThunkCodeRX->m_movR10[0], &pEntryThunkCodeRX->m_jmpRAX[3]-&pEntryThunkCodeRX->m_movR10[0])); + FlushInstructionCache(GetCurrentProcess(),pEntryThunkCodeRX,sizeof(UMEntryThunkCode)); } void UMEntryThunkCode::Poison() @@ -574,7 +575,7 @@ void UMEntryThunkCode::Poison() pThisRW->m_movR10[1] = 0xBF; #endif - ClrFlushInstructionCache(&m_movR10[0], &m_jmpRAX[3]-&m_movR10[0]); + FlushInstructionCache(GetCurrentProcess(), &m_movR10[0], &m_jmpRAX[3]-&m_movR10[0]); } UMEntryThunk* UMEntryThunk::Decode(LPVOID pCallback) diff --git a/src/coreclr/vm/amd64/jitinterfaceamd64.cpp b/src/coreclr/vm/amd64/jitinterfaceamd64.cpp index 02b023777b8a94..9714893cce0999 100644 --- a/src/coreclr/vm/amd64/jitinterfaceamd64.cpp +++ b/src/coreclr/vm/amd64/jitinterfaceamd64.cpp @@ -296,6 +296,7 @@ int WriteBarrierManager::ChangeWriteBarrierTo(WriteBarrierType newWriteBarrier, { ExecutableWriterHolder writeBarrierWriterHolder(GetWriteBarrierCodeLocation((void*)JIT_WriteBarrier), GetCurrentWriteBarrierSize()); memcpy(writeBarrierWriterHolder.GetRW(), (LPVOID)GetCurrentWriteBarrierCode(), GetCurrentWriteBarrierSize()); + stompWBCompleteActions |= SWB_ICACHE_FLUSH; } switch (newWriteBarrier) diff --git a/src/coreclr/vm/comcallablewrapper.cpp b/src/coreclr/vm/comcallablewrapper.cpp index 724a72ec50134f..48103f1ac39c86 100644 --- a/src/coreclr/vm/comcallablewrapper.cpp +++ b/src/coreclr/vm/comcallablewrapper.cpp @@ -566,6 +566,7 @@ extern "C" PCODE ComPreStubWorker(ComPrestubMethodFrame *pPFrame, UINT64 *pError #else *ppofsWriterHolder.GetRW() = ((UINT_PTR)pStub); #endif + FlushInstructionCache(GetCurrentProcess(), ppofs, sizeof(UINT_PTR)); // Return the address of the prepad. The prepad will regenerate the hidden parameter and due // to the update above will execute the new stub code the second time around. diff --git a/src/coreclr/vm/i386/cgenx86.cpp b/src/coreclr/vm/i386/cgenx86.cpp index 287dd810f90e71..0da059cede4326 100644 --- a/src/coreclr/vm/i386/cgenx86.cpp +++ b/src/coreclr/vm/i386/cgenx86.cpp @@ -1157,7 +1157,7 @@ void UMEntryThunkCode::Encode(UMEntryThunkCode *pEntryThunkCodeRX, BYTE* pTarget m_jmp = X86_INSTR_JMP_REL32; m_execstub = (BYTE*) ((pTargetCode) - (4+((BYTE*)&pEntryThunkCodeRX->m_execstub))); - FlushInstructionCache(GetCurrentProcess(),pEntryThunkCodeRX->GetEntryPoint(),sizeof(UMEntryThunkCode)); + FlushInstructionCache(GetCurrentProcess(),pEntryThunkCodeRX->GetEntryPoint(),sizeof(UMEntryThunkCode) - GetEntryPointOffset()); } void UMEntryThunkCode::Poison() @@ -1172,7 +1172,7 @@ void UMEntryThunkCode::Poison() // mov ecx, imm32 pThisRW->m_movEAX = 0xb9; - ClrFlushInstructionCache(GetEntryPoint(),sizeof(UMEntryThunkCode)); + FlushInstructionCache(GetCurrentProcess(), GetEntryPoint(),sizeof(UMEntryThunkCode) - GetEntryPointOffset()); } UMEntryThunk* UMEntryThunk::Decode(LPVOID pCallback) diff --git a/src/coreclr/vm/i386/jitinterfacex86.cpp b/src/coreclr/vm/i386/jitinterfacex86.cpp index 82782d86c2bf62..4961f5fdc7efb7 100644 --- a/src/coreclr/vm/i386/jitinterfacex86.cpp +++ b/src/coreclr/vm/i386/jitinterfacex86.cpp @@ -1326,7 +1326,11 @@ int StompWriteBarrierResize(bool isRuntimeSuspended, bool bReqUpperBoundsCheck) // cmp offset[edx], 0ffh instruction _ASSERTE(pBuf[22] == 0x80); pfunc = (size_t *) &pBufRW[PostGrow_CardTableFirstLocation]; - *pfunc = (size_t) g_card_table; + if (*pfunc != (size_t) g_card_table) + { + stompWBCompleteActions |= SWB_ICACHE_FLUSH; + *pfunc = (size_t) g_card_table; + } // What we're trying to update is the offset field of a // mov offset[edx], 0ffh instruction @@ -1341,7 +1345,11 @@ int StompWriteBarrierResize(bool isRuntimeSuspended, bool bReqUpperBoundsCheck) // cmp offset[edx], 0ffh instruction _ASSERTE(pBuf[14] == 0x80); pfunc = (size_t *) &pBufRW[PreGrow_CardTableFirstLocation]; - *pfunc = (size_t) g_card_table; + if (*pfunc != (size_t) g_card_table) + { + stompWBCompleteActions |= SWB_ICACHE_FLUSH; + *pfunc = (size_t) g_card_table; + } // What we're trying to update is the offset field of a @@ -1357,7 +1365,11 @@ int StompWriteBarrierResize(bool isRuntimeSuspended, bool bReqUpperBoundsCheck) // cmp offset[edx], 0ffh instruction _ASSERTE(pBuf[22] == 0x80); pfunc = (size_t *) &pBufRW[PostGrow_CardTableFirstLocation]; - *pfunc = (size_t) g_card_table; + if (*pfunc != (size_t) g_card_table) + { + stompWBCompleteActions |= SWB_ICACHE_FLUSH; + *pfunc = (size_t) g_card_table; + } // What we're trying to update is the offset field of a // mov offset[edx], 0ffh instruction @@ -1366,7 +1378,11 @@ int StompWriteBarrierResize(bool isRuntimeSuspended, bool bReqUpperBoundsCheck) } // Stick in the adjustment value. - *pfunc = (size_t) g_card_table; + if (*pfunc != (size_t) g_card_table) + { + stompWBCompleteActions |= SWB_ICACHE_FLUSH; + *pfunc = (size_t) g_card_table; + } } if (bStompWriteBarrierEphemeral) @@ -1379,7 +1395,7 @@ int StompWriteBarrierResize(bool isRuntimeSuspended, bool bReqUpperBoundsCheck) void FlushWriteBarrierInstructionCache() { - FlushInstructionCache(GetCurrentProcess(), (void *)JIT_PatchedWriteBarrierGroup, + FlushInstructionCache(GetCurrentProcess(), (void *)GetWriteBarrierCodeLocation(JIT_PatchedWriteBarrierGroup), (BYTE*)JIT_PatchedWriteBarrierGroup_End - (BYTE*)JIT_PatchedWriteBarrierGroup); } diff --git a/src/coreclr/vm/jitinterface.cpp b/src/coreclr/vm/jitinterface.cpp index 78a439d4332af1..7a061a2aaa975d 100644 --- a/src/coreclr/vm/jitinterface.cpp +++ b/src/coreclr/vm/jitinterface.cpp @@ -12996,7 +12996,7 @@ PCODE UnsafeJitFunction(PrepareCodeConfig* config, //DbgPrintf("Jitted Entry at" FMT_ADDR "method %s::%s %s size %08x\n", DBG_ADDR(nativeEntry), // pszDebugClassName, pszDebugMethodName, pszDebugMethodSignature, sizeOfCode); - ClrFlushInstructionCache(nativeEntry, sizeOfCode); + FlushInstructionCache(GetCurrentProcess(), nativeEntry, sizeOfCode); ret = (PCODE)nativeEntry; #ifdef TARGET_ARM diff --git a/src/coreclr/vm/threadsuspend.cpp b/src/coreclr/vm/threadsuspend.cpp index 89e5598a10e139..0f79790365b23e 100644 --- a/src/coreclr/vm/threadsuspend.cpp +++ b/src/coreclr/vm/threadsuspend.cpp @@ -2877,7 +2877,7 @@ BOOL Thread::RedirectThreadAtHandledJITCase(PFN_REDIRECTTARGET pTgt) // This should not normally fail. // The system silently ignores any feature specified in the FeatureMask // which is not enabled on the processor. - bRes &= SetXStateFeaturesMask(pCtx, XSTATE_MASK_AVX); + SetXStateFeaturesMask(pCtx, XSTATE_MASK_AVX); #endif //defined(TARGET_X86) || defined(TARGET_AMD64) // Make sure we specify CONTEXT_EXCEPTION_REQUEST to detect "trap frame reporting". @@ -2978,7 +2978,7 @@ BOOL Thread::RedirectCurrentThreadAtHandledJITCase(PFN_REDIRECTTARGET pTgt, CONT _ASSERTE(PreemptiveGCDisabledOther()); _ASSERTE(IsAddrOfRedirectFunc(pTgt)); _ASSERTE(pCurrentThreadCtx); - _ASSERTE((pCurrentThreadCtx->ContextFlags & CONTEXT_COMPLETE) == CONTEXT_COMPLETE); + _ASSERTE((pCurrentThreadCtx->ContextFlags & CONTEXT_FULL) == CONTEXT_FULL); _ASSERTE(ExecutionManager::IsManagedCode(GetIP(pCurrentThreadCtx))); //////////////////////////////////////////////////////////////// diff --git a/src/tests/JIT/HardwareIntrinsics/X86/X86Base/CpuId.cs b/src/tests/JIT/HardwareIntrinsics/X86/X86Base/CpuId.cs index 39dd182e4e0bf8..abccb0846a8ae5 100644 --- a/src/tests/JIT/HardwareIntrinsics/X86/X86Base/CpuId.cs +++ b/src/tests/JIT/HardwareIntrinsics/X86/X86Base/CpuId.cs @@ -28,11 +28,12 @@ static unsafe int Main(string[] args) bool isAuthenticAmd = (ebx == 0x68747541) && (ecx == 0x444D4163) && (edx == 0x69746E65); bool isGenuineIntel = (ebx == 0x756E6547) && (ecx == 0x6C65746E) && (edx == 0x49656E69); + bool isVirtualCPU = (ebx == 0x74726956) && (ecx == 0x20555043) && (edx == 0x206C6175); - if (!isAuthenticAmd && !isGenuineIntel) + if (!isAuthenticAmd && !isGenuineIntel && !isVirtualCPU) { // CPUID checks are vendor specific and aren't guaranteed to match up, even across Intel/AMD - // as such, we limit ourselves to just AuthenticAMD and GenuineIntel right now. Any other + // as such, we limit ourselves to just AuthenticAMD, GenuineIntel and "Virtual CPU" right now. Any other // vendors would need to be validated against the checks below and added to the list as necessary. // An example of a difference is Intel/AMD for LZCNT. While the same underlying bit is used to diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_34587/Runtime_34587.cs b/src/tests/JIT/Regression/JitBlue/Runtime_34587/Runtime_34587.cs index 03f5e08eba07fa..ae15bf382bbd2a 100644 --- a/src/tests/JIT/Regression/JitBlue/Runtime_34587/Runtime_34587.cs +++ b/src/tests/JIT/Regression/JitBlue/Runtime_34587/Runtime_34587.cs @@ -422,13 +422,13 @@ static bool ValidateX86Base() if (X86BaseIsSupported) { - succeeded &= (RuntimeInformation.OSArchitecture == Architecture.X86) || (RuntimeInformation.OSArchitecture == Architecture.X64); + succeeded &= (RuntimeInformation.ProcessArchitecture == Architecture.X86) || (RuntimeInformation.ProcessArchitecture == Architecture.X64); } if (X86BaseX64IsSupported) { succeeded &= X86BaseIsSupported; - succeeded &= (RuntimeInformation.OSArchitecture == Architecture.X64); + succeeded &= (RuntimeInformation.ProcessArchitecture == Architecture.X64); } return succeeded; From eddbe617e056ccfdef5fbbef82587f5c7061ac7f Mon Sep 17 00:00:00 2001 From: Jan Vorlicek Date: Fri, 22 Jul 2022 15:11:05 -0700 Subject: [PATCH 2/3] Fix x86 Linux build --- src/coreclr/vm/i386/jitinterfacex86.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/coreclr/vm/i386/jitinterfacex86.cpp b/src/coreclr/vm/i386/jitinterfacex86.cpp index 4961f5fdc7efb7..e9e82b3d1cca55 100644 --- a/src/coreclr/vm/i386/jitinterfacex86.cpp +++ b/src/coreclr/vm/i386/jitinterfacex86.cpp @@ -1395,7 +1395,7 @@ int StompWriteBarrierResize(bool isRuntimeSuspended, bool bReqUpperBoundsCheck) void FlushWriteBarrierInstructionCache() { - FlushInstructionCache(GetCurrentProcess(), (void *)GetWriteBarrierCodeLocation(JIT_PatchedWriteBarrierGroup), + FlushInstructionCache(GetCurrentProcess(), GetWriteBarrierCodeLocation((BYTE*)JIT_PatchedWriteBarrierGroup), (BYTE*)JIT_PatchedWriteBarrierGroup_End - (BYTE*)JIT_PatchedWriteBarrierGroup); } From f276bcf7f99036679217ec774f96712cd09f6818 Mon Sep 17 00:00:00 2001 From: Jan Vorlicek Date: Tue, 2 Aug 2022 23:10:31 +0200 Subject: [PATCH 3/3] Add hasCodeExecutedBefore argument to ClrFlushInstructionCache --- src/coreclr/vm/amd64/cgenamd64.cpp | 2 +- src/coreclr/vm/amd64/cgencpu.h | 12 +++++++++--- src/coreclr/vm/arm/cgencpu.h | 2 +- src/coreclr/vm/arm64/cgencpu.h | 2 +- src/coreclr/vm/comcallablewrapper.cpp | 2 +- src/coreclr/vm/i386/cgencpu.h | 12 +++++++++--- src/coreclr/vm/i386/cgenx86.cpp | 4 ++-- src/coreclr/vm/i386/jitinterfacex86.cpp | 4 ++-- src/coreclr/vm/jitinterface.cpp | 3 ++- src/coreclr/vm/loongarch64/cgencpu.h | 2 +- src/coreclr/vm/precode.cpp | 3 ++- 11 files changed, 31 insertions(+), 17 deletions(-) diff --git a/src/coreclr/vm/amd64/cgenamd64.cpp b/src/coreclr/vm/amd64/cgenamd64.cpp index bee362d140451b..e510d09708e391 100644 --- a/src/coreclr/vm/amd64/cgenamd64.cpp +++ b/src/coreclr/vm/amd64/cgenamd64.cpp @@ -575,7 +575,7 @@ void UMEntryThunkCode::Poison() pThisRW->m_movR10[1] = 0xBF; #endif - FlushInstructionCache(GetCurrentProcess(), &m_movR10[0], &m_jmpRAX[3]-&m_movR10[0]); + ClrFlushInstructionCache(&m_movR10[0], &m_jmpRAX[3]-&m_movR10[0], /* hasCodeExecutedBefore */ true); } UMEntryThunk* UMEntryThunk::Decode(LPVOID pCallback) diff --git a/src/coreclr/vm/amd64/cgencpu.h b/src/coreclr/vm/amd64/cgencpu.h index b64d3282e29fc3..86e8d0f37084bd 100644 --- a/src/coreclr/vm/amd64/cgencpu.h +++ b/src/coreclr/vm/amd64/cgencpu.h @@ -534,10 +534,16 @@ DWORD GetOffsetAtEndOfFunction(ULONGLONG uImageBase, // Currently ClrFlushInstructionCache has no effect on AMD64 // -inline BOOL ClrFlushInstructionCache(LPCVOID pCodeAddr, size_t sizeOfCode) +inline BOOL ClrFlushInstructionCache(LPCVOID pCodeAddr, size_t sizeOfCode, bool hasCodeExecutedBefore = false) { - // FlushInstructionCache(GetCurrentProcess(), pCodeAddr, sizeOfCode); - MemoryBarrier(); + if (hasCodeExecutedBefore) + { + FlushInstructionCache(GetCurrentProcess(), pCodeAddr, sizeOfCode); + } + else + { + MemoryBarrier(); + } return TRUE; } diff --git a/src/coreclr/vm/arm/cgencpu.h b/src/coreclr/vm/arm/cgencpu.h index c207c5ba87814a..1017052e8ab9eb 100644 --- a/src/coreclr/vm/arm/cgencpu.h +++ b/src/coreclr/vm/arm/cgencpu.h @@ -998,7 +998,7 @@ struct HijackArgs // Currently ClrFlushInstructionCache has no effect on X86 // -inline BOOL ClrFlushInstructionCache(LPCVOID pCodeAddr, size_t sizeOfCode) +inline BOOL ClrFlushInstructionCache(LPCVOID pCodeAddr, size_t sizeOfCode, bool hasCodeExecutedBefore = false) { return FlushInstructionCache(GetCurrentProcess(), pCodeAddr, sizeOfCode); } diff --git a/src/coreclr/vm/arm64/cgencpu.h b/src/coreclr/vm/arm64/cgencpu.h index 28694df7d2b834..ea29ec2bdce028 100644 --- a/src/coreclr/vm/arm64/cgencpu.h +++ b/src/coreclr/vm/arm64/cgencpu.h @@ -277,7 +277,7 @@ inline NEON128 GetSimdMem(PCODE ip) void emitCOMStubCall (ComCallMethodDesc *pCOMMethodRX, ComCallMethodDesc *pCOMMethodRW, PCODE target); #endif // FEATURE_COMINTEROP -inline BOOL ClrFlushInstructionCache(LPCVOID pCodeAddr, size_t sizeOfCode) +inline BOOL ClrFlushInstructionCache(LPCVOID pCodeAddr, size_t sizeOfCode, bool hasCodeExecutedBefore = false) { return FlushInstructionCache(GetCurrentProcess(), pCodeAddr, sizeOfCode); } diff --git a/src/coreclr/vm/comcallablewrapper.cpp b/src/coreclr/vm/comcallablewrapper.cpp index 48103f1ac39c86..90976fcbf8c1c7 100644 --- a/src/coreclr/vm/comcallablewrapper.cpp +++ b/src/coreclr/vm/comcallablewrapper.cpp @@ -566,7 +566,7 @@ extern "C" PCODE ComPreStubWorker(ComPrestubMethodFrame *pPFrame, UINT64 *pError #else *ppofsWriterHolder.GetRW() = ((UINT_PTR)pStub); #endif - FlushInstructionCache(GetCurrentProcess(), ppofs, sizeof(UINT_PTR)); + ClrFlushInstructionCache(ppofs, sizeof(UINT_PTR), /* hasCodeExecutedBefore */ true); // Return the address of the prepad. The prepad will regenerate the hidden parameter and due // to the update above will execute the new stub code the second time around. diff --git a/src/coreclr/vm/i386/cgencpu.h b/src/coreclr/vm/i386/cgencpu.h index 1cc63b10d8b9d9..9e6024c0cb980b 100644 --- a/src/coreclr/vm/i386/cgencpu.h +++ b/src/coreclr/vm/i386/cgencpu.h @@ -501,10 +501,16 @@ struct HijackArgs // Currently ClrFlushInstructionCache has no effect on X86 // -inline BOOL ClrFlushInstructionCache(LPCVOID pCodeAddr, size_t sizeOfCode) +inline BOOL ClrFlushInstructionCache(LPCVOID pCodeAddr, size_t sizeOfCode, bool hasCodeExecutedBefore = false) { - // FlushInstructionCache(GetCurrentProcess(), pCodeAddr, sizeOfCode); - MemoryBarrier(); + if (hasCodeExecutedBefore) + { + FlushInstructionCache(GetCurrentProcess(), pCodeAddr, sizeOfCode); + } + else + { + MemoryBarrier(); + } return TRUE; } diff --git a/src/coreclr/vm/i386/cgenx86.cpp b/src/coreclr/vm/i386/cgenx86.cpp index 0da059cede4326..356dab119f78b0 100644 --- a/src/coreclr/vm/i386/cgenx86.cpp +++ b/src/coreclr/vm/i386/cgenx86.cpp @@ -1157,7 +1157,7 @@ void UMEntryThunkCode::Encode(UMEntryThunkCode *pEntryThunkCodeRX, BYTE* pTarget m_jmp = X86_INSTR_JMP_REL32; m_execstub = (BYTE*) ((pTargetCode) - (4+((BYTE*)&pEntryThunkCodeRX->m_execstub))); - FlushInstructionCache(GetCurrentProcess(),pEntryThunkCodeRX->GetEntryPoint(),sizeof(UMEntryThunkCode) - GetEntryPointOffset()); + ClrFlushInstructionCache(pEntryThunkCodeRX->GetEntryPoint(),sizeof(UMEntryThunkCode) - GetEntryPointOffset(), /* hasCodeExecutedBefore */ true); } void UMEntryThunkCode::Poison() @@ -1172,7 +1172,7 @@ void UMEntryThunkCode::Poison() // mov ecx, imm32 pThisRW->m_movEAX = 0xb9; - FlushInstructionCache(GetCurrentProcess(), GetEntryPoint(),sizeof(UMEntryThunkCode) - GetEntryPointOffset()); + ClrFlushInstructionCache(GetEntryPoint(),sizeof(UMEntryThunkCode) - GetEntryPointOffset(), /* hasCodeExecutedBefore */ true); } UMEntryThunk* UMEntryThunk::Decode(LPVOID pCallback) diff --git a/src/coreclr/vm/i386/jitinterfacex86.cpp b/src/coreclr/vm/i386/jitinterfacex86.cpp index e9e82b3d1cca55..c7239ffd89b24c 100644 --- a/src/coreclr/vm/i386/jitinterfacex86.cpp +++ b/src/coreclr/vm/i386/jitinterfacex86.cpp @@ -1395,7 +1395,7 @@ int StompWriteBarrierResize(bool isRuntimeSuspended, bool bReqUpperBoundsCheck) void FlushWriteBarrierInstructionCache() { - FlushInstructionCache(GetCurrentProcess(), GetWriteBarrierCodeLocation((BYTE*)JIT_PatchedWriteBarrierGroup), - (BYTE*)JIT_PatchedWriteBarrierGroup_End - (BYTE*)JIT_PatchedWriteBarrierGroup); + ClrFlushInstructionCache(GetWriteBarrierCodeLocation((BYTE*)JIT_PatchedWriteBarrierGroup), + (BYTE*)JIT_PatchedWriteBarrierGroup_End - (BYTE*)JIT_PatchedWriteBarrierGroup, /* hasCodeExecutedBefore */ true); } diff --git a/src/coreclr/vm/jitinterface.cpp b/src/coreclr/vm/jitinterface.cpp index 7a061a2aaa975d..d831c10bb5881b 100644 --- a/src/coreclr/vm/jitinterface.cpp +++ b/src/coreclr/vm/jitinterface.cpp @@ -12996,7 +12996,8 @@ PCODE UnsafeJitFunction(PrepareCodeConfig* config, //DbgPrintf("Jitted Entry at" FMT_ADDR "method %s::%s %s size %08x\n", DBG_ADDR(nativeEntry), // pszDebugClassName, pszDebugMethodName, pszDebugMethodSignature, sizeOfCode); - FlushInstructionCache(GetCurrentProcess(), nativeEntry, sizeOfCode); + // For dynamic method, the code memory may be reused, thus we are passing in the hasCodeExecutedBefore set to true + ClrFlushInstructionCache(nativeEntry, sizeOfCode, /* hasCodeExecutedBefore */ true); ret = (PCODE)nativeEntry; #ifdef TARGET_ARM diff --git a/src/coreclr/vm/loongarch64/cgencpu.h b/src/coreclr/vm/loongarch64/cgencpu.h index ea682213c3aa46..febe1cb1b98bbe 100644 --- a/src/coreclr/vm/loongarch64/cgencpu.h +++ b/src/coreclr/vm/loongarch64/cgencpu.h @@ -226,7 +226,7 @@ inline TADDR GetMem(PCODE address, SIZE_T size, bool signExtend) void emitCOMStubCall (ComCallMethodDesc *pCOMMethodRX, ComCallMethodDesc *pCOMMethodRW, PCODE target); #endif // FEATURE_COMINTEROP -inline BOOL ClrFlushInstructionCache(LPCVOID pCodeAddr, size_t sizeOfCode) +inline BOOL ClrFlushInstructionCache(LPCVOID pCodeAddr, size_t sizeOfCode, bool hasCodeExecutedBefore = false) { return FlushInstructionCache(GetCurrentProcess(), pCodeAddr, sizeOfCode); } diff --git a/src/coreclr/vm/precode.cpp b/src/coreclr/vm/precode.cpp index b9366dddcf2128..c997af5f678818 100644 --- a/src/coreclr/vm/precode.cpp +++ b/src/coreclr/vm/precode.cpp @@ -350,6 +350,7 @@ BOOL Precode::SetTargetInterlocked(PCODE target, BOOL fOnlyRedirectFromPrestub) #ifdef HAS_THISPTR_RETBUF_PRECODE case PRECODE_THISPTR_RETBUF: ret = AsThisPtrRetBufPrecode()->SetTargetInterlocked(target, expected); + ClrFlushInstructionCache(this, sizeof(ThisPtrRetBufPrecode), /* hasCodeExecutedBefore */ true); break; #endif // HAS_THISPTR_RETBUF_PRECODE @@ -381,7 +382,7 @@ void Precode::Reset() { ExecutableWriterHolder precodeWriterHolder(this, size); precodeWriterHolder.GetRW()->Init(this, t, pMD, pMD->GetLoaderAllocator()); - ClrFlushInstructionCache(this, SizeOf()); + ClrFlushInstructionCache(this, SizeOf(), /* hasCodeExecutedBefore */ true); } }