Merge pull request #8769 from unknownbrackets/cpuinfo

Add ugly invalidation workaround for SGS7s
This commit is contained in:
Henrik Rydgård 2016-05-24 09:59:05 +02:00
commit 9b63a44c86
5 changed files with 89 additions and 32 deletions

View File

@ -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);

View File

@ -23,6 +23,9 @@
#ifdef BLACKBERRY
#include <bps/deviceinfo.h>
#endif
#ifdef ANDROID
#include <sys/system_properties.h>
#endif
// Only Linux platforms have /proc/cpuinfo
#if defined(__linux__)
@ -30,51 +33,70 @@ const char procfile[] = "/proc/cpuinfo";
// https://www.kernel.org/doc/Documentation/ABI/testing/sysfs-devices-system-cpu
const char syscpupresentfile[] = "/sys/devices/system/cpu/present";
std::string GetCPUString()
{
std::string line, marker = "Hardware\t: ";
std::string cpu_string = "Unknown";
std::string GetCPUString() {
std::string cpu_string;
std::fstream file;
if (!File::OpenCPPFile(file, procfile, std::ios::in))
return cpu_string;
while (std::getline(file, line))
{
if (line.find(marker) != std::string::npos)
{
cpu_string = line.substr(marker.length());
if (cpu_string.back() == '\n')
cpu_string.pop_back(); // Drop the new-line character
if (File::OpenCPPFile(file, procfile, std::ios::in)) {
std::string line, marker = "Hardware\t: ";
while (std::getline(file, line)) {
if (line.find(marker) != std::string::npos) {
cpu_string = line.substr(marker.length());
}
}
}
#ifdef ANDROID
if (cpu_string.empty()) {
char temp[PROP_VALUE_MAX];
if (__system_property_get("ro.product.board", temp) != 0) {
cpu_string = temp;
} else if (__system_property_get("ro.product.name", temp) != 0) {
cpu_string = temp;
}
}
#endif
if (cpu_string.empty())
cpu_string = "Unknown";
else if (cpu_string.back() == '\n')
cpu_string.pop_back(); // Drop the new-line character
return cpu_string;
}
std::string GetCPUBrandString()
{
std::string line, marker = "Processor\t: ";
std::string brand_string = "Unknown";
std::string GetCPUBrandString() {
std::string brand_string;
std::fstream file;
if (!File::OpenCPPFile(file, procfile, std::ios::in))
return brand_string;
while (std::getline(file, line))
{
if (line.find(marker) != std::string::npos)
{
brand_string = line.substr(marker.length());
if (brand_string.back() == '\n')
brand_string.pop_back(); // Drop the new-line character
if (brand_string.length() == 0 || isdigit(brand_string[0])) {
brand_string = "Unknown";
continue;
if (File::OpenCPPFile(file, procfile, std::ios::in)) {
std::string line, marker = "Processor\t: ";
while (std::getline(file, line)) {
if (line.find(marker) != std::string::npos) {
brand_string = line.substr(marker.length());
if (brand_string.length() != 0 && !isdigit(brand_string[0])) {
break;
}
}
break;
}
}
#ifdef ANDROID
if (brand_string.empty()) {
char temp[PROP_VALUE_MAX];
if (__system_property_get("ro.product.model", temp) != 0) {
brand_string = temp;
} else if (__system_property_get("ro.product.name", temp) != 0) {
brand_string = temp;
}
}
#endif
if (brand_string.empty())
brand_string = "Unknown";
else if (brand_string.back() == '\n')
brand_string.pop_back(); // Drop the new-line character
return brand_string;
}
@ -274,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
}

View File

@ -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();

View File

@ -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();

View File

@ -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) {