mirror of
https://github.com/torvalds/linux.git
synced 2026-05-25 23:52:08 +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".
|
||||
|
||||
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
|
||||
bool "SiFive errata"
|
||||
depends on RISCV_ALTERNATIVE
|
||||
|
|
|
|||
|
|
@ -13,5 +13,6 @@ endif
|
|||
endif
|
||||
|
||||
obj-$(CONFIG_ERRATA_ANDES) += andes/
|
||||
obj-$(CONFIG_ERRATA_MIPS) += mips/
|
||||
obj-$(CONFIG_ERRATA_SIFIVE) += sifive/
|
||||
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,
|
||||
unsigned long archid, unsigned long impid,
|
||||
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,
|
||||
unsigned long archid, unsigned long impid,
|
||||
unsigned int stage);
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@
|
|||
#include <asm/insn-def.h>
|
||||
#include <asm/cpufeature-macros.h>
|
||||
#include <asm/processor.h>
|
||||
#include <asm/errata_list.h>
|
||||
|
||||
#define __arch_xchg_masked(sc_sfx, swap_sfx, prepend, sc_append, \
|
||||
swap_append, r, p, n) \
|
||||
|
|
@ -438,7 +439,7 @@ static __always_inline void __cmpwait(volatile void *ptr,
|
|||
return;
|
||||
|
||||
no_zawrs:
|
||||
asm volatile(RISCV_PAUSE : : : "memory");
|
||||
ALT_RISCV_PAUSE();
|
||||
}
|
||||
|
||||
#define __cmpwait_relaxed(ptr, val) \
|
||||
|
|
|
|||
|
|
@ -5,12 +5,12 @@
|
|||
#ifndef ASM_ERRATA_LIST_H
|
||||
#define ASM_ERRATA_LIST_H
|
||||
|
||||
#include <asm/alternative.h>
|
||||
#include <asm/csr.h>
|
||||
#include <asm/insn-def.h>
|
||||
#include <asm/hwcap.h>
|
||||
#include <asm/vendorid_list.h>
|
||||
#include <asm/errata_list_vendors.h>
|
||||
#include <asm/vendor_extensions/mips.h>
|
||||
|
||||
#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) \
|
||||
: : "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
|
||||
* in the default case.
|
||||
|
|
|
|||
|
|
@ -21,4 +21,9 @@
|
|||
#define ERRATA_THEAD_NUMBER 3
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_ERRATA_MIPS
|
||||
#define ERRATA_MIPS_P8700_PAUSE_OPCODE 0
|
||||
#define ERRATA_MIPS_NUMBER 1
|
||||
#endif
|
||||
|
||||
#endif /* ASM_ERRATA_LIST_VENDORS_H */
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
#ifndef __ASSEMBLER__
|
||||
|
||||
#include <asm/barrier.h>
|
||||
#include <asm/errata_list.h>
|
||||
#include <asm/insn-def.h>
|
||||
|
||||
static inline void cpu_relax(void)
|
||||
|
|
@ -19,7 +20,7 @@ static inline void cpu_relax(void)
|
|||
* Reduce instruction retirement.
|
||||
* This assumes the PC changes.
|
||||
*/
|
||||
__asm__ __volatile__ (RISCV_PAUSE);
|
||||
ALT_RISCV_PAUSE();
|
||||
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;
|
||||
break;
|
||||
#endif
|
||||
#ifdef CONFIG_ERRATA_MIPS
|
||||
case MIPS_VENDOR_ID:
|
||||
cpu_mfr_info->patch_func = mips_errata_patch_func;
|
||||
break;
|
||||
#endif
|
||||
#ifdef CONFIG_ERRATA_SIFIVE
|
||||
case SIFIVE_VENDOR_ID:
|
||||
cpu_mfr_info->patch_func = sifive_errata_patch_func;
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@
|
|||
#include <linux/init.h>
|
||||
#include <linux/linkage.h>
|
||||
|
||||
#include <asm/alternative-macros.h>
|
||||
#include <asm/asm.h>
|
||||
#include <asm/csr.h>
|
||||
#include <asm/scs.h>
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@
|
|||
#include <linux/kfence.h>
|
||||
#include <linux/execmem.h>
|
||||
|
||||
#include <asm/alternative.h>
|
||||
#include <asm/fixmap.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/kasan.h>
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user