summaryrefslogtreecommitdiff
path: root/arch/csky/mm/cachev2.c
diff options
context:
space:
mode:
authorPaolo Bonzini <pbonzini@redhat.com>2020-05-13 19:14:05 +0300
committerPaolo Bonzini <pbonzini@redhat.com>2020-05-13 19:14:05 +0300
commit4aef2ec9022b217f74d0f4c9b84081f07cc223d9 (patch)
treeedf9bb9ca1f8ab6345c156a7e87aaed28939f66c /arch/csky/mm/cachev2.c
parent7c67f54661fcc8d141fb11abbab1739f32e13b03 (diff)
parent37486135d3a7b03acc7755b63627a130437f066a (diff)
downloadlinux-4aef2ec9022b217f74d0f4c9b84081f07cc223d9.tar.xz
Merge branch 'kvm-amd-fixes' into HEAD
Diffstat (limited to 'arch/csky/mm/cachev2.c')
-rw-r--r--arch/csky/mm/cachev2.c45
1 files changed, 39 insertions, 6 deletions
diff --git a/arch/csky/mm/cachev2.c b/arch/csky/mm/cachev2.c
index bc419f8039d3..7a9664adce43 100644
--- a/arch/csky/mm/cachev2.c
+++ b/arch/csky/mm/cachev2.c
@@ -7,8 +7,12 @@
#include <asm/cache.h>
#include <asm/barrier.h>
+/* for L1-cache */
#define INS_CACHE (1 << 0)
+#define DATA_CACHE (1 << 1)
#define CACHE_INV (1 << 4)
+#define CACHE_CLR (1 << 5)
+#define CACHE_OMS (1 << 6)
void local_icache_inv_all(void *priv)
{
@@ -16,11 +20,6 @@ void local_icache_inv_all(void *priv)
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)
{
@@ -31,9 +30,43 @@ void icache_inv_range(unsigned long start, unsigned long end)
sync_is();
}
#else
+struct cache_range {
+ unsigned long start;
+ unsigned long end;
+};
+
+static DEFINE_SPINLOCK(cache_lock);
+
+static inline void cache_op_line(unsigned long i, unsigned int val)
+{
+ mtcr("cr22", i);
+ mtcr("cr17", val);
+}
+
+void local_icache_inv_range(void *priv)
+{
+ struct cache_range *param = priv;
+ unsigned long i = param->start & ~(L1_CACHE_BYTES - 1);
+ unsigned long flags;
+
+ spin_lock_irqsave(&cache_lock, flags);
+
+ for (; i < param->end; i += L1_CACHE_BYTES)
+ cache_op_line(i, INS_CACHE | CACHE_INV | CACHE_OMS);
+
+ spin_unlock_irqrestore(&cache_lock, flags);
+
+ sync_is();
+}
+
void icache_inv_range(unsigned long start, unsigned long end)
{
- icache_inv_all();
+ struct cache_range param = { start, end };
+
+ if (irqs_disabled())
+ local_icache_inv_range(&param);
+ else
+ on_each_cpu(local_icache_inv_range, &param, 1);
}
#endif