summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/sbi/sbi_vector.h40
-rw-r--r--lib/sbi/objects.mk1
-rw-r--r--lib/sbi/sbi_vector.c94
3 files changed, 135 insertions, 0 deletions
diff --git a/include/sbi/sbi_vector.h b/include/sbi/sbi_vector.h
new file mode 100644
index 00000000..f00184f0
--- /dev/null
+++ b/include/sbi/sbi_vector.h
@@ -0,0 +1,40 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2026 RISCstar Solutions.
+ *
+ * Authors:
+ * Dave Patel <[email protected]>
+ */
+
+#ifndef __SBI_VECTOR_H__
+#define __SBI_VECTOR_H__
+
+#include <sbi/sbi_types.h>
+
+struct sbi_vector_context {
+ unsigned long vcsr;
+ unsigned long vstart;
+
+ /* size depends on VLEN */
+ uint8_t vregs[];
+};
+
+#ifdef OPENSBI_CC_SUPPORT_VECTOR
+void sbi_vector_save(struct sbi_vector_context *dst);
+void sbi_vector_restore(const struct sbi_vector_context *src);
+size_t sbi_vector_context_size(void);
+#else
+static inline void sbi_vector_save(struct sbi_vector_context *dst)
+{
+}
+static inline void sbi_vector_restore(const struct sbi_vector_context *src)
+{
+}
+static inline size_t sbi_vector_context_size(void)
+{
+ return 0;
+}
+#endif /* OPENSBI_CC_SUPPORT_VECTOR */
+
+#endif /* __SBI_VECTOR_H__ */
diff --git a/lib/sbi/objects.mk b/lib/sbi/objects.mk
index 07d13229..c965e86d 100644
--- a/lib/sbi/objects.mk
+++ b/lib/sbi/objects.mk
@@ -102,3 +102,4 @@ libsbi-objs-y += sbi_trap_v_ldst.o
libsbi-objs-y += sbi_unpriv.o
libsbi-objs-y += sbi_expected_trap.o
libsbi-objs-y += sbi_cppc.o
+libsbi-objs-$(CC_SUPPORT_VECTOR) += sbi_vector.o
diff --git a/lib/sbi/sbi_vector.c b/lib/sbi/sbi_vector.c
new file mode 100644
index 00000000..1f9e01cf
--- /dev/null
+++ b/lib/sbi/sbi_vector.c
@@ -0,0 +1,94 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2026 RISCstar Solutions.
+ *
+ * Authors:
+ * Dave Patel <[email protected]>
+ */
+
+#include <sbi/riscv_encoding.h>
+#include <sbi/riscv_asm.h>
+#include <sbi/sbi_vector.h>
+#include <sbi/sbi_types.h>
+#include <sbi/sbi_hart.h>
+#include <sbi/sbi_error.h>
+
+size_t sbi_vector_context_size(void)
+{
+ return sizeof(struct sbi_vector_context) + (32 * csr_read(CSR_VLENB));
+}
+
+void sbi_vector_save(struct sbi_vector_context *dst)
+{
+ unsigned long vlenb, mstatus_orig;
+
+ if (!dst)
+ return;
+
+ /* Step 1. Save original mstatus and Enable VS */
+ mstatus_orig = csr_read_set(CSR_MSTATUS, MSTATUS_VS);
+ vlenb = csr_read(CSR_VLENB);
+
+ /* Step 2: Save CSRs */
+ dst->vcsr = csr_read(vcsr);
+ dst->vstart = csr_read(vstart);
+
+ /* Step 3: Save vector registers */
+#define SAVE_VREG(i) \
+ ({ \
+ asm volatile( \
+ " .option push\n\t" \
+ " .option arch, +v\n\t" \
+ " vs8r.v v" #i ", (%0)\n\t" \
+ " .option pop\n\t" \
+ :: "r"(dst->vregs + (i) * vlenb) : "memory"); \
+ }) \
+
+ SAVE_VREG(0);
+ SAVE_VREG(8);
+ SAVE_VREG(16);
+ SAVE_VREG(24);
+
+#undef SAVE_VREG
+
+ /* Step 4. Restore original mstatus LAST */
+ csr_write(CSR_MSTATUS, mstatus_orig);
+}
+
+void sbi_vector_restore(const struct sbi_vector_context *src)
+{
+ unsigned long vlenb, mstatus_orig;
+
+ if (!src)
+ return;
+
+ /* Step 1. Save original mstatus and Enable VS */
+ mstatus_orig = csr_read_set(CSR_MSTATUS, MSTATUS_VS);
+ vlenb = csr_read(CSR_VLENB);
+
+ /* Step 2: Restore vector registers */
+#define RESTORE_VREG(i) \
+ ({ \
+ asm volatile( \
+ " .option push\n\t" \
+ " .option arch, +v\n\t" \
+ " vl8r.v v" #i ", (%0)\n\t" \
+ " .option pop\n\t" \
+ :: "r"(src->vregs + (i) * vlenb) : "memory"); \
+ }) \
+
+ RESTORE_VREG(0);
+ RESTORE_VREG(8);
+ RESTORE_VREG(16);
+ RESTORE_VREG(24);
+#undef RESTORE_VREG
+
+ /* Step 3: Restore CSR's last */
+ /* Restore CSRs first */
+ csr_write(vcsr, src->vcsr);
+ csr_write(vstart, src->vstart);
+
+ /* Step 4. Restore original mstatus LAST */
+ csr_write(CSR_MSTATUS, mstatus_orig);
+}