diff options
author | Martin Schwidefsky <schwidefsky@de.ibm.com> | 2016-05-31 12:47:03 +0200 |
---|---|---|
committer | Martin Schwidefsky <schwidefsky@de.ibm.com> | 2016-06-13 15:58:20 +0200 |
commit | 936cc855ffe808b428cf75116fe031af9f12237e (patch) | |
tree | 48be65e1168b3ce87dba556cfca3f95f647c95c8 /arch/s390/kernel/time.c | |
parent | 4027789192d149678262ad606b2d7e2a61bed0f2 (diff) | |
download | blackbird-obmc-linux-936cc855ffe808b428cf75116fe031af9f12237e.tar.gz blackbird-obmc-linux-936cc855ffe808b428cf75116fe031af9f12237e.zip |
s390/time: add leap seconds to initial system time
The PTFF instruction can be used to retrieve information about UTC
including the current number of leap seconds. Use this value to
convert the coordinated server time value of the TOD clock to a
proper UTC timestamp to initialize the system time. Without this
correction the system time will be off by the number of leap seonds
until it has been corrected via NTP.
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Diffstat (limited to 'arch/s390/kernel/time.c')
-rw-r--r-- | arch/s390/kernel/time.c | 17 |
1 files changed, 15 insertions, 2 deletions
diff --git a/arch/s390/kernel/time.c b/arch/s390/kernel/time.c index d71623639997..1a27d4d08b43 100644 --- a/arch/s390/kernel/time.c +++ b/arch/s390/kernel/time.c @@ -64,6 +64,7 @@ EXPORT_SYMBOL(s390_epoch_delta_notifier); unsigned char ptff_function_mask[16]; unsigned long lpar_offset; +unsigned long initial_leap_seconds; /* * Get time offsets with PTFF @@ -71,6 +72,7 @@ unsigned long lpar_offset; void __init ptff_init(void) { struct ptff_qto qto; + struct ptff_qui qui; if (!test_facility(28)) return; @@ -79,6 +81,11 @@ void __init ptff_init(void) /* get LPAR offset */ if (ptff_query(PTFF_QTO) && ptff(&qto, sizeof(qto), PTFF_QTO) == 0) lpar_offset = qto.tod_epoch_difference; + + /* get initial leap seconds */ + if (ptff_query(PTFF_QUI) && ptff(&qui, sizeof(qui), PTFF_QUI) == 0) + initial_leap_seconds = (unsigned long) + ((long) qui.old_leap * 4096000000L); } /* @@ -200,12 +207,18 @@ static void stp_reset(void); void read_persistent_clock64(struct timespec64 *ts) { - tod_to_timeval(get_tod_clock() - TOD_UNIX_EPOCH, ts); + __u64 clock; + + clock = get_tod_clock() - initial_leap_seconds; + tod_to_timeval(clock - TOD_UNIX_EPOCH, ts); } void read_boot_clock64(struct timespec64 *ts) { - tod_to_timeval(sched_clock_base_cc - TOD_UNIX_EPOCH, ts); + __u64 clock; + + clock = sched_clock_base_cc - initial_leap_seconds; + tod_to_timeval(clock - TOD_UNIX_EPOCH, ts); } static cycle_t read_tod_clock(struct clocksource *cs) |