[RFC 2/3] RISCV Vector changes

[email protected] Tue, 23 Jun 2026 07:18:54 +0100
Newsgroups org.trustedfirmware.lists.op-tee
Message-ID <[email protected]>
From: Dave Patel <[email protected]>

Signed-off-by: Dave Patel <[email protected]>
---
 core/arch/riscv/include/riscv_vector.h | 32 +++++++++++
 core/arch/riscv/kernel/riscv_vector.c  | 77 ++++++++++++++++++++++++++
 2 files changed, 109 insertions(+)
 create mode 100644 core/arch/riscv/include/riscv_vector.h
 create mode 100644 core/arch/riscv/kernel/riscv_vector.c

diff --git a/core/arch/riscv/include/riscv_vector.h b/core/arch/riscv/include/riscv_vector.h
new file mode 100644
index 000000000..2aa3b26db
--- /dev/null
+++ b/core/arch/riscv/include/riscv_vector.h
@@ -0,0 +1,32 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+/*
+ * Copyright (c) 2026, RISCStar Limited
+ */
+
+#ifndef __KERNEL_RISCV_VECTOR_H
+#define __KERNEL_RISCV_VECTOR_H
+
+#include <types_ext.h>
+#include <compiler.h>
+
+/* CSR Status Bit Masks for Vector Extensions */
+#define SSTATUS_VS_MASK       SHIFT_U32(3, 9)   /* bits [10:9] */
+#define SSTATUS_VS_OFF        SHIFT_U32(0, 9)
+#define SSTATUS_VS_INITIAL    SHIFT_U32(1, 9)
+#define SSTATUS_VS_CLEAN      SHIFT_U32(2, 9)
+#define SSTATUS_VS_DIRTY      SHIFT_U32(3, 9)
+
+/* Vector Context Struct */
+struct riscv_vector_state {
+	uint8_t *vregs;
+	unsigned long vtype;
+	unsigned long vl;
+	unsigned long vcsr;
+	unsigned long vstart;
+};
+
+/* Internal context routers instantiated inside riscv_vector.c */
+void riscv_vector_save_internal(struct riscv_vector_state *dst);
+void riscv_vector_restore_internal(const struct riscv_vector_state *src);
+
+#endif /* __KERNEL_RISCV_VECTOR_H */
diff --git a/core/arch/riscv/kernel/riscv_vector.c b/core/arch/riscv/kernel/riscv_vector.c
new file mode 100644
index 000000000..b7f7431fe
--- /dev/null
+++ b/core/arch/riscv/kernel/riscv_vector.c
@@ -0,0 +1,77 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+/*
+ * Copyright (c) 2026, RISCStar Limited
+ */
+
+#include <kernel/riscv_vector.h>
+#include <types_ext.h>
+
+void riscv_vector_save_internal(struct riscv_vector_state *dst)
+{
+	unsigned long vlenb;
+	uint8_t *base;
+
+	if (!dst)
+		return;
+
+	asm volatile("csrr %0, vtype" : "=r"(dst->vtype));
+	asm volatile("csrr %0, vl" : "=r"(dst->vl));
+	asm volatile("csrr %0, vcsr" : "=r"(dst->vcsr));
+	asm volatile("csrr %0, vstart" : "=r"(dst->vstart));
+	asm volatile("csrr %0, 0xc22" : "=r"(vlenb)); /* CSR_VLENB = 0xc22 */
+
+	base = dst->vregs;
+
+#define SAVE_VREG_CHUNK(i)					\
+	asm volatile(						\
+		"       .option push\n\t"			\
+		"       .option arch, +v\n\t"			\
+		"       vs8r.v v" #i ", (%0)\n\t"		\
+		"       .option pop\n\t"			\
+		:: "r"(base + (i) * vlenb) : "memory")
+
+	SAVE_VREG_CHUNK(0);
+	SAVE_VREG_CHUNK(8);
+	SAVE_VREG_CHUNK(16);
+	SAVE_VREG_CHUNK(24);
+#undef SAVE_VREG_CHUNK
+}
+
+void riscv_vector_restore_internal(const struct riscv_vector_state *src)
+{
+	unsigned long vlenb;
+	const uint8_t *base;
+
+	if (!src)
+		return;
+
+	asm volatile("csrw vcsr, %0" :: "r"(src->vcsr));
+	asm volatile("csrw vstart, %0" :: "r"(src->vstart));
+
+	/* Re-establish execution parameters prior to block transfer */
+	asm volatile(
+		"       .option push\n\t"
+		"       .option arch, +v\n\t"
+		"       vsetvl zero, %0, %1\n\t"
+		"       .option pop\n\t"
+		:: "r"(src->vl), "r"(src->vtype));
+
+	asm volatile("csrr %0, 0xc22" : "=r"(vlenb));
+	base = src->vregs;
+
+#define RESTORE_VREG_CHUNK(i)					\
+								\
+	asm volatile(						\
+		"       .option push\n\t"			\
+		"       .option arch, +v\n\t"			\
+		"       vl8r.v v" #i ", (%0)\n\t"		\
+		"       .option pop\n\t"			\
+		:: "r"(base + (i) * vlenb) : "memory")
+
+	RESTORE_VREG_CHUNK(0);
+	RESTORE_VREG_CHUNK(8);
+	RESTORE_VREG_CHUNK(16);
+	RESTORE_VREG_CHUNK(24);
+#undef RESTORE_VREG_CHUNK
+}
+
-- 
2.43.0