Skip to content

Fixed MPIE being cleared leading to have interrupts being disable after an mret instruction#522

Open
cpdpls wants to merge 2 commits intoeclipse-threadx:devfrom
cpdpls:dev
Open

Fixed MPIE being cleared leading to have interrupts being disable after an mret instruction#522
cpdpls wants to merge 2 commits intoeclipse-threadx:devfrom
cpdpls:dev

Conversation

@cpdpls
Copy link
Copy Markdown

@cpdpls cpdpls commented Apr 14, 2026

Fixed #517

  1. MPIE was being cleared alongside MIE before issuing an mret instruction. As a side effect, this led to have no interruptions enabled forever when returning from the very first context switching.
  2. Removed some assembly leftovers from the previous ports when changing the mstatus register inside the _tx_thread_context_restore routine

PR checklist

  • Updated function header with a short description and version number
  • Added test case for bug fix or new feature
  • Validated on real hardware (Microchip Polarfire SOC -- riscv64-unknown-elf-gcc (xPack GNU RISC-V Embedded GCC (Microsemi SoftConsole build), 64-bit) 8.3.0

@fdesbiens fdesbiens requested a review from akifejaz April 14, 2026 20:57
@fdesbiens fdesbiens moved this to In review in ThreadX Roadmap Apr 14, 2026
@fdesbiens
Copy link
Copy Markdown
Contributor

Thank you for the detailed bug report and the fix @cpdpls — the root cause analysis is correct. Clearing MPIE before mret is indeed the culprit: mret copies MPIE→MIE, so with MPIE=0 interrupts are permanently disabled after the first context switch.

However, the fix seems to introduce a new logic error in both modified hunks.

The problem

 li      t2, 0x1880        // Set MPP(0x1800) | MPIE(0x80)
 li      t3, ~0x8          // Preserve all bits except MIE   ← computed but never read
 
 or      t1, t1, t2        // MPP and MPIE are now set       ✅
 and     t1, t1, t2        // Clear MIE                      ❌ wrong register

The and uses t2 (value 0x1880) instead of t3 (value ~0x8). ANDing with 0x1880 zeros every mstatus bit except MPP and MPIE, corrupting fields like FS (bits 14:13), VS (bits 10:9), MPRV (bit 17), and others. The FP and vector #if blocks below happen to re-set FS and VS, partially hiding the problem in those build variants — but the base (no FP, no vector) build is left with a corrupted mstatus.

t3 is loaded but never used — the same dead-register issue the PR description notes about the original code.

The same logic appears in both the _tx_thread_context_restore and _tx_thread_no_preempt_restore hunks.

Suggested fix:

Since ~0x8 = -9 fits within RISC-V's 12-bit signed andi immediate range, t3 can be dropped entirely:

 csrr    t1, mstatus
 li      t2, 0x1880        // MPP(0x1800) | MPIE(0x80)
 or      t1, t1, t2        // Set MPP and MPIE
 andi    t1, t1, ~0x8      // Clear only MIE (bit 3); preserve all other mstatus bits

Apply the same three-instruction sequence to both hunks.

What do you think?

@cpdpls
Copy link
Copy Markdown
Author

cpdpls commented Apr 18, 2026

Hello @fdesbiens,

Indeed, I somehow reused T2 both inside the AND and the OR instruction. My intention was to use T3 with the AND instruction … I feel a bit ashamed that I let that one through though.

Thank you for reviewing though, I totally agree with the provided solution and will update the PR immediately.

Sorry again for that embarrassing mistake.

@cpdpls
Copy link
Copy Markdown
Author

cpdpls commented Apr 18, 2026

PR has been updated with the new suggestions. Thanks again for the review

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: In review

Development

Successfully merging this pull request may close these issues.

2 participants