[klibc] i386: use the vdso for system calls on i386
Use the system call entry point in the vdso for system calls on i386.
The vdso can provide either int $0x80, sysenter or syscall depending
on the CPU.
Signed-off-by: H. Peter Anvin <hpa@zytor.com>
diff --git a/usr/klibc/arch/i386/socketcall.S b/usr/klibc/arch/i386/socketcall.S
index a40cc02..44e2004 100644
--- a/usr/klibc/arch/i386/socketcall.S
+++ b/usr/klibc/arch/i386/socketcall.S
@@ -32,7 +32,7 @@
#endif
movl $__NR_socketcall,%eax
- int $0x80
+ call *__syscall_entry
#ifdef _REGPARM
addl $6*4, %esp
diff --git a/usr/klibc/arch/i386/syscall.S b/usr/klibc/arch/i386/syscall.S
index 0dd363b..b7814e8 100644
--- a/usr/klibc/arch/i386/syscall.S
+++ b/usr/klibc/arch/i386/syscall.S
@@ -37,7 +37,7 @@
#endif
.globl __syscall_common_tail
__syscall_common_tail:
- int $0x80
+ call *__syscall_entry
cmpl $-4095,%eax
@@ -66,3 +66,17 @@
__syscall_varadic = __syscall_common
#endif
+
+ .align 4
+__syscall_int80:
+ int $0x80
+ ret
+ .type __syscall_int80,@function
+ .size __syscall_int80,.-__syscall_int80
+
+ .data
+ .align 4
+ .globl __syscall_entry
+__syscall_entry:
+ .long __syscall_int80
+ .size __syscall_entry,.-__syscall_entry
diff --git a/usr/klibc/arch/i386/vfork.S b/usr/klibc/arch/i386/vfork.S
index c98ba3a..d32b9b9 100644
--- a/usr/klibc/arch/i386/vfork.S
+++ b/usr/klibc/arch/i386/vfork.S
@@ -4,7 +4,10 @@
# vfork is nasty - there must be nothing at all on the stack above
# the stack frame of the enclosing function.
#
-
+# We *MUST* use int $0x80, because calling the vdso would screw up
+# our stack handling.
+#
+
#include <asm/unistd.h>
.text
@@ -14,7 +17,7 @@
vfork:
popl %edx /* Return address */
movl $__NR_vfork, %eax
- int $0x80
+ int $0x80 /* DO NOT call the vdso here! */
pushl %edx
cmpl $-4095, %eax
jae 1f
diff --git a/usr/klibc/libc_init.c b/usr/klibc/libc_init.c
index 1087f95..1c6180b 100644
--- a/usr/klibc/libc_init.c
+++ b/usr/klibc/libc_init.c
@@ -90,6 +90,15 @@
__page_size = page_size = __auxval[AT_PAGESZ];
+#ifdef __i386__
+ {
+ extern void (*__syscall_entry)(int, ...);
+ if (__auxval[AT_SYSINFO])
+ __syscall_entry = (void (*)(int, ...))
+ __auxval[AT_SYSINFO];
+ }
+#endif
+
#if __GNUC__ >= 4
/* unsigned int is 32 bits on all our architectures */
page_shift = __builtin_clz(page_size) ^ 31;