Linux-RISC-V Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v6 0/5] Add workarounds for Picoheart errata
@ 2026-11-04  7:57 Yicong Yang
  2026-11-04  7:57 ` [PATCH v6 1/5] riscv: Make get_insn public for instruction fault handling Yicong Yang
                   ` (4 more replies)
  0 siblings, 5 replies; 12+ messages in thread
From: Yicong Yang @ 2026-11-04  7:57 UTC (permalink / raw)
  To: pjw, palmer, aou, linux-riscv
  Cc: conor, wangruikang, ganboing, alex, cleger, geshijian, niehaitao,
	cuiyunhui, gaohan, yang.yicong

This series adds an errata framework for Picoheart SoCs and workarounds
for two hardware issues: unreliable cbo.clean writeback and unavailable
AMOCAS.Q despite the Zacas extension being advertised.

On affected CPUs, use cbo.flush for kernel cache writeback and trap
userspace cbo.clean/cbo.flush instructions to emulate them with cbo.flush.
Disable kernel cmpxchg128 support while retaining the other Zacas
operations. The supporting patches share the instruction-fetching helper
between fault handlers, add MXR support for execute-only mappings, and
add CBO instruction decoding definitions.

[Apply Notice]
Patch 1/5 based on below fix of stale SR_* on context switch.
https://lore.kernel.org/all/20261022083212.84721-1-cuiyunhui@bytedance.com/

Changes since v5:
- Rebase on v7.4-rc1 and drop the obsolete RISCV_ALTERNATIVE stuffs
- Use the simpler v4-style get_user() wrapper in __read_insn()
- Add Tested-by tags from Han Gao. Thanks for testing.
Link: https://lore.kernel.org/linux-riscv/20261017083100.40157-1-yang.yicong@picoheart.com/

Changes since v4:
- Rebase on v7.3-rc7.
- Make the CBO erratum depend on MMU.
- Limit MXR enablement to __get_user().
- Restrict Picoheart errata to 64BIT and skip alternative patching during
  RISCV_ALTERNATIVES_EARLY_BOOT.
Link: https://lore.kernel.org/linux-riscv/20260915083305.81913-1-yang.yicong@picoheart.com/

Changes since v3:
- Work around AMOCAS.Q by patching system_has_cmpxchg128().
Link: https://lore.kernel.org/linux-riscv/20260907072149.72031-1-yang.yicong@picoheart.com/

Changes since v2:
- Rebase on v7.3-rc2.
- Merge the MXR fix and get_insn() extraction into one patch.
Link: https://lore.kernel.org/linux-riscv/20260728094627.94975-1-yang.yicong@picoheart.com/

Changes since v1:
- Factor out a common get_insn() for reading userspace instructions.
- Fix instruction fetching from execute-only mappings.
- Apply cleanups and coding-style refinements from review.
Link: https://lore.kernel.org/linux-riscv/20260715084724.26578-1-yang.yicong@picoheart.com/

Yicong Yang (5):
  riscv: Make get_insn public for instruction fault handling
  riscv: insn: Support decoding of CBO instructions
  riscv: errata: Add init framework for picoheart errata
  riscv: errata: picoheart: Add workaround for cbo.clean errata
  riscv: errata: picoheart: Add workaround for AMOCASQ errata

 arch/riscv/Kconfig.errata                    |  35 +++
 arch/riscv/errata/Makefile                   |   1 +
 arch/riscv/errata/picoheart/Makefile         |   5 +
 arch/riscv/errata/picoheart/errata.c         | 235 +++++++++++++++++++
 arch/riscv/include/asm/alternative.h         |   3 +
 arch/riscv/include/asm/cmpxchg.h             |  18 +-
 arch/riscv/include/asm/csr.h                 |   1 +
 arch/riscv/include/asm/errata_list.h         |  25 +-
 arch/riscv/include/asm/errata_list_vendors.h |   5 +
 arch/riscv/include/asm/insn.h                |  63 ++++-
 arch/riscv/include/asm/processor.h           |   2 +-
 arch/riscv/include/asm/vendorid_list.h       |   1 +
 arch/riscv/kernel/alternative.c              |   5 +
 arch/riscv/kernel/asm-offsets.c              |   6 +-
 arch/riscv/kernel/cpufeature.c               |   3 +
 arch/riscv/kernel/entry.S                    |  14 +-
 arch/riscv/kernel/traps.c                    |   4 +
 arch/riscv/kernel/traps_misaligned.c         |  52 ----
 arch/riscv/kernel/vector.c                   |   6 +-
 19 files changed, 414 insertions(+), 70 deletions(-)
 create mode 100644 arch/riscv/errata/picoheart/Makefile
 create mode 100644 arch/riscv/errata/picoheart/errata.c

-- 
2.54.0 (Apple Git-157)

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 12+ messages in thread

* [PATCH v6 1/5] riscv: Make get_insn public for instruction fault handling
  2026-11-04  7:57 [PATCH v6 0/5] Add workarounds for Picoheart errata Yicong Yang
@ 2026-11-04  7:57 ` Yicong Yang
  2026-11-04  7:57 ` [PATCH v6 2/5] riscv: insn: Support decoding of CBO instructions Yicong Yang
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 12+ messages in thread
From: Yicong Yang @ 2026-11-04  7:57 UTC (permalink / raw)
  To: pjw, palmer, aou, linux-riscv
  Cc: conor, wangruikang, ganboing, alex, cleger, geshijian, niehaitao,
	cuiyunhui, gaohan, yang.yicong

Currently two places (vector and misaligned load/store) need
to get fault instructions for handling and they implement the
function separately. This is a common function so make
get_insn() public in asm/insn.h for doing this job to make it
less fragile and improve the maintainability.

Also fix a bug that Bo Gan noticed: get_user() is insufficient
in this case since it's possible for the instruction segment
mapped as execute-only and get_user() doesn't have permissions
to load it. The architecture provides sstatus.MXR for handling
this so set MXR when reading userspace instruction.

Cc: Bo Gan <ganboing@gmail.com>
Tested-by: Han Gao <gaohan@iscas.ac.cn>
Signed-off-by: Yicong Yang <yang.yicong@picoheart.com>
---
 arch/riscv/include/asm/csr.h         |  1 +
 arch/riscv/include/asm/insn.h        | 55 ++++++++++++++++++++++++++++
 arch/riscv/include/asm/processor.h   |  2 +-
 arch/riscv/kernel/asm-offsets.c      |  6 +--
 arch/riscv/kernel/entry.S            | 14 +++----
 arch/riscv/kernel/traps_misaligned.c | 52 --------------------------
 arch/riscv/kernel/vector.c           |  6 +--
 7 files changed, 70 insertions(+), 66 deletions(-)

diff --git a/arch/riscv/include/asm/csr.h b/arch/riscv/include/asm/csr.h
index 621f84d1898f..e790cc2b8065 100644
--- a/arch/riscv/include/asm/csr.h
+++ b/arch/riscv/include/asm/csr.h
@@ -17,6 +17,7 @@
 #define SR_SPP		_AC(0x00000100, UL) /* Previously Supervisor */
 #define SR_MPP		_AC(0x00001800, UL) /* Previously Machine */
 #define SR_SUM		_AC(0x00040000, UL) /* Supervisor User Memory Access */
+#define SR_MXR		_AC(0x00080000, UL) /* Make eXecutable Readable */
 
 /* zicfilp landing pad status bit */
 #define SR_SPELP	_AC(0x00800000, UL)
diff --git a/arch/riscv/include/asm/insn.h b/arch/riscv/include/asm/insn.h
index ad348d8b8857..6fe5eb487c45 100644
--- a/arch/riscv/include/asm/insn.h
+++ b/arch/riscv/include/asm/insn.h
@@ -600,4 +600,59 @@ static inline void riscv_insn_insert_utype_itype_imm(u32 *utype_insn, u32 *itype
 	*utype_insn |= (imm & RV_U_IMM_31_12_MASK) + ((imm & BIT(11)) << 1);
 	*itype_insn |= ((imm & RV_I_IMM_11_0_MASK) << RV_I_IMM_11_0_OPOFF);
 }
+
+#define __read_insn(regs, insn, insn_addr, type)			\
+({									\
+	int __ret;							\
+									\
+	if (user_mode(regs)) {						\
+		csr_set(CSR_STATUS, SR_MXR);				\
+		__ret = get_user(insn, (type __user *) insn_addr);	\
+		csr_clear(CSR_STATUS, SR_MXR);				\
+	} else {							\
+		(insn) = *(type *)(insn_addr);				\
+		__ret = 0;						\
+	}								\
+									\
+	__ret;								\
+})
+
+static inline int get_insn(struct pt_regs *regs, ulong epc, ulong *r_insn)
+{
+	ulong insn = 0;
+
+	if (epc & 0x2) {
+		ulong tmp = 0;
+
+		if (__read_insn(regs, insn, epc, u16))
+			return -EFAULT;
+		/* __get_user() uses regular "lw" which sign extend the loaded
+		 * value make sure to clear higher order bits in case we "or" it
+		 * below with the upper 16 bits half.
+		 */
+		insn &= GENMASK(15, 0);
+		if ((insn & __INSN_LENGTH_MASK) != __INSN_LENGTH_32) {
+			*r_insn = insn;
+			return 0;
+		}
+		epc += sizeof(u16);
+		if (__read_insn(regs, tmp, epc, u16))
+			return -EFAULT;
+		*r_insn = (tmp << 16) | insn;
+
+		return 0;
+	} else {
+		if (__read_insn(regs, insn, epc, u32))
+			return -EFAULT;
+		if ((insn & __INSN_LENGTH_MASK) == __INSN_LENGTH_32) {
+			*r_insn = insn;
+			return 0;
+		}
+		insn &= GENMASK(15, 0);
+		*r_insn = insn;
+
+		return 0;
+	}
+}
+
 #endif /* _ASM_RISCV_INSN_H */
diff --git a/arch/riscv/include/asm/processor.h b/arch/riscv/include/asm/processor.h
index e9d339bcb7e9..2ea52a33b1e5 100644
--- a/arch/riscv/include/asm/processor.h
+++ b/arch/riscv/include/asm/processor.h
@@ -120,7 +120,7 @@ struct thread_struct {
 	struct __riscv_d_ext_state fstate;
 	unsigned long bad_cause;
 	unsigned long envcfg;
-	unsigned long sum;
+	unsigned long sum_mxr;
 	u32 riscv_v_flags;
 	u32 vstate_ctrl;
 	struct __riscv_v_ext_state vstate;
diff --git a/arch/riscv/kernel/asm-offsets.c b/arch/riscv/kernel/asm-offsets.c
index a75f0cfea1e9..b6de2179570b 100644
--- a/arch/riscv/kernel/asm-offsets.c
+++ b/arch/riscv/kernel/asm-offsets.c
@@ -35,7 +35,7 @@ void asm_offsets(void)
 	OFFSET(TASK_THREAD_S9, task_struct, thread.s[9]);
 	OFFSET(TASK_THREAD_S10, task_struct, thread.s[10]);
 	OFFSET(TASK_THREAD_S11, task_struct, thread.s[11]);
-	OFFSET(TASK_THREAD_SUM, task_struct, thread.sum);
+	OFFSET(TASK_THREAD_SUM_MXR, task_struct, thread.sum_mxr);
 
 	OFFSET(TASK_TI_CPU, task_struct, thread_info.cpu);
 	OFFSET(TASK_TI_PREEMPT_COUNT, task_struct, thread_info.preempt_count);
@@ -352,8 +352,8 @@ void asm_offsets(void)
 		  offsetof(struct task_struct, thread.s[11])
 		- offsetof(struct task_struct, thread.ra)
 	);
-	DEFINE(TASK_THREAD_SUM_RA,
-		  offsetof(struct task_struct, thread.sum)
+	DEFINE(TASK_THREAD_SUM_MXR_RA,
+		  offsetof(struct task_struct, thread.sum_mxr)
 		- offsetof(struct task_struct, thread.ra)
 	);
 
diff --git a/arch/riscv/kernel/entry.S b/arch/riscv/kernel/entry.S
index 628b85e3915a..71e116771d39 100644
--- a/arch/riscv/kernel/entry.S
+++ b/arch/riscv/kernel/entry.S
@@ -172,13 +172,13 @@ SYM_CODE_START(handle_exception)
 	save_from_x6_to_x31
 
 	/*
-	 * Disable user-mode memory access as it should only be set in the
-	 * actual user copy routines.
+	 * Disable user-mode memory access and MXR as it should only be set in
+	 * the actual user copy routines.
 	 *
 	 * Disable the FPU/Vector to detect illegal usage of floating point
 	 * or vector in kernel space.
 	 */
-	li t0, SR_SUM | SR_FS_VS
+	li t0, SR_SUM | SR_MXR | SR_FS_VS
 #ifdef CONFIG_64BIT
 	li t1, SR_ELP
 	or t0, t0, t1
@@ -443,15 +443,15 @@ SYM_FUNC_START(__switch_to)
 	REG_S s10, TASK_THREAD_S10_RA(a3)
 	REG_S s11, TASK_THREAD_S11_RA(a3)
 
-	/* Save and clear the user space access flag. */
-	li    s1, SR_SUM
+	/* Save and clear the user space access and MXR flag. */
+	li    s1, SR_SUM | SR_MXR
 	csrrc s0, CSR_STATUS, s1
-	REG_S s0, TASK_THREAD_SUM_RA(a3)
+	REG_S s0, TASK_THREAD_SUM_MXR_RA(a3)
 
 	/* Save the kernel shadow call stack pointer */
 	scs_save_current
 	/* Restore context from next->thread */
-	REG_L s0,  TASK_THREAD_SUM_RA(a4)
+	REG_L s0,  TASK_THREAD_SUM_MXR_RA(a4)
 	and   s0,  s0, s1
 	csrs  CSR_STATUS, s0
 	REG_L ra,  TASK_THREAD_RA_RA(a4)
diff --git a/arch/riscv/kernel/traps_misaligned.c b/arch/riscv/kernel/traps_misaligned.c
index 6e8ae6c66322..f10f14001480 100644
--- a/arch/riscv/kernel/traps_misaligned.c
+++ b/arch/riscv/kernel/traps_misaligned.c
@@ -129,58 +129,6 @@ static unsigned long get_f32_rs(unsigned long insn, u8 fp_reg_offset,
 #define GET_F32_RS2C(insn, regs) (get_f32_rs(insn, 2, regs))
 #define GET_F32_RS2S(insn, regs) (get_f32_rs(RVC_RS2S(insn), 0, regs))
 
-#define __read_insn(regs, insn, insn_addr, type)	\
-({							\
-	int __ret;					\
-							\
-	if (user_mode(regs)) {				\
-		__ret = get_user(insn, (type __user *) insn_addr); \
-	} else {					\
-		insn = *(type *)insn_addr;		\
-		__ret = 0;				\
-	}						\
-							\
-	__ret;						\
-})
-
-static inline int get_insn(struct pt_regs *regs, ulong epc, ulong *r_insn)
-{
-	ulong insn = 0;
-
-	if (epc & 0x2) {
-		ulong tmp = 0;
-
-		if (__read_insn(regs, insn, epc, u16))
-			return -EFAULT;
-		/* __get_user() uses regular "lw" which sign extend the loaded
-		 * value make sure to clear higher order bits in case we "or" it
-		 * below with the upper 16 bits half.
-		 */
-		insn &= GENMASK(15, 0);
-		if ((insn & __INSN_LENGTH_MASK) != __INSN_LENGTH_32) {
-			*r_insn = insn;
-			return 0;
-		}
-		epc += sizeof(u16);
-		if (__read_insn(regs, tmp, epc, u16))
-			return -EFAULT;
-		*r_insn = (tmp << 16) | insn;
-
-		return 0;
-	} else {
-		if (__read_insn(regs, insn, epc, u32))
-			return -EFAULT;
-		if ((insn & __INSN_LENGTH_MASK) == __INSN_LENGTH_32) {
-			*r_insn = insn;
-			return 0;
-		}
-		insn &= GENMASK(15, 0);
-		*r_insn = insn;
-
-		return 0;
-	}
-}
-
 union reg_data {
 	u8 data_bytes[8];
 	ulong data_ulong;
diff --git a/arch/riscv/kernel/vector.c b/arch/riscv/kernel/vector.c
index b112166d51e9..1e37810035a9 100644
--- a/arch/riscv/kernel/vector.c
+++ b/arch/riscv/kernel/vector.c
@@ -184,8 +184,8 @@ EXPORT_SYMBOL_GPL(riscv_v_vstate_ctrl_user_allowed);
 
 bool riscv_v_first_use_handler(struct pt_regs *regs)
 {
-	u32 __user *epc = (u32 __user *)regs->epc;
-	u32 insn = (u32)regs->badaddr;
+	unsigned long epc = regs->epc;
+	unsigned long insn = regs->badaddr;
 
 	if (!(has_vector() || has_xtheadvector()))
 		return false;
@@ -200,7 +200,7 @@ bool riscv_v_first_use_handler(struct pt_regs *regs)
 
 	/* Get the instruction */
 	if (!insn) {
-		if (__get_user(insn, epc))
+		if (get_insn(regs, epc, &insn))
 			return false;
 	}
 
-- 
2.54.0 (Apple Git-157)

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH v6 2/5] riscv: insn: Support decoding of CBO instructions
  2026-11-04  7:57 [PATCH v6 0/5] Add workarounds for Picoheart errata Yicong Yang
  2026-11-04  7:57 ` [PATCH v6 1/5] riscv: Make get_insn public for instruction fault handling Yicong Yang
@ 2026-11-04  7:57 ` Yicong Yang
  2026-11-04  7:57 ` [PATCH v6 3/5] riscv: errata: Add init framework for picoheart errata Yicong Yang
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 12+ messages in thread
From: Yicong Yang @ 2026-11-04  7:57 UTC (permalink / raw)
  To: pjw, palmer, aou, linux-riscv
  Cc: conor, wangruikang, ganboing, alex, cleger, geshijian, niehaitao,
	cuiyunhui, gaohan, yang.yicong

Add definitions for decoding CBO instructions. Rename
RVG_OPCODE_FENCE to RVG_OPCODE_MISC_MEM as spec defines
it as MISC-MEM and it's also used by CBO instructions.

Tested-by: Han Gao <gaohan@iscas.ac.cn>
Signed-off-by: Yicong Yang <yang.yicong@picoheart.com>
---
 arch/riscv/include/asm/insn.h | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/arch/riscv/include/asm/insn.h b/arch/riscv/include/asm/insn.h
index 6fe5eb487c45..0fe81a4ca062 100644
--- a/arch/riscv/include/asm/insn.h
+++ b/arch/riscv/include/asm/insn.h
@@ -12,6 +12,7 @@
 #define RV_INSN_FUNCT3_OPOFF	12
 #define RV_INSN_OPCODE_MASK	GENMASK(6, 0)
 #define RV_INSN_OPCODE_OPOFF	0
+#define RV_INSN_FUNCT12_MASK	GENMASK(31, 20)
 #define RV_INSN_FUNCT12_OPOFF	20
 
 #define RV_ENCODE_FUNCT3(f_)	(RVG_FUNCT3_##f_ << RV_INSN_FUNCT3_OPOFF)
@@ -135,7 +136,7 @@
 #define RVC_C2_RS1_MASK		GENMASK(4, 0)
 
 /* parts of opcode for RVG*/
-#define RVG_OPCODE_FENCE	0x0f
+#define RVG_OPCODE_MISC_MEM	0x0f
 #define RVG_OPCODE_AUIPC	0x17
 #define RVG_OPCODE_BRANCH	0x63
 #define RVG_OPCODE_JALR		0x67
@@ -171,6 +172,7 @@
 #define RVG_FUNCT3_JALR		0x0
 #define RVG_FUNCT3_BEQ		0x0
 #define RVG_FUNCT3_BNE		0x1
+#define RVG_FUNCT3_CBO		0x2
 #define RVG_FUNCT3_BLT		0x4
 #define RVG_FUNCT3_BGE		0x5
 #define RVG_FUNCT3_BLTU		0x6
@@ -186,12 +188,14 @@
 #define RVC_FUNCT4_C_EBREAK	0x9
 
 #define RVG_FUNCT12_EBREAK	0x1
+#define RVG_FUNCT12_CBO_CLEAN	0x1
+#define RVG_FUNCT12_CBO_FLUSH	0x2
 #define RVG_FUNCT12_SRET	0x102
 
 #define RVG_MATCH_AUIPC		(RVG_OPCODE_AUIPC)
 #define RVG_MATCH_JALR		(RV_ENCODE_FUNCT3(JALR) | RVG_OPCODE_JALR)
 #define RVG_MATCH_JAL		(RVG_OPCODE_JAL)
-#define RVG_MATCH_FENCE		(RVG_OPCODE_FENCE)
+#define RVG_MATCH_FENCE		(RVG_OPCODE_MISC_MEM)
 #define RVG_MATCH_BEQ		(RV_ENCODE_FUNCT3(BEQ) | RVG_OPCODE_BRANCH)
 #define RVG_MATCH_BNE		(RV_ENCODE_FUNCT3(BNE) | RVG_OPCODE_BRANCH)
 #define RVG_MATCH_BLT		(RV_ENCODE_FUNCT3(BLT) | RVG_OPCODE_BRANCH)
-- 
2.54.0 (Apple Git-157)

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH v6 3/5] riscv: errata: Add init framework for picoheart errata
  2026-11-04  7:57 [PATCH v6 0/5] Add workarounds for Picoheart errata Yicong Yang
  2026-11-04  7:57 ` [PATCH v6 1/5] riscv: Make get_insn public for instruction fault handling Yicong Yang
  2026-11-04  7:57 ` [PATCH v6 2/5] riscv: insn: Support decoding of CBO instructions Yicong Yang
@ 2026-11-04  7:57 ` Yicong Yang
  2026-11-04  7:57 ` [PATCH v6 4/5] riscv: errata: picoheart: Add workaround for cbo.clean errata Yicong Yang
  2026-11-04  7:57 ` [PATCH v6 5/5] riscv: errata: picoheart: Add workaround for AMOCASQ errata Yicong Yang
  4 siblings, 0 replies; 12+ messages in thread
From: Yicong Yang @ 2026-11-04  7:57 UTC (permalink / raw)
  To: pjw, palmer, aou, linux-riscv
  Cc: conor, wangruikang, ganboing, alex, cleger, geshijian, niehaitao,
	cuiyunhui, gaohan, yang.yicong

Add init framework for handling upcoming picoheart erratas.

Tested-by: Han Gao <gaohan@iscas.ac.cn>
Signed-off-by: Yicong Yang <yang.yicong@picoheart.com>
---
 arch/riscv/Kconfig.errata                    | 10 ++++
 arch/riscv/errata/Makefile                   |  1 +
 arch/riscv/errata/picoheart/Makefile         |  5 ++
 arch/riscv/errata/picoheart/errata.c         | 53 ++++++++++++++++++++
 arch/riscv/include/asm/alternative.h         |  3 ++
 arch/riscv/include/asm/errata_list_vendors.h |  4 ++
 arch/riscv/include/asm/vendorid_list.h       |  1 +
 arch/riscv/kernel/alternative.c              |  5 ++
 8 files changed, 82 insertions(+)
 create mode 100644 arch/riscv/errata/picoheart/Makefile
 create mode 100644 arch/riscv/errata/picoheart/errata.c

diff --git a/arch/riscv/Kconfig.errata b/arch/riscv/Kconfig.errata
index 4f77b3c6d7fd..3713e88bb446 100644
--- a/arch/riscv/Kconfig.errata
+++ b/arch/riscv/Kconfig.errata
@@ -179,4 +179,14 @@ config ERRATA_THEAD_GHOSTWRITE
 
 	  If you don't know what to do here, say "Y".
 
+config ERRATA_PICOHEART
+	bool "Picoheart errata"
+	depends on 64BIT
+	help
+	  All Picoheart errata Kconfig depend on this Kconfig. Disabling
+	  this Kconfig will disable all Picoheart errata. Please say "Y"
+	  here if your platform uses Picoheart CPU cores.
+
+	  Otherwise, please say "N" here to avoid unnecessary overhead.
+
 endmenu # "CPU errata selection"
diff --git a/arch/riscv/errata/Makefile b/arch/riscv/errata/Makefile
index 02a7a3335b1d..a36c5ce1ce7b 100644
--- a/arch/riscv/errata/Makefile
+++ b/arch/riscv/errata/Makefile
@@ -16,3 +16,4 @@ obj-$(CONFIG_ERRATA_ANDES) += andes/
 obj-$(CONFIG_ERRATA_MIPS) += mips/
 obj-$(CONFIG_ERRATA_SIFIVE) += sifive/
 obj-$(CONFIG_ERRATA_THEAD) += thead/
+obj-$(CONFIG_ERRATA_PICOHEART) += picoheart/
diff --git a/arch/riscv/errata/picoheart/Makefile b/arch/riscv/errata/picoheart/Makefile
new file mode 100644
index 000000000000..6278c389b801
--- /dev/null
+++ b/arch/riscv/errata/picoheart/Makefile
@@ -0,0 +1,5 @@
+ifdef CONFIG_RISCV_ALTERNATIVE_EARLY
+CFLAGS_errata.o := -mcmodel=medany
+endif
+
+obj-y += errata.o
diff --git a/arch/riscv/errata/picoheart/errata.c b/arch/riscv/errata/picoheart/errata.c
new file mode 100644
index 000000000000..aad0bf5ed7d2
--- /dev/null
+++ b/arch/riscv/errata/picoheart/errata.c
@@ -0,0 +1,53 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2026 Picoheart (SG) Pte. Ltd.
+ *
+ * Author: Yicong Yang <yang.yicong@picoheart.com>
+ */
+
+#include <linux/cacheflush.h>
+#include <linux/cleanup.h>
+#include <linux/kernel.h>
+#include <linux/memory.h>
+#include <linux/string.h>
+#include <asm/alternative.h>
+#include <asm/errata_list.h>
+#include <asm/text-patching.h>
+#include <asm/vendor_extensions.h>
+#include <asm/vendorid_list.h>
+
+static u32 picoheart_errata_probe(unsigned int stage, unsigned long archid,
+				  unsigned long impid)
+{
+	return 0;
+}
+
+void picoheart_errata_patch_func(struct alt_entry *begin, struct alt_entry *end,
+				 unsigned long archid, unsigned long impid,
+				 unsigned int stage)
+{
+	u32 cpu_req_errata = picoheart_errata_probe(stage, archid, impid);
+	struct alt_entry *alt;
+	void *oldptr, *altptr;
+	u32 tmp;
+
+	BUILD_BUG_ON(ERRATA_PICOHEART_NUMBER >= RISCV_VENDOR_EXT_ALTERNATIVES_BASE);
+
+	if (stage == RISCV_ALTERNATIVES_EARLY_BOOT)
+		return;
+
+	for (alt = begin; alt < end; alt++) {
+		if (alt->vendor_id != PICOHEART_VENDOR_ID ||
+		    alt->patch_id >= ERRATA_PICOHEART_NUMBER)
+			continue;
+
+		tmp = (1U << alt->patch_id);
+		if (cpu_req_errata & tmp) {
+			oldptr = ALT_OLD_PTR(alt);
+			altptr = ALT_ALT_PTR(alt);
+
+			guard(mutex)(&text_mutex);
+			patch_text_nosync(oldptr, altptr, alt->alt_len);
+		}
+	}
+}
diff --git a/arch/riscv/include/asm/alternative.h b/arch/riscv/include/asm/alternative.h
index 6be7b2b6ade9..b727e74606bf 100644
--- a/arch/riscv/include/asm/alternative.h
+++ b/arch/riscv/include/asm/alternative.h
@@ -55,6 +55,9 @@ void sifive_errata_patch_func(struct alt_entry *begin, struct alt_entry *end,
 void thead_errata_patch_func(struct alt_entry *begin, struct alt_entry *end,
 			     unsigned long archid, unsigned long impid,
 			     unsigned int stage);
+void picoheart_errata_patch_func(struct alt_entry *begin, struct alt_entry *end,
+				 unsigned long archid, unsigned long impid,
+				 unsigned int stage);
 
 void riscv_cpufeature_patch_func(struct alt_entry *begin, struct alt_entry *end,
 				 unsigned int stage);
diff --git a/arch/riscv/include/asm/errata_list_vendors.h b/arch/riscv/include/asm/errata_list_vendors.h
index 02b5ab0d23a8..8160afed8d21 100644
--- a/arch/riscv/include/asm/errata_list_vendors.h
+++ b/arch/riscv/include/asm/errata_list_vendors.h
@@ -28,4 +28,8 @@
 #define ERRATA_MIPS_NUMBER 2
 #endif
 
+#ifdef CONFIG_ERRATA_PICOHEART
+#define ERRATA_PICOHEART_NUMBER	0
+#endif
+
 #endif /* ASM_ERRATA_LIST_VENDORS_H */
diff --git a/arch/riscv/include/asm/vendorid_list.h b/arch/riscv/include/asm/vendorid_list.h
index 7f5030ee1fcf..1ea6d00eb61a 100644
--- a/arch/riscv/include/asm/vendorid_list.h
+++ b/arch/riscv/include/asm/vendorid_list.h
@@ -10,5 +10,6 @@
 #define MIPS_VENDOR_ID		0x127
 #define SIFIVE_VENDOR_ID	0x489
 #define THEAD_VENDOR_ID		0x5b7
+#define PICOHEART_VENDOR_ID     0x77d
 
 #endif
diff --git a/arch/riscv/kernel/alternative.c b/arch/riscv/kernel/alternative.c
index bbb215349452..d9e0e963237c 100644
--- a/arch/riscv/kernel/alternative.c
+++ b/arch/riscv/kernel/alternative.c
@@ -61,6 +61,11 @@ static void riscv_fill_cpu_mfr_info(struct cpu_manufacturer_info_t *cpu_mfr_info
 	case THEAD_VENDOR_ID:
 		cpu_mfr_info->patch_func = thead_errata_patch_func;
 		break;
+#endif
+#ifdef CONFIG_ERRATA_PICOHEART
+	case PICOHEART_VENDOR_ID:
+		cpu_mfr_info->patch_func = picoheart_errata_patch_func;
+		break;
 #endif
 	default:
 		cpu_mfr_info->patch_func = NULL;
-- 
2.54.0 (Apple Git-157)

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH v6 4/5] riscv: errata: picoheart: Add workaround for cbo.clean errata
  2026-11-04  7:57 [PATCH v6 0/5] Add workarounds for Picoheart errata Yicong Yang
                   ` (2 preceding siblings ...)
  2026-11-04  7:57 ` [PATCH v6 3/5] riscv: errata: Add init framework for picoheart errata Yicong Yang
@ 2026-11-04  7:57 ` Yicong Yang
  2026-11-04  7:57 ` [PATCH v6 5/5] riscv: errata: picoheart: Add workaround for AMOCASQ errata Yicong Yang
  4 siblings, 0 replies; 12+ messages in thread
From: Yicong Yang @ 2026-11-04  7:57 UTC (permalink / raw)
  To: pjw, palmer, aou, linux-riscv
  Cc: conor, wangruikang, ganboing, alex, cleger, geshijian, niehaitao,
	cuiyunhui, gaohan, yang.yicong

cbo.clean may fail to write back the cacheline in a few very corner
cases on the affected Picoheart SoCs. Since cbo.flush is not affected,
the problem could be solved by promoting cbo.clean to cbo.flush to
keep the data coherent. So Implement and register Picoheart specific
riscv_nonstd_cache_ops for all the kernel space cache maintenance
operations. Implement riscv_nonstd_cache_ops->wback with cbo.clean
while other callbacks with corresponding CBO operations.

This could solve the issue in the kernel space. For userspace, clear
the xenvcfg.CBCFE to trap the cbo.{clean, flush} and emulate
the cbo.clean with cbo.flush in the kernel space to avoid the issue.

Tested-by: Han Gao <gaohan@iscas.ac.cn>
Signed-off-by: Yicong Yang <yang.yicong@picoheart.com>
---
 arch/riscv/Kconfig.errata            |  13 +++
 arch/riscv/errata/picoheart/errata.c | 159 +++++++++++++++++++++++++++
 arch/riscv/include/asm/errata_list.h |  25 ++++-
 arch/riscv/kernel/cpufeature.c       |   3 +
 arch/riscv/kernel/traps.c            |   4 +
 5 files changed, 203 insertions(+), 1 deletion(-)

diff --git a/arch/riscv/Kconfig.errata b/arch/riscv/Kconfig.errata
index 3713e88bb446..c75dec4b0ba7 100644
--- a/arch/riscv/Kconfig.errata
+++ b/arch/riscv/Kconfig.errata
@@ -189,4 +189,17 @@ config ERRATA_PICOHEART
 
 	  Otherwise, please say "N" here to avoid unnecessary overhead.
 
+config ERRATA_PICOHEART_CBO_CLEAN
+	bool "Apply Picoheart cbo.clean errata"
+	depends on ERRATA_PICOHEART && MMU
+	select RISCV_NONSTANDARD_CACHE_OPS
+	select JUMP_LABEL
+	default y
+	help
+	   This will apply the cbo.clean errata workaround on the affected
+	   Picoheart SoCs where cbo.clean instructions may fail to write back
+	   the cacheline in few corner cases.
+
+	   If you don't know what to do here, say "Y".
+
 endmenu # "CPU errata selection"
diff --git a/arch/riscv/errata/picoheart/errata.c b/arch/riscv/errata/picoheart/errata.c
index aad0bf5ed7d2..c945ae694396 100644
--- a/arch/riscv/errata/picoheart/errata.c
+++ b/arch/riscv/errata/picoheart/errata.c
@@ -5,20 +5,179 @@
  * Author: Yicong Yang <yang.yicong@picoheart.com>
  */
 
+#include <linux/align.h>
 #include <linux/cacheflush.h>
 #include <linux/cleanup.h>
+#include <linux/jump_label.h>
 #include <linux/kernel.h>
 #include <linux/memory.h>
+#include <linux/mm_types.h>
+#include <linux/mmap_lock.h>
+#include <linux/signal.h>
 #include <linux/string.h>
+#include <asm/asm-extable.h>
 #include <asm/alternative.h>
+#include <asm/cpufeature.h>
+#include <asm/dma-noncoherent.h>
 #include <asm/errata_list.h>
+#include <asm/insn.h>
+#include <asm/insn-def.h>
 #include <asm/text-patching.h>
+#include <asm/uaccess.h>
 #include <asm/vendor_extensions.h>
 #include <asm/vendorid_list.h>
 
+#ifdef CONFIG_ERRATA_PICOHEART_CBO_CLEAN
+
+static bool insn_is_cbo_clean_flush(u32 insn_buf)
+{
+	u32 rd, opcode, funct3, funct12;
+
+	/* CBO instructions don't have compressed variants */
+	if (GET_INSN_LENGTH(insn_buf) != 4)
+		return false;
+
+	rd = RV_EXTRACT_RD_REG(insn_buf);
+	opcode = insn_buf & __INSN_OPCODE_MASK;
+	funct3 = insn_buf & RV_INSN_FUNCT3_MASK;
+	funct12 = insn_buf & RV_INSN_FUNCT12_MASK;
+
+	if (rd != 0 || opcode != RVG_OPCODE_MISC_MEM ||
+	    funct3 != RV_ENCODE_FUNCT3(CBO) ||
+	    (funct12 != RV_ENCODE_FUNCT12(CBO_CLEAN) &&
+	     funct12 != RV_ENCODE_FUNCT12(CBO_FLUSH)))
+		return false;
+
+	return true;
+}
+
+static int cbo_clean_fault_sicode(unsigned long addr)
+{
+	struct mm_struct *mm = current->mm;
+	struct vm_area_struct *vma;
+
+	guard(mmap_read_lock)(mm);
+	vma = vma_lookup(mm, addr);
+	if (!vma)
+		return SEGV_MAPERR;
+
+	return SEGV_ACCERR;
+}
+
+bool riscv_picoheart_illegal_insn_handler(struct pt_regs *regs)
+{
+	unsigned long insn = regs->badaddr;
+	unsigned long epc = regs->epc;
+	void __user *line_addr;
+	unsigned long addr;
+	int ret = 0;
+	u32 rs1;
+
+	if (!insn) {
+		if (get_insn(regs, epc, &insn))
+			return false;
+	}
+
+	if (!insn_is_cbo_clean_flush(insn))
+		return false;
+
+	rs1 = RV_EXTRACT_RS1_REG(insn);
+	addr = rs1 ? ((unsigned long *)regs)[rs1] : 0;
+	line_addr = (void __user *)ALIGN_DOWN(addr, riscv_cbom_block_size);
+
+	/*
+	 * Check if the target address is within the valid userspace
+	 * address range. Otherwise update the bad_cause to match the
+	 * store page fault. See the comment below.
+	 */
+	if (!access_ok(line_addr, riscv_cbom_block_size)) {
+		current->thread.bad_cause = EXC_STORE_PAGE_FAULT;
+		goto err_map;
+	}
+
+	__enable_user_access();
+	asm volatile("\n"
+		"1:	\n"
+		CBO_FLUSH(%[addr])
+		"2:	\n"
+		_ASM_EXTABLE_UACCESS_ERR(1b, 2b, %[err])
+	: [err] "+r" (ret)
+	: [addr] "r" (untagged_addr(addr))
+	: "memory");
+	__disable_user_access();
+
+	if (ret)
+		goto err_map;
+
+	regs->epc += GET_INSN_LENGTH(insn);
+	return true;
+
+err_map:
+	/*
+	 * We'll reach here if the target address is invalid.
+	 * cbo.{flush ,clean} on invalid address will cause
+	 * store page fault, update the cause and badaddr.
+	 */
+	regs->badaddr = addr;
+	regs->cause = current->thread.bad_cause;
+
+	/*
+	 * In emulation of the cbo.clean, a SIGSEGV rather than
+	 * a SIGILL should be issued if the target address is
+	 * invalid. Use do_trap() to handle the signal delivery
+	 * and related stuffs to make it analogous to the page
+	 * fault.
+	 */
+	do_trap(regs, SIGSEGV, cbo_clean_fault_sicode(untagged_addr(addr)),
+		untagged_addr(addr));
+
+	return true;
+}
+
+#endif /* CONFIG_ERRATA_PICOHEART_CBO_CLEAN */
+
+static void picoheart_errata_cache_wback(phys_addr_t paddr, size_t size)
+{
+	void *vaddr = phys_to_virt(paddr);
+
+	ALT_CMO_OP(FLUSH, vaddr, size, riscv_cbom_block_size);
+}
+
+/*
+ * The errata only affects the cbo.clean (wback) so use standard operations
+ * for other semantic.
+ */
+struct riscv_nonstd_cache_ops picoheart_errata_cmo_ops = {
+	.wback = &picoheart_errata_cache_wback,
+};
+
+DEFINE_STATIC_KEY_FALSE(has_picoheart_cbo_clean_errata);
+
+static void picoheart_errata_probe_cbo_clean(unsigned int stage,
+					     unsigned long archid,
+					     unsigned long impid)
+{
+	if (!IS_ENABLED(CONFIG_ERRATA_PICOHEART_CBO_CLEAN))
+		return;
+
+	if (stage != RISCV_ALTERNATIVES_BOOT)
+		return;
+
+	if (!riscv_isa_extension_available(NULL, ZICBOM))
+		return;
+
+	if (archid != 0x804a555049544552 || impid != 0x100)
+		return;
+
+	riscv_noncoherent_supported();
+	riscv_noncoherent_register_cache_ops(&picoheart_errata_cmo_ops);
+	static_branch_enable(&has_picoheart_cbo_clean_errata);
+}
+
 static u32 picoheart_errata_probe(unsigned int stage, unsigned long archid,
 				  unsigned long impid)
 {
+	picoheart_errata_probe_cbo_clean(stage, archid, impid);
 	return 0;
 }
 
diff --git a/arch/riscv/include/asm/errata_list.h b/arch/riscv/include/asm/errata_list.h
index 6fdb445c0f45..89216702814e 100644
--- a/arch/riscv/include/asm/errata_list.h
+++ b/arch/riscv/include/asm/errata_list.h
@@ -154,6 +154,29 @@ asm volatile(ALTERNATIVE(						\
 #define THEAD_C9XX_RV_IRQ_PMU			17
 #define THEAD_C9XX_CSR_SCOUNTEROF		0x5c5
 
-#endif /* __ASSEMBLER__ */
+#ifdef CONFIG_ERRATA_PICOHEART_CBO_CLEAN
+
+#include <linux/jump_label.h>
+
+DECLARE_STATIC_KEY_FALSE(has_picoheart_cbo_clean_errata);
+
+static inline bool riscv_has_picoheart_zicbom_errata(void)
+{
+	return static_branch_unlikely(&has_picoheart_cbo_clean_errata);
+}
+
+bool riscv_picoheart_illegal_insn_handler(struct pt_regs *regs);
+
+#else /* !CONFIG_ERRATA_PICOHEART_CBO_CLEAN */
+
+static inline bool riscv_has_picoheart_zicbom_errata(void) { return false; }
+static inline bool riscv_picoheart_illegal_insn_handler(struct pt_regs *regs)
+{
+	return false;
+}
+
+#endif /* CONFIG_ERRATA_PICOHEART_CBO_CLEAN */
+
+#endif /* __ASSEMBLY__ */
 
 #endif
diff --git a/arch/riscv/kernel/cpufeature.c b/arch/riscv/kernel/cpufeature.c
index 72bce616491f..6ceb27085406 100644
--- a/arch/riscv/kernel/cpufeature.c
+++ b/arch/riscv/kernel/cpufeature.c
@@ -1280,6 +1280,9 @@ void __init riscv_user_isa_enable(void)
 	if (!riscv_has_extension_unlikely(RISCV_ISA_EXT_ZICBOP) &&
 	    any_cpu_has_zicbop)
 		pr_warn("Zicbop disabled as it is unavailable on some harts\n");
+
+	if (riscv_has_picoheart_zicbom_errata())
+		current->thread.envcfg &= ~ENVCFG_CBCFE;
 }
 
 void riscv_clear_hypervisor_csr(void)
diff --git a/arch/riscv/kernel/traps.c b/arch/riscv/kernel/traps.c
index f8292adda099..a103203622ff 100644
--- a/arch/riscv/kernel/traps.c
+++ b/arch/riscv/kernel/traps.c
@@ -176,6 +176,10 @@ asmlinkage __visible __trap_section void do_trap_insn_illegal(struct pt_regs *re
 		local_irq_enable();
 
 		handled = riscv_v_first_use_handler(regs);
+
+		if (!handled && riscv_has_picoheart_zicbom_errata())
+			handled = riscv_picoheart_illegal_insn_handler(regs);
+
 		if (!handled)
 			do_trap_error(regs, SIGILL, ILL_ILLOPC, regs->epc,
 				      "Oops - illegal instruction");
-- 
2.54.0 (Apple Git-157)

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH v6 5/5] riscv: errata: picoheart: Add workaround for AMOCASQ errata
  2026-11-04  7:57 [PATCH v6 0/5] Add workarounds for Picoheart errata Yicong Yang
                   ` (3 preceding siblings ...)
  2026-11-04  7:57 ` [PATCH v6 4/5] riscv: errata: picoheart: Add workaround for cbo.clean errata Yicong Yang
@ 2026-11-04  7:57 ` Yicong Yang
  2026-11-07 13:34   ` Jisheng Zhang
  4 siblings, 1 reply; 12+ messages in thread
From: Yicong Yang @ 2026-11-04  7:57 UTC (permalink / raw)
  To: pjw, palmer, aou, linux-riscv
  Cc: conor, wangruikang, ganboing, alex, cleger, geshijian, niehaitao,
	cuiyunhui, gaohan, yang.yicong

Some Picoheart CPUs implement Zacas extension but lack support
for AMOCASQ PMA attribute. Thus makes the CASQ instruction de
facto unavailable. Since currently no ways to retrieve the PMA
information and the riscv kernel will declare cmpxchg128 support
if platform declare support of Zacas, the use of cmpxchg128 will
lead to PMA violation and crash the kernel. Add the errata
workaround to disable the use of cmpxchg128 on the affected CPUs.

Tested-by: Han Gao <gaohan@iscas.ac.cn>
Signed-off-by: Yicong Yang <yang.yicong@picoheart.com>
---
 arch/riscv/Kconfig.errata                    | 12 ++++++++++
 arch/riscv/errata/picoheart/errata.c         | 25 +++++++++++++++++++-
 arch/riscv/include/asm/cmpxchg.h             | 18 +++++++++++++-
 arch/riscv/include/asm/errata_list_vendors.h |  3 ++-
 4 files changed, 55 insertions(+), 3 deletions(-)

diff --git a/arch/riscv/Kconfig.errata b/arch/riscv/Kconfig.errata
index c75dec4b0ba7..4e6516ba3a42 100644
--- a/arch/riscv/Kconfig.errata
+++ b/arch/riscv/Kconfig.errata
@@ -202,4 +202,16 @@ config ERRATA_PICOHEART_CBO_CLEAN
 
 	   If you don't know what to do here, say "Y".
 
+config ERRATA_PICOHEART_AMOCASQ
+	bool "Apply Picoheart AMOCASQ errata"
+	depends on ERRATA_PICOHEART && RISCV_ISA_ZACAS
+	default y
+	help
+	  Some Picoheart CPUs implement the Zacas extension but lack support
+	  for AMOCASQ PMA attribute. Thus makes the CASQ instruction de facto
+	  unavailable. Enable this errata workaround to disable the use of
+	  CASQ in the kernel (cmpxchg128).
+
+	  If you don't know what to do here, say "Y".
+
 endmenu # "CPU errata selection"
diff --git a/arch/riscv/errata/picoheart/errata.c b/arch/riscv/errata/picoheart/errata.c
index c945ae694396..a658f38cf4de 100644
--- a/arch/riscv/errata/picoheart/errata.c
+++ b/arch/riscv/errata/picoheart/errata.c
@@ -174,11 +174,34 @@ static void picoheart_errata_probe_cbo_clean(unsigned int stage,
 	static_branch_enable(&has_picoheart_cbo_clean_errata);
 }
 
+static bool picoheart_errata_probe_amocasq(unsigned int stage,
+					   unsigned long archid,
+					   unsigned long impid)
+{
+	if (!IS_ENABLED(CONFIG_ERRATA_PICOHEART_AMOCASQ))
+		return false;
+
+	if (!IS_ENABLED(CONFIG_RISCV_ISA_ZACAS) ||
+	    !riscv_isa_extension_available(NULL, ZACAS))
+		return false;
+
+	if (archid != 0x804a555049544552 || impid != 0x100)
+		return false;
+
+	return true;
+}
+
 static u32 picoheart_errata_probe(unsigned int stage, unsigned long archid,
 				  unsigned long impid)
 {
+	u32 cpu_req_errata = 0;
+
 	picoheart_errata_probe_cbo_clean(stage, archid, impid);
-	return 0;
+
+	if (picoheart_errata_probe_amocasq(stage, archid, impid))
+		cpu_req_errata |= BIT(ERRATA_PICOHEART_AMOCASQ);
+
+	return cpu_req_errata;
 }
 
 void picoheart_errata_patch_func(struct alt_entry *begin, struct alt_entry *end,
diff --git a/arch/riscv/include/asm/cmpxchg.h b/arch/riscv/include/asm/cmpxchg.h
index 662e160b0522..0488b9314c13 100644
--- a/arch/riscv/include/asm/cmpxchg.h
+++ b/arch/riscv/include/asm/cmpxchg.h
@@ -329,7 +329,23 @@
 
 #if defined(CONFIG_64BIT) && defined(CONFIG_RISCV_ISA_ZACAS) && defined(CONFIG_TOOLCHAIN_HAS_ZACAS)
 
-#define system_has_cmpxchg128()        riscv_has_extension_unlikely(RISCV_ISA_EXT_ZACAS)
+#define system_has_cmpxchg128 system_has_cmpxchg128
+static __always_inline bool system_has_cmpxchg128(void)
+{
+	/* The vendor erratum overrides the standard Zacas alternative. */
+	asm goto(ALTERNATIVE_2(
+			"nop",
+			"j %l[l_yes]",
+			STANDARD_EXT, RISCV_ISA_EXT_ZACAS, 1,
+			"nop",
+			PICOHEART_VENDOR_ID, ERRATA_PICOHEART_AMOCASQ,
+			CONFIG_ERRATA_PICOHEART_AMOCASQ)
+		: : : : l_yes);
+
+	return false;
+l_yes:
+	return true;
+}
 
 union __u128_halves {
 	u128 full;
diff --git a/arch/riscv/include/asm/errata_list_vendors.h b/arch/riscv/include/asm/errata_list_vendors.h
index 8160afed8d21..97b7bbdc4984 100644
--- a/arch/riscv/include/asm/errata_list_vendors.h
+++ b/arch/riscv/include/asm/errata_list_vendors.h
@@ -29,7 +29,8 @@
 #endif
 
 #ifdef CONFIG_ERRATA_PICOHEART
-#define ERRATA_PICOHEART_NUMBER	0
+#define ERRATA_PICOHEART_AMOCASQ	0
+#define ERRATA_PICOHEART_NUMBER		1
 #endif
 
 #endif /* ASM_ERRATA_LIST_VENDORS_H */
-- 
2.54.0 (Apple Git-157)

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* Re: [PATCH v6 5/5] riscv: errata: picoheart: Add workaround for AMOCASQ errata
  2026-11-04  7:57 ` [PATCH v6 5/5] riscv: errata: picoheart: Add workaround for AMOCASQ errata Yicong Yang
@ 2026-11-07 13:34   ` Jisheng Zhang
  2026-11-07 15:10     ` Yicong Yang
  0 siblings, 1 reply; 12+ messages in thread
From: Jisheng Zhang @ 2026-11-07 13:34 UTC (permalink / raw)
  To: Yicong Yang
  Cc: pjw, palmer, aou, linux-riscv, conor, wangruikang, ganboing, alex,
	cleger, geshijian, niehaitao, cuiyunhui, gaohan

On Wed, Nov 04, 2026 at 03:57:06PM +0800, Yicong Yang wrote:
> Some Picoheart CPUs implement Zacas extension but lack support
> for AMOCASQ PMA attribute. Thus makes the CASQ instruction de
> facto unavailable. Since currently no ways to retrieve the PMA
> information and the riscv kernel will declare cmpxchg128 support
> if platform declare support of Zacas, the use of cmpxchg128 will
> lead to PMA violation and crash the kernel. Add the errata
> workaround to disable the use of cmpxchg128 on the affected CPUs.
> 
> Tested-by: Han Gao <gaohan@iscas.ac.cn>
> Signed-off-by: Yicong Yang <yang.yicong@picoheart.com>
> ---
>  arch/riscv/Kconfig.errata                    | 12 ++++++++++
>  arch/riscv/errata/picoheart/errata.c         | 25 +++++++++++++++++++-
>  arch/riscv/include/asm/cmpxchg.h             | 18 +++++++++++++-
>  arch/riscv/include/asm/errata_list_vendors.h |  3 ++-
>  4 files changed, 55 insertions(+), 3 deletions(-)
> 
> diff --git a/arch/riscv/Kconfig.errata b/arch/riscv/Kconfig.errata
> index c75dec4b0ba7..4e6516ba3a42 100644
> --- a/arch/riscv/Kconfig.errata
> +++ b/arch/riscv/Kconfig.errata
> @@ -202,4 +202,16 @@ config ERRATA_PICOHEART_CBO_CLEAN
>  
>  	   If you don't know what to do here, say "Y".
>  
> +config ERRATA_PICOHEART_AMOCASQ
> +	bool "Apply Picoheart AMOCASQ errata"
> +	depends on ERRATA_PICOHEART && RISCV_ISA_ZACAS
> +	default y
> +	help
> +	  Some Picoheart CPUs implement the Zacas extension but lack support
> +	  for AMOCASQ PMA attribute. Thus makes the CASQ instruction de facto
> +	  unavailable. Enable this errata workaround to disable the use of
> +	  CASQ in the kernel (cmpxchg128).
> +
> +	  If you don't know what to do here, say "Y".
> +
>  endmenu # "CPU errata selection"
> diff --git a/arch/riscv/errata/picoheart/errata.c b/arch/riscv/errata/picoheart/errata.c
> index c945ae694396..a658f38cf4de 100644
> --- a/arch/riscv/errata/picoheart/errata.c
> +++ b/arch/riscv/errata/picoheart/errata.c
> @@ -174,11 +174,34 @@ static void picoheart_errata_probe_cbo_clean(unsigned int stage,
>  	static_branch_enable(&has_picoheart_cbo_clean_errata);
>  }
>  
> +static bool picoheart_errata_probe_amocasq(unsigned int stage,
> +					   unsigned long archid,
> +					   unsigned long impid)
> +{
> +	if (!IS_ENABLED(CONFIG_ERRATA_PICOHEART_AMOCASQ))
> +		return false;
> +
> +	if (!IS_ENABLED(CONFIG_RISCV_ISA_ZACAS) ||
> +	    !riscv_isa_extension_available(NULL, ZACAS))
> +		return false;
> +
> +	if (archid != 0x804a555049544552 || impid != 0x100)
> +		return false;
> +
> +	return true;
> +}
> +
>  static u32 picoheart_errata_probe(unsigned int stage, unsigned long archid,
>  				  unsigned long impid)
>  {
> +	u32 cpu_req_errata = 0;
> +
>  	picoheart_errata_probe_cbo_clean(stage, archid, impid);
> -	return 0;
> +
> +	if (picoheart_errata_probe_amocasq(stage, archid, impid))
> +		cpu_req_errata |= BIT(ERRATA_PICOHEART_AMOCASQ);
> +
> +	return cpu_req_errata;
>  }
>  
>  void picoheart_errata_patch_func(struct alt_entry *begin, struct alt_entry *end,
> diff --git a/arch/riscv/include/asm/cmpxchg.h b/arch/riscv/include/asm/cmpxchg.h
> index 662e160b0522..0488b9314c13 100644
> --- a/arch/riscv/include/asm/cmpxchg.h
> +++ b/arch/riscv/include/asm/cmpxchg.h
> @@ -329,7 +329,23 @@
>  
>  #if defined(CONFIG_64BIT) && defined(CONFIG_RISCV_ISA_ZACAS) && defined(CONFIG_TOOLCHAIN_HAS_ZACAS)
>  
> -#define system_has_cmpxchg128()        riscv_has_extension_unlikely(RISCV_ISA_EXT_ZACAS)
> +#define system_has_cmpxchg128 system_has_cmpxchg128
> +static __always_inline bool system_has_cmpxchg128(void)
> +{
> +	/* The vendor erratum overrides the standard Zacas alternative. */
> +	asm goto(ALTERNATIVE_2(
> +			"nop",
> +			"j %l[l_yes]",
> +			STANDARD_EXT, RISCV_ISA_EXT_ZACAS, 1,
> +			"nop",
> +			PICOHEART_VENDOR_ID, ERRATA_PICOHEART_AMOCASQ,
> +			CONFIG_ERRATA_PICOHEART_AMOCASQ)
> +		: : : : l_yes);

This makes the generic code ugly, adds some maintain effort.
why not discarding "zacas" in the dts? It's much simpler

> +
> +	return false;
> +l_yes:
> +	return true;
> +}
>  
>  union __u128_halves {
>  	u128 full;
> diff --git a/arch/riscv/include/asm/errata_list_vendors.h b/arch/riscv/include/asm/errata_list_vendors.h
> index 8160afed8d21..97b7bbdc4984 100644
> --- a/arch/riscv/include/asm/errata_list_vendors.h
> +++ b/arch/riscv/include/asm/errata_list_vendors.h
> @@ -29,7 +29,8 @@
>  #endif
>  
>  #ifdef CONFIG_ERRATA_PICOHEART
> -#define ERRATA_PICOHEART_NUMBER	0
> +#define ERRATA_PICOHEART_AMOCASQ	0
> +#define ERRATA_PICOHEART_NUMBER		1
>  #endif
>  
>  #endif /* ASM_ERRATA_LIST_VENDORS_H */
> -- 
> 2.54.0 (Apple Git-157)
> 
> _______________________________________________
> linux-riscv mailing list
> linux-riscv@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-riscv

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH v6 5/5] riscv: errata: picoheart: Add workaround for AMOCASQ errata
  2026-11-07 13:34   ` Jisheng Zhang
@ 2026-11-07 15:10     ` Yicong Yang
  2026-11-08  1:33       ` Jisheng Zhang
  0 siblings, 1 reply; 12+ messages in thread
From: Yicong Yang @ 2026-11-07 15:10 UTC (permalink / raw)
  To: Jisheng Zhang
  Cc: yang.yicong, pjw, palmer, aou, linux-riscv, conor, wangruikang,
	ganboing, alex, cleger, geshijian, niehaitao, cuiyunhui, gaohan

On 11/7/26 9:34 PM, Jisheng Zhang wrote:
> On Wed, Nov 04, 2026 at 03:57:06PM +0800, Yicong Yang wrote:
>> Some Picoheart CPUs implement Zacas extension but lack support
>> for AMOCASQ PMA attribute. Thus makes the CASQ instruction de
>> facto unavailable. Since currently no ways to retrieve the PMA
>> information and the riscv kernel will declare cmpxchg128 support
>> if platform declare support of Zacas, the use of cmpxchg128 will
>> lead to PMA violation and crash the kernel. Add the errata
>> workaround to disable the use of cmpxchg128 on the affected CPUs.
>>
>> Tested-by: Han Gao <gaohan@iscas.ac.cn>
>> Signed-off-by: Yicong Yang <yang.yicong@picoheart.com>
>> ---
>>  arch/riscv/Kconfig.errata                    | 12 ++++++++++
>>  arch/riscv/errata/picoheart/errata.c         | 25 +++++++++++++++++++-
>>  arch/riscv/include/asm/cmpxchg.h             | 18 +++++++++++++-
>>  arch/riscv/include/asm/errata_list_vendors.h |  3 ++-
>>  4 files changed, 55 insertions(+), 3 deletions(-)
>>
>> diff --git a/arch/riscv/Kconfig.errata b/arch/riscv/Kconfig.errata
>> index c75dec4b0ba7..4e6516ba3a42 100644
>> --- a/arch/riscv/Kconfig.errata
>> +++ b/arch/riscv/Kconfig.errata
>> @@ -202,4 +202,16 @@ config ERRATA_PICOHEART_CBO_CLEAN
>>  
>>  	   If you don't know what to do here, say "Y".
>>  
>> +config ERRATA_PICOHEART_AMOCASQ
>> +	bool "Apply Picoheart AMOCASQ errata"
>> +	depends on ERRATA_PICOHEART && RISCV_ISA_ZACAS
>> +	default y
>> +	help
>> +	  Some Picoheart CPUs implement the Zacas extension but lack support
>> +	  for AMOCASQ PMA attribute. Thus makes the CASQ instruction de facto
>> +	  unavailable. Enable this errata workaround to disable the use of
>> +	  CASQ in the kernel (cmpxchg128).
>> +
>> +	  If you don't know what to do here, say "Y".
>> +
>>  endmenu # "CPU errata selection"
>> diff --git a/arch/riscv/errata/picoheart/errata.c b/arch/riscv/errata/picoheart/errata.c
>> index c945ae694396..a658f38cf4de 100644
>> --- a/arch/riscv/errata/picoheart/errata.c
>> +++ b/arch/riscv/errata/picoheart/errata.c
>> @@ -174,11 +174,34 @@ static void picoheart_errata_probe_cbo_clean(unsigned int stage,
>>  	static_branch_enable(&has_picoheart_cbo_clean_errata);
>>  }
>>  
>> +static bool picoheart_errata_probe_amocasq(unsigned int stage,
>> +					   unsigned long archid,
>> +					   unsigned long impid)
>> +{
>> +	if (!IS_ENABLED(CONFIG_ERRATA_PICOHEART_AMOCASQ))
>> +		return false;
>> +
>> +	if (!IS_ENABLED(CONFIG_RISCV_ISA_ZACAS) ||
>> +	    !riscv_isa_extension_available(NULL, ZACAS))
>> +		return false;
>> +
>> +	if (archid != 0x804a555049544552 || impid != 0x100)
>> +		return false;
>> +
>> +	return true;
>> +}
>> +
>>  static u32 picoheart_errata_probe(unsigned int stage, unsigned long archid,
>>  				  unsigned long impid)
>>  {
>> +	u32 cpu_req_errata = 0;
>> +
>>  	picoheart_errata_probe_cbo_clean(stage, archid, impid);
>> -	return 0;
>> +
>> +	if (picoheart_errata_probe_amocasq(stage, archid, impid))
>> +		cpu_req_errata |= BIT(ERRATA_PICOHEART_AMOCASQ);
>> +
>> +	return cpu_req_errata;
>>  }
>>  
>>  void picoheart_errata_patch_func(struct alt_entry *begin, struct alt_entry *end,
>> diff --git a/arch/riscv/include/asm/cmpxchg.h b/arch/riscv/include/asm/cmpxchg.h
>> index 662e160b0522..0488b9314c13 100644
>> --- a/arch/riscv/include/asm/cmpxchg.h
>> +++ b/arch/riscv/include/asm/cmpxchg.h
>> @@ -329,7 +329,23 @@
>>  
>>  #if defined(CONFIG_64BIT) && defined(CONFIG_RISCV_ISA_ZACAS) && defined(CONFIG_TOOLCHAIN_HAS_ZACAS)
>>  
>> -#define system_has_cmpxchg128()        riscv_has_extension_unlikely(RISCV_ISA_EXT_ZACAS)
>> +#define system_has_cmpxchg128 system_has_cmpxchg128
>> +static __always_inline bool system_has_cmpxchg128(void)
>> +{
>> +	/* The vendor erratum overrides the standard Zacas alternative. */
>> +	asm goto(ALTERNATIVE_2(
>> +			"nop",
>> +			"j %l[l_yes]",
>> +			STANDARD_EXT, RISCV_ISA_EXT_ZACAS, 1,
>> +			"nop",
>> +			PICOHEART_VENDOR_ID, ERRATA_PICOHEART_AMOCASQ,
>> +			CONFIG_ERRATA_PICOHEART_AMOCASQ)
>> +		: : : : l_yes);
> 
> This makes the generic code ugly, adds some maintain effort.
> why not discarding "zacas" in the dts? It's much simpler

it'll prevent the usage of other more widely used CAS instructions
in both user and kernel space. we'd like to retain the performance
benefit of CAS over LR/SC for primitives such as cmpxchg() on our
server as well.

since kernel already provides system_has_cmpxchg128() as a
separate capability check, disabling 128-bit CAS here lets us
limit the workaround to cmpxhg128 only and could be a reasonable
solution.

thanks.

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH v6 5/5] riscv: errata: picoheart: Add workaround for AMOCASQ errata
  2026-11-07 15:10     ` Yicong Yang
@ 2026-11-08  1:33       ` Jisheng Zhang
  2026-11-10  9:50         ` Yicong Yang
  0 siblings, 1 reply; 12+ messages in thread
From: Jisheng Zhang @ 2026-11-08  1:33 UTC (permalink / raw)
  To: Yicong Yang
  Cc: pjw, palmer, aou, linux-riscv, conor, wangruikang, ganboing, alex,
	cleger, geshijian, niehaitao, cuiyunhui, gaohan

On Sat, Nov 07, 2026 at 11:10:59PM +0800, Yicong Yang wrote:
> On 11/7/26 9:34 PM, Jisheng Zhang wrote:
> > On Wed, Nov 04, 2026 at 03:57:06PM +0800, Yicong Yang wrote:
> >> Some Picoheart CPUs implement Zacas extension but lack support
> >> for AMOCASQ PMA attribute. Thus makes the CASQ instruction de
> >> facto unavailable. Since currently no ways to retrieve the PMA
> >> information and the riscv kernel will declare cmpxchg128 support
> >> if platform declare support of Zacas, the use of cmpxchg128 will
> >> lead to PMA violation and crash the kernel. Add the errata
> >> workaround to disable the use of cmpxchg128 on the affected CPUs.
> >>
> >> Tested-by: Han Gao <gaohan@iscas.ac.cn>
> >> Signed-off-by: Yicong Yang <yang.yicong@picoheart.com>
> >> ---
> >>  arch/riscv/Kconfig.errata                    | 12 ++++++++++
> >>  arch/riscv/errata/picoheart/errata.c         | 25 +++++++++++++++++++-
> >>  arch/riscv/include/asm/cmpxchg.h             | 18 +++++++++++++-
> >>  arch/riscv/include/asm/errata_list_vendors.h |  3 ++-
> >>  4 files changed, 55 insertions(+), 3 deletions(-)
> >>
> >> diff --git a/arch/riscv/Kconfig.errata b/arch/riscv/Kconfig.errata
> >> index c75dec4b0ba7..4e6516ba3a42 100644
> >> --- a/arch/riscv/Kconfig.errata
> >> +++ b/arch/riscv/Kconfig.errata
> >> @@ -202,4 +202,16 @@ config ERRATA_PICOHEART_CBO_CLEAN
> >>  
> >>  	   If you don't know what to do here, say "Y".
> >>  
> >> +config ERRATA_PICOHEART_AMOCASQ
> >> +	bool "Apply Picoheart AMOCASQ errata"
> >> +	depends on ERRATA_PICOHEART && RISCV_ISA_ZACAS
> >> +	default y
> >> +	help
> >> +	  Some Picoheart CPUs implement the Zacas extension but lack support
> >> +	  for AMOCASQ PMA attribute. Thus makes the CASQ instruction de facto
> >> +	  unavailable. Enable this errata workaround to disable the use of
> >> +	  CASQ in the kernel (cmpxchg128).
> >> +
> >> +	  If you don't know what to do here, say "Y".
> >> +
> >>  endmenu # "CPU errata selection"
> >> diff --git a/arch/riscv/errata/picoheart/errata.c b/arch/riscv/errata/picoheart/errata.c
> >> index c945ae694396..a658f38cf4de 100644
> >> --- a/arch/riscv/errata/picoheart/errata.c
> >> +++ b/arch/riscv/errata/picoheart/errata.c
> >> @@ -174,11 +174,34 @@ static void picoheart_errata_probe_cbo_clean(unsigned int stage,
> >>  	static_branch_enable(&has_picoheart_cbo_clean_errata);
> >>  }
> >>  
> >> +static bool picoheart_errata_probe_amocasq(unsigned int stage,
> >> +					   unsigned long archid,
> >> +					   unsigned long impid)
> >> +{
> >> +	if (!IS_ENABLED(CONFIG_ERRATA_PICOHEART_AMOCASQ))
> >> +		return false;
> >> +
> >> +	if (!IS_ENABLED(CONFIG_RISCV_ISA_ZACAS) ||
> >> +	    !riscv_isa_extension_available(NULL, ZACAS))
> >> +		return false;
> >> +
> >> +	if (archid != 0x804a555049544552 || impid != 0x100)
> >> +		return false;
> >> +
> >> +	return true;
> >> +}
> >> +
> >>  static u32 picoheart_errata_probe(unsigned int stage, unsigned long archid,
> >>  				  unsigned long impid)
> >>  {
> >> +	u32 cpu_req_errata = 0;
> >> +
> >>  	picoheart_errata_probe_cbo_clean(stage, archid, impid);
> >> -	return 0;
> >> +
> >> +	if (picoheart_errata_probe_amocasq(stage, archid, impid))
> >> +		cpu_req_errata |= BIT(ERRATA_PICOHEART_AMOCASQ);
> >> +
> >> +	return cpu_req_errata;
> >>  }
> >>  
> >>  void picoheart_errata_patch_func(struct alt_entry *begin, struct alt_entry *end,
> >> diff --git a/arch/riscv/include/asm/cmpxchg.h b/arch/riscv/include/asm/cmpxchg.h
> >> index 662e160b0522..0488b9314c13 100644
> >> --- a/arch/riscv/include/asm/cmpxchg.h
> >> +++ b/arch/riscv/include/asm/cmpxchg.h
> >> @@ -329,7 +329,23 @@
> >>  
> >>  #if defined(CONFIG_64BIT) && defined(CONFIG_RISCV_ISA_ZACAS) && defined(CONFIG_TOOLCHAIN_HAS_ZACAS)
> >>  
> >> -#define system_has_cmpxchg128()        riscv_has_extension_unlikely(RISCV_ISA_EXT_ZACAS)
> >> +#define system_has_cmpxchg128 system_has_cmpxchg128
> >> +static __always_inline bool system_has_cmpxchg128(void)
> >> +{
> >> +	/* The vendor erratum overrides the standard Zacas alternative. */
> >> +	asm goto(ALTERNATIVE_2(
> >> +			"nop",
> >> +			"j %l[l_yes]",
> >> +			STANDARD_EXT, RISCV_ISA_EXT_ZACAS, 1,
> >> +			"nop",
> >> +			PICOHEART_VENDOR_ID, ERRATA_PICOHEART_AMOCASQ,
> >> +			CONFIG_ERRATA_PICOHEART_AMOCASQ)
> >> +		: : : : l_yes);
> > 
> > This makes the generic code ugly, adds some maintain effort.
> > why not discarding "zacas" in the dts? It's much simpler
> 
> it'll prevent the usage of other more widely used CAS instructions
> in both user and kernel space. we'd like to retain the performance
> benefit of CAS over LR/SC for primitives such as cmpxchg() on our
> server as well.

If the Zacas can't be safely exposed on this platform, the ISA extension
should be disabled, rather than adding vendor specific exceptions to
generic cap detecion which adds unnecessary complexity and maintenance
burden to generic code. It also sets an undesirable precedent for
handling similar errata in the future. Imagine if various vendors don't
implement various extensions correctly, then the riscv arch code will
be full of this kind of specific exceptions here and there, which make
thes fragmentation in RISC-V land situation worse.

> 
> since kernel already provides system_has_cmpxchg128() as a
> separate capability check, disabling 128-bit CAS here lets us
> limit the workaround to cmpxhg128 only and could be a reasonable

The workaround only affects kernel's cap check, but doesn't prevent
userspace from executing the affected instruction if userspace uses
hwprobe etc. to dynamically detect the underlying hw supported
extensions. Therefore, this workaround does not fully address the
errata and could leave userspace exposed to the same issue.

Disabling the affected extension at the platform level is a more
consistent approach.

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH v6 5/5] riscv: errata: picoheart: Add workaround for AMOCASQ errata
  2026-11-08  1:33       ` Jisheng Zhang
@ 2026-11-10  9:50         ` Yicong Yang
  2026-11-11  0:27           ` Jisheng Zhang
  0 siblings, 1 reply; 12+ messages in thread
From: Yicong Yang @ 2026-11-10  9:50 UTC (permalink / raw)
  To: Jisheng Zhang
  Cc: yang.yicong, pjw, palmer, aou, linux-riscv, conor, wangruikang,
	ganboing, alex, cleger, geshijian, niehaitao, cuiyunhui, gaohan

Hi Jisheng,

On 11/8/26 9:33 AM, Jisheng Zhang wrote:
> On Sat, Nov 07, 2026 at 11:10:59PM +0800, Yicong Yang wrote:
>> On 11/7/26 9:34 PM, Jisheng Zhang wrote:
>>> On Wed, Nov 04, 2026 at 03:57:06PM +0800, Yicong Yang wrote:
>>>> Some Picoheart CPUs implement Zacas extension but lack support
>>>> for AMOCASQ PMA attribute. Thus makes the CASQ instruction de
>>>> facto unavailable. Since currently no ways to retrieve the PMA
>>>> information and the riscv kernel will declare cmpxchg128 support
>>>> if platform declare support of Zacas, the use of cmpxchg128 will
>>>> lead to PMA violation and crash the kernel. Add the errata
>>>> workaround to disable the use of cmpxchg128 on the affected CPUs.
>>>>
>>>> Tested-by: Han Gao <gaohan@iscas.ac.cn>
>>>> Signed-off-by: Yicong Yang <yang.yicong@picoheart.com>
>>>> ---
>>>>  arch/riscv/Kconfig.errata                    | 12 ++++++++++
>>>>  arch/riscv/errata/picoheart/errata.c         | 25 +++++++++++++++++++-
>>>>  arch/riscv/include/asm/cmpxchg.h             | 18 +++++++++++++-
>>>>  arch/riscv/include/asm/errata_list_vendors.h |  3 ++-
>>>>  4 files changed, 55 insertions(+), 3 deletions(-)
>>>>
>>>> diff --git a/arch/riscv/Kconfig.errata b/arch/riscv/Kconfig.errata
>>>> index c75dec4b0ba7..4e6516ba3a42 100644
>>>> --- a/arch/riscv/Kconfig.errata
>>>> +++ b/arch/riscv/Kconfig.errata
>>>> @@ -202,4 +202,16 @@ config ERRATA_PICOHEART_CBO_CLEAN
>>>>  
>>>>  	   If you don't know what to do here, say "Y".
>>>>  
>>>> +config ERRATA_PICOHEART_AMOCASQ
>>>> +	bool "Apply Picoheart AMOCASQ errata"
>>>> +	depends on ERRATA_PICOHEART && RISCV_ISA_ZACAS
>>>> +	default y
>>>> +	help
>>>> +	  Some Picoheart CPUs implement the Zacas extension but lack support
>>>> +	  for AMOCASQ PMA attribute. Thus makes the CASQ instruction de facto
>>>> +	  unavailable. Enable this errata workaround to disable the use of
>>>> +	  CASQ in the kernel (cmpxchg128).
>>>> +
>>>> +	  If you don't know what to do here, say "Y".
>>>> +
>>>>  endmenu # "CPU errata selection"
>>>> diff --git a/arch/riscv/errata/picoheart/errata.c b/arch/riscv/errata/picoheart/errata.c
>>>> index c945ae694396..a658f38cf4de 100644
>>>> --- a/arch/riscv/errata/picoheart/errata.c
>>>> +++ b/arch/riscv/errata/picoheart/errata.c
>>>> @@ -174,11 +174,34 @@ static void picoheart_errata_probe_cbo_clean(unsigned int stage,
>>>>  	static_branch_enable(&has_picoheart_cbo_clean_errata);
>>>>  }
>>>>  
>>>> +static bool picoheart_errata_probe_amocasq(unsigned int stage,
>>>> +					   unsigned long archid,
>>>> +					   unsigned long impid)
>>>> +{
>>>> +	if (!IS_ENABLED(CONFIG_ERRATA_PICOHEART_AMOCASQ))
>>>> +		return false;
>>>> +
>>>> +	if (!IS_ENABLED(CONFIG_RISCV_ISA_ZACAS) ||
>>>> +	    !riscv_isa_extension_available(NULL, ZACAS))
>>>> +		return false;
>>>> +
>>>> +	if (archid != 0x804a555049544552 || impid != 0x100)
>>>> +		return false;
>>>> +
>>>> +	return true;
>>>> +}
>>>> +
>>>>  static u32 picoheart_errata_probe(unsigned int stage, unsigned long archid,
>>>>  				  unsigned long impid)
>>>>  {
>>>> +	u32 cpu_req_errata = 0;
>>>> +
>>>>  	picoheart_errata_probe_cbo_clean(stage, archid, impid);
>>>> -	return 0;
>>>> +
>>>> +	if (picoheart_errata_probe_amocasq(stage, archid, impid))
>>>> +		cpu_req_errata |= BIT(ERRATA_PICOHEART_AMOCASQ);
>>>> +
>>>> +	return cpu_req_errata;
>>>>  }
>>>>  
>>>>  void picoheart_errata_patch_func(struct alt_entry *begin, struct alt_entry *end,
>>>> diff --git a/arch/riscv/include/asm/cmpxchg.h b/arch/riscv/include/asm/cmpxchg.h
>>>> index 662e160b0522..0488b9314c13 100644
>>>> --- a/arch/riscv/include/asm/cmpxchg.h
>>>> +++ b/arch/riscv/include/asm/cmpxchg.h
>>>> @@ -329,7 +329,23 @@
>>>>  
>>>>  #if defined(CONFIG_64BIT) && defined(CONFIG_RISCV_ISA_ZACAS) && defined(CONFIG_TOOLCHAIN_HAS_ZACAS)
>>>>  
>>>> -#define system_has_cmpxchg128()        riscv_has_extension_unlikely(RISCV_ISA_EXT_ZACAS)
>>>> +#define system_has_cmpxchg128 system_has_cmpxchg128
>>>> +static __always_inline bool system_has_cmpxchg128(void)
>>>> +{
>>>> +	/* The vendor erratum overrides the standard Zacas alternative. */
>>>> +	asm goto(ALTERNATIVE_2(
>>>> +			"nop",
>>>> +			"j %l[l_yes]",
>>>> +			STANDARD_EXT, RISCV_ISA_EXT_ZACAS, 1,
>>>> +			"nop",
>>>> +			PICOHEART_VENDOR_ID, ERRATA_PICOHEART_AMOCASQ,
>>>> +			CONFIG_ERRATA_PICOHEART_AMOCASQ)
>>>> +		: : : : l_yes);
>>>
>>> This makes the generic code ugly, adds some maintain effort.
>>> why not discarding "zacas" in the dts? It's much simpler
>>
>> it'll prevent the usage of other more widely used CAS instructions
>> in both user and kernel space. we'd like to retain the performance
>> benefit of CAS over LR/SC for primitives such as cmpxchg() on our
>> server as well.
> 
> If the Zacas can't be safely exposed on this platform, the ISA extension
> should be disabled, rather than adding vendor specific exceptions to
> generic cap detecion which adds unnecessary complexity and maintenance
> burden to generic code. It also sets an undesirable precedent for
> handling similar errata in the future. Imagine if various vendors don't
> implement various extensions correctly, then the riscv arch code will
> be full of this kind of specific exceptions here and there, which make
> thes fragmentation in RISC-V land situation worse.
> 

I totally understand the concerns. The silicon errata is unexpected but
the riscv's errata framework and alternatives provides the means to save
the case. I'd like to keep the erratum handling as small as possible and
open to better solutions..

Disabling the entire extension because of the AMOCAS.Q erratum would also
lose the benefits of the working AMOCAS.W/D instructions. Preserving their
performance benefit in the kernel is my main motivation. Our measurements  
show substantial gains for some cmpxchg() workloads, particularly under
contention on our server platform. The following results compare kernel
cmpxchg() using CAS and LR/SC:

CAS will reduce the latency by about 20~21%:
Width       LR/SC       CAS    Improvement
32-bit     1.000×    1.253×         +25.3%
64-bit     1.000×    1.270×         +27.0%

and increase the throughput by at most 6x at high contention.
Width Contenders       LR/SC       CAS    Improvement
32-bit         2      1.000×    0.982×          -1.8%
32-bit         4      1.000×    2.115×        +111.5%
32-bit         8      1.000×    4.102×        +310.2%
32-bit        16      1.000×    6.981×        +598.1%
32-bit        30      1.000×    4.808×        +380.8%
64-bit         2      1.000×    1.088×          +8.8%
64-bit         4      1.000×    1.554×         +55.4%
64-bit         8      1.000×    2.907×        +190.7%
64-bit        16      1.000×    4.970×        +397.0%
64-bit        30      1.000×    5.262×        +426.2%

>>
>> since kernel already provides system_has_cmpxchg128() as a
>> separate capability check, disabling 128-bit CAS here lets us
>> limit the workaround to cmpxhg128 only and could be a reasonable
> 
> The workaround only affects kernel's cap check, but doesn't prevent
> userspace from executing the affected instruction if userspace uses
> hwprobe etc. to dynamically detect the underlying hw supported
> extensions. Therefore, this workaround does not fully address the
> errata and could leave userspace exposed to the same issue.

indeed. we initially decided to retain the advertisement of Zacas to
userspace as AMOCAS.Q is not frequently used and the access fault by
AMOCAS.Q is less fatal compared to the kernel. the access fault in
kernel will crash the system.

> 
> Disabling the affected extension at the platform level is a more
> consistent approach.

what about retaining AMOCAS.W/D for kernel use, while keeping
cmpxchg128() disabled and withholding Zacas from userspace capability
advertisement? That would preserve the measured kernel performance
benefit without advertising full Zacas support to applications.

thanks.

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH v6 5/5] riscv: errata: picoheart: Add workaround for AMOCASQ errata
  2026-11-10  9:50         ` Yicong Yang
@ 2026-11-11  0:27           ` Jisheng Zhang
  2026-11-11  7:42             ` Yicong Yang
  0 siblings, 1 reply; 12+ messages in thread
From: Jisheng Zhang @ 2026-11-11  0:27 UTC (permalink / raw)
  To: Yicong Yang
  Cc: pjw, palmer, aou, linux-riscv, conor, wangruikang, ganboing, alex,
	cleger, geshijian, niehaitao, cuiyunhui, gaohan

On Tue, Nov 10, 2026 at 05:50:46PM +0800, Yicong Yang wrote:
> Hi Jisheng,
> 
> On 11/8/26 9:33 AM, Jisheng Zhang wrote:
> > On Sat, Nov 07, 2026 at 11:10:59PM +0800, Yicong Yang wrote:
> >> On 11/7/26 9:34 PM, Jisheng Zhang wrote:
> >>> On Wed, Nov 04, 2026 at 03:57:06PM +0800, Yicong Yang wrote:
> >>>> Some Picoheart CPUs implement Zacas extension but lack support
> >>>> for AMOCASQ PMA attribute. Thus makes the CASQ instruction de
> >>>> facto unavailable. Since currently no ways to retrieve the PMA
> >>>> information and the riscv kernel will declare cmpxchg128 support
> >>>> if platform declare support of Zacas, the use of cmpxchg128 will
> >>>> lead to PMA violation and crash the kernel. Add the errata
> >>>> workaround to disable the use of cmpxchg128 on the affected CPUs.
> >>>>
> >>>> Tested-by: Han Gao <gaohan@iscas.ac.cn>
> >>>> Signed-off-by: Yicong Yang <yang.yicong@picoheart.com>
> >>>> ---
> >>>>  arch/riscv/Kconfig.errata                    | 12 ++++++++++
> >>>>  arch/riscv/errata/picoheart/errata.c         | 25 +++++++++++++++++++-
> >>>>  arch/riscv/include/asm/cmpxchg.h             | 18 +++++++++++++-
> >>>>  arch/riscv/include/asm/errata_list_vendors.h |  3 ++-
> >>>>  4 files changed, 55 insertions(+), 3 deletions(-)
> >>>>
> >>>> diff --git a/arch/riscv/Kconfig.errata b/arch/riscv/Kconfig.errata
> >>>> index c75dec4b0ba7..4e6516ba3a42 100644
> >>>> --- a/arch/riscv/Kconfig.errata
> >>>> +++ b/arch/riscv/Kconfig.errata
> >>>> @@ -202,4 +202,16 @@ config ERRATA_PICOHEART_CBO_CLEAN
> >>>>  
> >>>>  	   If you don't know what to do here, say "Y".
> >>>>  
> >>>> +config ERRATA_PICOHEART_AMOCASQ
> >>>> +	bool "Apply Picoheart AMOCASQ errata"
> >>>> +	depends on ERRATA_PICOHEART && RISCV_ISA_ZACAS
> >>>> +	default y
> >>>> +	help
> >>>> +	  Some Picoheart CPUs implement the Zacas extension but lack support
> >>>> +	  for AMOCASQ PMA attribute. Thus makes the CASQ instruction de facto
> >>>> +	  unavailable. Enable this errata workaround to disable the use of
> >>>> +	  CASQ in the kernel (cmpxchg128).
> >>>> +
> >>>> +	  If you don't know what to do here, say "Y".
> >>>> +
> >>>>  endmenu # "CPU errata selection"
> >>>> diff --git a/arch/riscv/errata/picoheart/errata.c b/arch/riscv/errata/picoheart/errata.c
> >>>> index c945ae694396..a658f38cf4de 100644
> >>>> --- a/arch/riscv/errata/picoheart/errata.c
> >>>> +++ b/arch/riscv/errata/picoheart/errata.c
> >>>> @@ -174,11 +174,34 @@ static void picoheart_errata_probe_cbo_clean(unsigned int stage,
> >>>>  	static_branch_enable(&has_picoheart_cbo_clean_errata);
> >>>>  }
> >>>>  
> >>>> +static bool picoheart_errata_probe_amocasq(unsigned int stage,
> >>>> +					   unsigned long archid,
> >>>> +					   unsigned long impid)
> >>>> +{
> >>>> +	if (!IS_ENABLED(CONFIG_ERRATA_PICOHEART_AMOCASQ))
> >>>> +		return false;
> >>>> +
> >>>> +	if (!IS_ENABLED(CONFIG_RISCV_ISA_ZACAS) ||
> >>>> +	    !riscv_isa_extension_available(NULL, ZACAS))
> >>>> +		return false;
> >>>> +
> >>>> +	if (archid != 0x804a555049544552 || impid != 0x100)
> >>>> +		return false;
> >>>> +
> >>>> +	return true;
> >>>> +}
> >>>> +
> >>>>  static u32 picoheart_errata_probe(unsigned int stage, unsigned long archid,
> >>>>  				  unsigned long impid)
> >>>>  {
> >>>> +	u32 cpu_req_errata = 0;
> >>>> +
> >>>>  	picoheart_errata_probe_cbo_clean(stage, archid, impid);
> >>>> -	return 0;
> >>>> +
> >>>> +	if (picoheart_errata_probe_amocasq(stage, archid, impid))
> >>>> +		cpu_req_errata |= BIT(ERRATA_PICOHEART_AMOCASQ);
> >>>> +
> >>>> +	return cpu_req_errata;
> >>>>  }
> >>>>  
> >>>>  void picoheart_errata_patch_func(struct alt_entry *begin, struct alt_entry *end,
> >>>> diff --git a/arch/riscv/include/asm/cmpxchg.h b/arch/riscv/include/asm/cmpxchg.h
> >>>> index 662e160b0522..0488b9314c13 100644
> >>>> --- a/arch/riscv/include/asm/cmpxchg.h
> >>>> +++ b/arch/riscv/include/asm/cmpxchg.h
> >>>> @@ -329,7 +329,23 @@
> >>>>  
> >>>>  #if defined(CONFIG_64BIT) && defined(CONFIG_RISCV_ISA_ZACAS) && defined(CONFIG_TOOLCHAIN_HAS_ZACAS)
> >>>>  
> >>>> -#define system_has_cmpxchg128()        riscv_has_extension_unlikely(RISCV_ISA_EXT_ZACAS)
> >>>> +#define system_has_cmpxchg128 system_has_cmpxchg128
> >>>> +static __always_inline bool system_has_cmpxchg128(void)
> >>>> +{
> >>>> +	/* The vendor erratum overrides the standard Zacas alternative. */
> >>>> +	asm goto(ALTERNATIVE_2(
> >>>> +			"nop",
> >>>> +			"j %l[l_yes]",
> >>>> +			STANDARD_EXT, RISCV_ISA_EXT_ZACAS, 1,
> >>>> +			"nop",
> >>>> +			PICOHEART_VENDOR_ID, ERRATA_PICOHEART_AMOCASQ,
> >>>> +			CONFIG_ERRATA_PICOHEART_AMOCASQ)
> >>>> +		: : : : l_yes);
> >>>
> >>> This makes the generic code ugly, adds some maintain effort.
> >>> why not discarding "zacas" in the dts? It's much simpler
> >>
> >> it'll prevent the usage of other more widely used CAS instructions
> >> in both user and kernel space. we'd like to retain the performance
> >> benefit of CAS over LR/SC for primitives such as cmpxchg() on our
> >> server as well.
> > 
> > If the Zacas can't be safely exposed on this platform, the ISA extension
> > should be disabled, rather than adding vendor specific exceptions to
> > generic cap detecion which adds unnecessary complexity and maintenance
> > burden to generic code. It also sets an undesirable precedent for
> > handling similar errata in the future. Imagine if various vendors don't
> > implement various extensions correctly, then the riscv arch code will
> > be full of this kind of specific exceptions here and there, which make
> > thes fragmentation in RISC-V land situation worse.
> > 
> 
> I totally understand the concerns. The silicon errata is unexpected but
> the riscv's errata framework and alternatives provides the means to save
> the case. I'd like to keep the erratum handling as small as possible and
> open to better solutions..
> 
> Disabling the entire extension because of the AMOCAS.Q erratum would also

I re-read the patch's commit msg, "AMOCASQ PMA attribute", it seems the PMA
attribute doesn't support 128bit, IMO, this seems not an errata but a design
choice -- decide to support subset of Zacas during the design stage. This is
just my guess though.

This reminds me a recent patch in the mailist which is to workaround a design
choice: only implement subset of 'A". IMHO this kind of workaround
should be kept out of tree. arch/riscv code fragmentation becomes non-trivial
due to various extension combinations becomes, if vendor choose to implement
subset of each extension, then it significantly increases combinations
we need to support, to test, to maintain.

> lose the benefits of the working AMOCAS.W/D instructions. Preserving their
> performance benefit in the kernel is my main motivation. Our measurements  
> show substantial gains for some cmpxchg() workloads, particularly under
> contention on our server platform. The following results compare kernel
> cmpxchg() using CAS and LR/SC:
> 
> CAS will reduce the latency by about 20~21%:
> Width       LR/SC       CAS    Improvement
> 32-bit     1.000×    1.253×         +25.3%
> 64-bit     1.000×    1.270×         +27.0%
> 
> and increase the throughput by at most 6x at high contention.
> Width Contenders       LR/SC       CAS    Improvement
> 32-bit         2      1.000×    0.982×          -1.8%
> 32-bit         4      1.000×    2.115×        +111.5%
> 32-bit         8      1.000×    4.102×        +310.2%
> 32-bit        16      1.000×    6.981×        +598.1%
> 32-bit        30      1.000×    4.808×        +380.8%
> 64-bit         2      1.000×    1.088×          +8.8%
> 64-bit         4      1.000×    1.554×         +55.4%
> 64-bit         8      1.000×    2.907×        +190.7%
> 64-bit        16      1.000×    4.970×        +397.0%
> 64-bit        30      1.000×    5.262×        +426.2%
> 
> >>
> >> since kernel already provides system_has_cmpxchg128() as a
> >> separate capability check, disabling 128-bit CAS here lets us
> >> limit the workaround to cmpxhg128 only and could be a reasonable
> > 
> > The workaround only affects kernel's cap check, but doesn't prevent
> > userspace from executing the affected instruction if userspace uses
> > hwprobe etc. to dynamically detect the underlying hw supported
> > extensions. Therefore, this workaround does not fully address the
> > errata and could leave userspace exposed to the same issue.
> 
> indeed. we initially decided to retain the advertisement of Zacas to
> userspace as AMOCAS.Q is not frequently used and the access fault by
> AMOCAS.Q is less fatal compared to the kernel. the access fault in
> kernel will crash the system.
> 
> > 
> > Disabling the affected extension at the platform level is a more
> > consistent approach.
> 
> what about retaining AMOCAS.W/D for kernel use, while keeping
> cmpxchg128() disabled and withholding Zacas from userspace capability
> advertisement? That would preserve the measured kernel performance
> benefit without advertising full Zacas support to applications.
> 

AIUI, this can't be acchived without introducing subset concept of Zacas
to the arch/riscv code

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH v6 5/5] riscv: errata: picoheart: Add workaround for AMOCASQ errata
  2026-11-11  0:27           ` Jisheng Zhang
@ 2026-11-11  7:42             ` Yicong Yang
  0 siblings, 0 replies; 12+ messages in thread
From: Yicong Yang @ 2026-11-11  7:42 UTC (permalink / raw)
  To: Jisheng Zhang
  Cc: yang.yicong, pjw, palmer, aou, linux-riscv, conor, wangruikang,
	ganboing, alex, cleger, geshijian, niehaitao, cuiyunhui, gaohan

On 11/11/26 8:27 AM, Jisheng Zhang wrote:
> On Tue, Nov 10, 2026 at 05:50:46PM +0800, Yicong Yang wrote:
>> Hi Jisheng,
>>
>> On 11/8/26 9:33 AM, Jisheng Zhang wrote:
>>> On Sat, Nov 07, 2026 at 11:10:59PM +0800, Yicong Yang wrote:
>>>> On 11/7/26 9:34 PM, Jisheng Zhang wrote:
>>>>> On Wed, Nov 04, 2026 at 03:57:06PM +0800, Yicong Yang wrote:
>>>>>> Some Picoheart CPUs implement Zacas extension but lack support
>>>>>> for AMOCASQ PMA attribute. Thus makes the CASQ instruction de
>>>>>> facto unavailable. Since currently no ways to retrieve the PMA
>>>>>> information and the riscv kernel will declare cmpxchg128 support
>>>>>> if platform declare support of Zacas, the use of cmpxchg128 will
>>>>>> lead to PMA violation and crash the kernel. Add the errata
>>>>>> workaround to disable the use of cmpxchg128 on the affected CPUs.
>>>>>>
>>>>>> Tested-by: Han Gao <gaohan@iscas.ac.cn>
>>>>>> Signed-off-by: Yicong Yang <yang.yicong@picoheart.com>
>>>>>> ---
>>>>>>  arch/riscv/Kconfig.errata                    | 12 ++++++++++
>>>>>>  arch/riscv/errata/picoheart/errata.c         | 25 +++++++++++++++++++-
>>>>>>  arch/riscv/include/asm/cmpxchg.h             | 18 +++++++++++++-
>>>>>>  arch/riscv/include/asm/errata_list_vendors.h |  3 ++-
>>>>>>  4 files changed, 55 insertions(+), 3 deletions(-)
>>>>>>
>>>>>> diff --git a/arch/riscv/Kconfig.errata b/arch/riscv/Kconfig.errata
>>>>>> index c75dec4b0ba7..4e6516ba3a42 100644
>>>>>> --- a/arch/riscv/Kconfig.errata
>>>>>> +++ b/arch/riscv/Kconfig.errata
>>>>>> @@ -202,4 +202,16 @@ config ERRATA_PICOHEART_CBO_CLEAN
>>>>>>  
>>>>>>  	   If you don't know what to do here, say "Y".
>>>>>>  
>>>>>> +config ERRATA_PICOHEART_AMOCASQ
>>>>>> +	bool "Apply Picoheart AMOCASQ errata"
>>>>>> +	depends on ERRATA_PICOHEART && RISCV_ISA_ZACAS
>>>>>> +	default y
>>>>>> +	help
>>>>>> +	  Some Picoheart CPUs implement the Zacas extension but lack support
>>>>>> +	  for AMOCASQ PMA attribute. Thus makes the CASQ instruction de facto
>>>>>> +	  unavailable. Enable this errata workaround to disable the use of
>>>>>> +	  CASQ in the kernel (cmpxchg128).
>>>>>> +
>>>>>> +	  If you don't know what to do here, say "Y".
>>>>>> +
>>>>>>  endmenu # "CPU errata selection"
>>>>>> diff --git a/arch/riscv/errata/picoheart/errata.c b/arch/riscv/errata/picoheart/errata.c
>>>>>> index c945ae694396..a658f38cf4de 100644
>>>>>> --- a/arch/riscv/errata/picoheart/errata.c
>>>>>> +++ b/arch/riscv/errata/picoheart/errata.c
>>>>>> @@ -174,11 +174,34 @@ static void picoheart_errata_probe_cbo_clean(unsigned int stage,
>>>>>>  	static_branch_enable(&has_picoheart_cbo_clean_errata);
>>>>>>  }
>>>>>>  
>>>>>> +static bool picoheart_errata_probe_amocasq(unsigned int stage,
>>>>>> +					   unsigned long archid,
>>>>>> +					   unsigned long impid)
>>>>>> +{
>>>>>> +	if (!IS_ENABLED(CONFIG_ERRATA_PICOHEART_AMOCASQ))
>>>>>> +		return false;
>>>>>> +
>>>>>> +	if (!IS_ENABLED(CONFIG_RISCV_ISA_ZACAS) ||
>>>>>> +	    !riscv_isa_extension_available(NULL, ZACAS))
>>>>>> +		return false;
>>>>>> +
>>>>>> +	if (archid != 0x804a555049544552 || impid != 0x100)
>>>>>> +		return false;
>>>>>> +
>>>>>> +	return true;
>>>>>> +}
>>>>>> +
>>>>>>  static u32 picoheart_errata_probe(unsigned int stage, unsigned long archid,
>>>>>>  				  unsigned long impid)
>>>>>>  {
>>>>>> +	u32 cpu_req_errata = 0;
>>>>>> +
>>>>>>  	picoheart_errata_probe_cbo_clean(stage, archid, impid);
>>>>>> -	return 0;
>>>>>> +
>>>>>> +	if (picoheart_errata_probe_amocasq(stage, archid, impid))
>>>>>> +		cpu_req_errata |= BIT(ERRATA_PICOHEART_AMOCASQ);
>>>>>> +
>>>>>> +	return cpu_req_errata;
>>>>>>  }
>>>>>>  
>>>>>>  void picoheart_errata_patch_func(struct alt_entry *begin, struct alt_entry *end,
>>>>>> diff --git a/arch/riscv/include/asm/cmpxchg.h b/arch/riscv/include/asm/cmpxchg.h
>>>>>> index 662e160b0522..0488b9314c13 100644
>>>>>> --- a/arch/riscv/include/asm/cmpxchg.h
>>>>>> +++ b/arch/riscv/include/asm/cmpxchg.h
>>>>>> @@ -329,7 +329,23 @@
>>>>>>  
>>>>>>  #if defined(CONFIG_64BIT) && defined(CONFIG_RISCV_ISA_ZACAS) && defined(CONFIG_TOOLCHAIN_HAS_ZACAS)
>>>>>>  
>>>>>> -#define system_has_cmpxchg128()        riscv_has_extension_unlikely(RISCV_ISA_EXT_ZACAS)
>>>>>> +#define system_has_cmpxchg128 system_has_cmpxchg128
>>>>>> +static __always_inline bool system_has_cmpxchg128(void)
>>>>>> +{
>>>>>> +	/* The vendor erratum overrides the standard Zacas alternative. */
>>>>>> +	asm goto(ALTERNATIVE_2(
>>>>>> +			"nop",
>>>>>> +			"j %l[l_yes]",
>>>>>> +			STANDARD_EXT, RISCV_ISA_EXT_ZACAS, 1,
>>>>>> +			"nop",
>>>>>> +			PICOHEART_VENDOR_ID, ERRATA_PICOHEART_AMOCASQ,
>>>>>> +			CONFIG_ERRATA_PICOHEART_AMOCASQ)
>>>>>> +		: : : : l_yes);
>>>>>
>>>>> This makes the generic code ugly, adds some maintain effort.
>>>>> why not discarding "zacas" in the dts? It's much simpler
>>>>
>>>> it'll prevent the usage of other more widely used CAS instructions
>>>> in both user and kernel space. we'd like to retain the performance
>>>> benefit of CAS over LR/SC for primitives such as cmpxchg() on our
>>>> server as well.
>>>
>>> If the Zacas can't be safely exposed on this platform, the ISA extension
>>> should be disabled, rather than adding vendor specific exceptions to
>>> generic cap detecion which adds unnecessary complexity and maintenance
>>> burden to generic code. It also sets an undesirable precedent for
>>> handling similar errata in the future. Imagine if various vendors don't
>>> implement various extensions correctly, then the riscv arch code will
>>> be full of this kind of specific exceptions here and there, which make
>>> thes fragmentation in RISC-V land situation worse.
>>>
>>
>> I totally understand the concerns. The silicon errata is unexpected but
>> the riscv's errata framework and alternatives provides the means to save
>> the case. I'd like to keep the erratum handling as small as possible and
>> open to better solutions..
>>
>> Disabling the entire extension because of the AMOCAS.Q erratum would also
> 
> I re-read the patch's commit msg, "AMOCASQ PMA attribute", it seems the PMA
> attribute doesn't support 128bit, IMO, this seems not an errata but a design
> choice -- decide to support subset of Zacas during the design stage. This is
> just my guess though.

you're correct. per spec all the AMOCAS.W/D/Q instructions
are included by Zacas but the PMA attribute for CAS is splitted to
AMOCASW/D/Q separately. The AMOCASQ PMA attribute is not supported
in our case.

I classified it as an errata because it'll be handled through the errata
framework. Currently riscv lacks the standard way to report and retrieve
the PMA attributes. Some non-standard vendor extension are classified as
errata as well, e.g. THead MAE.

> 
> This reminds me a recent patch in the mailist which is to workaround a design
> choice: only implement subset of 'A". IMHO this kind of workaround
> should be kept out of tree. arch/riscv code fragmentation becomes non-trivial
> due to various extension combinations becomes, if vendor choose to implement
> subset of each extension, then it significantly increases combinations
> we need to support, to test, to maintain.

I think it's different. The lack of AMOCASQ PMA is compliant to the spec
and kernel has already provided a system_has_cmpxchg128() so it could be
optional, in contrast riscv kernel regard A as a required extension.
The current change is rather trivial. It's using standard alternatives and
is consistent to the existed errata solutions [1]. I can move the override
there and guard it with CONFIG_ERRATA_PICOHEART_AMOCASQ if you think it'll
help with the fragmentation.

[1] https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/arch/riscv/include/asm/errata_list.h

> 
>> lose the benefits of the working AMOCAS.W/D instructions. Preserving their
>> performance benefit in the kernel is my main motivation. Our measurements  
>> show substantial gains for some cmpxchg() workloads, particularly under
>> contention on our server platform. The following results compare kernel
>> cmpxchg() using CAS and LR/SC:
>>
>> CAS will reduce the latency by about 20~21%:
>> Width       LR/SC       CAS    Improvement
>> 32-bit     1.000×    1.253×         +25.3%
>> 64-bit     1.000×    1.270×         +27.0%
>>
>> and increase the throughput by at most 6x at high contention.
>> Width Contenders       LR/SC       CAS    Improvement
>> 32-bit         2      1.000×    0.982×          -1.8%
>> 32-bit         4      1.000×    2.115×        +111.5%
>> 32-bit         8      1.000×    4.102×        +310.2%
>> 32-bit        16      1.000×    6.981×        +598.1%
>> 32-bit        30      1.000×    4.808×        +380.8%
>> 64-bit         2      1.000×    1.088×          +8.8%
>> 64-bit         4      1.000×    1.554×         +55.4%
>> 64-bit         8      1.000×    2.907×        +190.7%
>> 64-bit        16      1.000×    4.970×        +397.0%
>> 64-bit        30      1.000×    5.262×        +426.2%
>>
>>>>
>>>> since kernel already provides system_has_cmpxchg128() as a
>>>> separate capability check, disabling 128-bit CAS here lets us
>>>> limit the workaround to cmpxhg128 only and could be a reasonable
>>>
>>> The workaround only affects kernel's cap check, but doesn't prevent
>>> userspace from executing the affected instruction if userspace uses
>>> hwprobe etc. to dynamically detect the underlying hw supported
>>> extensions. Therefore, this workaround does not fully address the
>>> errata and could leave userspace exposed to the same issue.
>>
>> indeed. we initially decided to retain the advertisement of Zacas to
>> userspace as AMOCAS.Q is not frequently used and the access fault by
>> AMOCAS.Q is less fatal compared to the kernel. the access fault in
>> kernel will crash the system.
>>
>>>
>>> Disabling the affected extension at the platform level is a more
>>> consistent approach.
>>
>> what about retaining AMOCAS.W/D for kernel use, while keeping
>> cmpxchg128() disabled and withholding Zacas from userspace capability
>> advertisement? That would preserve the measured kernel performance
>> benefit without advertising full Zacas support to applications.
>>
> 
> AIUI, this can't be acchived without introducing subset concept of Zacas
> to the arch/riscv code

I didn't mean to split the Zacas extension but to stop advertising Zacas
to userspace while retaining in the kernel and disable system_has_cmpxchg128()
on affected platform. It won't block userspace to use AMOCAS.W/D if they
know it's supported.

this will need some work to achieve in this way. unlike arm64 that supports
expose a subset sanitized features to the userspace, riscv64 currently
use the same isa bitmap for both userspace and kernel. so personally I'd
perfer to still advertise the Zacas to userspace, but could warn the CASQ
is not supported in the kernel log.

thanks.

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 12+ messages in thread

end of thread, other threads:[~2026-11-11  7:42 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-11-04  7:57 [PATCH v6 0/5] Add workarounds for Picoheart errata Yicong Yang
2026-11-04  7:57 ` [PATCH v6 1/5] riscv: Make get_insn public for instruction fault handling Yicong Yang
2026-11-04  7:57 ` [PATCH v6 2/5] riscv: insn: Support decoding of CBO instructions Yicong Yang
2026-11-04  7:57 ` [PATCH v6 3/5] riscv: errata: Add init framework for picoheart errata Yicong Yang
2026-11-04  7:57 ` [PATCH v6 4/5] riscv: errata: picoheart: Add workaround for cbo.clean errata Yicong Yang
2026-11-04  7:57 ` [PATCH v6 5/5] riscv: errata: picoheart: Add workaround for AMOCASQ errata Yicong Yang
2026-11-07 13:34   ` Jisheng Zhang
2026-11-07 15:10     ` Yicong Yang
2026-11-08  1:33       ` Jisheng Zhang
2026-11-10  9:50         ` Yicong Yang
2026-11-11  0:27           ` Jisheng Zhang
2026-11-11  7:42             ` Yicong Yang

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox