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 + */ + +#ifndef __SBI_VECTOR_H__ +#define __SBI_VECTOR_H__ + +#include + +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 + */ + +#include +#include +#include +#include +#include +#include + +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); +}