mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH v3] MIPS: c-r4k: Flush the cache error vector before writing it uncached
@ 2026-11-02  9:43 Imre Kaloz
  0 siblings, 0 replies; only message in thread
From: Imre Kaloz @ 2026-11-02  9:43 UTC (permalink / raw)
  To: Thomas Bogendoerfer, linux-mips
  Cc: Ethan Nelson-Moore, Maciej W. Rozycki, linux-kernel, stable

On R10000-class CPUs, a store prefetch while copying the preceding
vector can leave a dirty line whose write-back overwrites the uncached
cache error handler.

Write back and invalidate that line in set_uncached_handler() before
the copy, through a new flush_dcache_size() hook. c-r4k and c-r3k
provide it with r4k_dma_cache_wback_inv() and r3k_dma_cache_wback_inv(),
renamed as they are no longer DMA-only.

Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
Cc: stable@vger.kernel.org
Signed-off-by: Imre Kaloz <kaloz@kernel.org>
---
Changes in v3:
- Renamed the hook to flush_dcache_size() and the c-r4k implementation
  to r4k_flush_dcache_size().
- r3k_dma_cache_wback_inv() becomes r3k_flush_dcache_size() and is
  installed as the hook as well.

Changes in v2:
- Fixes: 1da177e4c3f4 instead of e01402b115cc.
- Moved the write-back into set_uncached_handler(), for every caller.
- Renamed r4k_dma_cache_wback_inv() to r4k_cache_wback_inv().

v2: https://lore.kernel.org/r/20261026120430.13238-1-kaloz@kernel.org

 arch/mips/include/asm/cacheflush.h |  1 +
 arch/mips/kernel/traps.c           |  6 ++++++
 arch/mips/mm/c-r3k.c               |  9 +++++----
 arch/mips/mm/c-r4k.c               | 11 ++++++-----
 arch/mips/mm/cache.c               |  1 +
 5 files changed, 19 insertions(+), 9 deletions(-)

diff --git a/arch/mips/include/asm/cacheflush.h b/arch/mips/include/asm/cacheflush.h
index 5099c1b65a58..fb8eeb205897 100644
--- a/arch/mips/include/asm/cacheflush.h
+++ b/arch/mips/include/asm/cacheflush.h
@@ -120,6 +120,7 @@ extern void copy_from_user_page(struct vm_area_struct *vma,
 
 extern void (*flush_icache_all)(void);
 extern void (*flush_data_cache_page)(unsigned long addr);
+extern void (*flush_dcache_size)(unsigned long start, unsigned long size);
 
 /* Run kernel code uncached, useful for cache probing functions. */
 unsigned long run_uncached(void *func);
diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c
index 8ec1e185b35c..19a8946e14ae 100644
--- a/arch/mips/kernel/traps.c
+++ b/arch/mips/kernel/traps.c
@@ -2305,6 +2305,12 @@ void set_uncached_handler(unsigned long offset, void *addr,
 	if (!addr)
 		panic(panic_null_cerr);
 
+	/*
+	 * A store prefetch or speculative store may have left a dirty line of
+	 * the cached view; write it back and invalidate it first, or its later
+	 * write-back overwrites the handler.
+	 */
+	flush_dcache_size(ebase + offset, size);
 	memcpy((void *)(uncached_ebase + offset), addr, size);
 }
 
diff --git a/arch/mips/mm/c-r3k.c b/arch/mips/mm/c-r3k.c
index 5869df848fab..a1be13775d2c 100644
--- a/arch/mips/mm/c-r3k.c
+++ b/arch/mips/mm/c-r3k.c
@@ -270,7 +270,7 @@ static void r3k_flush_kernel_vmap_range(unsigned long vaddr, int size)
 	BUG();
 }
 
-static void r3k_dma_cache_wback_inv(unsigned long start, unsigned long size)
+static void r3k_flush_dcache_size(unsigned long start, unsigned long size)
 {
 	/* Catch bad driver code */
 	BUG_ON(size == 0);
@@ -299,10 +299,11 @@ void r3k_cache_init(void)
 	__flush_kernel_vmap_range = r3k_flush_kernel_vmap_range;
 
 	flush_data_cache_page = r3k_flush_data_cache_page;
+	flush_dcache_size = r3k_flush_dcache_size;
 
-	_dma_cache_wback_inv = r3k_dma_cache_wback_inv;
-	_dma_cache_wback = r3k_dma_cache_wback_inv;
-	_dma_cache_inv = r3k_dma_cache_wback_inv;
+	_dma_cache_wback_inv = r3k_flush_dcache_size;
+	_dma_cache_wback = r3k_flush_dcache_size;
+	_dma_cache_inv = r3k_flush_dcache_size;
 
 	pr_info("Primary instruction cache %ldkB, linesize %ld bytes.\n",
 		icache_size >> 10, icache_lsize);
diff --git a/arch/mips/mm/c-r4k.c b/arch/mips/mm/c-r4k.c
index d8aadd3dc057..8b600de64dff 100644
--- a/arch/mips/mm/c-r4k.c
+++ b/arch/mips/mm/c-r4k.c
@@ -743,9 +743,7 @@ static void r4k_flush_icache_user_range(unsigned long start, unsigned long end)
 	return __r4k_flush_icache_range(start, end, true);
 }
 
-#ifdef CONFIG_DMA_NONCOHERENT
-
-static void r4k_dma_cache_wback_inv(unsigned long addr, unsigned long size)
+static void r4k_flush_dcache_size(unsigned long addr, unsigned long size)
 {
 	/* Catch bad driver code */
 	if (WARN_ON(size == 0))
@@ -786,6 +784,8 @@ static void r4k_dma_cache_wback_inv(unsigned long addr, unsigned long size)
 	__sync();
 }
 
+#ifdef CONFIG_DMA_NONCOHERENT
+
 static void prefetch_cache_inv(unsigned long addr, unsigned long size)
 {
 	unsigned int linesz = cpu_scache_line_size();
@@ -1743,14 +1743,15 @@ void r4k_cache_init(void)
 
 	flush_icache_all	= r4k_flush_icache_all;
 	flush_data_cache_page	= r4k_flush_data_cache_page;
+	flush_dcache_size	= r4k_flush_dcache_size;
 	flush_icache_range	= r4k_flush_icache_range;
 	local_flush_icache_range	= local_r4k_flush_icache_range;
 	__flush_icache_user_range	= r4k_flush_icache_user_range;
 	__local_flush_icache_user_range	= local_r4k_flush_icache_user_range;
 
 #ifdef CONFIG_DMA_NONCOHERENT
-	_dma_cache_wback_inv	= r4k_dma_cache_wback_inv;
-	_dma_cache_wback	= r4k_dma_cache_wback_inv;
+	_dma_cache_wback_inv	= r4k_flush_dcache_size;
+	_dma_cache_wback	= r4k_flush_dcache_size;
 	_dma_cache_inv		= r4k_dma_cache_inv;
 #endif /* CONFIG_DMA_NONCOHERENT */
 
diff --git a/arch/mips/mm/cache.c b/arch/mips/mm/cache.c
index ad9b0430a28e..b69b87c6c0cb 100644
--- a/arch/mips/mm/cache.c
+++ b/arch/mips/mm/cache.c
@@ -51,6 +51,7 @@ EXPORT_SYMBOL_GPL(__flush_kernel_vmap_range);
 /* MIPS specific cache operations */
 void (*flush_data_cache_page)(unsigned long addr);
 void (*flush_icache_all)(void);
+void (*flush_dcache_size)(unsigned long start, unsigned long size);
 
 EXPORT_SYMBOL(flush_data_cache_page);
 EXPORT_SYMBOL(flush_icache_all);

base-commit: 24a19b953e2a3d0ea5a8c4951a0ab8f32720c907
-- 
2.47.3


^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2026-11-02  9:45 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-11-02  9:43 [PATCH v3] MIPS: c-r4k: Flush the cache error vector before writing it uncached Imre Kaloz

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®