From mboxrd@z Thu Jan 1 00:00:00 1970 From: Stefano Stabellini Subject: [PATCH v4 1/3] xen: move wallclock functions from x86 to common Date: Thu, 12 Nov 2015 17:46:02 +0000 Message-ID: <1447350364-22923-1-git-send-email-stefano.stabellini@eu.citrix.com> References: Mime-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Return-path: In-Reply-To: List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Sender: xen-devel-bounces@lists.xen.org Errors-To: xen-devel-bounces@lists.xen.org To: xen-devel@lists.xensource.com Cc: andrew.cooper3@citrix.com, Ian.Campbell@citrix.com, JBeulich@suse.com, Stefano Stabellini List-Id: xen-devel@lists.xenproject.org Remove dummy arm implementation of wallclock_time. Use shared_info() in common code rather than x86-ism to access it, when possible. Define the static variable wc_sec, and the local variale sec in update_domain_wallclock_time, as uint64_t instead of unsigned long, to avoid size issue on arm. Take a uint64_t sec paramter in do_settime for the same reason. Signed-off-by: Stefano Stabellini Acked-by: Jan Beulich CC: JBeulich@suse.com CC: andrew.cooper3@citrix.com --- Changes in v3: - remove stray blank lines Changes in v2: - remove stray blank lines - remove include - move version_update_* to include/xen/time.h - introduce ifdef to fix build issue in common/time.c - define wc_sec and sec as uint64_t - pass u64 to do_settime --- xen/arch/arm/time.c | 5 --- xen/arch/x86/time.c | 96 +----------------------------------------------- xen/common/time.c | 95 ++++++++++++++++++++++++++++++++++++++++++++++- xen/include/xen/time.h | 5 ++- 4 files changed, 99 insertions(+), 102 deletions(-) diff --git a/xen/arch/arm/time.c b/xen/arch/arm/time.c index 5ded30c..6207615 100644 --- a/xen/arch/arm/time.c +++ b/xen/arch/arm/time.c @@ -280,11 +280,6 @@ void domain_set_time_offset(struct domain *d, int64_t time_offset_seconds) /* XXX update guest visible wallclock time */ } -struct tm wallclock_time(uint64_t *ns) -{ - return (struct tm) { 0 }; -} - /* * Local variables: * mode: C diff --git a/xen/arch/x86/time.c b/xen/arch/x86/time.c index bbb7e6c..0f16db5 100644 --- a/xen/arch/x86/time.c +++ b/xen/arch/x86/time.c @@ -47,9 +47,6 @@ string_param("clocksource", opt_clocksource); unsigned long __read_mostly cpu_khz; /* CPU clock frequency in kHz. */ DEFINE_SPINLOCK(rtc_lock); unsigned long pit0_ticks; -static unsigned long wc_sec; /* UTC time at last 'time update'. */ -static unsigned int wc_nsec; -static DEFINE_SPINLOCK(wc_lock); struct cpu_time { u64 local_tsc_stamp; @@ -783,10 +780,6 @@ uint64_t tsc_ticks2ns(uint64_t ticks) return scale_delta(ticks, &t->tsc_scale); } -/* Explicitly OR with 1 just in case version number gets out of sync. */ -#define version_update_begin(v) (((v)+1)|1) -#define version_update_end(v) ((v)+1) - static void __update_vcpu_system_time(struct vcpu *v, int force) { struct cpu_time *t; @@ -900,37 +893,6 @@ void force_update_vcpu_system_time(struct vcpu *v) __update_vcpu_system_time(v, 1); } -void update_domain_wallclock_time(struct domain *d) -{ - uint32_t *wc_version; - unsigned long sec; - - spin_lock(&wc_lock); - - wc_version = &shared_info(d, wc_version); - *wc_version = version_update_begin(*wc_version); - wmb(); - - sec = wc_sec + d->time_offset_seconds; - if ( likely(!has_32bit_shinfo(d)) ) - { - d->shared_info->native.wc_sec = sec; - d->shared_info->native.wc_nsec = wc_nsec; - d->shared_info->native.wc_sec_hi = sec >> 32; - } - else - { - d->shared_info->compat.wc_sec = sec; - d->shared_info->compat.wc_nsec = wc_nsec; - d->shared_info->compat.arch.wc_sec_hi = sec >> 32; - } - - wmb(); - *wc_version = version_update_end(*wc_version); - - spin_unlock(&wc_lock); -} - static void update_domain_rtc(void) { struct domain *d; @@ -988,27 +950,6 @@ int cpu_frequency_change(u64 freq) return 0; } -/* Set clock to after 00:00:00 UTC, 1 January, 1970. */ -void do_settime(unsigned long secs, unsigned int nsecs, u64 system_time_base) -{ - u64 x; - u32 y; - struct domain *d; - - x = SECONDS(secs) + nsecs - system_time_base; - y = do_div(x, 1000000000); - - spin_lock(&wc_lock); - wc_sec = x; - wc_nsec = y; - spin_unlock(&wc_lock); - - rcu_read_lock(&domlist_read_lock); - for_each_domain ( d ) - update_domain_wallclock_time(d); - rcu_read_unlock(&domlist_read_lock); -} - /* Per-CPU communication between rendezvous IRQ and softirq handler. */ struct cpu_calibration { u64 local_tsc_stamp; @@ -1608,25 +1549,6 @@ void send_timer_event(struct vcpu *v) send_guest_vcpu_virq(v, VIRQ_TIMER); } -/* Return secs after 00:00:00 localtime, 1 January, 1970. */ -unsigned long get_localtime(struct domain *d) -{ - return wc_sec + (wc_nsec + NOW()) / 1000000000ULL - + d->time_offset_seconds; -} - -/* Return microsecs after 00:00:00 localtime, 1 January, 1970. */ -uint64_t get_localtime_us(struct domain *d) -{ - return (SECONDS(wc_sec + d->time_offset_seconds) + wc_nsec + NOW()) - / 1000UL; -} - -unsigned long get_sec(void) -{ - return wc_sec + (wc_nsec + NOW()) / 1000000000ULL; -} - /* "cmos_utc_offset" is the difference between UTC time and CMOS time. */ static long cmos_utc_offset; /* in seconds */ @@ -1635,7 +1557,7 @@ int time_suspend(void) if ( smp_processor_id() == 0 ) { cmos_utc_offset = -get_cmos_time(); - cmos_utc_offset += (wc_sec + (wc_nsec + NOW()) / 1000000000ULL); + cmos_utc_offset += get_sec(); kill_timer(&calibration_timer); /* Sync platform timer stamps. */ @@ -1715,22 +1637,6 @@ int hwdom_pit_access(struct ioreq *ioreq) return 0; } -struct tm wallclock_time(uint64_t *ns) -{ - uint64_t seconds, nsec; - - if ( !wc_sec ) - return (struct tm) { 0 }; - - seconds = NOW() + SECONDS(wc_sec) + wc_nsec; - nsec = do_div(seconds, 1000000000); - - if ( ns ) - *ns = nsec; - - return gmtime(seconds); -} - /* * PV SoftTSC Emulation. */ diff --git a/xen/common/time.c b/xen/common/time.c index 29fdf52..721ada8 100644 --- a/xen/common/time.c +++ b/xen/common/time.c @@ -15,8 +15,12 @@ * along with this program; If not, see . */ -#include +#include +#include +#include #include +#include +#include /* Nonzero if YEAR is a leap year (every 4 years, except every 100th isn't, and every 400th is). */ @@ -34,6 +38,10 @@ const unsigned short int __mon_lengths[2][12] = { #define SECS_PER_HOUR (60 * 60) #define SECS_PER_DAY (SECS_PER_HOUR * 24) +static uint64_t wc_sec; /* UTC time at last 'time update'. */ +static unsigned int wc_nsec; +static DEFINE_SPINLOCK(wc_lock); + struct tm gmtime(unsigned long t) { struct tm tbuf; @@ -85,3 +93,88 @@ struct tm gmtime(unsigned long t) return tbuf; } + +void update_domain_wallclock_time(struct domain *d) +{ + uint32_t *wc_version; + uint64_t sec; + + spin_lock(&wc_lock); + + wc_version = &shared_info(d, wc_version); + *wc_version = version_update_begin(*wc_version); + wmb(); + + sec = wc_sec + d->time_offset_seconds; + shared_info(d, wc_sec) = sec; + shared_info(d, wc_nsec) = wc_nsec; +#ifdef CONFIG_X86 + if ( likely(!has_32bit_shinfo(d)) ) + d->shared_info->native.wc_sec_hi = sec >> 32; + else + d->shared_info->compat.arch.wc_sec_hi = sec >> 32; +#else + shared_info(d, wc_sec_hi) = sec >> 32; +#endif + + wmb(); + *wc_version = version_update_end(*wc_version); + + spin_unlock(&wc_lock); +} + +/* Set clock to after 00:00:00 UTC, 1 January, 1970. */ +void do_settime(u64 secs, unsigned int nsecs, u64 system_time_base) +{ + u64 x; + u32 y; + struct domain *d; + + x = SECONDS(secs) + nsecs - system_time_base; + y = do_div(x, 1000000000); + + spin_lock(&wc_lock); + wc_sec = x; + wc_nsec = y; + spin_unlock(&wc_lock); + + rcu_read_lock(&domlist_read_lock); + for_each_domain ( d ) + update_domain_wallclock_time(d); + rcu_read_unlock(&domlist_read_lock); +} + +/* Return secs after 00:00:00 localtime, 1 January, 1970. */ +unsigned long get_localtime(struct domain *d) +{ + return wc_sec + (wc_nsec + NOW()) / 1000000000ULL + + d->time_offset_seconds; +} + +/* Return microsecs after 00:00:00 localtime, 1 January, 1970. */ +uint64_t get_localtime_us(struct domain *d) +{ + return (SECONDS(wc_sec + d->time_offset_seconds) + wc_nsec + NOW()) + / 1000UL; +} + +unsigned long get_sec(void) +{ + return wc_sec + (wc_nsec + NOW()) / 1000000000ULL; +} + +struct tm wallclock_time(uint64_t *ns) +{ + uint64_t seconds, nsec; + + if ( !wc_sec ) + return (struct tm) { 0 }; + + seconds = NOW() + SECONDS(wc_sec) + wc_nsec; + nsec = do_div(seconds, 1000000000); + + if ( ns ) + *ns = nsec; + + return gmtime(seconds); +} diff --git a/xen/include/xen/time.h b/xen/include/xen/time.h index da4e8d7..b742746 100644 --- a/xen/include/xen/time.h +++ b/xen/include/xen/time.h @@ -60,11 +60,14 @@ struct tm wallclock_time(uint64_t *ns); /* Chosen so (NOW() + delta) wont overflow without an uptime of 200 years */ #define STIME_DELTA_MAX ((s_time_t)((uint64_t)~0ull>>2)) +/* Explicitly OR with 1 just in case version number gets out of sync. */ +#define version_update_begin(v) (((v) + 1) | 1) +#define version_update_end(v) ((v) + 1) extern void update_vcpu_system_time(struct vcpu *v); extern void update_domain_wallclock_time(struct domain *d); extern void do_settime( - unsigned long secs, unsigned int nsecs, u64 system_time_base); + u64 secs, unsigned int nsecs, u64 system_time_base); extern void send_timer_event(struct vcpu *v); -- 1.7.10.4