1/* 2 * Copyright 2020, Data61, CSIRO (ABN 41 687 119 230) 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("dc csw, %0" : : "r"(wsl)); 12} 13 14static inline void cleanInvalidateByWSL(word_t wsl) 15{ 16 asm volatile("dc cisw, %0" : : "r"(wsl)); 17} 18 19static inline word_t readCLID(void) 20{ 21 word_t CLID; 22 MRS("clidr_el1", CLID); 23 return CLID; 24} 25 26#define LOUU(x) (((x) >> 27) & MASK(3)) 27#define LOC(x) (((x) >> 24) & MASK(3)) 28#define LOUIS(x) (((x) >> 21) & MASK(3)) 29#define CTYPE(x,n) (((x) >> (n*3)) & MASK(3)) 30 31enum arm_cache_type { 32 ARMCacheI = 1, 33 ARMCacheD = 2, 34 ARMCacheID = 3, 35}; 36 37static inline word_t readCacheSize(int level, bool_t instruction) 38{ 39 word_t size, csselr_old; 40 /* Save CSSELR */ 41 MRS("csselr_el1", csselr_old); 42 /* Select cache level */ 43 MSR("csselr_el1", ((level << 1) | instruction)); 44 /* Read 'size' */ 45 MRS("ccsidr_el1", size); 46 /* Restore CSSELR */ 47 MSR("csselr_el1", csselr_old); 48 return size; 49} 50 51#define LINEBITS(s) (((s) & MASK(3)) + 4) 52#define ASSOC(s) ((((s) >> 3) & MASK(10)) + 1) 53#define NSETS(s) ((((s) >> 13) & MASK(15)) + 1) 54 55void clean_D_PoU(void) 56{ 57 int clid = readCLID(); 58 int lou = LOUU(clid); 59 60 for (int l = 0; l < lou; l++) { 61 if (CTYPE(clid, l) > ARMCacheI) { 62 word_t lsize = readCacheSize(l, 0); 63 int lbits = LINEBITS(lsize); 64 int assoc = ASSOC(lsize); 65 int assoc_bits = wordBits - clzl(assoc - 1); 66 int nsets = NSETS(lsize); 67 for (int w = 0; w < assoc; w++) { 68 for (int s = 0; s < nsets; s++) { 69 cleanByWSL((w << (32 - assoc_bits)) | 70 (s << lbits) | (l << 1)); 71 } 72 } 73 } 74 } 75} 76 77static inline void cleanInvalidate_D_by_level(int l) 78{ 79 word_t lsize = readCacheSize(l, 0); 80 int lbits = LINEBITS(lsize); 81 int assoc = ASSOC(lsize); 82 int assoc_bits = wordBits - clzl(assoc - 1); 83 int nsets = NSETS(lsize); 84 85 for (int w = 0; w < assoc; w++) { 86 for (int s = 0; s < nsets; s++) { 87 cleanInvalidateByWSL((w << (32 - assoc_bits)) | 88 (s << lbits) | (l << 1)); 89 } 90 } 91} 92 93void cleanInvalidate_D_PoC(void) 94{ 95 int clid = readCLID(); 96 int loc = LOC(clid); 97 98 for (int l = 0; l < loc; l++) { 99 if (CTYPE(clid, l) > ARMCacheI) { 100 cleanInvalidate_D_by_level(l); 101 } 102 } 103} 104 105void cleanInvalidate_L1D(void) 106{ 107 cleanInvalidate_D_by_level(0); 108} 109