[PATCH v6 3/3] lib: sbi: domain FP/Vector context support for context switch

Anup Patel anup at brainfault.org
Sun May 17 08:37:57 PDT 2026


On Sun, May 17, 2026 at 3:51 AM <dave.patel at riscstar.com> wrote:
>
> From: Dave Patel <dave.patel at riscstar.com>
>
> This patch adds proper support for per-domain floating-point (FP) and
> vector (V) contexts in the domain context switch logic. Each domain
> now maintains its own FP and vector state, which is saved and restored
> during domain switches.
>
> Conditionalize FP and Vector save/restore based on extensions, unconditional
> save and restore of floating-point (FP) and Vector registers fails on
> generic platform firmware. This firmware must run on multiple platforms
> that may lack these extensions.
>
> Address this by conditionally executing FP save/restore only if the underlying
> hart supports the F or D extensions. Similarly, perform Vector save/restore
> only if the hart supports the Vector extension.
>
> Changes include:
>
> - Added `fp_ctx` and `vec_ctx` members to `struct hart_context`.
> - Introduced dynamic vector struct allocation for vlenb in 'struct hart_context'
>   to allocate and free per-domain FP and vector context.
> - Modified `sbi_domain_register()` to initialize FP/Vector context per domain.
> - Updated `switch_to_next_domain_context()` to save/restore FP and vector
>   contexts safely:
>     - Ensures FS/VS fields in `mstatus` are enabled (set to Initial) only if Off.
> - Added runtime checks for FP and vector extensions where needed.
> - Added SBI_HART_EXT_F, SBI_HART_EXT_D, SBI_HART_EXT_V to enum
>   sbi_hart_extensions and the sbi_hart_ext[] array. Use sbi_hart_has_extension()
>   to check for these capabilities before performing the context switches

This changelog should be part of cover-letter with every series revision.

>
> This improves support for multi-domain systems with FP and Vector
> extensions, and prevents corruption of FP/Vector state during domain
> switches.
>
> Signed-off-by: Dave Patel <dave.patel at riscstar.com>
> ---
>  include/sbi/sbi_hart.h       |  6 ++++++
>  lib/sbi/sbi_domain_context.c | 37 ++++++++++++++++++++++++++++++++++++
>  lib/sbi/sbi_hart.c           |  3 +++
>  3 files changed, 46 insertions(+)
>
> diff --git a/include/sbi/sbi_hart.h b/include/sbi/sbi_hart.h
> index a788b34c..68a01b97 100644
> --- a/include/sbi/sbi_hart.h
> +++ b/include/sbi/sbi_hart.h
> @@ -87,6 +87,12 @@ enum sbi_hart_extensions {
>         SBI_HART_EXT_XSIFIVE_CFLUSH_D_L1,
>         /** Hart has Xsfcease extension */
>         SBI_HART_EXT_XSIFIVE_CEASE,
> +       /** Hart has V extension */
> +       SBI_HART_EXT_V,
> +       /** Hart has F extension */
> +       SBI_HART_EXT_F,
> +       /** Hart has D extension */
> +       SBI_HART_EXT_D,
>
>         /** Maximum index of Hart extension */
>         SBI_HART_EXT_MAX,
> diff --git a/lib/sbi/sbi_domain_context.c b/lib/sbi/sbi_domain_context.c
> index 158f4990..a3f69e7f 100644
> --- a/lib/sbi/sbi_domain_context.c
> +++ b/lib/sbi/sbi_domain_context.c
> @@ -18,6 +18,8 @@
>  #include <sbi/sbi_domain_context.h>
>  #include <sbi/sbi_platform.h>
>  #include <sbi/sbi_trap.h>
> +#include <sbi/sbi_vector.h>
> +#include <sbi/sbi_fp.h>
>
>  /** Context representation for a hart within a domain */
>  struct hart_context {
> @@ -55,6 +57,11 @@ struct hart_context {
>         struct hart_context *prev_ctx;
>         /** Is context initialized and runnable */
>         bool initialized;
> +
> +       /** float context state */
> +       struct sbi_fp_context fp_ctx;
> +       /** vector context state */
> +       struct sbi_vector_context *vec_ctx;
>  };
>
>  static struct sbi_domain_data dcpriv;
> @@ -143,6 +150,22 @@ static int switch_to_next_domain_context(struct hart_context *ctx,
>         if (sbi_hart_has_extension(scratch, SBI_HART_EXT_SSQOSID))
>                 ctx->srmcfg     = csr_swap(CSR_SRMCFG, dom_ctx->srmcfg);
>
> +       /* Eager context switch F */
> +       if (sbi_hart_has_extension(sbi_scratch_thishart_ptr(),
> +                                  SBI_HART_EXT_F) ||
> +           sbi_hart_has_extension(sbi_scratch_thishart_ptr(),
> +                                  SBI_HART_EXT_D)) {
> +               sbi_fp_save(&ctx->fp_ctx);
> +               sbi_fp_restore(&dom_ctx->fp_ctx);
> +       }
> +
> +       /* Eager context switch V */
> +       if (sbi_hart_has_extension(sbi_scratch_thishart_ptr(),
> +                                  SBI_HART_EXT_V)) {
> +               sbi_vector_save(ctx->vec_ctx);
> +               sbi_vector_restore(dom_ctx->vec_ctx);
> +       }
> +
>         /* Save current trap state and restore target domain's trap state */
>         trap_ctx = sbi_trap_get_context(scratch);
>         sbi_memcpy(&ctx->trap_ctx, trap_ctx, sizeof(*trap_ctx));
> @@ -180,6 +203,20 @@ static int hart_context_init(u32 hartindex)
>                 if (!ctx)
>                         return SBI_ENOMEM;
>
> +               if (sbi_hart_has_extension(sbi_scratch_thishart_ptr(),
> +                                          SBI_HART_EXT_V)) {
> +                       unsigned long vlenb = vector_vlenb();
> +                       /* Calculate size: base struct + 32 registers of vlenb size */
> +                       size_t vec_size = sizeof(struct sbi_vector_context) + (32 * vlenb);

Use sbi_vector_context_size() over here as suggested in PATCH1

> +
> +                       /* Allocate the vector context pointer */
> +                       ctx->vec_ctx = sbi_zalloc(vec_size);
> +                       if (!ctx->vec_ctx) {
> +                               sbi_free(ctx);
> +                               return SBI_ENOMEM;
> +                       }
> +               }
> +
>                 /* Bind context and domain */
>                 ctx->dom = dom;
>                 hart_context_set(dom, hartindex, ctx);
> diff --git a/lib/sbi/sbi_hart.c b/lib/sbi/sbi_hart.c
> index 60e95bca..b5e0ee10 100644
> --- a/lib/sbi/sbi_hart.c
> +++ b/lib/sbi/sbi_hart.c
> @@ -396,6 +396,9 @@ const struct sbi_hart_ext_data sbi_hart_ext[] = {
>         __SBI_HART_EXT_DATA(ssstateen, SBI_HART_EXT_SSSTATEEN),
>         __SBI_HART_EXT_DATA(xsfcflushdlone, SBI_HART_EXT_XSIFIVE_CFLUSH_D_L1),
>         __SBI_HART_EXT_DATA(xsfcease, SBI_HART_EXT_XSIFIVE_CEASE),
> +       __SBI_HART_EXT_DATA(v, SBI_HART_EXT_V),
> +       __SBI_HART_EXT_DATA(f, SBI_HART_EXT_F),
> +       __SBI_HART_EXT_DATA(d, SBI_HART_EXT_D),
>  };
>
>  _Static_assert(SBI_HART_EXT_MAX == array_size(sbi_hart_ext),
> --
> 2.43.0
>
>
> --
> opensbi mailing list
> opensbi at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/opensbi

Regards,
Anup



More information about the opensbi mailing list