X-Git-Url: http://v3vee.org/palacios/gitweb/gitweb.cgi?a=blobdiff_plain;f=kitten%2Farch%2Fx86_64%2Fkernel%2Fvsyscall.c;fp=kitten%2Farch%2Fx86_64%2Fkernel%2Fvsyscall.c;h=c022ece300f2f0d1a0485213ff3f64388c33700f;hb=66a1a4c7a9edcd7d8bc207aca093d694a6e6b5b2;hp=0000000000000000000000000000000000000000;hpb=f7cf9c19ecb0a589dd45ae0d2c91814bd3c2acc2;p=palacios-OLD.git diff --git a/kitten/arch/x86_64/kernel/vsyscall.c b/kitten/arch/x86_64/kernel/vsyscall.c new file mode 100644 index 0000000..c022ece --- /dev/null +++ b/kitten/arch/x86_64/kernel/vsyscall.c @@ -0,0 +1,71 @@ +/* + * Derived from Linux 2.6.25 linux-2.6.25/arch/x86/kernel/vsyscall.c + * Original header: + * Copyright (C) 2001 Andrea Arcangeli SuSE + * Copyright 2003 Andi Kleen, SuSE Labs. + * + * Thanks to hpa@transmeta.com for some useful hint. + * Special thanks to Ingo Molnar for his early experience with + * a different vsyscall implementation for Linux/IA32 and for the name. + * + * vsyscall 1 is located at -10Mbyte, vsyscall 2 is located + * at virtual address -10Mbyte+1024bytes etc... There are at max 4 + * vsyscalls. One vsyscall can reserve more than 1 slot to avoid + * jumping out of line if necessary. We cannot add more with this + * mechanism because older kernels won't return -ENOSYS. + * If we want more than four we need a vDSO. + * + * Note: the concept clashes with user mode linux. If you use UML and + * want per guest time just set the kernel.vsyscall64 sysctl to 0. + */ + +#include +#include +#include +#include +#include +#include +#include + +#define __vsyscall(nr) __attribute__ ((unused,__section__(".vsyscall_" #nr))) +#define __syscall_clobber "r11","cx","memory" + +int __vsyscall(0) +vgettimeofday(struct timeval *tv, struct timezone *tz) +{ + int ret; + asm volatile("syscall" + : "=a" (ret) + : "0" (__NR_gettimeofday),"D" (tv),"S" (tz) + : __syscall_clobber ); + return ret; +} + +time_t __vsyscall(1) +vtime(time_t *t) +{ + int ret; + asm volatile("syscall" + : "=a" (ret) + : "0" (__NR_time),"D" (t) + : __syscall_clobber ); + return ret; +} + +void __init +vsyscall_map(void) +{ + extern char __vsyscall_0; + unsigned long physaddr_page0 = __pa_symbol(&__vsyscall_0); + + /* Setup the virtual syscall fixmap entry */ + __set_fixmap(VSYSCALL_FIRST_PAGE, physaddr_page0, PAGE_KERNEL_VSYSCALL); + + BUG_ON((VSYSCALL_ADDR(0) != __fix_to_virt(VSYSCALL_FIRST_PAGE))); + + BUG_ON((unsigned long) &vgettimeofday != + VSYSCALL_ADDR(__NR_vgettimeofday)); + BUG_ON((unsigned long) &vtime != + VSYSCALL_ADDR(__NR_vtime)); +} +