2 * Derived from Linux 2.6.25 linux-2.6.25/arch/x86/kernel/vsyscall.c
4 * Copyright (C) 2001 Andrea Arcangeli <andrea@suse.de> SuSE
5 * Copyright 2003 Andi Kleen, SuSE Labs.
7 * Thanks to hpa@transmeta.com for some useful hint.
8 * Special thanks to Ingo Molnar for his early experience with
9 * a different vsyscall implementation for Linux/IA32 and for the name.
11 * vsyscall 1 is located at -10Mbyte, vsyscall 2 is located
12 * at virtual address -10Mbyte+1024bytes etc... There are at max 4
13 * vsyscalls. One vsyscall can reserve more than 1 slot to avoid
14 * jumping out of line if necessary. We cannot add more with this
15 * mechanism because older kernels won't return -ENOSYS.
16 * If we want more than four we need a vDSO.
18 * Note: the concept clashes with user mode linux. If you use UML and
19 * want per guest time just set the kernel.vsyscall64 sysctl to 0.
22 #include <lwk/kernel.h>
25 #include <lwk/unistd.h>
26 #include <arch/vsyscall.h>
27 #include <arch/pgtable.h>
28 #include <arch/fixmap.h>
30 #define __vsyscall(nr) __attribute__ ((unused,__section__(".vsyscall_" #nr)))
31 #define __syscall_clobber "r11","cx","memory"
34 vgettimeofday(struct timeval *tv, struct timezone *tz)
37 asm volatile("syscall"
39 : "0" (__NR_gettimeofday),"D" (tv),"S" (tz)
40 : __syscall_clobber );
48 asm volatile("syscall"
50 : "0" (__NR_time),"D" (t)
51 : __syscall_clobber );
58 extern char __vsyscall_0;
59 unsigned long physaddr_page0 = __pa_symbol(&__vsyscall_0);
61 /* Setup the virtual syscall fixmap entry */
62 __set_fixmap(VSYSCALL_FIRST_PAGE, physaddr_page0, PAGE_KERNEL_VSYSCALL);
64 BUG_ON((VSYSCALL_ADDR(0) != __fix_to_virt(VSYSCALL_FIRST_PAGE)));
66 BUG_ON((unsigned long) &vgettimeofday !=
67 VSYSCALL_ADDR(__NR_vgettimeofday));
68 BUG_ON((unsigned long) &vtime !=
69 VSYSCALL_ADDR(__NR_vtime));