Re: Calling syscalls from x86-64 kernel results in a crash on Opteronmachines
From: Brian Gerst
Date: Mon Sep 13 2004 - 10:20:01 EST
Constantine Gavrilov wrote:
Hello:
We have a piece of kernel code that calls some system calls in kernel
context (from a process with mm and a daemonized kernel thread that does
not have mm). This works fine on IA64 and i386 architectures.
When I try this on x86-64 kernel on Opteron machines, it results in
immediate crash. I have tried standard _syscall() macros from
asm/unistd.h. The system panics when returning from the system call.
The disassembled code shows that gcc has often a hard time deciding
which registers (32-bit or 64-bit) it will use. For example, it puts the
system call number to eax, while it should put it to rax. However, this
register thing is not a problem. I have tried my own gcc hand-crafted
inline assembly and glibc inline syscall assembly that results in
"correct" disassembled code. The result is always the same -- kernel
crash when calling a function defined by _syscall() macros or when using
an "inline" block defined by glibc macros.
Attached please find a test module that tries to call the umask() (JUST
TO DEMONSTRATE a problem) via the syscall machanism. Both methods (the
_syscall1() marco and GLIBC INLINE_SYCALL() were used.
The assembly dump of the umask() called via _syscall(1) and via
INLINE_SYSCALL() as well as the disassembly of umask() from glibc are
provided in a separate attachement. The crash dump (captured with a
serial console) is provided along with disassembly of the main module
function.
It seems that segmentation is changed during the syscall and not
restored properly, or some other REALLY BAD THING happens. The entry.S
for x86_64 architecture is very informative, but I am not an expert in
Opteron architecture and I do not know how the syscall instruction is
supposed to work.
Can someone explain the reason for the crash? Can you think of a
workaround? Comments and ideas are very welcome (except of the kind that
it can be implemented in the user space or with a help of a user proxy
process).
You should never use the unistd.h macros from kernel space. Call
sys_foo() directly. This may mean you have to export it. The reason it
crashes is that the "syscall" opcode used by the x86-64 macros (unlike
the "int $0x80" for i386) causes a fault when already running in kernel
space.
--
Brian Gerst
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/