Matteo Concas created an issue: 
https://gitlab.rtems.org/rtems/rtos/rtems/-/issues/5274



## Summary

It seems the current RISC-V implementation isn't compatible with processors 
using the Smdbltrp extension. This extension introduces the MDT 
(M-mode-disable-trap) bit in the status register which is set when a trap is 
taken in M mode. If MDT is set then the MIE (Machine Interrupt Enable) bit 
cannot be set so the MDT bit needs to be cleared at some point.

>From section 3.6.1.2 of the RISC-V Instruction Set Manual Volume II:

> The M-mode-disable-trap (MDT) bit is a WARL field introduced by the Smdbltrp 
> extension. Upon reset, the MDT field is set to 1. When the MDT bit is set to 
> 1 by an explicit CSR write, the MIE (Machine Interrupt Enable) bit is cleared 
> to 0. For RV64, this clearing occurs regardless of the value written, if any, 
> to the MIE bit by the same write. The MIE bit can only be set to 1 by an 
> explicit CSR write if the MDT bit is already 0 or, for RV64, is being set to 
> 0 by the same write (For RV32, the MDT bit is in mstatush and the MIE bit in 
> mstatus register).
>
> When a trap is to be taken into M-mode, if the MDT bit is currently 0, it is 
> then set to 1, and the trap is delivered as expected. However, if MDT is 
> already set to 1, then this is an unexpected trap. When the Smrnmi extension 
> is implemented, a trap caused by an RNMI is not considered an unexpected trap 
> irrespective of the state of the MDT bit. A trap caused by an RNMI does not 
> set the MDT bit. However, a trap that occurs when executing in M-mode with 
> mnstatus.NMIE set to 0 is an unexpected trap. 

This means a call to `_Thread_Do_dispatch` might result in a 
`INTERNAL_ERROR_BAD_THREAD_DISPATCH_ENVIRONMENT` error because it checks if 
interrupts are disabled by looking at the MIE bit.

We fixed it with this quick patch:

```diff
diff --git a/cpukit/score/cpu/riscv/riscv-exception-handler.S 
b/cpukit/score/cpu/riscv/riscv-exception-handler.S
index 34e7cbb0b3..8d36f36741 100644
--- a/cpukit/score/cpu/riscv/riscv-exception-handler.S
+++ b/cpukit/score/cpu/riscv/riscv-exception-handler.S
@@ -161,6 +161,10 @@ SYM(_RISCV_Exception_handler):
     sw    t0, PER_CPU_ISR_DISPATCH_DISABLE(s0)
     sw    t0, PER_CPU_THREAD_DISPATCH_DISABLE_LEVEL(s0)
 
+    /* Clear MDT bit */
+    li    t0, (1 << 42)
+    csrrc    zero, mstatus, t0
+
     /* Call _Thread_Do_dispatch(), this function will enable interrupts */
     mv    a0, s0
     li    a1, RISCV_MSTATUS_MIE
```

This will clear the MDT bit before `_Thread_Do_dispatch()` is called.

It would probably be good to discuss how to properly implement this.

-- 
View it on GitLab: https://gitlab.rtems.org/rtems/rtos/rtems/-/issues/5274
You're receiving this email because of your account on gitlab.rtems.org.


_______________________________________________
bugs mailing list
[email protected]
http://lists.rtems.org/mailman/listinfo/bugs

Reply via email to