#include <arch/machine/hardware.h>
static inline void invalidateByWSL(word_t wsl)
{
asm volatile("dc isw, %0" : : "r"(wsl));
}
static inline void cleanByWSL(word_t wsl)
{
asm volatile("dc csw, %0" : : "r"(wsl));
}
static inline void cleanInvalidateByWSL(word_t wsl)
{
asm volatile("dc cisw, %0" : : "r"(wsl));
}
static inline word_t readCLID(void)
{
word_t CLID;
MRS("clidr_el1", CLID);
return CLID;
}
#define LOUU(x) (((x) >> 27) & MASK(3))
#define LOC(x) (((x) >> 24) & MASK(3))
#define LOUIS(x) (((x) >> 21) & MASK(3))
#define CTYPE(x,n) (((x) >> (n*3)) & MASK(3))
enum arm_cache_type {
ARMCacheI = 1,
ARMCacheD = 2,
ARMCacheID = 3,
};
static inline word_t readCacheSize(int level, bool_t instruction)
{
word_t size, csselr_old;
MRS("csselr_el1", csselr_old);
MSR("csselr_el1", ((level << 1) | instruction));
MRS("ccsidr_el1", size);
MSR("csselr_el1", csselr_old);
return size;
}
#define LINEBITS(s) (((s) & MASK(3)) + 4)
#define ASSOC(s) ((((s) >> 3) & MASK(10)) + 1)
#define NSETS(s) ((((s) >> 13) & MASK(15)) + 1)
void
clean_D_PoU(void)
{
int clid = readCLID();
int lou = LOUU(clid);
int l;
for (l = 0; l < lou; l++) {
if (CTYPE(clid, l) > ARMCacheI) {
word_t s = readCacheSize(l, 0);
int lbits = LINEBITS(s);
int assoc = ASSOC(s);
int assoc_bits = wordBits - clzl(assoc - 1);
int nsets = NSETS(s);
int w;
for (w = 0; w < assoc; w++) {
int s;
for (s = 0; s < nsets; s++) {
cleanByWSL((w << (32 - assoc_bits)) |
(s << lbits) | (l << 1));
}
}
}
}
}
void
cleanInvalidate_D_PoC(void)
{
int clid = readCLID();
int loc = LOC(clid);
int l;
for (l = 0; l < loc; l++) {
if (CTYPE(clid, l) > ARMCacheI) {
word_t s = readCacheSize(l, 0);
int lbits = LINEBITS(s);
int assoc = ASSOC(s);
int assoc_bits = wordBits - clzl(assoc - 1);
int nsets = NSETS(s);
int w;
for (w = 0; w < assoc; w++) {
int s;
for (s = 0; s < nsets; s++) {
cleanInvalidateByWSL((w << (32 - assoc_bits)) |
(s << lbits) | (l << 1));
}
}
}
}
}