[PATCH v5 1/4] lib: sbi: Add RISC-V vector context save/restore support

Anup Patel anup at brainfault.org
Sat May 16 09:00:10 PDT 2026


On Sat, May 16, 2026 at 3:53 PM Dave Patel <dave.patel at riscstar.com> wrote:
>
> On 5/15/26 08:41, Anup Patel wrote:
> > On Fri, May 15, 2026 at 11:12 AM <dave.patel at riscstar.com> wrote:
> >>
> >> From: Dave Patel <dave.patel at riscstar.com>
> >>
> >> Eager context switch: Add support for saving and restoring RISC-V vector
> >> extension state in OpenSBI. This introduces a per-hart vector context
> >> structure and helper routines to perform full context save and restore.
> >>
> >> The vector context includes vcsr CSRs along with storage for all 32 vector
> >> registers. The register state is saved and restored using byte-wise vector
> >> load/store instructions (vs8r/vl8r).
> >>
> >> The implementation follows an eager context switching model where the entire
> >> vector state is saved and restored on every context switch. This provides a
> >> simple and deterministic mechanism without requiring lazy trap-based
> >> management.
> >>
> >> Signed-off-by: Dave Patel <dave.patel at riscstar.com>
> >> ---
> >>  include/sbi/sbi_vector.h |  28 ++++++++++
> >>  lib/sbi/objects.mk       |   1 +
> >>  lib/sbi/sbi_vector.c     | 109 +++++++++++++++++++++++++++++++++++++++
> >>  3 files changed, 138 insertions(+)
> >>  create mode 100644 include/sbi/sbi_vector.h
> >>  create mode 100644 lib/sbi/sbi_vector.c
> >>
> >> diff --git a/include/sbi/sbi_vector.h b/include/sbi/sbi_vector.h
> >> new file mode 100644
> >> index 00000000..bbd857c3
> >> --- /dev/null
> >> +++ b/include/sbi/sbi_vector.h
> >> @@ -0,0 +1,28 @@
> >> +/*
> >> + * SPDX-License-Identifier: BSD-2-Clause
> >> + *
> >> + * Copyright (c) 2026 RISCstar Solutions.
> >> + *
> >> + * Authors:
> >> + *   Dave Patel <dave.patel at riscstar.com>
> >> + */
> >> +
> >> +#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[];
> >> +};
> >> +
> >> +void sbi_vector_save(struct sbi_vector_context *dst);
> >> +void sbi_vector_restore(const struct sbi_vector_context *src);
> >> +unsigned long vector_vlenb(void);
> >> +
> >> +#endif //__SBI_VECTOR_H__
> >> +
> >> diff --git a/lib/sbi/objects.mk b/lib/sbi/objects.mk
> >> index 97cc4521..ddb2e7ac 100644
> >> --- a/lib/sbi/objects.mk
> >> +++ b/lib/sbi/objects.mk
> >> @@ -109,3 +109,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-y += sbi_vector.o
> >> diff --git a/lib/sbi/sbi_vector.c b/lib/sbi/sbi_vector.c
> >> new file mode 100644
> >> index 00000000..1d2ac944
> >> --- /dev/null
> >> +++ b/lib/sbi/sbi_vector.c
> >> @@ -0,0 +1,109 @@
> >> +/*
> >> + * SPDX-License-Identifier: BSD-2-Clause
> >> + *
> >> + * Copyright (c) 2026 RISCstar Solutions.
> >> + *
> >> + * Authors:
> >> + *      Dave Patel <dave.patel at riscstar.com>
> >> + */
> >> +
> >> +#include <sbi/sbi_domain.h>
> >> +#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>
> >> +#include <sbi/sbi_console.h>
> >> +
> >> +#ifdef OPENSBI_CC_SUPPORT_VECTOR
> >> +
> >> +unsigned long vector_vlenb(void)
> >> +{
> >> +       unsigned long vlenb = 0;
> >> +
> >> +       asm volatile (
> >> +               ".option push\n\t"
> >> +               ".option arch, +v\n\t"
> >> +               "csrr %0, vlenb\n\t"
> >> +               ".option pop\n\t"
> >> +               : "=r"(vlenb)
> >> +               :
> >> +               : "memory");
> >> +
> >> +       return vlenb;
> >> +}
> >> +
> >> +void sbi_vector_save(struct sbi_vector_context *dst)
> >> +{
> >> +       if (!dst)
> >> +               return;
> >> +
> >> +       /* Step 1: Save CSRs */
> >> +       dst->vcsr = csr_read(vcsr);
> >> +       dst->vstart = csr_read(vstart);
> >> +
> >> +       ulong vlenb = vector_vlenb();
> >> +       uint8_t *base = dst->vregs;
> >> +
> >> +       /* 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"(base + (i) * vlenb) : "memory");    \
> >> +       })                                                      \
> >> +
> >> +       SAVE_VREG(0);
> >> +       SAVE_VREG(8);
> >> +       SAVE_VREG(16);
> >> +       SAVE_VREG(24);
> >
> > Same issue as FP save/restore, this will trap and crash
> > if Vector is disabled in mstatus.VS.
> >
> > For correct implementation, refer __riscv_v_vstate_save()/restore()
> > from <linux_source>/arch/riscv/include/asm/vector.h
> >
> >> +
> >> +#undef SAVE_VREG
> >> +}
> >> +
> >> +void sbi_vector_restore(const struct sbi_vector_context *src)
> >> +{
> >> +       if (!src)
> >> +               return;
> >> +
> >> +       const uint8_t *base = src->vregs;
> >> +       ulong vlenb = vector_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"(base + (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);
> >> +}
> >> +
> >> +#else
> >> +
> >> +void sbi_vector_save(struct sbi_vector_context *dst)
> >> +{
> >> +}
> >> +
> >> +void sbi_vector_restore(const struct sbi_vector_context *src)
> >> +{
> >> +}
> >> +
> >> +#endif /* OPENSBI_CC_SUPPORT_VECTOR */
> >> --
> >> 2.43.0
> >>
> >>
> >> --
> >> opensbi mailing list
> >> opensbi at lists.infradead.org
> >> http://lists.infradead.org/mailman/listinfo/opensbi
> >
> > Regards,
> > Anup
>
> Hi Anup,
>         Firstly thanks for all your review comments, I have endeavor to
> cover all of them, so please confirm.
>
> Rgarding this comment of mstatus.VS and FS (I think which includes 3
> comments)
>
> I have already have code inplace in patch 3, please see below line from
> patch 3
>
> +       /* Make sure FS and VS is on before context switch */
>
> +       csr_set(CSR_MSTATUS, MSTATUS_FS | MSTATUS_VS);

Setting mstatus.FS and mstatus.VS in switch_to_next_domain_context()
means you floating and vectore save/restore is not self contained and
expecting the calling function to setup mstatus.FS and mstatus.VS.


>
> Since the context of Floating and Vector is more granular in Opensbi I
> thought of handle in context switch.
>
> So there is no issue of trap and crash, however there is still a
> question regarding if you are fine with this or you want it more fine
> grained inside its individual functions?
>

I would insist to keep the float and vector save/restore code
aligned with Linux sources.

Regards,
Anup



More information about the opensbi mailing list