From 4113fd940c51daded98e260f193e336228a0f594 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Mon, 23 May 2016 21:35:28 -0700 Subject: [PATCH] Add ugly invalidation workaround for SGS7s. Otherwise they just crash, and crash often. Special thanks to Jaaan for numerous trials to try to find the best way to solve the crashes. --- Common/Arm64Emitter.cpp | 8 ++++++++ Common/ArmCPUDetect.cpp | 2 ++ Common/CPUDetect.h | 9 +++++++++ Core/MIPS/ARM64/Arm64Jit.cpp | 8 ++++++++ GPU/Common/VertexDecoderArm64.cpp | 8 ++++++++ 5 files changed, 35 insertions(+) diff --git a/Common/Arm64Emitter.cpp b/Common/Arm64Emitter.cpp index 9029117e45..7708958f62 100644 --- a/Common/Arm64Emitter.cpp +++ b/Common/Arm64Emitter.cpp @@ -16,6 +16,7 @@ #include "Arm64Emitter.h" #include "MathUtil.h" #include "CommonTypes.h" +#include "CPUDetect.h" namespace Arm64Gen { @@ -312,6 +313,13 @@ void ARM64XEmitter::FlushIcache() void ARM64XEmitter::FlushIcacheSection(u8* start, u8* end) { + if (cpu_info.sBugs.bExynos8890Invalidation) + { + // Over invalidate to force this CPU to listen. + start = m_startcode + 4096 < start ? start - 4096 : m_startcode; + end += 4096; + } + #if defined(IOS) // Header file says this is equivalent to: sys_icache_invalidate(start, end - start); sys_cache_control(kCacheFunctionPrepareForExecution, start, end - start); diff --git a/Common/ArmCPUDetect.cpp b/Common/ArmCPUDetect.cpp index 78cc3a918f..025c8833b4 100644 --- a/Common/ArmCPUDetect.cpp +++ b/Common/ArmCPUDetect.cpp @@ -296,6 +296,8 @@ void CPUInfo::Detect() // Whether the above detection failed or not, on ARM64 we do have ASIMD/NEON. bNEON = true; bASIMD = true; + + sBugs.bExynos8890Invalidation = strcmp(cpu_string, "universal8890") == 0; #endif } diff --git a/Common/CPUDetect.h b/Common/CPUDetect.h index 0adbfac8e6..25b8b42ee8 100644 --- a/Common/CPUDetect.h +++ b/Common/CPUDetect.h @@ -89,6 +89,15 @@ struct CPUInfo { bool bXBurst1; bool bXBurst2; + // Bugs + struct { + // Samsung Galaxy S7 devices (Exynos 8890) have a bug that causes invalidation to work incorrectly. + // This may be caused by interaction between the separate CPU cores. + // Padding jit blocks and over-invalidating seems to "solve" it. + // Only affects ARM64. + bool bExynos8890Invalidation; + } sBugs; + // Call Detect() explicit CPUInfo(); diff --git a/Core/MIPS/ARM64/Arm64Jit.cpp b/Core/MIPS/ARM64/Arm64Jit.cpp index a3f032ea5a..9ced4a8ada 100644 --- a/Core/MIPS/ARM64/Arm64Jit.cpp +++ b/Core/MIPS/ARM64/Arm64Jit.cpp @@ -329,6 +329,14 @@ const u8 *Arm64Jit::DoJit(u32 em_address, JitBlock *b) { if (dontLogBlocks > 0) dontLogBlocks--; + if (cpu_info.sBugs.bExynos8890Invalidation) { + // What a waste. If we don't do both this and over-invalidate, the device crashes. + // This space won't ever get run, but it's wasted jit cache space. + for (int i = 0; i < 32; ++i) { + HINT(HINT_NOP); + } + } + // Don't forget to zap the newly written instructions in the instruction cache! FlushIcache(); diff --git a/GPU/Common/VertexDecoderArm64.cpp b/GPU/Common/VertexDecoderArm64.cpp index 7b85c686c5..20303b7a44 100644 --- a/GPU/Common/VertexDecoderArm64.cpp +++ b/GPU/Common/VertexDecoderArm64.cpp @@ -275,6 +275,14 @@ JittedVertexDecoder VertexDecoderJitCache::Compile(const VertexDecoder &dec, int RET(); + if (cpu_info.sBugs.bExynos8890Invalidation) { + // Apparently the vertex cache hasn't been the problem, but adding this here for the same + // reasons as the standard jit. + for (int i = 0; i < 32; ++i) { + HINT(HINT_NOP); + } + } + FlushIcache(); if (log) {