[PATCH 2/2] lib: sbi: Reduce stack usage of vector misaligned load/store emulation

Anup Patel anup.patel at oss.qualcomm.com
Sat Jun 13 06:21:29 PDT 2026


The vector misaligned load/store emulation requires mask[] of 8192
bytes which cause stack corruptions since default stack size is also
8192 bytes.

To address the above issue, allocate mask[] on-demand from heap for
each hart and store the per-hart pointer in scratch space for reuse.

Signed-off-by: Anup Patel <anup.patel at oss.qualcomm.com>
---
 include/sbi/sbi_trap_ldst.h |  2 ++
 lib/sbi/sbi_trap.c          |  8 +++++
 lib/sbi/sbi_trap_v_ldst.c   | 61 +++++++++++++++++++++++++++++++++++--
 3 files changed, 68 insertions(+), 3 deletions(-)

diff --git a/include/sbi/sbi_trap_ldst.h b/include/sbi/sbi_trap_ldst.h
index a6a6c75b..65539035 100644
--- a/include/sbi/sbi_trap_ldst.h
+++ b/include/sbi/sbi_trap_ldst.h
@@ -37,4 +37,6 @@ int sbi_misaligned_v_ld_emulator(int rlen, union sbi_ldst_data *out_val,
 int sbi_misaligned_v_st_emulator(int wlen, union sbi_ldst_data in_val,
 				 struct sbi_trap_context *tcntx);
 
+int sbi_misaligned_v_ldst_init(void);
+
 #endif
diff --git a/lib/sbi/sbi_trap.c b/lib/sbi/sbi_trap.c
index 16774fd2..428d9296 100644
--- a/lib/sbi/sbi_trap.c
+++ b/lib/sbi/sbi_trap.c
@@ -459,5 +459,13 @@ static int delegate_traps(struct sbi_scratch *scratch)
 
 int sbi_trap_init(struct sbi_scratch *scratch, bool cold_boot)
 {
+	int rc;
+
+	if (cold_boot) {
+		rc = sbi_misaligned_v_ldst_init();
+		if (rc)
+			return rc;
+	}
+
 	return delegate_traps(scratch);
 }
diff --git a/lib/sbi/sbi_trap_v_ldst.c b/lib/sbi/sbi_trap_v_ldst.c
index f4d469dc..e642d4a2 100644
--- a/lib/sbi/sbi_trap_v_ldst.c
+++ b/lib/sbi/sbi_trap_v_ldst.c
@@ -12,15 +12,45 @@
 #include <sbi/riscv_asm.h>
 #include <sbi/riscv_encoding.h>
 #include <sbi/sbi_error.h>
+#include <sbi/sbi_heap.h>
+#include <sbi/sbi_scratch.h>
 #include <sbi/sbi_trap_ldst.h>
 #include <sbi/sbi_trap.h>
 #include <sbi/sbi_unpriv.h>
-#include <sbi/sbi_trap.h>
 
 #ifdef OPENSBI_CC_SUPPORT_VECTOR
 
 #define VLEN_MAX 65536
 
+struct misaligned_v_ldst_data {
+	uint8_t mask[VLEN_MAX / 8];
+};
+
+static unsigned long misaligned_v_ldst_dataptr_offset;
+
+#define misaligned_v_ldst_get_data_ptr(__scratch)				\
+	sbi_scratch_read_type((__scratch), void *, misaligned_v_ldst_dataptr_offset)
+
+#define misaligned_v_ldst_set_data_ptr(__scratch, __ldst)			\
+	sbi_scratch_write_type((__scratch), void *, misaligned_v_ldst_dataptr_offset, (__ldst))
+
+static struct misaligned_v_ldst_data *misaligned_v_ldst_thishart_data_ptr(void)
+{
+	struct sbi_scratch *scratch = sbi_scratch_thishart_ptr();
+	struct misaligned_v_ldst_data *ptr;
+
+	if (!misaligned_v_ldst_dataptr_offset)
+		return NULL;
+
+	ptr = misaligned_v_ldst_get_data_ptr(scratch);
+	if (!ptr) {
+		ptr = sbi_zalloc(sizeof(*ptr));
+		misaligned_v_ldst_set_data_ptr(scratch, ptr);
+	}
+
+	return misaligned_v_ldst_get_data_ptr(sbi_scratch_thishart_ptr());
+}
+
 static inline void set_vreg(ulong vlenb, ulong which,
 			    ulong pos, ulong size, const uint8_t *bytes)
 {
@@ -142,6 +172,7 @@ int sbi_misaligned_v_ld_emulator(int rlen, union sbi_ldst_data *out_val,
 {
 	const struct sbi_trap_info *orig_trap = &tcntx->trap;
 	struct sbi_trap_regs *regs = &tcntx->regs;
+	struct misaligned_v_ldst_data *hart_data;
 	struct sbi_trap_info uptrap;
 	ulong insn = sbi_get_insn(regs->mepc, &uptrap);
 	ulong vl = csr_read(CSR_VL);
@@ -157,12 +188,17 @@ int sbi_misaligned_v_ld_emulator(int rlen, union sbi_ldst_data *out_val,
 	ulong vlmul = GET_VLMUL(vtype);
 	bool illegal = GET_MEW(insn);
 	bool masked = IS_MASKED(insn);
-	uint8_t mask[VLEN_MAX / 8];
 	uint8_t bytes[8 * sizeof(uint64_t)];
 	ulong len = GET_LEN(view);
 	ulong nf = GET_NF(insn);
 	ulong vemul = GET_VEMUL(vlmul, view, vsew);
 	ulong emul = GET_EMUL(vemul);
+	uint8_t *mask;
+
+	hart_data = misaligned_v_ldst_thishart_data_ptr();
+	if (!hart_data)
+		return SBI_ENOMEM;
+	mask = hart_data->mask;
 
 	if (IS_UNIT_STRIDE_LOAD(insn) || IS_FAULT_ONLY_FIRST_LOAD(insn)) {
 		stride = nf * len;
@@ -242,6 +278,7 @@ int sbi_misaligned_v_st_emulator(int wlen, union sbi_ldst_data in_val,
 {
 	const struct sbi_trap_info *orig_trap = &tcntx->trap;
 	struct sbi_trap_regs *regs = &tcntx->regs;
+	struct misaligned_v_ldst_data *hart_data;
 	struct sbi_trap_info uptrap;
 	ulong insn = sbi_get_insn(regs->mepc, &uptrap);
 	ulong vl = csr_read(CSR_VL);
@@ -257,12 +294,17 @@ int sbi_misaligned_v_st_emulator(int wlen, union sbi_ldst_data in_val,
 	ulong vlmul = GET_VLMUL(vtype);
 	bool illegal = GET_MEW(insn);
 	bool masked = IS_MASKED(insn);
-	uint8_t mask[VLEN_MAX / 8];
 	uint8_t bytes[8 * sizeof(uint64_t)];
 	ulong len = GET_LEN(view);
 	ulong nf = GET_NF(insn);
 	ulong vemul = GET_VEMUL(vlmul, view, vsew);
 	ulong emul = GET_EMUL(vemul);
+	uint8_t *mask;
+
+	hart_data = misaligned_v_ldst_thishart_data_ptr();
+	if (!hart_data)
+		return SBI_ENOMEM;
+	mask = hart_data->mask;
 
 	if (IS_UNIT_STRIDE_STORE(insn)) {
 		stride = nf * len;
@@ -330,6 +372,15 @@ int sbi_misaligned_v_st_emulator(int wlen, union sbi_ldst_data in_val,
 
 	return vl;
 }
+
+int sbi_misaligned_v_ldst_init(void)
+{
+	misaligned_v_ldst_dataptr_offset = sbi_scratch_alloc_type_offset(void *);
+	if (!misaligned_v_ldst_dataptr_offset)
+		return SBI_ENOMEM;
+
+	return 0;
+}
 #else
 int sbi_misaligned_v_ld_emulator(int rlen, union sbi_ldst_data *out_val,
 				 struct sbi_trap_context *tcntx)
@@ -341,4 +392,8 @@ int sbi_misaligned_v_st_emulator(int wlen, union sbi_ldst_data in_val,
 {
 	return 0;
 }
+int sbi_misaligned_v_ldst_init(void)
+{
+	return 0;
+}
 #endif /* OPENSBI_CC_SUPPORT_VECTOR */
-- 
2.43.0




More information about the opensbi mailing list