/* This function is only called on the boot processor */ void __init time_init(void) { time_t sec, old_sec; unsigned old_stamp, stamp, elapsed; if (ppc_md.time_init != NULL) time_offset = ppc_md.time_init(); if (__USE_RTC()) { /* 601 processor: dec counts down by 128 every 128ns */ tb_ticks_per_jiffy = DECREMENTER_COUNT_601; /* mulhwu_scale_factor(1000000000, 1000000) is 0x418937 */ tb_to_us = 0x418937; } else { ppc_md.calibrate_decr(); } /* Now that the decrementer is calibrated, it can be used in case the * clock is stuck, but the fact that we have to handle the 601 * makes things more complex. Repeatedly read the RTC until the * next second boundary to try to achieve some precision. If there * is no RTC, we still need to set tb_last_stamp and * last_jiffy_stamp(cpu 0) to the current stamp. */ stamp = get_native_tbl(); if (ppc_md.get_rtc_time) { sec = ppc_md.get_rtc_time(); elapsed = 0; do { old_stamp = stamp; old_sec = sec; stamp = get_native_tbl(); if (__USE_RTC() && stamp < old_stamp) old_stamp -= 1000000000; elapsed += stamp - old_stamp; sec = ppc_md.get_rtc_time(); } while ( sec == old_sec && elapsed < 2*HZ*tb_ticks_per_jiffy); if (sec == old_sec) printk("Warning: real time clock seems stuck!\n"); xtime.tv_sec = sec; xtime.tv_usec = 0; /* No update now, we just read the time from the RTC ! */ last_rtc_update = xtime.tv_sec; } last_jiffy_stamp(0) = tb_last_stamp = stamp; /* Not exact, but the timer interrupt takes care of this */ set_dec(tb_ticks_per_jiffy); /* If platform provided a timezone (pmac), we correct the time * using do_sys_settimeofday() which in turn calls warp_clock() */ if (time_offset) { struct timezone tz; tz.tz_minuteswest = -time_offset / 60; tz.tz_dsttime = 0; do_sys_settimeofday(NULL, &tz); } }
asmlinkage int sys_settimeofday(struct timeval *tv, struct timezone *tz) { struct timeval new_tv; struct timezone new_tz; if (tv) { if (copy_from_user(&new_tv, tv, sizeof(*tv))) return -EFAULT; } if (tz) { if (copy_from_user(&new_tz, tz, sizeof(*tz))) return -EFAULT; } return do_sys_settimeofday(tv ? &new_tv : NULL, tz ? &new_tz : NULL); }
asmlinkage long compat_sys_settimeofday(struct compat_timeval __user *tv, struct timezone __user *tz) { struct timespec kts; struct timezone ktz; if (tv) { if (get_ts32(&kts, tv)) return -EFAULT; } if (tz) { if (copy_from_user(&ktz, tz, sizeof(ktz))) return -EFAULT; } return do_sys_settimeofday(tv ? &kts : NULL, tz ? &ktz : NULL); }
COMPAT_SYSCALL_DEFINE2(settimeofday, struct compat_timeval __user *, tv, struct timezone __user *, tz) { struct timeval user_tv; struct timespec new_ts; struct timezone new_tz; if (tv) { if (compat_get_timeval(&user_tv, tv)) return -EFAULT; new_ts.tv_sec = user_tv.tv_sec; new_ts.tv_nsec = user_tv.tv_usec * NSEC_PER_USEC; } if (tz) { if (copy_from_user(&new_tz, tz, sizeof(*tz))) return -EFAULT; } return do_sys_settimeofday(tv ? &new_ts : NULL, tz ? &new_tz : NULL); }
asmlinkage long sys_settimeofday(struct timeval __user *tv, struct timezone __user *tz) { struct timeval user_tv; struct timespec new_ts; struct timezone new_tz; if (tv) { if (copy_from_user(&user_tv, tv, sizeof(*tv))) return -EFAULT; new_ts.tv_sec = user_tv.tv_sec; new_ts.tv_nsec = user_tv.tv_usec * NSEC_PER_USEC; } if (tz) { if (copy_from_user(&new_tz, tz, sizeof(*tz))) return -EFAULT; } return do_sys_settimeofday(tv ? &new_ts : NULL, tz ? &new_tz : NULL); }
/* Set clock_realtime */ static int posix_clock_realtime_set(const clockid_t which_clock, const struct timespec *tp) { return do_sys_settimeofday(tp, NULL); }
static inline int common_clock_set(const clockid_t which_clock, struct timespec *tp) { return do_sys_settimeofday(tp, NULL); }