1 1.1 joerg /* ===-- clear_cache.c - Implement __clear_cache ---------------------------=== 2 1.1 joerg * 3 1.1 joerg * The LLVM Compiler Infrastructure 4 1.1 joerg * 5 1.1 joerg * This file is dual licensed under the MIT and the University of Illinois Open 6 1.1 joerg * Source Licenses. See LICENSE.TXT for details. 7 1.1 joerg * 8 1.1 joerg * ===----------------------------------------------------------------------=== 9 1.1 joerg */ 10 1.1 joerg 11 1.1 joerg #include "int_lib.h" 12 1.2 joerg #include <stddef.h> 13 1.1 joerg 14 1.1 joerg #if __APPLE__ 15 1.1 joerg #include <libkern/OSCacheControl.h> 16 1.1 joerg #endif 17 1.2 joerg #if (defined(__FreeBSD__) || defined(__Bitrig__)) && defined(__arm__) 18 1.2 joerg #include <sys/types.h> 19 1.2 joerg #include <machine/sysarch.h> 20 1.2 joerg #endif 21 1.2 joerg 22 1.1 joerg #if defined(__NetBSD__) && defined(__arm__) 23 1.1 joerg #include <machine/sysarch.h> 24 1.1 joerg #endif 25 1.1 joerg 26 1.3 joerg #if defined(__NetBSD__) && defined(__ppc__) 27 1.3 joerg #include <machine/cpu.h> 28 1.3 joerg #endif 29 1.3 joerg 30 1.2 joerg #if defined(__mips__) 31 1.2 joerg #include <sys/cachectl.h> 32 1.2 joerg #include <sys/syscall.h> 33 1.2 joerg #include <unistd.h> 34 1.2 joerg #if defined(__ANDROID__) && defined(__LP64__) 35 1.2 joerg /* 36 1.2 joerg * clear_mips_cache - Invalidates instruction cache for Mips. 37 1.2 joerg */ 38 1.2 joerg static void clear_mips_cache(const void* Addr, size_t Size) { 39 1.2 joerg asm volatile ( 40 1.2 joerg ".set push\n" 41 1.2 joerg ".set noreorder\n" 42 1.2 joerg ".set noat\n" 43 1.2 joerg "beq %[Size], $zero, 20f\n" /* If size == 0, branch around. */ 44 1.2 joerg "nop\n" 45 1.2 joerg "daddu %[Size], %[Addr], %[Size]\n" /* Calculate end address + 1 */ 46 1.2 joerg "rdhwr $v0, $1\n" /* Get step size for SYNCI. 47 1.2 joerg $1 is $HW_SYNCI_Step */ 48 1.2 joerg "beq $v0, $zero, 20f\n" /* If no caches require 49 1.2 joerg synchronization, branch 50 1.2 joerg around. */ 51 1.2 joerg "nop\n" 52 1.2 joerg "10:\n" 53 1.2 joerg "synci 0(%[Addr])\n" /* Synchronize all caches around 54 1.2 joerg address. */ 55 1.2 joerg "daddu %[Addr], %[Addr], $v0\n" /* Add step size. */ 56 1.2 joerg "sltu $at, %[Addr], %[Size]\n" /* Compare current with end 57 1.2 joerg address. */ 58 1.2 joerg "bne $at, $zero, 10b\n" /* Branch if more to do. */ 59 1.2 joerg "nop\n" 60 1.2 joerg "sync\n" /* Clear memory hazards. */ 61 1.2 joerg "20:\n" 62 1.2 joerg "bal 30f\n" 63 1.2 joerg "nop\n" 64 1.2 joerg "30:\n" 65 1.2 joerg "daddiu $ra, $ra, 12\n" /* $ra has a value of $pc here. 66 1.2 joerg Add offset of 12 to point to the 67 1.2 joerg instruction after the last nop. 68 1.2 joerg */ 69 1.2 joerg "jr.hb $ra\n" /* Return, clearing instruction 70 1.2 joerg hazards. */ 71 1.2 joerg "nop\n" 72 1.2 joerg ".set pop\n" 73 1.2 joerg : [Addr] "+r"(Addr), [Size] "+r"(Size) 74 1.2 joerg :: "at", "ra", "v0", "memory" 75 1.2 joerg ); 76 1.2 joerg } 77 1.2 joerg #endif 78 1.2 joerg #endif 79 1.2 joerg 80 1.2 joerg #if defined(__ANDROID__) && defined(__arm__) 81 1.2 joerg #include <asm/unistd.h> 82 1.2 joerg #endif 83 1.2 joerg 84 1.1 joerg /* 85 1.1 joerg * The compiler generates calls to __clear_cache() when creating 86 1.1 joerg * trampoline functions on the stack for use with nested functions. 87 1.1 joerg * It is expected to invalidate the instruction cache for the 88 1.1 joerg * specified range. 89 1.1 joerg */ 90 1.1 joerg 91 1.2 joerg void __clear_cache(void *start, void *end) { 92 1.1 joerg #if __i386__ || __x86_64__ 93 1.1 joerg /* 94 1.1 joerg * Intel processors have a unified instruction and data cache 95 1.1 joerg * so there is nothing to do 96 1.1 joerg */ 97 1.2 joerg #elif defined(__arm__) && !defined(__APPLE__) 98 1.2 joerg #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__Bitrig__) 99 1.2 joerg struct arm_sync_icache_args arg; 100 1.2 joerg 101 1.2 joerg arg.addr = (uintptr_t)start; 102 1.2 joerg arg.len = (uintptr_t)end - (uintptr_t)start; 103 1.2 joerg 104 1.2 joerg sysarch(ARM_SYNC_ICACHE, &arg); 105 1.2 joerg #elif defined(__ANDROID__) 106 1.2 joerg register int start_reg __asm("r0") = (int) (intptr_t) start; 107 1.2 joerg const register int end_reg __asm("r1") = (int) (intptr_t) end; 108 1.2 joerg const register int flags __asm("r2") = 0; 109 1.2 joerg const register int syscall_nr __asm("r7") = __ARM_NR_cacheflush; 110 1.2 joerg __asm __volatile("svc 0x0" : "=r"(start_reg) 111 1.2 joerg : "r"(syscall_nr), "r"(start_reg), "r"(end_reg), "r"(flags) : "r0"); 112 1.2 joerg if (start_reg != 0) { 113 1.2 joerg compilerrt_abort(); 114 1.2 joerg } 115 1.2 joerg #else 116 1.2 joerg compilerrt_abort(); 117 1.2 joerg #endif 118 1.2 joerg #elif defined(__mips__) 119 1.2 joerg const uintptr_t start_int = (uintptr_t) start; 120 1.2 joerg const uintptr_t end_int = (uintptr_t) end; 121 1.2 joerg #if defined(__ANDROID__) && defined(__LP64__) 122 1.2 joerg // Call synci implementation for short address range. 123 1.2 joerg const uintptr_t address_range_limit = 256; 124 1.2 joerg if ((end_int - start_int) <= address_range_limit) { 125 1.2 joerg clear_mips_cache(start, (end_int - start_int)); 126 1.2 joerg } else { 127 1.2 joerg syscall(__NR_cacheflush, start, (end_int - start_int), BCACHE); 128 1.2 joerg } 129 1.2 joerg #else 130 1.2 joerg syscall(__NR_cacheflush, start, (end_int - start_int), BCACHE); 131 1.2 joerg #endif 132 1.1 joerg #elif defined(__aarch64__) && !defined(__APPLE__) 133 1.1 joerg uint64_t xstart = (uint64_t)(uintptr_t) start; 134 1.1 joerg uint64_t xend = (uint64_t)(uintptr_t) end; 135 1.2 joerg uint64_t addr; 136 1.1 joerg 137 1.1 joerg // Get Cache Type Info 138 1.1 joerg uint64_t ctr_el0; 139 1.1 joerg __asm __volatile("mrs %0, ctr_el0" : "=r"(ctr_el0)); 140 1.1 joerg 141 1.1 joerg /* 142 1.1 joerg * dc & ic instructions must use 64bit registers so we don't use 143 1.1 joerg * uintptr_t in case this runs in an IPL32 environment. 144 1.1 joerg */ 145 1.1 joerg const size_t dcache_line_size = 4 << ((ctr_el0 >> 16) & 15); 146 1.4 jmcneill for (addr = xstart & ~(dcache_line_size - 1); addr < xend; 147 1.4 jmcneill addr += dcache_line_size) 148 1.1 joerg __asm __volatile("dc cvau, %0" :: "r"(addr)); 149 1.1 joerg __asm __volatile("dsb ish"); 150 1.1 joerg 151 1.1 joerg const size_t icache_line_size = 4 << ((ctr_el0 >> 0) & 15); 152 1.4 jmcneill for (addr = xstart & ~(icache_line_size - 1); addr < xend; 153 1.4 jmcneill addr += icache_line_size) 154 1.1 joerg __asm __volatile("ic ivau, %0" :: "r"(addr)); 155 1.1 joerg __asm __volatile("isb sy"); 156 1.2 joerg #elif defined(__sparc__) 157 1.2 joerg uintptr_t xstart = (uintptr_t) start & ~(uintptr_t)3; 158 1.2 joerg uintptr_t xend = (uintptr_t) end; 159 1.2 joerg 160 1.2 joerg for (; xstart < xend; xstart += 4) { 161 1.2 joerg __asm __volatile("flush %0" :: "r" (xstart)); 162 1.2 joerg } 163 1.3 joerg #elif defined(__NetBSD__) && defined(__ppc__) 164 1.3 joerg __syncicache(start, (uintptr_t)end - (uintptr_t)start); 165 1.1 joerg #else 166 1.1 joerg #if __APPLE__ 167 1.1 joerg /* On Darwin, sys_icache_invalidate() provides this functionality */ 168 1.1 joerg sys_icache_invalidate(start, end-start); 169 1.1 joerg #else 170 1.1 joerg compilerrt_abort(); 171 1.1 joerg #endif 172 1.1 joerg #endif 173 1.1 joerg } 174 1.1 joerg 175