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->tkr_mono.clock->archdata.vclock_mode; 35 vdata->cycle_last = tk->tkr_mono.cycle_last; 36 vdata->mask = tk->tkr_mono.mask; 37 vdata->mult = tk->tkr_mono.mult; 38 vdata->shift = tk->tkr_mono.shift; 39 40 vdata->wall_time_sec = tk->xtime_sec; 41 vdata->wall_time_snsec = tk->tkr_mono.xtime_nsec; 42 43 vdata->monotonic_time_sec = tk->xtime_sec 44 + tk->wall_to_monotonic.tv_sec; 45 vdata->monotonic_time_snsec = tk->tkr_mono.xtime_nsec 46 + ((u64)tk->wall_to_monotonic.tv_nsec 47 << tk->tkr_mono.shift); 48 while (vdata->monotonic_time_snsec >= 49 (((u64)NSEC_PER_SEC) << tk->tkr_mono.shift)) { 50 vdata->monotonic_time_snsec -= 51 ((u64)NSEC_PER_SEC) << tk->tkr_mono.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->tkr_mono.xtime_nsec >> 57 tk->tkr_mono.shift); 58 59 vdata->monotonic_time_coarse_sec = 60 vdata->wall_time_coarse_sec + tk->wall_to_monotonic.tv_sec; 61 vdata->monotonic_time_coarse_nsec = 62 vdata->wall_time_coarse_nsec + tk->wall_to_monotonic.tv_nsec; 63 64 while (vdata->monotonic_time_coarse_nsec >= NSEC_PER_SEC) { 65 vdata->monotonic_time_coarse_nsec -= NSEC_PER_SEC; 66 vdata->monotonic_time_coarse_sec++; 67 } 68 69 gtod_write_end(vdata); 70} 71