Files
opensbi/lib/sbi/sbi_vector.c
T
Dave Patel 21461156da lib: sbi: Add RISC-V vector context save/restore support
Eager context switch: 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 vcsr CSRs along with storage for all 32 vector
registers. The register state is saved and restored using byte-wise vector
load/store instructions (vs8r/vl8r).

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.

Signed-off-by: Dave Patel <dave.patel@riscstar.com>
Signed-off-by: Anup Patel <anup.patel@oss.qualcomm.com>
Link: https://lore.kernel.org/r/20260518083023.997323-2-anup.patel@oss.qualcomm.com
Signed-off-by: Anup Patel <anup@brainfault.org>
2026-05-18 14:02:28 +05:30

95 lines
2.0 KiB
C

/*
* SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2026 RISCstar Solutions.
*
* Authors:
* Dave Patel <dave.patel@riscstar.com>
*/
#include <sbi/riscv_encoding.h>
#include <sbi/riscv_asm.h>
#include <sbi/sbi_vector.h>
#include <sbi/sbi_types.h>
#include <sbi/sbi_hart.h>
#include <sbi/sbi_error.h>
size_t sbi_vector_context_size(void)
{
return sizeof(struct sbi_vector_context) + (32 * csr_read(CSR_VLENB));
}
void sbi_vector_save(struct sbi_vector_context *dst)
{
unsigned long vlenb, mstatus_orig;
if (!dst)
return;
/* Step 1. Save original mstatus and Enable VS */
mstatus_orig = csr_read_set(CSR_MSTATUS, MSTATUS_VS);
vlenb = csr_read(CSR_VLENB);
/* Step 2: Save CSRs */
dst->vcsr = csr_read(vcsr);
dst->vstart = csr_read(vstart);
/* Step 3: Save vector registers */
#define SAVE_VREG(i) \
({ \
asm volatile( \
" .option push\n\t" \
" .option arch, +v\n\t" \
" vs8r.v v" #i ", (%0)\n\t" \
" .option pop\n\t" \
:: "r"(dst->vregs + (i) * vlenb) : "memory"); \
}) \
SAVE_VREG(0);
SAVE_VREG(8);
SAVE_VREG(16);
SAVE_VREG(24);
#undef SAVE_VREG
/* Step 4. Restore original mstatus LAST */
csr_write(CSR_MSTATUS, mstatus_orig);
}
void sbi_vector_restore(const struct sbi_vector_context *src)
{
unsigned long vlenb, mstatus_orig;
if (!src)
return;
/* Step 1. Save original mstatus and Enable VS */
mstatus_orig = csr_read_set(CSR_MSTATUS, MSTATUS_VS);
vlenb = csr_read(CSR_VLENB);
/* Step 2: Restore vector registers */
#define RESTORE_VREG(i) \
({ \
asm volatile( \
" .option push\n\t" \
" .option arch, +v\n\t" \
" vl8r.v v" #i ", (%0)\n\t" \
" .option pop\n\t" \
:: "r"(src->vregs + (i) * vlenb) : "memory"); \
}) \
RESTORE_VREG(0);
RESTORE_VREG(8);
RESTORE_VREG(16);
RESTORE_VREG(24);
#undef RESTORE_VREG
/* Step 3: Restore CSR's last */
/* Restore CSRs first */
csr_write(vcsr, src->vcsr);
csr_write(vstart, src->vstart);
/* Step 4. Restore original mstatus LAST */
csr_write(CSR_MSTATUS, mstatus_orig);
}