aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kernel/vsyscall_64.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/x86/kernel/vsyscall_64.c')
-rw-r--r--arch/x86/kernel/vsyscall_64.c52
1 files changed, 3 insertions, 49 deletions
diff --git a/arch/x86/kernel/vsyscall_64.c b/arch/x86/kernel/vsyscall_64.c
index 3f8242774580..b6be812fac05 100644
--- a/arch/x86/kernel/vsyscall_64.c
+++ b/arch/x86/kernel/vsyscall_64.c
@@ -44,11 +44,6 @@
44 44
45#define __vsyscall(nr) __attribute__ ((unused,__section__(".vsyscall_" #nr))) 45#define __vsyscall(nr) __attribute__ ((unused,__section__(".vsyscall_" #nr)))
46#define __syscall_clobber "r11","cx","memory" 46#define __syscall_clobber "r11","cx","memory"
47#define __pa_vsymbol(x) \
48 ({unsigned long v; \
49 extern char __vsyscall_0; \
50 asm("" : "=r" (v) : "0" (x)); \
51 ((v - VSYSCALL_START) + __pa_symbol(&__vsyscall_0)); })
52 47
53/* 48/*
54 * vsyscall_gtod_data contains data that is : 49 * vsyscall_gtod_data contains data that is :
@@ -102,7 +97,7 @@ static __always_inline void do_get_tz(struct timezone * tz)
102static __always_inline int gettimeofday(struct timeval *tv, struct timezone *tz) 97static __always_inline int gettimeofday(struct timeval *tv, struct timezone *tz)
103{ 98{
104 int ret; 99 int ret;
105 asm volatile("vsysc2: syscall" 100 asm volatile("syscall"
106 : "=a" (ret) 101 : "=a" (ret)
107 : "0" (__NR_gettimeofday),"D" (tv),"S" (tz) 102 : "0" (__NR_gettimeofday),"D" (tv),"S" (tz)
108 : __syscall_clobber ); 103 : __syscall_clobber );
@@ -112,7 +107,7 @@ static __always_inline int gettimeofday(struct timeval *tv, struct timezone *tz)
112static __always_inline long time_syscall(long *t) 107static __always_inline long time_syscall(long *t)
113{ 108{
114 long secs; 109 long secs;
115 asm volatile("vsysc1: syscall" 110 asm volatile("syscall"
116 : "=a" (secs) 111 : "=a" (secs)
117 : "0" (__NR_time),"D" (t) : __syscall_clobber); 112 : "0" (__NR_time),"D" (t) : __syscall_clobber);
118 return secs; 113 return secs;
@@ -227,50 +222,10 @@ long __vsyscall(3) venosys_1(void)
227} 222}
228 223
229#ifdef CONFIG_SYSCTL 224#ifdef CONFIG_SYSCTL
230
231#define SYSCALL 0x050f
232#define NOP2 0x9090
233
234/*
235 * NOP out syscall in vsyscall page when not needed.
236 */
237static int vsyscall_sysctl_change(ctl_table *ctl, int write, struct file * filp,
238 void __user *buffer, size_t *lenp, loff_t *ppos)
239{
240 extern u16 vsysc1, vsysc2;
241 u16 __iomem *map1;
242 u16 __iomem *map2;
243 int ret = proc_dointvec(ctl, write, filp, buffer, lenp, ppos);
244 if (!write)
245 return ret;
246 /* gcc has some trouble with __va(__pa()), so just do it this
247 way. */
248 map1 = ioremap(__pa_vsymbol(&vsysc1), 2);
249 if (!map1)
250 return -ENOMEM;
251 map2 = ioremap(__pa_vsymbol(&vsysc2), 2);
252 if (!map2) {
253 ret = -ENOMEM;
254 goto out;
255 }
256 if (!vsyscall_gtod_data.sysctl_enabled) {
257 writew(SYSCALL, map1);
258 writew(SYSCALL, map2);
259 } else {
260 writew(NOP2, map1);
261 writew(NOP2, map2);
262 }
263 iounmap(map2);
264out:
265 iounmap(map1);
266 return ret;
267}
268
269static ctl_table kernel_table2[] = { 225static ctl_table kernel_table2[] = {
270 { .procname = "vsyscall64", 226 { .procname = "vsyscall64",
271 .data = &vsyscall_gtod_data.sysctl_enabled, .maxlen = sizeof(int), 227 .data = &vsyscall_gtod_data.sysctl_enabled, .maxlen = sizeof(int),
272 .mode = 0644, 228 .mode = 0644 },
273 .proc_handler = vsyscall_sysctl_change },
274 {} 229 {}
275}; 230};
276 231
@@ -279,7 +234,6 @@ static ctl_table kernel_root_table2[] = {
279 .child = kernel_table2 }, 234 .child = kernel_table2 },
280 {} 235 {}
281}; 236};
282
283#endif 237#endif
284 238
285/* Assume __initcall executes before all user space. Hopefully kmod 239/* Assume __initcall executes before all user space. Hopefully kmod