blob: 1d49b7c81fdcaa405dacf9e99a1b00693954f2f4 [file] [log] [blame]
Edward O'Callaghan2bf62722009-08-05 04:02:56 +00001/* ===-- clear_cache.c - Implement __clear_cache ---------------------------===
2 *
3 * The LLVM Compiler Infrastructure
4 *
Howard Hinnant9ad441f2010-11-16 22:13:33 +00005 * This file is dual licensed under the MIT and the University of Illinois Open
6 * Source Licenses. See LICENSE.TXT for details.
Edward O'Callaghan2bf62722009-08-05 04:02:56 +00007 *
8 * ===----------------------------------------------------------------------===
9 */
Daniel Dunbarb3a69012009-06-26 16:47:03 +000010
Bob Wilsona98b7cb2012-01-03 18:59:25 +000011#include "int_lib.h"
12
Daniel Dunbarb3a69012009-06-26 16:47:03 +000013#if __APPLE__
14 #include <libkern/OSCacheControl.h>
15#endif
16
Daniel Sanders423cdd62014-03-12 16:38:27 +000017#if defined(ANDROID) && defined(__mips__)
18 #include <sys/cachectl.h>
19#endif
20
21#if defined(ANDROID) && defined(__arm__)
22 #include <asm/unistd.h>
23#endif
24
Edward O'Callaghan2bf62722009-08-05 04:02:56 +000025/*
Joerg Sonnenberger4845f5d2014-01-28 14:02:22 +000026 * The compiler generates calls to __clear_cache() when creating
Edward O'Callaghan2bf62722009-08-05 04:02:56 +000027 * trampoline functions on the stack for use with nested functions.
Joerg Sonnenberger4845f5d2014-01-28 14:02:22 +000028 * It is expected to invalidate the instruction cache for the
Edward O'Callaghan2bf62722009-08-05 04:02:56 +000029 * specified range.
30 */
31
Daniel Dunbarb3a69012009-06-26 16:47:03 +000032void __clear_cache(void* start, void* end)
33{
34#if __i386__ || __x86_64__
Edward O'Callaghan2bf62722009-08-05 04:02:56 +000035/*
36 * Intel processors have a unified instruction and data cache
37 * so there is nothing to do
38 */
Daniel Sanders423cdd62014-03-12 16:38:27 +000039#elif defined(__arm__) && !defined(__APPLE__)
40 #if defined(__NetBSD__)
41 struct arm_sync_icache_args arg;
Joerg Sonnenberger4845f5d2014-01-28 14:02:22 +000042
Daniel Sanders423cdd62014-03-12 16:38:27 +000043 arg.addr = (uintptr_t)start;
44 arg.len = (uintptr_t)end - (uintptr_t)start;
Joerg Sonnenberger4845f5d2014-01-28 14:02:22 +000045
Daniel Sanders423cdd62014-03-12 16:38:27 +000046 sysarch(ARM_SYNC_ICACHE, &arg);
47 #elif defined(ANDROID)
48 const register int start_reg __asm("r0") = (int) (intptr_t) start;
49 const register int end_reg __asm("r1") = (int) (intptr_t) end;
50 const register int flags __asm("r2") = 0;
51 const register int syscall_nr __asm("r7") = __ARM_NR_cacheflush;
52 __asm __volatile("svc 0x0" : "=r"(start_reg)
53 : "r"(syscall_nr), "r"(start_reg), "r"(end_reg), "r"(flags) : "r0");
54 if (start_reg != 0) {
55 compilerrt_abort();
56 }
57 #else
58 compilerrt_abort();
59 #endif
60#elif defined(ANDROID) && defined(__mips__)
61 const uintptr_t start_int = (uintptr_t) start;
62 const uintptr_t end_int = (uintptr_t) end;
63 _flush_cache(start, (end_int - start_int), BCACHE);
Joerg Sonnenberger4845f5d2014-01-28 14:02:22 +000064#elif defined(__aarch64__) && !defined(__APPLE__)
65 uint64_t xstart = (uint64_t)(uintptr_t) start;
66 uint64_t xend = (uint64_t)(uintptr_t) end;
67
68 // Get Cache Type Info
69 uint64_t ctr_el0;
70 __asm __volatile("mrs %0, ctr_el0" : "=r"(ctr_el0));
71
72 /*
73 * dc & ic instructions must use 64bit registers so we don't use
74 * uintptr_t in case this runs in an IPL32 environment.
75 */
76 const size_t dcache_line_size = 4 << ((ctr_el0 >> 16) & 15);
77 for (uint64_t addr = xstart; addr < xend; addr += dcache_line_size)
78 __asm __volatile("dc cvau, %0" :: "r"(addr));
79 __asm __volatile("dsb ish");
80
81 const size_t icache_line_size = 4 << ((ctr_el0 >> 0) & 15);
82 for (uint64_t addr = xstart; addr < xend; addr += icache_line_size)
83 __asm __volatile("ic ivau, %0" :: "r"(addr));
84 __asm __volatile("isb sy");
Daniel Dunbarb3a69012009-06-26 16:47:03 +000085#else
86 #if __APPLE__
Edward O'Callaghan2bf62722009-08-05 04:02:56 +000087 /* On Darwin, sys_icache_invalidate() provides this functionality */
Daniel Dunbarb3a69012009-06-26 16:47:03 +000088 sys_icache_invalidate(start, end-start);
89 #else
Daniel Dunbar48f46ac2010-03-31 17:00:45 +000090 compilerrt_abort();
Daniel Dunbarb3a69012009-06-26 16:47:03 +000091 #endif
92#endif
93}
94