Disable jit_memory_region_test tests on buggy kernels.

Test: jit_memory_region_test
Change-Id: I5339071ab1fcb9765a91015e33024d05774ac2b1
diff --git a/libartbase/base/utils.cc b/libartbase/base/utils.cc
index 65d02da..840216c 100644
--- a/libartbase/base/utils.cc
+++ b/libartbase/base/utils.cc
@@ -47,6 +47,7 @@
 #if defined(__linux__)
 #include <linux/unistd.h>
 #include <sys/syscall.h>
+#include <sys/utsname.h>
 #endif
 
 #if defined(_WIN32)
@@ -154,6 +155,29 @@
 
 #endif
 
+bool CacheOperationsMaySegFault() {
+#if defined(__linux__) && defined(__aarch64__)
+  // Avoid issue on older ARM64 kernels where data cache operations could be classified as writes
+  // and cause segmentation faults. This was fixed in Linux 3.11rc2:
+  //
+  // https://github.com/torvalds/linux/commit/db6f41063cbdb58b14846e600e6bc3f4e4c2e888
+  //
+  // This behaviour means we should avoid the dual view JIT on the device. This is just
+  // an issue when running tests on devices that have an old kernel.
+  static constexpr int kRequiredMajor = 3;
+  static constexpr int kRequiredMinor = 12;
+  struct utsname uts;
+  int major, minor;
+  if (uname(&uts) != 0 ||
+      strcmp(uts.sysname, "Linux") != 0 ||
+      sscanf(uts.release, "%d.%d", &major, &minor) != 2 ||
+      (major < kRequiredMajor || (major == kRequiredMajor && minor < kRequiredMinor))) {
+    return true;
+  }
+#endif
+  return false;
+}
+
 pid_t GetTid() {
 #if defined(__APPLE__)
   uint64_t owner;
diff --git a/libartbase/base/utils.h b/libartbase/base/utils.h
index f434cb4..ba95331 100644
--- a/libartbase/base/utils.h
+++ b/libartbase/base/utils.h
@@ -116,6 +116,9 @@
 // Flush CPU caches. Returns true on success, false if flush failed.
 WARN_UNUSED bool FlushCpuCaches(void* begin, void* end);
 
+// On some old kernels, a cache operation may segfault.
+WARN_UNUSED bool CacheOperationsMaySegFault();
+
 template <typename T>
 constexpr PointerSize ConvertToPointerSize(T any) {
   if (any == 4 || any == 8) {