* [PATCH 1/4] lib: sbi: Add RISC-V vector context save/restore support (eager switching)
2026-03-20 14:30 [PATCH v1 0/4] Add eager FP and RISC-V vector context switching support dave.patel
@ 2026-03-20 14:30 ` dave.patel
2026-03-23 4:37 ` Samuel Holland
2026-03-20 14:30 ` [PATCH 2/4] lib: sbi: Add floating-point context save/restore support dave.patel
` (2 subsequent siblings)
3 siblings, 1 reply; 8+ messages in thread
From: dave.patel @ 2026-03-20 14:30 UTC (permalink / raw)
To: opensbi
Cc: Scott Bambrough, Robin Randhawa, Anup Patel, Samuel Holland,
Dave Patel, Ray Mao, Anup Patel, Dhaval, Peter Lin
From: Dave Patel <dave.patel@riscstar.com>
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 vl, vtype, vcsr CSRs along with storage for all
32 vector registers. The register state is saved and restored using byte-wise
vector load/store instructions (vse8.v/vle8.v), making the implementation
independent of current SEW/LMUL configuration.
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.
A per-hart pointer is used to track the current vector context owner.
Notes:
- The maximum supported VLEN is capped via SBI_MAX_VLENB.
- The implementation assumes the vector unit is enabled when invoked.
- vstart CSR is not currently saved/restored and is expected to be zero
across context switch boundaries.
Signed-off-by: Dave Patel <dave.patel@riscstar.com>
---
include/sbi/sbi_vector.h | 30 +++++++++
lib/sbi/objects.mk | 1 +
lib/sbi/sbi_vector.c | 136 +++++++++++++++++++++++++++++++++++++++
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..6be477c0
--- /dev/null
+++ b/include/sbi/sbi_vector.h
@@ -0,0 +1,30 @@
+/* SPDX-License-Identifier: GPL-2.0
+ *
+ * Copyright (c) 2026 RISCstar Solutions.
+ *
+ * Authors:
+ * Dave Patel <dave.patel@riscstar.com>
+ */
+
+#ifndef __SBI_VECTOR_H__
+#define __SBI_VECTOR_H__
+
+#include <sbi/sbi_types.h>
+
+#define SBI_MAX_VLENB 256
+
+struct sbi_vector_context {
+ unsigned long vl;
+ unsigned long vtype;
+ unsigned long vcsr;
+
+ /* size depends on VLEN */
+ uint8_t vregs[32 * SBI_MAX_VLENB];
+};
+
+struct sbi_vector_context *sbi_current_vector_context(void);
+void sbi_vector_save(struct sbi_vector_context *dst);
+void sbi_vector_restore(const struct sbi_vector_context *src);
+
+#endif //__SBI_VECTOR_H__
+
diff --git a/lib/sbi/objects.mk b/lib/sbi/objects.mk
index ea816e92..5c0caf39 100644
--- a/lib/sbi/objects.mk
+++ b/lib/sbi/objects.mk
@@ -106,3 +106,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..37239ce2
--- /dev/null
+++ b/lib/sbi/sbi_vector.c
@@ -0,0 +1,136 @@
+/* SPDX-License-Identifier: GPL-2.0
+ *
+ * Copyright (c) 2026 RISCstar Solutions.
+ *
+ * Authors:
+ * Dave Patel <dave.patel@riscstar.com>
+ */
+
+#include <sbi/sbi_domain.h>
+#include <sbi/riscv_encoding.h>
+#include <sbi/riscv_asm.h>
+#include <sbi/sbi_vector.h>
+
+/* Per-hart vector owner */
+static inline struct sbi_vector_context **vec_owner_ptr(void)
+{
+ struct sbi_scratch *scratch = sbi_scratch_thishart_ptr();
+ return &scratch->vec_ctx;
+}
+
+/* Get current vector context */
+struct sbi_vector_context *sbi_current_vector_context(void)
+{
+ return *vec_owner_ptr();
+}
+
+static inline unsigned long vector_vlenb(void)
+{
+ unsigned long vlenb;
+ asm volatile ("csrr %0, vlenb" : "=r"(vlenb));
+ return vlenb;
+}
+
+
+void sbi_vector_save(struct sbi_vector_context *dst)
+{
+ if (!dst)
+ return;
+
+ uint8_t *base = dst->vregs;
+ unsigned long vlenb = vector_vlenb();
+
+ asm volatile("csrr %0, vtype" : "=r"(dst->vtype));
+ asm volatile("csrr %0, vl" : "=r"(dst->vl));
+ asm volatile("csrr %0, vcsr" : "=r"(dst->vcsr));
+
+#define SAVE_VREG(num) \
+ asm volatile("vse8.v v" #num ", (%0)" :: "r"(base + num * vlenb) : "memory")
+
+ SAVE_VREG(0);
+ SAVE_VREG(1);
+ SAVE_VREG(2);
+ SAVE_VREG(3);
+ SAVE_VREG(4);
+ SAVE_VREG(5);
+ SAVE_VREG(6);
+ SAVE_VREG(7);
+ SAVE_VREG(8);
+ SAVE_VREG(9);
+ SAVE_VREG(10);
+ SAVE_VREG(11);
+ SAVE_VREG(12);
+ SAVE_VREG(13);
+ SAVE_VREG(14);
+ SAVE_VREG(15);
+ SAVE_VREG(16);
+ SAVE_VREG(17);
+ SAVE_VREG(18);
+ SAVE_VREG(19);
+ SAVE_VREG(20);
+ SAVE_VREG(21);
+ SAVE_VREG(22);
+ SAVE_VREG(23);
+ SAVE_VREG(24);
+ SAVE_VREG(25);
+ SAVE_VREG(26);
+ SAVE_VREG(27);
+ SAVE_VREG(28);
+ SAVE_VREG(29);
+ SAVE_VREG(30);
+ SAVE_VREG(31);
+
+#undef SAVE_VREG
+}
+
+void sbi_vector_restore(const struct sbi_vector_context *src)
+{
+ if (!src)
+ return;
+
+ const uint8_t *base = src->vregs;
+ unsigned long vlenb = vector_vlenb();
+
+ asm volatile("csrw vtype, %0" :: "r"(src->vtype));
+ asm volatile("csrw vl, %0" :: "r"(src->vl));
+ asm volatile("csrw vcsr, %0" :: "r"(src->vcsr));
+
+#define RESTORE_VREG(num) \
+ asm volatile("vle8.v v" #num ", (%0)" :: "r"(base + num * vlenb) : "memory")
+
+ RESTORE_VREG(0);
+ RESTORE_VREG(1);
+ RESTORE_VREG(2);
+ RESTORE_VREG(3);
+ RESTORE_VREG(4);
+ RESTORE_VREG(5);
+ RESTORE_VREG(6);
+ RESTORE_VREG(7);
+ RESTORE_VREG(8);
+ RESTORE_VREG(9);
+ RESTORE_VREG(10);
+ RESTORE_VREG(11);
+ RESTORE_VREG(12);
+ RESTORE_VREG(13);
+ RESTORE_VREG(14);
+ RESTORE_VREG(15);
+ RESTORE_VREG(16);
+ RESTORE_VREG(17);
+ RESTORE_VREG(18);
+ RESTORE_VREG(19);
+ RESTORE_VREG(20);
+ RESTORE_VREG(21);
+ RESTORE_VREG(22);
+ RESTORE_VREG(23);
+ RESTORE_VREG(24);
+ RESTORE_VREG(25);
+ RESTORE_VREG(26);
+ RESTORE_VREG(27);
+ RESTORE_VREG(28);
+ RESTORE_VREG(29);
+ RESTORE_VREG(30);
+ RESTORE_VREG(31);
+
+#undef RESTORE_VREG
+}
+
--
2.43.0
--
opensbi mailing list
opensbi@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/opensbi
^ permalink raw reply related [flat|nested] 8+ messages in thread* Re: [PATCH 1/4] lib: sbi: Add RISC-V vector context save/restore support (eager switching)
2026-03-20 14:30 ` [PATCH 1/4] lib: sbi: Add RISC-V vector context save/restore support (eager switching) dave.patel
@ 2026-03-23 4:37 ` Samuel Holland
2026-03-23 10:05 ` Dave Patel
0 siblings, 1 reply; 8+ messages in thread
From: Samuel Holland @ 2026-03-23 4:37 UTC (permalink / raw)
To: dave.patel, opensbi
Cc: Scott Bambrough, Robin Randhawa, Anup Patel, Ray Mao, Anup Patel,
Dhaval, Peter Lin
Hi Dave,
On 2026-03-20 9:30 AM, dave.patel@riscstar.com wrote:
> From: Dave Patel <dave.patel@riscstar.com>
>
> 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 vl, vtype, vcsr CSRs along with storage for all
> 32 vector registers. The register state is saved and restored using byte-wise
> vector load/store instructions (vse8.v/vle8.v), making the implementation
> independent of current SEW/LMUL configuration.
>
> 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.
>
> A per-hart pointer is used to track the current vector context owner.
Storing only one context per hart means that you must save/restore the context
every time the hart traps to M-mode. This is unnecessary and inefficient,
because OpenSBI itself does not use the vector registers (except where it
explicitly modifies the lower-privilege vector state when emulating
instructions). It is only necessary to save/restore the context when switching
between domains, not when trapping to M-mode and returning to the same domain.
So a better place for the context is in `struct hart_context` in
lib/sbi/sbi_domain_context.c.
> Notes:
> - The maximum supported VLEN is capped via SBI_MAX_VLENB.
> - The implementation assumes the vector unit is enabled when invoked.
This is not something you can assume. The code must not crash when running on
hardware without vector ISA support (Zve32x).
> - vstart CSR is not currently saved/restored and is expected to be zero
> across context switch boundaries.
This is not something you can assume. A trap can happen anywhere (e.g. due to an
interrupt), so vstart may be nonzero and must not leak across domains.
>
> Signed-off-by: Dave Patel <dave.patel@riscstar.com>
> ---
> include/sbi/sbi_vector.h | 30 +++++++++
> lib/sbi/objects.mk | 1 +
> lib/sbi/sbi_vector.c | 136 +++++++++++++++++++++++++++++++++++++++
> 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..6be477c0
> --- /dev/null
> +++ b/include/sbi/sbi_vector.h
> @@ -0,0 +1,30 @@
> +/* SPDX-License-Identifier: GPL-2.0
> + *
> + * Copyright (c) 2026 RISCstar Solutions.
> + *
> + * Authors:
> + * Dave Patel <dave.patel@riscstar.com>
> + */
> +
> +#ifndef __SBI_VECTOR_H__
> +#define __SBI_VECTOR_H__
> +
> +#include <sbi/sbi_types.h>
> +
> +#define SBI_MAX_VLENB 256
> +
> +struct sbi_vector_context {
> + unsigned long vl;
> + unsigned long vtype;
> + unsigned long vcsr;
> +
> + /* size depends on VLEN */
> + uint8_t vregs[32 * SBI_MAX_VLENB];
> +};
> +
> +struct sbi_vector_context *sbi_current_vector_context(void);
> +void sbi_vector_save(struct sbi_vector_context *dst);
> +void sbi_vector_restore(const struct sbi_vector_context *src);
> +
> +#endif //__SBI_VECTOR_H__
> +
> diff --git a/lib/sbi/objects.mk b/lib/sbi/objects.mk
> index ea816e92..5c0caf39 100644
> --- a/lib/sbi/objects.mk
> +++ b/lib/sbi/objects.mk
> @@ -106,3 +106,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..37239ce2
> --- /dev/null
> +++ b/lib/sbi/sbi_vector.c
> @@ -0,0 +1,136 @@
> +/* SPDX-License-Identifier: GPL-2.0
> + *
> + * Copyright (c) 2026 RISCstar Solutions.
> + *
> + * Authors:
> + * Dave Patel <dave.patel@riscstar.com>
> + */
> +
> +#include <sbi/sbi_domain.h>
> +#include <sbi/riscv_encoding.h>
> +#include <sbi/riscv_asm.h>
> +#include <sbi/sbi_vector.h>
> +
> +/* Per-hart vector owner */
> +static inline struct sbi_vector_context **vec_owner_ptr(void)
> +{
> + struct sbi_scratch *scratch = sbi_scratch_thishart_ptr();
> + return &scratch->vec_ctx;
The code must compile and run after every patch in the series, but the vec_ctx
member isn't added until patch 3, so this doesn't compile. However, as mentioned
above, the context should be stored per-domain anyway.
Regards,
Samuel
> +}
> +
> +/* Get current vector context */
> +struct sbi_vector_context *sbi_current_vector_context(void)
> +{
> + return *vec_owner_ptr();
> +}
> +
> +static inline unsigned long vector_vlenb(void)
> +{
> + unsigned long vlenb;
> + asm volatile ("csrr %0, vlenb" : "=r"(vlenb));
> + return vlenb;
> +}
> +
> +
> +void sbi_vector_save(struct sbi_vector_context *dst)
> +{
> + if (!dst)
> + return;
> +
> + uint8_t *base = dst->vregs;
> + unsigned long vlenb = vector_vlenb();
> +
> + asm volatile("csrr %0, vtype" : "=r"(dst->vtype));
> + asm volatile("csrr %0, vl" : "=r"(dst->vl));
> + asm volatile("csrr %0, vcsr" : "=r"(dst->vcsr));
> +
> +#define SAVE_VREG(num) \
> + asm volatile("vse8.v v" #num ", (%0)" :: "r"(base + num * vlenb) : "memory")
> +
> + SAVE_VREG(0);
> + SAVE_VREG(1);
> + SAVE_VREG(2);
> + SAVE_VREG(3);
> + SAVE_VREG(4);
> + SAVE_VREG(5);
> + SAVE_VREG(6);
> + SAVE_VREG(7);
> + SAVE_VREG(8);
> + SAVE_VREG(9);
> + SAVE_VREG(10);
> + SAVE_VREG(11);
> + SAVE_VREG(12);
> + SAVE_VREG(13);
> + SAVE_VREG(14);
> + SAVE_VREG(15);
> + SAVE_VREG(16);
> + SAVE_VREG(17);
> + SAVE_VREG(18);
> + SAVE_VREG(19);
> + SAVE_VREG(20);
> + SAVE_VREG(21);
> + SAVE_VREG(22);
> + SAVE_VREG(23);
> + SAVE_VREG(24);
> + SAVE_VREG(25);
> + SAVE_VREG(26);
> + SAVE_VREG(27);
> + SAVE_VREG(28);
> + SAVE_VREG(29);
> + SAVE_VREG(30);
> + SAVE_VREG(31);
> +
> +#undef SAVE_VREG
> +}
> +
> +void sbi_vector_restore(const struct sbi_vector_context *src)
> +{
> + if (!src)
> + return;
> +
> + const uint8_t *base = src->vregs;
> + unsigned long vlenb = vector_vlenb();
> +
> + asm volatile("csrw vtype, %0" :: "r"(src->vtype));
> + asm volatile("csrw vl, %0" :: "r"(src->vl));
> + asm volatile("csrw vcsr, %0" :: "r"(src->vcsr));
> +
> +#define RESTORE_VREG(num) \
> + asm volatile("vle8.v v" #num ", (%0)" :: "r"(base + num * vlenb) : "memory")
> +
> + RESTORE_VREG(0);
> + RESTORE_VREG(1);
> + RESTORE_VREG(2);
> + RESTORE_VREG(3);
> + RESTORE_VREG(4);
> + RESTORE_VREG(5);
> + RESTORE_VREG(6);
> + RESTORE_VREG(7);
> + RESTORE_VREG(8);
> + RESTORE_VREG(9);
> + RESTORE_VREG(10);
> + RESTORE_VREG(11);
> + RESTORE_VREG(12);
> + RESTORE_VREG(13);
> + RESTORE_VREG(14);
> + RESTORE_VREG(15);
> + RESTORE_VREG(16);
> + RESTORE_VREG(17);
> + RESTORE_VREG(18);
> + RESTORE_VREG(19);
> + RESTORE_VREG(20);
> + RESTORE_VREG(21);
> + RESTORE_VREG(22);
> + RESTORE_VREG(23);
> + RESTORE_VREG(24);
> + RESTORE_VREG(25);
> + RESTORE_VREG(26);
> + RESTORE_VREG(27);
> + RESTORE_VREG(28);
> + RESTORE_VREG(29);
> + RESTORE_VREG(30);
> + RESTORE_VREG(31);
> +
> +#undef RESTORE_VREG
> +}
> +
--
opensbi mailing list
opensbi@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/opensbi
^ permalink raw reply [flat|nested] 8+ messages in thread* Re: [PATCH 1/4] lib: sbi: Add RISC-V vector context save/restore support (eager switching)
2026-03-23 4:37 ` Samuel Holland
@ 2026-03-23 10:05 ` Dave Patel
0 siblings, 0 replies; 8+ messages in thread
From: Dave Patel @ 2026-03-23 10:05 UTC (permalink / raw)
To: Samuel Holland, opensbi
Cc: Scott Bambrough, Robin Randhawa, Anup Patel, Ray Mao, Anup Patel,
Dhaval, Peter Lin
On 3/23/26 04:37, Samuel Holland wrote:
> Hi Dave,
>
> On 2026-03-20 9:30 AM, dave.patel@riscstar.com wrote:
>> From: Dave Patel <dave.patel@riscstar.com>
>>
>> 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 vl, vtype, vcsr CSRs along with storage for all
>> 32 vector registers. The register state is saved and restored using byte-wise
>> vector load/store instructions (vse8.v/vle8.v), making the implementation
>> independent of current SEW/LMUL configuration.
>>
>> 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.
>>
>> A per-hart pointer is used to track the current vector context owner.
>
> Storing only one context per hart means that you must save/restore the context
> every time the hart traps to M-mode. This is unnecessary and inefficient,
> because OpenSBI itself does not use the vector registers (except where it
> explicitly modifies the lower-privilege vector state when emulating
> instructions). It is only necessary to save/restore the context when switching
> between domains, not when trapping to M-mode and returning to the same domain.
> So a better place for the context is in `struct hart_context` in
> lib/sbi/sbi_domain_context.c.
This was the comment of the email and RFC is for discussion as OpenSBI
does not use the vector registers, the implementation was to give the
context with the RFC (overhead on every trap due to full state save and
restore). Is it possible to provide usecase and more information to
cover this as Opensbi won't be using the vector registers?
Also do we have any consideration of how this context switch work when
there a trap occurs in the middle of this context?
Also the domain context should be covered by S-mode for example Linux
kernel, how is it different to domain context in Opensbi?
>
>> Notes:
>> - The maximum supported VLEN is capped via SBI_MAX_VLENB.
>> - The implementation assumes the vector unit is enabled when invoked.
>
> This is not something you can assume. The code must not crash when running on
> hardware without vector ISA support (Zve32x).
Yes I was going to provide Complie switch, however left it open for
discussion. So should this only be compiled switch for
PLATFORM_RISCV_ISA=rv64gcv? and that we don't want this to be included
for Zve32x?
>
>> - vstart CSR is not currently saved/restored and is expected to be zero
>> across context switch boundaries.
>
> This is not something you can assume. A trap can happen anywhere (e.g. due to an
> interrupt), so vstart may be nonzero and must not leak across domains.
Yes correct, I deliberately left it open to have a discussion and view
point, so I will save vstart CSR for context aswell.
>
>>
>> Signed-off-by: Dave Patel <dave.patel@riscstar.com>
>> ---
>> include/sbi/sbi_vector.h | 30 +++++++++
>> lib/sbi/objects.mk | 1 +
>> lib/sbi/sbi_vector.c | 136 +++++++++++++++++++++++++++++++++++++++
>> 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..6be477c0
>> --- /dev/null
>> +++ b/include/sbi/sbi_vector.h
>> @@ -0,0 +1,30 @@
>> +/* SPDX-License-Identifier: GPL-2.0
>> + *
>> + * Copyright (c) 2026 RISCstar Solutions.
>> + *
>> + * Authors:
>> + * Dave Patel <dave.patel@riscstar.com>
>> + */
>> +
>> +#ifndef __SBI_VECTOR_H__
>> +#define __SBI_VECTOR_H__
>> +
>> +#include <sbi/sbi_types.h>
>> +
>> +#define SBI_MAX_VLENB 256
>> +
>> +struct sbi_vector_context {
>> + unsigned long vl;
>> + unsigned long vtype;
>> + unsigned long vcsr;
>> +
>> + /* size depends on VLEN */
>> + uint8_t vregs[32 * SBI_MAX_VLENB];
>> +};
>> +
>> +struct sbi_vector_context *sbi_current_vector_context(void);
>> +void sbi_vector_save(struct sbi_vector_context *dst);
>> +void sbi_vector_restore(const struct sbi_vector_context *src);
>> +
>> +#endif //__SBI_VECTOR_H__
>> +
>> diff --git a/lib/sbi/objects.mk b/lib/sbi/objects.mk
>> index ea816e92..5c0caf39 100644
>> --- a/lib/sbi/objects.mk
>> +++ b/lib/sbi/objects.mk
>> @@ -106,3 +106,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..37239ce2
>> --- /dev/null
>> +++ b/lib/sbi/sbi_vector.c
>> @@ -0,0 +1,136 @@
>> +/* SPDX-License-Identifier: GPL-2.0
>> + *
>> + * Copyright (c) 2026 RISCstar Solutions.
>> + *
>> + * Authors:
>> + * Dave Patel <dave.patel@riscstar.com>
>> + */
>> +
>> +#include <sbi/sbi_domain.h>
>> +#include <sbi/riscv_encoding.h>
>> +#include <sbi/riscv_asm.h>
>> +#include <sbi/sbi_vector.h>
>> +
>> +/* Per-hart vector owner */
>> +static inline struct sbi_vector_context **vec_owner_ptr(void)
>> +{
>> + struct sbi_scratch *scratch = sbi_scratch_thishart_ptr();
>> + return &scratch->vec_ctx;
>
> The code must compile and run after every patch in the series, but the vec_ctx
> member isn't added until patch 3, so this doesn't compile. However, as mentioned
> above, the context should be stored per-domain anyway.
ok, thanks.
>
> Regards,
> Samuel
>
Hi Samuel,
Thanks for taking out time and providing comments: very much
appreciated.
I have some question.
Thanks
Dave
--
opensbi mailing list
opensbi@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/opensbi
^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH 2/4] lib: sbi: Add floating-point context save/restore support.
2026-03-20 14:30 [PATCH v1 0/4] Add eager FP and RISC-V vector context switching support dave.patel
2026-03-20 14:30 ` [PATCH 1/4] lib: sbi: Add RISC-V vector context save/restore support (eager switching) dave.patel
@ 2026-03-20 14:30 ` dave.patel
2026-03-20 14:30 ` [PATCH 3/4] include: sbi: scratch: Add per-hart FP and vector context pointers in scratch dave.patel
2026-03-20 14:30 ` [PATCH 4/4] lib: sbi: trap: Save/restore FP and vector state on trap entry/exit dave.patel
3 siblings, 0 replies; 8+ messages in thread
From: dave.patel @ 2026-03-20 14:30 UTC (permalink / raw)
To: opensbi
Cc: Scott Bambrough, Robin Randhawa, Anup Patel, Samuel Holland,
Dave Patel, Ray Mao, Anup Patel, Dhaval, Peter Lin
From: Dave Patel <dave.patel@riscstar.com>
Add support for saving and restoring RISC-V floating-point (F/D) extension
state in OpenSBI. This introduces a per-hart floating-point context
structure and helper routines to perform full context save and restore.
The floating-point context includes storage for all 32 FPi registers (f0–f31)
along with the fcsr control and status register. The register state is saved
and restored using double-precision load/store instructions (fsd/fld),
assuming an RV64 system with D-extension support.
The implementation follows an eager context switching model where the entire
FP state is saved and restored on every context switch. This avoids the need
for trap-based lazy management and keeps the design simple and deterministic.
A per-hart pointer is used to track the current floating-point context owner.
Notes:
- The implementation assumes the floating-point unit is enabled
(mstatus.FS != Off) when invoked.
- The context layout is fixed to 64-bit FP registers.
Signed-off-by: Dave Patel <dave.patel@riscstar.com>"
---
include/sbi/sbi_fp.h | 22 ++++++++
lib/sbi/objects.mk | 1 +
lib/sbi/sbi_fp.c | 117 +++++++++++++++++++++++++++++++++++++++++++
3 files changed, 140 insertions(+)
create mode 100644 include/sbi/sbi_fp.h
create mode 100644 lib/sbi/sbi_fp.c
diff --git a/include/sbi/sbi_fp.h b/include/sbi/sbi_fp.h
new file mode 100644
index 00000000..58c5b50e
--- /dev/null
+++ b/include/sbi/sbi_fp.h
@@ -0,0 +1,22 @@
+/* SPDX-License-Identifier: GPL-2.0
+ *
+ * Copyright (c) 2026 RISCstar Solutions.
+ *
+ * Authors:
+ * Dave Patel <dave.patel@riscstar.com>
+ */
+
+#ifndef __SBI_FP_H__
+#define __SBI_FP_H__
+
+struct sbi_fp_context {
+ unsigned long f[32];
+ unsigned long fcsr;
+};
+
+struct sbi_fp_context *sbi_current_fp_context(void);
+void sbi_fp_save(struct sbi_fp_context *dst);
+void sbi_fp_restore(const struct sbi_fp_context *src);
+
+#endif //__SBI_VECTOR_H__
+
diff --git a/lib/sbi/objects.mk b/lib/sbi/objects.mk
index 5c0caf39..ca560c2e 100644
--- a/lib/sbi/objects.mk
+++ b/lib/sbi/objects.mk
@@ -107,3 +107,4 @@ 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
+libsbi-objs-y += sbi_fp.o
diff --git a/lib/sbi/sbi_fp.c b/lib/sbi/sbi_fp.c
new file mode 100644
index 00000000..4d5e0f68
--- /dev/null
+++ b/lib/sbi/sbi_fp.c
@@ -0,0 +1,117 @@
+/* SPDX-License-Identifier: GPL-2.0
+ *
+ * Copyright (c) 2026 RISCstar Solutions.
+ *
+ * Authors:
+ * Dave Patel <dave.patel@riscstar.com>
+ */
+
+#include <sbi/riscv_asm.h>
+#include <sbi/riscv_encoding.h>
+#include <sbi/sbi_scratch.h>
+#include <sbi/sbi_fp.h>
+
+/* Per-hart current owner pointer (SMP-safe) */
+static inline struct sbi_fp_context **fp_owner_ptr(void)
+{
+ struct sbi_scratch *scratch = sbi_scratch_thishart_ptr();
+ return &scratch->fp_ctx;
+}
+
+/* Get current FP context */
+struct sbi_fp_context *sbi_current_fp_context(void)
+{
+ return *fp_owner_ptr();
+}
+
+void sbi_fp_save(struct sbi_fp_context *dst)
+{
+ if (!dst)
+ return;
+
+ asm volatile(
+ "fsd f0, 0(%0)\n"
+ "fsd f1, 8(%0)\n"
+ "fsd f2, 16(%0)\n"
+ "fsd f3, 24(%0)\n"
+ "fsd f4, 32(%0)\n"
+ "fsd f5, 40(%0)\n"
+ "fsd f6, 48(%0)\n"
+ "fsd f7, 56(%0)\n"
+ "fsd f8, 64(%0)\n"
+ "fsd f9, 72(%0)\n"
+ "fsd f10, 80(%0)\n"
+ "fsd f11, 88(%0)\n"
+ "fsd f12, 96(%0)\n"
+ "fsd f13, 104(%0)\n"
+ "fsd f14, 112(%0)\n"
+ "fsd f15, 120(%0)\n"
+ "fsd f16, 128(%0)\n"
+ "fsd f17, 136(%0)\n"
+ "fsd f18, 144(%0)\n"
+ "fsd f19, 152(%0)\n"
+ "fsd f20, 160(%0)\n"
+ "fsd f21, 168(%0)\n"
+ "fsd f22, 176(%0)\n"
+ "fsd f23, 184(%0)\n"
+ "fsd f24, 192(%0)\n"
+ "fsd f25, 200(%0)\n"
+ "fsd f26, 208(%0)\n"
+ "fsd f27, 216(%0)\n"
+ "fsd f28, 224(%0)\n"
+ "fsd f29, 232(%0)\n"
+ "fsd f30, 240(%0)\n"
+ "fsd f31, 248(%0)\n"
+ :
+ : "r"(dst->f)
+ : "memory"
+ );
+
+ dst->fcsr = csr_read(CSR_FCSR);
+}
+
+void sbi_fp_restore(const struct sbi_fp_context *src)
+{
+ if (!src)
+ return;
+
+ asm volatile(
+ "fld f0, 0(%0)\n"
+ "fld f1, 8(%0)\n"
+ "fld f2, 16(%0)\n"
+ "fld f3, 24(%0)\n"
+ "fld f4, 32(%0)\n"
+ "fld f5, 40(%0)\n"
+ "fld f6, 48(%0)\n"
+ "fld f7, 56(%0)\n"
+ "fld f8, 64(%0)\n"
+ "fld f9, 72(%0)\n"
+ "fld f10, 80(%0)\n"
+ "fld f11, 88(%0)\n"
+ "fld f12, 96(%0)\n"
+ "fld f13, 104(%0)\n"
+ "fld f14, 112(%0)\n"
+ "fld f15, 120(%0)\n"
+ "fld f16, 128(%0)\n"
+ "fld f17, 136(%0)\n"
+ "fld f18, 144(%0)\n"
+ "fld f19, 152(%0)\n"
+ "fld f20, 160(%0)\n"
+ "fld f21, 168(%0)\n"
+ "fld f22, 176(%0)\n"
+ "fld f23, 184(%0)\n"
+ "fld f24, 192(%0)\n"
+ "fld f25, 200(%0)\n"
+ "fld f26, 208(%0)\n"
+ "fld f27, 216(%0)\n"
+ "fld f28, 224(%0)\n"
+ "fld f29, 232(%0)\n"
+ "fld f30, 240(%0)\n"
+ "fld f31, 248(%0)\n"
+ :
+ : "r"(src->f)
+ : "memory"
+ );
+
+ csr_write(CSR_FCSR, src->fcsr);
+}
--
2.43.0
--
opensbi mailing list
opensbi@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/opensbi
^ permalink raw reply related [flat|nested] 8+ messages in thread* [PATCH 3/4] include: sbi: scratch: Add per-hart FP and vector context pointers in scratch
2026-03-20 14:30 [PATCH v1 0/4] Add eager FP and RISC-V vector context switching support dave.patel
2026-03-20 14:30 ` [PATCH 1/4] lib: sbi: Add RISC-V vector context save/restore support (eager switching) dave.patel
2026-03-20 14:30 ` [PATCH 2/4] lib: sbi: Add floating-point context save/restore support dave.patel
@ 2026-03-20 14:30 ` dave.patel
2026-03-20 14:30 ` [PATCH 4/4] lib: sbi: trap: Save/restore FP and vector state on trap entry/exit dave.patel
3 siblings, 0 replies; 8+ messages in thread
From: dave.patel @ 2026-03-20 14:30 UTC (permalink / raw)
To: opensbi
Cc: Scott Bambrough, Robin Randhawa, Anup Patel, Samuel Holland,
Dave Patel, Ray Mao, Anup Patel, Dhaval, Peter Lin
From: Dave Patel <dave.patel@riscstar.com>
Extend the per-hart sbi_scratch structure to include pointers to floating-point
and vector context storage.
This enables tracking of the currently active FP and vector context on a per-hart
basis, which is required for eager context switching during trap handling.
The scratch structure serves as the central per-hart storage area, making these
pointers readily accessible in low-level trap and context switch paths.
The FP and vector context pointers are used by the corresponding save/restore
routines to preserve architectural state across traps, ensuring correct isolation
between privilege levels.
This change lays the foundation for eager FP and vector context management in OpenSBI.
Signed-off-by: Dave Patel <dave.patel@riscstar.com>
---
include/sbi/sbi_scratch.h | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/include/sbi/sbi_scratch.h b/include/sbi/sbi_scratch.h
index 58d54628..13e4a294 100644
--- a/include/sbi/sbi_scratch.h
+++ b/include/sbi/sbi_scratch.h
@@ -54,6 +54,8 @@
#ifndef __ASSEMBLER__
#include <sbi/sbi_types.h>
+#include <sbi/sbi_fp.h>
+#include <sbi/sbi_vector.h>
/** Representation of per-HART scratch space */
struct sbi_scratch {
@@ -87,6 +89,9 @@ struct sbi_scratch {
unsigned long options;
/** Index of the hart */
unsigned long hartindex;
+ /* Current FP/Vector context owner per hart */
+ struct sbi_fp_context *fp_ctx;
+ struct sbi_vector_context *vec_ctx;
};
/**
--
2.43.0
--
opensbi mailing list
opensbi@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/opensbi
^ permalink raw reply related [flat|nested] 8+ messages in thread* [PATCH 4/4] lib: sbi: trap: Save/restore FP and vector state on trap entry/exit
2026-03-20 14:30 [PATCH v1 0/4] Add eager FP and RISC-V vector context switching support dave.patel
` (2 preceding siblings ...)
2026-03-20 14:30 ` [PATCH 3/4] include: sbi: scratch: Add per-hart FP and vector context pointers in scratch dave.patel
@ 2026-03-20 14:30 ` dave.patel
2026-03-23 4:42 ` Samuel Holland
3 siblings, 1 reply; 8+ messages in thread
From: dave.patel @ 2026-03-20 14:30 UTC (permalink / raw)
To: opensbi
Cc: Scott Bambrough, Robin Randhawa, Anup Patel, Samuel Holland,
Dave Patel, Ray Mao, Anup Patel, Dhaval, Peter Lin
From: Dave Patel <dave.patel@riscstar.com>
Add eager floating-point and vector context save/restore in the OpenSBI trap
handler. The FP and vector state of the current hart is saved on trap entry
and restored before returning from the trap.
This ensures that machine-mode trap handling does not clobber floating-point
or vector state belonging to lower privilege software (e.g. supervisor mode),
providing correct isolation across trap boundaries.
The implementation leverages sbi_fp_save/restore() and sbi_vector_save/restore()
helpers and uses per-hart context pointers stored in sbi_scratch.
This follows an eager context switching model where the full FP and vector state
is preserved unconditionally on every trap, avoiding the need for lazy
enable/disable or trap-on-first-use mechanisms.
Notes:
- Assumes FP and vector units are enabled when trap handling occurs
(mstatus.FS/VS != Off).
- Context pointers (fp_ctx, vec_ctx) must be valid when used.
- This may introduce additional trap latency due to full state save/restore.
Signed-off-by: Dave Patel <dave.patel@riscstar.com>
---
lib/sbi/sbi_fp.c | 2 +-
lib/sbi/sbi_trap.c | 18 ++++++++++++++++++
2 files changed, 19 insertions(+), 1 deletion(-)
diff --git a/lib/sbi/sbi_fp.c b/lib/sbi/sbi_fp.c
index 4d5e0f68..24d97937 100644
--- a/lib/sbi/sbi_fp.c
+++ b/lib/sbi/sbi_fp.c
@@ -72,7 +72,7 @@ void sbi_fp_save(struct sbi_fp_context *dst)
void sbi_fp_restore(const struct sbi_fp_context *src)
{
- if (!src)
+ if (!src)
return;
asm volatile(
diff --git a/lib/sbi/sbi_trap.c b/lib/sbi/sbi_trap.c
index f41db4d1..6a182216 100644
--- a/lib/sbi/sbi_trap.c
+++ b/lib/sbi/sbi_trap.c
@@ -24,6 +24,8 @@
#include <sbi/sbi_sse.h>
#include <sbi/sbi_timer.h>
#include <sbi/sbi_trap.h>
+#include <sbi/sbi_fp.h>
+#include <sbi/sbi_vector.h>
static void sbi_trap_error_one(const struct sbi_trap_context *tcntx,
const char *prefix, u32 hartid, u32 depth)
@@ -310,6 +312,14 @@ struct sbi_trap_context *sbi_trap_handler(struct sbi_trap_context *tcntx)
struct sbi_trap_regs *regs = &tcntx->regs;
ulong mcause = tcntx->trap.cause;
+ /* save floating context */
+ struct sbi_fp_context *fpctx = scratch->fp_ctx;
+ sbi_fp_save(fpctx);
+
+ /* save vector context */
+ struct sbi_vector_context *vecctx = scratch->vec_ctx;
+ sbi_vector_save(vecctx);
+
/* Update trap context pointer */
tcntx->prev_context = sbi_trap_get_context(scratch);
sbi_trap_set_context(scratch, tcntx);
@@ -373,5 +383,13 @@ trap_done:
sbi_sse_process_pending_events(regs);
sbi_trap_set_context(scratch, tcntx->prev_context);
+
+
+ /* restore floating context */
+ sbi_fp_restore(fpctx);
+
+ /* restore vector context */
+ sbi_vector_restore(vecctx);
+
return tcntx;
}
--
2.43.0
--
opensbi mailing list
opensbi@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/opensbi
^ permalink raw reply related [flat|nested] 8+ messages in thread* Re: [PATCH 4/4] lib: sbi: trap: Save/restore FP and vector state on trap entry/exit
2026-03-20 14:30 ` [PATCH 4/4] lib: sbi: trap: Save/restore FP and vector state on trap entry/exit dave.patel
@ 2026-03-23 4:42 ` Samuel Holland
0 siblings, 0 replies; 8+ messages in thread
From: Samuel Holland @ 2026-03-23 4:42 UTC (permalink / raw)
To: dave.patel, opensbi
Cc: Scott Bambrough, Robin Randhawa, Anup Patel, Ray Mao, Anup Patel,
Dhaval, Peter Lin
Hi Dave,
On 2026-03-20 9:30 AM, dave.patel@riscstar.com wrote:
> From: Dave Patel <dave.patel@riscstar.com>
>
> Add eager floating-point and vector context save/restore in the OpenSBI trap
> handler. The FP and vector state of the current hart is saved on trap entry
> and restored before returning from the trap.
>
> This ensures that machine-mode trap handling does not clobber floating-point
> or vector state belonging to lower privilege software (e.g. supervisor mode),
> providing correct isolation across trap boundaries.
>
> The implementation leverages sbi_fp_save/restore() and sbi_vector_save/restore()
> helpers and uses per-hart context pointers stored in sbi_scratch.
>
> This follows an eager context switching model where the full FP and vector state
> is preserved unconditionally on every trap, avoiding the need for lazy
> enable/disable or trap-on-first-use mechanisms.
>
> Notes:
> - Assumes FP and vector units are enabled when trap handling occurs
> (mstatus.FS/VS != Off).
> - Context pointers (fp_ctx, vec_ctx) must be valid when used.
> - This may introduce additional trap latency due to full state save/restore.
>
> Signed-off-by: Dave Patel <dave.patel@riscstar.com>
> ---
> lib/sbi/sbi_fp.c | 2 +-
> lib/sbi/sbi_trap.c | 18 ++++++++++++++++++
> 2 files changed, 19 insertions(+), 1 deletion(-)
>
> diff --git a/lib/sbi/sbi_fp.c b/lib/sbi/sbi_fp.c
> index 4d5e0f68..24d97937 100644
> --- a/lib/sbi/sbi_fp.c
> +++ b/lib/sbi/sbi_fp.c
> @@ -72,7 +72,7 @@ void sbi_fp_save(struct sbi_fp_context *dst)
>
> void sbi_fp_restore(const struct sbi_fp_context *src)
> {
> - if (!src)
> + if (!src)
> return;
>
> asm volatile(
> diff --git a/lib/sbi/sbi_trap.c b/lib/sbi/sbi_trap.c
> index f41db4d1..6a182216 100644
> --- a/lib/sbi/sbi_trap.c
> +++ b/lib/sbi/sbi_trap.c
> @@ -24,6 +24,8 @@
> #include <sbi/sbi_sse.h>
> #include <sbi/sbi_timer.h>
> #include <sbi/sbi_trap.h>
> +#include <sbi/sbi_fp.h>
> +#include <sbi/sbi_vector.h>
>
> static void sbi_trap_error_one(const struct sbi_trap_context *tcntx,
> const char *prefix, u32 hartid, u32 depth)
> @@ -310,6 +312,14 @@ struct sbi_trap_context *sbi_trap_handler(struct sbi_trap_context *tcntx)
> struct sbi_trap_regs *regs = &tcntx->regs;
> ulong mcause = tcntx->trap.cause;
>
> + /* save floating context */
> + struct sbi_fp_context *fpctx = scratch->fp_ctx;
> + sbi_fp_save(fpctx);
> +
> + /* save vector context */
> + struct sbi_vector_context *vecctx = scratch->vec_ctx;
> + sbi_vector_save(vecctx);
> +
> /* Update trap context pointer */
> tcntx->prev_context = sbi_trap_get_context(scratch);
> sbi_trap_set_context(scratch, tcntx);
> @@ -373,5 +383,13 @@ trap_done:
> sbi_sse_process_pending_events(regs);
>
> sbi_trap_set_context(scratch, tcntx->prev_context);
> +
> +
> + /* restore floating context */
> + sbi_fp_restore(fpctx);
> +
> + /* restore vector context */
> + sbi_vector_restore(vecctx);
> +
As referenced in patch 1, these calls should go inside
switch_to_next_domain_context(), not the top-level trap handling. In fact,
restoring the context here is broken because it will undo any changes to the
register file made by the misaligned access handlers.
Regards,
Samuel
> return tcntx;
> }
--
opensbi mailing list
opensbi@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/opensbi
^ permalink raw reply [flat|nested] 8+ messages in thread