[arm64] manually flush icache
authorBernhard Urban <bernhard.urban@xamarin.com>
Fri, 9 Sep 2016 22:42:58 +0000 (00:42 +0200)
committerBernhard Urban <bernhard.urban@xamarin.com>
Fri, 9 Sep 2016 22:42:58 +0000 (00:42 +0200)
should fix https://bugzilla.xamarin.com/show_bug.cgi?id=39859

mono/mini/mini-arm64.c

index 31a7329628ac04b98a61c893a9c97e0c10a53acb..6417c11f6c34c5d7ebd2fca88f219eaa4cab5dec 100644 (file)
@@ -1777,7 +1777,33 @@ mono_arch_flush_icache (guint8 *code, gint size)
 #if __APPLE__
        sys_icache_invalidate (code, size);
 #else
-       __clear_cache (code, code + size);
+       /* Don't rely on GCC's __clear_cache implementation, as it caches
+        * icache/dcache cache line sizes, that can vary between cores on
+        * big.LITTLE architectures. */
+       guint64 end = (guint64) (code + size);
+       guint64 addr, ctr_el0;
+       static size_t icache_line_size = 0xffff, dcache_line_size = 0xffff;
+       size_t isize, dsize;
+
+       asm volatile ("mrs %0, ctr_el0" : "=r" (ctr_el0));
+       isize = 4 << ((ctr_el0 >> 0 ) & 0xf);
+       dsize = 4 << ((ctr_el0 >> 16) & 0xf);
+
+       /* determine the global minimum cache line size */
+       icache_line_size = isize = MIN (icache_line_size, isize);
+       dcache_line_size = dsize = MIN (dcache_line_size, dsize);
+
+       addr = (guint64) code & ~(guint64) (dsize - 1);
+       for (; addr < end; addr += dsize)
+               asm volatile("dc cvau, %0" : : "r" (addr) : "memory");
+       asm volatile("dsb ish" : : : "memory");
+
+       addr = (guint64) code & ~(guint64) (isize - 1);
+       for (; addr < end; addr += isize)
+               asm volatile("ic ivau, %0" : : "r" (addr) : "memory");
+
+       asm volatile ("dsb ish" : : : "memory");
+       asm volatile ("isb" : : : "memory");
 #endif
 #endif
 }