Commit b1537c10 authored by Andrew Morton's avatar Andrew Morton Committed by Linus Torvalds

[PATCH] ppc64: fix do_settimeofday() for new API

parent a05d0bae
...@@ -1112,11 +1112,18 @@ asmlinkage long sys32_pause(void) ...@@ -1112,11 +1112,18 @@ asmlinkage long sys32_pause(void)
static inline long get_tv32(struct timeval *o, struct compat_timeval *i) static inline long get_ts32(struct timespec *o, struct compat_timeval *i)
{ {
return (!access_ok(VERIFY_READ, i, sizeof(*i)) || long usec;
(__get_user(o->tv_sec, &i->tv_sec) |
__get_user(o->tv_usec, &i->tv_usec))); if (!access_ok(VERIFY_READ, i, sizeof(*i)))
return -EFAULT;
if (__get_user(o->tv_sec, &i->tv_sec))
return -EFAULT;
if (__get_user(usec, &i->tv_usec))
return -EFAULT;
o->tv_nsec = usec * 1000;
return 0;
} }
static inline long put_tv32(struct compat_timeval *o, struct timeval *i) static inline long put_tv32(struct compat_timeval *o, struct timeval *i)
...@@ -1199,7 +1206,6 @@ asmlinkage long sys32_sysinfo(struct sysinfo32 *info) ...@@ -1199,7 +1206,6 @@ asmlinkage long sys32_sysinfo(struct sysinfo32 *info)
/* Translations due to time_t size differences. Which affects all /* Translations due to time_t size differences. Which affects all
sorts of things, like timeval and itimerval. */ sorts of things, like timeval and itimerval. */
extern struct timezone sys_tz; extern struct timezone sys_tz;
extern int do_sys_settimeofday(struct timeval *tv, struct timezone *tz);
asmlinkage long sys32_gettimeofday(struct compat_timeval *tv, struct timezone *tz) asmlinkage long sys32_gettimeofday(struct compat_timeval *tv, struct timezone *tz)
{ {
...@@ -1221,11 +1227,11 @@ asmlinkage long sys32_gettimeofday(struct compat_timeval *tv, struct timezone *t ...@@ -1221,11 +1227,11 @@ asmlinkage long sys32_gettimeofday(struct compat_timeval *tv, struct timezone *t
asmlinkage long sys32_settimeofday(struct compat_timeval *tv, struct timezone *tz) asmlinkage long sys32_settimeofday(struct compat_timeval *tv, struct timezone *tz)
{ {
struct timeval ktv; struct timespec kts;
struct timezone ktz; struct timezone ktz;
if (tv) { if (tv) {
if (get_tv32(&ktv, tv)) if (get_ts32(&kts, tv))
return -EFAULT; return -EFAULT;
} }
if (tz) { if (tz) {
...@@ -1233,7 +1239,7 @@ asmlinkage long sys32_settimeofday(struct compat_timeval *tv, struct timezone *t ...@@ -1233,7 +1239,7 @@ asmlinkage long sys32_settimeofday(struct compat_timeval *tv, struct timezone *t
return -EFAULT; return -EFAULT;
} }
return do_sys_settimeofday(tv ? &ktv : NULL, tz ? &ktz : NULL); return do_sys_settimeofday(tv ? &kts : NULL, tz ? &ktz : NULL);
} }
......
...@@ -337,13 +337,16 @@ void do_gettimeofday(struct timeval *tv) ...@@ -337,13 +337,16 @@ void do_gettimeofday(struct timeval *tv)
tv->tv_usec = usec; tv->tv_usec = usec;
} }
void do_settimeofday(struct timeval *tv) int do_settimeofday(struct timespec *tv)
{ {
unsigned long flags; unsigned long flags;
unsigned long delta_xsec; unsigned long delta_xsec;
long int tb_delta, new_usec, new_sec; long int tb_delta, new_nsec, new_sec;
unsigned long new_xsec; unsigned long new_xsec;
if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC)
return -EINVAL;
write_seqlock_irqsave(&xtime_lock, flags); write_seqlock_irqsave(&xtime_lock, flags);
/* Updating the RTC is not the job of this code. If the time is /* Updating the RTC is not the job of this code. If the time is
* stepped under NTP, the RTC will be update after STA_UNSYNC * stepped under NTP, the RTC will be update after STA_UNSYNC
...@@ -362,12 +365,12 @@ void do_settimeofday(struct timeval *tv) ...@@ -362,12 +365,12 @@ void do_settimeofday(struct timeval *tv)
tb_delta += (jiffies - wall_jiffies) * tb_ticks_per_jiffy; tb_delta += (jiffies - wall_jiffies) * tb_ticks_per_jiffy;
new_sec = tv->tv_sec; new_sec = tv->tv_sec;
new_usec = tv->tv_usec - tb_delta / tb_ticks_per_usec; new_nsec = tv->tv_nsec - (tb_delta / tb_ticks_per_usec / 1000);
while (new_usec <0) { while (new_nsec < 0) {
new_sec--; new_sec--;
new_usec += USEC_PER_SEC; new_nsec += NSEC_PER_SEC;
} }
xtime.tv_nsec = new_usec * 1000; xtime.tv_nsec = new_nsec;
xtime.tv_sec = new_sec; xtime.tv_sec = new_sec;
/* In case of a large backwards jump in time with NTP, we want the /* In case of a large backwards jump in time with NTP, we want the
...@@ -381,7 +384,7 @@ void do_settimeofday(struct timeval *tv) ...@@ -381,7 +384,7 @@ void do_settimeofday(struct timeval *tv)
time_esterror = NTP_PHASE_LIMIT; time_esterror = NTP_PHASE_LIMIT;
delta_xsec = mulhdu( (tb_last_stamp-do_gtod.tb_orig_stamp), do_gtod.varp->tb_to_xs ); delta_xsec = mulhdu( (tb_last_stamp-do_gtod.tb_orig_stamp), do_gtod.varp->tb_to_xs );
new_xsec = (new_usec * XSEC_PER_SEC) / USEC_PER_SEC; new_xsec = (new_nsec * XSEC_PER_SEC) / NSEC_PER_SEC;
new_xsec += new_sec * XSEC_PER_SEC; new_xsec += new_sec * XSEC_PER_SEC;
if ( new_xsec > delta_xsec ) { if ( new_xsec > delta_xsec ) {
do_gtod.varp->stamp_xsec = new_xsec - delta_xsec; do_gtod.varp->stamp_xsec = new_xsec - delta_xsec;
...@@ -396,6 +399,7 @@ void do_settimeofday(struct timeval *tv) ...@@ -396,6 +399,7 @@ void do_settimeofday(struct timeval *tv)
} }
write_sequnlock_irqrestore(&xtime_lock, flags); write_sequnlock_irqrestore(&xtime_lock, flags);
return 0;
} }
/* /*
...@@ -407,7 +411,7 @@ void do_settimeofday(struct timeval *tv) ...@@ -407,7 +411,7 @@ void do_settimeofday(struct timeval *tv)
long ppc64_sys32_stime(int* tptr) long ppc64_sys32_stime(int* tptr)
{ {
int value; int value;
struct timeval myTimeval; struct timespec myTimeval;
if (!capable(CAP_SYS_TIME)) if (!capable(CAP_SYS_TIME))
return -EPERM; return -EPERM;
...@@ -416,7 +420,7 @@ long ppc64_sys32_stime(int* tptr) ...@@ -416,7 +420,7 @@ long ppc64_sys32_stime(int* tptr)
return -EFAULT; return -EFAULT;
myTimeval.tv_sec = value; myTimeval.tv_sec = value;
myTimeval.tv_usec = 0; myTimeval.tv_nsec = 0;
do_settimeofday(&myTimeval); do_settimeofday(&myTimeval);
...@@ -432,7 +436,7 @@ long ppc64_sys32_stime(int* tptr) ...@@ -432,7 +436,7 @@ long ppc64_sys32_stime(int* tptr)
long ppc64_sys_stime(long* tptr) long ppc64_sys_stime(long* tptr)
{ {
long value; long value;
struct timeval myTimeval; struct timespec myTimeval;
if (!capable(CAP_SYS_TIME)) if (!capable(CAP_SYS_TIME))
return -EPERM; return -EPERM;
...@@ -441,7 +445,7 @@ long ppc64_sys_stime(long* tptr) ...@@ -441,7 +445,7 @@ long ppc64_sys_stime(long* tptr)
return -EFAULT; return -EFAULT;
myTimeval.tv_sec = value; myTimeval.tv_sec = value;
myTimeval.tv_usec = 0; myTimeval.tv_nsec = 0;
do_settimeofday(&myTimeval); do_settimeofday(&myTimeval);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment