commit 306353a8d233c3d7c60e7b02799b8675e745d5c2 Author: Julian Seward Date: Tue May 16 05:35:23 2017 +0000 arm64-linux: detect Cavium CPUs (implementer = 0x43) and enable the fallback LLSC implementation in that case. Pertains to bug #369459. git-svn-id: svn://svn.valgrind.org/valgrind/trunk@16380 diff --git a/coregrind/m_machine.c b/coregrind/m_machine.c index 93bdd72..eac1c16 100644 --- a/coregrind/m_machine.c +++ b/coregrind/m_machine.c @@ -634,7 +634,7 @@ static UInt VG_(get_machine_model)(void) return model; } -#endif /* VGA_s390x */ +#endif /* defined(VGA_s390x) */ #if defined(VGA_mips32) || defined(VGA_mips64) @@ -755,12 +755,65 @@ static Bool VG_(parse_cpuinfo)(void) return True; } -#endif +#endif /* defined(VGA_mips32) || defined(VGA_mips64) */ + +#if defined(VGP_arm64_linux) + +/* Check to see whether we are running on a Cavium core, and if so auto-enable + the fallback LLSC implementation. See #369459. */ + +static Bool VG_(parse_cpuinfo)(void) +{ + const char *search_Cavium_str = "CPU implementer\t: 0x43"; + + Int n, fh; + SysRes fd; + SizeT num_bytes, file_buf_size; + HChar *file_buf; + + /* Slurp contents of /proc/cpuinfo into FILE_BUF */ + fd = VG_(open)( "/proc/cpuinfo", 0, VKI_S_IRUSR ); + if ( sr_isError(fd) ) return False; + + fh = sr_Res(fd); + + /* Determine the size of /proc/cpuinfo. + Work around broken-ness in /proc file system implementation. + fstat returns a zero size for /proc/cpuinfo although it is + claimed to be a regular file. */ + num_bytes = 0; + file_buf_size = 1000; + file_buf = VG_(malloc)("cpuinfo", file_buf_size + 1); + while (42) { + n = VG_(read)(fh, file_buf, file_buf_size); + if (n < 0) break; + + num_bytes += n; + if (n < file_buf_size) break; /* reached EOF */ + } + + if (n < 0) num_bytes = 0; /* read error; ignore contents */ + + if (num_bytes > file_buf_size) { + VG_(free)( file_buf ); + VG_(lseek)( fh, 0, VKI_SEEK_SET ); + file_buf = VG_(malloc)( "cpuinfo", num_bytes + 1 ); + n = VG_(read)( fh, file_buf, num_bytes ); + if (n < 0) num_bytes = 0; + } -/* Determine what insn set and insn set variant the host has, and - record it. To be called once at system startup. Returns False if - this a CPU incapable of running Valgrind. - Also determine information about the caches on this host. */ + file_buf[num_bytes] = '\0'; + VG_(close)(fh); + + /* Parse file */ + if (VG_(strstr)(file_buf, search_Cavium_str) != NULL) + vai.arm64_requires_fallback_LLSC = True; + + VG_(free)(file_buf); + return True; +} + +#endif /* defined(VGP_arm64_linux) */ Bool VG_(machine_get_hwcaps)( void ) { @@ -1588,6 +1641,11 @@ Bool VG_(machine_get_hwcaps)( void ) VG_(machine_get_cache_info)(&vai); + /* Check whether we need to use the fallback LLSC implementation. + If the check fails, give up. */ + if (! VG_(parse_cpuinfo)()) + return False; + /* 0 denotes 'not set'. The range of legitimate values here, after being set that is, is 2 though 17 inclusive. */ vg_assert(vai.arm64_dMinLine_lg2_szB == 0); @@ -1600,6 +1658,8 @@ Bool VG_(machine_get_hwcaps)( void ) "ctr_el0.iMinLine_szB = %d\n", 1 << vai.arm64_dMinLine_lg2_szB, 1 << vai.arm64_iMinLine_lg2_szB); + VG_(debugLog)(1, "machine", "ARM64: requires_fallback_LLSC: %s\n", + vai.arm64_requires_fallback_LLSC ? "yes" : "no"); return True; } diff --git a/coregrind/m_translate.c b/coregrind/m_translate.c index 2f0ceac..55c845d 100644 --- a/coregrind/m_translate.c +++ b/coregrind/m_translate.c @@ -1707,7 +1707,10 @@ Bool VG_(translate) ( ThreadId tid, # if defined(VGP_arm64_linux) vex_abiinfo.guest__use_fallback_LLSC - = SimHintiS(SimHint_fallback_llsc, VG_(clo_sim_hints)); + = /* The user asked explicitly */ + SimHintiS(SimHint_fallback_llsc, VG_(clo_sim_hints)) + || /* we autodetected that it is necessary */ + vex_archinfo.arm64_requires_fallback_LLSC; # endif /* Set up closure args. */