diff options
Diffstat (limited to 'arch/x86/kernel/vsyscall_gtod.c')
-rw-r--r-- | arch/x86/kernel/vsyscall_gtod.c | 69 |
1 files changed, 69 insertions, 0 deletions
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 | |||
19 | DEFINE_VVAR(struct vsyscall_gtod_data, vsyscall_gtod_data); | ||
20 | |||
21 | void 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 | |||
27 | void 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 | } | ||