Re: [PATCH v6 1/3] lib: sbi: Add RISC-V vector context save/restore support

Anup Patel <[email protected]>
Newsgroups org.infradead.lists.opensbi
Message-ID <CAAhSdy2ngCAq=GkK-KV1BNwJaEmbuCgesmnM9vakoS-KQWFYMQ@mail.gmail.com>
On Sun, May 17, 2026 at 3:51 AM <[email protected]> wrote:
>
> From: Dave Patel <[email protected]>
>
> 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 <[email protected]>
> ---
>  include/sbi/sbi_vector.h |  28 ++++++++
>  lib/sbi/objects.mk       |   1 +
>  lib/sbi/sbi_vector.c     | 138 +++++++++++++++++++++++++++++++++++++++
>  3 files changed, 167 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 <[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[];
> +};
> +
> +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..c596ec7a
> --- /dev/null
> +++ b/lib/sbi/sbi_vector.c
> @@ -0,0 +1,138 @@
> +/*
> + * SPDX-License-Identifier: BSD-2-Clause
> + *
> + * Copyright (c) 2026 RISCstar Solutions.
> + *
> + * Authors:
> + *      Dave Patel <[email protected]>
> + */
> +
> +#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;

This whole function can be a single statement "csr_read(CSR_VLENB);"

Introduce new function sbi_vector_context_size() over here which
estimates vector context size over here so that all vector context
related code is in one place.

size_t sbi_vector_context_size(void)
{
    return sizeof(struct sbi_vector_context) + (32 * csr_read(CSR_VLENB));
}

> +}
> +
> +static inline void set_vs(void)
> +{
> +       csr_set(CSR_MSTATUS, MSTATUS_VS);
> +}
> +
> +void sbi_vector_save(struct sbi_vector_context *dst)
> +{
> +       if (!dst)
> +               return;
> +
> +       unsigned long mstatus_orig;

Move all variable declarations at the start of function.

> +       /* Step 1. Save original mstatus */
> +       asm volatile("csrr %0, mstatus" : "=r"(mstatus_orig));
> +
> +       /* Step 2. Enable VS */
> +       set_vs();

These two lines can be just one once CSR operation:
mstatus_orig = csr_read_set(CSR_MSTATUS, MSTATUS_VS);

> +
> +       /* Step 3: Save CSRs */
> +       dst->vcsr = csr_read(vcsr);
> +       dst->vstart = csr_read(vstart);
> +
> +       ulong vlenb = vector_vlenb();
> +       uint8_t *base = dst->vregs;
> +
> +       /* Step 4: 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);
> +
> +#undef SAVE_VREG
> +
> +       /* Step 5. Restore original mstatus LAST */
> +       asm volatile("csrw mstatus, %0" :: "r"(mstatus_orig));

csr_write(CSR_MSTATUS, mstatus_orig);

> +}
> +
> +void sbi_vector_restore(const struct sbi_vector_context *src)
> +{
> +       if (!src)
> +               return;
> +
> +       unsigned long mstatus_orig;

Move all variable declarations at the start of function.

> +       /* Step 1. Save original mstatus */
> +       asm volatile("csrr %0, mstatus" : "=r"(mstatus_orig));
> +
> +       /* Step 2. Enable VS */
> +       set_vs();

Same comment as above.

> +
> +       const uint8_t *base = src->vregs;
> +       ulong vlenb = vector_vlenb();
> +
> +       /* Step 3: 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 4: Restore CSR's last */
> +       /* Restore CSRs first */
> +       csr_write(vcsr,   src->vcsr);
> +       csr_write(vstart, src->vstart);
> +
> +       /* Step 5. Restore original mstatus LAST */
> +       asm volatile("csrw mstatus, %0" :: "r"(mstatus_orig));

Same comment as above.

> +}
> +
> +#else
> +
> +void sbi_vector_save(struct sbi_vector_context *dst)
> +{
> +}
> +
> +void sbi_vector_restore(const struct sbi_vector_context *src)
> +{
> +}
> +
> +unsigned long vector_vlenb(void)
> +{
> +       return 0;
> +}

size_t sbi_vector_context_size(void)
{
     return 0;
}

> +#endif /* OPENSBI_CC_SUPPORT_VECTOR */
> --
> 2.43.0
>
>
> --
> opensbi mailing list
> [email protected]
> http://lists.infradead.org/mailman/listinfo/opensbi

Regards,
Anup

-- 
opensbi mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/opensbi
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.