SRET doesn't clear mstatus.MPRV, but it should always clear it.
The privileged spec, on xRET:
"When executing an xRET instruction, supposing xPP holds the value y, xIE is set to xPIE; the privilege mode is changed to y; xPIE is set to 1; and xPP is set to the least-privileged supported mode (U if U-mode is implemented, else M). If y!=M, xRET also sets MPRV=0."
and again in the MPRV description:
"An MRET or SRET instruction that changes the privilege mode to a mode less privileged than M also sets MPRV=0."
In riscv_emulate_opc_system() the MRET path does this (it clears MPRV when next_priv < M), but the SRET path doesn't clear MPRV at all. And for SRET the return mode y is just SPP, which is one bit - so it's always U or S, always less privileged than M. That means SRET should clear MPRV unconditionally, and right now it never does.
Low impact in practice, since MPRV is written from M-mode and an SRET arriving with MPRV still set is an unusual flow, but it's a real spec deviation: a stale MPRV=1 after SRET keeps loads/stores using MPP's translation/protection in S/U mode.
Fix is a one-liner in the SRET case mirroring MRET: clear CSR_STATUS_MPRV.
SRET doesn't clear mstatus.MPRV, but it should always clear it.
The privileged spec, on xRET:
"When executing an xRET instruction, supposing xPP holds the value y, xIE is set to xPIE; the privilege mode is changed to y; xPIE is set to 1; and xPP is set to the least-privileged supported mode (U if U-mode is implemented, else M). If y!=M, xRET also sets MPRV=0."
and again in the MPRV description:
"An MRET or SRET instruction that changes the privilege mode to a mode less privileged than M also sets MPRV=0."
In riscv_emulate_opc_system() the MRET path does this (it clears MPRV when next_priv < M), but the SRET path doesn't clear MPRV at all. And for SRET the return mode y is just SPP, which is one bit - so it's always U or S, always less privileged than M. That means SRET should clear MPRV unconditionally, and right now it never does.
Low impact in practice, since MPRV is written from M-mode and an SRET arriving with MPRV still set is an unusual flow, but it's a real spec deviation: a stale MPRV=1 after SRET keeps loads/stores using MPP's translation/protection in S/U mode.
Fix is a one-liner in the SRET case mirroring MRET: clear CSR_STATUS_MPRV.