summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBo Gan <ganboing@gmail.com>2026-06-05 04:32:08 -0700
committerAnup Patel <anup@brainfault.org>2026-06-16 12:29:59 +0530
commitbd986ed03d6336ddbd5ee90aca8a3ca533b1d5a4 (patch)
treefd5272ac1445e03e37821704e49f178a2a4e2269
parent3c4fa3404eb331b0c605d0de2d1b6d840d95109e (diff)
downloadopensbi-bd986ed03d6336ddbd5ee90aca8a3ca533b1d5a4.tar.gz
opensbi-bd986ed03d6336ddbd5ee90aca8a3ca533b1d5a4.zip
include: sbi: Add sbi_regs_prev_xlen
sbi_regs_prev_xlen reports the xlen of previous mode by decoding from multiple CSRs including mstatus/hstatus/vsstatus Signed-off-by: Bo Gan <ganboing@gmail.com> Reviewed-by: Anup Patel <anup@brainfault.org> Tested-by: Anirudh Srinivasan <asrinivasan@oss.tenstorrent.com> Link: https://lore.kernel.org/r/20260605113214.242-3-ganboing@gmail.com Signed-off-by: Anup Patel <anup@brainfault.org>
-rw-r--r--include/sbi/sbi_trap.h58
1 files changed, 58 insertions, 0 deletions
diff --git a/include/sbi/sbi_trap.h b/include/sbi/sbi_trap.h
index 091a2446..3be418a3 100644
--- a/include/sbi/sbi_trap.h
+++ b/include/sbi/sbi_trap.h
@@ -273,6 +273,64 @@ static inline int sbi_mstatus_prev_mode(unsigned long mstatus)
return (mstatus & MSTATUS_MPP) >> MSTATUS_MPP_SHIFT;
}
+#if __riscv_xlen == 32
+static inline int sbi_regs_prev_xlen(const struct sbi_trap_regs *regs)
+{
+ return __riscv_xlen;
+}
+#else
+static inline int sbi_mstatus_sxl(unsigned long mstatus)
+{
+ return (mstatus & MSTATUS_SXL) >> MSTATUS_SXL_SHIFT;
+}
+
+static inline int sbi_mstatus_uxl(unsigned long mstatus)
+{
+ return (mstatus & MSTATUS_UXL) >> MSTATUS_UXL_SHIFT;
+}
+
+static inline int sbi_hstatus_vsxl(unsigned long hstatus)
+{
+ return (hstatus & HSTATUS_VSXL) >> HSTATUS_VSXL_SHIFT;
+}
+
+static inline int sbi_regs_prev_xlen(const struct sbi_trap_regs *regs)
+{
+ unsigned long hstatus, vsstatus;
+
+ if (!sbi_regs_from_virt(regs)) {
+ switch (sbi_mstatus_prev_mode(regs->mstatus)) {
+ case PRV_M:
+ return __riscv_xlen;
+ case PRV_S:
+ return MXL_TO_XLEN(sbi_mstatus_sxl(regs->mstatus));
+ case PRV_U:
+ return MXL_TO_XLEN(sbi_mstatus_uxl(regs->mstatus));
+ default:
+ __builtin_unreachable();
+ }
+ }
+
+ /* V=1, Check HSXLEN first */
+ if (sbi_mstatus_sxl(regs->mstatus) < MXL_XLEN_64)
+ return 32;
+
+ hstatus = csr_read(CSR_HSTATUS);
+ /* Check VSXLEN */
+ if (sbi_hstatus_vsxl(hstatus) < MXL_XLEN_64)
+ return 32;
+
+ vsstatus = csr_read(CSR_VSSTATUS);
+ switch (sbi_mstatus_prev_mode(regs->mstatus)) {
+ case PRV_S:
+ return MXL_TO_XLEN(sbi_hstatus_vsxl(hstatus));
+ case PRV_U:
+ return MXL_TO_XLEN(sbi_mstatus_uxl(vsstatus));
+ }
+ __builtin_unreachable();
+}
+#endif
+
int sbi_trap_redirect(struct sbi_trap_regs *regs,
const struct sbi_trap_info *trap);