Cache invalidation for AARCH64. Disabled for Apple for now as requested
by Tim Northover. Written by Matt Thomas.

Differential Revision: http://llvm-reviews.chandlerc.com/D2631

git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@200317 91177308-0d34-0410-b5e6-96231b3b80d8

Conflicts:
	lib/clear_cache.c

Change-Id: I08417a541c413205382a1abea36d941bb30727b6
diff --git a/lib/clear_cache.c b/lib/clear_cache.c
index b934fd4..f791cf9 100644
--- a/lib/clear_cache.c
+++ b/lib/clear_cache.c
@@ -15,9 +15,9 @@
 #endif
 
 /*
- * The compiler generates calls to __clear_cache() when creating 
+ * The compiler generates calls to __clear_cache() when creating
  * trampoline functions on the stack for use with nested functions.
- * It is expected to invalidate the instruction cache for the 
+ * It is expected to invalidate the instruction cache for the
  * specified range.
  */
 
@@ -28,6 +28,34 @@
  * Intel processors have a unified instruction and data cache
  * so there is nothing to do
  */
+#elif defined(__NetBSD__) && defined(__arm__)
+  struct arm_sync_icache_args arg;
+
+  arg.addr = (uintptr_t)start;
+  arg.len = (uintptr_t)end - (uintptr_t)start;
+
+  sysarch(ARM_SYNC_ICACHE, &arg);
+#elif defined(__aarch64__) && !defined(__APPLE__)
+  uint64_t xstart = (uint64_t)(uintptr_t) start;
+  uint64_t xend = (uint64_t)(uintptr_t) end;
+
+  // Get Cache Type Info
+  uint64_t ctr_el0;
+  __asm __volatile("mrs %0, ctr_el0" : "=r"(ctr_el0));
+
+  /*
+   * dc & ic instructions must use 64bit registers so we don't use
+   * uintptr_t in case this runs in an IPL32 environment.
+   */
+  const size_t dcache_line_size = 4 << ((ctr_el0 >> 16) & 15);
+  for (uint64_t addr = xstart; addr < xend; addr += dcache_line_size)
+    __asm __volatile("dc cvau, %0" :: "r"(addr));
+  __asm __volatile("dsb ish");
+
+  const size_t icache_line_size = 4 << ((ctr_el0 >> 0) & 15);
+  for (uint64_t addr = xstart; addr < xend; addr += icache_line_size)
+    __asm __volatile("ic ivau, %0" :: "r"(addr));
+  __asm __volatile("isb sy");
 #else
     #if __APPLE__
         /* On Darwin, sys_icache_invalidate() provides this functionality */