diff --git a/include/sbi/sbi_hart.h b/include/sbi/sbi_hart.h index 937cdf29..543393bb 100644 --- a/include/sbi/sbi_hart.h +++ b/include/sbi/sbi_hart.h @@ -89,6 +89,12 @@ enum sbi_hart_extensions { SBI_HART_EXT_XSIFIVE_CEASE, /** Hart has Smrnmi extension */ SBI_HART_EXT_SMRNMI, + /** 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..fad402a8 100644 --- a/lib/sbi/sbi_domain_context.c +++ b/lib/sbi/sbi_domain_context.c @@ -18,6 +18,8 @@ #include #include #include +#include +#include /** Context representation for a hart within a domain */ struct hart_context { @@ -49,6 +51,11 @@ struct hart_context { /** Supervisor resource management configuration register */ unsigned long srmcfg; + /** Float context state */ + struct sbi_fp_context fp_ctx; + /** Vector context state */ + struct sbi_vector_context *vec_ctx; + /** Reference to the owning domain */ struct sbi_domain *dom; /** Previous context (caller) to jump to during context exits */ @@ -143,6 +150,19 @@ 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 for float */ + if (sbi_hart_has_extension(scratch, SBI_HART_EXT_F) || + sbi_hart_has_extension(scratch, SBI_HART_EXT_D)) { + sbi_fp_save(&ctx->fp_ctx); + sbi_fp_restore(&dom_ctx->fp_ctx); + } + + /* Eager context switch for vector */ + if (sbi_hart_has_extension(scratch, 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)); @@ -168,6 +188,7 @@ static int switch_to_next_domain_context(struct hart_context *ctx, static int hart_context_init(u32 hartindex) { + size_t vec_size; struct hart_context *ctx; struct sbi_domain *dom; @@ -180,6 +201,18 @@ 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)) { + vec_size = sbi_vector_context_size(); + + /* 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 43197721..0f690f53 100644 --- a/lib/sbi/sbi_hart.c +++ b/lib/sbi/sbi_hart.c @@ -399,6 +399,9 @@ const struct sbi_hart_ext_data sbi_hart_ext[] = { __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(smrnmi, SBI_HART_EXT_SMRNMI), + __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),