19f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson/* ===-- clear_cache.c - Implement __clear_cache ---------------------------===
29f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson *
39f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson *                     The LLVM Compiler Infrastructure
49f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson *
59f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * This file is dual licensed under the MIT and the University of Illinois Open
69f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * Source Licenses. See LICENSE.TXT for details.
79f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson *
89f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * ===----------------------------------------------------------------------===
99f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson */
109f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
119f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson#include "int_lib.h"
129f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
139f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson#if __APPLE__
149f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  #include <libkern/OSCacheControl.h>
159f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson#endif
169f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson#if defined(__NetBSD__) && defined(__arm__)
179f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  #include <machine/sysarch.h>
189f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson#endif
199f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
209f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson#if defined(ANDROID) && defined(__mips__)
219f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  #include <sys/cachectl.h>
229f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson#endif
239f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
249f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson#if defined(ANDROID) && defined(__arm__)
259f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  #include <asm/unistd.h>
269f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson#endif
279f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
289f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson/*
299f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * The compiler generates calls to __clear_cache() when creating
309f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * trampoline functions on the stack for use with nested functions.
319f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * It is expected to invalidate the instruction cache for the
329f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * specified range.
339f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson */
349f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
359f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse WilsonCOMPILER_RT_EXPORT void
369f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson__clear_cache(void* start, void* end)
379f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson{
389f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson#if __i386__ || __x86_64__
399f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson/*
409f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * Intel processors have a unified instruction and data cache
419f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * so there is nothing to do
429f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson */
439f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson#elif defined(__arm__) && !defined(__APPLE__)
449f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    #if defined(__NetBSD__)
459f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        struct arm_sync_icache_args arg;
469f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
479f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        arg.addr = (uintptr_t)start;
489f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        arg.len = (uintptr_t)end - (uintptr_t)start;
499f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
509f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        sysarch(ARM_SYNC_ICACHE, &arg);
519f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    #elif defined(ANDROID)
529f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson         const register int start_reg __asm("r0") = (int) (intptr_t) start;
539f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson         const register int end_reg __asm("r1") = (int) (intptr_t) end;
549f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson         const register int flags __asm("r2") = 0;
559f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson         const register int syscall_nr __asm("r7") = __ARM_NR_cacheflush;
569f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        __asm __volatile("svc 0x0" : "=r"(start_reg)
579f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson            : "r"(syscall_nr), "r"(start_reg), "r"(end_reg), "r"(flags) : "r0");
589f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson         if (start_reg != 0) {
599f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson             compilerrt_abort();
609f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson         }
619f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    #else
629f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        compilerrt_abort();
639f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    #endif
649f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson#elif defined(ANDROID) && defined(__mips__)
659f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  const uintptr_t start_int = (uintptr_t) start;
669f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  const uintptr_t end_int = (uintptr_t) end;
679f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  _flush_cache(start, (end_int - start_int), BCACHE);
689f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson#elif defined(__aarch64__) && !defined(__APPLE__)
699f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  uint64_t xstart = (uint64_t)(uintptr_t) start;
709f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  uint64_t xend = (uint64_t)(uintptr_t) end;
719f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
729f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  // Get Cache Type Info
739f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  uint64_t ctr_el0;
749f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  __asm __volatile("mrs %0, ctr_el0" : "=r"(ctr_el0));
759f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
769f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  /*
779f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * dc & ic instructions must use 64bit registers so we don't use
789f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * uintptr_t in case this runs in an IPL32 environment.
799f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   */
809f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  const size_t dcache_line_size = 4 << ((ctr_el0 >> 16) & 15);
819f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  for (uint64_t addr = xstart; addr < xend; addr += dcache_line_size)
829f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    __asm __volatile("dc cvau, %0" :: "r"(addr));
839f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  __asm __volatile("dsb ish");
849f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
859f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  const size_t icache_line_size = 4 << ((ctr_el0 >> 0) & 15);
869f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  for (uint64_t addr = xstart; addr < xend; addr += icache_line_size)
879f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    __asm __volatile("ic ivau, %0" :: "r"(addr));
889f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  __asm __volatile("isb sy");
899f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson#else
909f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    #if __APPLE__
919f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        /* On Darwin, sys_icache_invalidate() provides this functionality */
929f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        sys_icache_invalidate(start, end-start);
939f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    #else
949f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        compilerrt_abort();
959f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    #endif
969f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson#endif
979f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson}
989f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
999f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson