1/* 2 * Copyright 2014, General Dynamics C4 Systems 3 * 4 * SPDX-License-Identifier: GPL-2.0-only 5 */ 6 7#include <arch/machine/hardware.h> 8 9static inline void cleanByWSL(word_t wsl) 10{ 11 asm volatile("mcr p15, 0, %0, c7, c10, 2" : : "r"(wsl)); 12} 13 14static inline void cleanInvalidateByWSL(word_t wsl) 15{ 16 asm volatile("mcr p15, 0, %0, c7, c14, 2" : : "r"(wsl)); 17} 18 19 20static inline word_t readCLID(void) 21{ 22 word_t CLID; 23 asm volatile("mrc p15, 1, %0, c0, c0, 1" : "=r"(CLID)); 24 return CLID; 25} 26 27#define LOUU(x) (((x) >> 27) & MASK(3)) 28#define LOC(x) (((x) >> 24) & MASK(3)) 29#define LOUIS(x) (((x) >> 21) & MASK(3)) 30#define CTYPE(x,n) (((x) >> (n*3)) & MASK(3)) 31 32enum arm_cache_type { 33 ARMCacheNone = 0, 34 ARMCacheI = 1, 35 ARMCacheD = 2, 36 ARMCacheID = 3, 37 ARMCacheU = 4, 38}; 39 40 41static inline word_t readCacheSize(int level, bool_t instruction) 42{ 43 word_t size_unique_name, csselr_old; 44 /* Save CSSELR */ 45 asm volatile("mrc p15, 2, %0, c0, c0, 0" : "=r"(csselr_old)); 46 /* Select cache level */ 47 asm volatile("mcr p15, 2, %0, c0, c0, 0" : : "r"((level << 1) | instruction)); 48 /* Read 'size' */ 49 asm volatile("mrc p15, 1, %0, c0, c0, 0" : "=r"(size_unique_name)); 50 /* Restore CSSELR */ 51 asm volatile("mcr p15, 2, %0, c0, c0, 0" : : "r"(csselr_old)); 52 return size_unique_name; 53} 54 55/* Number of bits to index within a cache line. The field is log2(nwords) - 2 56 * , and thus by adding 4 we get log2(nbytes). */ 57#define LINEBITS(s) (( (s) & MASK(3)) + 4) 58/* Associativity, field is assoc - 1. */ 59#define ASSOC(s) ((((s) >> 3) & MASK(10)) + 1) 60/* Number of sets, field is nsets - 1. */ 61#define NSETS(s) ((((s) >> 13) & MASK(15)) + 1) 62 63 64void clean_D_PoU(void) 65{ 66 int clid = readCLID(); 67 int lou = LOUU(clid); 68 int l; 69 70 for (l = 0; l < lou; l++) { 71 if (CTYPE(clid, l) > ARMCacheI) { 72 word_t s = readCacheSize(l, 0); 73 int lbits = LINEBITS(s); 74 int assoc = ASSOC(s); 75 int assoc_bits = wordBits - clzl(assoc - 1); 76 int nsets = NSETS(s); 77 int w; 78 79 for (w = 0; w < assoc; w++) { 80 int v; 81 82 for (v = 0; v < nsets; v++) { 83 cleanByWSL((w << (32 - assoc_bits)) | 84 (v << lbits) | (l << 1)); 85 } 86 } 87 } 88 } 89} 90 91static inline void cleanInvalidate_D_by_level(int l) 92{ 93 word_t s = readCacheSize(l, 0); 94 int lbits = LINEBITS(s); 95 int assoc = ASSOC(s); 96 int assoc_bits = wordBits - clzl(assoc - 1); 97 int nsets = NSETS(s); 98 int w; 99 100 for (w = 0; w < assoc; w++) { 101 int v; 102 103 for (v = 0; v < nsets; v++) { 104 cleanInvalidateByWSL((w << (32 - assoc_bits)) | 105 (v << lbits) | (l << 1)); 106 } 107 } 108} 109 110void cleanInvalidate_D_PoC(void) 111{ 112 int clid = readCLID(); 113 int loc = LOC(clid); 114 int l; 115 116 for (l = 0; l < loc; l++) { 117 if (CTYPE(clid, l) > ARMCacheI) { 118 cleanInvalidate_D_by_level(l); 119 } 120 } 121} 122 123void cleanInvalidate_L1D(void) 124{ 125 cleanInvalidate_D_by_level(0); 126} 127