From 30755e71abb1aa9d1d51ea9fdd6a5c07807c3b40 Mon Sep 17 00:00:00 2001 From: Aleksa Paunovic Date: Mon, 5 Oct 2026 19:02:53 -0600 Subject: [PATCH] riscv: Add support for early boot errata application on MIPS chips MIPS errata implementation previously skipped early boot application entirely. Although the only currently existing MIPS erratum does not require this, amending this now should make any future addition easier to implement. This commit was based on the existing T-Head implementation. Suggested-by: Jesse Taube Link: https://lore.kernel.org/linux-riscv/CADRr4bcbD57hmR0XGgo8BjgNp4shEADOondZEtwscCJ9-nxXRQ@mail.gmail.com/ Signed-off-by: Aleksa Paunovic Link: https://patch.msgid.link/20260810-p8700-early-boot-v1-1-5c4aa08d500f@htecgroup.com Signed-off-by: Paul Walmsley --- arch/riscv/Kconfig.errata | 1 + arch/riscv/errata/mips/Makefile | 6 ++++++ arch/riscv/errata/mips/errata.c | 38 ++++++++++++++++++++------------- 3 files changed, 30 insertions(+), 15 deletions(-) diff --git a/arch/riscv/Kconfig.errata b/arch/riscv/Kconfig.errata index a6aac8774f25..53e28e5b4f92 100644 --- a/arch/riscv/Kconfig.errata +++ b/arch/riscv/Kconfig.errata @@ -24,6 +24,7 @@ config ERRATA_ANDES_CMO config ERRATA_MIPS bool "MIPS errata" depends on RISCV_ALTERNATIVE + select RISCV_ALTERNATIVE_EARLY help All MIPS errata Kconfig depend on this Kconfig. Disabling this Kconfig will disable all MIPS errata. Please say "Y" diff --git a/arch/riscv/errata/mips/Makefile b/arch/riscv/errata/mips/Makefile index 6278c389b801..137e700d9d3f 100644 --- a/arch/riscv/errata/mips/Makefile +++ b/arch/riscv/errata/mips/Makefile @@ -1,5 +1,11 @@ ifdef CONFIG_RISCV_ALTERNATIVE_EARLY CFLAGS_errata.o := -mcmodel=medany +ifdef CONFIG_FTRACE +CFLAGS_REMOVE_errata.o = $(CC_FLAGS_FTRACE) +endif +ifdef CONFIG_KASAN +KASAN_SANITIZE_errata.o := n +endif endif obj-y += errata.o diff --git a/arch/riscv/errata/mips/errata.c b/arch/riscv/errata/mips/errata.c index 2c3dc2259e93..ac9a12d0a30c 100644 --- a/arch/riscv/errata/mips/errata.c +++ b/arch/riscv/errata/mips/errata.c @@ -7,12 +7,13 @@ #include #include #include +#include #include #include #include #include -static inline bool errata_probe_pause(void) +static inline bool errata_probe_pause(unsigned int stage) { if (!IS_ENABLED(CONFIG_ERRATA_MIPS_P8700_PAUSE_OPCODE)) return false; @@ -20,14 +21,17 @@ static inline bool errata_probe_pause(void) if (!riscv_isa_vendor_extension_available(MIPS_VENDOR_ID, XMIPSEXECTL)) return false; + if (stage == RISCV_ALTERNATIVES_EARLY_BOOT) + return false; + return true; } -static u32 mips_errata_probe(void) +static u32 mips_errata_probe(unsigned int stage) { u32 cpu_req_errata = 0; - if (errata_probe_pause()) + if (errata_probe_pause(stage)) cpu_req_errata |= BIT(ERRATA_MIPS_P8700_PAUSE_OPCODE); return cpu_req_errata; @@ -38,30 +42,34 @@ void mips_errata_patch_func(struct alt_entry *begin, struct alt_entry *end, unsigned int stage) { struct alt_entry *alt; - u32 cpu_req_errata = mips_errata_probe(); + u32 cpu_req_errata = mips_errata_probe(stage); u32 tmp; + void *oldptr, *altptr; BUILD_BUG_ON(ERRATA_MIPS_NUMBER >= RISCV_VENDOR_EXT_ALTERNATIVES_BASE); - if (stage == RISCV_ALTERNATIVES_EARLY_BOOT) - return; - for (alt = begin; alt < end; alt++) { if (alt->vendor_id != MIPS_VENDOR_ID) continue; - if (alt->patch_id >= ERRATA_MIPS_NUMBER) { - WARN(1, "MIPS errata id:%d not in kernel errata list\n", - alt->patch_id); + if (alt->patch_id >= ERRATA_MIPS_NUMBER) continue; - } tmp = (1U << alt->patch_id); if (cpu_req_errata & tmp) { - mutex_lock(&text_mutex); - patch_text_nosync(ALT_OLD_PTR(alt), ALT_ALT_PTR(alt), - alt->alt_len); - mutex_unlock(&text_mutex); + oldptr = ALT_OLD_PTR(alt); + altptr = ALT_ALT_PTR(alt); + + if (stage == RISCV_ALTERNATIVES_EARLY_BOOT) { + memcpy(oldptr, altptr, alt->alt_len); + } else { + mutex_lock(&text_mutex); + patch_text_nosync(oldptr, altptr, alt->alt_len); + mutex_unlock(&text_mutex); + } } } + + if (stage == RISCV_ALTERNATIVES_EARLY_BOOT) + local_flush_icache_all(); }