diff options
| author | Bo Gan <ganboing@gmail.com> | 2026-06-05 04:32:08 -0700 |
|---|---|---|
| committer | Anup Patel <anup@brainfault.org> | 2026-06-16 12:29:59 +0530 |
| commit | bd986ed03d6336ddbd5ee90aca8a3ca533b1d5a4 (patch) | |
| tree | fd5272ac1445e03e37821704e49f178a2a4e2269 /include | |
| parent | 3c4fa3404eb331b0c605d0de2d1b6d840d95109e (diff) | |
| download | opensbi-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>
Diffstat (limited to 'include')
| -rw-r--r-- | include/sbi/sbi_trap.h | 58 |
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); |
