lib: sbi: sse: Add support for SSTATUS.SDT

Similarly to what is done for SPELP, handle SSTATUS.SDT upon event
injection. In order to mimick an interrupt, set SDT to 1 for injection and
save its previous value in interrupted_flags[5:5]. Restore it upon
completion.

Signed-off-by: Clément Léger <cleger@rivosinc.com>
Reviewed-by: Andrew Jones <ajones@ventanamicro.com>
This commit is contained in:
Clément Léger
2025-03-25 11:26:14 +01:00
committed by Anup Patel
parent b4464b22e4
commit 3ac49712e3
3 changed files with 13 additions and 3 deletions

View File

@@ -32,7 +32,8 @@
#define MSTATUS_TVM _UL(0x00100000) #define MSTATUS_TVM _UL(0x00100000)
#define MSTATUS_TW _UL(0x00200000) #define MSTATUS_TW _UL(0x00200000)
#define MSTATUS_TSR _UL(0x00400000) #define MSTATUS_TSR _UL(0x00400000)
#define MSTATUS_SPELP _UL(0x00800000) #define MSTATUS_SPELP _UL(0x00800000)
#define MSTATUS_SDT _UL(0x01000000)
#define MSTATUS32_SD _UL(0x80000000) #define MSTATUS32_SD _UL(0x80000000)
#if __riscv_xlen == 64 #if __riscv_xlen == 64
#define MSTATUS_UXL _ULL(0x0000000300000000) #define MSTATUS_UXL _ULL(0x0000000300000000)

View File

@@ -385,6 +385,7 @@ enum sbi_sse_attr_id {
#define SBI_SSE_ATTR_INTERRUPTED_FLAGS_HSTATUS_SPV BIT(2) #define SBI_SSE_ATTR_INTERRUPTED_FLAGS_HSTATUS_SPV BIT(2)
#define SBI_SSE_ATTR_INTERRUPTED_FLAGS_HSTATUS_SPVP BIT(3) #define SBI_SSE_ATTR_INTERRUPTED_FLAGS_HSTATUS_SPVP BIT(3)
#define SBI_SSE_ATTR_INTERRUPTED_FLAGS_SSTATUS_SPELP BIT(4) #define SBI_SSE_ATTR_INTERRUPTED_FLAGS_SSTATUS_SPELP BIT(4)
#define SBI_SSE_ATTR_INTERRUPTED_FLAGS_SSTATUS_SDT BIT(5)
enum sbi_sse_state { enum sbi_sse_state {
SBI_SSE_STATE_UNUSED = 0, SBI_SSE_STATE_UNUSED = 0,

View File

@@ -431,7 +431,8 @@ static int sse_event_set_attr_check(struct sbi_sse_event *e, uint32_t attr_id,
SBI_SSE_ATTR_INTERRUPTED_FLAGS_SSTATUS_SPIE | SBI_SSE_ATTR_INTERRUPTED_FLAGS_SSTATUS_SPIE |
SBI_SSE_ATTR_INTERRUPTED_FLAGS_HSTATUS_SPV | SBI_SSE_ATTR_INTERRUPTED_FLAGS_HSTATUS_SPV |
SBI_SSE_ATTR_INTERRUPTED_FLAGS_HSTATUS_SPVP | SBI_SSE_ATTR_INTERRUPTED_FLAGS_HSTATUS_SPVP |
SBI_SSE_ATTR_INTERRUPTED_FLAGS_SSTATUS_SPELP)) SBI_SSE_ATTR_INTERRUPTED_FLAGS_SSTATUS_SPELP |
SBI_SSE_ATTR_INTERRUPTED_FLAGS_SSTATUS_SDT))
return SBI_EINVAL; return SBI_EINVAL;
__attribute__((__fallthrough__)); __attribute__((__fallthrough__));
case SBI_SSE_ATTR_INTERRUPTED_SEPC: case SBI_SSE_ATTR_INTERRUPTED_SEPC:
@@ -525,6 +526,8 @@ static unsigned long sse_interrupted_flags(unsigned long mstatus)
flags |= SBI_SSE_ATTR_INTERRUPTED_FLAGS_SSTATUS_SPP; flags |= SBI_SSE_ATTR_INTERRUPTED_FLAGS_SSTATUS_SPP;
if (mstatus & MSTATUS_SPELP) if (mstatus & MSTATUS_SPELP)
flags |= SBI_SSE_ATTR_INTERRUPTED_FLAGS_SSTATUS_SPELP; flags |= SBI_SSE_ATTR_INTERRUPTED_FLAGS_SSTATUS_SPELP;
if (mstatus & MSTATUS_SDT)
flags |= SBI_SSE_ATTR_INTERRUPTED_FLAGS_SSTATUS_SDT;
if (misa_extension('H')) { if (misa_extension('H')) {
hstatus = csr_read(CSR_HSTATUS); hstatus = csr_read(CSR_HSTATUS);
@@ -584,10 +587,11 @@ static void sse_event_inject(struct sbi_sse_event *e,
/* /*
* Return to S-mode with virtualization disabled, not expected landing * Return to S-mode with virtualization disabled, not expected landing
* pad. * pad, supervisor trap disabled.
*/ */
regs->mstatus &= ~(MSTATUS_MPP | MSTATUS_SIE | MSTATUS_SPELP); regs->mstatus &= ~(MSTATUS_MPP | MSTATUS_SIE | MSTATUS_SPELP);
regs->mstatus |= (PRV_S << MSTATUS_MPP_SHIFT); regs->mstatus |= (PRV_S << MSTATUS_MPP_SHIFT);
regs->mstatus |= MSTATUS_SDT;
#if __riscv_xlen == 64 #if __riscv_xlen == 64
regs->mstatus &= ~MSTATUS_MPV; regs->mstatus &= ~MSTATUS_MPV;
@@ -649,6 +653,10 @@ static void sse_event_resume(struct sbi_sse_event *e,
if (i_ctx->flags & SBI_SSE_ATTR_INTERRUPTED_FLAGS_SSTATUS_SPELP) if (i_ctx->flags & SBI_SSE_ATTR_INTERRUPTED_FLAGS_SSTATUS_SPELP)
regs->mstatus |= MSTATUS_SPELP; regs->mstatus |= MSTATUS_SPELP;
regs->mstatus &= ~MSTATUS_SDT;
if (i_ctx->flags & SBI_SSE_ATTR_INTERRUPTED_FLAGS_SSTATUS_SDT)
regs->mstatus |= MSTATUS_SDT;
regs->a7 = i_ctx->a7; regs->a7 = i_ctx->a7;
regs->a6 = i_ctx->a6; regs->a6 = i_ctx->a6;
csr_write(CSR_SEPC, i_ctx->sepc); csr_write(CSR_SEPC, i_ctx->sepc);