This is an automated email from the ASF dual-hosted git repository.

acassis pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git

commit a5bf9ad9c96a45a1959ffac020e9aab3b6ddadc1
Author: raiden00pl <[email protected]>
AuthorDate: Tue Sep 1 11:34:33 2026 +0200

    arch/intel64: iretq directly from the register save area
    
    x86_64_fullcontextrestore() built the iretq frame by pushing onto the
    current stack.  When called from up_switch_context()/up_exit() that is
    the outgoing task's stack, and the outgoing task may already be running
    on another CPU, whose pushes clobber the frame before iretq consumes it,
    causing a #GP/#PF panic under SMP load.
    
    REG_RIP..REG_SS are contiguous and match the iretq frame layout, so
    point RSP at the register save area and iretq from there without
    touching the stack at all.
    
    Assisted-by: Claude Code
    Signed-off-by: raiden00pl <[email protected]>
---
 .../src/intel64/intel64_fullcontextrestore.S       | 45 ++++++----------------
 1 file changed, 12 insertions(+), 33 deletions(-)

diff --git a/arch/x86_64/src/intel64/intel64_fullcontextrestore.S 
b/arch/x86_64/src/intel64/intel64_fullcontextrestore.S
index 4b5427d8c52..a52c0dfc2fc 100644
--- a/arch/x86_64/src/intel64/intel64_fullcontextrestore.S
+++ b/arch/x86_64/src/intel64/intel64_fullcontextrestore.S
@@ -64,38 +64,11 @@ x86_64_fullcontextrestore:
        xrstor   (%rdi)
 #endif
 
-       /* Create an interrupt stack frame for the final iret.
-       *
-       *
-       *                  IRET STACK
-       *               ---------------
-       * RSP Before ->
-       *                  SS
-       *                  RSP
-       *                  RFLAGS
-       *                  CS
-       * RSP After  ->    RIP
-       *
-       */
-
-       movq    (8*REG_SS)(%rdi), %rbx
-       push    %rbx
-       movq    (8*REG_RSP)(%rdi), %rbx
-       push    %rbx
-
-       movq    (8*REG_RFLAGS)(%rdi), %rbx
-       push    %rbx
-       movq    (8*REG_CS)(%rdi), %rbx
-       push    %rbx
-       movq    (8*REG_RIP)(%rdi), %rbx
-       push    %rbx
-
-       /* Save the value of RDI on the stack too */
+       /* Restore the remaining registers.  The current stack may belong to
+        * the outgoing task, which can already be running on another CPU, so
+        * it must not be written from here on.
+        */
 
-       movq    (8*REG_RDI)(%rdi), %rbx
-       push    %rbx
-
-       /* Now restore the remaining registers */
        movq    (8*REG_RSI)(%rdi), %rsi
        movq    (8*REG_RDX)(%rdi), %rdx
        movq    (8*REG_RCX)(%rdi), %rcx
@@ -132,11 +105,17 @@ x86_64_fullcontextrestore:
 
        movq    (8*REG_RAX)(%rdi), %rax
 
+       /* REG_RIP..REG_SS are contiguous and match the iretq frame layout,
+        * so iretq can pop them straight from the register save area.
+        */
+
+       leaq    (8*REG_RIP)(%rdi), %rsp
+
        /* Restore the correct value of RDI */
 
-       popq    %rdi
+       movq    (8*REG_RDI)(%rdi), %rdi
 
-       /* Pops 5 things at once: RIP, CS, RFLAGS RSP and SS */
+       /* Pops 5 things at once: RIP, CS, RFLAGS, RSP and SS */
 
        iretq
        .size x86_64_fullcontextrestore, . - x86_64_fullcontextrestore

Reply via email to