blob: d98634c76060e735290c03f0fabff5d635437e8c [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * sys_ppc32.c: Conversion between 32bit and 64bit native syscalls.
3 *
4 * Copyright (C) 2001 IBM
5 * Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
6 * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu)
7 *
8 * These routines maintain argument size conversion between 32bit and 64bit
9 * environment.
10 *
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License
13 * as published by the Free Software Foundation; either version
14 * 2 of the License, or (at your option) any later version.
15 */
16
Linus Torvalds1da177e2005-04-16 15:20:36 -070017#include <linux/kernel.h>
18#include <linux/sched.h>
19#include <linux/fs.h>
20#include <linux/mm.h>
21#include <linux/file.h>
22#include <linux/signal.h>
23#include <linux/resource.h>
24#include <linux/times.h>
25#include <linux/utsname.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070026#include <linux/smp.h>
27#include <linux/smp_lock.h>
28#include <linux/sem.h>
29#include <linux/msg.h>
30#include <linux/shm.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070031#include <linux/poll.h>
32#include <linux/personality.h>
33#include <linux/stat.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070034#include <linux/mman.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070035#include <linux/in.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070036#include <linux/syscalls.h>
37#include <linux/unistd.h>
38#include <linux/sysctl.h>
39#include <linux/binfmts.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070040#include <linux/security.h>
41#include <linux/compat.h>
42#include <linux/ptrace.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070043#include <linux/elf.h>
Adrian Bunkcba4fbb2007-10-16 23:29:24 -070044#include <linux/ipc.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070045
Linus Torvalds1da177e2005-04-16 15:20:36 -070046#include <asm/ptrace.h>
47#include <asm/types.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070048#include <asm/uaccess.h>
49#include <asm/unistd.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070050#include <asm/time.h>
51#include <asm/mmu_context.h>
Stephen Rothwelld3878992005-09-28 02:50:25 +100052#include <asm/ppc-pci.h>
Arnd Bergmann369cf4b2006-11-27 19:18:59 +010053#include <asm/syscalls.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070054
Linus Torvalds1da177e2005-04-16 15:20:36 -070055
Linus Torvalds1da177e2005-04-16 15:20:36 -070056asmlinkage long ppc32_select(u32 n, compat_ulong_t __user *inp,
57 compat_ulong_t __user *outp, compat_ulong_t __user *exp,
58 compat_uptr_t tvp_x)
59{
60 /* sign extend n */
61 return compat_sys_select((int)n, inp, outp, exp, compat_ptr(tvp_x));
62}
63
64int cp_compat_stat(struct kstat *stat, struct compat_stat __user *statbuf)
65{
David Howellsafefdbb2006-10-03 01:13:46 -070066 compat_ino_t ino;
Linus Torvalds1da177e2005-04-16 15:20:36 -070067 long err;
68
69 if (stat->size > MAX_NON_LFS || !new_valid_dev(stat->dev) ||
70 !new_valid_dev(stat->rdev))
71 return -EOVERFLOW;
72
David Howellsafefdbb2006-10-03 01:13:46 -070073 ino = stat->ino;
74 if (sizeof(ino) < sizeof(stat->ino) && ino != stat->ino)
75 return -EOVERFLOW;
76
Linus Torvalds1da177e2005-04-16 15:20:36 -070077 err = access_ok(VERIFY_WRITE, statbuf, sizeof(*statbuf)) ? 0 : -EFAULT;
78 err |= __put_user(new_encode_dev(stat->dev), &statbuf->st_dev);
David Howellsafefdbb2006-10-03 01:13:46 -070079 err |= __put_user(ino, &statbuf->st_ino);
Linus Torvalds1da177e2005-04-16 15:20:36 -070080 err |= __put_user(stat->mode, &statbuf->st_mode);
81 err |= __put_user(stat->nlink, &statbuf->st_nlink);
82 err |= __put_user(stat->uid, &statbuf->st_uid);
83 err |= __put_user(stat->gid, &statbuf->st_gid);
84 err |= __put_user(new_encode_dev(stat->rdev), &statbuf->st_rdev);
85 err |= __put_user(stat->size, &statbuf->st_size);
86 err |= __put_user(stat->atime.tv_sec, &statbuf->st_atime);
87 err |= __put_user(stat->atime.tv_nsec, &statbuf->st_atime_nsec);
88 err |= __put_user(stat->mtime.tv_sec, &statbuf->st_mtime);
89 err |= __put_user(stat->mtime.tv_nsec, &statbuf->st_mtime_nsec);
90 err |= __put_user(stat->ctime.tv_sec, &statbuf->st_ctime);
91 err |= __put_user(stat->ctime.tv_nsec, &statbuf->st_ctime_nsec);
92 err |= __put_user(stat->blksize, &statbuf->st_blksize);
93 err |= __put_user(stat->blocks, &statbuf->st_blocks);
94 err |= __put_user(0, &statbuf->__unused4[0]);
95 err |= __put_user(0, &statbuf->__unused4[1]);
96
97 return err;
98}
99
100/* Note: it is necessary to treat option as an unsigned int,
101 * with the corresponding cast to a signed int to insure that the
102 * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
103 * and the register representation of a signed int (msr in 64-bit mode) is performed.
104 */
Stephen Rothwellb09a4912005-10-18 14:51:57 +1000105asmlinkage long compat_sys_sysfs(u32 option, u32 arg1, u32 arg2)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700106{
107 return sys_sysfs((int)option, arg1, arg2);
108}
109
Stephen Rothwellb09a4912005-10-18 14:51:57 +1000110asmlinkage long compat_sys_pause(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700111{
112 current->state = TASK_INTERRUPTIBLE;
113 schedule();
114
115 return -ERESTARTNOHAND;
116}
117
Linus Torvalds1da177e2005-04-16 15:20:36 -0700118static inline long get_ts32(struct timespec *o, struct compat_timeval __user *i)
119{
120 long usec;
121
122 if (!access_ok(VERIFY_READ, i, sizeof(*i)))
123 return -EFAULT;
124 if (__get_user(o->tv_sec, &i->tv_sec))
125 return -EFAULT;
126 if (__get_user(usec, &i->tv_usec))
127 return -EFAULT;
128 o->tv_nsec = usec * 1000;
129 return 0;
130}
131
132static inline long put_tv32(struct compat_timeval __user *o, struct timeval *i)
133{
134 return (!access_ok(VERIFY_WRITE, o, sizeof(*o)) ||
135 (__put_user(i->tv_sec, &o->tv_sec) |
136 __put_user(i->tv_usec, &o->tv_usec)));
137}
138
Linus Torvalds1da177e2005-04-16 15:20:36 -0700139
140
141
142/* Translations due to time_t size differences. Which affects all
143 sorts of things, like timeval and itimerval. */
144extern struct timezone sys_tz;
145
Stephen Rothwellb09a4912005-10-18 14:51:57 +1000146asmlinkage long compat_sys_gettimeofday(struct compat_timeval __user *tv, struct timezone __user *tz)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700147{
148 if (tv) {
149 struct timeval ktv;
150 do_gettimeofday(&ktv);
151 if (put_tv32(tv, &ktv))
152 return -EFAULT;
153 }
154 if (tz) {
155 if (copy_to_user(tz, &sys_tz, sizeof(sys_tz)))
156 return -EFAULT;
157 }
158
159 return 0;
160}
161
162
163
Stephen Rothwellb09a4912005-10-18 14:51:57 +1000164asmlinkage long compat_sys_settimeofday(struct compat_timeval __user *tv, struct timezone __user *tz)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700165{
166 struct timespec kts;
167 struct timezone ktz;
168
169 if (tv) {
170 if (get_ts32(&kts, tv))
171 return -EFAULT;
172 }
173 if (tz) {
174 if (copy_from_user(&ktz, tz, sizeof(ktz)))
175 return -EFAULT;
176 }
177
178 return do_sys_settimeofday(tv ? &kts : NULL, tz ? &ktz : NULL);
179}
180
181#ifdef CONFIG_SYSVIPC
Stephen Rothwellb09a4912005-10-18 14:51:57 +1000182long compat_sys_ipc(u32 call, u32 first, u32 second, u32 third, compat_uptr_t ptr,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700183 u32 fifth)
184{
185 int version;
186
187 version = call >> 16; /* hack for backward compatibility */
188 call &= 0xffff;
189
190 switch (call) {
191
192 case SEMTIMEDOP:
193 if (fifth)
194 /* sign extend semid */
195 return compat_sys_semtimedop((int)first,
196 compat_ptr(ptr), second,
197 compat_ptr(fifth));
198 /* else fall through for normal semop() */
199 case SEMOP:
200 /* struct sembuf is the same on 32 and 64bit :)) */
201 /* sign extend semid */
202 return sys_semtimedop((int)first, compat_ptr(ptr), second,
203 NULL);
204 case SEMGET:
205 /* sign extend key, nsems */
206 return sys_semget((int)first, (int)second, third);
207 case SEMCTL:
208 /* sign extend semid, semnum */
209 return compat_sys_semctl((int)first, (int)second, third,
210 compat_ptr(ptr));
211
212 case MSGSND:
213 /* sign extend msqid */
214 return compat_sys_msgsnd((int)first, (int)second, third,
215 compat_ptr(ptr));
216 case MSGRCV:
217 /* sign extend msqid, msgtyp */
218 return compat_sys_msgrcv((int)first, second, (int)fifth,
219 third, version, compat_ptr(ptr));
220 case MSGGET:
221 /* sign extend key */
222 return sys_msgget((int)first, second);
223 case MSGCTL:
224 /* sign extend msqid */
225 return compat_sys_msgctl((int)first, second, compat_ptr(ptr));
226
227 case SHMAT:
228 /* sign extend shmid */
229 return compat_sys_shmat((int)first, second, third, version,
230 compat_ptr(ptr));
231 case SHMDT:
232 return sys_shmdt(compat_ptr(ptr));
233 case SHMGET:
234 /* sign extend key_t */
235 return sys_shmget((int)first, second, third);
236 case SHMCTL:
237 /* sign extend shmid */
238 return compat_sys_shmctl((int)first, second, compat_ptr(ptr));
239
240 default:
241 return -ENOSYS;
242 }
243
244 return -ENOSYS;
245}
246#endif
247
248/* Note: it is necessary to treat out_fd and in_fd as unsigned ints,
249 * with the corresponding cast to a signed int to insure that the
250 * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
251 * and the register representation of a signed int (msr in 64-bit mode) is performed.
252 */
Stephen Rothwellb09a4912005-10-18 14:51:57 +1000253asmlinkage long compat_sys_sendfile(u32 out_fd, u32 in_fd, compat_off_t __user * offset, u32 count)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700254{
255 mm_segment_t old_fs = get_fs();
256 int ret;
257 off_t of;
258 off_t __user *up;
259
260 if (offset && get_user(of, offset))
261 return -EFAULT;
262
263 /* The __user pointer cast is valid because of the set_fs() */
264 set_fs(KERNEL_DS);
265 up = offset ? (off_t __user *) &of : NULL;
266 ret = sys_sendfile((int)out_fd, (int)in_fd, up, count);
267 set_fs(old_fs);
268
269 if (offset && put_user(of, offset))
270 return -EFAULT;
271
272 return ret;
273}
274
Stephen Rothwellb09a4912005-10-18 14:51:57 +1000275asmlinkage int compat_sys_sendfile64(int out_fd, int in_fd, compat_loff_t __user *offset, s32 count)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700276{
277 mm_segment_t old_fs = get_fs();
278 int ret;
279 loff_t lof;
280 loff_t __user *up;
281
282 if (offset && get_user(lof, offset))
283 return -EFAULT;
284
285 /* The __user pointer cast is valid because of the set_fs() */
286 set_fs(KERNEL_DS);
287 up = offset ? (loff_t __user *) &lof : NULL;
288 ret = sys_sendfile64(out_fd, in_fd, up, count);
289 set_fs(old_fs);
290
291 if (offset && put_user(lof, offset))
292 return -EFAULT;
293
294 return ret;
295}
296
Stephen Rothwellb09a4912005-10-18 14:51:57 +1000297long compat_sys_execve(unsigned long a0, unsigned long a1, unsigned long a2,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700298 unsigned long a3, unsigned long a4, unsigned long a5,
299 struct pt_regs *regs)
300{
301 int error;
302 char * filename;
303
304 filename = getname((char __user *) a0);
305 error = PTR_ERR(filename);
306 if (IS_ERR(filename))
307 goto out;
308 flush_fp_to_thread(current);
309 flush_altivec_to_thread(current);
310
311 error = compat_do_execve(filename, compat_ptr(a1), compat_ptr(a2), regs);
312
Linus Torvalds1da177e2005-04-16 15:20:36 -0700313 putname(filename);
314
315out:
316 return error;
317}
318
Linus Torvalds1da177e2005-04-16 15:20:36 -0700319/* Note: it is necessary to treat option as an unsigned int,
320 * with the corresponding cast to a signed int to insure that the
321 * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
322 * and the register representation of a signed int (msr in 64-bit mode) is performed.
323 */
Stephen Rothwellb09a4912005-10-18 14:51:57 +1000324asmlinkage long compat_sys_prctl(u32 option, u32 arg2, u32 arg3, u32 arg4, u32 arg5)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700325{
326 return sys_prctl((int)option,
327 (unsigned long) arg2,
328 (unsigned long) arg3,
329 (unsigned long) arg4,
330 (unsigned long) arg5);
331}
332
333/* Note: it is necessary to treat pid as an unsigned int,
334 * with the corresponding cast to a signed int to insure that the
335 * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
336 * and the register representation of a signed int (msr in 64-bit mode) is performed.
337 */
Stephen Rothwellb09a4912005-10-18 14:51:57 +1000338asmlinkage long compat_sys_sched_rr_get_interval(u32 pid, struct compat_timespec __user *interval)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700339{
340 struct timespec t;
341 int ret;
342 mm_segment_t old_fs = get_fs ();
343
344 /* The __user pointer cast is valid because of the set_fs() */
345 set_fs (KERNEL_DS);
346 ret = sys_sched_rr_get_interval((int)pid, (struct timespec __user *) &t);
347 set_fs (old_fs);
348 if (put_compat_timespec(&t, interval))
349 return -EFAULT;
350 return ret;
351}
352
Linus Torvalds1da177e2005-04-16 15:20:36 -0700353/* Note: it is necessary to treat mode as an unsigned int,
354 * with the corresponding cast to a signed int to insure that the
355 * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
356 * and the register representation of a signed int (msr in 64-bit mode) is performed.
357 */
Stephen Rothwellb09a4912005-10-18 14:51:57 +1000358asmlinkage long compat_sys_access(const char __user * filename, u32 mode)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700359{
360 return sys_access(filename, (int)mode);
361}
362
363
364/* Note: it is necessary to treat mode as an unsigned int,
365 * with the corresponding cast to a signed int to insure that the
366 * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
367 * and the register representation of a signed int (msr in 64-bit mode) is performed.
368 */
Stephen Rothwellb09a4912005-10-18 14:51:57 +1000369asmlinkage long compat_sys_creat(const char __user * pathname, u32 mode)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700370{
371 return sys_creat(pathname, (int)mode);
372}
373
374
375/* Note: it is necessary to treat pid and options as unsigned ints,
376 * with the corresponding cast to a signed int to insure that the
377 * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
378 * and the register representation of a signed int (msr in 64-bit mode) is performed.
379 */
Stephen Rothwellb09a4912005-10-18 14:51:57 +1000380asmlinkage long compat_sys_waitpid(u32 pid, unsigned int __user * stat_addr, u32 options)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700381{
382 return sys_waitpid((int)pid, stat_addr, (int)options);
383}
384
385
386/* Note: it is necessary to treat gidsetsize as an unsigned int,
387 * with the corresponding cast to a signed int to insure that the
388 * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
389 * and the register representation of a signed int (msr in 64-bit mode) is performed.
390 */
Stephen Rothwellb09a4912005-10-18 14:51:57 +1000391asmlinkage long compat_sys_getgroups(u32 gidsetsize, gid_t __user *grouplist)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700392{
393 return sys_getgroups((int)gidsetsize, grouplist);
394}
395
396
397/* Note: it is necessary to treat pid as an unsigned int,
398 * with the corresponding cast to a signed int to insure that the
399 * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
400 * and the register representation of a signed int (msr in 64-bit mode) is performed.
401 */
Stephen Rothwellb09a4912005-10-18 14:51:57 +1000402asmlinkage long compat_sys_getpgid(u32 pid)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700403{
404 return sys_getpgid((int)pid);
405}
406
407
Linus Torvalds1da177e2005-04-16 15:20:36 -0700408
409/* Note: it is necessary to treat pid as an unsigned int,
410 * with the corresponding cast to a signed int to insure that the
411 * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
412 * and the register representation of a signed int (msr in 64-bit mode) is performed.
413 */
Stephen Rothwellb09a4912005-10-18 14:51:57 +1000414asmlinkage long compat_sys_getsid(u32 pid)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700415{
416 return sys_getsid((int)pid);
417}
418
419
420/* Note: it is necessary to treat pid and sig as unsigned ints,
421 * with the corresponding cast to a signed int to insure that the
422 * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
423 * and the register representation of a signed int (msr in 64-bit mode) is performed.
424 */
Stephen Rothwellb09a4912005-10-18 14:51:57 +1000425asmlinkage long compat_sys_kill(u32 pid, u32 sig)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700426{
427 return sys_kill((int)pid, (int)sig);
428}
429
430
431/* Note: it is necessary to treat mode as an unsigned int,
432 * with the corresponding cast to a signed int to insure that the
433 * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
434 * and the register representation of a signed int (msr in 64-bit mode) is performed.
435 */
Stephen Rothwellb09a4912005-10-18 14:51:57 +1000436asmlinkage long compat_sys_mkdir(const char __user * pathname, u32 mode)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700437{
438 return sys_mkdir(pathname, (int)mode);
439}
440
Stephen Rothwellb09a4912005-10-18 14:51:57 +1000441long compat_sys_nice(u32 increment)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700442{
443 /* sign extend increment */
444 return sys_nice((int)increment);
445}
446
447off_t ppc32_lseek(unsigned int fd, u32 offset, unsigned int origin)
448{
449 /* sign extend n */
450 return sys_lseek(fd, (int)offset, origin);
451}
452
Linus Torvalds1da177e2005-04-16 15:20:36 -0700453/* Note: it is necessary to treat bufsiz as an unsigned int,
454 * with the corresponding cast to a signed int to insure that the
455 * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
456 * and the register representation of a signed int (msr in 64-bit mode) is performed.
457 */
Stephen Rothwellb09a4912005-10-18 14:51:57 +1000458asmlinkage long compat_sys_readlink(const char __user * path, char __user * buf, u32 bufsiz)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700459{
460 return sys_readlink(path, buf, (int)bufsiz);
461}
462
463/* Note: it is necessary to treat option as an unsigned int,
464 * with the corresponding cast to a signed int to insure that the
465 * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
466 * and the register representation of a signed int (msr in 64-bit mode) is performed.
467 */
Stephen Rothwellb09a4912005-10-18 14:51:57 +1000468asmlinkage long compat_sys_sched_get_priority_max(u32 policy)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700469{
470 return sys_sched_get_priority_max((int)policy);
471}
472
473
474/* Note: it is necessary to treat policy as an unsigned int,
475 * with the corresponding cast to a signed int to insure that the
476 * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
477 * and the register representation of a signed int (msr in 64-bit mode) is performed.
478 */
Stephen Rothwellb09a4912005-10-18 14:51:57 +1000479asmlinkage long compat_sys_sched_get_priority_min(u32 policy)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700480{
481 return sys_sched_get_priority_min((int)policy);
482}
483
484
485/* Note: it is necessary to treat pid as an unsigned int,
486 * with the corresponding cast to a signed int to insure that the
487 * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
488 * and the register representation of a signed int (msr in 64-bit mode) is performed.
489 */
Stephen Rothwellb09a4912005-10-18 14:51:57 +1000490asmlinkage long compat_sys_sched_getparam(u32 pid, struct sched_param __user *param)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700491{
492 return sys_sched_getparam((int)pid, param);
493}
494
495
496/* Note: it is necessary to treat pid as an unsigned int,
497 * with the corresponding cast to a signed int to insure that the
498 * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
499 * and the register representation of a signed int (msr in 64-bit mode) is performed.
500 */
Stephen Rothwellb09a4912005-10-18 14:51:57 +1000501asmlinkage long compat_sys_sched_getscheduler(u32 pid)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700502{
503 return sys_sched_getscheduler((int)pid);
504}
505
506
507/* Note: it is necessary to treat pid as an unsigned int,
508 * with the corresponding cast to a signed int to insure that the
509 * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
510 * and the register representation of a signed int (msr in 64-bit mode) is performed.
511 */
Stephen Rothwellb09a4912005-10-18 14:51:57 +1000512asmlinkage long compat_sys_sched_setparam(u32 pid, struct sched_param __user *param)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700513{
514 return sys_sched_setparam((int)pid, param);
515}
516
517
518/* Note: it is necessary to treat pid and policy as unsigned ints,
519 * with the corresponding cast to a signed int to insure that the
520 * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
521 * and the register representation of a signed int (msr in 64-bit mode) is performed.
522 */
Stephen Rothwellb09a4912005-10-18 14:51:57 +1000523asmlinkage long compat_sys_sched_setscheduler(u32 pid, u32 policy, struct sched_param __user *param)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700524{
525 return sys_sched_setscheduler((int)pid, (int)policy, param);
526}
527
528
529/* Note: it is necessary to treat len as an unsigned int,
530 * with the corresponding cast to a signed int to insure that the
531 * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
532 * and the register representation of a signed int (msr in 64-bit mode) is performed.
533 */
Stephen Rothwellb09a4912005-10-18 14:51:57 +1000534asmlinkage long compat_sys_setdomainname(char __user *name, u32 len)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700535{
536 return sys_setdomainname(name, (int)len);
537}
538
539
540/* Note: it is necessary to treat gidsetsize as an unsigned int,
541 * with the corresponding cast to a signed int to insure that the
542 * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
543 * and the register representation of a signed int (msr in 64-bit mode) is performed.
544 */
Stephen Rothwellb09a4912005-10-18 14:51:57 +1000545asmlinkage long compat_sys_setgroups(u32 gidsetsize, gid_t __user *grouplist)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700546{
547 return sys_setgroups((int)gidsetsize, grouplist);
548}
549
550
Stephen Rothwellb09a4912005-10-18 14:51:57 +1000551asmlinkage long compat_sys_sethostname(char __user *name, u32 len)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700552{
553 /* sign extend len */
554 return sys_sethostname(name, (int)len);
555}
556
557
558/* Note: it is necessary to treat pid and pgid as unsigned ints,
559 * with the corresponding cast to a signed int to insure that the
560 * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
561 * and the register representation of a signed int (msr in 64-bit mode) is performed.
562 */
Stephen Rothwellb09a4912005-10-18 14:51:57 +1000563asmlinkage long compat_sys_setpgid(u32 pid, u32 pgid)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700564{
565 return sys_setpgid((int)pid, (int)pgid);
566}
567
Stephen Rothwellb09a4912005-10-18 14:51:57 +1000568long compat_sys_getpriority(u32 which, u32 who)
Anton Blanchard79c2cc72005-07-07 17:56:15 -0700569{
570 /* sign extend which and who */
571 return sys_getpriority((int)which, (int)who);
572}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700573
Stephen Rothwellb09a4912005-10-18 14:51:57 +1000574long compat_sys_setpriority(u32 which, u32 who, u32 niceval)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700575{
576 /* sign extend which, who and niceval */
577 return sys_setpriority((int)which, (int)who, (int)niceval);
578}
579
Stephen Rothwellb09a4912005-10-18 14:51:57 +1000580long compat_sys_ioprio_get(u32 which, u32 who)
Anton Blanchard79c2cc72005-07-07 17:56:15 -0700581{
582 /* sign extend which and who */
583 return sys_ioprio_get((int)which, (int)who);
584}
585
Stephen Rothwellb09a4912005-10-18 14:51:57 +1000586long compat_sys_ioprio_set(u32 which, u32 who, u32 ioprio)
Anton Blanchard79c2cc72005-07-07 17:56:15 -0700587{
588 /* sign extend which, who and ioprio */
589 return sys_ioprio_set((int)which, (int)who, (int)ioprio);
590}
591
Linus Torvalds1da177e2005-04-16 15:20:36 -0700592/* Note: it is necessary to treat newmask as an unsigned int,
593 * with the corresponding cast to a signed int to insure that the
594 * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
595 * and the register representation of a signed int (msr in 64-bit mode) is performed.
596 */
Stephen Rothwellb09a4912005-10-18 14:51:57 +1000597asmlinkage long compat_sys_ssetmask(u32 newmask)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700598{
599 return sys_ssetmask((int) newmask);
600}
601
Stephen Rothwellb09a4912005-10-18 14:51:57 +1000602asmlinkage long compat_sys_syslog(u32 type, char __user * buf, u32 len)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700603{
604 /* sign extend len */
605 return sys_syslog(type, buf, (int)len);
606}
607
608
609/* Note: it is necessary to treat mask as an unsigned int,
610 * with the corresponding cast to a signed int to insure that the
611 * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
612 * and the register representation of a signed int (msr in 64-bit mode) is performed.
613 */
Stephen Rothwellb09a4912005-10-18 14:51:57 +1000614asmlinkage long compat_sys_umask(u32 mask)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700615{
616 return sys_umask((int)mask);
617}
618
Eric W. Biedermanb89a8172006-09-27 01:51:04 -0700619#ifdef CONFIG_SYSCTL_SYSCALL
Linus Torvalds1da177e2005-04-16 15:20:36 -0700620struct __sysctl_args32 {
621 u32 name;
622 int nlen;
623 u32 oldval;
624 u32 oldlenp;
625 u32 newval;
626 u32 newlen;
627 u32 __unused[4];
628};
629
Stephen Rothwellb09a4912005-10-18 14:51:57 +1000630asmlinkage long compat_sys_sysctl(struct __sysctl_args32 __user *args)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700631{
632 struct __sysctl_args32 tmp;
633 int error;
634 size_t oldlen;
635 size_t __user *oldlenp = NULL;
636 unsigned long addr = (((unsigned long)&args->__unused[0]) + 7) & ~7;
637
638 if (copy_from_user(&tmp, args, sizeof(tmp)))
639 return -EFAULT;
640
641 if (tmp.oldval && tmp.oldlenp) {
642 /* Duh, this is ugly and might not work if sysctl_args
643 is in read-only memory, but do_sysctl does indirectly
644 a lot of uaccess in both directions and we'd have to
645 basically copy the whole sysctl.c here, and
646 glibc's __sysctl uses rw memory for the structure
647 anyway. */
648 oldlenp = (size_t __user *)addr;
649 if (get_user(oldlen, (compat_size_t __user *)compat_ptr(tmp.oldlenp)) ||
650 put_user(oldlen, oldlenp))
651 return -EFAULT;
652 }
653
654 lock_kernel();
655 error = do_sysctl(compat_ptr(tmp.name), tmp.nlen,
656 compat_ptr(tmp.oldval), oldlenp,
657 compat_ptr(tmp.newval), tmp.newlen);
658 unlock_kernel();
659 if (oldlenp) {
660 if (!error) {
661 if (get_user(oldlen, oldlenp) ||
662 put_user(oldlen, (compat_size_t __user *)compat_ptr(tmp.oldlenp)))
663 error = -EFAULT;
664 }
665 copy_to_user(args->__unused, tmp.__unused, sizeof(tmp.__unused));
666 }
667 return error;
668}
669#endif
670
Stephen Rothwellb09a4912005-10-18 14:51:57 +1000671unsigned long compat_sys_mmap2(unsigned long addr, size_t len,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700672 unsigned long prot, unsigned long flags,
673 unsigned long fd, unsigned long pgoff)
674{
675 /* This should remain 12 even if PAGE_SIZE changes */
676 return sys_mmap(addr, len, prot, flags, fd, pgoff << 12);
677}
678
Stephen Rothwellb09a4912005-10-18 14:51:57 +1000679long compat_sys_tgkill(u32 tgid, u32 pid, int sig)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700680{
681 /* sign extend tgid, pid */
682 return sys_tgkill((int)tgid, (int)pid, sig);
683}
684
685/*
686 * long long munging:
687 * The 32 bit ABI passes long longs in an odd even register pair.
688 */
689
Stephen Rothwellb09a4912005-10-18 14:51:57 +1000690compat_ssize_t compat_sys_pread64(unsigned int fd, char __user *ubuf, compat_size_t count,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700691 u32 reg6, u32 poshi, u32 poslo)
692{
693 return sys_pread64(fd, ubuf, count, ((loff_t)poshi << 32) | poslo);
694}
695
Stephen Rothwellb09a4912005-10-18 14:51:57 +1000696compat_ssize_t compat_sys_pwrite64(unsigned int fd, char __user *ubuf, compat_size_t count,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700697 u32 reg6, u32 poshi, u32 poslo)
698{
699 return sys_pwrite64(fd, ubuf, count, ((loff_t)poshi << 32) | poslo);
700}
701
Stephen Rothwellb09a4912005-10-18 14:51:57 +1000702compat_ssize_t compat_sys_readahead(int fd, u32 r4, u32 offhi, u32 offlo, u32 count)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700703{
704 return sys_readahead(fd, ((loff_t)offhi << 32) | offlo, count);
705}
706
Stephen Rothwellb09a4912005-10-18 14:51:57 +1000707asmlinkage int compat_sys_truncate64(const char __user * path, u32 reg4,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700708 unsigned long high, unsigned long low)
709{
710 return sys_truncate(path, (high << 32) | low);
711}
712
Amit Arora97ac7352007-07-17 21:42:44 -0400713asmlinkage long compat_sys_fallocate(int fd, int mode, u32 offhi, u32 offlo,
714 u32 lenhi, u32 lenlo)
715{
716 return sys_fallocate(fd, mode, ((loff_t)offhi << 32) | offlo,
717 ((loff_t)lenhi << 32) | lenlo);
718}
719
Stephen Rothwellb09a4912005-10-18 14:51:57 +1000720asmlinkage int compat_sys_ftruncate64(unsigned int fd, u32 reg4, unsigned long high,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700721 unsigned long low)
722{
723 return sys_ftruncate(fd, (high << 32) | low);
724}
725
726long ppc32_lookup_dcookie(u32 cookie_high, u32 cookie_low, char __user *buf,
727 size_t len)
728{
729 return sys_lookup_dcookie((u64)cookie_high << 32 | cookie_low,
730 buf, len);
731}
732
733long ppc32_fadvise64(int fd, u32 unused, u32 offset_high, u32 offset_low,
734 size_t len, int advice)
735{
736 return sys_fadvise64(fd, (u64)offset_high << 32 | offset_low, len,
737 advice);
738}
739
Stephen Rothwellb09a4912005-10-18 14:51:57 +1000740asmlinkage long compat_sys_add_key(const char __user *_type,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700741 const char __user *_description,
742 const void __user *_payload,
743 u32 plen,
744 u32 ringid)
745{
746 return sys_add_key(_type, _description, _payload, plen, ringid);
747}
748
Stephen Rothwellb09a4912005-10-18 14:51:57 +1000749asmlinkage long compat_sys_request_key(const char __user *_type,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700750 const char __user *_description,
751 const char __user *_callout_info,
752 u32 destringid)
753{
754 return sys_request_key(_type, _description, _callout_info, destringid);
755}
756
David Woodhouseedd5cd42007-06-27 14:10:09 -0700757asmlinkage long compat_sys_sync_file_range2(int fd, unsigned int flags,
758 unsigned offset_hi, unsigned offset_lo,
759 unsigned nbytes_hi, unsigned nbytes_lo)
760{
761 loff_t offset = ((loff_t)offset_hi << 32) | offset_lo;
762 loff_t nbytes = ((loff_t)nbytes_hi << 32) | nbytes_lo;
763
764 return sys_sync_file_range(fd, offset, nbytes, flags);
765}