162306a36Sopenharmony_ci/* 262306a36Sopenharmony_ci * Copyright (C) 2001 Andrea Arcangeli <andrea@suse.de> SuSE 362306a36Sopenharmony_ci * Copyright 2003 Andi Kleen, SuSE Labs. 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Thanks to hpa@transmeta.com for some useful hint. 662306a36Sopenharmony_ci * Special thanks to Ingo Molnar for his early experience with 762306a36Sopenharmony_ci * a different vsyscall implementation for Linux/IA32 and for the name. 862306a36Sopenharmony_ci */ 962306a36Sopenharmony_ci 1062306a36Sopenharmony_ci#include <linux/time.h> 1162306a36Sopenharmony_ci#include <linux/timekeeper_internal.h> 1262306a36Sopenharmony_ci 1362306a36Sopenharmony_ci#include <asm/vvar.h> 1462306a36Sopenharmony_ci 1562306a36Sopenharmony_civoid update_vsyscall_tz(void) 1662306a36Sopenharmony_ci{ 1762306a36Sopenharmony_ci if (unlikely(vvar_data == NULL)) 1862306a36Sopenharmony_ci return; 1962306a36Sopenharmony_ci 2062306a36Sopenharmony_ci vvar_data->tz_minuteswest = sys_tz.tz_minuteswest; 2162306a36Sopenharmony_ci vvar_data->tz_dsttime = sys_tz.tz_dsttime; 2262306a36Sopenharmony_ci} 2362306a36Sopenharmony_ci 2462306a36Sopenharmony_civoid update_vsyscall(struct timekeeper *tk) 2562306a36Sopenharmony_ci{ 2662306a36Sopenharmony_ci struct vvar_data *vdata = vvar_data; 2762306a36Sopenharmony_ci 2862306a36Sopenharmony_ci if (unlikely(vdata == NULL)) 2962306a36Sopenharmony_ci return; 3062306a36Sopenharmony_ci 3162306a36Sopenharmony_ci vvar_write_begin(vdata); 3262306a36Sopenharmony_ci vdata->vclock_mode = tk->tkr_mono.clock->archdata.vclock_mode; 3362306a36Sopenharmony_ci vdata->clock.cycle_last = tk->tkr_mono.cycle_last; 3462306a36Sopenharmony_ci vdata->clock.mask = tk->tkr_mono.mask; 3562306a36Sopenharmony_ci vdata->clock.mult = tk->tkr_mono.mult; 3662306a36Sopenharmony_ci vdata->clock.shift = tk->tkr_mono.shift; 3762306a36Sopenharmony_ci 3862306a36Sopenharmony_ci vdata->wall_time_sec = tk->xtime_sec; 3962306a36Sopenharmony_ci vdata->wall_time_snsec = tk->tkr_mono.xtime_nsec; 4062306a36Sopenharmony_ci 4162306a36Sopenharmony_ci vdata->monotonic_time_sec = tk->xtime_sec + 4262306a36Sopenharmony_ci tk->wall_to_monotonic.tv_sec; 4362306a36Sopenharmony_ci vdata->monotonic_time_snsec = tk->tkr_mono.xtime_nsec + 4462306a36Sopenharmony_ci (tk->wall_to_monotonic.tv_nsec << 4562306a36Sopenharmony_ci tk->tkr_mono.shift); 4662306a36Sopenharmony_ci 4762306a36Sopenharmony_ci while (vdata->monotonic_time_snsec >= 4862306a36Sopenharmony_ci (((u64)NSEC_PER_SEC) << tk->tkr_mono.shift)) { 4962306a36Sopenharmony_ci vdata->monotonic_time_snsec -= 5062306a36Sopenharmony_ci ((u64)NSEC_PER_SEC) << tk->tkr_mono.shift; 5162306a36Sopenharmony_ci vdata->monotonic_time_sec++; 5262306a36Sopenharmony_ci } 5362306a36Sopenharmony_ci 5462306a36Sopenharmony_ci vdata->wall_time_coarse_sec = tk->xtime_sec; 5562306a36Sopenharmony_ci vdata->wall_time_coarse_nsec = 5662306a36Sopenharmony_ci (long)(tk->tkr_mono.xtime_nsec >> tk->tkr_mono.shift); 5762306a36Sopenharmony_ci 5862306a36Sopenharmony_ci vdata->monotonic_time_coarse_sec = 5962306a36Sopenharmony_ci vdata->wall_time_coarse_sec + tk->wall_to_monotonic.tv_sec; 6062306a36Sopenharmony_ci vdata->monotonic_time_coarse_nsec = 6162306a36Sopenharmony_ci vdata->wall_time_coarse_nsec + tk->wall_to_monotonic.tv_nsec; 6262306a36Sopenharmony_ci 6362306a36Sopenharmony_ci while (vdata->monotonic_time_coarse_nsec >= NSEC_PER_SEC) { 6462306a36Sopenharmony_ci vdata->monotonic_time_coarse_nsec -= NSEC_PER_SEC; 6562306a36Sopenharmony_ci vdata->monotonic_time_coarse_sec++; 6662306a36Sopenharmony_ci } 6762306a36Sopenharmony_ci 6862306a36Sopenharmony_ci vvar_write_end(vdata); 6962306a36Sopenharmony_ci} 70