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

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

commit cd1e88f9db1c2d6ad91b7cc64f1e17b4f9606486
Author: Marco Casaroli <[email protected]>
AuthorDate: Sun Nov 1 11:31:50 2026 +0100

    arch/x86_64: Give the system call parameters in their registers.
    
    sys_call6() loads the system call number and the six parameters into
    RAX, RDI, RSI, RDX, R10, R8 and R9 with one move each, from operands
    that the compiler may put in any register ("rm").  None of the six
    registers is an output or a clobber, so with optimization the compiler
    can keep a parameter in one of them, and a move before it overwrites
    it.  Then the kernel gets a wrong parameter.
    
    For example qemu-intel64:knsh_romfs with CONFIG_DEBUG_FULLOPT: the
    kernel faults on address 0x27 when init starts.  Without optimization
    every operand is on the stack, so this did not show.
    
    Put each value in its register with a register variable and pass them
    as operands of the syscall instruction.  The kernel can change them, so
    they are outputs too.
    
    Assisted-by: Claude Code:claude-opus-5-5
    Signed-off-by: Marco Casaroli <[email protected]>
---
 arch/x86_64/include/syscall.h | 31 +++++++++++++++----------------
 1 file changed, 15 insertions(+), 16 deletions(-)

diff --git a/arch/x86_64/include/syscall.h b/arch/x86_64/include/syscall.h
index 87acd968925..b4e5d3da235 100644
--- a/arch/x86_64/include/syscall.h
+++ b/arch/x86_64/include/syscall.h
@@ -162,9 +162,17 @@ static inline uintptr_t sys_call6(unsigned int nbr, 
uintptr_t parm1,
                                   uintptr_t parm4, uintptr_t parm5,
                                   uintptr_t parm6)
 {
-  uint64_t ret;
-
-  /* Registers modified by syscall instruction:
+  register uint64_t rax __asm__("rax") = nbr;
+  register uint64_t rdi __asm__("rdi") = parm1;
+  register uint64_t rsi __asm__("rsi") = parm2;
+  register uint64_t rdx __asm__("rdx") = parm3;
+  register uint64_t r10 __asm__("r10") = parm4;
+  register uint64_t r8  __asm__("r8")  = parm5;
+  register uint64_t r9  __asm__("r9")  = parm6;
+
+  /* Each parameter is in its register before the syscall instruction.
+   * The kernel can change them, so they are outputs too.
+   * Registers modified by the syscall instruction:
    *   RCX = RIP
    *   R11 = RFLAGS
    *   RIP = IA32_LSTAR (x86_64_syscall_entry)
@@ -172,23 +180,14 @@ static inline uintptr_t sys_call6(unsigned int nbr, 
uintptr_t parm1,
 
   __asm__ volatile
   (
-    "movl %1, %%eax\n"
-    "movq %2, %%rdi\n"
-    "movq %3, %%rsi\n"
-    "movq %4, %%rdx\n"
-    "movq %5, %%r10\n"
-    "movq %6, %%r8\n"
-    "movq %7, %%r9\n"
     "syscall\n"
-    "movq %%rax, %0\n"
-    : "=r"(ret)
-    : "rm"(nbr), "rm"(parm1), "rm"(parm2),
-      "rm"(parm3), "rm"(parm4), "rm"(parm5),
-      "rm"(parm6)
+    : "+r"(rax), "+r"(rdi), "+r"(rsi), "+r"(rdx), "+r"(r10), "+r"(r8),
+      "+r"(r9)
+    :
     : "memory", "rcx", "r11"
   );
 
-  return ret;
+  return rax;
 }
 
 #ifdef __cplusplus

Reply via email to