From 715375405457d51741b8f56adedcbe4ebb15b068 Mon Sep 17 00:00:00 2001 From: xuxingliang Date: Thu, 25 Dec 2025 22:43:06 +0800 Subject: [PATCH] arch/armv8-m: Fix IRQ number corruption in exception_direct with O2 optimization 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. Signed-off-by: xuxingliang --- arch/arm/src/armv8-m/arm_doirq.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/src/armv8-m/arm_doirq.c b/arch/arm/src/armv8-m/arm_doirq.c index a86de9f7e78e1..5f902b1edacad 100644 --- a/arch/arm/src/armv8-m/arm_doirq.c +++ b/arch/arm/src/armv8-m/arm_doirq.c @@ -55,6 +55,7 @@ void exception_direct(void) "vmsr fpscr, r0\n" : : "i" (ARMV8M_FPSCR_LTPSIZE_NONE) + : "r0" ); #endif