Synchronous debug reasons handled before taking interrupt enabled via instruction
Created by: Silabs-ArjanB
When an mret instruction or CSR write globally (re-)enables a locally enabled and pending interrupt, a following ebreak instruction can cause debug mode entry although it should have been cancelled by the interrupt. This is basically the same issue as https://github.com/openhwgroup/cv32e40x/issues/325, but that issue had only been fixed for load/store instructions following re-enabling of interrupts.
We should reconsider the implementation of all synchronous debug entry reasons (not only ebreak). We currently have all debug entry reasons prioritized above all (non-NMI) interrupt entry reasons. We need to double check if that was an arbitrary choice or whether that is implied by some RISC-V spec.
Possible fixes include:
- Detecting synchronous debug entry cases after re-enable/disable of IRQs and cause stall cycle such that interrupt can be taken before debug entry reason enters WB.
- Change priority between IRQs and synchronous debug entry reasons in main FSM (if not specified otherwise by RISC-V)
- mstatus.ie=0 and we execute an mret instruction 2. Interrupts are already pending (MSWInterrupt) and the target address of the interrupt is 0x0000_000c (j 0x6b2e) 3. mepc=0x0000_5fea (c.ebreak)
So should the processor execute the jump at 0xc having taken the interrupt, or the c.ebreak at target fetch address of 0x5fea
the REF model executes the pending interrupt, once enabled after executing the mret the RTL executes the c.ebreak and goes into debug mode.
before execution of mret MEPC=0x00005FEA (0x5fea: 9002 c.ebreak) MIP=0x4E3C0088 MSTATUS=0x0001880 (mpie=1)
after execution of mret MSTATUS=0x0001888 (mie=0->1)
So I would expect the pending interrupt mip[3] to be taken, not the c.ebreak at the next fetch address of the mepc This looks very much like the issue we saw with Loads/Stores executing before an interrupt being taken after executing an mret which re-enabled the interrupts