1// ------------------------------------------------------------ 2// v7-A Cache and Branch Prediction Maintenance Operations 3// 4// Copyright (c) 2011-2018 Arm Limited (or its affiliates). All rights reserved. 5// Use, modification and redistribution of this file is subject to your possession of a 6// valid End User License Agreement for the Arm Product of which these examples are part of 7// and your compliance with all applicable terms and conditions of such licence agreement. 8// ------------------------------------------------------------ 9 10 .arm 11// ------------------------------------------------------------ 12// Interrupt enable/disable 13// ------------------------------------------------------------ 14 15 // Could use intrinsic instead of these 16 17 .global enableInterrupts 18 .type enableInterrupts,function 19 // void enableInterrupts(void)// 20enableInterrupts: 21 CPSIE i 22 BX lr 23 24 25 .global disableInterrupts 26 .type disableInterrupts,function 27 // void disableInterrupts(void)// 28disableInterrupts: 29 CPSID i 30 BX lr 31 32 33// ------------------------------------------------------------ 34// Cache Maintenance 35// ------------------------------------------------------------ 36 37 .global enableCaches 38 .type enableCaches,function 39 // void enableCaches(void)// 40enableCaches: 41 MRC p15, 0, r0, c1, c0, 0 // Read System Control Register 42 ORR r0, r0, #(1 << 2) // Set C bit 43 ORR r0, r0, #(1 << 12) // Set I bit 44 MCR p15, 0, r0, c1, c0, 0 // Write System Control Register 45 ISB 46 BX lr 47 48 49 50 .global disableCaches 51 .type disableCaches,function 52 // void disableCaches(void) 53disableCaches: 54 MRC p15, 0, r0, c1, c0, 0 // Read System Control Register 55 BIC r0, r0, #(1 << 2) // Clear C bit 56 BIC r0, r0, #(1 << 12) // Clear I bit 57 MCR p15, 0, r0, c1, c0, 0 // Write System Control Register 58 ISB 59 BX lr 60 61 62 63 .global cleanDCache 64 .type cleanDCache,function 65 // void cleanDCache(void)// 66cleanDCache: 67 PUSH {r4-r12} 68 69 // 70 // Based on code example given in section 11.2.4 of Armv7-A/R Architecture Reference Manual (DDI 0406B) 71 // 72 73 MRC p15, 1, r0, c0, c0, 1 // Read CLIDR 74 ANDS r3, r0, #0x7000000 75 MOV r3, r3, LSR #23 // Cache level value (naturally aligned) 76 BEQ clean_dcache_finished 77 MOV r10, #0 78 79clean_dcache_loop1: 80 ADD r2, r10, r10, LSR #1 // Work out 3xcachelevel 81 MOV r1, r0, LSR r2 // bottom 3 bits are the Cache type for this level 82 AND r1, r1, #7 // get those 3 bits alone 83 CMP r1, #2 84 BLT clean_dcache_skip // no cache or only instruction cache at this level 85 MCR p15, 2, r10, c0, c0, 0 // write the Cache Size selection register 86 ISB // ISB to sync the change to the CacheSizeID reg 87 MRC p15, 1, r1, c0, c0, 0 // reads current Cache Size ID register 88 AND r2, r1, #7 // extract the line length field 89 ADD r2, r2, #4 // add 4 for the line length offset (log2 16 bytes) 90 LDR r4, =0x3FF 91 ANDS r4, r4, r1, LSR #3 // R4 is the max number on the way size (right aligned) 92 CLZ r5, r4 // R5 is the bit position of the way size increment 93 LDR r7, =0x00007FFF 94 ANDS r7, r7, r1, LSR #13 // R7 is the max number of the index size (right aligned) 95 96clean_dcache_loop2: 97 MOV r9, R4 // R9 working copy of the max way size (right aligned) 98 99clean_dcache_loop3: 100 ORR r11, r10, r9, LSL r5 // factor in the way number and cache number into R11 101 ORR r11, r11, r7, LSL r2 // factor in the index number 102 MCR p15, 0, r11, c7, c10, 2 // DCCSW - clean by set/way 103 SUBS r9, r9, #1 // decrement the way number 104 BGE clean_dcache_loop3 105 SUBS r7, r7, #1 // decrement the index 106 BGE clean_dcache_loop2 107 108clean_dcache_skip: 109 ADD r10, r10, #2 // increment the cache number 110 CMP r3, r10 111 BGT clean_dcache_loop1 112 113clean_dcache_finished: 114 POP {r4-r12} 115 116 BX lr 117 118 119 .global cleanInvalidateDCache 120 .type cleanInvalidateDCache,function 121 // void cleanInvalidateDCache(void)// 122cleanInvalidateDCache: 123 PUSH {r4-r12} 124 125 // 126 // Based on code example given in section 11.2.4 of Armv7-A/R Architecture Reference Manual (DDI 0406B) 127 // 128 129 MRC p15, 1, r0, c0, c0, 1 // Read CLIDR 130 ANDS r3, r0, #0x7000000 131 MOV r3, r3, LSR #23 // Cache level value (naturally aligned) 132 BEQ clean_invalidate_dcache_finished 133 MOV r10, #0 134 135clean_invalidate_dcache_loop1: 136 ADD r2, r10, r10, LSR #1 // Work out 3xcachelevel 137 MOV r1, r0, LSR r2 // bottom 3 bits are the Cache type for this level 138 AND r1, r1, #7 // get those 3 bits alone 139 CMP r1, #2 140 BLT clean_invalidate_dcache_skip // no cache or only instruction cache at this level 141 MCR p15, 2, r10, c0, c0, 0 // write the Cache Size selection register 142 ISB // ISB to sync the change to the CacheSizeID reg 143 MRC p15, 1, r1, c0, c0, 0 // reads current Cache Size ID register 144 AND r2, r1, #7 // extract the line length field 145 ADD r2, r2, #4 // add 4 for the line length offset (log2 16 bytes) 146 LDR r4, =0x3FF 147 ANDS r4, r4, r1, LSR #3 // R4 is the max number on the way size (right aligned) 148 CLZ r5, r4 // R5 is the bit position of the way size increment 149 LDR r7, =0x00007FFF 150 ANDS r7, r7, r1, LSR #13 // R7 is the max number of the index size (right aligned) 151 152clean_invalidate_dcache_loop2: 153 MOV r9, R4 // R9 working copy of the max way size (right aligned) 154 155clean_invalidate_dcache_loop3: 156 ORR r11, r10, r9, LSL r5 // factor in the way number and cache number into R11 157 ORR r11, r11, r7, LSL r2 // factor in the index number 158 MCR p15, 0, r11, c7, c14, 2 // DCCISW - clean and invalidate by set/way 159 SUBS r9, r9, #1 // decrement the way number 160 BGE clean_invalidate_dcache_loop3 161 SUBS r7, r7, #1 // decrement the index 162 BGE clean_invalidate_dcache_loop2 163 164clean_invalidate_dcache_skip: 165 ADD r10, r10, #2 // increment the cache number 166 CMP r3, r10 167 BGT clean_invalidate_dcache_loop1 168 169clean_invalidate_dcache_finished: 170 POP {r4-r12} 171 172 BX lr 173 174 175 176 .global invalidateCaches 177 .type invalidateCaches,function 178 // void invalidateCaches(void)// 179invalidateCaches: 180 PUSH {r4-r12} 181 182 // 183 // Based on code example given in section B2.2.4/11.2.4 of Armv7-A/R Architecture Reference Manual (DDI 0406B) 184 // 185 186 MOV r0, #0 187 MCR p15, 0, r0, c7, c5, 0 // ICIALLU - Invalidate entire I Cache, and flushes branch target cache 188 189 MRC p15, 1, r0, c0, c0, 1 // Read CLIDR 190 ANDS r3, r0, #0x7000000 191 MOV r3, r3, LSR #23 // Cache level value (naturally aligned) 192 BEQ invalidate_caches_finished 193 MOV r10, #0 194 195invalidate_caches_loop1: 196 ADD r2, r10, r10, LSR #1 // Work out 3xcachelevel 197 MOV r1, r0, LSR r2 // bottom 3 bits are the Cache type for this level 198 AND r1, r1, #7 // get those 3 bits alone 199 CMP r1, #2 200 BLT invalidate_caches_skip // no cache or only instruction cache at this level 201 MCR p15, 2, r10, c0, c0, 0 // write the Cache Size selection register 202 ISB // ISB to sync the change to the CacheSizeID reg 203 MRC p15, 1, r1, c0, c0, 0 // reads current Cache Size ID register 204 AND r2, r1, #7 // extract the line length field 205 ADD r2, r2, #4 // add 4 for the line length offset (log2 16 bytes) 206 LDR r4, =0x3FF 207 ANDS r4, r4, r1, LSR #3 // R4 is the max number on the way size (right aligned) 208 CLZ r5, r4 // R5 is the bit position of the way size increment 209 LDR r7, =0x00007FFF 210 ANDS r7, r7, r1, LSR #13 // R7 is the max number of the index size (right aligned) 211 212invalidate_caches_loop2: 213 MOV r9, R4 // R9 working copy of the max way size (right aligned) 214 215invalidate_caches_loop3: 216 ORR r11, r10, r9, LSL r5 // factor in the way number and cache number into R11 217 ORR r11, r11, r7, LSL r2 // factor in the index number 218 MCR p15, 0, r11, c7, c6, 2 // DCISW - invalidate by set/way 219 SUBS r9, r9, #1 // decrement the way number 220 BGE invalidate_caches_loop3 221 SUBS r7, r7, #1 // decrement the index 222 BGE invalidate_caches_loop2 223 224invalidate_caches_skip: 225 ADD r10, r10, #2 // increment the cache number 226 CMP r3, r10 227 BGT invalidate_caches_loop1 228 229invalidate_caches_finished: 230 POP {r4-r12} 231 BX lr 232 233 234 235 .global invalidateCaches_IS 236 .type invalidateCaches_IS,function 237 // void invalidateCaches_IS(void)// 238invalidateCaches_IS: 239 PUSH {r4-r12} 240 241 MOV r0, #0 242 MCR p15, 0, r0, c7, c1, 0 // ICIALLUIS - Invalidate entire I Cache inner shareable 243 244 MRC p15, 1, r0, c0, c0, 1 // Read CLIDR 245 ANDS r3, r0, #0x7000000 246 MOV r3, r3, LSR #23 // Cache level value (naturally aligned) 247 BEQ invalidate_caches_is_finished 248 MOV r10, #0 249 250invalidate_caches_is_loop1: 251 ADD r2, r10, r10, LSR #1 // Work out 3xcachelevel 252 MOV r1, r0, LSR r2 // bottom 3 bits are the Cache type for this level 253 AND r1, r1, #7 // get those 3 bits alone 254 CMP r1, #2 255 BLT invalidate_caches_is_skip // no cache or only instruction cache at this level 256 MCR p15, 2, r10, c0, c0, 0 // write the Cache Size selection register 257 ISB // ISB to sync the change to the CacheSizeID reg 258 MRC p15, 1, r1, c0, c0, 0 // reads current Cache Size ID register 259 AND r2, r1, #7 // extract the line length field 260 ADD r2, r2, #4 // add 4 for the line length offset (log2 16 bytes) 261 LDR r4, =0x3FF 262 ANDS r4, r4, r1, LSR #3 // R4 is the max number on the way size (right aligned) 263 CLZ r5, r4 // R5 is the bit position of the way size increment 264 LDR r7, =0x00007FFF 265 ANDS r7, r7, r1, LSR #13 // R7 is the max number of the index size (right aligned) 266 267invalidate_caches_is_loop2: 268 MOV r9, R4 // R9 working copy of the max way size (right aligned) 269 270invalidate_caches_is_loop3: 271 ORR r11, r10, r9, LSL r5 // factor in the way number and cache number into R11 272 ORR r11, r11, r7, LSL r2 // factor in the index number 273 MCR p15, 0, r11, c7, c6, 2 // DCISW - clean by set/way 274 SUBS r9, r9, #1 // decrement the way number 275 BGE invalidate_caches_is_loop3 276 SUBS r7, r7, #1 // decrement the index 277 BGE invalidate_caches_is_loop2 278 279invalidate_caches_is_skip: 280 ADD r10, r10, #2 // increment the cache number 281 CMP r3, r10 282 BGT invalidate_caches_is_loop1 283 284invalidate_caches_is_finished: 285 POP {r4-r12} 286 BX lr 287 288 289// ------------------------------------------------------------ 290// TLB 291// ------------------------------------------------------------ 292 293 .global invalidateUnifiedTLB 294 .type invalidateUnifiedTLB,function 295 // void invalidateUnifiedTLB(void)// 296invalidateUnifiedTLB: 297 MOV r0, #0 298 MCR p15, 0, r0, c8, c7, 0 // TLBIALL - Invalidate entire unified TLB 299 BX lr 300 301 302 .global invalidateUnifiedTLB_IS 303 .type invalidateUnifiedTLB_IS,function 304 // void invalidateUnifiedTLB_IS(void)// 305invalidateUnifiedTLB_IS: 306 MOV r0, #1 307 MCR p15, 0, r0, c8, c3, 0 // TLBIALLIS - Invalidate entire unified TLB Inner Shareable 308 BX lr 309 310 311// ------------------------------------------------------------ 312// Branch Prediction 313// ------------------------------------------------------------ 314 315 .global flushBranchTargetCache 316 .type flushBranchTargetCache,function 317 // void flushBranchTargetCache(void) 318flushBranchTargetCache: 319 MOV r0, #0 320 MCR p15, 0, r0, c7, c5, 6 // BPIALL - Invalidate entire branch predictor array 321 BX lr 322 323 324 .global flushBranchTargetCache_IS 325 .type flushBranchTargetCache_IS,function 326 // void flushBranchTargetCache_IS(void) 327flushBranchTargetCache_IS: 328 MOV r0, #0 329 MCR p15, 0, r0, c7, c1, 6 // BPIALLIS - Invalidate entire branch predictor array Inner Shareable 330 BX lr 331 332 333// ------------------------------------------------------------ 334// High Vecs 335// ------------------------------------------------------------ 336 337 .global enableHighVecs 338 .type enableHighVecs,function 339 // void enableHighVecs(void)// 340enableHighVecs: 341 MRC p15, 0, r0, c1, c0, 0 // Read Control Register 342 ORR r0, r0, #(1 << 13) // Set the V bit (bit 13) 343 MCR p15, 0, r0, c1, c0, 0 // Write Control Register 344 ISB 345 BX lr 346 347 348 .global disableHighVecs 349 .type disableHighVecs,function 350 // void disable_highvecs(void)// 351disableHighVecs: 352 MRC p15, 0, r0, c1, c0, 0 // Read Control Register 353 BIC r0, r0, #(1 << 13) // Clear the V bit (bit 13) 354 MCR p15, 0, r0, c1, c0, 0 // Write Control Register 355 ISB 356 BX lr 357 358 359// ------------------------------------------------------------ 360// Context ID 361// ------------------------------------------------------------ 362 363 .global getContextID 364 .type getContextID,function 365 // uint32_t getContextIDd(void)// 366getContextID: 367 MRC p15, 0, r0, c13, c0, 1 // Read Context ID Register 368 BX lr 369 370 371 .global setContextID 372 .type setContextID,function 373 // void setContextID(uint32_t)// 374setContextID: 375 MCR p15, 0, r0, c13, c0, 1 // Write Context ID Register 376 BX lr 377 378 379// ------------------------------------------------------------ 380// ID registers 381// ------------------------------------------------------------ 382 383 .global getMIDR 384 .type getMIDR,function 385 // uint32_t getMIDR(void)// 386getMIDR: 387 MRC p15, 0, r0, c0, c0, 0 // Read Main ID Register (MIDR) 388 BX lr 389 390 391 .global getMPIDR 392 .type getMPIDR,function 393 // uint32_t getMPIDR(void)// 394getMPIDR: 395 MRC p15, 0, r0, c0 ,c0, 5// Read Multiprocessor ID register (MPIDR) 396 BX lr 397 398 399// ------------------------------------------------------------ 400// CP15 SMP related 401// ------------------------------------------------------------ 402 403 .global getBaseAddr 404 .type getBaseAddr,function 405 // uint32_t getBaseAddr(void) 406 // Returns the value CBAR (base address of the private peripheral memory space) 407getBaseAddr: 408 MRC p15, 4, r0, c15, c0, 0 // Read peripheral base address 409 BX lr 410 411 412// ------------------------------------------------------------ 413 414 .global getCPUID 415 .type getCPUID,function 416 // uint32_t getCPUID(void) 417 // Returns the CPU ID (0 to 3) of the CPU executed on 418getCPUID: 419 MRC p15, 0, r0, c0, c0, 5 // Read CPU ID register 420 AND r0, r0, #0x03 // Mask off, leaving the CPU ID field 421 BX lr 422 423 424// ------------------------------------------------------------ 425 426 .global goToSleep 427 .type goToSleep,function 428 // void goToSleep(void) 429goToSleep: 430 DSB // Clear all pending data accesses 431 WFI // Go into standby 432 B goToSleep // Catch in case of rogue events 433 BX lr 434 435 436// ------------------------------------------------------------ 437 438 .global joinSMP 439 .type joinSMP,function 440 // void joinSMP(void) 441 // Sets the ACTRL.SMP bit 442joinSMP: 443 444 // SMP status is controlled by bit 6 of the CP15 Aux Ctrl Reg 445 446 MRC p15, 0, r0, c1, c0, 1 // Read ACTLR 447 MOV r1, r0 448 ORR r0, r0, #0x040 // Set bit 6 449 CMP r0, r1 450 MCRNE p15, 0, r0, c1, c0, 1 // Write ACTLR 451 ISB 452 453 BX lr 454 455 456// ------------------------------------------------------------ 457 458 .global leaveSMP 459 .type leaveSMP,function 460 // void leaveSMP(void) 461 // Clear the ACTRL.SMP bit 462leaveSMP: 463 464 // SMP status is controlled by bit 6 of the CP15 Aux Ctrl Reg 465 466 MRC p15, 0, r0, c1, c0, 1 // Read ACTLR 467 BIC r0, r0, #0x040 // Clear bit 6 468 MCR p15, 0, r0, c1, c0, 1 // Write ACTLR 469 ISB 470 471 BX lr 472 473 474// ------------------------------------------------------------ 475// End of v7.s 476// ------------------------------------------------------------ 477