--- org/kernel/hrtimer.c 2012-01-28 03:54:02.000000000 +0900 +++ new/kernel/hrtimer.c 2013-12-10 02:03:01.000000000 +0900 @@ -627,6 +627,12 @@ return res; } +static inline ktime_t hrtimer_update_base(struct hrtimer_cpu_base *base) +{ + ktime_t *offs_real = &base->clock_base[CLOCK_REALTIME].offset; + + return ktime_get_update_offsets(offs_real); +} /* * Retrigger next event is called after clock was set @@ -636,25 +642,16 @@ static void retrigger_next_event(void *arg) { struct hrtimer_cpu_base *base; - struct timespec realtime_offset, wtm; - unsigned long seq; if (!hrtimer_hres_active()) return; - do { - seq = read_seqbegin(&xtime_lock); - wtm = __get_wall_to_monotonic(); - } while (read_seqretry(&xtime_lock, seq)); - set_normalized_timespec(&realtime_offset, -wtm.tv_sec, -wtm.tv_nsec); - base = &__get_cpu_var(hrtimer_bases); /* Adjust CLOCK_REALTIME offset */ raw_spin_lock(&base->lock); - base->clock_base[CLOCK_REALTIME].offset = - timespec_to_ktime(realtime_offset); + hrtimer_update_base(base); hrtimer_force_reprogram(base, 0); raw_spin_unlock(&base->lock); } @@ -790,6 +787,19 @@ return 1; } +/* + * Called from timekeeping code to reprogramm the hrtimer interrupt + * device. If called from the timer interrupt context we defer it to + * softirq context. + */ +void clock_was_set_delayed(void) +{ + struct hrtimer_cpu_base *cpu_base = &__get_cpu_var(hrtimer_bases); + + cpu_base->clock_was_set = 1; + __raise_softirq_irqoff(HRTIMER_SOFTIRQ); +} + #else static inline int hrtimer_hres_active(void) { return 0; } @@ -1320,11 +1330,10 @@ cpu_base->nr_events++; dev->next_event.tv64 = KTIME_MAX; - entry_time = now = ktime_get(); + raw_spin_lock(&cpu_base->lock); + entry_time = now = hrtimer_update_base(cpu_base); retry: expires_next.tv64 = KTIME_MAX; - - raw_spin_lock(&cpu_base->lock); /* * We set expires_next to KTIME_MAX here with cpu_base->lock * held to prevent that a timer is enqueued in our queue via @@ -1398,8 +1407,12 @@ * We need to prevent that we loop forever in the hrtimer * interrupt routine. We give it 3 attempts to avoid * overreacting on some spurious event. + * + * Acquire base lock for updating the offsets and retrieving + * the current time. */ - now = ktime_get(); + raw_spin_lock(&cpu_base->lock); + now = hrtimer_update_base(cpu_base); cpu_base->nr_retries++; if (++retries < 3) goto retry; @@ -1411,6 +1424,7 @@ */ cpu_base->nr_hangs++; cpu_base->hang_detected = 1; + raw_spin_unlock(&cpu_base->lock); delta = ktime_sub(now, entry_time); if (delta.tv64 > cpu_base->max_hang_time.tv64) cpu_base->max_hang_time = delta; @@ -1463,6 +1477,13 @@ static void run_hrtimer_softirq(struct softirq_action *h) { + struct hrtimer_cpu_base *cpu_base = &__get_cpu_var(hrtimer_bases); + + if (cpu_base->clock_was_set) { + cpu_base->clock_was_set = 0; + clock_was_set(); + } + hrtimer_peek_ahead_timers(); } --- org/kernel/time/timekeeping.c 2012-01-28 03:54:02.000000000 +0900 +++ new/kernel/time/timekeeping.c 2013-12-10 02:03:01.000000000 +0900 @@ -169,24 +169,43 @@ static struct timespec wall_to_monotonic __attribute__ ((aligned (16))); static struct timespec total_sleep_time; +/* Offset clock monotonic -> clock realtime */ +static ktime_t offs_real; + +/* Offset clock monotonic -> clock boottime */ +static ktime_t offs_boot; + /* * The raw monotonic time for the CLOCK_MONOTONIC_RAW posix clock. */ struct timespec raw_time; -/* flag for if timekeeping is suspended */ -int __read_mostly timekeeping_suspended; +/* must hold write on xtime_lock */ +static void update_rt_offset(void) +{ + struct timespec tmp, *wtm = &wall_to_monotonic; + + set_normalized_timespec(&tmp, -wtm->tv_sec, -wtm->tv_nsec); + offs_real = timespec_to_ktime(tmp); +} -/* must hold xtime_lock */ -void timekeeping_leap_insert(int leapsecond) +/* must hold write on xtime_lock */ +static void timekeeping_update(bool clearntp) { - xtime.tv_sec += leapsecond; - wall_to_monotonic.tv_sec -= leapsecond; - masterclock_settime(); + if (clearntp) { + timekeeper.ntp_error = 0; + ntp_clear(); + } + update_rt_offset(); update_vsyscall(&xtime, &wall_to_monotonic, timekeeper.clock, - timekeeper.mult); + timekeeper.mult); } + + +/* flag for if timekeeping is suspended */ +int __read_mostly timekeeping_suspended; + /** * timekeeping_forward_now - update clock to the current time * @@ -344,8 +363,7 @@ touch_nmi_watchdog(); touch_all_softlockup_watchdogs(); - update_vsyscall(&xtime, &wall_to_monotonic, timekeeper.clock, - timekeeper.mult); + timekeeping_update(true); write_sequnlock_irqrestore(&xtime_lock, flags); @@ -585,6 +603,7 @@ } set_normalized_timespec(&wall_to_monotonic, -boot.tv_sec, -boot.tv_nsec); + update_rt_offset(); total_sleep_time.tv_sec = 0; total_sleep_time.tv_nsec = 0; write_sequnlock_irqrestore(&xtime_lock, flags); @@ -593,6 +612,12 @@ /* time in seconds when suspend began */ static struct timespec timekeeping_suspend_time; +static void update_sleep_time(struct timespec t) +{ + total_sleep_time = t; + offs_boot = timespec_to_ktime(t); +} + /** * timekeeping_resume - Resumes the generic timekeeping subsystem. * @dev: unused @@ -616,12 +641,13 @@ ts = timespec_sub(ts, timekeeping_suspend_time); xtime = timespec_add(xtime, ts); wall_to_monotonic = timespec_sub(wall_to_monotonic, ts); - total_sleep_time = timespec_add(total_sleep_time, ts); + update_sleep_time(timespec_add_safe(total_sleep_time, ts)); } /* re-base the last cycle value */ timekeeper.clock->cycle_last = timekeeper.clock->read(timekeeper.clock); timekeeper.ntp_error = 0; timekeeping_suspended = 0; + timekeeping_update(false); write_sequnlock_irqrestore(&xtime_lock, flags); touch_softlockup_watchdog(); @@ -783,9 +809,16 @@ timekeeper.xtime_nsec += timekeeper.xtime_interval << shift; while (timekeeper.xtime_nsec >= nsecps) { + int leap; timekeeper.xtime_nsec -= nsecps; xtime.tv_sec++; - second_overflow(); + leap = second_overflow(xtime.tv_sec); + xtime.tv_sec += leap; + wall_to_monotonic.tv_sec -= leap; + if (leap) { + clock_was_set_delayed(); + masterclock_settime(); + } } /* Accumulate raw time */ @@ -934,15 +967,20 @@ * xtime.tv_nsec isn't larger then NSEC_PER_SEC */ if (unlikely(xtime.tv_nsec >= NSEC_PER_SEC)) { + int leap; xtime.tv_nsec -= NSEC_PER_SEC; xtime.tv_sec++; - second_overflow(); + leap = second_overflow(xtime.tv_sec); + xtime.tv_sec += leap; + wall_to_monotonic.tv_sec -= leap; + if (leap) { + clock_was_set_delayed(); + masterclock_settime(); + } } - set_tsc_quotient_current(); - /* check to see if there is a new clocksource to use */ - update_vsyscall(&xtime, &wall_to_monotonic, timekeeper.clock, - timekeeper.mult); + timekeeping_update(false); + set_tsc_quotient_current(); } /** @@ -1025,6 +1063,38 @@ return now; } +#ifdef CONFIG_HIGH_RES_TIMERS +/** + * ktime_get_update_offsets - hrtimer helper + * @real: pointer to storage for monotonic -> realtime offset + * + * Returns current monotonic time and updates the offsets + * Called from hrtimer_interupt() or retrigger_next_event() + */ +ktime_t ktime_get_update_offsets(ktime_t *real) +{ + ktime_t now; + unsigned int seq; + u64 secs, nsecs; + + do { + seq = read_seqbegin(&xtime_lock); + + secs = xtime.tv_sec; + nsecs = xtime.tv_nsec; + nsecs += timekeeping_get_ns(); + /* If arch requires, add in gettimeoffset() */ + nsecs += arch_gettimeoffset(); + + *real = offs_real; + } while (read_seqretry(&xtime_lock, seq)); + + now = ktime_add_ns(ktime_set(secs, 0), nsecs); + now = ktime_sub(now, *real); + return now; +} +#endif + #ifdef CONFIG_MASTERCLOCK /* * Masterclock implementation starts here. --- org/kernel/time/ntp.c 2012-01-28 03:53:58.000000000 +0900 +++ new/kernel/time/ntp.c 2013-12-10 02:03:01.000000000 +0900 @@ -28,8 +28,6 @@ u64 tick_length; static u64 tick_length_base; -static struct hrtimer leap_timer; - #define MAX_TICKADJ 500LL /* usecs */ #define MAX_TICKADJ_SCALED \ (((MAX_TICKADJ * NSEC_PER_USEC) << NTP_SCALE_SHIFT) / NTP_INTERVAL_FREQ) @@ -206,58 +204,14 @@ } /* - * Leap second processing. If in leap-insert state at the end of the - * day, the system clock is set back one second; if in leap-delete - * state, the system clock is set ahead one second. - */ -static enum hrtimer_restart ntp_leap_second(struct hrtimer *timer) -{ - enum hrtimer_restart res = HRTIMER_NORESTART; - const char *msg = NULL; - - write_seqlock(&xtime_lock); - - switch (time_state) { - case TIME_OK: - break; - case TIME_INS: - timekeeping_leap_insert(-1); - time_state = TIME_OOP; - msg = "inserting leap second 23:59:60 UTC"; - hrtimer_add_expires_ns(&leap_timer, NSEC_PER_SEC); - res = HRTIMER_RESTART; - break; - case TIME_DEL: - timekeeping_leap_insert(1); - time_tai--; - time_state = TIME_WAIT; - msg = "deleting leap second 23:59:59 UTC"; - break; - case TIME_OOP: - time_tai++; - time_state = TIME_WAIT; - /* fall through */ - case TIME_WAIT: - if (!(time_status & (STA_INS | STA_DEL))) - time_state = TIME_OK; - break; - } - - write_sequnlock(&xtime_lock); - - if (msg) - printk(KERN_NOTICE "Clock: %s\n", msg); - - return res; -} - -/* * this routine handles the overflow of the microsecond field * * The tricky bits of code to handle the accurate clock support * were provided by Dave Mills (Mills@UDEL.EDU) of NTP fame. * They were originally developed for SUN and DEC kernels. * All the kudos should go to Dave for this stuff. + * + * Also handles leap second processing, and returns leap offset */ void __second_overflow(void) { @@ -310,9 +264,54 @@ time_adjust = 0; } -void second_overflow(void) +int second_overflow(unsigned long secs) { s64 delta, phase_adj; + int leap = 0; + + /* + * Leap second processing. If in leap-insert state at the end of the + * day, the system clock is set back one second; if in leap-delete + * state, the system clock is set ahead one second. + */ + switch (time_state) { + case TIME_OK: + if (time_status & STA_INS) + time_state = TIME_INS; + else if (time_status & STA_DEL) + time_state = TIME_DEL; + break; + case TIME_INS: + if (!(time_status & STA_INS)) + time_state = TIME_OK; + else if (secs % 86400 == 0) { + leap = -1; + time_state = TIME_OOP; + time_tai++; + printk(KERN_NOTICE + "Clock: inserting leap second 23:59:60 UTC\n"); + } + break; + case TIME_DEL: + if (!(time_status & STA_DEL)) + time_state = TIME_OK; + else if ((secs + 1) % 86400 == 0) { + leap = 1; + time_tai--; + time_state = TIME_WAIT; + printk(KERN_NOTICE + "Clock: deleting leap second 23:59:59 UTC\n"); + } + break; + case TIME_OOP: + time_state = TIME_WAIT; + break; + + case TIME_WAIT: + if (!(time_status & (STA_INS | STA_DEL))) + time_state = TIME_OK; + break; + } ntp_update_frequency(); @@ -331,6 +330,8 @@ time_status &= ~(STA_PPSSIGNAL | STA_PPSJITTER | STA_PPSWANDER | STA_PPSERROR); #endif + + return leap; } #ifdef CONFIG_GENERIC_CMOS_UPDATE @@ -392,27 +393,6 @@ static inline void notify_cmos_timer(void) { } #endif -/* - * Start the leap seconds timer: - */ -static inline void ntp_start_leap_timer(struct timespec *ts) -{ - long now = ts->tv_sec; - - if (time_status & STA_INS) { - time_state = TIME_INS; - now += 86400 - now % 86400; - hrtimer_start(&leap_timer, ktime_set(now, 0), HRTIMER_MODE_ABS); - - return; - } - - if (time_status & STA_DEL) { - time_state = TIME_DEL; - now += 86400 - (now + 1) % 86400; - hrtimer_start(&leap_timer, ktime_set(now, 0), HRTIMER_MODE_ABS); - } -} /* * Propagate a new txc->status value into the NTP state: @@ -435,22 +415,6 @@ time_status &= STA_RONLY; time_status |= txc->status & ~STA_RONLY; - switch (time_state) { - case TIME_OK: - ntp_start_leap_timer(ts); - break; - case TIME_INS: - case TIME_DEL: - time_state = TIME_OK; - ntp_start_leap_timer(ts); - case TIME_WAIT: - if (!(time_status & (STA_INS | STA_DEL))) - time_state = TIME_OK; - break; - case TIME_OOP: - hrtimer_restart(&leap_timer); - break; - } } /* * Called with the xtime lock held, so we can access and modify @@ -541,9 +505,6 @@ (txc->tick < 900000/USER_HZ || txc->tick > 1100000/USER_HZ)) return -EINVAL; - - if (txc->modes & ADJ_STATUS && time_state != TIME_OK) - hrtimer_cancel(&leap_timer); } getnstimeofday(&ts); @@ -624,6 +585,4 @@ void __init ntp_init(void) { ntp_clear(); - hrtimer_init(&leap_timer, CLOCK_REALTIME, HRTIMER_MODE_ABS); - leap_timer.function = ntp_leap_second; } --- org/include/linux/timex.h 2012-01-28 03:53:58.000000000 +0900 +++ new/include/linux/timex.h 2013-12-10 02:03:01.000000000 +0900 @@ -313,7 +313,7 @@ /* Returns how long ticks are at present, in ns / 2^NTP_SCALE_SHIFT. */ extern u64 tick_length; -extern void second_overflow(void); +extern int second_overflow(unsigned long secs); extern void update_ntp_one_tick(void); extern int do_adjtimex(struct timex *); --- org/include/linux/hrtimer.h 2012-01-28 03:53:54.000000000 +0900 +++ new/include/linux/hrtimer.h 2013-12-10 02:03:01.000000000 +0900 @@ -160,6 +160,7 @@ * and timers * @clock_base: array of clock bases for this cpu * @curr_timer: the timer which is executing a callback right now + * @clock_was_set: Indicates that clock was set from irq context. * @expires_next: absolute time of the next event which was scheduled * via clock_set_next_event() * @hres_active: State of high resolution mode @@ -172,6 +173,7 @@ struct hrtimer_cpu_base { raw_spinlock_t lock; struct hrtimer_clock_base clock_base[HRTIMER_MAX_CLOCK_BASES]; + unsigned int clock_was_set; #ifdef CONFIG_HIGH_RES_TIMERS ktime_t expires_next; int hres_active; @@ -281,6 +283,8 @@ # define MONOTONIC_RES_NSEC HIGH_RES_NSEC # define KTIME_MONOTONIC_RES KTIME_HIGH_RES +extern void clock_was_set_delayed(void); + #else # define MONOTONIC_RES_NSEC LOW_RES_NSEC @@ -309,11 +313,14 @@ { return 0; } + +static inline void clock_was_set_delayed(void) { } + #endif extern ktime_t ktime_get(void); extern ktime_t ktime_get_real(void); - +extern ktime_t ktime_get_update_offsets(ktime_t *offs_real); DECLARE_PER_CPU(struct tick_device, tick_cpu_device); --- org/scripts/package/ccur-changelog 2012-01-28 03:54:02.000000000 +0900 +++ new/scripts/package/ccur-changelog 2013-12-10 02:03:01.000000000 +0900 @@ -1,3 +1,9 @@ +* Fri Dec 6 2013 RedHawk Developers +- RedHawk 6.0.2-fujitsu-1 +- Private baseline for Fujitsu started. +- Backported a collection of leap second and timekeeping fixes from + later releases of Linux. + * Thu Jan 19 2012 RedHawk Developers - RedHawk 6.0.2 - Turn on CONFIG_NETWORK_PHY_TIMESTAMPING for x86_64 (already on in i386).