* [PATCH 0/3] riscv: Fix xtheadvector vector status handling
@ 2026-10-06 0:35 Gleb Pesin via B4 Relay
2026-10-06 0:35 ` [PATCH 1/3] riscv: vector: Check the xtheadvector status field in riscv_v_is_on() Gleb Pesin via B4 Relay
` (2 more replies)
0 siblings, 3 replies; 4+ messages in thread
From: Gleb Pesin via B4 Relay @ 2026-10-06 0:35 UTC (permalink / raw)
To: Paul Walmsley, Palmer Dabbelt, Albert Ou, Alexandre Ghiti
Cc: linux-riscv, linux-kernel, Andy Chiu, Charlie Jenkins, stable,
Gleb Pesin
Since commit d863910eabaf ("riscv: vector: Support xtheadvector
save/restore"), cores with xtheadvector keep the vector unit state in
sstatus bits 24:23 (SR_VS_THEAD) instead of the standard VS field.
riscv_v_enable() and riscv_v_disable() handle that, but two other users
of the vector status still look only at the standard field:
1. riscv_v_is_on() (patch 1), which __switch_to_vector() uses to
recognise a task switched out inside a preemptible kernel-mode
vector section.
2. The trap entry mask, which is meant to disable FP and vector in the
kernel (patch 3; patch 2 makes the vendor extension headers usable
from entry.S).
Mainline has no in-tree kernel-mode vector user that runs on
xtheadvector, so patch 1 only matters for such users (out-of-tree code
today), while patch 3 changes behaviour on every trap from a context
with the vector unit enabled.
Testing was done on a Sipeed NanoKVM (SG2002, T-Head C906, VLEN 128).
Mainline does not boot on that board without platform patches, so I
used a downstream 7.2.9 kernel (PREEMPT_LAZY, RISCV_ISA_V_PREEMPTIVE=y,
RISCV_ISA_XTHEADVECTOR=y, no other in-kernel vector users) built twice
from the same tree and config, with and without these changes; the
touched code is the same as in v7.3-rc6. A small test module and a user
program that executes xtheadvector instructions were used:
without with
T1 riscv_v_is_on() inside kernel_vector_begin() false true
(sstatus VS_THEAD = DIRTY in both cases)
T4 timer interrupts taken from a user task that 12420 of 0 of
keeps the vector unit busy, where SR_VS_THEAD 12433 12370
is still set in the interrupt handler
Syscall entry was not affected in either kernel, because the syscall
path already turns the vector unit off when it discards the user
vector state.
A test that sleeps inside a kernel-mode vector section hung the kernel
without patch 1; with it the kernel survives, but the vector registers
are not preserved across the sleep. I do not think sleeping there is
supported, so I only mention this as an observation.
The series builds without new warnings (riscv defconfig plus
RISCV_ISA_XTHEADVECTOR and RISCV_ISA_V_PREEMPTIVE, each patch
separately, W=1 for the touched files) and passes checkpatch --strict.
The patches are against v7.3-rc6. None of them is in riscv for-next. Andy
Chiu's "riscv: optimize mode switch latency for Vector" v6 touches the
same lines:
- its patch 1/8 removes the only riscv_v_is_on() caller in
__switch_to_vector(); if that series lands first, patch 1 here can be
dropped from mainline, but stable kernels still need it;
- its patch 8/8 rewrites the entry mask under an alternative keyed on
the standard vector extension and still leaves SR_VS_THEAD set, so
patches 2 and 3 are needed either way. I am happy to rebase them on
top of that series if preferred.
The issue was found and the fixes were first written with an AI coding
assistant (OpenAI Codex) while working on a downstream SG2002 kernel.
The mainline port, the reproducer and these changelogs were prepared
with another assistant (Anthropic Claude); the reproducer ran on my
SG2002 board. I have reviewed the patches and take responsibility for
them, per Documentation/process/generated-content.rst.
---
Gleb Pesin (3):
riscv: vector: Check the xtheadvector status field in riscv_v_is_on()
riscv: Make the vendor extension headers usable from assembly
riscv: Disable the xtheadvector unit on kernel entry
arch/riscv/include/asm/vector.h | 4 +++-
arch/riscv/include/asm/vendor_extensions.h | 28 ++++++++++++++----------
arch/riscv/include/asm/vendor_extensions/thead.h | 8 +++++--
arch/riscv/kernel/entry.S | 11 ++++++++--
4 files changed, 34 insertions(+), 17 deletions(-)
---
base-commit: 67f0943b394d920b6c142aad8c6af94340342ae7
change-id: 20261006-riscv-xtheadvector-vs-8a31214a75e9
Best regards,
--
Gleb Pesin <dormancygrace@gmail.com>
^ permalink raw reply [flat|nested] 4+ messages in thread
* [PATCH 1/3] riscv: vector: Check the xtheadvector status field in riscv_v_is_on()
2026-10-06 0:35 [PATCH 0/3] riscv: Fix xtheadvector vector status handling Gleb Pesin via B4 Relay
@ 2026-10-06 0:35 ` Gleb Pesin via B4 Relay
2026-10-06 0:35 ` [PATCH 2/3] riscv: Make the vendor extension headers usable from assembly Gleb Pesin via B4 Relay
2026-10-06 0:35 ` [PATCH 3/3] riscv: Disable the xtheadvector unit on kernel entry Gleb Pesin via B4 Relay
2 siblings, 0 replies; 4+ messages in thread
From: Gleb Pesin via B4 Relay @ 2026-10-06 0:35 UTC (permalink / raw)
To: Paul Walmsley, Palmer Dabbelt, Albert Ou, Alexandre Ghiti
Cc: linux-riscv, linux-kernel, Andy Chiu, Charlie Jenkins, stable,
Gleb Pesin
From: Gleb Pesin <dormancygrace@gmail.com>
riscv_v_is_on() tests only the standard sstatus.VS field. Since commit
d863910eabaf ("riscv: vector: Support xtheadvector save/restore"),
riscv_v_enable() and riscv_v_disable() set and clear SR_VS_THEAD instead
on cores with xtheadvector, so riscv_v_is_on() returns false there even
while the vector unit is enabled.
__switch_to_vector() relies on riscv_v_is_on() to recognise a task that
is switched out inside a preemptible kernel-mode vector section. On
xtheadvector cores that check never succeeds: the outgoing task neither
disables the vector unit nor sets RISCV_PREEMPT_V_IN_SCHEDULE, and
riscv_v_enable() is skipped when the task is switched back in.
Test the status field that the running core actually uses.
Fixes: d863910eabaf ("riscv: vector: Support xtheadvector save/restore")
Cc: stable@vger.kernel.org
Assisted-by: LLM
Signed-off-by: Gleb Pesin <dormancygrace@gmail.com>
---
arch/riscv/include/asm/vector.h | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/arch/riscv/include/asm/vector.h b/arch/riscv/include/asm/vector.h
index fffe72a77..910313dd0 100644
--- a/arch/riscv/include/asm/vector.h
+++ b/arch/riscv/include/asm/vector.h
@@ -128,7 +128,9 @@ static __always_inline void riscv_v_disable(void)
static __always_inline bool riscv_v_is_on(void)
{
- return !!(csr_read(CSR_SSTATUS) & SR_VS);
+ unsigned long mask = has_xtheadvector() ? SR_VS_THEAD : SR_VS;
+
+ return !!(csr_read(CSR_SSTATUS) & mask);
}
static __always_inline void __vstate_csr_save(struct __riscv_v_ext_state *dest)
--
2.53.0
^ permalink raw reply [flat|nested] 4+ messages in thread
* [PATCH 2/3] riscv: Make the vendor extension headers usable from assembly
2026-10-06 0:35 [PATCH 0/3] riscv: Fix xtheadvector vector status handling Gleb Pesin via B4 Relay
2026-10-06 0:35 ` [PATCH 1/3] riscv: vector: Check the xtheadvector status field in riscv_v_is_on() Gleb Pesin via B4 Relay
@ 2026-10-06 0:35 ` Gleb Pesin via B4 Relay
2026-10-06 0:35 ` [PATCH 3/3] riscv: Disable the xtheadvector unit on kernel entry Gleb Pesin via B4 Relay
2 siblings, 0 replies; 4+ messages in thread
From: Gleb Pesin via B4 Relay @ 2026-10-06 0:35 UTC (permalink / raw)
To: Paul Walmsley, Palmer Dabbelt, Albert Ou, Alexandre Ghiti
Cc: linux-riscv, linux-kernel, Andy Chiu, Charlie Jenkins, stable,
Gleb Pesin
From: Gleb Pesin <dormancygrace@gmail.com>
<asm/vendor_extensions.h> and <asm/vendor_extensions/thead.h> provide
the constants that ALTERNATIVE() needs for a vendor extension
(RISCV_VENDOR_EXT_ALTERNATIVES_BASE and RISCV_ISA_VENDOR_EXT_*), but
they also pull in C headers and declarations, so assembly files cannot
include them.
Keep the constants visible to assembly and guard the rest with
__ASSEMBLY__. No functional change.
This is needed by the next patch, which uses the xtheadvector
alternative in entry.S.
Cc: stable@vger.kernel.org # 6.14+: needed by the next patch
Assisted-by: LLM
Signed-off-by: Gleb Pesin <dormancygrace@gmail.com>
---
arch/riscv/include/asm/vendor_extensions.h | 28 ++++++++++++++----------
arch/riscv/include/asm/vendor_extensions/thead.h | 8 +++++--
2 files changed, 22 insertions(+), 14 deletions(-)
diff --git a/arch/riscv/include/asm/vendor_extensions.h b/arch/riscv/include/asm/vendor_extensions.h
index 7437304a7..c9fca8591 100644
--- a/arch/riscv/include/asm/vendor_extensions.h
+++ b/arch/riscv/include/asm/vendor_extensions.h
@@ -6,16 +6,25 @@
#ifndef _ASM_VENDOR_EXTENSIONS_H
#define _ASM_VENDOR_EXTENSIONS_H
-#include <asm/cpufeature.h>
-
-#include <linux/array_size.h>
-#include <linux/types.h>
-
/*
* The extension keys of each vendor must be strictly less than this value.
*/
#define RISCV_ISA_VENDOR_EXT_MAX 32
+/*
+ * The alternatives need some way of distinguishing between vendor extensions
+ * and errata. Incrementing all of the vendor extension keys so they are at
+ * least 0x8000 accomplishes that.
+ */
+#define RISCV_VENDOR_EXT_ALTERNATIVES_BASE 0x8000
+
+#ifndef __ASSEMBLY__
+
+#include <asm/cpufeature.h>
+
+#include <linux/array_size.h>
+#include <linux/types.h>
+
struct riscv_isavendorinfo {
DECLARE_BITMAP(isa, RISCV_ISA_VENDOR_EXT_MAX);
};
@@ -32,13 +41,6 @@ extern struct riscv_isa_vendor_ext_data_list *riscv_isa_vendor_ext_list[];
extern const size_t riscv_isa_vendor_ext_list_size;
-/*
- * The alternatives need some way of distinguishing between vendor extensions
- * and errata. Incrementing all of the vendor extension keys so they are at
- * least 0x8000 accomplishes that.
- */
-#define RISCV_VENDOR_EXT_ALTERNATIVES_BASE 0x8000
-
#define VENDOR_EXT_ALL_CPUS -1
bool __riscv_isa_vendor_extension_available(int cpu, unsigned long vendor, unsigned int bit);
@@ -101,4 +103,6 @@ static __always_inline bool riscv_cpu_has_vendor_extension_unlikely(const unsign
return __riscv_isa_vendor_extension_available(cpu, vendor, ext);
}
+#endif /* __ASSEMBLY__ */
+
#endif /* _ASM_VENDOR_EXTENSIONS_H */
diff --git a/arch/riscv/include/asm/vendor_extensions/thead.h b/arch/riscv/include/asm/vendor_extensions/thead.h
index e85c75b3b..625f44175 100644
--- a/arch/riscv/include/asm/vendor_extensions/thead.h
+++ b/arch/riscv/include/asm/vendor_extensions/thead.h
@@ -4,13 +4,15 @@
#include <asm/vendor_extensions.h>
-#include <linux/types.h>
-
/*
* Extension keys must be strictly less than RISCV_ISA_VENDOR_EXT_MAX.
*/
#define RISCV_ISA_VENDOR_EXT_XTHEADVECTOR 0
+#ifndef __ASSEMBLY__
+
+#include <linux/types.h>
+
extern struct riscv_isa_vendor_ext_data_list riscv_isa_vendor_ext_list_thead;
#ifdef CONFIG_RISCV_ISA_VENDOR_EXT_THEAD
@@ -19,6 +21,8 @@ void disable_xtheadvector(void);
static inline void disable_xtheadvector(void) { }
#endif
+#endif /* __ASSEMBLY__ */
+
/* Extension specific helpers */
/*
--
2.53.0
^ permalink raw reply [flat|nested] 4+ messages in thread
* [PATCH 3/3] riscv: Disable the xtheadvector unit on kernel entry
2026-10-06 0:35 [PATCH 0/3] riscv: Fix xtheadvector vector status handling Gleb Pesin via B4 Relay
2026-10-06 0:35 ` [PATCH 1/3] riscv: vector: Check the xtheadvector status field in riscv_v_is_on() Gleb Pesin via B4 Relay
2026-10-06 0:35 ` [PATCH 2/3] riscv: Make the vendor extension headers usable from assembly Gleb Pesin via B4 Relay
@ 2026-10-06 0:35 ` Gleb Pesin via B4 Relay
2 siblings, 0 replies; 4+ messages in thread
From: Gleb Pesin via B4 Relay @ 2026-10-06 0:35 UTC (permalink / raw)
To: Paul Walmsley, Palmer Dabbelt, Albert Ou, Alexandre Ghiti
Cc: linux-riscv, linux-kernel, Andy Chiu, Charlie Jenkins, stable,
Gleb Pesin
From: Gleb Pesin <dormancygrace@gmail.com>
handle_exception clears SR_FS_VS on entry so that stray floating-point
or vector instructions in the kernel raise an illegal-instruction
exception. xtheadvector keeps its vector status in SR_VS_THEAD
(sstatus bits 24:23), which that mask does not cover. On 64-bit kernels
bit 23 happens to be cleared as SR_SPELP, so the T-Head field is only
partly reset: DIRTY becomes CLEAN, and the vector unit stays enabled in
the kernel after a trap from a context that used it.
Clear the whole SR_VS_THEAD field on cores with xtheadvector. The status
saved in pt_regs still holds the interrupted value, so the vector state
is restored on return exactly as before. Other cores keep the current
mask, because bit 24 is not part of the vector status there.
Fixes: d863910eabaf ("riscv: vector: Support xtheadvector save/restore")
Cc: stable@vger.kernel.org
Assisted-by: LLM
Signed-off-by: Gleb Pesin <dormancygrace@gmail.com>
---
arch/riscv/kernel/entry.S | 11 +++++++++--
1 file changed, 9 insertions(+), 2 deletions(-)
diff --git a/arch/riscv/kernel/entry.S b/arch/riscv/kernel/entry.S
index d799c4e56..aeb99c20b 100644
--- a/arch/riscv/kernel/entry.S
+++ b/arch/riscv/kernel/entry.S
@@ -16,6 +16,8 @@
#include <asm/thread_info.h>
#include <asm/asm-offsets.h>
#include <asm/errata_list.h>
+#include <asm/vendor_extensions.h>
+#include <asm/vendor_extensions/thead.h>
#include <linux/sizes.h>
.section .irqentry.text, "ax"
@@ -176,9 +178,14 @@ SYM_CODE_START(handle_exception)
* actual user copy routines.
*
* Disable the FPU/Vector to detect illegal usage of floating point
- * or vector in kernel space.
+ * or vector in kernel space. xtheadvector keeps its vector status in
+ * a different sstatus field; those bits are reserved elsewhere.
*/
- li t0, SR_SUM | SR_FS_VS
+ ALTERNATIVE(__stringify(li t0, SR_SUM | SR_FS_VS),
+ __stringify(li t0, SR_SUM | SR_FS_VS | SR_VS_THEAD),
+ THEAD_VENDOR_ID,
+ RISCV_VENDOR_EXT_ALTERNATIVES_BASE + RISCV_ISA_VENDOR_EXT_XTHEADVECTOR,
+ CONFIG_RISCV_ISA_XTHEADVECTOR)
#ifdef CONFIG_64BIT
li t1, SR_ELP
or t0, t0, t1
--
2.53.0
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2026-10-06 0:36 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-10-06 0:35 [PATCH 0/3] riscv: Fix xtheadvector vector status handling Gleb Pesin via B4 Relay
2026-10-06 0:35 ` [PATCH 1/3] riscv: vector: Check the xtheadvector status field in riscv_v_is_on() Gleb Pesin via B4 Relay
2026-10-06 0:35 ` [PATCH 2/3] riscv: Make the vendor extension headers usable from assembly Gleb Pesin via B4 Relay
2026-10-06 0:35 ` [PATCH 3/3] riscv: Disable the xtheadvector unit on kernel entry Gleb Pesin via B4 Relay
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®