lib: sbi: add zicfilp/zicfiss and elp cfi state reflect back in status

This patch adds support to check for zicfilp / zicfiss extension.

zicfilp record status of hart's ELP state in *status csr. Missing landing
pad sets MPELP in mstatus. When SBI is redirecting back to S/VS/HS, SPELP
is set in sstatus/vsstatus.

Signed-off-by: Deepak Gupta <debug@rivosinc.com>
Reviewed-by: Atish Patra <atishp@rivosinc.com>
Reviewed-by: Samuel Holland <samuel.holland@sifive.com>
This commit is contained in:
Deepak Gupta
2024-09-16 11:23:55 -07:00
committed by Anup Patel
parent 6758a756c4
commit c0804ed49a
3 changed files with 26 additions and 0 deletions

View File

@@ -69,6 +69,10 @@ enum sbi_hart_extensions {
SBI_HART_EXT_SVADU, SBI_HART_EXT_SVADU,
/** Hart has Smnpm extension */ /** Hart has Smnpm extension */
SBI_HART_EXT_SMNPM, SBI_HART_EXT_SMNPM,
/** HART has zicfilp extension */
SBI_HART_EXT_ZICFILP,
/** HART has zicfiss extension */
SBI_HART_EXT_ZICFISS,
/** Maximum index of Hart extension */ /** Maximum index of Hart extension */
SBI_HART_EXT_MAX, SBI_HART_EXT_MAX,

View File

@@ -681,6 +681,8 @@ const struct sbi_hart_ext_data sbi_hart_ext[] = {
__SBI_HART_EXT_DATA(svade, SBI_HART_EXT_SVADE), __SBI_HART_EXT_DATA(svade, SBI_HART_EXT_SVADE),
__SBI_HART_EXT_DATA(svadu, SBI_HART_EXT_SVADU), __SBI_HART_EXT_DATA(svadu, SBI_HART_EXT_SVADU),
__SBI_HART_EXT_DATA(smnpm, SBI_HART_EXT_SMNPM), __SBI_HART_EXT_DATA(smnpm, SBI_HART_EXT_SMNPM),
__SBI_HART_EXT_DATA(zicfilp, SBI_HART_EXT_ZICFILP),
__SBI_HART_EXT_DATA(zicfiss, SBI_HART_EXT_ZICFISS),
}; };
_Static_assert(SBI_HART_EXT_MAX == array_size(sbi_hart_ext), _Static_assert(SBI_HART_EXT_MAX == array_size(sbi_hart_ext),

View File

@@ -103,6 +103,7 @@ int sbi_trap_redirect(struct sbi_trap_regs *regs,
const struct sbi_trap_info *trap) const struct sbi_trap_info *trap)
{ {
ulong hstatus, vsstatus, prev_mode; ulong hstatus, vsstatus, prev_mode;
bool elp = false;
#if __riscv_xlen == 32 #if __riscv_xlen == 32
bool prev_virt = (regs->mstatusH & MSTATUSH_MPV) ? true : false; bool prev_virt = (regs->mstatusH & MSTATUSH_MPV) ? true : false;
#else #else
@@ -116,6 +117,17 @@ int sbi_trap_redirect(struct sbi_trap_regs *regs,
if (prev_mode != PRV_S && prev_mode != PRV_U) if (prev_mode != PRV_S && prev_mode != PRV_U)
return SBI_ENOTSUPP; return SBI_ENOTSUPP;
/* If hart support for zicfilp, clear MPELP because redirecting to VS or (H)S */
if (sbi_hart_has_extension(sbi_scratch_thishart_ptr(), SBI_HART_EXT_ZICFILP)) {
#if __riscv_xlen == 32
elp = regs->mstatusH & MSTATUSH_MPELP;
regs->mstatusH &= ~MSTATUSH_MPELP;
#else
elp = regs->mstatus & MSTATUS_MPELP;
regs->mstatus &= ~MSTATUS_MPELP;
#endif
}
/* If exceptions came from VS/VU-mode, redirect to VS-mode if /* If exceptions came from VS/VU-mode, redirect to VS-mode if
* delegated in hedeleg * delegated in hedeleg
*/ */
@@ -169,6 +181,10 @@ int sbi_trap_redirect(struct sbi_trap_regs *regs,
/* Get VS-mode SSTATUS CSR */ /* Get VS-mode SSTATUS CSR */
vsstatus = csr_read(CSR_VSSTATUS); vsstatus = csr_read(CSR_VSSTATUS);
/* If elp was set, set it back in vsstatus */
if (elp)
vsstatus |= MSTATUS_SPELP;
/* Set SPP for VS-mode */ /* Set SPP for VS-mode */
vsstatus &= ~SSTATUS_SPP; vsstatus &= ~SSTATUS_SPP;
if (prev_mode == PRV_S) if (prev_mode == PRV_S)
@@ -209,6 +225,10 @@ int sbi_trap_redirect(struct sbi_trap_regs *regs,
/* Clear SIE for S-mode */ /* Clear SIE for S-mode */
regs->mstatus &= ~MSTATUS_SIE; regs->mstatus &= ~MSTATUS_SIE;
/* If elp was set, set it back in mstatus */
if (elp)
regs->mstatus |= MSTATUS_SPELP;
} }
return 0; return 0;