linux-mips.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
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


  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).