Commit 153b5d054ac2d98ea0d86504884326b6777f683d
Committed by
Linus Torvalds
1 parent
9f14f669d1
Exists in
master
and in
20 other branches
ntp: support for TAI
This adds support for setting the TAI value (International Atomic Time). The value is reported back to userspace via timex (as we don't have a ntp_gettime() syscall). Signed-off-by: Roman Zippel <zippel@linux-m68k.org> Cc: john stultz <johnstul@us.ibm.com> Cc: Thomas Gleixner <tglx@linutronix.de> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Showing 4 changed files with 15 additions and 3 deletions Inline Diff
include/linux/compat.h
1 | #ifndef _LINUX_COMPAT_H | 1 | #ifndef _LINUX_COMPAT_H |
2 | #define _LINUX_COMPAT_H | 2 | #define _LINUX_COMPAT_H |
3 | /* | 3 | /* |
4 | * These are the type definitions for the architecture specific | 4 | * These are the type definitions for the architecture specific |
5 | * syscall compatibility layer. | 5 | * syscall compatibility layer. |
6 | */ | 6 | */ |
7 | 7 | ||
8 | #ifdef CONFIG_COMPAT | 8 | #ifdef CONFIG_COMPAT |
9 | 9 | ||
10 | #include <linux/stat.h> | 10 | #include <linux/stat.h> |
11 | #include <linux/param.h> /* for HZ */ | 11 | #include <linux/param.h> /* for HZ */ |
12 | #include <linux/sem.h> | 12 | #include <linux/sem.h> |
13 | 13 | ||
14 | #include <asm/compat.h> | 14 | #include <asm/compat.h> |
15 | #include <asm/siginfo.h> | 15 | #include <asm/siginfo.h> |
16 | #include <asm/signal.h> | 16 | #include <asm/signal.h> |
17 | 17 | ||
18 | #define compat_jiffies_to_clock_t(x) \ | 18 | #define compat_jiffies_to_clock_t(x) \ |
19 | (((unsigned long)(x) * COMPAT_USER_HZ) / HZ) | 19 | (((unsigned long)(x) * COMPAT_USER_HZ) / HZ) |
20 | 20 | ||
21 | typedef __compat_uid32_t compat_uid_t; | 21 | typedef __compat_uid32_t compat_uid_t; |
22 | typedef __compat_gid32_t compat_gid_t; | 22 | typedef __compat_gid32_t compat_gid_t; |
23 | 23 | ||
24 | struct rusage; | 24 | struct rusage; |
25 | 25 | ||
26 | struct compat_itimerspec { | 26 | struct compat_itimerspec { |
27 | struct compat_timespec it_interval; | 27 | struct compat_timespec it_interval; |
28 | struct compat_timespec it_value; | 28 | struct compat_timespec it_value; |
29 | }; | 29 | }; |
30 | 30 | ||
31 | struct compat_utimbuf { | 31 | struct compat_utimbuf { |
32 | compat_time_t actime; | 32 | compat_time_t actime; |
33 | compat_time_t modtime; | 33 | compat_time_t modtime; |
34 | }; | 34 | }; |
35 | 35 | ||
36 | struct compat_itimerval { | 36 | struct compat_itimerval { |
37 | struct compat_timeval it_interval; | 37 | struct compat_timeval it_interval; |
38 | struct compat_timeval it_value; | 38 | struct compat_timeval it_value; |
39 | }; | 39 | }; |
40 | 40 | ||
41 | struct compat_tms { | 41 | struct compat_tms { |
42 | compat_clock_t tms_utime; | 42 | compat_clock_t tms_utime; |
43 | compat_clock_t tms_stime; | 43 | compat_clock_t tms_stime; |
44 | compat_clock_t tms_cutime; | 44 | compat_clock_t tms_cutime; |
45 | compat_clock_t tms_cstime; | 45 | compat_clock_t tms_cstime; |
46 | }; | 46 | }; |
47 | 47 | ||
48 | struct compat_timex { | 48 | struct compat_timex { |
49 | compat_uint_t modes; | 49 | compat_uint_t modes; |
50 | compat_long_t offset; | 50 | compat_long_t offset; |
51 | compat_long_t freq; | 51 | compat_long_t freq; |
52 | compat_long_t maxerror; | 52 | compat_long_t maxerror; |
53 | compat_long_t esterror; | 53 | compat_long_t esterror; |
54 | compat_int_t status; | 54 | compat_int_t status; |
55 | compat_long_t constant; | 55 | compat_long_t constant; |
56 | compat_long_t precision; | 56 | compat_long_t precision; |
57 | compat_long_t tolerance; | 57 | compat_long_t tolerance; |
58 | struct compat_timeval time; | 58 | struct compat_timeval time; |
59 | compat_long_t tick; | 59 | compat_long_t tick; |
60 | compat_long_t ppsfreq; | 60 | compat_long_t ppsfreq; |
61 | compat_long_t jitter; | 61 | compat_long_t jitter; |
62 | compat_int_t shift; | 62 | compat_int_t shift; |
63 | compat_long_t stabil; | 63 | compat_long_t stabil; |
64 | compat_long_t jitcnt; | 64 | compat_long_t jitcnt; |
65 | compat_long_t calcnt; | 65 | compat_long_t calcnt; |
66 | compat_long_t errcnt; | 66 | compat_long_t errcnt; |
67 | compat_long_t stbcnt; | 67 | compat_long_t stbcnt; |
68 | compat_int_t tai; | ||
68 | 69 | ||
69 | compat_int_t :32; compat_int_t :32; compat_int_t :32; compat_int_t :32; | 70 | compat_int_t :32; compat_int_t :32; compat_int_t :32; compat_int_t :32; |
70 | compat_int_t :32; compat_int_t :32; compat_int_t :32; compat_int_t :32; | 71 | compat_int_t :32; compat_int_t :32; compat_int_t :32; compat_int_t :32; |
71 | compat_int_t :32; compat_int_t :32; compat_int_t :32; compat_int_t :32; | 72 | compat_int_t :32; compat_int_t :32; compat_int_t :32; |
72 | }; | 73 | }; |
73 | 74 | ||
74 | #define _COMPAT_NSIG_WORDS (_COMPAT_NSIG / _COMPAT_NSIG_BPW) | 75 | #define _COMPAT_NSIG_WORDS (_COMPAT_NSIG / _COMPAT_NSIG_BPW) |
75 | 76 | ||
76 | typedef struct { | 77 | typedef struct { |
77 | compat_sigset_word sig[_COMPAT_NSIG_WORDS]; | 78 | compat_sigset_word sig[_COMPAT_NSIG_WORDS]; |
78 | } compat_sigset_t; | 79 | } compat_sigset_t; |
79 | 80 | ||
80 | extern int cp_compat_stat(struct kstat *, struct compat_stat __user *); | 81 | extern int cp_compat_stat(struct kstat *, struct compat_stat __user *); |
81 | extern int get_compat_timespec(struct timespec *, const struct compat_timespec __user *); | 82 | extern int get_compat_timespec(struct timespec *, const struct compat_timespec __user *); |
82 | extern int put_compat_timespec(const struct timespec *, struct compat_timespec __user *); | 83 | extern int put_compat_timespec(const struct timespec *, struct compat_timespec __user *); |
83 | 84 | ||
84 | struct compat_iovec { | 85 | struct compat_iovec { |
85 | compat_uptr_t iov_base; | 86 | compat_uptr_t iov_base; |
86 | compat_size_t iov_len; | 87 | compat_size_t iov_len; |
87 | }; | 88 | }; |
88 | 89 | ||
89 | struct compat_rlimit { | 90 | struct compat_rlimit { |
90 | compat_ulong_t rlim_cur; | 91 | compat_ulong_t rlim_cur; |
91 | compat_ulong_t rlim_max; | 92 | compat_ulong_t rlim_max; |
92 | }; | 93 | }; |
93 | 94 | ||
94 | struct compat_rusage { | 95 | struct compat_rusage { |
95 | struct compat_timeval ru_utime; | 96 | struct compat_timeval ru_utime; |
96 | struct compat_timeval ru_stime; | 97 | struct compat_timeval ru_stime; |
97 | compat_long_t ru_maxrss; | 98 | compat_long_t ru_maxrss; |
98 | compat_long_t ru_ixrss; | 99 | compat_long_t ru_ixrss; |
99 | compat_long_t ru_idrss; | 100 | compat_long_t ru_idrss; |
100 | compat_long_t ru_isrss; | 101 | compat_long_t ru_isrss; |
101 | compat_long_t ru_minflt; | 102 | compat_long_t ru_minflt; |
102 | compat_long_t ru_majflt; | 103 | compat_long_t ru_majflt; |
103 | compat_long_t ru_nswap; | 104 | compat_long_t ru_nswap; |
104 | compat_long_t ru_inblock; | 105 | compat_long_t ru_inblock; |
105 | compat_long_t ru_oublock; | 106 | compat_long_t ru_oublock; |
106 | compat_long_t ru_msgsnd; | 107 | compat_long_t ru_msgsnd; |
107 | compat_long_t ru_msgrcv; | 108 | compat_long_t ru_msgrcv; |
108 | compat_long_t ru_nsignals; | 109 | compat_long_t ru_nsignals; |
109 | compat_long_t ru_nvcsw; | 110 | compat_long_t ru_nvcsw; |
110 | compat_long_t ru_nivcsw; | 111 | compat_long_t ru_nivcsw; |
111 | }; | 112 | }; |
112 | 113 | ||
113 | extern int put_compat_rusage(const struct rusage *, struct compat_rusage __user *); | 114 | extern int put_compat_rusage(const struct rusage *, struct compat_rusage __user *); |
114 | 115 | ||
115 | struct compat_siginfo; | 116 | struct compat_siginfo; |
116 | 117 | ||
117 | extern asmlinkage long compat_sys_waitid(int, compat_pid_t, | 118 | extern asmlinkage long compat_sys_waitid(int, compat_pid_t, |
118 | struct compat_siginfo __user *, int, | 119 | struct compat_siginfo __user *, int, |
119 | struct compat_rusage __user *); | 120 | struct compat_rusage __user *); |
120 | 121 | ||
121 | struct compat_dirent { | 122 | struct compat_dirent { |
122 | u32 d_ino; | 123 | u32 d_ino; |
123 | compat_off_t d_off; | 124 | compat_off_t d_off; |
124 | u16 d_reclen; | 125 | u16 d_reclen; |
125 | char d_name[256]; | 126 | char d_name[256]; |
126 | }; | 127 | }; |
127 | 128 | ||
128 | typedef union compat_sigval { | 129 | typedef union compat_sigval { |
129 | compat_int_t sival_int; | 130 | compat_int_t sival_int; |
130 | compat_uptr_t sival_ptr; | 131 | compat_uptr_t sival_ptr; |
131 | } compat_sigval_t; | 132 | } compat_sigval_t; |
132 | 133 | ||
133 | #define COMPAT_SIGEV_PAD_SIZE ((SIGEV_MAX_SIZE/sizeof(int)) - 3) | 134 | #define COMPAT_SIGEV_PAD_SIZE ((SIGEV_MAX_SIZE/sizeof(int)) - 3) |
134 | 135 | ||
135 | typedef struct compat_sigevent { | 136 | typedef struct compat_sigevent { |
136 | compat_sigval_t sigev_value; | 137 | compat_sigval_t sigev_value; |
137 | compat_int_t sigev_signo; | 138 | compat_int_t sigev_signo; |
138 | compat_int_t sigev_notify; | 139 | compat_int_t sigev_notify; |
139 | union { | 140 | union { |
140 | compat_int_t _pad[COMPAT_SIGEV_PAD_SIZE]; | 141 | compat_int_t _pad[COMPAT_SIGEV_PAD_SIZE]; |
141 | compat_int_t _tid; | 142 | compat_int_t _tid; |
142 | 143 | ||
143 | struct { | 144 | struct { |
144 | compat_uptr_t _function; | 145 | compat_uptr_t _function; |
145 | compat_uptr_t _attribute; | 146 | compat_uptr_t _attribute; |
146 | } _sigev_thread; | 147 | } _sigev_thread; |
147 | } _sigev_un; | 148 | } _sigev_un; |
148 | } compat_sigevent_t; | 149 | } compat_sigevent_t; |
149 | 150 | ||
150 | struct compat_robust_list { | 151 | struct compat_robust_list { |
151 | compat_uptr_t next; | 152 | compat_uptr_t next; |
152 | }; | 153 | }; |
153 | 154 | ||
154 | struct compat_robust_list_head { | 155 | struct compat_robust_list_head { |
155 | struct compat_robust_list list; | 156 | struct compat_robust_list list; |
156 | compat_long_t futex_offset; | 157 | compat_long_t futex_offset; |
157 | compat_uptr_t list_op_pending; | 158 | compat_uptr_t list_op_pending; |
158 | }; | 159 | }; |
159 | 160 | ||
160 | extern void compat_exit_robust_list(struct task_struct *curr); | 161 | extern void compat_exit_robust_list(struct task_struct *curr); |
161 | 162 | ||
162 | asmlinkage long | 163 | asmlinkage long |
163 | compat_sys_set_robust_list(struct compat_robust_list_head __user *head, | 164 | compat_sys_set_robust_list(struct compat_robust_list_head __user *head, |
164 | compat_size_t len); | 165 | compat_size_t len); |
165 | asmlinkage long | 166 | asmlinkage long |
166 | compat_sys_get_robust_list(int pid, compat_uptr_t __user *head_ptr, | 167 | compat_sys_get_robust_list(int pid, compat_uptr_t __user *head_ptr, |
167 | compat_size_t __user *len_ptr); | 168 | compat_size_t __user *len_ptr); |
168 | 169 | ||
169 | long compat_sys_semctl(int first, int second, int third, void __user *uptr); | 170 | long compat_sys_semctl(int first, int second, int third, void __user *uptr); |
170 | long compat_sys_msgsnd(int first, int second, int third, void __user *uptr); | 171 | long compat_sys_msgsnd(int first, int second, int third, void __user *uptr); |
171 | long compat_sys_msgrcv(int first, int second, int msgtyp, int third, | 172 | long compat_sys_msgrcv(int first, int second, int msgtyp, int third, |
172 | int version, void __user *uptr); | 173 | int version, void __user *uptr); |
173 | long compat_sys_msgctl(int first, int second, void __user *uptr); | 174 | long compat_sys_msgctl(int first, int second, void __user *uptr); |
174 | long compat_sys_shmat(int first, int second, compat_uptr_t third, int version, | 175 | long compat_sys_shmat(int first, int second, compat_uptr_t third, int version, |
175 | void __user *uptr); | 176 | void __user *uptr); |
176 | long compat_sys_shmctl(int first, int second, void __user *uptr); | 177 | long compat_sys_shmctl(int first, int second, void __user *uptr); |
177 | long compat_sys_semtimedop(int semid, struct sembuf __user *tsems, | 178 | long compat_sys_semtimedop(int semid, struct sembuf __user *tsems, |
178 | unsigned nsems, const struct compat_timespec __user *timeout); | 179 | unsigned nsems, const struct compat_timespec __user *timeout); |
179 | asmlinkage long compat_sys_keyctl(u32 option, | 180 | asmlinkage long compat_sys_keyctl(u32 option, |
180 | u32 arg2, u32 arg3, u32 arg4, u32 arg5); | 181 | u32 arg2, u32 arg3, u32 arg4, u32 arg5); |
181 | 182 | ||
182 | asmlinkage ssize_t compat_sys_readv(unsigned long fd, | 183 | asmlinkage ssize_t compat_sys_readv(unsigned long fd, |
183 | const struct compat_iovec __user *vec, unsigned long vlen); | 184 | const struct compat_iovec __user *vec, unsigned long vlen); |
184 | asmlinkage ssize_t compat_sys_writev(unsigned long fd, | 185 | asmlinkage ssize_t compat_sys_writev(unsigned long fd, |
185 | const struct compat_iovec __user *vec, unsigned long vlen); | 186 | const struct compat_iovec __user *vec, unsigned long vlen); |
186 | 187 | ||
187 | int compat_do_execve(char * filename, compat_uptr_t __user *argv, | 188 | int compat_do_execve(char * filename, compat_uptr_t __user *argv, |
188 | compat_uptr_t __user *envp, struct pt_regs * regs); | 189 | compat_uptr_t __user *envp, struct pt_regs * regs); |
189 | 190 | ||
190 | asmlinkage long compat_sys_select(int n, compat_ulong_t __user *inp, | 191 | asmlinkage long compat_sys_select(int n, compat_ulong_t __user *inp, |
191 | compat_ulong_t __user *outp, compat_ulong_t __user *exp, | 192 | compat_ulong_t __user *outp, compat_ulong_t __user *exp, |
192 | struct compat_timeval __user *tvp); | 193 | struct compat_timeval __user *tvp); |
193 | 194 | ||
194 | asmlinkage long compat_sys_wait4(compat_pid_t pid, | 195 | asmlinkage long compat_sys_wait4(compat_pid_t pid, |
195 | compat_uint_t __user *stat_addr, int options, | 196 | compat_uint_t __user *stat_addr, int options, |
196 | struct compat_rusage __user *ru); | 197 | struct compat_rusage __user *ru); |
197 | 198 | ||
198 | #define BITS_PER_COMPAT_LONG (8*sizeof(compat_long_t)) | 199 | #define BITS_PER_COMPAT_LONG (8*sizeof(compat_long_t)) |
199 | 200 | ||
200 | #define BITS_TO_COMPAT_LONGS(bits) \ | 201 | #define BITS_TO_COMPAT_LONGS(bits) \ |
201 | (((bits)+BITS_PER_COMPAT_LONG-1)/BITS_PER_COMPAT_LONG) | 202 | (((bits)+BITS_PER_COMPAT_LONG-1)/BITS_PER_COMPAT_LONG) |
202 | 203 | ||
203 | long compat_get_bitmap(unsigned long *mask, const compat_ulong_t __user *umask, | 204 | long compat_get_bitmap(unsigned long *mask, const compat_ulong_t __user *umask, |
204 | unsigned long bitmap_size); | 205 | unsigned long bitmap_size); |
205 | long compat_put_bitmap(compat_ulong_t __user *umask, unsigned long *mask, | 206 | long compat_put_bitmap(compat_ulong_t __user *umask, unsigned long *mask, |
206 | unsigned long bitmap_size); | 207 | unsigned long bitmap_size); |
207 | int copy_siginfo_from_user32(siginfo_t *to, struct compat_siginfo __user *from); | 208 | int copy_siginfo_from_user32(siginfo_t *to, struct compat_siginfo __user *from); |
208 | int copy_siginfo_to_user32(struct compat_siginfo __user *to, siginfo_t *from); | 209 | int copy_siginfo_to_user32(struct compat_siginfo __user *to, siginfo_t *from); |
209 | int get_compat_sigevent(struct sigevent *event, | 210 | int get_compat_sigevent(struct sigevent *event, |
210 | const struct compat_sigevent __user *u_event); | 211 | const struct compat_sigevent __user *u_event); |
211 | 212 | ||
212 | static inline int compat_timeval_compare(struct compat_timeval *lhs, | 213 | static inline int compat_timeval_compare(struct compat_timeval *lhs, |
213 | struct compat_timeval *rhs) | 214 | struct compat_timeval *rhs) |
214 | { | 215 | { |
215 | if (lhs->tv_sec < rhs->tv_sec) | 216 | if (lhs->tv_sec < rhs->tv_sec) |
216 | return -1; | 217 | return -1; |
217 | if (lhs->tv_sec > rhs->tv_sec) | 218 | if (lhs->tv_sec > rhs->tv_sec) |
218 | return 1; | 219 | return 1; |
219 | return lhs->tv_usec - rhs->tv_usec; | 220 | return lhs->tv_usec - rhs->tv_usec; |
220 | } | 221 | } |
221 | 222 | ||
222 | static inline int compat_timespec_compare(struct compat_timespec *lhs, | 223 | static inline int compat_timespec_compare(struct compat_timespec *lhs, |
223 | struct compat_timespec *rhs) | 224 | struct compat_timespec *rhs) |
224 | { | 225 | { |
225 | if (lhs->tv_sec < rhs->tv_sec) | 226 | if (lhs->tv_sec < rhs->tv_sec) |
226 | return -1; | 227 | return -1; |
227 | if (lhs->tv_sec > rhs->tv_sec) | 228 | if (lhs->tv_sec > rhs->tv_sec) |
228 | return 1; | 229 | return 1; |
229 | return lhs->tv_nsec - rhs->tv_nsec; | 230 | return lhs->tv_nsec - rhs->tv_nsec; |
230 | } | 231 | } |
231 | 232 | ||
232 | extern int get_compat_itimerspec(struct itimerspec *dst, | 233 | extern int get_compat_itimerspec(struct itimerspec *dst, |
233 | const struct compat_itimerspec __user *src); | 234 | const struct compat_itimerspec __user *src); |
234 | extern int put_compat_itimerspec(struct compat_itimerspec __user *dst, | 235 | extern int put_compat_itimerspec(struct compat_itimerspec __user *dst, |
235 | const struct itimerspec *src); | 236 | const struct itimerspec *src); |
236 | 237 | ||
237 | asmlinkage long compat_sys_adjtimex(struct compat_timex __user *utp); | 238 | asmlinkage long compat_sys_adjtimex(struct compat_timex __user *utp); |
238 | 239 | ||
239 | extern int compat_printk(const char *fmt, ...); | 240 | extern int compat_printk(const char *fmt, ...); |
240 | extern void sigset_from_compat(sigset_t *set, compat_sigset_t *compat); | 241 | extern void sigset_from_compat(sigset_t *set, compat_sigset_t *compat); |
241 | 242 | ||
242 | asmlinkage long compat_sys_migrate_pages(compat_pid_t pid, | 243 | asmlinkage long compat_sys_migrate_pages(compat_pid_t pid, |
243 | compat_ulong_t maxnode, const compat_ulong_t __user *old_nodes, | 244 | compat_ulong_t maxnode, const compat_ulong_t __user *old_nodes, |
244 | const compat_ulong_t __user *new_nodes); | 245 | const compat_ulong_t __user *new_nodes); |
245 | 246 | ||
246 | extern int compat_ptrace_request(struct task_struct *child, | 247 | extern int compat_ptrace_request(struct task_struct *child, |
247 | compat_long_t request, | 248 | compat_long_t request, |
248 | compat_ulong_t addr, compat_ulong_t data); | 249 | compat_ulong_t addr, compat_ulong_t data); |
249 | 250 | ||
250 | #ifdef __ARCH_WANT_COMPAT_SYS_PTRACE | 251 | #ifdef __ARCH_WANT_COMPAT_SYS_PTRACE |
251 | extern long compat_arch_ptrace(struct task_struct *child, compat_long_t request, | 252 | extern long compat_arch_ptrace(struct task_struct *child, compat_long_t request, |
252 | compat_ulong_t addr, compat_ulong_t data); | 253 | compat_ulong_t addr, compat_ulong_t data); |
253 | asmlinkage long compat_sys_ptrace(compat_long_t request, compat_long_t pid, | 254 | asmlinkage long compat_sys_ptrace(compat_long_t request, compat_long_t pid, |
254 | compat_long_t addr, compat_long_t data); | 255 | compat_long_t addr, compat_long_t data); |
255 | #endif /* __ARCH_WANT_COMPAT_SYS_PTRACE */ | 256 | #endif /* __ARCH_WANT_COMPAT_SYS_PTRACE */ |
256 | 257 | ||
257 | /* | 258 | /* |
258 | * epoll (fs/eventpoll.c) compat bits follow ... | 259 | * epoll (fs/eventpoll.c) compat bits follow ... |
259 | */ | 260 | */ |
260 | struct epoll_event; | 261 | struct epoll_event; |
261 | #define compat_epoll_event epoll_event | 262 | #define compat_epoll_event epoll_event |
262 | asmlinkage long compat_sys_epoll_pwait(int epfd, | 263 | asmlinkage long compat_sys_epoll_pwait(int epfd, |
263 | struct compat_epoll_event __user *events, | 264 | struct compat_epoll_event __user *events, |
264 | int maxevents, int timeout, | 265 | int maxevents, int timeout, |
265 | const compat_sigset_t __user *sigmask, | 266 | const compat_sigset_t __user *sigmask, |
266 | compat_size_t sigsetsize); | 267 | compat_size_t sigsetsize); |
267 | 268 | ||
268 | asmlinkage long compat_sys_utimensat(unsigned int dfd, char __user *filename, | 269 | asmlinkage long compat_sys_utimensat(unsigned int dfd, char __user *filename, |
269 | struct compat_timespec __user *t, int flags); | 270 | struct compat_timespec __user *t, int flags); |
270 | 271 | ||
271 | asmlinkage long compat_sys_signalfd(int ufd, | 272 | asmlinkage long compat_sys_signalfd(int ufd, |
272 | const compat_sigset_t __user *sigmask, | 273 | const compat_sigset_t __user *sigmask, |
273 | compat_size_t sigsetsize); | 274 | compat_size_t sigsetsize); |
274 | asmlinkage long compat_sys_timerfd_settime(int ufd, int flags, | 275 | asmlinkage long compat_sys_timerfd_settime(int ufd, int flags, |
275 | const struct compat_itimerspec __user *utmr, | 276 | const struct compat_itimerspec __user *utmr, |
276 | struct compat_itimerspec __user *otmr); | 277 | struct compat_itimerspec __user *otmr); |
277 | asmlinkage long compat_sys_timerfd_gettime(int ufd, | 278 | asmlinkage long compat_sys_timerfd_gettime(int ufd, |
278 | struct compat_itimerspec __user *otmr); | 279 | struct compat_itimerspec __user *otmr); |
279 | 280 | ||
280 | #endif /* CONFIG_COMPAT */ | 281 | #endif /* CONFIG_COMPAT */ |
281 | #endif /* _LINUX_COMPAT_H */ | 282 | #endif /* _LINUX_COMPAT_H */ |
282 | 283 |
include/linux/timex.h
1 | /***************************************************************************** | 1 | /***************************************************************************** |
2 | * * | 2 | * * |
3 | * Copyright (c) David L. Mills 1993 * | 3 | * Copyright (c) David L. Mills 1993 * |
4 | * * | 4 | * * |
5 | * Permission to use, copy, modify, and distribute this software and its * | 5 | * Permission to use, copy, modify, and distribute this software and its * |
6 | * documentation for any purpose and without fee is hereby granted, provided * | 6 | * documentation for any purpose and without fee is hereby granted, provided * |
7 | * that the above copyright notice appears in all copies and that both the * | 7 | * that the above copyright notice appears in all copies and that both the * |
8 | * copyright notice and this permission notice appear in supporting * | 8 | * copyright notice and this permission notice appear in supporting * |
9 | * documentation, and that the name University of Delaware not be used in * | 9 | * documentation, and that the name University of Delaware not be used in * |
10 | * advertising or publicity pertaining to distribution of the software * | 10 | * advertising or publicity pertaining to distribution of the software * |
11 | * without specific, written prior permission. The University of Delaware * | 11 | * without specific, written prior permission. The University of Delaware * |
12 | * makes no representations about the suitability this software for any * | 12 | * makes no representations about the suitability this software for any * |
13 | * purpose. It is provided "as is" without express or implied warranty. * | 13 | * purpose. It is provided "as is" without express or implied warranty. * |
14 | * * | 14 | * * |
15 | *****************************************************************************/ | 15 | *****************************************************************************/ |
16 | 16 | ||
17 | /* | 17 | /* |
18 | * Modification history timex.h | 18 | * Modification history timex.h |
19 | * | 19 | * |
20 | * 29 Dec 97 Russell King | 20 | * 29 Dec 97 Russell King |
21 | * Moved CLOCK_TICK_RATE, CLOCK_TICK_FACTOR and FINETUNE to asm/timex.h | 21 | * Moved CLOCK_TICK_RATE, CLOCK_TICK_FACTOR and FINETUNE to asm/timex.h |
22 | * for ARM machines | 22 | * for ARM machines |
23 | * | 23 | * |
24 | * 9 Jan 97 Adrian Sun | 24 | * 9 Jan 97 Adrian Sun |
25 | * Shifted LATCH define to allow access to alpha machines. | 25 | * Shifted LATCH define to allow access to alpha machines. |
26 | * | 26 | * |
27 | * 26 Sep 94 David L. Mills | 27 | * 26 Sep 94 David L. Mills |
28 | * Added defines for hybrid phase/frequency-lock loop. | 28 | * Added defines for hybrid phase/frequency-lock loop. |
29 | * | 29 | * |
30 | * 19 Mar 94 David L. Mills | 30 | * 19 Mar 94 David L. Mills |
31 | * Moved defines from kernel routines to header file and added new | 31 | * Moved defines from kernel routines to header file and added new |
32 | * defines for PPS phase-lock loop. | 32 | * defines for PPS phase-lock loop. |
33 | * | 33 | * |
34 | * 20 Feb 94 David L. Mills | 34 | * 20 Feb 94 David L. Mills |
35 | * Revised status codes and structures for external clock and PPS | 35 | * Revised status codes and structures for external clock and PPS |
36 | * signal discipline. | 36 | * signal discipline. |
37 | * | 37 | * |
38 | * 28 Nov 93 David L. Mills | 38 | * 28 Nov 93 David L. Mills |
39 | * Adjusted parameters to improve stability and increase poll | 39 | * Adjusted parameters to improve stability and increase poll |
40 | * interval. | 40 | * interval. |
41 | * | 41 | * |
42 | * 17 Sep 93 David L. Mills | 42 | * 17 Sep 93 David L. Mills |
43 | * Created file $NTP/include/sys/timex.h | 43 | * Created file $NTP/include/sys/timex.h |
44 | * 07 Oct 93 Torsten Duwe | 44 | * 07 Oct 93 Torsten Duwe |
45 | * Derived linux/timex.h | 45 | * Derived linux/timex.h |
46 | * 1995-08-13 Torsten Duwe | 46 | * 1995-08-13 Torsten Duwe |
47 | * kernel PLL updated to 1994-12-13 specs (rfc-1589) | 47 | * kernel PLL updated to 1994-12-13 specs (rfc-1589) |
48 | * 1997-08-30 Ulrich Windl | 48 | * 1997-08-30 Ulrich Windl |
49 | * Added new constant NTP_PHASE_LIMIT | 49 | * Added new constant NTP_PHASE_LIMIT |
50 | * 2004-08-12 Christoph Lameter | 50 | * 2004-08-12 Christoph Lameter |
51 | * Reworked time interpolation logic | 51 | * Reworked time interpolation logic |
52 | */ | 52 | */ |
53 | #ifndef _LINUX_TIMEX_H | 53 | #ifndef _LINUX_TIMEX_H |
54 | #define _LINUX_TIMEX_H | 54 | #define _LINUX_TIMEX_H |
55 | 55 | ||
56 | #include <linux/compiler.h> | 56 | #include <linux/compiler.h> |
57 | #include <linux/time.h> | 57 | #include <linux/time.h> |
58 | 58 | ||
59 | #include <asm/param.h> | 59 | #include <asm/param.h> |
60 | 60 | ||
61 | #define NTP_API 4 /* NTP API version */ | 61 | #define NTP_API 4 /* NTP API version */ |
62 | 62 | ||
63 | /* | 63 | /* |
64 | * SHIFT_KG and SHIFT_KF establish the damping of the PLL and are chosen | 64 | * SHIFT_KG and SHIFT_KF establish the damping of the PLL and are chosen |
65 | * for a slightly underdamped convergence characteristic. SHIFT_KH | 65 | * for a slightly underdamped convergence characteristic. SHIFT_KH |
66 | * establishes the damping of the FLL and is chosen by wisdom and black | 66 | * establishes the damping of the FLL and is chosen by wisdom and black |
67 | * art. | 67 | * art. |
68 | * | 68 | * |
69 | * MAXTC establishes the maximum time constant of the PLL. With the | 69 | * MAXTC establishes the maximum time constant of the PLL. With the |
70 | * SHIFT_KG and SHIFT_KF values given and a time constant range from | 70 | * SHIFT_KG and SHIFT_KF values given and a time constant range from |
71 | * zero to MAXTC, the PLL will converge in 15 minutes to 16 hours, | 71 | * zero to MAXTC, the PLL will converge in 15 minutes to 16 hours, |
72 | * respectively. | 72 | * respectively. |
73 | */ | 73 | */ |
74 | #define SHIFT_PLL 4 /* PLL frequency factor (shift) */ | 74 | #define SHIFT_PLL 4 /* PLL frequency factor (shift) */ |
75 | #define SHIFT_FLL 2 /* FLL frequency factor (shift) */ | 75 | #define SHIFT_FLL 2 /* FLL frequency factor (shift) */ |
76 | #define MAXTC 10 /* maximum time constant (shift) */ | 76 | #define MAXTC 10 /* maximum time constant (shift) */ |
77 | 77 | ||
78 | /* | 78 | /* |
79 | * SHIFT_USEC defines the scaling (shift) of the time_freq and | 79 | * SHIFT_USEC defines the scaling (shift) of the time_freq and |
80 | * time_tolerance variables, which represent the current frequency | 80 | * time_tolerance variables, which represent the current frequency |
81 | * offset and maximum frequency tolerance. | 81 | * offset and maximum frequency tolerance. |
82 | */ | 82 | */ |
83 | #define SHIFT_USEC 16 /* frequency offset scale (shift) */ | 83 | #define SHIFT_USEC 16 /* frequency offset scale (shift) */ |
84 | #define PPM_SCALE (NSEC_PER_USEC << (TICK_LENGTH_SHIFT - SHIFT_USEC)) | 84 | #define PPM_SCALE (NSEC_PER_USEC << (TICK_LENGTH_SHIFT - SHIFT_USEC)) |
85 | #define PPM_SCALE_INV_SHIFT 20 | 85 | #define PPM_SCALE_INV_SHIFT 20 |
86 | #define PPM_SCALE_INV ((1ll << (PPM_SCALE_INV_SHIFT + TICK_LENGTH_SHIFT)) / \ | 86 | #define PPM_SCALE_INV ((1ll << (PPM_SCALE_INV_SHIFT + TICK_LENGTH_SHIFT)) / \ |
87 | PPM_SCALE + 1) | 87 | PPM_SCALE + 1) |
88 | 88 | ||
89 | #define MAXPHASE 500000000l /* max phase error (ns) */ | 89 | #define MAXPHASE 500000000l /* max phase error (ns) */ |
90 | #define MAXFREQ 500000 /* max frequency error (ns/s) */ | 90 | #define MAXFREQ 500000 /* max frequency error (ns/s) */ |
91 | #define MAXFREQ_SCALED ((s64)MAXFREQ << TICK_LENGTH_SHIFT) | 91 | #define MAXFREQ_SCALED ((s64)MAXFREQ << TICK_LENGTH_SHIFT) |
92 | #define MINSEC 256 /* min interval between updates (s) */ | 92 | #define MINSEC 256 /* min interval between updates (s) */ |
93 | #define MAXSEC 2048 /* max interval between updates (s) */ | 93 | #define MAXSEC 2048 /* max interval between updates (s) */ |
94 | #define NTP_PHASE_LIMIT ((MAXPHASE / NSEC_PER_USEC) << 5) /* beyond max. dispersion */ | 94 | #define NTP_PHASE_LIMIT ((MAXPHASE / NSEC_PER_USEC) << 5) /* beyond max. dispersion */ |
95 | 95 | ||
96 | /* | 96 | /* |
97 | * syscall interface - used (mainly by NTP daemon) | 97 | * syscall interface - used (mainly by NTP daemon) |
98 | * to discipline kernel clock oscillator | 98 | * to discipline kernel clock oscillator |
99 | */ | 99 | */ |
100 | struct timex { | 100 | struct timex { |
101 | unsigned int modes; /* mode selector */ | 101 | unsigned int modes; /* mode selector */ |
102 | long offset; /* time offset (usec) */ | 102 | long offset; /* time offset (usec) */ |
103 | long freq; /* frequency offset (scaled ppm) */ | 103 | long freq; /* frequency offset (scaled ppm) */ |
104 | long maxerror; /* maximum error (usec) */ | 104 | long maxerror; /* maximum error (usec) */ |
105 | long esterror; /* estimated error (usec) */ | 105 | long esterror; /* estimated error (usec) */ |
106 | int status; /* clock command/status */ | 106 | int status; /* clock command/status */ |
107 | long constant; /* pll time constant */ | 107 | long constant; /* pll time constant */ |
108 | long precision; /* clock precision (usec) (read only) */ | 108 | long precision; /* clock precision (usec) (read only) */ |
109 | long tolerance; /* clock frequency tolerance (ppm) | 109 | long tolerance; /* clock frequency tolerance (ppm) |
110 | * (read only) | 110 | * (read only) |
111 | */ | 111 | */ |
112 | struct timeval time; /* (read only) */ | 112 | struct timeval time; /* (read only) */ |
113 | long tick; /* (modified) usecs between clock ticks */ | 113 | long tick; /* (modified) usecs between clock ticks */ |
114 | 114 | ||
115 | long ppsfreq; /* pps frequency (scaled ppm) (ro) */ | 115 | long ppsfreq; /* pps frequency (scaled ppm) (ro) */ |
116 | long jitter; /* pps jitter (us) (ro) */ | 116 | long jitter; /* pps jitter (us) (ro) */ |
117 | int shift; /* interval duration (s) (shift) (ro) */ | 117 | int shift; /* interval duration (s) (shift) (ro) */ |
118 | long stabil; /* pps stability (scaled ppm) (ro) */ | 118 | long stabil; /* pps stability (scaled ppm) (ro) */ |
119 | long jitcnt; /* jitter limit exceeded (ro) */ | 119 | long jitcnt; /* jitter limit exceeded (ro) */ |
120 | long calcnt; /* calibration intervals (ro) */ | 120 | long calcnt; /* calibration intervals (ro) */ |
121 | long errcnt; /* calibration errors (ro) */ | 121 | long errcnt; /* calibration errors (ro) */ |
122 | long stbcnt; /* stability limit exceeded (ro) */ | 122 | long stbcnt; /* stability limit exceeded (ro) */ |
123 | 123 | ||
124 | int tai; /* TAI offset (ro) */ | ||
125 | |||
124 | int :32; int :32; int :32; int :32; | 126 | int :32; int :32; int :32; int :32; |
125 | int :32; int :32; int :32; int :32; | 127 | int :32; int :32; int :32; int :32; |
126 | int :32; int :32; int :32; int :32; | 128 | int :32; int :32; int :32; |
127 | }; | 129 | }; |
128 | 130 | ||
129 | /* | 131 | /* |
130 | * Mode codes (timex.mode) | 132 | * Mode codes (timex.mode) |
131 | */ | 133 | */ |
132 | #define ADJ_OFFSET 0x0001 /* time offset */ | 134 | #define ADJ_OFFSET 0x0001 /* time offset */ |
133 | #define ADJ_FREQUENCY 0x0002 /* frequency offset */ | 135 | #define ADJ_FREQUENCY 0x0002 /* frequency offset */ |
134 | #define ADJ_MAXERROR 0x0004 /* maximum time error */ | 136 | #define ADJ_MAXERROR 0x0004 /* maximum time error */ |
135 | #define ADJ_ESTERROR 0x0008 /* estimated time error */ | 137 | #define ADJ_ESTERROR 0x0008 /* estimated time error */ |
136 | #define ADJ_STATUS 0x0010 /* clock status */ | 138 | #define ADJ_STATUS 0x0010 /* clock status */ |
137 | #define ADJ_TIMECONST 0x0020 /* pll time constant */ | 139 | #define ADJ_TIMECONST 0x0020 /* pll time constant */ |
140 | #define ADJ_TAI 0x0080 /* set TAI offset */ | ||
138 | #define ADJ_MICRO 0x1000 /* select microsecond resolution */ | 141 | #define ADJ_MICRO 0x1000 /* select microsecond resolution */ |
139 | #define ADJ_NANO 0x2000 /* select nanosecond resolution */ | 142 | #define ADJ_NANO 0x2000 /* select nanosecond resolution */ |
140 | #define ADJ_TICK 0x4000 /* tick value */ | 143 | #define ADJ_TICK 0x4000 /* tick value */ |
141 | #define ADJ_OFFSET_SINGLESHOT 0x8001 /* old-fashioned adjtime */ | 144 | #define ADJ_OFFSET_SINGLESHOT 0x8001 /* old-fashioned adjtime */ |
142 | #define ADJ_OFFSET_SS_READ 0xa001 /* read-only adjtime */ | 145 | #define ADJ_OFFSET_SS_READ 0xa001 /* read-only adjtime */ |
143 | 146 | ||
144 | /* xntp 3.4 compatibility names */ | 147 | /* xntp 3.4 compatibility names */ |
145 | #define MOD_OFFSET ADJ_OFFSET | 148 | #define MOD_OFFSET ADJ_OFFSET |
146 | #define MOD_FREQUENCY ADJ_FREQUENCY | 149 | #define MOD_FREQUENCY ADJ_FREQUENCY |
147 | #define MOD_MAXERROR ADJ_MAXERROR | 150 | #define MOD_MAXERROR ADJ_MAXERROR |
148 | #define MOD_ESTERROR ADJ_ESTERROR | 151 | #define MOD_ESTERROR ADJ_ESTERROR |
149 | #define MOD_STATUS ADJ_STATUS | 152 | #define MOD_STATUS ADJ_STATUS |
150 | #define MOD_TIMECONST ADJ_TIMECONST | 153 | #define MOD_TIMECONST ADJ_TIMECONST |
151 | 154 | ||
152 | 155 | ||
153 | /* | 156 | /* |
154 | * Status codes (timex.status) | 157 | * Status codes (timex.status) |
155 | */ | 158 | */ |
156 | #define STA_PLL 0x0001 /* enable PLL updates (rw) */ | 159 | #define STA_PLL 0x0001 /* enable PLL updates (rw) */ |
157 | #define STA_PPSFREQ 0x0002 /* enable PPS freq discipline (rw) */ | 160 | #define STA_PPSFREQ 0x0002 /* enable PPS freq discipline (rw) */ |
158 | #define STA_PPSTIME 0x0004 /* enable PPS time discipline (rw) */ | 161 | #define STA_PPSTIME 0x0004 /* enable PPS time discipline (rw) */ |
159 | #define STA_FLL 0x0008 /* select frequency-lock mode (rw) */ | 162 | #define STA_FLL 0x0008 /* select frequency-lock mode (rw) */ |
160 | 163 | ||
161 | #define STA_INS 0x0010 /* insert leap (rw) */ | 164 | #define STA_INS 0x0010 /* insert leap (rw) */ |
162 | #define STA_DEL 0x0020 /* delete leap (rw) */ | 165 | #define STA_DEL 0x0020 /* delete leap (rw) */ |
163 | #define STA_UNSYNC 0x0040 /* clock unsynchronized (rw) */ | 166 | #define STA_UNSYNC 0x0040 /* clock unsynchronized (rw) */ |
164 | #define STA_FREQHOLD 0x0080 /* hold frequency (rw) */ | 167 | #define STA_FREQHOLD 0x0080 /* hold frequency (rw) */ |
165 | 168 | ||
166 | #define STA_PPSSIGNAL 0x0100 /* PPS signal present (ro) */ | 169 | #define STA_PPSSIGNAL 0x0100 /* PPS signal present (ro) */ |
167 | #define STA_PPSJITTER 0x0200 /* PPS signal jitter exceeded (ro) */ | 170 | #define STA_PPSJITTER 0x0200 /* PPS signal jitter exceeded (ro) */ |
168 | #define STA_PPSWANDER 0x0400 /* PPS signal wander exceeded (ro) */ | 171 | #define STA_PPSWANDER 0x0400 /* PPS signal wander exceeded (ro) */ |
169 | #define STA_PPSERROR 0x0800 /* PPS signal calibration error (ro) */ | 172 | #define STA_PPSERROR 0x0800 /* PPS signal calibration error (ro) */ |
170 | 173 | ||
171 | #define STA_CLOCKERR 0x1000 /* clock hardware fault (ro) */ | 174 | #define STA_CLOCKERR 0x1000 /* clock hardware fault (ro) */ |
172 | #define STA_NANO 0x2000 /* resolution (0 = us, 1 = ns) (ro) */ | 175 | #define STA_NANO 0x2000 /* resolution (0 = us, 1 = ns) (ro) */ |
173 | #define STA_MODE 0x4000 /* mode (0 = PLL, 1 = FLL) (ro) */ | 176 | #define STA_MODE 0x4000 /* mode (0 = PLL, 1 = FLL) (ro) */ |
174 | #define STA_CLK 0x8000 /* clock source (0 = A, 1 = B) (ro) */ | 177 | #define STA_CLK 0x8000 /* clock source (0 = A, 1 = B) (ro) */ |
175 | 178 | ||
176 | /* read-only bits */ | 179 | /* read-only bits */ |
177 | #define STA_RONLY (STA_PPSSIGNAL | STA_PPSJITTER | STA_PPSWANDER | \ | 180 | #define STA_RONLY (STA_PPSSIGNAL | STA_PPSJITTER | STA_PPSWANDER | \ |
178 | STA_PPSERROR | STA_CLOCKERR | STA_NANO | STA_MODE | STA_CLK) | 181 | STA_PPSERROR | STA_CLOCKERR | STA_NANO | STA_MODE | STA_CLK) |
179 | 182 | ||
180 | /* | 183 | /* |
181 | * Clock states (time_state) | 184 | * Clock states (time_state) |
182 | */ | 185 | */ |
183 | #define TIME_OK 0 /* clock synchronized, no leap second */ | 186 | #define TIME_OK 0 /* clock synchronized, no leap second */ |
184 | #define TIME_INS 1 /* insert leap second */ | 187 | #define TIME_INS 1 /* insert leap second */ |
185 | #define TIME_DEL 2 /* delete leap second */ | 188 | #define TIME_DEL 2 /* delete leap second */ |
186 | #define TIME_OOP 3 /* leap second in progress */ | 189 | #define TIME_OOP 3 /* leap second in progress */ |
187 | #define TIME_WAIT 4 /* leap second has occurred */ | 190 | #define TIME_WAIT 4 /* leap second has occurred */ |
188 | #define TIME_ERROR 5 /* clock not synchronized */ | 191 | #define TIME_ERROR 5 /* clock not synchronized */ |
189 | #define TIME_BAD TIME_ERROR /* bw compat */ | 192 | #define TIME_BAD TIME_ERROR /* bw compat */ |
190 | 193 | ||
191 | #ifdef __KERNEL__ | 194 | #ifdef __KERNEL__ |
192 | #include <asm/timex.h> | 195 | #include <asm/timex.h> |
193 | 196 | ||
194 | /* | 197 | /* |
195 | * kernel variables | 198 | * kernel variables |
196 | * Note: maximum error = NTP synch distance = dispersion + delay / 2; | 199 | * Note: maximum error = NTP synch distance = dispersion + delay / 2; |
197 | * estimated error = NTP dispersion. | 200 | * estimated error = NTP dispersion. |
198 | */ | 201 | */ |
199 | extern unsigned long tick_usec; /* USER_HZ period (usec) */ | 202 | extern unsigned long tick_usec; /* USER_HZ period (usec) */ |
200 | extern unsigned long tick_nsec; /* ACTHZ period (nsec) */ | 203 | extern unsigned long tick_nsec; /* ACTHZ period (nsec) */ |
201 | extern int tickadj; /* amount of adjustment per tick */ | 204 | extern int tickadj; /* amount of adjustment per tick */ |
202 | 205 | ||
203 | /* | 206 | /* |
204 | * phase-lock loop variables | 207 | * phase-lock loop variables |
205 | */ | 208 | */ |
206 | extern int time_status; /* clock synchronization status bits */ | 209 | extern int time_status; /* clock synchronization status bits */ |
207 | extern long time_maxerror; /* maximum error */ | 210 | extern long time_maxerror; /* maximum error */ |
208 | extern long time_esterror; /* estimated error */ | 211 | extern long time_esterror; /* estimated error */ |
209 | 212 | ||
210 | extern long time_adjust; /* The amount of adjtime left */ | 213 | extern long time_adjust; /* The amount of adjtime left */ |
211 | 214 | ||
212 | extern void ntp_clear(void); | 215 | extern void ntp_clear(void); |
213 | 216 | ||
214 | /** | 217 | /** |
215 | * ntp_synced - Returns 1 if the NTP status is not UNSYNC | 218 | * ntp_synced - Returns 1 if the NTP status is not UNSYNC |
216 | * | 219 | * |
217 | */ | 220 | */ |
218 | static inline int ntp_synced(void) | 221 | static inline int ntp_synced(void) |
219 | { | 222 | { |
220 | return !(time_status & STA_UNSYNC); | 223 | return !(time_status & STA_UNSYNC); |
221 | } | 224 | } |
222 | 225 | ||
223 | /* Required to safely shift negative values */ | 226 | /* Required to safely shift negative values */ |
224 | #define shift_right(x, s) ({ \ | 227 | #define shift_right(x, s) ({ \ |
225 | __typeof__(x) __x = (x); \ | 228 | __typeof__(x) __x = (x); \ |
226 | __typeof__(s) __s = (s); \ | 229 | __typeof__(s) __s = (s); \ |
227 | __x < 0 ? -(-__x >> __s) : __x >> __s; \ | 230 | __x < 0 ? -(-__x >> __s) : __x >> __s; \ |
228 | }) | 231 | }) |
229 | 232 | ||
230 | #define TICK_LENGTH_SHIFT 32 | 233 | #define TICK_LENGTH_SHIFT 32 |
231 | 234 | ||
232 | #ifdef CONFIG_NO_HZ | 235 | #ifdef CONFIG_NO_HZ |
233 | #define NTP_INTERVAL_FREQ (2) | 236 | #define NTP_INTERVAL_FREQ (2) |
234 | #else | 237 | #else |
235 | #define NTP_INTERVAL_FREQ (HZ) | 238 | #define NTP_INTERVAL_FREQ (HZ) |
236 | #endif | 239 | #endif |
237 | #define NTP_INTERVAL_LENGTH (NSEC_PER_SEC/NTP_INTERVAL_FREQ) | 240 | #define NTP_INTERVAL_LENGTH (NSEC_PER_SEC/NTP_INTERVAL_FREQ) |
238 | 241 | ||
239 | /* Returns how long ticks are at present, in ns / 2^(SHIFT_SCALE-10). */ | 242 | /* Returns how long ticks are at present, in ns / 2^(SHIFT_SCALE-10). */ |
240 | extern u64 current_tick_length(void); | 243 | extern u64 current_tick_length(void); |
241 | 244 | ||
242 | extern void second_overflow(void); | 245 | extern void second_overflow(void); |
243 | extern void update_ntp_one_tick(void); | 246 | extern void update_ntp_one_tick(void); |
244 | extern int do_adjtimex(struct timex *); | 247 | extern int do_adjtimex(struct timex *); |
245 | 248 | ||
246 | /* Don't use! Compatibility define for existing users. */ | 249 | /* Don't use! Compatibility define for existing users. */ |
247 | #define tickadj (500/HZ ? : 1) | 250 | #define tickadj (500/HZ ? : 1) |
248 | 251 | ||
249 | int read_current_timer(unsigned long *timer_val); | 252 | int read_current_timer(unsigned long *timer_val); |
250 | 253 | ||
251 | #endif /* KERNEL */ | 254 | #endif /* KERNEL */ |
252 | 255 | ||
253 | #endif /* LINUX_TIMEX_H */ | 256 | #endif /* LINUX_TIMEX_H */ |
254 | 257 |
kernel/compat.c
1 | /* | 1 | /* |
2 | * linux/kernel/compat.c | 2 | * linux/kernel/compat.c |
3 | * | 3 | * |
4 | * Kernel compatibililty routines for e.g. 32 bit syscall support | 4 | * Kernel compatibililty routines for e.g. 32 bit syscall support |
5 | * on 64 bit kernels. | 5 | * on 64 bit kernels. |
6 | * | 6 | * |
7 | * Copyright (C) 2002-2003 Stephen Rothwell, IBM Corporation | 7 | * Copyright (C) 2002-2003 Stephen Rothwell, IBM Corporation |
8 | * | 8 | * |
9 | * This program is free software; you can redistribute it and/or modify | 9 | * This program is free software; you can redistribute it and/or modify |
10 | * it under the terms of the GNU General Public License version 2 as | 10 | * it under the terms of the GNU General Public License version 2 as |
11 | * published by the Free Software Foundation. | 11 | * published by the Free Software Foundation. |
12 | */ | 12 | */ |
13 | 13 | ||
14 | #include <linux/linkage.h> | 14 | #include <linux/linkage.h> |
15 | #include <linux/compat.h> | 15 | #include <linux/compat.h> |
16 | #include <linux/errno.h> | 16 | #include <linux/errno.h> |
17 | #include <linux/time.h> | 17 | #include <linux/time.h> |
18 | #include <linux/signal.h> | 18 | #include <linux/signal.h> |
19 | #include <linux/sched.h> /* for MAX_SCHEDULE_TIMEOUT */ | 19 | #include <linux/sched.h> /* for MAX_SCHEDULE_TIMEOUT */ |
20 | #include <linux/syscalls.h> | 20 | #include <linux/syscalls.h> |
21 | #include <linux/unistd.h> | 21 | #include <linux/unistd.h> |
22 | #include <linux/security.h> | 22 | #include <linux/security.h> |
23 | #include <linux/timex.h> | 23 | #include <linux/timex.h> |
24 | #include <linux/migrate.h> | 24 | #include <linux/migrate.h> |
25 | #include <linux/posix-timers.h> | 25 | #include <linux/posix-timers.h> |
26 | 26 | ||
27 | #include <asm/uaccess.h> | 27 | #include <asm/uaccess.h> |
28 | 28 | ||
29 | int get_compat_timespec(struct timespec *ts, const struct compat_timespec __user *cts) | 29 | int get_compat_timespec(struct timespec *ts, const struct compat_timespec __user *cts) |
30 | { | 30 | { |
31 | return (!access_ok(VERIFY_READ, cts, sizeof(*cts)) || | 31 | return (!access_ok(VERIFY_READ, cts, sizeof(*cts)) || |
32 | __get_user(ts->tv_sec, &cts->tv_sec) || | 32 | __get_user(ts->tv_sec, &cts->tv_sec) || |
33 | __get_user(ts->tv_nsec, &cts->tv_nsec)) ? -EFAULT : 0; | 33 | __get_user(ts->tv_nsec, &cts->tv_nsec)) ? -EFAULT : 0; |
34 | } | 34 | } |
35 | 35 | ||
36 | int put_compat_timespec(const struct timespec *ts, struct compat_timespec __user *cts) | 36 | int put_compat_timespec(const struct timespec *ts, struct compat_timespec __user *cts) |
37 | { | 37 | { |
38 | return (!access_ok(VERIFY_WRITE, cts, sizeof(*cts)) || | 38 | return (!access_ok(VERIFY_WRITE, cts, sizeof(*cts)) || |
39 | __put_user(ts->tv_sec, &cts->tv_sec) || | 39 | __put_user(ts->tv_sec, &cts->tv_sec) || |
40 | __put_user(ts->tv_nsec, &cts->tv_nsec)) ? -EFAULT : 0; | 40 | __put_user(ts->tv_nsec, &cts->tv_nsec)) ? -EFAULT : 0; |
41 | } | 41 | } |
42 | 42 | ||
43 | static long compat_nanosleep_restart(struct restart_block *restart) | 43 | static long compat_nanosleep_restart(struct restart_block *restart) |
44 | { | 44 | { |
45 | struct compat_timespec __user *rmtp; | 45 | struct compat_timespec __user *rmtp; |
46 | struct timespec rmt; | 46 | struct timespec rmt; |
47 | mm_segment_t oldfs; | 47 | mm_segment_t oldfs; |
48 | long ret; | 48 | long ret; |
49 | 49 | ||
50 | restart->nanosleep.rmtp = (struct timespec __user *) &rmt; | 50 | restart->nanosleep.rmtp = (struct timespec __user *) &rmt; |
51 | oldfs = get_fs(); | 51 | oldfs = get_fs(); |
52 | set_fs(KERNEL_DS); | 52 | set_fs(KERNEL_DS); |
53 | ret = hrtimer_nanosleep_restart(restart); | 53 | ret = hrtimer_nanosleep_restart(restart); |
54 | set_fs(oldfs); | 54 | set_fs(oldfs); |
55 | 55 | ||
56 | if (ret) { | 56 | if (ret) { |
57 | rmtp = restart->nanosleep.compat_rmtp; | 57 | rmtp = restart->nanosleep.compat_rmtp; |
58 | 58 | ||
59 | if (rmtp && put_compat_timespec(&rmt, rmtp)) | 59 | if (rmtp && put_compat_timespec(&rmt, rmtp)) |
60 | return -EFAULT; | 60 | return -EFAULT; |
61 | } | 61 | } |
62 | 62 | ||
63 | return ret; | 63 | return ret; |
64 | } | 64 | } |
65 | 65 | ||
66 | asmlinkage long compat_sys_nanosleep(struct compat_timespec __user *rqtp, | 66 | asmlinkage long compat_sys_nanosleep(struct compat_timespec __user *rqtp, |
67 | struct compat_timespec __user *rmtp) | 67 | struct compat_timespec __user *rmtp) |
68 | { | 68 | { |
69 | struct timespec tu, rmt; | 69 | struct timespec tu, rmt; |
70 | mm_segment_t oldfs; | 70 | mm_segment_t oldfs; |
71 | long ret; | 71 | long ret; |
72 | 72 | ||
73 | if (get_compat_timespec(&tu, rqtp)) | 73 | if (get_compat_timespec(&tu, rqtp)) |
74 | return -EFAULT; | 74 | return -EFAULT; |
75 | 75 | ||
76 | if (!timespec_valid(&tu)) | 76 | if (!timespec_valid(&tu)) |
77 | return -EINVAL; | 77 | return -EINVAL; |
78 | 78 | ||
79 | oldfs = get_fs(); | 79 | oldfs = get_fs(); |
80 | set_fs(KERNEL_DS); | 80 | set_fs(KERNEL_DS); |
81 | ret = hrtimer_nanosleep(&tu, | 81 | ret = hrtimer_nanosleep(&tu, |
82 | rmtp ? (struct timespec __user *)&rmt : NULL, | 82 | rmtp ? (struct timespec __user *)&rmt : NULL, |
83 | HRTIMER_MODE_REL, CLOCK_MONOTONIC); | 83 | HRTIMER_MODE_REL, CLOCK_MONOTONIC); |
84 | set_fs(oldfs); | 84 | set_fs(oldfs); |
85 | 85 | ||
86 | if (ret) { | 86 | if (ret) { |
87 | struct restart_block *restart | 87 | struct restart_block *restart |
88 | = ¤t_thread_info()->restart_block; | 88 | = ¤t_thread_info()->restart_block; |
89 | 89 | ||
90 | restart->fn = compat_nanosleep_restart; | 90 | restart->fn = compat_nanosleep_restart; |
91 | restart->nanosleep.compat_rmtp = rmtp; | 91 | restart->nanosleep.compat_rmtp = rmtp; |
92 | 92 | ||
93 | if (rmtp && put_compat_timespec(&rmt, rmtp)) | 93 | if (rmtp && put_compat_timespec(&rmt, rmtp)) |
94 | return -EFAULT; | 94 | return -EFAULT; |
95 | } | 95 | } |
96 | 96 | ||
97 | return ret; | 97 | return ret; |
98 | } | 98 | } |
99 | 99 | ||
100 | static inline long get_compat_itimerval(struct itimerval *o, | 100 | static inline long get_compat_itimerval(struct itimerval *o, |
101 | struct compat_itimerval __user *i) | 101 | struct compat_itimerval __user *i) |
102 | { | 102 | { |
103 | return (!access_ok(VERIFY_READ, i, sizeof(*i)) || | 103 | return (!access_ok(VERIFY_READ, i, sizeof(*i)) || |
104 | (__get_user(o->it_interval.tv_sec, &i->it_interval.tv_sec) | | 104 | (__get_user(o->it_interval.tv_sec, &i->it_interval.tv_sec) | |
105 | __get_user(o->it_interval.tv_usec, &i->it_interval.tv_usec) | | 105 | __get_user(o->it_interval.tv_usec, &i->it_interval.tv_usec) | |
106 | __get_user(o->it_value.tv_sec, &i->it_value.tv_sec) | | 106 | __get_user(o->it_value.tv_sec, &i->it_value.tv_sec) | |
107 | __get_user(o->it_value.tv_usec, &i->it_value.tv_usec))); | 107 | __get_user(o->it_value.tv_usec, &i->it_value.tv_usec))); |
108 | } | 108 | } |
109 | 109 | ||
110 | static inline long put_compat_itimerval(struct compat_itimerval __user *o, | 110 | static inline long put_compat_itimerval(struct compat_itimerval __user *o, |
111 | struct itimerval *i) | 111 | struct itimerval *i) |
112 | { | 112 | { |
113 | return (!access_ok(VERIFY_WRITE, o, sizeof(*o)) || | 113 | return (!access_ok(VERIFY_WRITE, o, sizeof(*o)) || |
114 | (__put_user(i->it_interval.tv_sec, &o->it_interval.tv_sec) | | 114 | (__put_user(i->it_interval.tv_sec, &o->it_interval.tv_sec) | |
115 | __put_user(i->it_interval.tv_usec, &o->it_interval.tv_usec) | | 115 | __put_user(i->it_interval.tv_usec, &o->it_interval.tv_usec) | |
116 | __put_user(i->it_value.tv_sec, &o->it_value.tv_sec) | | 116 | __put_user(i->it_value.tv_sec, &o->it_value.tv_sec) | |
117 | __put_user(i->it_value.tv_usec, &o->it_value.tv_usec))); | 117 | __put_user(i->it_value.tv_usec, &o->it_value.tv_usec))); |
118 | } | 118 | } |
119 | 119 | ||
120 | asmlinkage long compat_sys_getitimer(int which, | 120 | asmlinkage long compat_sys_getitimer(int which, |
121 | struct compat_itimerval __user *it) | 121 | struct compat_itimerval __user *it) |
122 | { | 122 | { |
123 | struct itimerval kit; | 123 | struct itimerval kit; |
124 | int error; | 124 | int error; |
125 | 125 | ||
126 | error = do_getitimer(which, &kit); | 126 | error = do_getitimer(which, &kit); |
127 | if (!error && put_compat_itimerval(it, &kit)) | 127 | if (!error && put_compat_itimerval(it, &kit)) |
128 | error = -EFAULT; | 128 | error = -EFAULT; |
129 | return error; | 129 | return error; |
130 | } | 130 | } |
131 | 131 | ||
132 | asmlinkage long compat_sys_setitimer(int which, | 132 | asmlinkage long compat_sys_setitimer(int which, |
133 | struct compat_itimerval __user *in, | 133 | struct compat_itimerval __user *in, |
134 | struct compat_itimerval __user *out) | 134 | struct compat_itimerval __user *out) |
135 | { | 135 | { |
136 | struct itimerval kin, kout; | 136 | struct itimerval kin, kout; |
137 | int error; | 137 | int error; |
138 | 138 | ||
139 | if (in) { | 139 | if (in) { |
140 | if (get_compat_itimerval(&kin, in)) | 140 | if (get_compat_itimerval(&kin, in)) |
141 | return -EFAULT; | 141 | return -EFAULT; |
142 | } else | 142 | } else |
143 | memset(&kin, 0, sizeof(kin)); | 143 | memset(&kin, 0, sizeof(kin)); |
144 | 144 | ||
145 | error = do_setitimer(which, &kin, out ? &kout : NULL); | 145 | error = do_setitimer(which, &kin, out ? &kout : NULL); |
146 | if (error || !out) | 146 | if (error || !out) |
147 | return error; | 147 | return error; |
148 | if (put_compat_itimerval(out, &kout)) | 148 | if (put_compat_itimerval(out, &kout)) |
149 | return -EFAULT; | 149 | return -EFAULT; |
150 | return 0; | 150 | return 0; |
151 | } | 151 | } |
152 | 152 | ||
153 | asmlinkage long compat_sys_times(struct compat_tms __user *tbuf) | 153 | asmlinkage long compat_sys_times(struct compat_tms __user *tbuf) |
154 | { | 154 | { |
155 | /* | 155 | /* |
156 | * In the SMP world we might just be unlucky and have one of | 156 | * In the SMP world we might just be unlucky and have one of |
157 | * the times increment as we use it. Since the value is an | 157 | * the times increment as we use it. Since the value is an |
158 | * atomically safe type this is just fine. Conceptually its | 158 | * atomically safe type this is just fine. Conceptually its |
159 | * as if the syscall took an instant longer to occur. | 159 | * as if the syscall took an instant longer to occur. |
160 | */ | 160 | */ |
161 | if (tbuf) { | 161 | if (tbuf) { |
162 | struct compat_tms tmp; | 162 | struct compat_tms tmp; |
163 | struct task_struct *tsk = current; | 163 | struct task_struct *tsk = current; |
164 | struct task_struct *t; | 164 | struct task_struct *t; |
165 | cputime_t utime, stime, cutime, cstime; | 165 | cputime_t utime, stime, cutime, cstime; |
166 | 166 | ||
167 | read_lock(&tasklist_lock); | 167 | read_lock(&tasklist_lock); |
168 | utime = tsk->signal->utime; | 168 | utime = tsk->signal->utime; |
169 | stime = tsk->signal->stime; | 169 | stime = tsk->signal->stime; |
170 | t = tsk; | 170 | t = tsk; |
171 | do { | 171 | do { |
172 | utime = cputime_add(utime, t->utime); | 172 | utime = cputime_add(utime, t->utime); |
173 | stime = cputime_add(stime, t->stime); | 173 | stime = cputime_add(stime, t->stime); |
174 | t = next_thread(t); | 174 | t = next_thread(t); |
175 | } while (t != tsk); | 175 | } while (t != tsk); |
176 | 176 | ||
177 | /* | 177 | /* |
178 | * While we have tasklist_lock read-locked, no dying thread | 178 | * While we have tasklist_lock read-locked, no dying thread |
179 | * can be updating current->signal->[us]time. Instead, | 179 | * can be updating current->signal->[us]time. Instead, |
180 | * we got their counts included in the live thread loop. | 180 | * we got their counts included in the live thread loop. |
181 | * However, another thread can come in right now and | 181 | * However, another thread can come in right now and |
182 | * do a wait call that updates current->signal->c[us]time. | 182 | * do a wait call that updates current->signal->c[us]time. |
183 | * To make sure we always see that pair updated atomically, | 183 | * To make sure we always see that pair updated atomically, |
184 | * we take the siglock around fetching them. | 184 | * we take the siglock around fetching them. |
185 | */ | 185 | */ |
186 | spin_lock_irq(&tsk->sighand->siglock); | 186 | spin_lock_irq(&tsk->sighand->siglock); |
187 | cutime = tsk->signal->cutime; | 187 | cutime = tsk->signal->cutime; |
188 | cstime = tsk->signal->cstime; | 188 | cstime = tsk->signal->cstime; |
189 | spin_unlock_irq(&tsk->sighand->siglock); | 189 | spin_unlock_irq(&tsk->sighand->siglock); |
190 | read_unlock(&tasklist_lock); | 190 | read_unlock(&tasklist_lock); |
191 | 191 | ||
192 | tmp.tms_utime = compat_jiffies_to_clock_t(cputime_to_jiffies(utime)); | 192 | tmp.tms_utime = compat_jiffies_to_clock_t(cputime_to_jiffies(utime)); |
193 | tmp.tms_stime = compat_jiffies_to_clock_t(cputime_to_jiffies(stime)); | 193 | tmp.tms_stime = compat_jiffies_to_clock_t(cputime_to_jiffies(stime)); |
194 | tmp.tms_cutime = compat_jiffies_to_clock_t(cputime_to_jiffies(cutime)); | 194 | tmp.tms_cutime = compat_jiffies_to_clock_t(cputime_to_jiffies(cutime)); |
195 | tmp.tms_cstime = compat_jiffies_to_clock_t(cputime_to_jiffies(cstime)); | 195 | tmp.tms_cstime = compat_jiffies_to_clock_t(cputime_to_jiffies(cstime)); |
196 | if (copy_to_user(tbuf, &tmp, sizeof(tmp))) | 196 | if (copy_to_user(tbuf, &tmp, sizeof(tmp))) |
197 | return -EFAULT; | 197 | return -EFAULT; |
198 | } | 198 | } |
199 | return compat_jiffies_to_clock_t(jiffies); | 199 | return compat_jiffies_to_clock_t(jiffies); |
200 | } | 200 | } |
201 | 201 | ||
202 | /* | 202 | /* |
203 | * Assumption: old_sigset_t and compat_old_sigset_t are both | 203 | * Assumption: old_sigset_t and compat_old_sigset_t are both |
204 | * types that can be passed to put_user()/get_user(). | 204 | * types that can be passed to put_user()/get_user(). |
205 | */ | 205 | */ |
206 | 206 | ||
207 | asmlinkage long compat_sys_sigpending(compat_old_sigset_t __user *set) | 207 | asmlinkage long compat_sys_sigpending(compat_old_sigset_t __user *set) |
208 | { | 208 | { |
209 | old_sigset_t s; | 209 | old_sigset_t s; |
210 | long ret; | 210 | long ret; |
211 | mm_segment_t old_fs = get_fs(); | 211 | mm_segment_t old_fs = get_fs(); |
212 | 212 | ||
213 | set_fs(KERNEL_DS); | 213 | set_fs(KERNEL_DS); |
214 | ret = sys_sigpending((old_sigset_t __user *) &s); | 214 | ret = sys_sigpending((old_sigset_t __user *) &s); |
215 | set_fs(old_fs); | 215 | set_fs(old_fs); |
216 | if (ret == 0) | 216 | if (ret == 0) |
217 | ret = put_user(s, set); | 217 | ret = put_user(s, set); |
218 | return ret; | 218 | return ret; |
219 | } | 219 | } |
220 | 220 | ||
221 | asmlinkage long compat_sys_sigprocmask(int how, compat_old_sigset_t __user *set, | 221 | asmlinkage long compat_sys_sigprocmask(int how, compat_old_sigset_t __user *set, |
222 | compat_old_sigset_t __user *oset) | 222 | compat_old_sigset_t __user *oset) |
223 | { | 223 | { |
224 | old_sigset_t s; | 224 | old_sigset_t s; |
225 | long ret; | 225 | long ret; |
226 | mm_segment_t old_fs; | 226 | mm_segment_t old_fs; |
227 | 227 | ||
228 | if (set && get_user(s, set)) | 228 | if (set && get_user(s, set)) |
229 | return -EFAULT; | 229 | return -EFAULT; |
230 | old_fs = get_fs(); | 230 | old_fs = get_fs(); |
231 | set_fs(KERNEL_DS); | 231 | set_fs(KERNEL_DS); |
232 | ret = sys_sigprocmask(how, | 232 | ret = sys_sigprocmask(how, |
233 | set ? (old_sigset_t __user *) &s : NULL, | 233 | set ? (old_sigset_t __user *) &s : NULL, |
234 | oset ? (old_sigset_t __user *) &s : NULL); | 234 | oset ? (old_sigset_t __user *) &s : NULL); |
235 | set_fs(old_fs); | 235 | set_fs(old_fs); |
236 | if (ret == 0) | 236 | if (ret == 0) |
237 | if (oset) | 237 | if (oset) |
238 | ret = put_user(s, oset); | 238 | ret = put_user(s, oset); |
239 | return ret; | 239 | return ret; |
240 | } | 240 | } |
241 | 241 | ||
242 | asmlinkage long compat_sys_setrlimit(unsigned int resource, | 242 | asmlinkage long compat_sys_setrlimit(unsigned int resource, |
243 | struct compat_rlimit __user *rlim) | 243 | struct compat_rlimit __user *rlim) |
244 | { | 244 | { |
245 | struct rlimit r; | 245 | struct rlimit r; |
246 | int ret; | 246 | int ret; |
247 | mm_segment_t old_fs = get_fs (); | 247 | mm_segment_t old_fs = get_fs (); |
248 | 248 | ||
249 | if (resource >= RLIM_NLIMITS) | 249 | if (resource >= RLIM_NLIMITS) |
250 | return -EINVAL; | 250 | return -EINVAL; |
251 | 251 | ||
252 | if (!access_ok(VERIFY_READ, rlim, sizeof(*rlim)) || | 252 | if (!access_ok(VERIFY_READ, rlim, sizeof(*rlim)) || |
253 | __get_user(r.rlim_cur, &rlim->rlim_cur) || | 253 | __get_user(r.rlim_cur, &rlim->rlim_cur) || |
254 | __get_user(r.rlim_max, &rlim->rlim_max)) | 254 | __get_user(r.rlim_max, &rlim->rlim_max)) |
255 | return -EFAULT; | 255 | return -EFAULT; |
256 | 256 | ||
257 | if (r.rlim_cur == COMPAT_RLIM_INFINITY) | 257 | if (r.rlim_cur == COMPAT_RLIM_INFINITY) |
258 | r.rlim_cur = RLIM_INFINITY; | 258 | r.rlim_cur = RLIM_INFINITY; |
259 | if (r.rlim_max == COMPAT_RLIM_INFINITY) | 259 | if (r.rlim_max == COMPAT_RLIM_INFINITY) |
260 | r.rlim_max = RLIM_INFINITY; | 260 | r.rlim_max = RLIM_INFINITY; |
261 | set_fs(KERNEL_DS); | 261 | set_fs(KERNEL_DS); |
262 | ret = sys_setrlimit(resource, (struct rlimit __user *) &r); | 262 | ret = sys_setrlimit(resource, (struct rlimit __user *) &r); |
263 | set_fs(old_fs); | 263 | set_fs(old_fs); |
264 | return ret; | 264 | return ret; |
265 | } | 265 | } |
266 | 266 | ||
267 | #ifdef COMPAT_RLIM_OLD_INFINITY | 267 | #ifdef COMPAT_RLIM_OLD_INFINITY |
268 | 268 | ||
269 | asmlinkage long compat_sys_old_getrlimit(unsigned int resource, | 269 | asmlinkage long compat_sys_old_getrlimit(unsigned int resource, |
270 | struct compat_rlimit __user *rlim) | 270 | struct compat_rlimit __user *rlim) |
271 | { | 271 | { |
272 | struct rlimit r; | 272 | struct rlimit r; |
273 | int ret; | 273 | int ret; |
274 | mm_segment_t old_fs = get_fs(); | 274 | mm_segment_t old_fs = get_fs(); |
275 | 275 | ||
276 | set_fs(KERNEL_DS); | 276 | set_fs(KERNEL_DS); |
277 | ret = sys_old_getrlimit(resource, &r); | 277 | ret = sys_old_getrlimit(resource, &r); |
278 | set_fs(old_fs); | 278 | set_fs(old_fs); |
279 | 279 | ||
280 | if (!ret) { | 280 | if (!ret) { |
281 | if (r.rlim_cur > COMPAT_RLIM_OLD_INFINITY) | 281 | if (r.rlim_cur > COMPAT_RLIM_OLD_INFINITY) |
282 | r.rlim_cur = COMPAT_RLIM_INFINITY; | 282 | r.rlim_cur = COMPAT_RLIM_INFINITY; |
283 | if (r.rlim_max > COMPAT_RLIM_OLD_INFINITY) | 283 | if (r.rlim_max > COMPAT_RLIM_OLD_INFINITY) |
284 | r.rlim_max = COMPAT_RLIM_INFINITY; | 284 | r.rlim_max = COMPAT_RLIM_INFINITY; |
285 | 285 | ||
286 | if (!access_ok(VERIFY_WRITE, rlim, sizeof(*rlim)) || | 286 | if (!access_ok(VERIFY_WRITE, rlim, sizeof(*rlim)) || |
287 | __put_user(r.rlim_cur, &rlim->rlim_cur) || | 287 | __put_user(r.rlim_cur, &rlim->rlim_cur) || |
288 | __put_user(r.rlim_max, &rlim->rlim_max)) | 288 | __put_user(r.rlim_max, &rlim->rlim_max)) |
289 | return -EFAULT; | 289 | return -EFAULT; |
290 | } | 290 | } |
291 | return ret; | 291 | return ret; |
292 | } | 292 | } |
293 | 293 | ||
294 | #endif | 294 | #endif |
295 | 295 | ||
296 | asmlinkage long compat_sys_getrlimit (unsigned int resource, | 296 | asmlinkage long compat_sys_getrlimit (unsigned int resource, |
297 | struct compat_rlimit __user *rlim) | 297 | struct compat_rlimit __user *rlim) |
298 | { | 298 | { |
299 | struct rlimit r; | 299 | struct rlimit r; |
300 | int ret; | 300 | int ret; |
301 | mm_segment_t old_fs = get_fs(); | 301 | mm_segment_t old_fs = get_fs(); |
302 | 302 | ||
303 | set_fs(KERNEL_DS); | 303 | set_fs(KERNEL_DS); |
304 | ret = sys_getrlimit(resource, (struct rlimit __user *) &r); | 304 | ret = sys_getrlimit(resource, (struct rlimit __user *) &r); |
305 | set_fs(old_fs); | 305 | set_fs(old_fs); |
306 | if (!ret) { | 306 | if (!ret) { |
307 | if (r.rlim_cur > COMPAT_RLIM_INFINITY) | 307 | if (r.rlim_cur > COMPAT_RLIM_INFINITY) |
308 | r.rlim_cur = COMPAT_RLIM_INFINITY; | 308 | r.rlim_cur = COMPAT_RLIM_INFINITY; |
309 | if (r.rlim_max > COMPAT_RLIM_INFINITY) | 309 | if (r.rlim_max > COMPAT_RLIM_INFINITY) |
310 | r.rlim_max = COMPAT_RLIM_INFINITY; | 310 | r.rlim_max = COMPAT_RLIM_INFINITY; |
311 | 311 | ||
312 | if (!access_ok(VERIFY_WRITE, rlim, sizeof(*rlim)) || | 312 | if (!access_ok(VERIFY_WRITE, rlim, sizeof(*rlim)) || |
313 | __put_user(r.rlim_cur, &rlim->rlim_cur) || | 313 | __put_user(r.rlim_cur, &rlim->rlim_cur) || |
314 | __put_user(r.rlim_max, &rlim->rlim_max)) | 314 | __put_user(r.rlim_max, &rlim->rlim_max)) |
315 | return -EFAULT; | 315 | return -EFAULT; |
316 | } | 316 | } |
317 | return ret; | 317 | return ret; |
318 | } | 318 | } |
319 | 319 | ||
320 | int put_compat_rusage(const struct rusage *r, struct compat_rusage __user *ru) | 320 | int put_compat_rusage(const struct rusage *r, struct compat_rusage __user *ru) |
321 | { | 321 | { |
322 | if (!access_ok(VERIFY_WRITE, ru, sizeof(*ru)) || | 322 | if (!access_ok(VERIFY_WRITE, ru, sizeof(*ru)) || |
323 | __put_user(r->ru_utime.tv_sec, &ru->ru_utime.tv_sec) || | 323 | __put_user(r->ru_utime.tv_sec, &ru->ru_utime.tv_sec) || |
324 | __put_user(r->ru_utime.tv_usec, &ru->ru_utime.tv_usec) || | 324 | __put_user(r->ru_utime.tv_usec, &ru->ru_utime.tv_usec) || |
325 | __put_user(r->ru_stime.tv_sec, &ru->ru_stime.tv_sec) || | 325 | __put_user(r->ru_stime.tv_sec, &ru->ru_stime.tv_sec) || |
326 | __put_user(r->ru_stime.tv_usec, &ru->ru_stime.tv_usec) || | 326 | __put_user(r->ru_stime.tv_usec, &ru->ru_stime.tv_usec) || |
327 | __put_user(r->ru_maxrss, &ru->ru_maxrss) || | 327 | __put_user(r->ru_maxrss, &ru->ru_maxrss) || |
328 | __put_user(r->ru_ixrss, &ru->ru_ixrss) || | 328 | __put_user(r->ru_ixrss, &ru->ru_ixrss) || |
329 | __put_user(r->ru_idrss, &ru->ru_idrss) || | 329 | __put_user(r->ru_idrss, &ru->ru_idrss) || |
330 | __put_user(r->ru_isrss, &ru->ru_isrss) || | 330 | __put_user(r->ru_isrss, &ru->ru_isrss) || |
331 | __put_user(r->ru_minflt, &ru->ru_minflt) || | 331 | __put_user(r->ru_minflt, &ru->ru_minflt) || |
332 | __put_user(r->ru_majflt, &ru->ru_majflt) || | 332 | __put_user(r->ru_majflt, &ru->ru_majflt) || |
333 | __put_user(r->ru_nswap, &ru->ru_nswap) || | 333 | __put_user(r->ru_nswap, &ru->ru_nswap) || |
334 | __put_user(r->ru_inblock, &ru->ru_inblock) || | 334 | __put_user(r->ru_inblock, &ru->ru_inblock) || |
335 | __put_user(r->ru_oublock, &ru->ru_oublock) || | 335 | __put_user(r->ru_oublock, &ru->ru_oublock) || |
336 | __put_user(r->ru_msgsnd, &ru->ru_msgsnd) || | 336 | __put_user(r->ru_msgsnd, &ru->ru_msgsnd) || |
337 | __put_user(r->ru_msgrcv, &ru->ru_msgrcv) || | 337 | __put_user(r->ru_msgrcv, &ru->ru_msgrcv) || |
338 | __put_user(r->ru_nsignals, &ru->ru_nsignals) || | 338 | __put_user(r->ru_nsignals, &ru->ru_nsignals) || |
339 | __put_user(r->ru_nvcsw, &ru->ru_nvcsw) || | 339 | __put_user(r->ru_nvcsw, &ru->ru_nvcsw) || |
340 | __put_user(r->ru_nivcsw, &ru->ru_nivcsw)) | 340 | __put_user(r->ru_nivcsw, &ru->ru_nivcsw)) |
341 | return -EFAULT; | 341 | return -EFAULT; |
342 | return 0; | 342 | return 0; |
343 | } | 343 | } |
344 | 344 | ||
345 | asmlinkage long compat_sys_getrusage(int who, struct compat_rusage __user *ru) | 345 | asmlinkage long compat_sys_getrusage(int who, struct compat_rusage __user *ru) |
346 | { | 346 | { |
347 | struct rusage r; | 347 | struct rusage r; |
348 | int ret; | 348 | int ret; |
349 | mm_segment_t old_fs = get_fs(); | 349 | mm_segment_t old_fs = get_fs(); |
350 | 350 | ||
351 | set_fs(KERNEL_DS); | 351 | set_fs(KERNEL_DS); |
352 | ret = sys_getrusage(who, (struct rusage __user *) &r); | 352 | ret = sys_getrusage(who, (struct rusage __user *) &r); |
353 | set_fs(old_fs); | 353 | set_fs(old_fs); |
354 | 354 | ||
355 | if (ret) | 355 | if (ret) |
356 | return ret; | 356 | return ret; |
357 | 357 | ||
358 | if (put_compat_rusage(&r, ru)) | 358 | if (put_compat_rusage(&r, ru)) |
359 | return -EFAULT; | 359 | return -EFAULT; |
360 | 360 | ||
361 | return 0; | 361 | return 0; |
362 | } | 362 | } |
363 | 363 | ||
364 | asmlinkage long | 364 | asmlinkage long |
365 | compat_sys_wait4(compat_pid_t pid, compat_uint_t __user *stat_addr, int options, | 365 | compat_sys_wait4(compat_pid_t pid, compat_uint_t __user *stat_addr, int options, |
366 | struct compat_rusage __user *ru) | 366 | struct compat_rusage __user *ru) |
367 | { | 367 | { |
368 | if (!ru) { | 368 | if (!ru) { |
369 | return sys_wait4(pid, stat_addr, options, NULL); | 369 | return sys_wait4(pid, stat_addr, options, NULL); |
370 | } else { | 370 | } else { |
371 | struct rusage r; | 371 | struct rusage r; |
372 | int ret; | 372 | int ret; |
373 | unsigned int status; | 373 | unsigned int status; |
374 | mm_segment_t old_fs = get_fs(); | 374 | mm_segment_t old_fs = get_fs(); |
375 | 375 | ||
376 | set_fs (KERNEL_DS); | 376 | set_fs (KERNEL_DS); |
377 | ret = sys_wait4(pid, | 377 | ret = sys_wait4(pid, |
378 | (stat_addr ? | 378 | (stat_addr ? |
379 | (unsigned int __user *) &status : NULL), | 379 | (unsigned int __user *) &status : NULL), |
380 | options, (struct rusage __user *) &r); | 380 | options, (struct rusage __user *) &r); |
381 | set_fs (old_fs); | 381 | set_fs (old_fs); |
382 | 382 | ||
383 | if (ret > 0) { | 383 | if (ret > 0) { |
384 | if (put_compat_rusage(&r, ru)) | 384 | if (put_compat_rusage(&r, ru)) |
385 | return -EFAULT; | 385 | return -EFAULT; |
386 | if (stat_addr && put_user(status, stat_addr)) | 386 | if (stat_addr && put_user(status, stat_addr)) |
387 | return -EFAULT; | 387 | return -EFAULT; |
388 | } | 388 | } |
389 | return ret; | 389 | return ret; |
390 | } | 390 | } |
391 | } | 391 | } |
392 | 392 | ||
393 | asmlinkage long compat_sys_waitid(int which, compat_pid_t pid, | 393 | asmlinkage long compat_sys_waitid(int which, compat_pid_t pid, |
394 | struct compat_siginfo __user *uinfo, int options, | 394 | struct compat_siginfo __user *uinfo, int options, |
395 | struct compat_rusage __user *uru) | 395 | struct compat_rusage __user *uru) |
396 | { | 396 | { |
397 | siginfo_t info; | 397 | siginfo_t info; |
398 | struct rusage ru; | 398 | struct rusage ru; |
399 | long ret; | 399 | long ret; |
400 | mm_segment_t old_fs = get_fs(); | 400 | mm_segment_t old_fs = get_fs(); |
401 | 401 | ||
402 | memset(&info, 0, sizeof(info)); | 402 | memset(&info, 0, sizeof(info)); |
403 | 403 | ||
404 | set_fs(KERNEL_DS); | 404 | set_fs(KERNEL_DS); |
405 | ret = sys_waitid(which, pid, (siginfo_t __user *)&info, options, | 405 | ret = sys_waitid(which, pid, (siginfo_t __user *)&info, options, |
406 | uru ? (struct rusage __user *)&ru : NULL); | 406 | uru ? (struct rusage __user *)&ru : NULL); |
407 | set_fs(old_fs); | 407 | set_fs(old_fs); |
408 | 408 | ||
409 | if ((ret < 0) || (info.si_signo == 0)) | 409 | if ((ret < 0) || (info.si_signo == 0)) |
410 | return ret; | 410 | return ret; |
411 | 411 | ||
412 | if (uru) { | 412 | if (uru) { |
413 | ret = put_compat_rusage(&ru, uru); | 413 | ret = put_compat_rusage(&ru, uru); |
414 | if (ret) | 414 | if (ret) |
415 | return ret; | 415 | return ret; |
416 | } | 416 | } |
417 | 417 | ||
418 | BUG_ON(info.si_code & __SI_MASK); | 418 | BUG_ON(info.si_code & __SI_MASK); |
419 | info.si_code |= __SI_CHLD; | 419 | info.si_code |= __SI_CHLD; |
420 | return copy_siginfo_to_user32(uinfo, &info); | 420 | return copy_siginfo_to_user32(uinfo, &info); |
421 | } | 421 | } |
422 | 422 | ||
423 | static int compat_get_user_cpu_mask(compat_ulong_t __user *user_mask_ptr, | 423 | static int compat_get_user_cpu_mask(compat_ulong_t __user *user_mask_ptr, |
424 | unsigned len, cpumask_t *new_mask) | 424 | unsigned len, cpumask_t *new_mask) |
425 | { | 425 | { |
426 | unsigned long *k; | 426 | unsigned long *k; |
427 | 427 | ||
428 | if (len < sizeof(cpumask_t)) | 428 | if (len < sizeof(cpumask_t)) |
429 | memset(new_mask, 0, sizeof(cpumask_t)); | 429 | memset(new_mask, 0, sizeof(cpumask_t)); |
430 | else if (len > sizeof(cpumask_t)) | 430 | else if (len > sizeof(cpumask_t)) |
431 | len = sizeof(cpumask_t); | 431 | len = sizeof(cpumask_t); |
432 | 432 | ||
433 | k = cpus_addr(*new_mask); | 433 | k = cpus_addr(*new_mask); |
434 | return compat_get_bitmap(k, user_mask_ptr, len * 8); | 434 | return compat_get_bitmap(k, user_mask_ptr, len * 8); |
435 | } | 435 | } |
436 | 436 | ||
437 | asmlinkage long compat_sys_sched_setaffinity(compat_pid_t pid, | 437 | asmlinkage long compat_sys_sched_setaffinity(compat_pid_t pid, |
438 | unsigned int len, | 438 | unsigned int len, |
439 | compat_ulong_t __user *user_mask_ptr) | 439 | compat_ulong_t __user *user_mask_ptr) |
440 | { | 440 | { |
441 | cpumask_t new_mask; | 441 | cpumask_t new_mask; |
442 | int retval; | 442 | int retval; |
443 | 443 | ||
444 | retval = compat_get_user_cpu_mask(user_mask_ptr, len, &new_mask); | 444 | retval = compat_get_user_cpu_mask(user_mask_ptr, len, &new_mask); |
445 | if (retval) | 445 | if (retval) |
446 | return retval; | 446 | return retval; |
447 | 447 | ||
448 | return sched_setaffinity(pid, &new_mask); | 448 | return sched_setaffinity(pid, &new_mask); |
449 | } | 449 | } |
450 | 450 | ||
451 | asmlinkage long compat_sys_sched_getaffinity(compat_pid_t pid, unsigned int len, | 451 | asmlinkage long compat_sys_sched_getaffinity(compat_pid_t pid, unsigned int len, |
452 | compat_ulong_t __user *user_mask_ptr) | 452 | compat_ulong_t __user *user_mask_ptr) |
453 | { | 453 | { |
454 | int ret; | 454 | int ret; |
455 | cpumask_t mask; | 455 | cpumask_t mask; |
456 | unsigned long *k; | 456 | unsigned long *k; |
457 | unsigned int min_length = sizeof(cpumask_t); | 457 | unsigned int min_length = sizeof(cpumask_t); |
458 | 458 | ||
459 | if (NR_CPUS <= BITS_PER_COMPAT_LONG) | 459 | if (NR_CPUS <= BITS_PER_COMPAT_LONG) |
460 | min_length = sizeof(compat_ulong_t); | 460 | min_length = sizeof(compat_ulong_t); |
461 | 461 | ||
462 | if (len < min_length) | 462 | if (len < min_length) |
463 | return -EINVAL; | 463 | return -EINVAL; |
464 | 464 | ||
465 | ret = sched_getaffinity(pid, &mask); | 465 | ret = sched_getaffinity(pid, &mask); |
466 | if (ret < 0) | 466 | if (ret < 0) |
467 | return ret; | 467 | return ret; |
468 | 468 | ||
469 | k = cpus_addr(mask); | 469 | k = cpus_addr(mask); |
470 | ret = compat_put_bitmap(user_mask_ptr, k, min_length * 8); | 470 | ret = compat_put_bitmap(user_mask_ptr, k, min_length * 8); |
471 | if (ret) | 471 | if (ret) |
472 | return ret; | 472 | return ret; |
473 | 473 | ||
474 | return min_length; | 474 | return min_length; |
475 | } | 475 | } |
476 | 476 | ||
477 | int get_compat_itimerspec(struct itimerspec *dst, | 477 | int get_compat_itimerspec(struct itimerspec *dst, |
478 | const struct compat_itimerspec __user *src) | 478 | const struct compat_itimerspec __user *src) |
479 | { | 479 | { |
480 | if (get_compat_timespec(&dst->it_interval, &src->it_interval) || | 480 | if (get_compat_timespec(&dst->it_interval, &src->it_interval) || |
481 | get_compat_timespec(&dst->it_value, &src->it_value)) | 481 | get_compat_timespec(&dst->it_value, &src->it_value)) |
482 | return -EFAULT; | 482 | return -EFAULT; |
483 | return 0; | 483 | return 0; |
484 | } | 484 | } |
485 | 485 | ||
486 | int put_compat_itimerspec(struct compat_itimerspec __user *dst, | 486 | int put_compat_itimerspec(struct compat_itimerspec __user *dst, |
487 | const struct itimerspec *src) | 487 | const struct itimerspec *src) |
488 | { | 488 | { |
489 | if (put_compat_timespec(&src->it_interval, &dst->it_interval) || | 489 | if (put_compat_timespec(&src->it_interval, &dst->it_interval) || |
490 | put_compat_timespec(&src->it_value, &dst->it_value)) | 490 | put_compat_timespec(&src->it_value, &dst->it_value)) |
491 | return -EFAULT; | 491 | return -EFAULT; |
492 | return 0; | 492 | return 0; |
493 | } | 493 | } |
494 | 494 | ||
495 | long compat_sys_timer_create(clockid_t which_clock, | 495 | long compat_sys_timer_create(clockid_t which_clock, |
496 | struct compat_sigevent __user *timer_event_spec, | 496 | struct compat_sigevent __user *timer_event_spec, |
497 | timer_t __user *created_timer_id) | 497 | timer_t __user *created_timer_id) |
498 | { | 498 | { |
499 | struct sigevent __user *event = NULL; | 499 | struct sigevent __user *event = NULL; |
500 | 500 | ||
501 | if (timer_event_spec) { | 501 | if (timer_event_spec) { |
502 | struct sigevent kevent; | 502 | struct sigevent kevent; |
503 | 503 | ||
504 | event = compat_alloc_user_space(sizeof(*event)); | 504 | event = compat_alloc_user_space(sizeof(*event)); |
505 | if (get_compat_sigevent(&kevent, timer_event_spec) || | 505 | if (get_compat_sigevent(&kevent, timer_event_spec) || |
506 | copy_to_user(event, &kevent, sizeof(*event))) | 506 | copy_to_user(event, &kevent, sizeof(*event))) |
507 | return -EFAULT; | 507 | return -EFAULT; |
508 | } | 508 | } |
509 | 509 | ||
510 | return sys_timer_create(which_clock, event, created_timer_id); | 510 | return sys_timer_create(which_clock, event, created_timer_id); |
511 | } | 511 | } |
512 | 512 | ||
513 | long compat_sys_timer_settime(timer_t timer_id, int flags, | 513 | long compat_sys_timer_settime(timer_t timer_id, int flags, |
514 | struct compat_itimerspec __user *new, | 514 | struct compat_itimerspec __user *new, |
515 | struct compat_itimerspec __user *old) | 515 | struct compat_itimerspec __user *old) |
516 | { | 516 | { |
517 | long err; | 517 | long err; |
518 | mm_segment_t oldfs; | 518 | mm_segment_t oldfs; |
519 | struct itimerspec newts, oldts; | 519 | struct itimerspec newts, oldts; |
520 | 520 | ||
521 | if (!new) | 521 | if (!new) |
522 | return -EINVAL; | 522 | return -EINVAL; |
523 | if (get_compat_itimerspec(&newts, new)) | 523 | if (get_compat_itimerspec(&newts, new)) |
524 | return -EFAULT; | 524 | return -EFAULT; |
525 | oldfs = get_fs(); | 525 | oldfs = get_fs(); |
526 | set_fs(KERNEL_DS); | 526 | set_fs(KERNEL_DS); |
527 | err = sys_timer_settime(timer_id, flags, | 527 | err = sys_timer_settime(timer_id, flags, |
528 | (struct itimerspec __user *) &newts, | 528 | (struct itimerspec __user *) &newts, |
529 | (struct itimerspec __user *) &oldts); | 529 | (struct itimerspec __user *) &oldts); |
530 | set_fs(oldfs); | 530 | set_fs(oldfs); |
531 | if (!err && old && put_compat_itimerspec(old, &oldts)) | 531 | if (!err && old && put_compat_itimerspec(old, &oldts)) |
532 | return -EFAULT; | 532 | return -EFAULT; |
533 | return err; | 533 | return err; |
534 | } | 534 | } |
535 | 535 | ||
536 | long compat_sys_timer_gettime(timer_t timer_id, | 536 | long compat_sys_timer_gettime(timer_t timer_id, |
537 | struct compat_itimerspec __user *setting) | 537 | struct compat_itimerspec __user *setting) |
538 | { | 538 | { |
539 | long err; | 539 | long err; |
540 | mm_segment_t oldfs; | 540 | mm_segment_t oldfs; |
541 | struct itimerspec ts; | 541 | struct itimerspec ts; |
542 | 542 | ||
543 | oldfs = get_fs(); | 543 | oldfs = get_fs(); |
544 | set_fs(KERNEL_DS); | 544 | set_fs(KERNEL_DS); |
545 | err = sys_timer_gettime(timer_id, | 545 | err = sys_timer_gettime(timer_id, |
546 | (struct itimerspec __user *) &ts); | 546 | (struct itimerspec __user *) &ts); |
547 | set_fs(oldfs); | 547 | set_fs(oldfs); |
548 | if (!err && put_compat_itimerspec(setting, &ts)) | 548 | if (!err && put_compat_itimerspec(setting, &ts)) |
549 | return -EFAULT; | 549 | return -EFAULT; |
550 | return err; | 550 | return err; |
551 | } | 551 | } |
552 | 552 | ||
553 | long compat_sys_clock_settime(clockid_t which_clock, | 553 | long compat_sys_clock_settime(clockid_t which_clock, |
554 | struct compat_timespec __user *tp) | 554 | struct compat_timespec __user *tp) |
555 | { | 555 | { |
556 | long err; | 556 | long err; |
557 | mm_segment_t oldfs; | 557 | mm_segment_t oldfs; |
558 | struct timespec ts; | 558 | struct timespec ts; |
559 | 559 | ||
560 | if (get_compat_timespec(&ts, tp)) | 560 | if (get_compat_timespec(&ts, tp)) |
561 | return -EFAULT; | 561 | return -EFAULT; |
562 | oldfs = get_fs(); | 562 | oldfs = get_fs(); |
563 | set_fs(KERNEL_DS); | 563 | set_fs(KERNEL_DS); |
564 | err = sys_clock_settime(which_clock, | 564 | err = sys_clock_settime(which_clock, |
565 | (struct timespec __user *) &ts); | 565 | (struct timespec __user *) &ts); |
566 | set_fs(oldfs); | 566 | set_fs(oldfs); |
567 | return err; | 567 | return err; |
568 | } | 568 | } |
569 | 569 | ||
570 | long compat_sys_clock_gettime(clockid_t which_clock, | 570 | long compat_sys_clock_gettime(clockid_t which_clock, |
571 | struct compat_timespec __user *tp) | 571 | struct compat_timespec __user *tp) |
572 | { | 572 | { |
573 | long err; | 573 | long err; |
574 | mm_segment_t oldfs; | 574 | mm_segment_t oldfs; |
575 | struct timespec ts; | 575 | struct timespec ts; |
576 | 576 | ||
577 | oldfs = get_fs(); | 577 | oldfs = get_fs(); |
578 | set_fs(KERNEL_DS); | 578 | set_fs(KERNEL_DS); |
579 | err = sys_clock_gettime(which_clock, | 579 | err = sys_clock_gettime(which_clock, |
580 | (struct timespec __user *) &ts); | 580 | (struct timespec __user *) &ts); |
581 | set_fs(oldfs); | 581 | set_fs(oldfs); |
582 | if (!err && put_compat_timespec(&ts, tp)) | 582 | if (!err && put_compat_timespec(&ts, tp)) |
583 | return -EFAULT; | 583 | return -EFAULT; |
584 | return err; | 584 | return err; |
585 | } | 585 | } |
586 | 586 | ||
587 | long compat_sys_clock_getres(clockid_t which_clock, | 587 | long compat_sys_clock_getres(clockid_t which_clock, |
588 | struct compat_timespec __user *tp) | 588 | struct compat_timespec __user *tp) |
589 | { | 589 | { |
590 | long err; | 590 | long err; |
591 | mm_segment_t oldfs; | 591 | mm_segment_t oldfs; |
592 | struct timespec ts; | 592 | struct timespec ts; |
593 | 593 | ||
594 | oldfs = get_fs(); | 594 | oldfs = get_fs(); |
595 | set_fs(KERNEL_DS); | 595 | set_fs(KERNEL_DS); |
596 | err = sys_clock_getres(which_clock, | 596 | err = sys_clock_getres(which_clock, |
597 | (struct timespec __user *) &ts); | 597 | (struct timespec __user *) &ts); |
598 | set_fs(oldfs); | 598 | set_fs(oldfs); |
599 | if (!err && tp && put_compat_timespec(&ts, tp)) | 599 | if (!err && tp && put_compat_timespec(&ts, tp)) |
600 | return -EFAULT; | 600 | return -EFAULT; |
601 | return err; | 601 | return err; |
602 | } | 602 | } |
603 | 603 | ||
604 | static long compat_clock_nanosleep_restart(struct restart_block *restart) | 604 | static long compat_clock_nanosleep_restart(struct restart_block *restart) |
605 | { | 605 | { |
606 | long err; | 606 | long err; |
607 | mm_segment_t oldfs; | 607 | mm_segment_t oldfs; |
608 | struct timespec tu; | 608 | struct timespec tu; |
609 | struct compat_timespec *rmtp = restart->nanosleep.compat_rmtp; | 609 | struct compat_timespec *rmtp = restart->nanosleep.compat_rmtp; |
610 | 610 | ||
611 | restart->nanosleep.rmtp = (struct timespec __user *) &tu; | 611 | restart->nanosleep.rmtp = (struct timespec __user *) &tu; |
612 | oldfs = get_fs(); | 612 | oldfs = get_fs(); |
613 | set_fs(KERNEL_DS); | 613 | set_fs(KERNEL_DS); |
614 | err = clock_nanosleep_restart(restart); | 614 | err = clock_nanosleep_restart(restart); |
615 | set_fs(oldfs); | 615 | set_fs(oldfs); |
616 | 616 | ||
617 | if ((err == -ERESTART_RESTARTBLOCK) && rmtp && | 617 | if ((err == -ERESTART_RESTARTBLOCK) && rmtp && |
618 | put_compat_timespec(&tu, rmtp)) | 618 | put_compat_timespec(&tu, rmtp)) |
619 | return -EFAULT; | 619 | return -EFAULT; |
620 | 620 | ||
621 | if (err == -ERESTART_RESTARTBLOCK) { | 621 | if (err == -ERESTART_RESTARTBLOCK) { |
622 | restart->fn = compat_clock_nanosleep_restart; | 622 | restart->fn = compat_clock_nanosleep_restart; |
623 | restart->nanosleep.compat_rmtp = rmtp; | 623 | restart->nanosleep.compat_rmtp = rmtp; |
624 | } | 624 | } |
625 | return err; | 625 | return err; |
626 | } | 626 | } |
627 | 627 | ||
628 | long compat_sys_clock_nanosleep(clockid_t which_clock, int flags, | 628 | long compat_sys_clock_nanosleep(clockid_t which_clock, int flags, |
629 | struct compat_timespec __user *rqtp, | 629 | struct compat_timespec __user *rqtp, |
630 | struct compat_timespec __user *rmtp) | 630 | struct compat_timespec __user *rmtp) |
631 | { | 631 | { |
632 | long err; | 632 | long err; |
633 | mm_segment_t oldfs; | 633 | mm_segment_t oldfs; |
634 | struct timespec in, out; | 634 | struct timespec in, out; |
635 | struct restart_block *restart; | 635 | struct restart_block *restart; |
636 | 636 | ||
637 | if (get_compat_timespec(&in, rqtp)) | 637 | if (get_compat_timespec(&in, rqtp)) |
638 | return -EFAULT; | 638 | return -EFAULT; |
639 | 639 | ||
640 | oldfs = get_fs(); | 640 | oldfs = get_fs(); |
641 | set_fs(KERNEL_DS); | 641 | set_fs(KERNEL_DS); |
642 | err = sys_clock_nanosleep(which_clock, flags, | 642 | err = sys_clock_nanosleep(which_clock, flags, |
643 | (struct timespec __user *) &in, | 643 | (struct timespec __user *) &in, |
644 | (struct timespec __user *) &out); | 644 | (struct timespec __user *) &out); |
645 | set_fs(oldfs); | 645 | set_fs(oldfs); |
646 | 646 | ||
647 | if ((err == -ERESTART_RESTARTBLOCK) && rmtp && | 647 | if ((err == -ERESTART_RESTARTBLOCK) && rmtp && |
648 | put_compat_timespec(&out, rmtp)) | 648 | put_compat_timespec(&out, rmtp)) |
649 | return -EFAULT; | 649 | return -EFAULT; |
650 | 650 | ||
651 | if (err == -ERESTART_RESTARTBLOCK) { | 651 | if (err == -ERESTART_RESTARTBLOCK) { |
652 | restart = ¤t_thread_info()->restart_block; | 652 | restart = ¤t_thread_info()->restart_block; |
653 | restart->fn = compat_clock_nanosleep_restart; | 653 | restart->fn = compat_clock_nanosleep_restart; |
654 | restart->nanosleep.compat_rmtp = rmtp; | 654 | restart->nanosleep.compat_rmtp = rmtp; |
655 | } | 655 | } |
656 | return err; | 656 | return err; |
657 | } | 657 | } |
658 | 658 | ||
659 | /* | 659 | /* |
660 | * We currently only need the following fields from the sigevent | 660 | * We currently only need the following fields from the sigevent |
661 | * structure: sigev_value, sigev_signo, sig_notify and (sometimes | 661 | * structure: sigev_value, sigev_signo, sig_notify and (sometimes |
662 | * sigev_notify_thread_id). The others are handled in user mode. | 662 | * sigev_notify_thread_id). The others are handled in user mode. |
663 | * We also assume that copying sigev_value.sival_int is sufficient | 663 | * We also assume that copying sigev_value.sival_int is sufficient |
664 | * to keep all the bits of sigev_value.sival_ptr intact. | 664 | * to keep all the bits of sigev_value.sival_ptr intact. |
665 | */ | 665 | */ |
666 | int get_compat_sigevent(struct sigevent *event, | 666 | int get_compat_sigevent(struct sigevent *event, |
667 | const struct compat_sigevent __user *u_event) | 667 | const struct compat_sigevent __user *u_event) |
668 | { | 668 | { |
669 | memset(event, 0, sizeof(*event)); | 669 | memset(event, 0, sizeof(*event)); |
670 | return (!access_ok(VERIFY_READ, u_event, sizeof(*u_event)) || | 670 | return (!access_ok(VERIFY_READ, u_event, sizeof(*u_event)) || |
671 | __get_user(event->sigev_value.sival_int, | 671 | __get_user(event->sigev_value.sival_int, |
672 | &u_event->sigev_value.sival_int) || | 672 | &u_event->sigev_value.sival_int) || |
673 | __get_user(event->sigev_signo, &u_event->sigev_signo) || | 673 | __get_user(event->sigev_signo, &u_event->sigev_signo) || |
674 | __get_user(event->sigev_notify, &u_event->sigev_notify) || | 674 | __get_user(event->sigev_notify, &u_event->sigev_notify) || |
675 | __get_user(event->sigev_notify_thread_id, | 675 | __get_user(event->sigev_notify_thread_id, |
676 | &u_event->sigev_notify_thread_id)) | 676 | &u_event->sigev_notify_thread_id)) |
677 | ? -EFAULT : 0; | 677 | ? -EFAULT : 0; |
678 | } | 678 | } |
679 | 679 | ||
680 | long compat_get_bitmap(unsigned long *mask, const compat_ulong_t __user *umask, | 680 | long compat_get_bitmap(unsigned long *mask, const compat_ulong_t __user *umask, |
681 | unsigned long bitmap_size) | 681 | unsigned long bitmap_size) |
682 | { | 682 | { |
683 | int i, j; | 683 | int i, j; |
684 | unsigned long m; | 684 | unsigned long m; |
685 | compat_ulong_t um; | 685 | compat_ulong_t um; |
686 | unsigned long nr_compat_longs; | 686 | unsigned long nr_compat_longs; |
687 | 687 | ||
688 | /* align bitmap up to nearest compat_long_t boundary */ | 688 | /* align bitmap up to nearest compat_long_t boundary */ |
689 | bitmap_size = ALIGN(bitmap_size, BITS_PER_COMPAT_LONG); | 689 | bitmap_size = ALIGN(bitmap_size, BITS_PER_COMPAT_LONG); |
690 | 690 | ||
691 | if (!access_ok(VERIFY_READ, umask, bitmap_size / 8)) | 691 | if (!access_ok(VERIFY_READ, umask, bitmap_size / 8)) |
692 | return -EFAULT; | 692 | return -EFAULT; |
693 | 693 | ||
694 | nr_compat_longs = BITS_TO_COMPAT_LONGS(bitmap_size); | 694 | nr_compat_longs = BITS_TO_COMPAT_LONGS(bitmap_size); |
695 | 695 | ||
696 | for (i = 0; i < BITS_TO_LONGS(bitmap_size); i++) { | 696 | for (i = 0; i < BITS_TO_LONGS(bitmap_size); i++) { |
697 | m = 0; | 697 | m = 0; |
698 | 698 | ||
699 | for (j = 0; j < sizeof(m)/sizeof(um); j++) { | 699 | for (j = 0; j < sizeof(m)/sizeof(um); j++) { |
700 | /* | 700 | /* |
701 | * We dont want to read past the end of the userspace | 701 | * We dont want to read past the end of the userspace |
702 | * bitmap. We must however ensure the end of the | 702 | * bitmap. We must however ensure the end of the |
703 | * kernel bitmap is zeroed. | 703 | * kernel bitmap is zeroed. |
704 | */ | 704 | */ |
705 | if (nr_compat_longs-- > 0) { | 705 | if (nr_compat_longs-- > 0) { |
706 | if (__get_user(um, umask)) | 706 | if (__get_user(um, umask)) |
707 | return -EFAULT; | 707 | return -EFAULT; |
708 | } else { | 708 | } else { |
709 | um = 0; | 709 | um = 0; |
710 | } | 710 | } |
711 | 711 | ||
712 | umask++; | 712 | umask++; |
713 | m |= (long)um << (j * BITS_PER_COMPAT_LONG); | 713 | m |= (long)um << (j * BITS_PER_COMPAT_LONG); |
714 | } | 714 | } |
715 | *mask++ = m; | 715 | *mask++ = m; |
716 | } | 716 | } |
717 | 717 | ||
718 | return 0; | 718 | return 0; |
719 | } | 719 | } |
720 | 720 | ||
721 | long compat_put_bitmap(compat_ulong_t __user *umask, unsigned long *mask, | 721 | long compat_put_bitmap(compat_ulong_t __user *umask, unsigned long *mask, |
722 | unsigned long bitmap_size) | 722 | unsigned long bitmap_size) |
723 | { | 723 | { |
724 | int i, j; | 724 | int i, j; |
725 | unsigned long m; | 725 | unsigned long m; |
726 | compat_ulong_t um; | 726 | compat_ulong_t um; |
727 | unsigned long nr_compat_longs; | 727 | unsigned long nr_compat_longs; |
728 | 728 | ||
729 | /* align bitmap up to nearest compat_long_t boundary */ | 729 | /* align bitmap up to nearest compat_long_t boundary */ |
730 | bitmap_size = ALIGN(bitmap_size, BITS_PER_COMPAT_LONG); | 730 | bitmap_size = ALIGN(bitmap_size, BITS_PER_COMPAT_LONG); |
731 | 731 | ||
732 | if (!access_ok(VERIFY_WRITE, umask, bitmap_size / 8)) | 732 | if (!access_ok(VERIFY_WRITE, umask, bitmap_size / 8)) |
733 | return -EFAULT; | 733 | return -EFAULT; |
734 | 734 | ||
735 | nr_compat_longs = BITS_TO_COMPAT_LONGS(bitmap_size); | 735 | nr_compat_longs = BITS_TO_COMPAT_LONGS(bitmap_size); |
736 | 736 | ||
737 | for (i = 0; i < BITS_TO_LONGS(bitmap_size); i++) { | 737 | for (i = 0; i < BITS_TO_LONGS(bitmap_size); i++) { |
738 | m = *mask++; | 738 | m = *mask++; |
739 | 739 | ||
740 | for (j = 0; j < sizeof(m)/sizeof(um); j++) { | 740 | for (j = 0; j < sizeof(m)/sizeof(um); j++) { |
741 | um = m; | 741 | um = m; |
742 | 742 | ||
743 | /* | 743 | /* |
744 | * We dont want to write past the end of the userspace | 744 | * We dont want to write past the end of the userspace |
745 | * bitmap. | 745 | * bitmap. |
746 | */ | 746 | */ |
747 | if (nr_compat_longs-- > 0) { | 747 | if (nr_compat_longs-- > 0) { |
748 | if (__put_user(um, umask)) | 748 | if (__put_user(um, umask)) |
749 | return -EFAULT; | 749 | return -EFAULT; |
750 | } | 750 | } |
751 | 751 | ||
752 | umask++; | 752 | umask++; |
753 | m >>= 4*sizeof(um); | 753 | m >>= 4*sizeof(um); |
754 | m >>= 4*sizeof(um); | 754 | m >>= 4*sizeof(um); |
755 | } | 755 | } |
756 | } | 756 | } |
757 | 757 | ||
758 | return 0; | 758 | return 0; |
759 | } | 759 | } |
760 | 760 | ||
761 | void | 761 | void |
762 | sigset_from_compat (sigset_t *set, compat_sigset_t *compat) | 762 | sigset_from_compat (sigset_t *set, compat_sigset_t *compat) |
763 | { | 763 | { |
764 | switch (_NSIG_WORDS) { | 764 | switch (_NSIG_WORDS) { |
765 | case 4: set->sig[3] = compat->sig[6] | (((long)compat->sig[7]) << 32 ); | 765 | case 4: set->sig[3] = compat->sig[6] | (((long)compat->sig[7]) << 32 ); |
766 | case 3: set->sig[2] = compat->sig[4] | (((long)compat->sig[5]) << 32 ); | 766 | case 3: set->sig[2] = compat->sig[4] | (((long)compat->sig[5]) << 32 ); |
767 | case 2: set->sig[1] = compat->sig[2] | (((long)compat->sig[3]) << 32 ); | 767 | case 2: set->sig[1] = compat->sig[2] | (((long)compat->sig[3]) << 32 ); |
768 | case 1: set->sig[0] = compat->sig[0] | (((long)compat->sig[1]) << 32 ); | 768 | case 1: set->sig[0] = compat->sig[0] | (((long)compat->sig[1]) << 32 ); |
769 | } | 769 | } |
770 | } | 770 | } |
771 | 771 | ||
772 | asmlinkage long | 772 | asmlinkage long |
773 | compat_sys_rt_sigtimedwait (compat_sigset_t __user *uthese, | 773 | compat_sys_rt_sigtimedwait (compat_sigset_t __user *uthese, |
774 | struct compat_siginfo __user *uinfo, | 774 | struct compat_siginfo __user *uinfo, |
775 | struct compat_timespec __user *uts, compat_size_t sigsetsize) | 775 | struct compat_timespec __user *uts, compat_size_t sigsetsize) |
776 | { | 776 | { |
777 | compat_sigset_t s32; | 777 | compat_sigset_t s32; |
778 | sigset_t s; | 778 | sigset_t s; |
779 | int sig; | 779 | int sig; |
780 | struct timespec t; | 780 | struct timespec t; |
781 | siginfo_t info; | 781 | siginfo_t info; |
782 | long ret, timeout = 0; | 782 | long ret, timeout = 0; |
783 | 783 | ||
784 | if (sigsetsize != sizeof(sigset_t)) | 784 | if (sigsetsize != sizeof(sigset_t)) |
785 | return -EINVAL; | 785 | return -EINVAL; |
786 | 786 | ||
787 | if (copy_from_user(&s32, uthese, sizeof(compat_sigset_t))) | 787 | if (copy_from_user(&s32, uthese, sizeof(compat_sigset_t))) |
788 | return -EFAULT; | 788 | return -EFAULT; |
789 | sigset_from_compat(&s, &s32); | 789 | sigset_from_compat(&s, &s32); |
790 | sigdelsetmask(&s,sigmask(SIGKILL)|sigmask(SIGSTOP)); | 790 | sigdelsetmask(&s,sigmask(SIGKILL)|sigmask(SIGSTOP)); |
791 | signotset(&s); | 791 | signotset(&s); |
792 | 792 | ||
793 | if (uts) { | 793 | if (uts) { |
794 | if (get_compat_timespec (&t, uts)) | 794 | if (get_compat_timespec (&t, uts)) |
795 | return -EFAULT; | 795 | return -EFAULT; |
796 | if (t.tv_nsec >= 1000000000L || t.tv_nsec < 0 | 796 | if (t.tv_nsec >= 1000000000L || t.tv_nsec < 0 |
797 | || t.tv_sec < 0) | 797 | || t.tv_sec < 0) |
798 | return -EINVAL; | 798 | return -EINVAL; |
799 | } | 799 | } |
800 | 800 | ||
801 | spin_lock_irq(¤t->sighand->siglock); | 801 | spin_lock_irq(¤t->sighand->siglock); |
802 | sig = dequeue_signal(current, &s, &info); | 802 | sig = dequeue_signal(current, &s, &info); |
803 | if (!sig) { | 803 | if (!sig) { |
804 | timeout = MAX_SCHEDULE_TIMEOUT; | 804 | timeout = MAX_SCHEDULE_TIMEOUT; |
805 | if (uts) | 805 | if (uts) |
806 | timeout = timespec_to_jiffies(&t) | 806 | timeout = timespec_to_jiffies(&t) |
807 | +(t.tv_sec || t.tv_nsec); | 807 | +(t.tv_sec || t.tv_nsec); |
808 | if (timeout) { | 808 | if (timeout) { |
809 | current->real_blocked = current->blocked; | 809 | current->real_blocked = current->blocked; |
810 | sigandsets(¤t->blocked, ¤t->blocked, &s); | 810 | sigandsets(¤t->blocked, ¤t->blocked, &s); |
811 | 811 | ||
812 | recalc_sigpending(); | 812 | recalc_sigpending(); |
813 | spin_unlock_irq(¤t->sighand->siglock); | 813 | spin_unlock_irq(¤t->sighand->siglock); |
814 | 814 | ||
815 | timeout = schedule_timeout_interruptible(timeout); | 815 | timeout = schedule_timeout_interruptible(timeout); |
816 | 816 | ||
817 | spin_lock_irq(¤t->sighand->siglock); | 817 | spin_lock_irq(¤t->sighand->siglock); |
818 | sig = dequeue_signal(current, &s, &info); | 818 | sig = dequeue_signal(current, &s, &info); |
819 | current->blocked = current->real_blocked; | 819 | current->blocked = current->real_blocked; |
820 | siginitset(¤t->real_blocked, 0); | 820 | siginitset(¤t->real_blocked, 0); |
821 | recalc_sigpending(); | 821 | recalc_sigpending(); |
822 | } | 822 | } |
823 | } | 823 | } |
824 | spin_unlock_irq(¤t->sighand->siglock); | 824 | spin_unlock_irq(¤t->sighand->siglock); |
825 | 825 | ||
826 | if (sig) { | 826 | if (sig) { |
827 | ret = sig; | 827 | ret = sig; |
828 | if (uinfo) { | 828 | if (uinfo) { |
829 | if (copy_siginfo_to_user32(uinfo, &info)) | 829 | if (copy_siginfo_to_user32(uinfo, &info)) |
830 | ret = -EFAULT; | 830 | ret = -EFAULT; |
831 | } | 831 | } |
832 | }else { | 832 | }else { |
833 | ret = timeout?-EINTR:-EAGAIN; | 833 | ret = timeout?-EINTR:-EAGAIN; |
834 | } | 834 | } |
835 | return ret; | 835 | return ret; |
836 | 836 | ||
837 | } | 837 | } |
838 | 838 | ||
839 | #ifdef __ARCH_WANT_COMPAT_SYS_TIME | 839 | #ifdef __ARCH_WANT_COMPAT_SYS_TIME |
840 | 840 | ||
841 | /* compat_time_t is a 32 bit "long" and needs to get converted. */ | 841 | /* compat_time_t is a 32 bit "long" and needs to get converted. */ |
842 | 842 | ||
843 | asmlinkage long compat_sys_time(compat_time_t __user * tloc) | 843 | asmlinkage long compat_sys_time(compat_time_t __user * tloc) |
844 | { | 844 | { |
845 | compat_time_t i; | 845 | compat_time_t i; |
846 | struct timeval tv; | 846 | struct timeval tv; |
847 | 847 | ||
848 | do_gettimeofday(&tv); | 848 | do_gettimeofday(&tv); |
849 | i = tv.tv_sec; | 849 | i = tv.tv_sec; |
850 | 850 | ||
851 | if (tloc) { | 851 | if (tloc) { |
852 | if (put_user(i,tloc)) | 852 | if (put_user(i,tloc)) |
853 | i = -EFAULT; | 853 | i = -EFAULT; |
854 | } | 854 | } |
855 | return i; | 855 | return i; |
856 | } | 856 | } |
857 | 857 | ||
858 | asmlinkage long compat_sys_stime(compat_time_t __user *tptr) | 858 | asmlinkage long compat_sys_stime(compat_time_t __user *tptr) |
859 | { | 859 | { |
860 | struct timespec tv; | 860 | struct timespec tv; |
861 | int err; | 861 | int err; |
862 | 862 | ||
863 | if (get_user(tv.tv_sec, tptr)) | 863 | if (get_user(tv.tv_sec, tptr)) |
864 | return -EFAULT; | 864 | return -EFAULT; |
865 | 865 | ||
866 | tv.tv_nsec = 0; | 866 | tv.tv_nsec = 0; |
867 | 867 | ||
868 | err = security_settime(&tv, NULL); | 868 | err = security_settime(&tv, NULL); |
869 | if (err) | 869 | if (err) |
870 | return err; | 870 | return err; |
871 | 871 | ||
872 | do_settimeofday(&tv); | 872 | do_settimeofday(&tv); |
873 | return 0; | 873 | return 0; |
874 | } | 874 | } |
875 | 875 | ||
876 | #endif /* __ARCH_WANT_COMPAT_SYS_TIME */ | 876 | #endif /* __ARCH_WANT_COMPAT_SYS_TIME */ |
877 | 877 | ||
878 | #ifdef __ARCH_WANT_COMPAT_SYS_RT_SIGSUSPEND | 878 | #ifdef __ARCH_WANT_COMPAT_SYS_RT_SIGSUSPEND |
879 | asmlinkage long compat_sys_rt_sigsuspend(compat_sigset_t __user *unewset, compat_size_t sigsetsize) | 879 | asmlinkage long compat_sys_rt_sigsuspend(compat_sigset_t __user *unewset, compat_size_t sigsetsize) |
880 | { | 880 | { |
881 | sigset_t newset; | 881 | sigset_t newset; |
882 | compat_sigset_t newset32; | 882 | compat_sigset_t newset32; |
883 | 883 | ||
884 | /* XXX: Don't preclude handling different sized sigset_t's. */ | 884 | /* XXX: Don't preclude handling different sized sigset_t's. */ |
885 | if (sigsetsize != sizeof(sigset_t)) | 885 | if (sigsetsize != sizeof(sigset_t)) |
886 | return -EINVAL; | 886 | return -EINVAL; |
887 | 887 | ||
888 | if (copy_from_user(&newset32, unewset, sizeof(compat_sigset_t))) | 888 | if (copy_from_user(&newset32, unewset, sizeof(compat_sigset_t))) |
889 | return -EFAULT; | 889 | return -EFAULT; |
890 | sigset_from_compat(&newset, &newset32); | 890 | sigset_from_compat(&newset, &newset32); |
891 | sigdelsetmask(&newset, sigmask(SIGKILL)|sigmask(SIGSTOP)); | 891 | sigdelsetmask(&newset, sigmask(SIGKILL)|sigmask(SIGSTOP)); |
892 | 892 | ||
893 | spin_lock_irq(¤t->sighand->siglock); | 893 | spin_lock_irq(¤t->sighand->siglock); |
894 | current->saved_sigmask = current->blocked; | 894 | current->saved_sigmask = current->blocked; |
895 | current->blocked = newset; | 895 | current->blocked = newset; |
896 | recalc_sigpending(); | 896 | recalc_sigpending(); |
897 | spin_unlock_irq(¤t->sighand->siglock); | 897 | spin_unlock_irq(¤t->sighand->siglock); |
898 | 898 | ||
899 | current->state = TASK_INTERRUPTIBLE; | 899 | current->state = TASK_INTERRUPTIBLE; |
900 | schedule(); | 900 | schedule(); |
901 | set_restore_sigmask(); | 901 | set_restore_sigmask(); |
902 | return -ERESTARTNOHAND; | 902 | return -ERESTARTNOHAND; |
903 | } | 903 | } |
904 | #endif /* __ARCH_WANT_COMPAT_SYS_RT_SIGSUSPEND */ | 904 | #endif /* __ARCH_WANT_COMPAT_SYS_RT_SIGSUSPEND */ |
905 | 905 | ||
906 | asmlinkage long compat_sys_adjtimex(struct compat_timex __user *utp) | 906 | asmlinkage long compat_sys_adjtimex(struct compat_timex __user *utp) |
907 | { | 907 | { |
908 | struct timex txc; | 908 | struct timex txc; |
909 | int ret; | 909 | int ret; |
910 | 910 | ||
911 | memset(&txc, 0, sizeof(struct timex)); | 911 | memset(&txc, 0, sizeof(struct timex)); |
912 | 912 | ||
913 | if (!access_ok(VERIFY_READ, utp, sizeof(struct compat_timex)) || | 913 | if (!access_ok(VERIFY_READ, utp, sizeof(struct compat_timex)) || |
914 | __get_user(txc.modes, &utp->modes) || | 914 | __get_user(txc.modes, &utp->modes) || |
915 | __get_user(txc.offset, &utp->offset) || | 915 | __get_user(txc.offset, &utp->offset) || |
916 | __get_user(txc.freq, &utp->freq) || | 916 | __get_user(txc.freq, &utp->freq) || |
917 | __get_user(txc.maxerror, &utp->maxerror) || | 917 | __get_user(txc.maxerror, &utp->maxerror) || |
918 | __get_user(txc.esterror, &utp->esterror) || | 918 | __get_user(txc.esterror, &utp->esterror) || |
919 | __get_user(txc.status, &utp->status) || | 919 | __get_user(txc.status, &utp->status) || |
920 | __get_user(txc.constant, &utp->constant) || | 920 | __get_user(txc.constant, &utp->constant) || |
921 | __get_user(txc.precision, &utp->precision) || | 921 | __get_user(txc.precision, &utp->precision) || |
922 | __get_user(txc.tolerance, &utp->tolerance) || | 922 | __get_user(txc.tolerance, &utp->tolerance) || |
923 | __get_user(txc.time.tv_sec, &utp->time.tv_sec) || | 923 | __get_user(txc.time.tv_sec, &utp->time.tv_sec) || |
924 | __get_user(txc.time.tv_usec, &utp->time.tv_usec) || | 924 | __get_user(txc.time.tv_usec, &utp->time.tv_usec) || |
925 | __get_user(txc.tick, &utp->tick) || | 925 | __get_user(txc.tick, &utp->tick) || |
926 | __get_user(txc.ppsfreq, &utp->ppsfreq) || | 926 | __get_user(txc.ppsfreq, &utp->ppsfreq) || |
927 | __get_user(txc.jitter, &utp->jitter) || | 927 | __get_user(txc.jitter, &utp->jitter) || |
928 | __get_user(txc.shift, &utp->shift) || | 928 | __get_user(txc.shift, &utp->shift) || |
929 | __get_user(txc.stabil, &utp->stabil) || | 929 | __get_user(txc.stabil, &utp->stabil) || |
930 | __get_user(txc.jitcnt, &utp->jitcnt) || | 930 | __get_user(txc.jitcnt, &utp->jitcnt) || |
931 | __get_user(txc.calcnt, &utp->calcnt) || | 931 | __get_user(txc.calcnt, &utp->calcnt) || |
932 | __get_user(txc.errcnt, &utp->errcnt) || | 932 | __get_user(txc.errcnt, &utp->errcnt) || |
933 | __get_user(txc.stbcnt, &utp->stbcnt)) | 933 | __get_user(txc.stbcnt, &utp->stbcnt)) |
934 | return -EFAULT; | 934 | return -EFAULT; |
935 | 935 | ||
936 | ret = do_adjtimex(&txc); | 936 | ret = do_adjtimex(&txc); |
937 | 937 | ||
938 | if (!access_ok(VERIFY_WRITE, utp, sizeof(struct compat_timex)) || | 938 | if (!access_ok(VERIFY_WRITE, utp, sizeof(struct compat_timex)) || |
939 | __put_user(txc.modes, &utp->modes) || | 939 | __put_user(txc.modes, &utp->modes) || |
940 | __put_user(txc.offset, &utp->offset) || | 940 | __put_user(txc.offset, &utp->offset) || |
941 | __put_user(txc.freq, &utp->freq) || | 941 | __put_user(txc.freq, &utp->freq) || |
942 | __put_user(txc.maxerror, &utp->maxerror) || | 942 | __put_user(txc.maxerror, &utp->maxerror) || |
943 | __put_user(txc.esterror, &utp->esterror) || | 943 | __put_user(txc.esterror, &utp->esterror) || |
944 | __put_user(txc.status, &utp->status) || | 944 | __put_user(txc.status, &utp->status) || |
945 | __put_user(txc.constant, &utp->constant) || | 945 | __put_user(txc.constant, &utp->constant) || |
946 | __put_user(txc.precision, &utp->precision) || | 946 | __put_user(txc.precision, &utp->precision) || |
947 | __put_user(txc.tolerance, &utp->tolerance) || | 947 | __put_user(txc.tolerance, &utp->tolerance) || |
948 | __put_user(txc.time.tv_sec, &utp->time.tv_sec) || | 948 | __put_user(txc.time.tv_sec, &utp->time.tv_sec) || |
949 | __put_user(txc.time.tv_usec, &utp->time.tv_usec) || | 949 | __put_user(txc.time.tv_usec, &utp->time.tv_usec) || |
950 | __put_user(txc.tick, &utp->tick) || | 950 | __put_user(txc.tick, &utp->tick) || |
951 | __put_user(txc.ppsfreq, &utp->ppsfreq) || | 951 | __put_user(txc.ppsfreq, &utp->ppsfreq) || |
952 | __put_user(txc.jitter, &utp->jitter) || | 952 | __put_user(txc.jitter, &utp->jitter) || |
953 | __put_user(txc.shift, &utp->shift) || | 953 | __put_user(txc.shift, &utp->shift) || |
954 | __put_user(txc.stabil, &utp->stabil) || | 954 | __put_user(txc.stabil, &utp->stabil) || |
955 | __put_user(txc.jitcnt, &utp->jitcnt) || | 955 | __put_user(txc.jitcnt, &utp->jitcnt) || |
956 | __put_user(txc.calcnt, &utp->calcnt) || | 956 | __put_user(txc.calcnt, &utp->calcnt) || |
957 | __put_user(txc.errcnt, &utp->errcnt) || | 957 | __put_user(txc.errcnt, &utp->errcnt) || |
958 | __put_user(txc.stbcnt, &utp->stbcnt)) | 958 | __put_user(txc.stbcnt, &utp->stbcnt) || |
959 | __put_user(txc.tai, &utp->tai)) | ||
959 | ret = -EFAULT; | 960 | ret = -EFAULT; |
960 | 961 | ||
961 | return ret; | 962 | return ret; |
962 | } | 963 | } |
963 | 964 | ||
964 | #ifdef CONFIG_NUMA | 965 | #ifdef CONFIG_NUMA |
965 | asmlinkage long compat_sys_move_pages(pid_t pid, unsigned long nr_pages, | 966 | asmlinkage long compat_sys_move_pages(pid_t pid, unsigned long nr_pages, |
966 | compat_uptr_t __user *pages32, | 967 | compat_uptr_t __user *pages32, |
967 | const int __user *nodes, | 968 | const int __user *nodes, |
968 | int __user *status, | 969 | int __user *status, |
969 | int flags) | 970 | int flags) |
970 | { | 971 | { |
971 | const void __user * __user *pages; | 972 | const void __user * __user *pages; |
972 | int i; | 973 | int i; |
973 | 974 | ||
974 | pages = compat_alloc_user_space(nr_pages * sizeof(void *)); | 975 | pages = compat_alloc_user_space(nr_pages * sizeof(void *)); |
975 | for (i = 0; i < nr_pages; i++) { | 976 | for (i = 0; i < nr_pages; i++) { |
976 | compat_uptr_t p; | 977 | compat_uptr_t p; |
977 | 978 | ||
978 | if (get_user(p, pages32 + i) || | 979 | if (get_user(p, pages32 + i) || |
979 | put_user(compat_ptr(p), pages + i)) | 980 | put_user(compat_ptr(p), pages + i)) |
980 | return -EFAULT; | 981 | return -EFAULT; |
981 | } | 982 | } |
982 | return sys_move_pages(pid, nr_pages, pages, nodes, status, flags); | 983 | return sys_move_pages(pid, nr_pages, pages, nodes, status, flags); |
983 | } | 984 | } |
984 | 985 | ||
985 | asmlinkage long compat_sys_migrate_pages(compat_pid_t pid, | 986 | asmlinkage long compat_sys_migrate_pages(compat_pid_t pid, |
986 | compat_ulong_t maxnode, | 987 | compat_ulong_t maxnode, |
987 | const compat_ulong_t __user *old_nodes, | 988 | const compat_ulong_t __user *old_nodes, |
988 | const compat_ulong_t __user *new_nodes) | 989 | const compat_ulong_t __user *new_nodes) |
989 | { | 990 | { |
990 | unsigned long __user *old = NULL; | 991 | unsigned long __user *old = NULL; |
991 | unsigned long __user *new = NULL; | 992 | unsigned long __user *new = NULL; |
992 | nodemask_t tmp_mask; | 993 | nodemask_t tmp_mask; |
993 | unsigned long nr_bits; | 994 | unsigned long nr_bits; |
994 | unsigned long size; | 995 | unsigned long size; |
995 | 996 | ||
996 | nr_bits = min_t(unsigned long, maxnode - 1, MAX_NUMNODES); | 997 | nr_bits = min_t(unsigned long, maxnode - 1, MAX_NUMNODES); |
997 | size = ALIGN(nr_bits, BITS_PER_LONG) / 8; | 998 | size = ALIGN(nr_bits, BITS_PER_LONG) / 8; |
998 | if (old_nodes) { | 999 | if (old_nodes) { |
999 | if (compat_get_bitmap(nodes_addr(tmp_mask), old_nodes, nr_bits)) | 1000 | if (compat_get_bitmap(nodes_addr(tmp_mask), old_nodes, nr_bits)) |
1000 | return -EFAULT; | 1001 | return -EFAULT; |
1001 | old = compat_alloc_user_space(new_nodes ? size * 2 : size); | 1002 | old = compat_alloc_user_space(new_nodes ? size * 2 : size); |
1002 | if (new_nodes) | 1003 | if (new_nodes) |
1003 | new = old + size / sizeof(unsigned long); | 1004 | new = old + size / sizeof(unsigned long); |
1004 | if (copy_to_user(old, nodes_addr(tmp_mask), size)) | 1005 | if (copy_to_user(old, nodes_addr(tmp_mask), size)) |
1005 | return -EFAULT; | 1006 | return -EFAULT; |
1006 | } | 1007 | } |
1007 | if (new_nodes) { | 1008 | if (new_nodes) { |
1008 | if (compat_get_bitmap(nodes_addr(tmp_mask), new_nodes, nr_bits)) | 1009 | if (compat_get_bitmap(nodes_addr(tmp_mask), new_nodes, nr_bits)) |
1009 | return -EFAULT; | 1010 | return -EFAULT; |
1010 | if (new == NULL) | 1011 | if (new == NULL) |
1011 | new = compat_alloc_user_space(size); | 1012 | new = compat_alloc_user_space(size); |
1012 | if (copy_to_user(new, nodes_addr(tmp_mask), size)) | 1013 | if (copy_to_user(new, nodes_addr(tmp_mask), size)) |
1013 | return -EFAULT; | 1014 | return -EFAULT; |
1014 | } | 1015 | } |
1015 | return sys_migrate_pages(pid, nr_bits + 1, old, new); | 1016 | return sys_migrate_pages(pid, nr_bits + 1, old, new); |
1016 | } | 1017 | } |
1017 | #endif | 1018 | #endif |
1018 | 1019 | ||
1019 | struct compat_sysinfo { | 1020 | struct compat_sysinfo { |
1020 | s32 uptime; | 1021 | s32 uptime; |
1021 | u32 loads[3]; | 1022 | u32 loads[3]; |
1022 | u32 totalram; | 1023 | u32 totalram; |
1023 | u32 freeram; | 1024 | u32 freeram; |
1024 | u32 sharedram; | 1025 | u32 sharedram; |
1025 | u32 bufferram; | 1026 | u32 bufferram; |
1026 | u32 totalswap; | 1027 | u32 totalswap; |
1027 | u32 freeswap; | 1028 | u32 freeswap; |
1028 | u16 procs; | 1029 | u16 procs; |
1029 | u16 pad; | 1030 | u16 pad; |
1030 | u32 totalhigh; | 1031 | u32 totalhigh; |
1031 | u32 freehigh; | 1032 | u32 freehigh; |
1032 | u32 mem_unit; | 1033 | u32 mem_unit; |
1033 | char _f[20-2*sizeof(u32)-sizeof(int)]; | 1034 | char _f[20-2*sizeof(u32)-sizeof(int)]; |
1034 | }; | 1035 | }; |
1035 | 1036 | ||
1036 | asmlinkage long | 1037 | asmlinkage long |
1037 | compat_sys_sysinfo(struct compat_sysinfo __user *info) | 1038 | compat_sys_sysinfo(struct compat_sysinfo __user *info) |
1038 | { | 1039 | { |
1039 | struct sysinfo s; | 1040 | struct sysinfo s; |
1040 | 1041 | ||
1041 | do_sysinfo(&s); | 1042 | do_sysinfo(&s); |
1042 | 1043 | ||
1043 | /* Check to see if any memory value is too large for 32-bit and scale | 1044 | /* Check to see if any memory value is too large for 32-bit and scale |
1044 | * down if needed | 1045 | * down if needed |
1045 | */ | 1046 | */ |
1046 | if ((s.totalram >> 32) || (s.totalswap >> 32)) { | 1047 | if ((s.totalram >> 32) || (s.totalswap >> 32)) { |
1047 | int bitcount = 0; | 1048 | int bitcount = 0; |
1048 | 1049 | ||
1049 | while (s.mem_unit < PAGE_SIZE) { | 1050 | while (s.mem_unit < PAGE_SIZE) { |
1050 | s.mem_unit <<= 1; | 1051 | s.mem_unit <<= 1; |
1051 | bitcount++; | 1052 | bitcount++; |
1052 | } | 1053 | } |
1053 | 1054 | ||
1054 | s.totalram >>= bitcount; | 1055 | s.totalram >>= bitcount; |
1055 | s.freeram >>= bitcount; | 1056 | s.freeram >>= bitcount; |
1056 | s.sharedram >>= bitcount; | 1057 | s.sharedram >>= bitcount; |
1057 | s.bufferram >>= bitcount; | 1058 | s.bufferram >>= bitcount; |
1058 | s.totalswap >>= bitcount; | 1059 | s.totalswap >>= bitcount; |
1059 | s.freeswap >>= bitcount; | 1060 | s.freeswap >>= bitcount; |
1060 | s.totalhigh >>= bitcount; | 1061 | s.totalhigh >>= bitcount; |
1061 | s.freehigh >>= bitcount; | 1062 | s.freehigh >>= bitcount; |
1062 | } | 1063 | } |
1063 | 1064 | ||
1064 | if (!access_ok(VERIFY_WRITE, info, sizeof(struct compat_sysinfo)) || | 1065 | if (!access_ok(VERIFY_WRITE, info, sizeof(struct compat_sysinfo)) || |
1065 | __put_user (s.uptime, &info->uptime) || | 1066 | __put_user (s.uptime, &info->uptime) || |
1066 | __put_user (s.loads[0], &info->loads[0]) || | 1067 | __put_user (s.loads[0], &info->loads[0]) || |
1067 | __put_user (s.loads[1], &info->loads[1]) || | 1068 | __put_user (s.loads[1], &info->loads[1]) || |
1068 | __put_user (s.loads[2], &info->loads[2]) || | 1069 | __put_user (s.loads[2], &info->loads[2]) || |
1069 | __put_user (s.totalram, &info->totalram) || | 1070 | __put_user (s.totalram, &info->totalram) || |
1070 | __put_user (s.freeram, &info->freeram) || | 1071 | __put_user (s.freeram, &info->freeram) || |
1071 | __put_user (s.sharedram, &info->sharedram) || | 1072 | __put_user (s.sharedram, &info->sharedram) || |
1072 | __put_user (s.bufferram, &info->bufferram) || | 1073 | __put_user (s.bufferram, &info->bufferram) || |
1073 | __put_user (s.totalswap, &info->totalswap) || | 1074 | __put_user (s.totalswap, &info->totalswap) || |
1074 | __put_user (s.freeswap, &info->freeswap) || | 1075 | __put_user (s.freeswap, &info->freeswap) || |
1075 | __put_user (s.procs, &info->procs) || | 1076 | __put_user (s.procs, &info->procs) || |
1076 | __put_user (s.totalhigh, &info->totalhigh) || | 1077 | __put_user (s.totalhigh, &info->totalhigh) || |
1077 | __put_user (s.freehigh, &info->freehigh) || | 1078 | __put_user (s.freehigh, &info->freehigh) || |
1078 | __put_user (s.mem_unit, &info->mem_unit)) | 1079 | __put_user (s.mem_unit, &info->mem_unit)) |
1079 | return -EFAULT; | 1080 | return -EFAULT; |
1080 | 1081 | ||
1081 | return 0; | 1082 | return 0; |
1082 | } | 1083 | } |
1083 | 1084 |
kernel/time/ntp.c
1 | /* | 1 | /* |
2 | * linux/kernel/time/ntp.c | 2 | * linux/kernel/time/ntp.c |
3 | * | 3 | * |
4 | * NTP state machine interfaces and logic. | 4 | * NTP state machine interfaces and logic. |
5 | * | 5 | * |
6 | * This code was mainly moved from kernel/timer.c and kernel/time.c | 6 | * This code was mainly moved from kernel/timer.c and kernel/time.c |
7 | * Please see those files for relevant copyright info and historical | 7 | * Please see those files for relevant copyright info and historical |
8 | * changelogs. | 8 | * changelogs. |
9 | */ | 9 | */ |
10 | 10 | ||
11 | #include <linux/mm.h> | 11 | #include <linux/mm.h> |
12 | #include <linux/time.h> | 12 | #include <linux/time.h> |
13 | #include <linux/timer.h> | 13 | #include <linux/timer.h> |
14 | #include <linux/timex.h> | 14 | #include <linux/timex.h> |
15 | #include <linux/jiffies.h> | 15 | #include <linux/jiffies.h> |
16 | #include <linux/hrtimer.h> | 16 | #include <linux/hrtimer.h> |
17 | #include <linux/capability.h> | 17 | #include <linux/capability.h> |
18 | #include <linux/math64.h> | 18 | #include <linux/math64.h> |
19 | #include <asm/timex.h> | 19 | #include <asm/timex.h> |
20 | 20 | ||
21 | /* | 21 | /* |
22 | * Timekeeping variables | 22 | * Timekeeping variables |
23 | */ | 23 | */ |
24 | unsigned long tick_usec = TICK_USEC; /* USER_HZ period (usec) */ | 24 | unsigned long tick_usec = TICK_USEC; /* USER_HZ period (usec) */ |
25 | unsigned long tick_nsec; /* ACTHZ period (nsec) */ | 25 | unsigned long tick_nsec; /* ACTHZ period (nsec) */ |
26 | static u64 tick_length, tick_length_base; | 26 | static u64 tick_length, tick_length_base; |
27 | 27 | ||
28 | #define MAX_TICKADJ 500 /* microsecs */ | 28 | #define MAX_TICKADJ 500 /* microsecs */ |
29 | #define MAX_TICKADJ_SCALED (((u64)(MAX_TICKADJ * NSEC_PER_USEC) << \ | 29 | #define MAX_TICKADJ_SCALED (((u64)(MAX_TICKADJ * NSEC_PER_USEC) << \ |
30 | TICK_LENGTH_SHIFT) / NTP_INTERVAL_FREQ) | 30 | TICK_LENGTH_SHIFT) / NTP_INTERVAL_FREQ) |
31 | 31 | ||
32 | /* | 32 | /* |
33 | * phase-lock loop variables | 33 | * phase-lock loop variables |
34 | */ | 34 | */ |
35 | /* TIME_ERROR prevents overwriting the CMOS clock */ | 35 | /* TIME_ERROR prevents overwriting the CMOS clock */ |
36 | static int time_state = TIME_OK; /* clock synchronization status */ | 36 | static int time_state = TIME_OK; /* clock synchronization status */ |
37 | int time_status = STA_UNSYNC; /* clock status bits */ | 37 | int time_status = STA_UNSYNC; /* clock status bits */ |
38 | static long time_tai; /* TAI offset (s) */ | ||
38 | static s64 time_offset; /* time adjustment (ns) */ | 39 | static s64 time_offset; /* time adjustment (ns) */ |
39 | static long time_constant = 2; /* pll time constant */ | 40 | static long time_constant = 2; /* pll time constant */ |
40 | long time_maxerror = NTP_PHASE_LIMIT; /* maximum error (us) */ | 41 | long time_maxerror = NTP_PHASE_LIMIT; /* maximum error (us) */ |
41 | long time_esterror = NTP_PHASE_LIMIT; /* estimated error (us) */ | 42 | long time_esterror = NTP_PHASE_LIMIT; /* estimated error (us) */ |
42 | static s64 time_freq; /* frequency offset (scaled ns/s)*/ | 43 | static s64 time_freq; /* frequency offset (scaled ns/s)*/ |
43 | static long time_reftime; /* time at last adjustment (s) */ | 44 | static long time_reftime; /* time at last adjustment (s) */ |
44 | long time_adjust; | 45 | long time_adjust; |
45 | static long ntp_tick_adj; | 46 | static long ntp_tick_adj; |
46 | 47 | ||
47 | static void ntp_update_frequency(void) | 48 | static void ntp_update_frequency(void) |
48 | { | 49 | { |
49 | u64 second_length = (u64)(tick_usec * NSEC_PER_USEC * USER_HZ) | 50 | u64 second_length = (u64)(tick_usec * NSEC_PER_USEC * USER_HZ) |
50 | << TICK_LENGTH_SHIFT; | 51 | << TICK_LENGTH_SHIFT; |
51 | second_length += (s64)ntp_tick_adj << TICK_LENGTH_SHIFT; | 52 | second_length += (s64)ntp_tick_adj << TICK_LENGTH_SHIFT; |
52 | second_length += time_freq; | 53 | second_length += time_freq; |
53 | 54 | ||
54 | tick_length_base = second_length; | 55 | tick_length_base = second_length; |
55 | 56 | ||
56 | tick_nsec = div_u64(second_length, HZ) >> TICK_LENGTH_SHIFT; | 57 | tick_nsec = div_u64(second_length, HZ) >> TICK_LENGTH_SHIFT; |
57 | tick_length_base = div_u64(tick_length_base, NTP_INTERVAL_FREQ); | 58 | tick_length_base = div_u64(tick_length_base, NTP_INTERVAL_FREQ); |
58 | } | 59 | } |
59 | 60 | ||
60 | static void ntp_update_offset(long offset) | 61 | static void ntp_update_offset(long offset) |
61 | { | 62 | { |
62 | long mtemp; | 63 | long mtemp; |
63 | s64 freq_adj; | 64 | s64 freq_adj; |
64 | 65 | ||
65 | if (!(time_status & STA_PLL)) | 66 | if (!(time_status & STA_PLL)) |
66 | return; | 67 | return; |
67 | 68 | ||
68 | if (!(time_status & STA_NANO)) | 69 | if (!(time_status & STA_NANO)) |
69 | offset *= NSEC_PER_USEC; | 70 | offset *= NSEC_PER_USEC; |
70 | 71 | ||
71 | /* | 72 | /* |
72 | * Scale the phase adjustment and | 73 | * Scale the phase adjustment and |
73 | * clamp to the operating range. | 74 | * clamp to the operating range. |
74 | */ | 75 | */ |
75 | offset = min(offset, MAXPHASE); | 76 | offset = min(offset, MAXPHASE); |
76 | offset = max(offset, -MAXPHASE); | 77 | offset = max(offset, -MAXPHASE); |
77 | 78 | ||
78 | /* | 79 | /* |
79 | * Select how the frequency is to be controlled | 80 | * Select how the frequency is to be controlled |
80 | * and in which mode (PLL or FLL). | 81 | * and in which mode (PLL or FLL). |
81 | */ | 82 | */ |
82 | if (time_status & STA_FREQHOLD || time_reftime == 0) | 83 | if (time_status & STA_FREQHOLD || time_reftime == 0) |
83 | time_reftime = xtime.tv_sec; | 84 | time_reftime = xtime.tv_sec; |
84 | mtemp = xtime.tv_sec - time_reftime; | 85 | mtemp = xtime.tv_sec - time_reftime; |
85 | time_reftime = xtime.tv_sec; | 86 | time_reftime = xtime.tv_sec; |
86 | 87 | ||
87 | freq_adj = (s64)offset * mtemp; | 88 | freq_adj = (s64)offset * mtemp; |
88 | freq_adj <<= TICK_LENGTH_SHIFT - 2 * (SHIFT_PLL + 2 + time_constant); | 89 | freq_adj <<= TICK_LENGTH_SHIFT - 2 * (SHIFT_PLL + 2 + time_constant); |
89 | time_status &= ~STA_MODE; | 90 | time_status &= ~STA_MODE; |
90 | if (mtemp >= MINSEC && (time_status & STA_FLL || mtemp > MAXSEC)) { | 91 | if (mtemp >= MINSEC && (time_status & STA_FLL || mtemp > MAXSEC)) { |
91 | freq_adj += div_s64((s64)offset << (TICK_LENGTH_SHIFT - SHIFT_FLL), | 92 | freq_adj += div_s64((s64)offset << (TICK_LENGTH_SHIFT - SHIFT_FLL), |
92 | mtemp); | 93 | mtemp); |
93 | time_status |= STA_MODE; | 94 | time_status |= STA_MODE; |
94 | } | 95 | } |
95 | freq_adj += time_freq; | 96 | freq_adj += time_freq; |
96 | freq_adj = min(freq_adj, MAXFREQ_SCALED); | 97 | freq_adj = min(freq_adj, MAXFREQ_SCALED); |
97 | time_freq = max(freq_adj, -MAXFREQ_SCALED); | 98 | time_freq = max(freq_adj, -MAXFREQ_SCALED); |
98 | 99 | ||
99 | time_offset = div_s64((s64)offset << TICK_LENGTH_SHIFT, NTP_INTERVAL_FREQ); | 100 | time_offset = div_s64((s64)offset << TICK_LENGTH_SHIFT, NTP_INTERVAL_FREQ); |
100 | } | 101 | } |
101 | 102 | ||
102 | /** | 103 | /** |
103 | * ntp_clear - Clears the NTP state variables | 104 | * ntp_clear - Clears the NTP state variables |
104 | * | 105 | * |
105 | * Must be called while holding a write on the xtime_lock | 106 | * Must be called while holding a write on the xtime_lock |
106 | */ | 107 | */ |
107 | void ntp_clear(void) | 108 | void ntp_clear(void) |
108 | { | 109 | { |
109 | time_adjust = 0; /* stop active adjtime() */ | 110 | time_adjust = 0; /* stop active adjtime() */ |
110 | time_status |= STA_UNSYNC; | 111 | time_status |= STA_UNSYNC; |
111 | time_maxerror = NTP_PHASE_LIMIT; | 112 | time_maxerror = NTP_PHASE_LIMIT; |
112 | time_esterror = NTP_PHASE_LIMIT; | 113 | time_esterror = NTP_PHASE_LIMIT; |
113 | 114 | ||
114 | ntp_update_frequency(); | 115 | ntp_update_frequency(); |
115 | 116 | ||
116 | tick_length = tick_length_base; | 117 | tick_length = tick_length_base; |
117 | time_offset = 0; | 118 | time_offset = 0; |
118 | } | 119 | } |
119 | 120 | ||
120 | /* | 121 | /* |
121 | * this routine handles the overflow of the microsecond field | 122 | * this routine handles the overflow of the microsecond field |
122 | * | 123 | * |
123 | * The tricky bits of code to handle the accurate clock support | 124 | * The tricky bits of code to handle the accurate clock support |
124 | * were provided by Dave Mills (Mills@UDEL.EDU) of NTP fame. | 125 | * were provided by Dave Mills (Mills@UDEL.EDU) of NTP fame. |
125 | * They were originally developed for SUN and DEC kernels. | 126 | * They were originally developed for SUN and DEC kernels. |
126 | * All the kudos should go to Dave for this stuff. | 127 | * All the kudos should go to Dave for this stuff. |
127 | */ | 128 | */ |
128 | void second_overflow(void) | 129 | void second_overflow(void) |
129 | { | 130 | { |
130 | s64 time_adj; | 131 | s64 time_adj; |
131 | 132 | ||
132 | /* Bump the maxerror field */ | 133 | /* Bump the maxerror field */ |
133 | time_maxerror += MAXFREQ / NSEC_PER_USEC; | 134 | time_maxerror += MAXFREQ / NSEC_PER_USEC; |
134 | if (time_maxerror > NTP_PHASE_LIMIT) { | 135 | if (time_maxerror > NTP_PHASE_LIMIT) { |
135 | time_maxerror = NTP_PHASE_LIMIT; | 136 | time_maxerror = NTP_PHASE_LIMIT; |
136 | time_status |= STA_UNSYNC; | 137 | time_status |= STA_UNSYNC; |
137 | } | 138 | } |
138 | 139 | ||
139 | /* | 140 | /* |
140 | * Leap second processing. If in leap-insert state at the end of the | 141 | * Leap second processing. If in leap-insert state at the end of the |
141 | * day, the system clock is set back one second; if in leap-delete | 142 | * day, the system clock is set back one second; if in leap-delete |
142 | * state, the system clock is set ahead one second. The microtime() | 143 | * state, the system clock is set ahead one second. The microtime() |
143 | * routine or external clock driver will insure that reported time is | 144 | * routine or external clock driver will insure that reported time is |
144 | * always monotonic. The ugly divides should be replaced. | 145 | * always monotonic. The ugly divides should be replaced. |
145 | */ | 146 | */ |
146 | switch (time_state) { | 147 | switch (time_state) { |
147 | case TIME_OK: | 148 | case TIME_OK: |
148 | if (time_status & STA_INS) | 149 | if (time_status & STA_INS) |
149 | time_state = TIME_INS; | 150 | time_state = TIME_INS; |
150 | else if (time_status & STA_DEL) | 151 | else if (time_status & STA_DEL) |
151 | time_state = TIME_DEL; | 152 | time_state = TIME_DEL; |
152 | break; | 153 | break; |
153 | case TIME_INS: | 154 | case TIME_INS: |
154 | if (xtime.tv_sec % 86400 == 0) { | 155 | if (xtime.tv_sec % 86400 == 0) { |
155 | xtime.tv_sec--; | 156 | xtime.tv_sec--; |
156 | wall_to_monotonic.tv_sec++; | 157 | wall_to_monotonic.tv_sec++; |
157 | time_state = TIME_OOP; | 158 | time_state = TIME_OOP; |
158 | printk(KERN_NOTICE "Clock: inserting leap second " | 159 | printk(KERN_NOTICE "Clock: inserting leap second " |
159 | "23:59:60 UTC\n"); | 160 | "23:59:60 UTC\n"); |
160 | } | 161 | } |
161 | break; | 162 | break; |
162 | case TIME_DEL: | 163 | case TIME_DEL: |
163 | if ((xtime.tv_sec + 1) % 86400 == 0) { | 164 | if ((xtime.tv_sec + 1) % 86400 == 0) { |
164 | xtime.tv_sec++; | 165 | xtime.tv_sec++; |
166 | time_tai--; | ||
165 | wall_to_monotonic.tv_sec--; | 167 | wall_to_monotonic.tv_sec--; |
166 | time_state = TIME_WAIT; | 168 | time_state = TIME_WAIT; |
167 | printk(KERN_NOTICE "Clock: deleting leap second " | 169 | printk(KERN_NOTICE "Clock: deleting leap second " |
168 | "23:59:59 UTC\n"); | 170 | "23:59:59 UTC\n"); |
169 | } | 171 | } |
170 | break; | 172 | break; |
171 | case TIME_OOP: | 173 | case TIME_OOP: |
174 | time_tai++; | ||
172 | time_state = TIME_WAIT; | 175 | time_state = TIME_WAIT; |
173 | break; | 176 | break; |
174 | case TIME_WAIT: | 177 | case TIME_WAIT: |
175 | if (!(time_status & (STA_INS | STA_DEL))) | 178 | if (!(time_status & (STA_INS | STA_DEL))) |
176 | time_state = TIME_OK; | 179 | time_state = TIME_OK; |
177 | } | 180 | } |
178 | 181 | ||
179 | /* | 182 | /* |
180 | * Compute the phase adjustment for the next second. The offset is | 183 | * Compute the phase adjustment for the next second. The offset is |
181 | * reduced by a fixed factor times the time constant. | 184 | * reduced by a fixed factor times the time constant. |
182 | */ | 185 | */ |
183 | tick_length = tick_length_base; | 186 | tick_length = tick_length_base; |
184 | time_adj = shift_right(time_offset, SHIFT_PLL + time_constant); | 187 | time_adj = shift_right(time_offset, SHIFT_PLL + time_constant); |
185 | time_offset -= time_adj; | 188 | time_offset -= time_adj; |
186 | tick_length += time_adj; | 189 | tick_length += time_adj; |
187 | 190 | ||
188 | if (unlikely(time_adjust)) { | 191 | if (unlikely(time_adjust)) { |
189 | if (time_adjust > MAX_TICKADJ) { | 192 | if (time_adjust > MAX_TICKADJ) { |
190 | time_adjust -= MAX_TICKADJ; | 193 | time_adjust -= MAX_TICKADJ; |
191 | tick_length += MAX_TICKADJ_SCALED; | 194 | tick_length += MAX_TICKADJ_SCALED; |
192 | } else if (time_adjust < -MAX_TICKADJ) { | 195 | } else if (time_adjust < -MAX_TICKADJ) { |
193 | time_adjust += MAX_TICKADJ; | 196 | time_adjust += MAX_TICKADJ; |
194 | tick_length -= MAX_TICKADJ_SCALED; | 197 | tick_length -= MAX_TICKADJ_SCALED; |
195 | } else { | 198 | } else { |
196 | tick_length += (s64)(time_adjust * NSEC_PER_USEC / | 199 | tick_length += (s64)(time_adjust * NSEC_PER_USEC / |
197 | NTP_INTERVAL_FREQ) << TICK_LENGTH_SHIFT; | 200 | NTP_INTERVAL_FREQ) << TICK_LENGTH_SHIFT; |
198 | time_adjust = 0; | 201 | time_adjust = 0; |
199 | } | 202 | } |
200 | } | 203 | } |
201 | } | 204 | } |
202 | 205 | ||
203 | /* | 206 | /* |
204 | * Return how long ticks are at the moment, that is, how much time | 207 | * Return how long ticks are at the moment, that is, how much time |
205 | * update_wall_time_one_tick will add to xtime next time we call it | 208 | * update_wall_time_one_tick will add to xtime next time we call it |
206 | * (assuming no calls to do_adjtimex in the meantime). | 209 | * (assuming no calls to do_adjtimex in the meantime). |
207 | * The return value is in fixed-point nanoseconds shifted by the | 210 | * The return value is in fixed-point nanoseconds shifted by the |
208 | * specified number of bits to the right of the binary point. | 211 | * specified number of bits to the right of the binary point. |
209 | * This function has no side-effects. | 212 | * This function has no side-effects. |
210 | */ | 213 | */ |
211 | u64 current_tick_length(void) | 214 | u64 current_tick_length(void) |
212 | { | 215 | { |
213 | return tick_length; | 216 | return tick_length; |
214 | } | 217 | } |
215 | 218 | ||
216 | #ifdef CONFIG_GENERIC_CMOS_UPDATE | 219 | #ifdef CONFIG_GENERIC_CMOS_UPDATE |
217 | 220 | ||
218 | /* Disable the cmos update - used by virtualization and embedded */ | 221 | /* Disable the cmos update - used by virtualization and embedded */ |
219 | int no_sync_cmos_clock __read_mostly; | 222 | int no_sync_cmos_clock __read_mostly; |
220 | 223 | ||
221 | static void sync_cmos_clock(unsigned long dummy); | 224 | static void sync_cmos_clock(unsigned long dummy); |
222 | 225 | ||
223 | static DEFINE_TIMER(sync_cmos_timer, sync_cmos_clock, 0, 0); | 226 | static DEFINE_TIMER(sync_cmos_timer, sync_cmos_clock, 0, 0); |
224 | 227 | ||
225 | static void sync_cmos_clock(unsigned long dummy) | 228 | static void sync_cmos_clock(unsigned long dummy) |
226 | { | 229 | { |
227 | struct timespec now, next; | 230 | struct timespec now, next; |
228 | int fail = 1; | 231 | int fail = 1; |
229 | 232 | ||
230 | /* | 233 | /* |
231 | * If we have an externally synchronized Linux clock, then update | 234 | * If we have an externally synchronized Linux clock, then update |
232 | * CMOS clock accordingly every ~11 minutes. Set_rtc_mmss() has to be | 235 | * CMOS clock accordingly every ~11 minutes. Set_rtc_mmss() has to be |
233 | * called as close as possible to 500 ms before the new second starts. | 236 | * called as close as possible to 500 ms before the new second starts. |
234 | * This code is run on a timer. If the clock is set, that timer | 237 | * This code is run on a timer. If the clock is set, that timer |
235 | * may not expire at the correct time. Thus, we adjust... | 238 | * may not expire at the correct time. Thus, we adjust... |
236 | */ | 239 | */ |
237 | if (!ntp_synced()) | 240 | if (!ntp_synced()) |
238 | /* | 241 | /* |
239 | * Not synced, exit, do not restart a timer (if one is | 242 | * Not synced, exit, do not restart a timer (if one is |
240 | * running, let it run out). | 243 | * running, let it run out). |
241 | */ | 244 | */ |
242 | return; | 245 | return; |
243 | 246 | ||
244 | getnstimeofday(&now); | 247 | getnstimeofday(&now); |
245 | if (abs(now.tv_nsec - (NSEC_PER_SEC / 2)) <= tick_nsec / 2) | 248 | if (abs(now.tv_nsec - (NSEC_PER_SEC / 2)) <= tick_nsec / 2) |
246 | fail = update_persistent_clock(now); | 249 | fail = update_persistent_clock(now); |
247 | 250 | ||
248 | next.tv_nsec = (NSEC_PER_SEC / 2) - now.tv_nsec; | 251 | next.tv_nsec = (NSEC_PER_SEC / 2) - now.tv_nsec; |
249 | if (next.tv_nsec <= 0) | 252 | if (next.tv_nsec <= 0) |
250 | next.tv_nsec += NSEC_PER_SEC; | 253 | next.tv_nsec += NSEC_PER_SEC; |
251 | 254 | ||
252 | if (!fail) | 255 | if (!fail) |
253 | next.tv_sec = 659; | 256 | next.tv_sec = 659; |
254 | else | 257 | else |
255 | next.tv_sec = 0; | 258 | next.tv_sec = 0; |
256 | 259 | ||
257 | if (next.tv_nsec >= NSEC_PER_SEC) { | 260 | if (next.tv_nsec >= NSEC_PER_SEC) { |
258 | next.tv_sec++; | 261 | next.tv_sec++; |
259 | next.tv_nsec -= NSEC_PER_SEC; | 262 | next.tv_nsec -= NSEC_PER_SEC; |
260 | } | 263 | } |
261 | mod_timer(&sync_cmos_timer, jiffies + timespec_to_jiffies(&next)); | 264 | mod_timer(&sync_cmos_timer, jiffies + timespec_to_jiffies(&next)); |
262 | } | 265 | } |
263 | 266 | ||
264 | static void notify_cmos_timer(void) | 267 | static void notify_cmos_timer(void) |
265 | { | 268 | { |
266 | if (!no_sync_cmos_clock) | 269 | if (!no_sync_cmos_clock) |
267 | mod_timer(&sync_cmos_timer, jiffies + 1); | 270 | mod_timer(&sync_cmos_timer, jiffies + 1); |
268 | } | 271 | } |
269 | 272 | ||
270 | #else | 273 | #else |
271 | static inline void notify_cmos_timer(void) { } | 274 | static inline void notify_cmos_timer(void) { } |
272 | #endif | 275 | #endif |
273 | 276 | ||
274 | /* adjtimex mainly allows reading (and writing, if superuser) of | 277 | /* adjtimex mainly allows reading (and writing, if superuser) of |
275 | * kernel time-keeping variables. used by xntpd. | 278 | * kernel time-keeping variables. used by xntpd. |
276 | */ | 279 | */ |
277 | int do_adjtimex(struct timex *txc) | 280 | int do_adjtimex(struct timex *txc) |
278 | { | 281 | { |
279 | struct timespec ts; | 282 | struct timespec ts; |
280 | long save_adjust; | 283 | long save_adjust; |
281 | int result; | 284 | int result; |
282 | 285 | ||
283 | /* In order to modify anything, you gotta be super-user! */ | 286 | /* In order to modify anything, you gotta be super-user! */ |
284 | if (txc->modes && !capable(CAP_SYS_TIME)) | 287 | if (txc->modes && !capable(CAP_SYS_TIME)) |
285 | return -EPERM; | 288 | return -EPERM; |
286 | 289 | ||
287 | /* Now we validate the data before disabling interrupts */ | 290 | /* Now we validate the data before disabling interrupts */ |
288 | 291 | ||
289 | if ((txc->modes & ADJ_OFFSET_SINGLESHOT) == ADJ_OFFSET_SINGLESHOT) { | 292 | if ((txc->modes & ADJ_OFFSET_SINGLESHOT) == ADJ_OFFSET_SINGLESHOT) { |
290 | /* singleshot must not be used with any other mode bits */ | 293 | /* singleshot must not be used with any other mode bits */ |
291 | if (txc->modes & ~ADJ_OFFSET_SS_READ) | 294 | if (txc->modes & ~ADJ_OFFSET_SS_READ) |
292 | return -EINVAL; | 295 | return -EINVAL; |
293 | } | 296 | } |
294 | 297 | ||
295 | /* if the quartz is off by more than 10% something is VERY wrong ! */ | 298 | /* if the quartz is off by more than 10% something is VERY wrong ! */ |
296 | if (txc->modes & ADJ_TICK) | 299 | if (txc->modes & ADJ_TICK) |
297 | if (txc->tick < 900000/USER_HZ || | 300 | if (txc->tick < 900000/USER_HZ || |
298 | txc->tick > 1100000/USER_HZ) | 301 | txc->tick > 1100000/USER_HZ) |
299 | return -EINVAL; | 302 | return -EINVAL; |
300 | 303 | ||
301 | write_seqlock_irq(&xtime_lock); | 304 | write_seqlock_irq(&xtime_lock); |
302 | 305 | ||
303 | /* Save for later - semantics of adjtime is to return old value */ | 306 | /* Save for later - semantics of adjtime is to return old value */ |
304 | save_adjust = time_adjust; | 307 | save_adjust = time_adjust; |
305 | 308 | ||
306 | /* If there are input parameters, then process them */ | 309 | /* If there are input parameters, then process them */ |
307 | if (txc->modes) { | 310 | if (txc->modes) { |
308 | if (txc->modes & ADJ_STATUS) { | 311 | if (txc->modes & ADJ_STATUS) { |
309 | if ((time_status & STA_PLL) && | 312 | if ((time_status & STA_PLL) && |
310 | !(txc->status & STA_PLL)) { | 313 | !(txc->status & STA_PLL)) { |
311 | time_state = TIME_OK; | 314 | time_state = TIME_OK; |
312 | time_status = STA_UNSYNC; | 315 | time_status = STA_UNSYNC; |
313 | } | 316 | } |
314 | /* only set allowed bits */ | 317 | /* only set allowed bits */ |
315 | time_status &= STA_RONLY; | 318 | time_status &= STA_RONLY; |
316 | time_status |= txc->status & ~STA_RONLY; | 319 | time_status |= txc->status & ~STA_RONLY; |
317 | } | 320 | } |
318 | 321 | ||
319 | if (txc->modes & ADJ_NANO) | 322 | if (txc->modes & ADJ_NANO) |
320 | time_status |= STA_NANO; | 323 | time_status |= STA_NANO; |
321 | if (txc->modes & ADJ_MICRO) | 324 | if (txc->modes & ADJ_MICRO) |
322 | time_status &= ~STA_NANO; | 325 | time_status &= ~STA_NANO; |
323 | 326 | ||
324 | if (txc->modes & ADJ_FREQUENCY) { | 327 | if (txc->modes & ADJ_FREQUENCY) { |
325 | time_freq = (s64)txc->freq * PPM_SCALE; | 328 | time_freq = (s64)txc->freq * PPM_SCALE; |
326 | time_freq = min(time_freq, MAXFREQ_SCALED); | 329 | time_freq = min(time_freq, MAXFREQ_SCALED); |
327 | time_freq = max(time_freq, -MAXFREQ_SCALED); | 330 | time_freq = max(time_freq, -MAXFREQ_SCALED); |
328 | } | 331 | } |
329 | 332 | ||
330 | if (txc->modes & ADJ_MAXERROR) | 333 | if (txc->modes & ADJ_MAXERROR) |
331 | time_maxerror = txc->maxerror; | 334 | time_maxerror = txc->maxerror; |
332 | if (txc->modes & ADJ_ESTERROR) | 335 | if (txc->modes & ADJ_ESTERROR) |
333 | time_esterror = txc->esterror; | 336 | time_esterror = txc->esterror; |
334 | 337 | ||
335 | if (txc->modes & ADJ_TIMECONST) { | 338 | if (txc->modes & ADJ_TIMECONST) { |
336 | time_constant = txc->constant; | 339 | time_constant = txc->constant; |
337 | if (!(time_status & STA_NANO)) | 340 | if (!(time_status & STA_NANO)) |
338 | time_constant += 4; | 341 | time_constant += 4; |
339 | time_constant = min(time_constant, (long)MAXTC); | 342 | time_constant = min(time_constant, (long)MAXTC); |
340 | time_constant = max(time_constant, 0l); | 343 | time_constant = max(time_constant, 0l); |
341 | } | 344 | } |
342 | 345 | ||
346 | if (txc->modes & ADJ_TAI && txc->constant > 0) | ||
347 | time_tai = txc->constant; | ||
348 | |||
343 | if (txc->modes & ADJ_OFFSET) { | 349 | if (txc->modes & ADJ_OFFSET) { |
344 | if (txc->modes == ADJ_OFFSET_SINGLESHOT) | 350 | if (txc->modes == ADJ_OFFSET_SINGLESHOT) |
345 | /* adjtime() is independent from ntp_adjtime() */ | 351 | /* adjtime() is independent from ntp_adjtime() */ |
346 | time_adjust = txc->offset; | 352 | time_adjust = txc->offset; |
347 | else | 353 | else |
348 | ntp_update_offset(txc->offset); | 354 | ntp_update_offset(txc->offset); |
349 | } | 355 | } |
350 | if (txc->modes & ADJ_TICK) | 356 | if (txc->modes & ADJ_TICK) |
351 | tick_usec = txc->tick; | 357 | tick_usec = txc->tick; |
352 | 358 | ||
353 | if (txc->modes & (ADJ_TICK|ADJ_FREQUENCY|ADJ_OFFSET)) | 359 | if (txc->modes & (ADJ_TICK|ADJ_FREQUENCY|ADJ_OFFSET)) |
354 | ntp_update_frequency(); | 360 | ntp_update_frequency(); |
355 | } | 361 | } |
356 | 362 | ||
357 | result = time_state; /* mostly `TIME_OK' */ | 363 | result = time_state; /* mostly `TIME_OK' */ |
358 | if (time_status & (STA_UNSYNC|STA_CLOCKERR)) | 364 | if (time_status & (STA_UNSYNC|STA_CLOCKERR)) |
359 | result = TIME_ERROR; | 365 | result = TIME_ERROR; |
360 | 366 | ||
361 | if ((txc->modes == ADJ_OFFSET_SINGLESHOT) || | 367 | if ((txc->modes == ADJ_OFFSET_SINGLESHOT) || |
362 | (txc->modes == ADJ_OFFSET_SS_READ)) | 368 | (txc->modes == ADJ_OFFSET_SS_READ)) |
363 | txc->offset = save_adjust; | 369 | txc->offset = save_adjust; |
364 | else { | 370 | else { |
365 | txc->offset = shift_right(time_offset * NTP_INTERVAL_FREQ, | 371 | txc->offset = shift_right(time_offset * NTP_INTERVAL_FREQ, |
366 | TICK_LENGTH_SHIFT); | 372 | TICK_LENGTH_SHIFT); |
367 | if (!(time_status & STA_NANO)) | 373 | if (!(time_status & STA_NANO)) |
368 | txc->offset /= NSEC_PER_USEC; | 374 | txc->offset /= NSEC_PER_USEC; |
369 | } | 375 | } |
370 | txc->freq = shift_right((s32)(time_freq >> PPM_SCALE_INV_SHIFT) * | 376 | txc->freq = shift_right((s32)(time_freq >> PPM_SCALE_INV_SHIFT) * |
371 | (s64)PPM_SCALE_INV, | 377 | (s64)PPM_SCALE_INV, |
372 | TICK_LENGTH_SHIFT); | 378 | TICK_LENGTH_SHIFT); |
373 | txc->maxerror = time_maxerror; | 379 | txc->maxerror = time_maxerror; |
374 | txc->esterror = time_esterror; | 380 | txc->esterror = time_esterror; |
375 | txc->status = time_status; | 381 | txc->status = time_status; |
376 | txc->constant = time_constant; | 382 | txc->constant = time_constant; |
377 | txc->precision = 1; | 383 | txc->precision = 1; |
378 | txc->tolerance = MAXFREQ_SCALED / PPM_SCALE; | 384 | txc->tolerance = MAXFREQ_SCALED / PPM_SCALE; |
379 | txc->tick = tick_usec; | 385 | txc->tick = tick_usec; |
386 | txc->tai = time_tai; | ||
380 | 387 | ||
381 | /* PPS is not implemented, so these are zero */ | 388 | /* PPS is not implemented, so these are zero */ |
382 | txc->ppsfreq = 0; | 389 | txc->ppsfreq = 0; |
383 | txc->jitter = 0; | 390 | txc->jitter = 0; |
384 | txc->shift = 0; | 391 | txc->shift = 0; |
385 | txc->stabil = 0; | 392 | txc->stabil = 0; |
386 | txc->jitcnt = 0; | 393 | txc->jitcnt = 0; |
387 | txc->calcnt = 0; | 394 | txc->calcnt = 0; |
388 | txc->errcnt = 0; | 395 | txc->errcnt = 0; |
389 | txc->stbcnt = 0; | 396 | txc->stbcnt = 0; |
390 | write_sequnlock_irq(&xtime_lock); | 397 | write_sequnlock_irq(&xtime_lock); |
391 | 398 | ||
392 | getnstimeofday(&ts); | 399 | getnstimeofday(&ts); |
393 | txc->time.tv_sec = ts.tv_sec; | 400 | txc->time.tv_sec = ts.tv_sec; |
394 | txc->time.tv_usec = ts.tv_nsec; | 401 | txc->time.tv_usec = ts.tv_nsec; |
395 | if (!(time_status & STA_NANO)) | 402 | if (!(time_status & STA_NANO)) |
396 | txc->time.tv_usec /= NSEC_PER_USEC; | 403 | txc->time.tv_usec /= NSEC_PER_USEC; |
397 | 404 | ||
398 | notify_cmos_timer(); | 405 | notify_cmos_timer(); |
399 | 406 | ||
400 | return result; | 407 | return result; |
401 | } | 408 | } |
402 | 409 | ||
403 | static int __init ntp_tick_adj_setup(char *str) | 410 | static int __init ntp_tick_adj_setup(char *str) |
404 | { | 411 | { |
405 | ntp_tick_adj = simple_strtol(str, NULL, 0); | 412 | ntp_tick_adj = simple_strtol(str, NULL, 0); |
406 | return 1; | 413 | return 1; |
407 | } | 414 | } |
408 | 415 | ||
409 | __setup("ntp_tick_adj=", ntp_tick_adj_setup); | 416 | __setup("ntp_tick_adj=", ntp_tick_adj_setup); |
410 | 417 |