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
