arch/armv8-m: Fix IRQ number corruption in exception_direct with O2 optimization #17684
+1
−0
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Summary
Fix wrong irq number got from getipsr() when optimization level is changed to above O2.
When compiling with O2 optimization, the compiler optimizes the code
in a way that causes irq variable to be corrupted. The getipsr()
function reads IPSR into r0, but the subsequent inline assembly that
sets FPSCR also uses r0 without declaring it as clobbered. This causes
the compiler to reuse r0 for the immediate value (0x40000), overwriting
the IRQ number read from IPSR.
The issue manifests as:
Root cause analysis from disassembly:
mrs r0, IPSR ; Read IPSR to r0
mov.w r0, #262144 ; Compiler overwrites r0 with 0x40000!
vmsr fpscr, r0 ; Set FPSCR
str r0, [sp, #4] ; Store corrupted 0x40000 as irq
...
ldr r0, [sp, #4] ; Load corrupted value
bl irq_dispatch ; Call with wrong IRQ number 0x40000
Fix by adding r0 to the clobber list in the inline assembly, which
forces the compiler to save irq value before using r0 for FPSCR setup.
This issue only occurs at O2 optimization level and affects ARMv8-M
architecture with FPU enabled.
Impact
Now it works with DEBUG_FULLOPT.
Testing
menuconfig to enable
DEBUG_FULLOPTBefore
After, works as normal.