blob: f791cf922e5dfffb5cb135837b0b9344bb99027e [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
Edward O'Callaghan2bf62722009-08-05 04:02:56 +000017/*
Joerg Sonnenberger4845f5d2014-01-28 14:02:22 +000018 * The compiler generates calls to __clear_cache() when creating
Edward O'Callaghan2bf62722009-08-05 04:02:56 +000019 * trampoline functions on the stack for use with nested functions.
Joerg Sonnenberger4845f5d2014-01-28 14:02:22 +000020 * It is expected to invalidate the instruction cache for the
Edward O'Callaghan2bf62722009-08-05 04:02:56 +000021 * specified range.
22 */
23
Daniel Dunbarb3a69012009-06-26 16:47:03 +000024void __clear_cache(void* start, void* end)
25{
26#if __i386__ || __x86_64__
Edward O'Callaghan2bf62722009-08-05 04:02:56 +000027/*
28 * Intel processors have a unified instruction and data cache
29 * so there is nothing to do
30 */
Joerg Sonnenberger4845f5d2014-01-28 14:02:22 +000031#elif defined(__NetBSD__) && defined(__arm__)
32 struct arm_sync_icache_args arg;
33
34 arg.addr = (uintptr_t)start;
35 arg.len = (uintptr_t)end - (uintptr_t)start;
36
37 sysarch(ARM_SYNC_ICACHE, &arg);
38#elif defined(__aarch64__) && !defined(__APPLE__)
39 uint64_t xstart = (uint64_t)(uintptr_t) start;
40 uint64_t xend = (uint64_t)(uintptr_t) end;
41
42 // Get Cache Type Info
43 uint64_t ctr_el0;
44 __asm __volatile("mrs %0, ctr_el0" : "=r"(ctr_el0));
45
46 /*
47 * dc & ic instructions must use 64bit registers so we don't use
48 * uintptr_t in case this runs in an IPL32 environment.
49 */
50 const size_t dcache_line_size = 4 << ((ctr_el0 >> 16) & 15);
51 for (uint64_t addr = xstart; addr < xend; addr += dcache_line_size)
52 __asm __volatile("dc cvau, %0" :: "r"(addr));
53 __asm __volatile("dsb ish");
54
55 const size_t icache_line_size = 4 << ((ctr_el0 >> 0) & 15);
56 for (uint64_t addr = xstart; addr < xend; addr += icache_line_size)
57 __asm __volatile("ic ivau, %0" :: "r"(addr));
58 __asm __volatile("isb sy");
Daniel Dunbarb3a69012009-06-26 16:47:03 +000059#else
60 #if __APPLE__
Edward O'Callaghan2bf62722009-08-05 04:02:56 +000061 /* On Darwin, sys_icache_invalidate() provides this functionality */
Daniel Dunbarb3a69012009-06-26 16:47:03 +000062 sys_icache_invalidate(start, end-start);
63 #else
Daniel Dunbar48f46ac2010-03-31 17:00:45 +000064 compilerrt_abort();
Daniel Dunbarb3a69012009-06-26 16:47:03 +000065 #endif
66#endif
67}
68