linux/arch/riscv/errata/thead/errata.c

225 lines
6 KiB
C
Raw Permalink Normal View History

// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (C) 2021 Heiko Stuebner <heiko@sntech.de>
*/
#include <linux/bug.h>
#include <linux/kernel.h>
RISC-V: take text_mutex during alternative patching 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@roeck-us.net> Link: https://lore.kernel.org/all/20230212154333.GA3760469@roeck-us.net/ Signed-off-by: Conor Dooley <conor.dooley@microchip.com> Reviewed-by: Samuel Holland <samuel@sholland.org> Tested-by: Guenter Roeck <linux@roeck-us.net> Link: https://lore.kernel.org/r/20230212194735.491785-1-conor@kernel.org Cc: stable@vger.kernel.org Signed-off-by: Palmer Dabbelt <palmer@rivosinc.com>
2023-02-12 19:47:36 +00:00
#include <linux/memory.h>
#include <linux/module.h>
#include <linux/string.h>
#include <linux/uaccess.h>
#include <asm/alternative.h>
#include <asm/bugs.h>
#include <asm/cacheflush.h>
RISC-V: hwprobe: Support probing of misaligned access performance This allows userspace to select various routines to use based on the performance of misaligned access on the target hardware. Rather than adding DT bindings, this change taps into the alternatives mechanism used to probe CPU errata. Add a new function pointer alongside the vendor-specific errata_patch_func() that probes for desirable errata (otherwise known as "features"). Unlike the errata_patch_func(), this function is called on each CPU as it comes up, so it can save feature information per-CPU. The T-head C906 has fast unaligned access, both as defined by GCC [1], and in performing a basic benchmark, which determined that byte copies are >50% slower than a misaligned word copy of the same data size (source for this test at [2]): bytecopy size f000 count 50000 offset 0 took 31664899 us wordcopy size f000 count 50000 offset 0 took 5180919 us wordcopy size f000 count 50000 offset 1 took 13416949 us [1] https://github.com/gcc-mirror/gcc/blob/master/gcc/config/riscv/riscv.cc#L353 [2] https://pastebin.com/EPXvDHSW Co-developed-by: Palmer Dabbelt <palmer@rivosinc.com> Signed-off-by: Evan Green <evan@rivosinc.com> Reviewed-by: Heiko Stuebner <heiko.stuebner@vrull.eu> Tested-by: Heiko Stuebner <heiko.stuebner@vrull.eu> Reviewed-by: Conor Dooley <conor.dooley@microchip.com> Reviewed-by: Paul Walmsley <paul.walmsley@sifive.com> Link: https://lore.kernel.org/r/20230407231103.2622178-5-evan@rivosinc.com Signed-off-by: Palmer Dabbelt <palmer@rivosinc.com>
2023-04-07 16:11:01 -07:00
#include <asm/cpufeature.h>
#include <asm/dma-noncoherent.h>
#include <asm/errata_list.h>
RISC-V: hwprobe: Support probing of misaligned access performance This allows userspace to select various routines to use based on the performance of misaligned access on the target hardware. Rather than adding DT bindings, this change taps into the alternatives mechanism used to probe CPU errata. Add a new function pointer alongside the vendor-specific errata_patch_func() that probes for desirable errata (otherwise known as "features"). Unlike the errata_patch_func(), this function is called on each CPU as it comes up, so it can save feature information per-CPU. The T-head C906 has fast unaligned access, both as defined by GCC [1], and in performing a basic benchmark, which determined that byte copies are >50% slower than a misaligned word copy of the same data size (source for this test at [2]): bytecopy size f000 count 50000 offset 0 took 31664899 us wordcopy size f000 count 50000 offset 0 took 5180919 us wordcopy size f000 count 50000 offset 1 took 13416949 us [1] https://github.com/gcc-mirror/gcc/blob/master/gcc/config/riscv/riscv.cc#L353 [2] https://pastebin.com/EPXvDHSW Co-developed-by: Palmer Dabbelt <palmer@rivosinc.com> Signed-off-by: Evan Green <evan@rivosinc.com> Reviewed-by: Heiko Stuebner <heiko.stuebner@vrull.eu> Tested-by: Heiko Stuebner <heiko.stuebner@vrull.eu> Reviewed-by: Conor Dooley <conor.dooley@microchip.com> Reviewed-by: Paul Walmsley <paul.walmsley@sifive.com> Link: https://lore.kernel.org/r/20230407231103.2622178-5-evan@rivosinc.com Signed-off-by: Palmer Dabbelt <palmer@rivosinc.com>
2023-04-07 16:11:01 -07:00
#include <asm/hwprobe.h>
#include <asm/io.h>
asm-generic: introduce text-patching.h Several architectures support text patching, but they name the header files that declare patching functions differently. Make all such headers consistently named text-patching.h and add an empty header in asm-generic for architectures that do not support text patching. Link: https://lkml.kernel.org/r/20241023162711.2579610-4-rppt@kernel.org Signed-off-by: Mike Rapoport (Microsoft) <rppt@kernel.org> Reviewed-by: Christoph Hellwig <hch@lst.de> Acked-by: Geert Uytterhoeven <geert@linux-m68k.org> # m68k Acked-by: Arnd Bergmann <arnd@arndb.de> Reviewed-by: Luis Chamberlain <mcgrof@kernel.org> Tested-by: kdevops <kdevops@lists.linux.dev> Cc: Andreas Larsson <andreas@gaisler.com> Cc: Andy Lutomirski <luto@kernel.org> Cc: Ard Biesheuvel <ardb@kernel.org> Cc: Borislav Petkov (AMD) <bp@alien8.de> Cc: Brian Cain <bcain@quicinc.com> Cc: Catalin Marinas <catalin.marinas@arm.com> Cc: Christophe Leroy <christophe.leroy@csgroup.eu> Cc: Dave Hansen <dave.hansen@linux.intel.com> Cc: Dinh Nguyen <dinguyen@kernel.org> Cc: Guo Ren <guoren@kernel.org> Cc: Helge Deller <deller@gmx.de> Cc: Huacai Chen <chenhuacai@kernel.org> Cc: Ingo Molnar <mingo@redhat.com> Cc: Johannes Berg <johannes@sipsolutions.net> Cc: John Paul Adrian Glaubitz <glaubitz@physik.fu-berlin.de> Cc: Kent Overstreet <kent.overstreet@linux.dev> Cc: Liam R. Howlett <Liam.Howlett@Oracle.com> Cc: Mark Rutland <mark.rutland@arm.com> Cc: Masami Hiramatsu (Google) <mhiramat@kernel.org> Cc: Matt Turner <mattst88@gmail.com> Cc: Max Filippov <jcmvbkbc@gmail.com> Cc: Michael Ellerman <mpe@ellerman.id.au> Cc: Michal Simek <monstr@monstr.eu> Cc: Oleg Nesterov <oleg@redhat.com> Cc: Palmer Dabbelt <palmer@dabbelt.com> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Richard Weinberger <richard@nod.at> Cc: Russell King <linux@armlinux.org.uk> Cc: Song Liu <song@kernel.org> Cc: Stafford Horne <shorne@gmail.com> Cc: Steven Rostedt (Google) <rostedt@goodmis.org> Cc: Suren Baghdasaryan <surenb@google.com> Cc: Thomas Bogendoerfer <tsbogend@alpha.franken.de> Cc: Thomas Gleixner <tglx@linutronix.de> Cc: Uladzislau Rezki (Sony) <urezki@gmail.com> Cc: Vineet Gupta <vgupta@kernel.org> Cc: Will Deacon <will@kernel.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
2024-10-23 19:27:06 +03:00
#include <asm/text-patching.h>
#include <asm/vendorid_list.h>
#include <asm/vendor_extensions.h>
#define CSR_TH_SXSTATUS 0x5c0
#define SXSTATUS_MAEE _AC(0x200000, UL)
static bool errata_probe_mae(unsigned int stage,
unsigned long arch_id, unsigned long impid)
{
if (!IS_ENABLED(CONFIG_ERRATA_THEAD_MAE))
return false;
if (arch_id != 0 || impid != 0)
return false;
if (stage != RISCV_ALTERNATIVES_EARLY_BOOT &&
stage != RISCV_ALTERNATIVES_MODULE)
return false;
if (!(csr_read(CSR_TH_SXSTATUS) & SXSTATUS_MAEE))
return false;
riscv: remove usage of function-pointers from cpufeatures and t-head errata Having a list of alternatives to check with a per-entry function pointer to a check function is nice style-wise. But in case of early-alternatives it can clash with the non-relocated kernel and the function pointer in the list pointing to a completely wrong location. This isn't an issue with one or two list entries, as in that case the compiler seems to unroll the loop and even usage of the list structure and then only does relative jumps into the check functions based on this. When adding a third entry to either list though, the issue that was hiding there from the beginning is triggered resulting a jump to a memory address that isn't part of the kernel at all. The list of features/erratas only contained an unused name and the pointer to the check function, so an easy solution for the problem is to just unroll the loop in code, dismantle the whole list structure and just call the relevant check functions one by one ourself. For the T-Head errata this includes moving the stage-check inside the check functions. The issue is only relevant for things that might be called for early- alternatives (T-Head and possible future main extensions), so the SiFive erratas were not affected from the beginning, as they got an early return for early-alternatives in the original patchset. Signed-off-by: Heiko Stuebner <heiko@sntech.de> Tested-by: Samuel Holland <samuel@sholland.org> Link: https://lore.kernel.org/r/20220526205646.258337-6-heiko@sntech.de Signed-off-by: Palmer Dabbelt <palmer@rivosinc.com>
2022-05-26 22:56:46 +02:00
return true;
riscv: remove usage of function-pointers from cpufeatures and t-head errata Having a list of alternatives to check with a per-entry function pointer to a check function is nice style-wise. But in case of early-alternatives it can clash with the non-relocated kernel and the function pointer in the list pointing to a completely wrong location. This isn't an issue with one or two list entries, as in that case the compiler seems to unroll the loop and even usage of the list structure and then only does relative jumps into the check functions based on this. When adding a third entry to either list though, the issue that was hiding there from the beginning is triggered resulting a jump to a memory address that isn't part of the kernel at all. The list of features/erratas only contained an unused name and the pointer to the check function, so an easy solution for the problem is to just unroll the loop in code, dismantle the whole list structure and just call the relevant check functions one by one ourself. For the T-Head errata this includes moving the stage-check inside the check functions. The issue is only relevant for things that might be called for early- alternatives (T-Head and possible future main extensions), so the SiFive erratas were not affected from the beginning, as they got an early return for early-alternatives in the original patchset. Signed-off-by: Heiko Stuebner <heiko@sntech.de> Tested-by: Samuel Holland <samuel@sholland.org> Link: https://lore.kernel.org/r/20220526205646.258337-6-heiko@sntech.de Signed-off-by: Palmer Dabbelt <palmer@rivosinc.com>
2022-05-26 22:56:46 +02:00
}
/*
* th.dcache.ipa rs1 (invalidate, physical address)
* | 31 - 25 | 24 - 20 | 19 - 15 | 14 - 12 | 11 - 7 | 6 - 0 |
* 0000001 01010 rs1 000 00000 0001011
* th.dcache.iva rs1 (invalidate, virtual address)
* 0000001 00110 rs1 000 00000 0001011
*
* th.dcache.cpa rs1 (clean, physical address)
* | 31 - 25 | 24 - 20 | 19 - 15 | 14 - 12 | 11 - 7 | 6 - 0 |
* 0000001 01001 rs1 000 00000 0001011
* th.dcache.cva rs1 (clean, virtual address)
* 0000001 00101 rs1 000 00000 0001011
*
* th.dcache.cipa rs1 (clean then invalidate, physical address)
* | 31 - 25 | 24 - 20 | 19 - 15 | 14 - 12 | 11 - 7 | 6 - 0 |
* 0000001 01011 rs1 000 00000 0001011
* th.dcache.civa rs1 (clean then invalidate, virtual address)
* 0000001 00111 rs1 000 00000 0001011
*
* th.sync.s (make sure all cache operations finished)
* | 31 - 25 | 24 - 20 | 19 - 15 | 14 - 12 | 11 - 7 | 6 - 0 |
* 0000000 11001 00000 000 00000 0001011
*/
#define THEAD_INVAL_A0 ".long 0x02a5000b"
#define THEAD_CLEAN_A0 ".long 0x0295000b"
#define THEAD_FLUSH_A0 ".long 0x02b5000b"
#define THEAD_SYNC_S ".long 0x0190000b"
#define THEAD_CMO_OP(_op, _start, _size, _cachesize) \
asm volatile("mv a0, %1\n\t" \
"j 2f\n\t" \
"3:\n\t" \
THEAD_##_op##_A0 "\n\t" \
"add a0, a0, %0\n\t" \
"2:\n\t" \
"bltu a0, %2, 3b\n\t" \
THEAD_SYNC_S \
: : "r"(_cachesize), \
"r"((unsigned long)(_start) & ~((_cachesize) - 1UL)), \
"r"((unsigned long)(_start) + (_size)) \
: "a0")
static void thead_errata_cache_inv(phys_addr_t paddr, size_t size)
{
THEAD_CMO_OP(INVAL, paddr, size, riscv_cbom_block_size);
}
static void thead_errata_cache_wback(phys_addr_t paddr, size_t size)
{
THEAD_CMO_OP(CLEAN, paddr, size, riscv_cbom_block_size);
}
static void thead_errata_cache_wback_inv(phys_addr_t paddr, size_t size)
{
THEAD_CMO_OP(FLUSH, paddr, size, riscv_cbom_block_size);
}
static const struct riscv_nonstd_cache_ops thead_errata_cmo_ops = {
.wback = &thead_errata_cache_wback,
.inv = &thead_errata_cache_inv,
.wback_inv = &thead_errata_cache_wback_inv,
};
static bool errata_probe_cmo(unsigned int stage,
unsigned long arch_id, unsigned long impid)
{
if (!IS_ENABLED(CONFIG_ERRATA_THEAD_CMO))
return false;
if (arch_id != 0 || impid != 0)
return false;
if (stage == RISCV_ALTERNATIVES_EARLY_BOOT)
return false;
if (stage == RISCV_ALTERNATIVES_BOOT) {
riscv_cbom_block_size = L1_CACHE_BYTES;
riscv_noncoherent_supported();
riscv_noncoherent_register_cache_ops(&thead_errata_cmo_ops);
}
return true;
}
static bool errata_probe_pmu(unsigned int stage,
unsigned long arch_id, unsigned long impid)
{
if (!IS_ENABLED(CONFIG_ERRATA_THEAD_PMU))
return false;
/* target-c9xx cores report arch_id and impid as 0 */
if (arch_id != 0 || impid != 0)
return false;
if (stage == RISCV_ALTERNATIVES_EARLY_BOOT)
return false;
return true;
}
static bool errata_probe_ghostwrite(unsigned int stage,
unsigned long arch_id, unsigned long impid)
{
if (!IS_ENABLED(CONFIG_ERRATA_THEAD_GHOSTWRITE))
return false;
/*
* target-c9xx cores report arch_id and impid as 0
*
* While ghostwrite may not affect all c9xx cores that implement
* xtheadvector, there is no futher granularity than c9xx. Assume
* vulnerable for this entire class of processors when xtheadvector is
* enabled.
*/
if (arch_id != 0 || impid != 0)
return false;
if (stage != RISCV_ALTERNATIVES_EARLY_BOOT)
return false;
ghostwrite_set_vulnerable();
return true;
}
riscv: remove usage of function-pointers from cpufeatures and t-head errata Having a list of alternatives to check with a per-entry function pointer to a check function is nice style-wise. But in case of early-alternatives it can clash with the non-relocated kernel and the function pointer in the list pointing to a completely wrong location. This isn't an issue with one or two list entries, as in that case the compiler seems to unroll the loop and even usage of the list structure and then only does relative jumps into the check functions based on this. When adding a third entry to either list though, the issue that was hiding there from the beginning is triggered resulting a jump to a memory address that isn't part of the kernel at all. The list of features/erratas only contained an unused name and the pointer to the check function, so an easy solution for the problem is to just unroll the loop in code, dismantle the whole list structure and just call the relevant check functions one by one ourself. For the T-Head errata this includes moving the stage-check inside the check functions. The issue is only relevant for things that might be called for early- alternatives (T-Head and possible future main extensions), so the SiFive erratas were not affected from the beginning, as they got an early return for early-alternatives in the original patchset. Signed-off-by: Heiko Stuebner <heiko@sntech.de> Tested-by: Samuel Holland <samuel@sholland.org> Link: https://lore.kernel.org/r/20220526205646.258337-6-heiko@sntech.de Signed-off-by: Palmer Dabbelt <palmer@rivosinc.com>
2022-05-26 22:56:46 +02:00
static u32 thead_errata_probe(unsigned int stage,
unsigned long archid, unsigned long impid)
{
u32 cpu_req_errata = 0;
if (errata_probe_mae(stage, archid, impid))
cpu_req_errata |= BIT(ERRATA_THEAD_MAE);
errata_probe_cmo(stage, archid, impid);
if (errata_probe_pmu(stage, archid, impid))
cpu_req_errata |= BIT(ERRATA_THEAD_PMU);
errata_probe_ghostwrite(stage, archid, impid);
return cpu_req_errata;
}
void thead_errata_patch_func(struct alt_entry *begin, struct alt_entry *end,
unsigned long archid, unsigned long impid,
unsigned int stage)
{
struct alt_entry *alt;
u32 cpu_req_errata = thead_errata_probe(stage, archid, impid);
u32 tmp;
void *oldptr, *altptr;
BUILD_BUG_ON(ERRATA_THEAD_NUMBER >= RISCV_VENDOR_EXT_ALTERNATIVES_BASE);
for (alt = begin; alt < end; alt++) {
if (alt->vendor_id != THEAD_VENDOR_ID)
continue;
if (alt->patch_id >= ERRATA_THEAD_NUMBER)
continue;
tmp = (1U << alt->patch_id);
if (cpu_req_errata & tmp) {
oldptr = ALT_OLD_PTR(alt);
altptr = ALT_ALT_PTR(alt);
/* On vm-alternatives, the mmu isn't running yet */
RISC-V: take text_mutex during alternative patching 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@roeck-us.net> Link: https://lore.kernel.org/all/20230212154333.GA3760469@roeck-us.net/ Signed-off-by: Conor Dooley <conor.dooley@microchip.com> Reviewed-by: Samuel Holland <samuel@sholland.org> Tested-by: Guenter Roeck <linux@roeck-us.net> Link: https://lore.kernel.org/r/20230212194735.491785-1-conor@kernel.org Cc: stable@vger.kernel.org Signed-off-by: Palmer Dabbelt <palmer@rivosinc.com>
2023-02-12 19:47:36 +00:00
if (stage == RISCV_ALTERNATIVES_EARLY_BOOT) {
memcpy(oldptr, altptr, alt->alt_len);
RISC-V: take text_mutex during alternative patching 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@roeck-us.net> Link: https://lore.kernel.org/all/20230212154333.GA3760469@roeck-us.net/ Signed-off-by: Conor Dooley <conor.dooley@microchip.com> Reviewed-by: Samuel Holland <samuel@sholland.org> Tested-by: Guenter Roeck <linux@roeck-us.net> Link: https://lore.kernel.org/r/20230212194735.491785-1-conor@kernel.org Cc: stable@vger.kernel.org Signed-off-by: Palmer Dabbelt <palmer@rivosinc.com>
2023-02-12 19:47:36 +00:00
} else {
mutex_lock(&text_mutex);
patch_text_nosync(oldptr, altptr, alt->alt_len);
RISC-V: take text_mutex during alternative patching 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@roeck-us.net> Link: https://lore.kernel.org/all/20230212154333.GA3760469@roeck-us.net/ Signed-off-by: Conor Dooley <conor.dooley@microchip.com> Reviewed-by: Samuel Holland <samuel@sholland.org> Tested-by: Guenter Roeck <linux@roeck-us.net> Link: https://lore.kernel.org/r/20230212194735.491785-1-conor@kernel.org Cc: stable@vger.kernel.org Signed-off-by: Palmer Dabbelt <palmer@rivosinc.com>
2023-02-12 19:47:36 +00:00
mutex_unlock(&text_mutex);
}
}
}
if (stage == RISCV_ALTERNATIVES_EARLY_BOOT)
local_flush_icache_all();
}