From: Imre Kaloz <kaloz@kernel.org>
To: Thomas Bogendoerfer <tsbogend@alpha.franken.de>,
linux-mips@vger.kernel.org
Cc: Ethan Nelson-Moore <enelsonmoore@gmail.com>,
"Maciej W. Rozycki" <macro@orcam.me.uk>,
linux-kernel@vger.kernel.org
Subject: [PATCH v2] MIPS: c-r4k: Flush the cache error vector before writing it uncached
Date: Mon, 26 Oct 2026 13:04:30 +0100 [thread overview]
Message-ID: <20261026120430.13238-1-kaloz@kernel.org> (raw)
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
next reply other threads:[~2026-10-26 12:05 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-26 12:04 Imre Kaloz [this message]
2026-10-26 20:00 ` Maciej W. Rozycki
2026-10-26 20:59 ` Imre Kaloz
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=20261026120430.13238-1-kaloz@kernel.org \
--to=kaloz@kernel.org \
--cc=enelsonmoore@gmail.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-mips@vger.kernel.org \
--cc=macro@orcam.me.uk \
--cc=tsbogend@alpha.franken.de \
/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
all inboxes | Powered by JetHome®