Skip to content

Conversation

@XuNeo
Copy link
Contributor

@XuNeo XuNeo commented Dec 26, 2025

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:

  • getipsr() correctly reads IPSR (e.g., 0xf for IRQ 15)
  • Compiler optimizes and reuses r0 for ARM_FPSCR_LTPSIZE_NONE (0x40000)
  • irq variable gets the wrong value 0x40000 instead of actual IRQ number
  • This leads to assertion failures in irq_dispatch due to invalid IRQ

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

cmake -Bbuild -GNinja -DBOARD_CONFIG=mps3-an547:nsh nuttx

menuconfig to enable DEBUG_FULLOPT

ninja -C build
qemu-system-arm -M mps3-an547 -m 2G -nographic -kernel build/nuttx

Before

irq_unexpected_isr: ERROR irq: 262144
dump_assert_info: Current Version: NuttX  12.11.0 28da499a7e2 Dec 26 2025 10:55:24 arm
dump_assert_info: Assertion failed panic: at file: /sched/irq/irq_unexpectedisr.c:56 task: Idle_Task process: Kernel 0x413d
up_dump_register: R0: 01001a40 R1: 00000038 R2: 000205bb  R3: 00000007
up_dump_register: R4: 00040000 R5: 01000ecc R6: 01000fa8  FP: 00000000
up_dump_register: R8: 000205bb SB: 00020fac SL: 00000038 R11: 00000003
up_dump_register: IP: 00000002 SP: 01000ad0 LR: 000047a1  PC: 000047a1
up_dump_register: xPSR: 6000000f BASEPRI: 00000080 CONTROL: 00000000
up_dump_register: EXC_RETURN: 00000000
dump_stackinfo: IRQ Stack:
dump_stackinfo:   base: 0x1000400
dump_stackinfo:   size: 00002048
dump_stackinfo:     sp: 0x1000ad0
stack_dump: 0x1000ab0: 000212c0 01000ad0 01000ecc 01000fa8 01000400 01003684 00000ff0 00004899
stack_dump: 0x1000ad0: 00000254 00000038 01000f78 000210ad 0000413d 00000000 00000000 00000000
stack_dump: 0x1000af0: 01000ecc 01001a40 000205bb 00020fac 00000038 7474754e 00000058 00003021
stack_dump: 0x1000b10: deadbeef 01000bc8 dead00ef 00020fab deadbeef deadbeef 32313434 dead3236
stack_dump: 0x1000b30: deadbeef deadbeef 2e323100 302e3131 deadbe00 01000ba4 000044b1 38320000
stack_dump: 0x1000b50: 39346164 65376139 65442032 36322063 32303220 30312035 3a35353a 00003432
stack_dump: 0x1000b70: 01000bc0 00008791 deadbeef 00020f99 6d7261ef 00000000 00009b5d 00009b1d
stack_dump: 0x1000b90: 00002ff1 0000000a 00000003 00040000 000044b1 00000000 00000000 00000001
stack_dump: 0x1000bb0: 00000000 00000000 00000000 00002af7 0000000a 000044d3 e0001000 0000447b
stack_dump: 0x1000bd0: 00040000 00000000 00000000 01004678 7ffffff0 60000000 80000000 0000038d
stack_dump: 0x1000bf0: 00000000 00040000 00000000 ffffffed 00000000 00000000 00000000 00000000
dump_stacks: ERROR: Stack pointer 1004674 is not within the stack
dump_stackinfo: User Stack:
dump_stackinfo:   base: 0x1003684
dump_stackinfo:   size: 00004080
stack_dump: 0x10045b4: 01000144 000003e8 00000000 00000009 7ffffff0 7ffffff0 60000008 00000002
stack_dump: 0x10045d4: 00002cbd 0000a1f6 21000200 00000000 00000000 00000000 00000000 00000000
stack_dump: 0x10045f4: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
stack_dump: 0x1004614: 00000000 00000000 00000000 00040000 00000000 0000a189 01000ec4 00000000
stack_dump: 0x1004634: 01000ecc 00000000 01000fa8 00008393 01002678 000042bb 01004674 001fb98c
stack_dump: 0x1004654: 00000000 00000000 00000000 00000000 00000000 000002c3 00000000 00000000
stack_dump: 0x1004674: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
dump_tasks:    PID GROUP PRI POLICY   TYPE    NPX STATE   EVENT      SIGMASK          STACKBASE  STACKSIZE      USED   FILLED    COMMAND
dump_tasks:   ----   --- --- -------- ------- --- ------- ---------- ---------------- 0x1000400      2048       636    31.0%    irq
dump_task:       0     0   0 FIFO     Kthread -   Running            0000000000000000 0x1003684      4080       192     4.7%    Idle_Task

After, works as normal.

…ptimization

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:
- getipsr() correctly reads IPSR (e.g., 0xf for IRQ 15)
- Compiler optimizes and reuses r0 for ARM_FPSCR_LTPSIZE_NONE (0x40000)
- irq variable gets the wrong value 0x40000 instead of actual IRQ number
- This leads to assertion failures in irq_dispatch due to invalid IRQ

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, apache#4]      ; Store corrupted 0x40000 as irq
  ...
  ldr r0, [sp, apache#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.

Signed-off-by: xuxingliang <[email protected]>
@XuNeo XuNeo requested a review from GUIDINGLI as a code owner December 26, 2025 02:58
@github-actions github-actions bot added Arch: arm Issues related to ARM (32-bit) architecture Size: XS The size of the change in this PR is very small labels Dec 26, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Arch: arm Issues related to ARM (32-bit) architecture Size: XS The size of the change in this PR is very small

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants