mirror of
https://github.com/torvalds/linux.git
synced 2026-05-28 00:53:34 +02:00
riscv: errata: Fix the PAUSE Opcode for MIPS P8700
Add ERRATA_MIPS and ERRATA_MIPS_P8700_PAUSE_OPCODE configs. Handle errata for the MIPS PAUSE instruction. Signed-off-by: Djordje Todorovic <djordje.todorovic@htecgroup.com> Signed-off-by: Aleksandar Rikalo <arikalo@gmail.com> Signed-off-by: Raj Vishwanathan4 <rvishwanathan@mips.com> Signed-off-by: Aleksa Paunovic <aleksa.paunovic@htecgroup.com> Reviewed-by: Alexandre Ghiti <alexghiti@rivosinc.com> Link: https://lore.kernel.org/r/20250724-p8700-pause-v5-7-a6cbbe1c3412@htecgroup.com [pjw@kernel.org: updated to apply and compile; fixed a checkpatch issue] Signed-off-by: Paul Walmsley <pjw@kernel.org>
This commit is contained in:
parent
c9a9fc2322
commit
0b0ca959d2
|
|
@ -21,6 +21,29 @@ config ERRATA_ANDES_CMO
|
||||||
|
|
||||||
If you don't know what to do here, say "Y".
|
If you don't know what to do here, say "Y".
|
||||||
|
|
||||||
|
config ERRATA_MIPS
|
||||||
|
bool "MIPS errata"
|
||||||
|
depends on RISCV_ALTERNATIVE
|
||||||
|
help
|
||||||
|
All MIPS errata Kconfig depend on this Kconfig. Disabling
|
||||||
|
this Kconfig will disable all MIPS errata. Please say "Y"
|
||||||
|
here if your platform uses MIPS CPU cores.
|
||||||
|
|
||||||
|
Otherwise, please say "N" here to avoid unnecessary overhead.
|
||||||
|
|
||||||
|
config ERRATA_MIPS_P8700_PAUSE_OPCODE
|
||||||
|
bool "Fix the PAUSE Opcode for MIPS P8700"
|
||||||
|
depends on ERRATA_MIPS && 64BIT
|
||||||
|
default n
|
||||||
|
help
|
||||||
|
The RISCV MIPS P8700 uses a different opcode for PAUSE.
|
||||||
|
It is a 'hint' encoding of the SLLI instruction,
|
||||||
|
with rd=0, rs1=0 and imm=5. It will behave as a NOP
|
||||||
|
instruction if no additional behavior beyond that of
|
||||||
|
SLLI is implemented.
|
||||||
|
|
||||||
|
If you are not using the P8700 processor, say n.
|
||||||
|
|
||||||
config ERRATA_SIFIVE
|
config ERRATA_SIFIVE
|
||||||
bool "SiFive errata"
|
bool "SiFive errata"
|
||||||
depends on RISCV_ALTERNATIVE
|
depends on RISCV_ALTERNATIVE
|
||||||
|
|
|
||||||
|
|
@ -13,5 +13,6 @@ endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
obj-$(CONFIG_ERRATA_ANDES) += andes/
|
obj-$(CONFIG_ERRATA_ANDES) += andes/
|
||||||
|
obj-$(CONFIG_ERRATA_MIPS) += mips/
|
||||||
obj-$(CONFIG_ERRATA_SIFIVE) += sifive/
|
obj-$(CONFIG_ERRATA_SIFIVE) += sifive/
|
||||||
obj-$(CONFIG_ERRATA_THEAD) += thead/
|
obj-$(CONFIG_ERRATA_THEAD) += thead/
|
||||||
|
|
|
||||||
5
arch/riscv/errata/mips/Makefile
Normal file
5
arch/riscv/errata/mips/Makefile
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
ifdef CONFIG_RISCV_ALTERNATIVE_EARLY
|
||||||
|
CFLAGS_errata.o := -mcmodel=medany
|
||||||
|
endif
|
||||||
|
|
||||||
|
obj-y += errata.o
|
||||||
67
arch/riscv/errata/mips/errata.c
Normal file
67
arch/riscv/errata/mips/errata.c
Normal file
|
|
@ -0,0 +1,67 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-only
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2025 MIPS.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <linux/memory.h>
|
||||||
|
#include <linux/module.h>
|
||||||
|
#include <asm/text-patching.h>
|
||||||
|
#include <asm/alternative.h>
|
||||||
|
#include <asm/errata_list.h>
|
||||||
|
#include <asm/vendorid_list.h>
|
||||||
|
#include <asm/vendor_extensions.h>
|
||||||
|
#include <asm/vendor_extensions/mips.h>
|
||||||
|
|
||||||
|
static inline bool errata_probe_pause(void)
|
||||||
|
{
|
||||||
|
if (!IS_ENABLED(CONFIG_ERRATA_MIPS_P8700_PAUSE_OPCODE))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!riscv_isa_vendor_extension_available(MIPS_VENDOR_ID, XMIPSEXECTL))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static u32 mips_errata_probe(void)
|
||||||
|
{
|
||||||
|
u32 cpu_req_errata = 0;
|
||||||
|
|
||||||
|
if (errata_probe_pause())
|
||||||
|
cpu_req_errata |= BIT(ERRATA_MIPS_P8700_PAUSE_OPCODE);
|
||||||
|
|
||||||
|
return cpu_req_errata;
|
||||||
|
}
|
||||||
|
|
||||||
|
void mips_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 = mips_errata_probe();
|
||||||
|
u32 tmp;
|
||||||
|
|
||||||
|
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);
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -48,6 +48,9 @@ struct alt_entry {
|
||||||
void andes_errata_patch_func(struct alt_entry *begin, struct alt_entry *end,
|
void andes_errata_patch_func(struct alt_entry *begin, struct alt_entry *end,
|
||||||
unsigned long archid, unsigned long impid,
|
unsigned long archid, unsigned long impid,
|
||||||
unsigned int stage);
|
unsigned int stage);
|
||||||
|
void mips_errata_patch_func(struct alt_entry *begin, struct alt_entry *end,
|
||||||
|
unsigned long archid, unsigned long impid,
|
||||||
|
unsigned int stage);
|
||||||
void sifive_errata_patch_func(struct alt_entry *begin, struct alt_entry *end,
|
void sifive_errata_patch_func(struct alt_entry *begin, struct alt_entry *end,
|
||||||
unsigned long archid, unsigned long impid,
|
unsigned long archid, unsigned long impid,
|
||||||
unsigned int stage);
|
unsigned int stage);
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,7 @@
|
||||||
#include <asm/insn-def.h>
|
#include <asm/insn-def.h>
|
||||||
#include <asm/cpufeature-macros.h>
|
#include <asm/cpufeature-macros.h>
|
||||||
#include <asm/processor.h>
|
#include <asm/processor.h>
|
||||||
|
#include <asm/errata_list.h>
|
||||||
|
|
||||||
#define __arch_xchg_masked(sc_sfx, swap_sfx, prepend, sc_append, \
|
#define __arch_xchg_masked(sc_sfx, swap_sfx, prepend, sc_append, \
|
||||||
swap_append, r, p, n) \
|
swap_append, r, p, n) \
|
||||||
|
|
@ -438,7 +439,7 @@ static __always_inline void __cmpwait(volatile void *ptr,
|
||||||
return;
|
return;
|
||||||
|
|
||||||
no_zawrs:
|
no_zawrs:
|
||||||
asm volatile(RISCV_PAUSE : : : "memory");
|
ALT_RISCV_PAUSE();
|
||||||
}
|
}
|
||||||
|
|
||||||
#define __cmpwait_relaxed(ptr, val) \
|
#define __cmpwait_relaxed(ptr, val) \
|
||||||
|
|
|
||||||
|
|
@ -5,12 +5,12 @@
|
||||||
#ifndef ASM_ERRATA_LIST_H
|
#ifndef ASM_ERRATA_LIST_H
|
||||||
#define ASM_ERRATA_LIST_H
|
#define ASM_ERRATA_LIST_H
|
||||||
|
|
||||||
#include <asm/alternative.h>
|
|
||||||
#include <asm/csr.h>
|
#include <asm/csr.h>
|
||||||
#include <asm/insn-def.h>
|
#include <asm/insn-def.h>
|
||||||
#include <asm/hwcap.h>
|
#include <asm/hwcap.h>
|
||||||
#include <asm/vendorid_list.h>
|
#include <asm/vendorid_list.h>
|
||||||
#include <asm/errata_list_vendors.h>
|
#include <asm/errata_list_vendors.h>
|
||||||
|
#include <asm/vendor_extensions/mips.h>
|
||||||
|
|
||||||
#ifdef __ASSEMBLER__
|
#ifdef __ASSEMBLER__
|
||||||
|
|
||||||
|
|
@ -42,6 +42,17 @@ asm(ALTERNATIVE("sfence.vma %0, %1", "sfence.vma", SIFIVE_VENDOR_ID, \
|
||||||
ERRATA_SIFIVE_CIP_1200, CONFIG_ERRATA_SIFIVE_CIP_1200) \
|
ERRATA_SIFIVE_CIP_1200, CONFIG_ERRATA_SIFIVE_CIP_1200) \
|
||||||
: : "r" (addr), "r" (asid) : "memory")
|
: : "r" (addr), "r" (asid) : "memory")
|
||||||
|
|
||||||
|
#define ALT_RISCV_PAUSE() \
|
||||||
|
asm(ALTERNATIVE( \
|
||||||
|
RISCV_PAUSE, /* Original RISC‑V pause insn */ \
|
||||||
|
MIPS_PAUSE, /* Replacement for MIPS P8700 */ \
|
||||||
|
MIPS_VENDOR_ID, /* Vendor ID to match */ \
|
||||||
|
ERRATA_MIPS_P8700_PAUSE_OPCODE, /* patch_id */ \
|
||||||
|
CONFIG_ERRATA_MIPS_P8700_PAUSE_OPCODE) \
|
||||||
|
: /* no outputs */ \
|
||||||
|
: /* no inputs */ \
|
||||||
|
: "memory")
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* _val is marked as "will be overwritten", so need to set it to 0
|
* _val is marked as "will be overwritten", so need to set it to 0
|
||||||
* in the default case.
|
* in the default case.
|
||||||
|
|
|
||||||
|
|
@ -21,4 +21,9 @@
|
||||||
#define ERRATA_THEAD_NUMBER 3
|
#define ERRATA_THEAD_NUMBER 3
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef CONFIG_ERRATA_MIPS
|
||||||
|
#define ERRATA_MIPS_P8700_PAUSE_OPCODE 0
|
||||||
|
#define ERRATA_MIPS_NUMBER 1
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif /* ASM_ERRATA_LIST_VENDORS_H */
|
#endif /* ASM_ERRATA_LIST_VENDORS_H */
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@
|
||||||
#ifndef __ASSEMBLER__
|
#ifndef __ASSEMBLER__
|
||||||
|
|
||||||
#include <asm/barrier.h>
|
#include <asm/barrier.h>
|
||||||
|
#include <asm/errata_list.h>
|
||||||
#include <asm/insn-def.h>
|
#include <asm/insn-def.h>
|
||||||
|
|
||||||
static inline void cpu_relax(void)
|
static inline void cpu_relax(void)
|
||||||
|
|
@ -19,7 +20,7 @@ static inline void cpu_relax(void)
|
||||||
* Reduce instruction retirement.
|
* Reduce instruction retirement.
|
||||||
* This assumes the PC changes.
|
* This assumes the PC changes.
|
||||||
*/
|
*/
|
||||||
__asm__ __volatile__ (RISCV_PAUSE);
|
ALT_RISCV_PAUSE();
|
||||||
barrier();
|
barrier();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -47,6 +47,11 @@ static void riscv_fill_cpu_mfr_info(struct cpu_manufacturer_info_t *cpu_mfr_info
|
||||||
cpu_mfr_info->patch_func = andes_errata_patch_func;
|
cpu_mfr_info->patch_func = andes_errata_patch_func;
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef CONFIG_ERRATA_MIPS
|
||||||
|
case MIPS_VENDOR_ID:
|
||||||
|
cpu_mfr_info->patch_func = mips_errata_patch_func;
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
#ifdef CONFIG_ERRATA_SIFIVE
|
#ifdef CONFIG_ERRATA_SIFIVE
|
||||||
case SIFIVE_VENDOR_ID:
|
case SIFIVE_VENDOR_ID:
|
||||||
cpu_mfr_info->patch_func = sifive_errata_patch_func;
|
cpu_mfr_info->patch_func = sifive_errata_patch_func;
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@
|
||||||
#include <linux/init.h>
|
#include <linux/init.h>
|
||||||
#include <linux/linkage.h>
|
#include <linux/linkage.h>
|
||||||
|
|
||||||
|
#include <asm/alternative-macros.h>
|
||||||
#include <asm/asm.h>
|
#include <asm/asm.h>
|
||||||
#include <asm/csr.h>
|
#include <asm/csr.h>
|
||||||
#include <asm/scs.h>
|
#include <asm/scs.h>
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,7 @@
|
||||||
#include <linux/kfence.h>
|
#include <linux/kfence.h>
|
||||||
#include <linux/execmem.h>
|
#include <linux/execmem.h>
|
||||||
|
|
||||||
|
#include <asm/alternative.h>
|
||||||
#include <asm/fixmap.h>
|
#include <asm/fixmap.h>
|
||||||
#include <asm/io.h>
|
#include <asm/io.h>
|
||||||
#include <asm/kasan.h>
|
#include <asm/kasan.h>
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user