aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'arch/x86/kernel')
-rw-r--r--arch/x86/kernel/Makefile2
-rw-r--r--arch/x86/kernel/hpet.c2
-rw-r--r--arch/x86/kernel/tsc.c2
-rw-r--r--arch/x86/kernel/vmlinux.lds.S8
-rw-r--r--arch/x86/kernel/vsyscall_64.c45
-rw-r--r--arch/x86/kernel/vsyscall_gtod.c69
6 files changed, 75 insertions, 53 deletions
diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile
index cb648c84b327..f4d96000d33a 100644
--- a/arch/x86/kernel/Makefile
+++ b/arch/x86/kernel/Makefile
@@ -26,7 +26,7 @@ obj-$(CONFIG_IRQ_WORK) += irq_work.o
26obj-y += probe_roms.o 26obj-y += probe_roms.o
27obj-$(CONFIG_X86_32) += i386_ksyms_32.o 27obj-$(CONFIG_X86_32) += i386_ksyms_32.o
28obj-$(CONFIG_X86_64) += sys_x86_64.o x8664_ksyms_64.o 28obj-$(CONFIG_X86_64) += sys_x86_64.o x8664_ksyms_64.o
29obj-y += syscall_$(BITS).o 29obj-y += syscall_$(BITS).o vsyscall_gtod.o
30obj-$(CONFIG_X86_64) += vsyscall_64.o 30obj-$(CONFIG_X86_64) += vsyscall_64.o
31obj-$(CONFIG_X86_64) += vsyscall_emu_64.o 31obj-$(CONFIG_X86_64) += vsyscall_emu_64.o
32obj-$(CONFIG_SYSFS) += ksysfs.o 32obj-$(CONFIG_SYSFS) += ksysfs.o
diff --git a/arch/x86/kernel/hpet.c b/arch/x86/kernel/hpet.c
index 014618dbaa7b..93eed15a8fd4 100644
--- a/arch/x86/kernel/hpet.c
+++ b/arch/x86/kernel/hpet.c
@@ -752,9 +752,7 @@ static struct clocksource clocksource_hpet = {
752 .mask = HPET_MASK, 752 .mask = HPET_MASK,
753 .flags = CLOCK_SOURCE_IS_CONTINUOUS, 753 .flags = CLOCK_SOURCE_IS_CONTINUOUS,
754 .resume = hpet_resume_counter, 754 .resume = hpet_resume_counter,
755#ifdef CONFIG_X86_64
756 .archdata = { .vclock_mode = VCLOCK_HPET }, 755 .archdata = { .vclock_mode = VCLOCK_HPET },
757#endif
758}; 756};
759 757
760static int hpet_clocksource_register(void) 758static int hpet_clocksource_register(void)
diff --git a/arch/x86/kernel/tsc.c b/arch/x86/kernel/tsc.c
index 7a9296ab8834..57e5ce126d5a 100644
--- a/arch/x86/kernel/tsc.c
+++ b/arch/x86/kernel/tsc.c
@@ -984,9 +984,7 @@ static struct clocksource clocksource_tsc = {
984 .mask = CLOCKSOURCE_MASK(64), 984 .mask = CLOCKSOURCE_MASK(64),
985 .flags = CLOCK_SOURCE_IS_CONTINUOUS | 985 .flags = CLOCK_SOURCE_IS_CONTINUOUS |
986 CLOCK_SOURCE_MUST_VERIFY, 986 CLOCK_SOURCE_MUST_VERIFY,
987#ifdef CONFIG_X86_64
988 .archdata = { .vclock_mode = VCLOCK_TSC }, 987 .archdata = { .vclock_mode = VCLOCK_TSC },
989#endif
990}; 988};
991 989
992void mark_tsc_unstable(char *reason) 990void mark_tsc_unstable(char *reason)
diff --git a/arch/x86/kernel/vmlinux.lds.S b/arch/x86/kernel/vmlinux.lds.S
index da6b35a98260..49edf2dd3613 100644
--- a/arch/x86/kernel/vmlinux.lds.S
+++ b/arch/x86/kernel/vmlinux.lds.S
@@ -147,7 +147,6 @@ SECTIONS
147 _edata = .; 147 _edata = .;
148 } :data 148 } :data
149 149
150#ifdef CONFIG_X86_64
151 150
152 . = ALIGN(PAGE_SIZE); 151 . = ALIGN(PAGE_SIZE);
153 __vvar_page = .; 152 __vvar_page = .;
@@ -165,12 +164,15 @@ SECTIONS
165#undef __VVAR_KERNEL_LDS 164#undef __VVAR_KERNEL_LDS
166#undef EMIT_VVAR 165#undef EMIT_VVAR
167 166
167 /*
168 * Pad the rest of the page with zeros. Otherwise the loader
169 * can leave garbage here.
170 */
171 . = __vvar_beginning_hack + PAGE_SIZE;
168 } :data 172 } :data
169 173
170 . = ALIGN(__vvar_page + PAGE_SIZE, PAGE_SIZE); 174 . = ALIGN(__vvar_page + PAGE_SIZE, PAGE_SIZE);
171 175
172#endif /* CONFIG_X86_64 */
173
174 /* Init code and data - will be freed after init */ 176 /* Init code and data - will be freed after init */
175 . = ALIGN(PAGE_SIZE); 177 . = ALIGN(PAGE_SIZE);
176 .init.begin : AT(ADDR(.init.begin) - LOAD_OFFSET) { 178 .init.begin : AT(ADDR(.init.begin) - LOAD_OFFSET) {
diff --git a/arch/x86/kernel/vsyscall_64.c b/arch/x86/kernel/vsyscall_64.c
index 1f96f9347ed9..9ea287666c65 100644
--- a/arch/x86/kernel/vsyscall_64.c
+++ b/arch/x86/kernel/vsyscall_64.c
@@ -47,14 +47,12 @@
47#include <asm/segment.h> 47#include <asm/segment.h>
48#include <asm/desc.h> 48#include <asm/desc.h>
49#include <asm/topology.h> 49#include <asm/topology.h>
50#include <asm/vgtod.h>
51#include <asm/traps.h> 50#include <asm/traps.h>
52 51
53#define CREATE_TRACE_POINTS 52#define CREATE_TRACE_POINTS
54#include "vsyscall_trace.h" 53#include "vsyscall_trace.h"
55 54
56DEFINE_VVAR(int, vgetcpu_mode); 55DEFINE_VVAR(int, vgetcpu_mode);
57DEFINE_VVAR(struct vsyscall_gtod_data, vsyscall_gtod_data);
58 56
59static enum { EMULATE, NATIVE, NONE } vsyscall_mode = EMULATE; 57static enum { EMULATE, NATIVE, NONE } vsyscall_mode = EMULATE;
60 58
@@ -77,48 +75,6 @@ static int __init vsyscall_setup(char *str)
77} 75}
78early_param("vsyscall", vsyscall_setup); 76early_param("vsyscall", vsyscall_setup);
79 77
80void update_vsyscall_tz(void)
81{
82 vsyscall_gtod_data.sys_tz = sys_tz;
83}
84
85void update_vsyscall(struct timekeeper *tk)
86{
87 struct vsyscall_gtod_data *vdata = &vsyscall_gtod_data;
88
89 write_seqcount_begin(&vdata->seq);
90
91 /* copy vsyscall data */
92 vdata->clock.vclock_mode = tk->clock->archdata.vclock_mode;
93 vdata->clock.cycle_last = tk->clock->cycle_last;
94 vdata->clock.mask = tk->clock->mask;
95 vdata->clock.mult = tk->mult;
96 vdata->clock.shift = tk->shift;
97
98 vdata->wall_time_sec = tk->xtime_sec;
99 vdata->wall_time_snsec = tk->xtime_nsec;
100
101 vdata->monotonic_time_sec = tk->xtime_sec
102 + tk->wall_to_monotonic.tv_sec;
103 vdata->monotonic_time_snsec = tk->xtime_nsec
104 + (tk->wall_to_monotonic.tv_nsec
105 << tk->shift);
106 while (vdata->monotonic_time_snsec >=
107 (((u64)NSEC_PER_SEC) << tk->shift)) {
108 vdata->monotonic_time_snsec -=
109 ((u64)NSEC_PER_SEC) << tk->shift;
110 vdata->monotonic_time_sec++;
111 }
112
113 vdata->wall_time_coarse.tv_sec = tk->xtime_sec;
114 vdata->wall_time_coarse.tv_nsec = (long)(tk->xtime_nsec >> tk->shift);
115
116 vdata->monotonic_time_coarse = timespec_add(vdata->wall_time_coarse,
117 tk->wall_to_monotonic);
118
119 write_seqcount_end(&vdata->seq);
120}
121
122static void warn_bad_vsyscall(const char *level, struct pt_regs *regs, 78static void warn_bad_vsyscall(const char *level, struct pt_regs *regs,
123 const char *message) 79 const char *message)
124{ 80{
@@ -374,7 +330,6 @@ void __init map_vsyscall(void)
374{ 330{
375 extern char __vsyscall_page; 331 extern char __vsyscall_page;
376 unsigned long physaddr_vsyscall = __pa_symbol(&__vsyscall_page); 332 unsigned long physaddr_vsyscall = __pa_symbol(&__vsyscall_page);
377 extern char __vvar_page;
378 unsigned long physaddr_vvar_page = __pa_symbol(&__vvar_page); 333 unsigned long physaddr_vvar_page = __pa_symbol(&__vvar_page);
379 334
380 __set_fixmap(VSYSCALL_FIRST_PAGE, physaddr_vsyscall, 335 __set_fixmap(VSYSCALL_FIRST_PAGE, physaddr_vsyscall,
diff --git a/arch/x86/kernel/vsyscall_gtod.c b/arch/x86/kernel/vsyscall_gtod.c
new file mode 100644
index 000000000000..f9c6e56e14b5
--- /dev/null
+++ b/arch/x86/kernel/vsyscall_gtod.c
@@ -0,0 +1,69 @@
1/*
2 * Copyright (C) 2001 Andrea Arcangeli <andrea@suse.de> SuSE
3 * Copyright 2003 Andi Kleen, SuSE Labs.
4 *
5 * Modified for x86 32 bit architecture by
6 * Stefani Seibold <stefani@seibold.net>
7 * sponsored by Rohde & Schwarz GmbH & Co. KG Munich/Germany
8 *
9 * Thanks to hpa@transmeta.com for some useful hint.
10 * Special thanks to Ingo Molnar for his early experience with
11 * a different vsyscall implementation for Linux/IA32 and for the name.
12 *
13 */
14
15#include <linux/timekeeper_internal.h>
16#include <asm/vgtod.h>
17#include <asm/vvar.h>
18
19DEFINE_VVAR(struct vsyscall_gtod_data, vsyscall_gtod_data);
20
21void update_vsyscall_tz(void)
22{
23 vsyscall_gtod_data.tz_minuteswest = sys_tz.tz_minuteswest;
24 vsyscall_gtod_data.tz_dsttime = sys_tz.tz_dsttime;
25}
26
27void update_vsyscall(struct timekeeper *tk)
28{
29 struct vsyscall_gtod_data *vdata = &vsyscall_gtod_data;
30
31 gtod_write_begin(vdata);
32
33 /* copy vsyscall data */
34 vdata->vclock_mode = tk->clock->archdata.vclock_mode;
35 vdata->cycle_last = tk->clock->cycle_last;
36 vdata->mask = tk->clock->mask;
37 vdata->mult = tk->mult;
38 vdata->shift = tk->shift;
39
40 vdata->wall_time_sec = tk->xtime_sec;
41 vdata->wall_time_snsec = tk->xtime_nsec;
42
43 vdata->monotonic_time_sec = tk->xtime_sec
44 + tk->wall_to_monotonic.tv_sec;
45 vdata->monotonic_time_snsec = tk->xtime_nsec
46 + (tk->wall_to_monotonic.tv_nsec
47 << tk->shift);
48 while (vdata->monotonic_time_snsec >=
49 (((u64)NSEC_PER_SEC) << tk->shift)) {
50 vdata->monotonic_time_snsec -=
51 ((u64)NSEC_PER_SEC) << tk->shift;
52 vdata->monotonic_time_sec++;
53 }
54
55 vdata->wall_time_coarse_sec = tk->xtime_sec;
56 vdata->wall_time_coarse_nsec = (long)(tk->xtime_nsec >> tk->shift);
57
58 vdata->monotonic_time_coarse_sec =
59 vdata->wall_time_coarse_sec + tk->wall_to_monotonic.tv_sec;
60 vdata->monotonic_time_coarse_nsec =
61 vdata->wall_time_coarse_nsec + tk->wall_to_monotonic.tv_nsec;
62
63 while (vdata->monotonic_time_coarse_nsec >= NSEC_PER_SEC) {
64 vdata->monotonic_time_coarse_nsec -= NSEC_PER_SEC;
65 vdata->monotonic_time_coarse_sec++;
66 }
67
68 gtod_write_end(vdata);
69}