fix: suppress MTE while scanning the stack

When Android's built with -fsanitize=memtag-stack, the GC scan crashes
because it doesn't read the stack with the right tagged stack pointer.
We could fix it by looking up the stack tags each iteration, but this
would impact the majority of MTE devices where the stack isn't tagged.

Bug: v8:14223
Change-Id: I616791b120915f834a5fa05b250d7ac45c98eb40
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/4843148
Reviewed-by: Michael Lippautz <mlippautz@chromium.org>
Commit-Queue: Richard Townsend <richard.townsend@arm.com>
Cr-Commit-Position: refs/heads/main@{#89937}
diff --git a/src/base/cpu.cc b/src/base/cpu.cc
index e63896b..9a21c10 100644
--- a/src/base/cpu.cc
+++ b/src/base/cpu.cc
@@ -14,7 +14,7 @@
 #if V8_OS_LINUX
 #include <linux/auxvec.h>  // AT_HWCAP
 #endif
-#if V8_GLIBC_PREREQ(2, 16)
+#if V8_GLIBC_PREREQ(2, 16) || V8_OS_ANDROID
 #include <sys/auxv.h>  // getauxval()
 #endif
 #if V8_OS_QNX
@@ -163,17 +163,27 @@
 #define HWCAP_SB (1 << 29)
 #define HWCAP_PACA (1 << 30)
 #define HWCAP_PACG (1UL << 31)
-
+// See <uapi/asm/hwcap.h> kernel header.
+/*
+ * HWCAP2 flags - for elf_hwcap2 (in kernel) and AT_HWCAP2
+ */
+#define HWCAP2_MTE (1 << 18)
 #endif  // V8_HOST_ARCH_ARM64
 
 #if V8_HOST_ARCH_ARM || V8_HOST_ARCH_ARM64
 
-static uint32_t ReadELFHWCaps() {
-  uint32_t result = 0;
-#if V8_GLIBC_PREREQ(2, 16)
-  result = static_cast<uint32_t>(getauxval(AT_HWCAP));
+static std::tuple<uint32_t, uint32_t> ReadELFHWCaps() {
+  uint32_t hwcap = 0;
+  uint32_t hwcap2 = 0;
+#if defined(AT_HWCAP)
+  hwcap = static_cast<uint32_t>(getauxval(AT_HWCAP));
+#if defined(AT_HWCAP2)
+  hwcap2 = static_cast<uint32_t>(getauxval(AT_HWCAP2));
+#endif  // AT_HWCAP2
 #else
   // Read the ELF HWCAP flags by parsing /proc/self/auxv.
+  // If getauxval is not available, the kernel/libc is also not new enough to
+  // expose hwcap2.
   FILE* fp = base::Fopen("/proc/self/auxv", "r");
   if (fp != nullptr) {
     struct {
@@ -193,7 +203,7 @@
     base::Fclose(fp);
   }
 #endif
-  return result;
+  return std::make_tuple(hwcap, hwcap2);
 }
 
 #endif  // V8_HOST_ARCH_ARM || V8_HOST_ARCH_ARM64
@@ -406,6 +416,7 @@
       has_jscvt_(false),
       has_dot_prod_(false),
       has_lse_(false),
+      has_mte_(false),
       is_fp64_mode_(false),
       has_non_stop_time_stamp_counter_(false),
       is_running_in_vm_(false),
@@ -628,7 +639,8 @@
   }
 
   // Try to extract the list of CPU features from ELF hwcaps.
-  uint32_t hwcaps = ReadELFHWCaps();
+  uint32_t hwcaps, hwcaps2;
+  std::tie(hwcaps, hwcaps2) = ReadELFHWCaps();
   if (hwcaps != 0) {
     has_idiva_ = (hwcaps & HWCAP_IDIVA) != 0;
     has_neon_ = (hwcaps & HWCAP_NEON) != 0;
@@ -740,7 +752,9 @@
 
 #elif V8_OS_LINUX
   // Try to extract the list of CPU features from ELF hwcaps.
-  uint32_t hwcaps = ReadELFHWCaps();
+  uint32_t hwcaps, hwcaps2;
+  std::tie(hwcaps, hwcaps2) = ReadELFHWCaps();
+  has_mte_ = (hwcaps2 & HWCAP2_MTE) != 0;
   if (hwcaps != 0) {
     has_jscvt_ = (hwcaps & HWCAP_JSCVT) != 0;
     has_dot_prod_ = (hwcaps & HWCAP_ASIMDDP) != 0;