summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/sbi/sbi_hart.h6
-rw-r--r--lib/sbi/sbi_domain_context.c33
-rw-r--r--lib/sbi/sbi_hart.c3
3 files changed, 42 insertions, 0 deletions
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 <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 {
@@ -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),