mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH v2] MIPS: c-r4k: Flush the cache error vector before writing it uncached
@ 2026-10-26 12:04 Imre Kaloz
  2026-10-26 20:00 ` Maciej W. Rozycki
  0 siblings, 1 reply; 3+ messages in thread
From: Imre Kaloz @ 2026-10-26 12:04 UTC (permalink / raw)
  To: Thomas Bogendoerfer, linux-mips
  Cc: Ethan Nelson-Moore, Maciej W. Rozycki, linux-kernel

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 cache_wback_inv() hook. c-r4k provides it with
r4k_dma_cache_wback_inv(), renamed as it is 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 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().

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

diff --git a/arch/mips/include/asm/cacheflush.h b/arch/mips/include/asm/cacheflush.h
index 5099c1b65a58..753dc3d7b190 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 (*cache_wback_inv)(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..7abd5abf28a9 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.
+	 */
+	cache_wback_inv(ebase + offset, size);
 	memcpy((void *)(uncached_ebase + offset), addr, size);
 }
 
diff --git a/arch/mips/mm/c-r4k.c b/arch/mips/mm/c-r4k.c
index d8aadd3dc057..11bb82263b63 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_cache_wback_inv(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;
+	cache_wback_inv		= r4k_cache_wback_inv;
 	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_cache_wback_inv;
+	_dma_cache_wback	= r4k_cache_wback_inv;
 	_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..555efcfffffe 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 (*cache_wback_inv)(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] 3+ messages in thread

* Re: [PATCH v2] MIPS: c-r4k: Flush the cache error vector before writing it uncached
  2026-10-26 12:04 [PATCH v2] MIPS: c-r4k: Flush the cache error vector before writing it uncached Imre Kaloz
@ 2026-10-26 20:00 ` Maciej W. Rozycki
  2026-10-26 20:59   ` Imre Kaloz
  0 siblings, 1 reply; 3+ messages in thread
From: Maciej W. Rozycki @ 2026-10-26 20:00 UTC (permalink / raw)
  To: Imre Kaloz
  Cc: Thomas Bogendoerfer, linux-mips, Ethan Nelson-Moore, linux-kernel

On Mon, 26 Oct 2026, Imre Kaloz wrote:

> diff --git a/arch/mips/include/asm/cacheflush.h b/arch/mips/include/asm/cacheflush.h
> index 5099c1b65a58..753dc3d7b190 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 (*cache_wback_inv)(unsigned long start, unsigned long size);

 Hmm, I'd be tempted to call the hook flush_dcache_size() or suchlike for 
consistency with our existing nomenclature where "flush" stands for WB+INV 
and to signify that this function doesn't touch I$ (the *_range() suffix 
is already taken for interfaces using start/end rather than start/size for 
the boundaries), although our naming seems messy overall.

 Any other suggestions, anyone?

> diff --git a/arch/mips/mm/c-r4k.c b/arch/mips/mm/c-r4k.c
> index d8aadd3dc057..11bb82263b63 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_cache_wback_inv(unsigned long addr, unsigned long size)

 Likewise accordingly.

> @@ -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;
> +	cache_wback_inv		= r4k_cache_wback_inv;

 Please update arch/mips/mm/c-r3k.c accordingly.

  Maciej

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [PATCH v2] MIPS: c-r4k: Flush the cache error vector before writing it uncached
  2026-10-26 20:00 ` Maciej W. Rozycki
@ 2026-10-26 20:59   ` Imre Kaloz
  0 siblings, 0 replies; 3+ messages in thread
From: Imre Kaloz @ 2026-10-26 20:59 UTC (permalink / raw)
  To: Maciej W. Rozycki
  Cc: Thomas Bogendoerfer, linux-mips, Ethan Nelson-Moore, linux-kernel

On Mon, Oct 26, 2026, at 21:00, Maciej W. Rozycki wrote:

<snip>

>  Hmm, I'd be tempted to call the hook flush_dcache_size() or suchlike for 
> consistency with our existing nomenclature where "flush" stands for WB+INV 
> and to signify that this function doesn't touch I$ (the *_range() suffix 
> is already taken for interfaces using start/end rather than start/size for 
> the boundaries), although our naming seems messy overall.
>
>  Any other suggestions, anyone?

Fine with me. Unless someone has a better name, v3 will call the hook
flush_dcache_size()

<snip>
>> @@ -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;
>> +	cache_wback_inv		= r4k_cache_wback_inv;
>
>  Please update arch/mips/mm/c-r3k.c accordingly.

Will do.


Thanks,
Imre

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2026-10-26 21:00 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-10-26 12:04 [PATCH v2] MIPS: c-r4k: Flush the cache error vector before writing it uncached Imre Kaloz
2026-10-26 20:00 ` Maciej W. Rozycki
2026-10-26 20:59   ` 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®