commit 306353a8d233c3d7c60e7b02799b8675e745d5c2
Author: Julian Seward <jseward@acm.org>
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. */