1 /* SPDX-License-Identifier: GPL-2.0-only */ 2 /* 3 * linux/arch/arm/mm/cache-v6.S 4 * 5 * Copyright (C) 2001 Deep Blue Solutions Ltd. 6 * 7 * This is the "shell" of the ARMv6 processor support. 8 */ 9 #include <linux/linkage.h> 10 #include <linux/init.h> 11 #include <linux/cfi_types.h> 12 #include <asm/assembler.h> 13 #include <asm/errno.h> 14 #include <asm/unwind.h> 15 16 #include "proc-macros.S" 17 18 #define HARVARD_CACHE 19 #define CACHE_LINE_SIZE 32 20 #define D_CACHE_LINE_SIZE 32 21 #define BTB_FLUSH_SIZE 8 22 23 .arch armv6 24 25 /* 26 * v6_flush_icache_all() 27 * 28 * Flush the whole I-cache. 29 * 30 * ARM1136 erratum 411920 - Invalidate Instruction Cache operation can fail. 31 * This erratum is present in 1136, 1156 and 1176. It does not affect the 32 * MPCore. 33 * 34 * Registers: 35 * r0 - set to 0 36 * r1 - corrupted 37 */ 38 SYM_TYPED_FUNC_START(v6_flush_icache_all) 39 mov r0, #0 40 #ifdef CONFIG_ARM_ERRATA_411920 41 mrs r1, cpsr 42 cpsid ifa @ disable interrupts 43 mcr p15, 0, r0, c7, c5, 0 @ invalidate entire I-cache 44 mcr p15, 0, r0, c7, c5, 0 @ invalidate entire I-cache 45 mcr p15, 0, r0, c7, c5, 0 @ invalidate entire I-cache 46 mcr p15, 0, r0, c7, c5, 0 @ invalidate entire I-cache 47 msr cpsr_cx, r1 @ restore interrupts 48 .rept 11 @ ARM Ltd recommends at least 49 nop @ 11 NOPs 50 .endr 51 #else 52 mcr p15, 0, r0, c7, c5, 0 @ invalidate I-cache 53 #endif 54 ret lr 55 SYM_FUNC_END(v6_flush_icache_all) 56 57 /* 58 * v6_flush_cache_all() 59 * 60 * Flush the entire cache. 61 * 62 * It is assumed that: 63 */ 64 SYM_TYPED_FUNC_START(v6_flush_kern_cache_all) 65 mov r0, #0 66 #ifdef HARVARD_CACHE 67 mcr p15, 0, r0, c7, c14, 0 @ D cache clean+invalidate 68 #ifndef CONFIG_ARM_ERRATA_411920 69 mcr p15, 0, r0, c7, c5, 0 @ I+BTB cache invalidate 70 #else 71 b v6_flush_icache_all 72 #endif 73 #else 74 mcr p15, 0, r0, c7, c15, 0 @ Cache clean+invalidate 75 #endif 76 ret lr 77 SYM_FUNC_END(v6_flush_kern_cache_all) 78 79 /* 80 * v6_flush_cache_all() 81 * 82 * Flush all TLB entries in a particular address space 83 * 84 * - mm - mm_struct describing address space 85 */ 86 SYM_TYPED_FUNC_START(v6_flush_user_cache_all) 87 ret lr 88 SYM_FUNC_END(v6_flush_user_cache_all) 89 90 /* 91 * v6_flush_cache_range(start, end, flags) 92 * 93 * Flush a range of TLB entries in the specified address space. 94 * 95 * - start - start address (may not be aligned) 96 * - end - end address (exclusive, may not be aligned) 97 * - flags - vm_area_struct flags describing address space 98 * 99 * It is assumed that: 100 * - we have a VIPT cache. 101 */ 102 SYM_TYPED_FUNC_START(v6_flush_user_cache_range) 103 ret lr 104 SYM_FUNC_END(v6_flush_user_cache_range) 105 106 /* 107 * v6_coherent_kern_range(start,end) 108 * 109 * Ensure that the I and D caches are coherent within specified 110 * region. This is typically used when code has been written to 111 * a memory region, and will be executed. 112 * 113 * - start - virtual start address of region 114 * - end - virtual end address of region 115 * 116 * It is assumed that: 117 * - the Icache does not read data from the write buffer 118 */ 119 SYM_TYPED_FUNC_START(v6_coherent_kern_range) 120 #ifdef CONFIG_CFI_CLANG /* Fallthrough if !CFI */ 121 b v6_coherent_user_range 122 #endif 123 SYM_FUNC_END(v6_coherent_kern_range) 124 125 /* 126 * v6_coherent_user_range(start,end) 127 * 128 * Ensure that the I and D caches are coherent within specified 129 * region. This is typically used when code has been written to 130 * a memory region, and will be executed. 131 * 132 * - start - virtual start address of region 133 * - end - virtual end address of region 134 * 135 * It is assumed that: 136 * - the Icache does not read data from the write buffer 137 */ 138 SYM_TYPED_FUNC_START(v6_coherent_user_range) 139 UNWIND(.fnstart ) 140 #ifdef HARVARD_CACHE 141 bic r0, r0, #CACHE_LINE_SIZE - 1 142 1: 143 USER( mcr p15, 0, r0, c7, c10, 1 ) @ clean D line 144 add r0, r0, #CACHE_LINE_SIZE 145 cmp r0, r1 146 blo 1b 147 #endif 148 mov r0, #0 149 #ifdef HARVARD_CACHE 150 mcr p15, 0, r0, c7, c10, 4 @ drain write buffer 151 #ifndef CONFIG_ARM_ERRATA_411920 152 mcr p15, 0, r0, c7, c5, 0 @ I+BTB cache invalidate 153 #else 154 b v6_flush_icache_all 155 #endif 156 #else 157 mcr p15, 0, r0, c7, c5, 6 @ invalidate BTB 158 #endif 159 ret lr 160 161 /* 162 * Fault handling for the cache operation above. If the virtual address in r0 163 * isn't mapped, fail with -EFAULT. 164 */ 165 9001: 166 mov r0, #-EFAULT 167 ret lr 168 UNWIND(.fnend ) 169 SYM_FUNC_END(v6_coherent_user_range) 170 171 /* 172 * v6_flush_kern_dcache_area(void *addr, size_t size) 173 * 174 * Ensure that the data held in the page kaddr is written back 175 * to the page in question. 176 * 177 * - addr - kernel address 178 * - size - region size 179 */ 180 SYM_TYPED_FUNC_START(v6_flush_kern_dcache_area) 181 add r1, r0, r1 182 bic r0, r0, #D_CACHE_LINE_SIZE - 1 183 1: 184 #ifdef HARVARD_CACHE 185 mcr p15, 0, r0, c7, c14, 1 @ clean & invalidate D line 186 #else 187 mcr p15, 0, r0, c7, c15, 1 @ clean & invalidate unified line 188 #endif 189 add r0, r0, #D_CACHE_LINE_SIZE 190 cmp r0, r1 191 blo 1b 192 #ifdef HARVARD_CACHE 193 mov r0, #0 194 mcr p15, 0, r0, c7, c10, 4 195 #endif 196 ret lr 197 SYM_FUNC_END(v6_flush_kern_dcache_area) 198 199 /* 200 * v6_dma_inv_range(start,end) 201 * 202 * Invalidate the data cache within the specified region; we will 203 * be performing a DMA operation in this region and we want to 204 * purge old data in the cache. 205 * 206 * - start - virtual start address of region 207 * - end - virtual end address of region 208 */ 209 v6_dma_inv_range: 210 tst r0, #D_CACHE_LINE_SIZE - 1 211 bic r0, r0, #D_CACHE_LINE_SIZE - 1 212 #ifdef HARVARD_CACHE 213 mcrne p15, 0, r0, c7, c10, 1 @ clean D line 214 #else 215 mcrne p15, 0, r0, c7, c11, 1 @ clean unified line 216 #endif 217 tst r1, #D_CACHE_LINE_SIZE - 1 218 bic r1, r1, #D_CACHE_LINE_SIZE - 1 219 #ifdef HARVARD_CACHE 220 mcrne p15, 0, r1, c7, c14, 1 @ clean & invalidate D line 221 #else 222 mcrne p15, 0, r1, c7, c15, 1 @ clean & invalidate unified line 223 #endif 224 1: 225 #ifdef HARVARD_CACHE 226 mcr p15, 0, r0, c7, c6, 1 @ invalidate D line 227 #else 228 mcr p15, 0, r0, c7, c7, 1 @ invalidate unified line 229 #endif 230 add r0, r0, #D_CACHE_LINE_SIZE 231 cmp r0, r1 232 blo 1b 233 mov r0, #0 234 mcr p15, 0, r0, c7, c10, 4 @ drain write buffer 235 ret lr 236 237 /* 238 * v6_dma_clean_range(start,end) 239 * - start - virtual start address of region 240 * - end - virtual end address of region 241 */ 242 v6_dma_clean_range: 243 bic r0, r0, #D_CACHE_LINE_SIZE - 1 244 1: 245 #ifdef HARVARD_CACHE 246 mcr p15, 0, r0, c7, c10, 1 @ clean D line 247 #else 248 mcr p15, 0, r0, c7, c11, 1 @ clean unified line 249 #endif 250 add r0, r0, #D_CACHE_LINE_SIZE 251 cmp r0, r1 252 blo 1b 253 mov r0, #0 254 mcr p15, 0, r0, c7, c10, 4 @ drain write buffer 255 ret lr 256 257 /* 258 * v6_dma_flush_range(start,end) 259 * - start - virtual start address of region 260 * - end - virtual end address of region 261 */ 262 SYM_TYPED_FUNC_START(v6_dma_flush_range) 263 bic r0, r0, #D_CACHE_LINE_SIZE - 1 264 1: 265 #ifdef HARVARD_CACHE 266 mcr p15, 0, r0, c7, c14, 1 @ clean & invalidate D line 267 #else 268 mcr p15, 0, r0, c7, c15, 1 @ clean & invalidate line 269 #endif 270 add r0, r0, #D_CACHE_LINE_SIZE 271 cmp r0, r1 272 blo 1b 273 mov r0, #0 274 mcr p15, 0, r0, c7, c10, 4 @ drain write buffer 275 ret lr 276 SYM_FUNC_END(v6_dma_flush_range) 277 278 /* 279 * dma_map_area(start, size, dir) 280 * - start - kernel virtual start address 281 * - size - size of region 282 * - dir - DMA direction 283 */ 284 SYM_TYPED_FUNC_START(v6_dma_map_area) 285 add r1, r1, r0 286 teq r2, #DMA_FROM_DEVICE 287 beq v6_dma_inv_range 288 b v6_dma_clean_range 289 SYM_FUNC_END(v6_dma_map_area) 290 291 /* 292 * dma_unmap_area(start, size, dir) 293 * - start - kernel virtual start address 294 * - size - size of region 295 * - dir - DMA direction 296 */ 297 SYM_TYPED_FUNC_START(v6_dma_unmap_area) 298 add r1, r1, r0 299 teq r2, #DMA_TO_DEVICE 300 bne v6_dma_inv_range 301 ret lr 302 SYM_FUNC_END(v6_dma_unmap_area)
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.