csky: Support icache flush without specific instructions

Some CPUs don't support icache specific instructions to flush icache
lines in broadcast way. We use cpu control registers to flush local
icache and use IPI to notify other cores.

Signed-off-by: Guo Ren <guoren@linux.alibaba.com>
Šī revīzija ir iekļauta:
Guo Ren
2020-01-22 11:15:14 +08:00
vecāks a736fa1ed7
revīzija 761b4f694c
4 mainīti faili ar 32 papildinājumiem un 9 dzēšanām

Parādīt failu

@@ -3,15 +3,25 @@
#include <linux/spinlock.h>
#include <linux/smp.h>
#include <linux/mm.h>
#include <asm/cache.h>
#include <asm/barrier.h>
inline void dcache_wb_line(unsigned long start)
#define INS_CACHE (1 << 0)
#define CACHE_INV (1 << 4)
void local_icache_inv_all(void *priv)
{
asm volatile("dcache.cval1 %0\n"::"r"(start):"memory");
mtcr("cr17", INS_CACHE|CACHE_INV);
sync_is();
}
void icache_inv_all(void)
{
on_each_cpu(local_icache_inv_all, NULL, 1);
}
#ifdef CONFIG_CPU_HAS_ICACHE_INS
void icache_inv_range(unsigned long start, unsigned long end)
{
unsigned long i = start & ~(L1_CACHE_BYTES - 1);
@@ -20,10 +30,16 @@ void icache_inv_range(unsigned long start, unsigned long end)
asm volatile("icache.iva %0\n"::"r"(i):"memory");
sync_is();
}
void icache_inv_all(void)
#else
void icache_inv_range(unsigned long start, unsigned long end)
{
asm volatile("icache.ialls\n":::"memory");
icache_inv_all();
}
#endif
inline void dcache_wb_line(unsigned long start)
{
asm volatile("dcache.cval1 %0\n"::"r"(start):"memory");
sync_is();
}
@@ -53,10 +69,7 @@ void cache_wbinv_range(unsigned long start, unsigned long end)
asm volatile("dcache.cval1 %0\n"::"r"(i):"memory");
sync_is();
i = start & ~(L1_CACHE_BYTES - 1);
for (; i < end; i += L1_CACHE_BYTES)
asm volatile("icache.iva %0\n"::"r"(i):"memory");
sync_is();
icache_inv_range(start, end);
}
EXPORT_SYMBOL(cache_wbinv_range);