diff --git a/arch/s390/include/asm/timex.h b/arch/s390/include/asm/timex.h index d744c3d62de58dc7d31de475507f6775689d5f3d..cc21e3e20fd778e338f6581248f488b452fd2c18 100644 --- a/arch/s390/include/asm/timex.h +++ b/arch/s390/include/asm/timex.h @@ -11,6 +11,9 @@ #ifndef _ASM_S390_TIMEX_H #define _ASM_S390_TIMEX_H +/* The value of the TOD clock for 1.1.1970. */ +#define TOD_UNIX_EPOCH 0x7d91048bca000000ULL + /* Inline functions for clock register access. */ static inline int set_clock(__u64 time) { @@ -85,4 +88,6 @@ int get_sync_clock(unsigned long long *clock); void init_cpu_timer(void); unsigned long long monotonic_clock(void); +extern u64 sched_clock_base_cc; + #endif diff --git a/arch/s390/kernel/early.c b/arch/s390/kernel/early.c index d4e1e5b6cfdaad9b5c37ca7ae20bbe621c19fdd3..cf09948faad6330aba32a207a88921aac833a307 100644 --- a/arch/s390/kernel/early.c +++ b/arch/s390/kernel/early.c @@ -38,6 +38,21 @@ static unsigned long machine_flags; static void __init setup_boot_command_line(void); +/* + * Get the TOD clock running. + */ +static void __init reset_tod_clock(void) +{ + u64 time; + + if (store_clock(&time) == 0) + return; + /* TOD clock not running. Set the clock to Unix Epoch. */ + if (set_clock(TOD_UNIX_EPOCH) != 0 || store_clock(&time) != 0) + disabled_wait(0); + + sched_clock_base_cc = TOD_UNIX_EPOCH; +} #ifdef CONFIG_SHARED_KERNEL int __init savesys_ipl_nss(char *cmd, const int cmdlen); @@ -372,6 +387,7 @@ static void __init setup_boot_command_line(void) */ void __init startup_init(void) { + reset_tod_clock(); ipl_save_parameters(); rescue_initrd(); clear_bss_section(); diff --git a/arch/s390/kernel/head.S b/arch/s390/kernel/head.S index 1046c2c9f8d139b723ce32fbeded0b71fc1f388b..16f8975325edbd6d192341813d378eda74043a37 100644 --- a/arch/s390/kernel/head.S +++ b/arch/s390/kernel/head.S @@ -471,6 +471,8 @@ startup:basr %r13,0 # get base .LPG0: xc 0x200(256),0x200 # partially clear lowcore xc 0x300(256),0x300 + l %r1,5f-.LPG0(%r13) + stck 0(%r1) #ifndef CONFIG_MARCH_G5 # check processor version against MARCH_{G5,Z900,Z990,Z9_109,Z10} @@ -496,9 +498,10 @@ startup:basr %r13,0 # get base brct %r0,0b #endif - l %r13,0f-.LPG0(%r13) + l %r13,4f-.LPG0(%r13) b 0(%r13) -0: .long startup_continue +4: .long startup_continue +5: .long sched_clock_base_cc # # params at 10400 (setup.h) diff --git a/arch/s390/kernel/time.c b/arch/s390/kernel/time.c index 05f93e77870b03370fc47c6034a3c0aa2294111b..369ff02c4ab2e9a0fde86352fef57bc8e50f3e68 100644 --- a/arch/s390/kernel/time.c +++ b/arch/s390/kernel/time.c @@ -52,9 +52,6 @@ #define USECS_PER_JIFFY ((unsigned long) 1000000/HZ) #define CLK_TICKS_PER_JIFFY ((unsigned long) USECS_PER_JIFFY << 12) -/* The value of the TOD clock for 1.1.1970. */ -#define TOD_UNIX_EPOCH 0x7d91048bca000000ULL - /* * Create a small time difference between the timer interrupts * on the different cpus to avoid lock contention. @@ -63,9 +60,10 @@ #define TICK_SIZE tick +u64 sched_clock_base_cc = -1; /* Force to data section. */ + static ext_int_info_t ext_int_info_cc; static ext_int_info_t ext_int_etr_cc; -static u64 sched_clock_base_cc; static DEFINE_PER_CPU(struct clock_event_device, comparators); @@ -195,22 +193,12 @@ static void timing_alert_interrupt(__u16 code) static void etr_reset(void); static void stp_reset(void); -/* - * Get the TOD clock running. - */ -static u64 __init reset_tod_clock(void) +unsigned long read_persistent_clock(void) { - u64 time; + struct timespec ts; - etr_reset(); - stp_reset(); - if (store_clock(&time) == 0) - return time; - /* TOD clock not running. Set the clock to Unix Epoch. */ - if (set_clock(TOD_UNIX_EPOCH) != 0 || store_clock(&time) != 0) - panic("TOD clock not operational."); - - return TOD_UNIX_EPOCH; + tod_to_timeval(get_clock() - TOD_UNIX_EPOCH, &ts); + return ts.tv_sec; } static cycle_t read_tod_clock(void) @@ -265,7 +253,9 @@ void update_vsyscall_tz(void) */ void __init time_init(void) { - sched_clock_base_cc = reset_tod_clock(); + /* Reset time synchronization interfaces. */ + etr_reset(); + stp_reset(); /* set xtime */ tod_to_timeval(sched_clock_base_cc - TOD_UNIX_EPOCH, &xtime);