Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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>

authored by

Djordje Todorovic and committed by
Paul Walmsley
0b0ca959 c9a9fc23

+127 -3
+23
arch/riscv/Kconfig.errata
··· 21 21 22 22 If you don't know what to do here, say "Y". 23 23 24 + config ERRATA_MIPS 25 + bool "MIPS errata" 26 + depends on RISCV_ALTERNATIVE 27 + help 28 + All MIPS errata Kconfig depend on this Kconfig. Disabling 29 + this Kconfig will disable all MIPS errata. Please say "Y" 30 + here if your platform uses MIPS CPU cores. 31 + 32 + Otherwise, please say "N" here to avoid unnecessary overhead. 33 + 34 + config ERRATA_MIPS_P8700_PAUSE_OPCODE 35 + bool "Fix the PAUSE Opcode for MIPS P8700" 36 + depends on ERRATA_MIPS && 64BIT 37 + default n 38 + help 39 + The RISCV MIPS P8700 uses a different opcode for PAUSE. 40 + It is a 'hint' encoding of the SLLI instruction, 41 + with rd=0, rs1=0 and imm=5. It will behave as a NOP 42 + instruction if no additional behavior beyond that of 43 + SLLI is implemented. 44 + 45 + If you are not using the P8700 processor, say n. 46 + 24 47 config ERRATA_SIFIVE 25 48 bool "SiFive errata" 26 49 depends on RISCV_ALTERNATIVE
+1
arch/riscv/errata/Makefile
··· 13 13 endif 14 14 15 15 obj-$(CONFIG_ERRATA_ANDES) += andes/ 16 + obj-$(CONFIG_ERRATA_MIPS) += mips/ 16 17 obj-$(CONFIG_ERRATA_SIFIVE) += sifive/ 17 18 obj-$(CONFIG_ERRATA_THEAD) += thead/
+5
arch/riscv/errata/mips/Makefile
··· 1 + ifdef CONFIG_RISCV_ALTERNATIVE_EARLY 2 + CFLAGS_errata.o := -mcmodel=medany 3 + endif 4 + 5 + obj-y += errata.o
+67
arch/riscv/errata/mips/errata.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + /* 3 + * Copyright (C) 2025 MIPS. 4 + */ 5 + 6 + #include <linux/memory.h> 7 + #include <linux/module.h> 8 + #include <asm/text-patching.h> 9 + #include <asm/alternative.h> 10 + #include <asm/errata_list.h> 11 + #include <asm/vendorid_list.h> 12 + #include <asm/vendor_extensions.h> 13 + #include <asm/vendor_extensions/mips.h> 14 + 15 + static inline bool errata_probe_pause(void) 16 + { 17 + if (!IS_ENABLED(CONFIG_ERRATA_MIPS_P8700_PAUSE_OPCODE)) 18 + return false; 19 + 20 + if (!riscv_isa_vendor_extension_available(MIPS_VENDOR_ID, XMIPSEXECTL)) 21 + return false; 22 + 23 + return true; 24 + } 25 + 26 + static u32 mips_errata_probe(void) 27 + { 28 + u32 cpu_req_errata = 0; 29 + 30 + if (errata_probe_pause()) 31 + cpu_req_errata |= BIT(ERRATA_MIPS_P8700_PAUSE_OPCODE); 32 + 33 + return cpu_req_errata; 34 + } 35 + 36 + void mips_errata_patch_func(struct alt_entry *begin, struct alt_entry *end, 37 + unsigned long archid, unsigned long impid, 38 + unsigned int stage) 39 + { 40 + struct alt_entry *alt; 41 + u32 cpu_req_errata = mips_errata_probe(); 42 + u32 tmp; 43 + 44 + BUILD_BUG_ON(ERRATA_MIPS_NUMBER >= RISCV_VENDOR_EXT_ALTERNATIVES_BASE); 45 + 46 + if (stage == RISCV_ALTERNATIVES_EARLY_BOOT) 47 + return; 48 + 49 + for (alt = begin; alt < end; alt++) { 50 + if (alt->vendor_id != MIPS_VENDOR_ID) 51 + continue; 52 + 53 + if (alt->patch_id >= ERRATA_MIPS_NUMBER) { 54 + WARN(1, "MIPS errata id:%d not in kernel errata list\n", 55 + alt->patch_id); 56 + continue; 57 + } 58 + 59 + tmp = (1U << alt->patch_id); 60 + if (cpu_req_errata && tmp) { 61 + mutex_lock(&text_mutex); 62 + patch_text_nosync(ALT_OLD_PTR(alt), ALT_ALT_PTR(alt), 63 + alt->alt_len); 64 + mutex_unlock(&text_mutex); 65 + } 66 + } 67 + }
+3
arch/riscv/include/asm/alternative.h
··· 48 48 void andes_errata_patch_func(struct alt_entry *begin, struct alt_entry *end, 49 49 unsigned long archid, unsigned long impid, 50 50 unsigned int stage); 51 + void mips_errata_patch_func(struct alt_entry *begin, struct alt_entry *end, 52 + unsigned long archid, unsigned long impid, 53 + unsigned int stage); 51 54 void sifive_errata_patch_func(struct alt_entry *begin, struct alt_entry *end, 52 55 unsigned long archid, unsigned long impid, 53 56 unsigned int stage);
+2 -1
arch/riscv/include/asm/cmpxchg.h
··· 14 14 #include <asm/insn-def.h> 15 15 #include <asm/cpufeature-macros.h> 16 16 #include <asm/processor.h> 17 + #include <asm/errata_list.h> 17 18 18 19 #define __arch_xchg_masked(sc_sfx, swap_sfx, prepend, sc_append, \ 19 20 swap_append, r, p, n) \ ··· 439 438 return; 440 439 441 440 no_zawrs: 442 - asm volatile(RISCV_PAUSE : : : "memory"); 441 + ALT_RISCV_PAUSE(); 443 442 } 444 443 445 444 #define __cmpwait_relaxed(ptr, val) \
+12 -1
arch/riscv/include/asm/errata_list.h
··· 5 5 #ifndef ASM_ERRATA_LIST_H 6 6 #define ASM_ERRATA_LIST_H 7 7 8 - #include <asm/alternative.h> 9 8 #include <asm/csr.h> 10 9 #include <asm/insn-def.h> 11 10 #include <asm/hwcap.h> 12 11 #include <asm/vendorid_list.h> 13 12 #include <asm/errata_list_vendors.h> 13 + #include <asm/vendor_extensions/mips.h> 14 14 15 15 #ifdef __ASSEMBLER__ 16 16 ··· 41 41 asm(ALTERNATIVE("sfence.vma %0, %1", "sfence.vma", SIFIVE_VENDOR_ID, \ 42 42 ERRATA_SIFIVE_CIP_1200, CONFIG_ERRATA_SIFIVE_CIP_1200) \ 43 43 : : "r" (addr), "r" (asid) : "memory") 44 + 45 + #define ALT_RISCV_PAUSE() \ 46 + asm(ALTERNATIVE( \ 47 + RISCV_PAUSE, /* Original RISC‑V pause insn */ \ 48 + MIPS_PAUSE, /* Replacement for MIPS P8700 */ \ 49 + MIPS_VENDOR_ID, /* Vendor ID to match */ \ 50 + ERRATA_MIPS_P8700_PAUSE_OPCODE, /* patch_id */ \ 51 + CONFIG_ERRATA_MIPS_P8700_PAUSE_OPCODE) \ 52 + : /* no outputs */ \ 53 + : /* no inputs */ \ 54 + : "memory") 44 55 45 56 /* 46 57 * _val is marked as "will be overwritten", so need to set it to 0
+5
arch/riscv/include/asm/errata_list_vendors.h
··· 21 21 #define ERRATA_THEAD_NUMBER 3 22 22 #endif 23 23 24 + #ifdef CONFIG_ERRATA_MIPS 25 + #define ERRATA_MIPS_P8700_PAUSE_OPCODE 0 26 + #define ERRATA_MIPS_NUMBER 1 27 + #endif 28 + 24 29 #endif /* ASM_ERRATA_LIST_VENDORS_H */
+2 -1
arch/riscv/include/asm/vdso/processor.h
··· 5 5 #ifndef __ASSEMBLER__ 6 6 7 7 #include <asm/barrier.h> 8 + #include <asm/errata_list.h> 8 9 #include <asm/insn-def.h> 9 10 10 11 static inline void cpu_relax(void) ··· 20 19 * Reduce instruction retirement. 21 20 * This assumes the PC changes. 22 21 */ 23 - __asm__ __volatile__ (RISCV_PAUSE); 22 + ALT_RISCV_PAUSE(); 24 23 barrier(); 25 24 } 26 25
+5
arch/riscv/kernel/alternative.c
··· 47 47 cpu_mfr_info->patch_func = andes_errata_patch_func; 48 48 break; 49 49 #endif 50 + #ifdef CONFIG_ERRATA_MIPS 51 + case MIPS_VENDOR_ID: 52 + cpu_mfr_info->patch_func = mips_errata_patch_func; 53 + break; 54 + #endif 50 55 #ifdef CONFIG_ERRATA_SIFIVE 51 56 case SIFIVE_VENDOR_ID: 52 57 cpu_mfr_info->patch_func = sifive_errata_patch_func;
+1
arch/riscv/kernel/entry.S
··· 7 7 #include <linux/init.h> 8 8 #include <linux/linkage.h> 9 9 10 + #include <asm/alternative-macros.h> 10 11 #include <asm/asm.h> 11 12 #include <asm/csr.h> 12 13 #include <asm/scs.h>
+1
arch/riscv/mm/init.c
··· 23 23 #include <linux/kfence.h> 24 24 #include <linux/execmem.h> 25 25 26 + #include <asm/alternative.h> 26 27 #include <asm/fixmap.h> 27 28 #include <asm/io.h> 28 29 #include <asm/kasan.h>