#include <arch/machine/hardware.h>
static inline void invalidateByWSL(word_t wsl)
{
asm volatile("mcr p15, 0, %0, c7, c6, 2" : : "r"(wsl));
}
static inline void cleanByWSL(word_t wsl)
{
asm volatile("mcr p15, 0, %0, c7, c10, 2" : : "r"(wsl));
}
static inline void cleanInvalidateByWSL(word_t wsl)
{
asm volatile("mcr p15, 0, %0, c7, c14, 2" : : "r"(wsl));
}
static inline word_t readCLID(void)
{
word_t CLID;
asm volatile("mrc p15, 1, %0, c0, c0, 1" : "=r"(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 {
ARMCacheNone = 0,
ARMCacheI = 1,
ARMCacheD = 2,
ARMCacheID = 3,
ARMCacheU = 4,
};
static inline word_t readCacheSize(int level, bool_t instruction)
{
word_t size_unique_name, csselr_old;
asm volatile("mrc p15, 2, %0, c0, c0, 0" : "=r"(csselr_old));
asm volatile("mcr p15, 2, %0, c0, c0, 0" : : "r"((level << 1) | instruction));
asm volatile("mrc p15, 1, %0, c0, c0, 0" : "=r"(size_unique_name));
asm volatile("mcr p15, 2, %0, c0, c0, 0" : : "r"(csselr_old));
return size_unique_name;
}
#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 v;
for (v = 0; v < nsets; v++) {
cleanByWSL((w << (32 - assoc_bits)) |
(v << 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 v;
for (v = 0; v < nsets; v++) {
cleanInvalidateByWSL((w << (32 - assoc_bits)) |
(v << lbits) | (l << 1));
}
}
}
}
}