blob: 1f9e01cf22aaf34b3fd9c4736ca121c6e8cdca93 [file]
/*
* 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);
}