[PATCH v1] RISC-V: take text_mutex during alternative patching
Guenter Roeck
linux at roeck-us.net
Sun Feb 12 15:08:55 PST 2023
On 2/12/23 11:47, Conor Dooley wrote:
> From: Conor Dooley <conor.dooley at microchip.com>
>
> Guenter reported a splat during boot, that Samuel pointed out was the
> lockdep assertion failing in patch_insn_write():
>
> WARNING: CPU: 0 PID: 0 at arch/riscv/kernel/patch.c:63 patch_insn_write+0x222/0x2f6
> epc : patch_insn_write+0x222/0x2f6
> ra : patch_insn_write+0x21e/0x2f6
> epc : ffffffff800068c6 ra : ffffffff800068c2 sp : ffffffff81803df0
> gp : ffffffff81a1ab78 tp : ffffffff81814f80 t0 : ffffffffffffe000
> t1 : 0000000000000001 t2 : 4c45203a76637369 s0 : ffffffff81803e40
> s1 : 0000000000000004 a0 : 0000000000000000 a1 : ffffffffffffffff
> a2 : 0000000000000004 a3 : 0000000000000000 a4 : 0000000000000001
> a5 : 0000000000000000 a6 : 0000000000000000 a7 : 0000000052464e43
> s2 : ffffffff80b4889c s3 : 000000000000082c s4 : ffffffff80b48828
> s5 : 0000000000000828 s6 : ffffffff8131a0a0 s7 : 0000000000000fff
> s8 : 0000000008000200 s9 : ffffffff8131a520 s10: 0000000000000018
> s11: 000000000000000b t3 : 0000000000000001 t4 : 000000000000000d
> t5 : ffffffffd8180000 t6 : ffffffff81803bc8
> status: 0000000200000100 badaddr: 0000000000000000 cause: 0000000000000003
> [<ffffffff800068c6>] patch_insn_write+0x222/0x2f6
> [<ffffffff80006a36>] patch_text_nosync+0xc/0x2a
> [<ffffffff80003b86>] riscv_cpufeature_patch_func+0x52/0x98
> [<ffffffff80003348>] _apply_alternatives+0x46/0x86
> [<ffffffff80c02d36>] apply_boot_alternatives+0x3c/0xfa
> [<ffffffff80c03ad8>] setup_arch+0x584/0x5b8
> [<ffffffff80c0075a>] start_kernel+0xa2/0x8f8
>
> This issue was exposed by 702e64550b12 ("riscv: fpu: switch has_fpu() to
> riscv_has_extension_likely()"), as it is the patching in has_fpu() that
> triggers the splats in Guenter's report.
>
> Take the text_mutex before doing any code patching to satisfy lockdep.
>
> Fixes: ff689fd21cb1 ("riscv: add RISC-V Svpbmt extension support")
> Fixes: a35707c3d850 ("riscv: add memory-type errata for T-Head")
> Fixes: 1a0e5dbd3723 ("riscv: sifive: Add SiFive alternative ports")
> Reported-by: Guenter Roeck <linux at roeck-us.net>
> Link: https://lore.kernel.org/all/20230212154333.GA3760469@roeck-us.net/
> Signed-off-by: Conor Dooley <conor.dooley at microchip.com>
Applying this patch together with
riscv: Fix early alternative patching
riscv: Fix Zbb alternative IDs
_and_ disabling CONFIG_RISCV_ISA_ZBB fixes all problems observed with
riscv64 for me. With that,
Tested-by: Guenter Roeck <linux at roeck-us.net>
Unfortunately I still see boot failures when trying to boot riscv32
images, so something is still broken. I don't know yet if that is
a generic problem or if it is related to a riscv patch.
I am still trying to track that down ...
Guenter
> ---
> Applies on top of Samuel's critical fixes in his "Fix alternatives
> issues on for-next":
> https://lore.kernel.org/all/20230212021534.59121-1-samuel@sholland.org/
> ---
> arch/riscv/errata/sifive/errata.c | 3 +++
> arch/riscv/errata/thead/errata.c | 8 ++++++--
> arch/riscv/kernel/cpufeature.c | 4 ++++
> 3 files changed, 13 insertions(+), 2 deletions(-)
>
> diff --git a/arch/riscv/errata/sifive/errata.c b/arch/riscv/errata/sifive/errata.c
> index ef9a4eec0dba..da55cb247e89 100644
> --- a/arch/riscv/errata/sifive/errata.c
> +++ b/arch/riscv/errata/sifive/errata.c
> @@ -4,6 +4,7 @@
> */
>
> #include <linux/kernel.h>
> +#include <linux/memory.h>
> #include <linux/module.h>
> #include <linux/string.h>
> #include <linux/bug.h>
> @@ -107,8 +108,10 @@ void __init_or_module sifive_errata_patch_func(struct alt_entry *begin,
>
> tmp = (1U << alt->errata_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_lock(&text_mutex);
> cpu_apply_errata |= tmp;
> }
> }
> diff --git a/arch/riscv/errata/thead/errata.c b/arch/riscv/errata/thead/errata.c
> index 1dd90a5f86f0..3b96a06d3c54 100644
> --- a/arch/riscv/errata/thead/errata.c
> +++ b/arch/riscv/errata/thead/errata.c
> @@ -5,6 +5,7 @@
>
> #include <linux/bug.h>
> #include <linux/kernel.h>
> +#include <linux/memory.h>
> #include <linux/module.h>
> #include <linux/string.h>
> #include <linux/uaccess.h>
> @@ -101,10 +102,13 @@ void __init_or_module thead_errata_patch_func(struct alt_entry *begin, struct al
> altptr = ALT_ALT_PTR(alt);
>
> /* On vm-alternatives, the mmu isn't running yet */
> - if (stage == RISCV_ALTERNATIVES_EARLY_BOOT)
> + if (stage == RISCV_ALTERNATIVES_EARLY_BOOT) {
> memcpy(oldptr, altptr, alt->alt_len);
> - else
> + } else {
> + mutex_lock(&text_mutex);
> patch_text_nosync(oldptr, altptr, alt->alt_len);
> + mutex_unlock(&text_mutex);
> + }
> }
> }
>
> diff --git a/arch/riscv/kernel/cpufeature.c b/arch/riscv/kernel/cpufeature.c
> index 21fb567e1b22..59d58ee0f68d 100644
> --- a/arch/riscv/kernel/cpufeature.c
> +++ b/arch/riscv/kernel/cpufeature.c
> @@ -10,6 +10,7 @@
> #include <linux/ctype.h>
> #include <linux/libfdt.h>
> #include <linux/log2.h>
> +#include <linux/memory.h>
> #include <linux/module.h>
> #include <linux/of.h>
> #include <asm/alternative.h>
> @@ -292,8 +293,11 @@ void __init_or_module riscv_cpufeature_patch_func(struct alt_entry *begin,
>
> oldptr = ALT_OLD_PTR(alt);
> altptr = ALT_ALT_PTR(alt);
> +
> + mutex_lock(&text_mutex);
> patch_text_nosync(oldptr, altptr, alt->alt_len);
> riscv_alternative_fix_offsets(oldptr, alt->alt_len, oldptr - altptr);
> + mutex_unlock(&text_mutex);
> }
> }
> #endif
More information about the linux-riscv
mailing list