From: Paul Burton <paul.burton@mips.com>
To: "linux-mips@vger.kernel.org" <linux-mips@vger.kernel.org>,
Chris Packham <chris.packham@alliedtelesis.co.nz>
Cc: Paul Burton <pburton@wavecomp.com>
Subject: [PATCH] MIPS: mm: Implement flush_cache_v(un)map using __flush_kernel_vmap_range
Date: Wed, 29 May 2019 22:47:11 +0000 [thread overview]
Message-ID: <20190529224659.27614-1-paul.burton@mips.com> (raw)
In-Reply-To: <20190528221255.22460-1-chris.packham@alliedtelesis.co.nz>
Our flush_cache_vmap() & flush_cache_vunmap() implementations for R4k
style systems simply call r4k_blast_dcache() to wipe out the whole L1
dcache if it suffers from aliases. This is unsafe on SMP for 2 reasons:
1) r4k_blast_dcache() relies upon preemption being disabled so that it
can use current_cpu_data/smp_processor_id() to discover the
properties of the current CPU's dcache & ensure the whole flush
operation happens on one CPU. This may not be the case when
flush_cache_vmap() or flush_cache_vunmap() are called.
2) It only flushes caches on one CPU, which means the caches for other
CPUs may still contain stale data.
We already have an implementation of flush_kernel_vmap_range() which
does exactly what we need - it invalidates dcache entries on all CPUs
safely, and is better optimized to avoid wiping out the entire cache for
small flushes.
Reimplement flush_cache_vmap() & flush_cache_vunmap() using
__flush_kernel_vmap_range() which does what we need already.
For tx39 __flush_kernel_vmap_range() will simply BUG(), but so far as I
can see tx39 systems don't suffer from dcache aliasing so this should be
fine since it should never be called.
Signed-off-by: Paul Burton <paul.burton@mips.com>
Reported-by: Chris Packham <chris.packham@alliedtelesis.co.nz>
---
Chris, would you mind giving this a try?
---
arch/mips/include/asm/cacheflush.h | 28 ++++++++++++----------------
arch/mips/mm/c-r4k.c | 15 ---------------
arch/mips/mm/c-tx39.c | 16 ----------------
arch/mips/mm/cache.c | 3 ---
4 files changed, 12 insertions(+), 50 deletions(-)
diff --git a/arch/mips/include/asm/cacheflush.h b/arch/mips/include/asm/cacheflush.h
index d687b40b9fbb..6285c830c9f2 100644
--- a/arch/mips/include/asm/cacheflush.h
+++ b/arch/mips/include/asm/cacheflush.h
@@ -85,22 +85,6 @@ extern void (*__flush_icache_user_range)(unsigned long start,
extern void (*__local_flush_icache_user_range)(unsigned long start,
unsigned long end);
-extern void (*__flush_cache_vmap)(void);
-
-static inline void flush_cache_vmap(unsigned long start, unsigned long end)
-{
- if (cpu_has_dc_aliases)
- __flush_cache_vmap();
-}
-
-extern void (*__flush_cache_vunmap)(void);
-
-static inline void flush_cache_vunmap(unsigned long start, unsigned long end)
-{
- if (cpu_has_dc_aliases)
- __flush_cache_vunmap();
-}
-
extern void copy_to_user_page(struct vm_area_struct *vma,
struct page *page, unsigned long vaddr, void *dst, const void *src,
unsigned long len);
@@ -150,4 +134,16 @@ static inline void invalidate_kernel_vmap_range(void *vaddr, int size)
__flush_kernel_vmap_range((unsigned long) vaddr, size);
}
+static inline void flush_cache_vmap(unsigned long start, unsigned long end)
+{
+ if (cpu_has_dc_aliases)
+ __flush_kernel_vmap_range(start, end - start);
+}
+
+static inline void flush_cache_vunmap(unsigned long start, unsigned long end)
+{
+ if (cpu_has_dc_aliases)
+ __flush_kernel_vmap_range(start, end - start);
+}
+
#endif /* _ASM_CACHEFLUSH_H */
diff --git a/arch/mips/mm/c-r4k.c b/arch/mips/mm/c-r4k.c
index 5166e38cd1c6..2b2953d3949d 100644
--- a/arch/mips/mm/c-r4k.c
+++ b/arch/mips/mm/c-r4k.c
@@ -559,16 +559,6 @@ static inline int has_valid_asid(const struct mm_struct *mm, unsigned int type)
return 0;
}
-static void r4k__flush_cache_vmap(void)
-{
- r4k_blast_dcache();
-}
-
-static void r4k__flush_cache_vunmap(void)
-{
- r4k_blast_dcache();
-}
-
/*
* Note: flush_tlb_range() assumes flush_cache_range() sufficiently flushes
* whole caches when vma is executable.
@@ -1854,9 +1844,6 @@ void r4k_cache_init(void)
else
shm_align_mask = PAGE_SIZE-1;
- __flush_cache_vmap = r4k__flush_cache_vmap;
- __flush_cache_vunmap = r4k__flush_cache_vunmap;
-
flush_cache_all = cache_noop;
__flush_cache_all = r4k___flush_cache_all;
flush_cache_mm = r4k_flush_cache_mm;
@@ -1931,8 +1918,6 @@ void r4k_cache_init(void)
case CPU_LOONGSON3:
/* Loongson-3 maintains cache coherency by hardware */
__flush_cache_all = cache_noop;
- __flush_cache_vmap = cache_noop;
- __flush_cache_vunmap = cache_noop;
__flush_kernel_vmap_range = (void *)cache_noop;
flush_cache_mm = (void *)cache_noop;
flush_cache_page = (void *)cache_noop;
diff --git a/arch/mips/mm/c-tx39.c b/arch/mips/mm/c-tx39.c
index b7c8a9d79c35..6bf13a7db485 100644
--- a/arch/mips/mm/c-tx39.c
+++ b/arch/mips/mm/c-tx39.c
@@ -121,16 +121,6 @@ static inline void tx39_blast_icache(void)
local_irq_restore(flags);
}
-static void tx39__flush_cache_vmap(void)
-{
- tx39_blast_dcache();
-}
-
-static void tx39__flush_cache_vunmap(void)
-{
- tx39_blast_dcache();
-}
-
static inline void tx39_flush_cache_all(void)
{
if (!cpu_has_dc_aliases)
@@ -339,8 +329,6 @@ void tx39_cache_init(void)
switch (current_cpu_type()) {
case CPU_TX3912:
/* TX39/H core (writethru direct-map cache) */
- __flush_cache_vmap = tx39__flush_cache_vmap;
- __flush_cache_vunmap = tx39__flush_cache_vunmap;
flush_cache_all = tx39h_flush_icache_all;
__flush_cache_all = tx39h_flush_icache_all;
flush_cache_mm = (void *) tx39h_flush_icache_all;
@@ -363,10 +351,6 @@ void tx39_cache_init(void)
default:
/* TX39/H2,H3 core (writeback 2way-set-associative cache) */
/* board-dependent init code may set WBON */
-
- __flush_cache_vmap = tx39__flush_cache_vmap;
- __flush_cache_vunmap = tx39__flush_cache_vunmap;
-
flush_cache_all = tx39_flush_cache_all;
__flush_cache_all = tx39___flush_cache_all;
flush_cache_mm = tx39_flush_cache_mm;
diff --git a/arch/mips/mm/cache.c b/arch/mips/mm/cache.c
index 3da216988672..c6c0ef539d3a 100644
--- a/arch/mips/mm/cache.c
+++ b/arch/mips/mm/cache.c
@@ -40,9 +40,6 @@ EXPORT_SYMBOL_GPL(__flush_icache_user_range);
void (*__local_flush_icache_user_range)(unsigned long start, unsigned long end);
EXPORT_SYMBOL_GPL(__local_flush_icache_user_range);
-void (*__flush_cache_vmap)(void);
-void (*__flush_cache_vunmap)(void);
-
void (*__flush_kernel_vmap_range)(unsigned long vaddr, int size);
EXPORT_SYMBOL_GPL(__flush_kernel_vmap_range);
--
2.21.0
next prev parent reply other threads:[~2019-05-29 22:48 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2019-05-28 22:12 [PATCH] MIPS: mm: Use SMP safe operations for flush_cache_vmap Chris Packham
2019-05-29 22:47 ` Paul Burton [this message]
2019-05-29 23:17 ` [PATCH] MIPS: mm: Implement flush_cache_v(un)map using __flush_kernel_vmap_range Chris Packham
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20190529224659.27614-1-paul.burton@mips.com \
--to=paul.burton@mips.com \
--cc=chris.packham@alliedtelesis.co.nz \
--cc=linux-mips@vger.kernel.org \
--cc=pburton@wavecomp.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).