#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
}