blob: 03a2a2f30d66dfcf555881fd05bed1228de6dbd7 [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>
44
Linus Torvalds1da177e2005-04-16 15:20:36 -070045#include <asm/ptrace.h>
46#include <asm/types.h>
47#include <asm/ipc.h>
48#include <asm/uaccess.h>
49#include <asm/unistd.h>
50#include <asm/semaphore.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070051#include <asm/time.h>
52#include <asm/mmu_context.h>
Stephen Rothwelld3878992005-09-28 02:50:25 +100053#include <asm/ppc-pci.h>
Arnd Bergmann369cf4b2006-11-27 19:18:59 +010054#include <asm/syscalls.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070055
56/* readdir & getdents */
57#define NAME_OFFSET(de) ((int) ((de)->d_name - (char __user *) (de)))
58#define ROUND_UP(x) (((x)+sizeof(u32)-1) & ~(sizeof(u32)-1))
59
60struct old_linux_dirent32 {
61 u32 d_ino;
62 u32 d_offset;
63 unsigned short d_namlen;
64 char d_name[1];
65};
66
67struct readdir_callback32 {
68 struct old_linux_dirent32 __user * dirent;
69 int count;
70};
71
72static int fillonedir(void * __buf, const char * name, int namlen,
David Howellsafefdbb2006-10-03 01:13:46 -070073 off_t offset, u64 ino, unsigned int d_type)
Linus Torvalds1da177e2005-04-16 15:20:36 -070074{
75 struct readdir_callback32 * buf = (struct readdir_callback32 *) __buf;
76 struct old_linux_dirent32 __user * dirent;
David Howellsafefdbb2006-10-03 01:13:46 -070077 ino_t d_ino;
Linus Torvalds1da177e2005-04-16 15:20:36 -070078
79 if (buf->count)
80 return -EINVAL;
David Howellsafefdbb2006-10-03 01:13:46 -070081 d_ino = ino;
82 if (sizeof(d_ino) < sizeof(ino) && d_ino != ino)
83 return -EOVERFLOW;
Linus Torvalds1da177e2005-04-16 15:20:36 -070084 buf->count++;
85 dirent = buf->dirent;
David Howellsafefdbb2006-10-03 01:13:46 -070086 put_user(d_ino, &dirent->d_ino);
Linus Torvalds1da177e2005-04-16 15:20:36 -070087 put_user(offset, &dirent->d_offset);
88 put_user(namlen, &dirent->d_namlen);
89 copy_to_user(dirent->d_name, name, namlen);
90 put_user(0, dirent->d_name + namlen);
91 return 0;
92}
93
94asmlinkage int old32_readdir(unsigned int fd, struct old_linux_dirent32 __user *dirent, unsigned int count)
95{
96 int error = -EBADF;
97 struct file * file;
98 struct readdir_callback32 buf;
99
100 file = fget(fd);
101 if (!file)
102 goto out;
103
104 buf.count = 0;
105 buf.dirent = dirent;
106
107 error = vfs_readdir(file, (filldir_t)fillonedir, &buf);
108 if (error < 0)
109 goto out_putf;
110 error = buf.count;
111
112out_putf:
113 fput(file);
114out:
115 return error;
116}
117
Linus Torvalds1da177e2005-04-16 15:20:36 -0700118asmlinkage long ppc32_select(u32 n, compat_ulong_t __user *inp,
119 compat_ulong_t __user *outp, compat_ulong_t __user *exp,
120 compat_uptr_t tvp_x)
121{
122 /* sign extend n */
123 return compat_sys_select((int)n, inp, outp, exp, compat_ptr(tvp_x));
124}
125
126int cp_compat_stat(struct kstat *stat, struct compat_stat __user *statbuf)
127{
David Howellsafefdbb2006-10-03 01:13:46 -0700128 compat_ino_t ino;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700129 long err;
130
131 if (stat->size > MAX_NON_LFS || !new_valid_dev(stat->dev) ||
132 !new_valid_dev(stat->rdev))
133 return -EOVERFLOW;
134
David Howellsafefdbb2006-10-03 01:13:46 -0700135 ino = stat->ino;
136 if (sizeof(ino) < sizeof(stat->ino) && ino != stat->ino)
137 return -EOVERFLOW;
138
Linus Torvalds1da177e2005-04-16 15:20:36 -0700139 err = access_ok(VERIFY_WRITE, statbuf, sizeof(*statbuf)) ? 0 : -EFAULT;
140 err |= __put_user(new_encode_dev(stat->dev), &statbuf->st_dev);
David Howellsafefdbb2006-10-03 01:13:46 -0700141 err |= __put_user(ino, &statbuf->st_ino);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700142 err |= __put_user(stat->mode, &statbuf->st_mode);
143 err |= __put_user(stat->nlink, &statbuf->st_nlink);
144 err |= __put_user(stat->uid, &statbuf->st_uid);
145 err |= __put_user(stat->gid, &statbuf->st_gid);
146 err |= __put_user(new_encode_dev(stat->rdev), &statbuf->st_rdev);
147 err |= __put_user(stat->size, &statbuf->st_size);
148 err |= __put_user(stat->atime.tv_sec, &statbuf->st_atime);
149 err |= __put_user(stat->atime.tv_nsec, &statbuf->st_atime_nsec);
150 err |= __put_user(stat->mtime.tv_sec, &statbuf->st_mtime);
151 err |= __put_user(stat->mtime.tv_nsec, &statbuf->st_mtime_nsec);
152 err |= __put_user(stat->ctime.tv_sec, &statbuf->st_ctime);
153 err |= __put_user(stat->ctime.tv_nsec, &statbuf->st_ctime_nsec);
154 err |= __put_user(stat->blksize, &statbuf->st_blksize);
155 err |= __put_user(stat->blocks, &statbuf->st_blocks);
156 err |= __put_user(0, &statbuf->__unused4[0]);
157 err |= __put_user(0, &statbuf->__unused4[1]);
158
159 return err;
160}
161
162/* Note: it is necessary to treat option as an unsigned int,
163 * with the corresponding cast to a signed int to insure that the
164 * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
165 * and the register representation of a signed int (msr in 64-bit mode) is performed.
166 */
Stephen Rothwellb09a4912005-10-18 14:51:57 +1000167asmlinkage long compat_sys_sysfs(u32 option, u32 arg1, u32 arg2)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700168{
169 return sys_sysfs((int)option, arg1, arg2);
170}
171
Stephen Rothwellb09a4912005-10-18 14:51:57 +1000172asmlinkage long compat_sys_pause(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700173{
174 current->state = TASK_INTERRUPTIBLE;
175 schedule();
176
177 return -ERESTARTNOHAND;
178}
179
Linus Torvalds1da177e2005-04-16 15:20:36 -0700180static inline long get_ts32(struct timespec *o, struct compat_timeval __user *i)
181{
182 long usec;
183
184 if (!access_ok(VERIFY_READ, i, sizeof(*i)))
185 return -EFAULT;
186 if (__get_user(o->tv_sec, &i->tv_sec))
187 return -EFAULT;
188 if (__get_user(usec, &i->tv_usec))
189 return -EFAULT;
190 o->tv_nsec = usec * 1000;
191 return 0;
192}
193
194static inline long put_tv32(struct compat_timeval __user *o, struct timeval *i)
195{
196 return (!access_ok(VERIFY_WRITE, o, sizeof(*o)) ||
197 (__put_user(i->tv_sec, &o->tv_sec) |
198 __put_user(i->tv_usec, &o->tv_usec)));
199}
200
201struct sysinfo32 {
202 s32 uptime;
203 u32 loads[3];
204 u32 totalram;
205 u32 freeram;
206 u32 sharedram;
207 u32 bufferram;
208 u32 totalswap;
209 u32 freeswap;
210 unsigned short procs;
211 unsigned short pad;
212 u32 totalhigh;
213 u32 freehigh;
214 u32 mem_unit;
215 char _f[20-2*sizeof(int)-sizeof(int)];
216};
217
Stephen Rothwellb09a4912005-10-18 14:51:57 +1000218asmlinkage long compat_sys_sysinfo(struct sysinfo32 __user *info)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700219{
220 struct sysinfo s;
221 int ret, err;
222 int bitcount=0;
223 mm_segment_t old_fs = get_fs ();
224
225 /* The __user cast is valid due to set_fs() */
226 set_fs (KERNEL_DS);
227 ret = sys_sysinfo((struct sysinfo __user *)&s);
228 set_fs (old_fs);
229
230 /* Check to see if any memory value is too large for 32-bit and
231 * scale down if needed.
232 */
233 if ((s.totalram >> 32) || (s.totalswap >> 32)) {
234 while (s.mem_unit < PAGE_SIZE) {
235 s.mem_unit <<= 1;
236 bitcount++;
237 }
238 s.totalram >>=bitcount;
239 s.freeram >>= bitcount;
240 s.sharedram >>= bitcount;
241 s.bufferram >>= bitcount;
242 s.totalswap >>= bitcount;
243 s.freeswap >>= bitcount;
244 s.totalhigh >>= bitcount;
245 s.freehigh >>= bitcount;
246 }
247
248 err = put_user (s.uptime, &info->uptime);
249 err |= __put_user (s.loads[0], &info->loads[0]);
250 err |= __put_user (s.loads[1], &info->loads[1]);
251 err |= __put_user (s.loads[2], &info->loads[2]);
252 err |= __put_user (s.totalram, &info->totalram);
253 err |= __put_user (s.freeram, &info->freeram);
254 err |= __put_user (s.sharedram, &info->sharedram);
255 err |= __put_user (s.bufferram, &info->bufferram);
256 err |= __put_user (s.totalswap, &info->totalswap);
257 err |= __put_user (s.freeswap, &info->freeswap);
258 err |= __put_user (s.procs, &info->procs);
259 err |= __put_user (s.totalhigh, &info->totalhigh);
260 err |= __put_user (s.freehigh, &info->freehigh);
261 err |= __put_user (s.mem_unit, &info->mem_unit);
262 if (err)
263 return -EFAULT;
264
265 return ret;
266}
267
268
269
270
271/* Translations due to time_t size differences. Which affects all
272 sorts of things, like timeval and itimerval. */
273extern struct timezone sys_tz;
274
Stephen Rothwellb09a4912005-10-18 14:51:57 +1000275asmlinkage long compat_sys_gettimeofday(struct compat_timeval __user *tv, struct timezone __user *tz)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700276{
277 if (tv) {
278 struct timeval ktv;
279 do_gettimeofday(&ktv);
280 if (put_tv32(tv, &ktv))
281 return -EFAULT;
282 }
283 if (tz) {
284 if (copy_to_user(tz, &sys_tz, sizeof(sys_tz)))
285 return -EFAULT;
286 }
287
288 return 0;
289}
290
291
292
Stephen Rothwellb09a4912005-10-18 14:51:57 +1000293asmlinkage long compat_sys_settimeofday(struct compat_timeval __user *tv, struct timezone __user *tz)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700294{
295 struct timespec kts;
296 struct timezone ktz;
297
298 if (tv) {
299 if (get_ts32(&kts, tv))
300 return -EFAULT;
301 }
302 if (tz) {
303 if (copy_from_user(&ktz, tz, sizeof(ktz)))
304 return -EFAULT;
305 }
306
307 return do_sys_settimeofday(tv ? &kts : NULL, tz ? &ktz : NULL);
308}
309
310#ifdef CONFIG_SYSVIPC
Stephen Rothwellb09a4912005-10-18 14:51:57 +1000311long compat_sys_ipc(u32 call, u32 first, u32 second, u32 third, compat_uptr_t ptr,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700312 u32 fifth)
313{
314 int version;
315
316 version = call >> 16; /* hack for backward compatibility */
317 call &= 0xffff;
318
319 switch (call) {
320
321 case SEMTIMEDOP:
322 if (fifth)
323 /* sign extend semid */
324 return compat_sys_semtimedop((int)first,
325 compat_ptr(ptr), second,
326 compat_ptr(fifth));
327 /* else fall through for normal semop() */
328 case SEMOP:
329 /* struct sembuf is the same on 32 and 64bit :)) */
330 /* sign extend semid */
331 return sys_semtimedop((int)first, compat_ptr(ptr), second,
332 NULL);
333 case SEMGET:
334 /* sign extend key, nsems */
335 return sys_semget((int)first, (int)second, third);
336 case SEMCTL:
337 /* sign extend semid, semnum */
338 return compat_sys_semctl((int)first, (int)second, third,
339 compat_ptr(ptr));
340
341 case MSGSND:
342 /* sign extend msqid */
343 return compat_sys_msgsnd((int)first, (int)second, third,
344 compat_ptr(ptr));
345 case MSGRCV:
346 /* sign extend msqid, msgtyp */
347 return compat_sys_msgrcv((int)first, second, (int)fifth,
348 third, version, compat_ptr(ptr));
349 case MSGGET:
350 /* sign extend key */
351 return sys_msgget((int)first, second);
352 case MSGCTL:
353 /* sign extend msqid */
354 return compat_sys_msgctl((int)first, second, compat_ptr(ptr));
355
356 case SHMAT:
357 /* sign extend shmid */
358 return compat_sys_shmat((int)first, second, third, version,
359 compat_ptr(ptr));
360 case SHMDT:
361 return sys_shmdt(compat_ptr(ptr));
362 case SHMGET:
363 /* sign extend key_t */
364 return sys_shmget((int)first, second, third);
365 case SHMCTL:
366 /* sign extend shmid */
367 return compat_sys_shmctl((int)first, second, compat_ptr(ptr));
368
369 default:
370 return -ENOSYS;
371 }
372
373 return -ENOSYS;
374}
375#endif
376
377/* Note: it is necessary to treat out_fd and in_fd as unsigned ints,
378 * with the corresponding cast to a signed int to insure that the
379 * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
380 * and the register representation of a signed int (msr in 64-bit mode) is performed.
381 */
Stephen Rothwellb09a4912005-10-18 14:51:57 +1000382asmlinkage long compat_sys_sendfile(u32 out_fd, u32 in_fd, compat_off_t __user * offset, u32 count)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700383{
384 mm_segment_t old_fs = get_fs();
385 int ret;
386 off_t of;
387 off_t __user *up;
388
389 if (offset && get_user(of, offset))
390 return -EFAULT;
391
392 /* The __user pointer cast is valid because of the set_fs() */
393 set_fs(KERNEL_DS);
394 up = offset ? (off_t __user *) &of : NULL;
395 ret = sys_sendfile((int)out_fd, (int)in_fd, up, count);
396 set_fs(old_fs);
397
398 if (offset && put_user(of, offset))
399 return -EFAULT;
400
401 return ret;
402}
403
Stephen Rothwellb09a4912005-10-18 14:51:57 +1000404asmlinkage int compat_sys_sendfile64(int out_fd, int in_fd, compat_loff_t __user *offset, s32 count)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700405{
406 mm_segment_t old_fs = get_fs();
407 int ret;
408 loff_t lof;
409 loff_t __user *up;
410
411 if (offset && get_user(lof, offset))
412 return -EFAULT;
413
414 /* The __user pointer cast is valid because of the set_fs() */
415 set_fs(KERNEL_DS);
416 up = offset ? (loff_t __user *) &lof : NULL;
417 ret = sys_sendfile64(out_fd, in_fd, up, count);
418 set_fs(old_fs);
419
420 if (offset && put_user(lof, offset))
421 return -EFAULT;
422
423 return ret;
424}
425
Stephen Rothwellb09a4912005-10-18 14:51:57 +1000426long compat_sys_execve(unsigned long a0, unsigned long a1, unsigned long a2,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700427 unsigned long a3, unsigned long a4, unsigned long a5,
428 struct pt_regs *regs)
429{
430 int error;
431 char * filename;
432
433 filename = getname((char __user *) a0);
434 error = PTR_ERR(filename);
435 if (IS_ERR(filename))
436 goto out;
437 flush_fp_to_thread(current);
438 flush_altivec_to_thread(current);
439
440 error = compat_do_execve(filename, compat_ptr(a1), compat_ptr(a2), regs);
441
442 if (error == 0) {
443 task_lock(current);
444 current->ptrace &= ~PT_DTRACE;
445 task_unlock(current);
446 }
447 putname(filename);
448
449out:
450 return error;
451}
452
Linus Torvalds1da177e2005-04-16 15:20:36 -0700453/* Note: it is necessary to treat option 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_prctl(u32 option, u32 arg2, u32 arg3, u32 arg4, u32 arg5)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700459{
460 return sys_prctl((int)option,
461 (unsigned long) arg2,
462 (unsigned long) arg3,
463 (unsigned long) arg4,
464 (unsigned long) arg5);
465}
466
467/* Note: it is necessary to treat pid as an unsigned int,
468 * with the corresponding cast to a signed int to insure that the
469 * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
470 * and the register representation of a signed int (msr in 64-bit mode) is performed.
471 */
Stephen Rothwellb09a4912005-10-18 14:51:57 +1000472asmlinkage long compat_sys_sched_rr_get_interval(u32 pid, struct compat_timespec __user *interval)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700473{
474 struct timespec t;
475 int ret;
476 mm_segment_t old_fs = get_fs ();
477
478 /* The __user pointer cast is valid because of the set_fs() */
479 set_fs (KERNEL_DS);
480 ret = sys_sched_rr_get_interval((int)pid, (struct timespec __user *) &t);
481 set_fs (old_fs);
482 if (put_compat_timespec(&t, interval))
483 return -EFAULT;
484 return ret;
485}
486
Linus Torvalds1da177e2005-04-16 15:20:36 -0700487/* Note: it is necessary to treat mode as an unsigned int,
488 * with the corresponding cast to a signed int to insure that the
489 * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
490 * and the register representation of a signed int (msr in 64-bit mode) is performed.
491 */
Stephen Rothwellb09a4912005-10-18 14:51:57 +1000492asmlinkage long compat_sys_access(const char __user * filename, u32 mode)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700493{
494 return sys_access(filename, (int)mode);
495}
496
497
498/* Note: it is necessary to treat mode as an unsigned int,
499 * with the corresponding cast to a signed int to insure that the
500 * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
501 * and the register representation of a signed int (msr in 64-bit mode) is performed.
502 */
Stephen Rothwellb09a4912005-10-18 14:51:57 +1000503asmlinkage long compat_sys_creat(const char __user * pathname, u32 mode)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700504{
505 return sys_creat(pathname, (int)mode);
506}
507
508
509/* Note: it is necessary to treat pid and options as unsigned ints,
510 * with the corresponding cast to a signed int to insure that the
511 * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
512 * and the register representation of a signed int (msr in 64-bit mode) is performed.
513 */
Stephen Rothwellb09a4912005-10-18 14:51:57 +1000514asmlinkage long compat_sys_waitpid(u32 pid, unsigned int __user * stat_addr, u32 options)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700515{
516 return sys_waitpid((int)pid, stat_addr, (int)options);
517}
518
519
520/* Note: it is necessary to treat gidsetsize as an unsigned int,
521 * with the corresponding cast to a signed int to insure that the
522 * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
523 * and the register representation of a signed int (msr in 64-bit mode) is performed.
524 */
Stephen Rothwellb09a4912005-10-18 14:51:57 +1000525asmlinkage long compat_sys_getgroups(u32 gidsetsize, gid_t __user *grouplist)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700526{
527 return sys_getgroups((int)gidsetsize, grouplist);
528}
529
530
531/* Note: it is necessary to treat pid as an unsigned int,
532 * with the corresponding cast to a signed int to insure that the
533 * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
534 * and the register representation of a signed int (msr in 64-bit mode) is performed.
535 */
Stephen Rothwellb09a4912005-10-18 14:51:57 +1000536asmlinkage long compat_sys_getpgid(u32 pid)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700537{
538 return sys_getpgid((int)pid);
539}
540
541
Linus Torvalds1da177e2005-04-16 15:20:36 -0700542
543/* Note: it is necessary to treat pid as an unsigned int,
544 * with the corresponding cast to a signed int to insure that the
545 * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
546 * and the register representation of a signed int (msr in 64-bit mode) is performed.
547 */
Stephen Rothwellb09a4912005-10-18 14:51:57 +1000548asmlinkage long compat_sys_getsid(u32 pid)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700549{
550 return sys_getsid((int)pid);
551}
552
553
554/* Note: it is necessary to treat pid and sig as unsigned ints,
555 * with the corresponding cast to a signed int to insure that the
556 * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
557 * and the register representation of a signed int (msr in 64-bit mode) is performed.
558 */
Stephen Rothwellb09a4912005-10-18 14:51:57 +1000559asmlinkage long compat_sys_kill(u32 pid, u32 sig)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700560{
561 return sys_kill((int)pid, (int)sig);
562}
563
564
565/* Note: it is necessary to treat mode as an unsigned int,
566 * with the corresponding cast to a signed int to insure that the
567 * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
568 * and the register representation of a signed int (msr in 64-bit mode) is performed.
569 */
Stephen Rothwellb09a4912005-10-18 14:51:57 +1000570asmlinkage long compat_sys_mkdir(const char __user * pathname, u32 mode)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700571{
572 return sys_mkdir(pathname, (int)mode);
573}
574
Stephen Rothwellb09a4912005-10-18 14:51:57 +1000575long compat_sys_nice(u32 increment)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700576{
577 /* sign extend increment */
578 return sys_nice((int)increment);
579}
580
581off_t ppc32_lseek(unsigned int fd, u32 offset, unsigned int origin)
582{
583 /* sign extend n */
584 return sys_lseek(fd, (int)offset, origin);
585}
586
Linus Torvalds1da177e2005-04-16 15:20:36 -0700587/* Note: it is necessary to treat bufsiz as an unsigned int,
588 * with the corresponding cast to a signed int to insure that the
589 * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
590 * and the register representation of a signed int (msr in 64-bit mode) is performed.
591 */
Stephen Rothwellb09a4912005-10-18 14:51:57 +1000592asmlinkage long compat_sys_readlink(const char __user * path, char __user * buf, u32 bufsiz)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700593{
594 return sys_readlink(path, buf, (int)bufsiz);
595}
596
597/* Note: it is necessary to treat option as an unsigned int,
598 * with the corresponding cast to a signed int to insure that the
599 * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
600 * and the register representation of a signed int (msr in 64-bit mode) is performed.
601 */
Stephen Rothwellb09a4912005-10-18 14:51:57 +1000602asmlinkage long compat_sys_sched_get_priority_max(u32 policy)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700603{
604 return sys_sched_get_priority_max((int)policy);
605}
606
607
608/* Note: it is necessary to treat policy as an unsigned int,
609 * with the corresponding cast to a signed int to insure that the
610 * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
611 * and the register representation of a signed int (msr in 64-bit mode) is performed.
612 */
Stephen Rothwellb09a4912005-10-18 14:51:57 +1000613asmlinkage long compat_sys_sched_get_priority_min(u32 policy)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700614{
615 return sys_sched_get_priority_min((int)policy);
616}
617
618
619/* Note: it is necessary to treat pid as an unsigned int,
620 * with the corresponding cast to a signed int to insure that the
621 * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
622 * and the register representation of a signed int (msr in 64-bit mode) is performed.
623 */
Stephen Rothwellb09a4912005-10-18 14:51:57 +1000624asmlinkage long compat_sys_sched_getparam(u32 pid, struct sched_param __user *param)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700625{
626 return sys_sched_getparam((int)pid, param);
627}
628
629
630/* Note: it is necessary to treat pid as an unsigned int,
631 * with the corresponding cast to a signed int to insure that the
632 * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
633 * and the register representation of a signed int (msr in 64-bit mode) is performed.
634 */
Stephen Rothwellb09a4912005-10-18 14:51:57 +1000635asmlinkage long compat_sys_sched_getscheduler(u32 pid)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700636{
637 return sys_sched_getscheduler((int)pid);
638}
639
640
641/* Note: it is necessary to treat pid as an unsigned int,
642 * with the corresponding cast to a signed int to insure that the
643 * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
644 * and the register representation of a signed int (msr in 64-bit mode) is performed.
645 */
Stephen Rothwellb09a4912005-10-18 14:51:57 +1000646asmlinkage long compat_sys_sched_setparam(u32 pid, struct sched_param __user *param)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700647{
648 return sys_sched_setparam((int)pid, param);
649}
650
651
652/* Note: it is necessary to treat pid and policy as unsigned ints,
653 * with the corresponding cast to a signed int to insure that the
654 * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
655 * and the register representation of a signed int (msr in 64-bit mode) is performed.
656 */
Stephen Rothwellb09a4912005-10-18 14:51:57 +1000657asmlinkage long compat_sys_sched_setscheduler(u32 pid, u32 policy, struct sched_param __user *param)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700658{
659 return sys_sched_setscheduler((int)pid, (int)policy, param);
660}
661
662
663/* Note: it is necessary to treat len as an unsigned int,
664 * with the corresponding cast to a signed int to insure that the
665 * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
666 * and the register representation of a signed int (msr in 64-bit mode) is performed.
667 */
Stephen Rothwellb09a4912005-10-18 14:51:57 +1000668asmlinkage long compat_sys_setdomainname(char __user *name, u32 len)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700669{
670 return sys_setdomainname(name, (int)len);
671}
672
673
674/* Note: it is necessary to treat gidsetsize as an unsigned int,
675 * with the corresponding cast to a signed int to insure that the
676 * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
677 * and the register representation of a signed int (msr in 64-bit mode) is performed.
678 */
Stephen Rothwellb09a4912005-10-18 14:51:57 +1000679asmlinkage long compat_sys_setgroups(u32 gidsetsize, gid_t __user *grouplist)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700680{
681 return sys_setgroups((int)gidsetsize, grouplist);
682}
683
684
Stephen Rothwellb09a4912005-10-18 14:51:57 +1000685asmlinkage long compat_sys_sethostname(char __user *name, u32 len)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700686{
687 /* sign extend len */
688 return sys_sethostname(name, (int)len);
689}
690
691
692/* Note: it is necessary to treat pid and pgid as unsigned ints,
693 * with the corresponding cast to a signed int to insure that the
694 * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
695 * and the register representation of a signed int (msr in 64-bit mode) is performed.
696 */
Stephen Rothwellb09a4912005-10-18 14:51:57 +1000697asmlinkage long compat_sys_setpgid(u32 pid, u32 pgid)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700698{
699 return sys_setpgid((int)pid, (int)pgid);
700}
701
Stephen Rothwellb09a4912005-10-18 14:51:57 +1000702long compat_sys_getpriority(u32 which, u32 who)
Anton Blanchard79c2cc72005-07-07 17:56:15 -0700703{
704 /* sign extend which and who */
705 return sys_getpriority((int)which, (int)who);
706}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700707
Stephen Rothwellb09a4912005-10-18 14:51:57 +1000708long compat_sys_setpriority(u32 which, u32 who, u32 niceval)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700709{
710 /* sign extend which, who and niceval */
711 return sys_setpriority((int)which, (int)who, (int)niceval);
712}
713
Stephen Rothwellb09a4912005-10-18 14:51:57 +1000714long compat_sys_ioprio_get(u32 which, u32 who)
Anton Blanchard79c2cc72005-07-07 17:56:15 -0700715{
716 /* sign extend which and who */
717 return sys_ioprio_get((int)which, (int)who);
718}
719
Stephen Rothwellb09a4912005-10-18 14:51:57 +1000720long compat_sys_ioprio_set(u32 which, u32 who, u32 ioprio)
Anton Blanchard79c2cc72005-07-07 17:56:15 -0700721{
722 /* sign extend which, who and ioprio */
723 return sys_ioprio_set((int)which, (int)who, (int)ioprio);
724}
725
Linus Torvalds1da177e2005-04-16 15:20:36 -0700726/* Note: it is necessary to treat newmask as an unsigned int,
727 * with the corresponding cast to a signed int to insure that the
728 * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
729 * and the register representation of a signed int (msr in 64-bit mode) is performed.
730 */
Stephen Rothwellb09a4912005-10-18 14:51:57 +1000731asmlinkage long compat_sys_ssetmask(u32 newmask)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700732{
733 return sys_ssetmask((int) newmask);
734}
735
Stephen Rothwellb09a4912005-10-18 14:51:57 +1000736asmlinkage long compat_sys_syslog(u32 type, char __user * buf, u32 len)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700737{
738 /* sign extend len */
739 return sys_syslog(type, buf, (int)len);
740}
741
742
743/* Note: it is necessary to treat mask as an unsigned int,
744 * with the corresponding cast to a signed int to insure that the
745 * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
746 * and the register representation of a signed int (msr in 64-bit mode) is performed.
747 */
Stephen Rothwellb09a4912005-10-18 14:51:57 +1000748asmlinkage long compat_sys_umask(u32 mask)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700749{
750 return sys_umask((int)mask);
751}
752
Eric W. Biedermanb89a8172006-09-27 01:51:04 -0700753#ifdef CONFIG_SYSCTL_SYSCALL
Linus Torvalds1da177e2005-04-16 15:20:36 -0700754struct __sysctl_args32 {
755 u32 name;
756 int nlen;
757 u32 oldval;
758 u32 oldlenp;
759 u32 newval;
760 u32 newlen;
761 u32 __unused[4];
762};
763
Stephen Rothwellb09a4912005-10-18 14:51:57 +1000764asmlinkage long compat_sys_sysctl(struct __sysctl_args32 __user *args)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700765{
766 struct __sysctl_args32 tmp;
767 int error;
768 size_t oldlen;
769 size_t __user *oldlenp = NULL;
770 unsigned long addr = (((unsigned long)&args->__unused[0]) + 7) & ~7;
771
772 if (copy_from_user(&tmp, args, sizeof(tmp)))
773 return -EFAULT;
774
775 if (tmp.oldval && tmp.oldlenp) {
776 /* Duh, this is ugly and might not work if sysctl_args
777 is in read-only memory, but do_sysctl does indirectly
778 a lot of uaccess in both directions and we'd have to
779 basically copy the whole sysctl.c here, and
780 glibc's __sysctl uses rw memory for the structure
781 anyway. */
782 oldlenp = (size_t __user *)addr;
783 if (get_user(oldlen, (compat_size_t __user *)compat_ptr(tmp.oldlenp)) ||
784 put_user(oldlen, oldlenp))
785 return -EFAULT;
786 }
787
788 lock_kernel();
789 error = do_sysctl(compat_ptr(tmp.name), tmp.nlen,
790 compat_ptr(tmp.oldval), oldlenp,
791 compat_ptr(tmp.newval), tmp.newlen);
792 unlock_kernel();
793 if (oldlenp) {
794 if (!error) {
795 if (get_user(oldlen, oldlenp) ||
796 put_user(oldlen, (compat_size_t __user *)compat_ptr(tmp.oldlenp)))
797 error = -EFAULT;
798 }
799 copy_to_user(args->__unused, tmp.__unused, sizeof(tmp.__unused));
800 }
801 return error;
802}
803#endif
804
Stephen Rothwellb09a4912005-10-18 14:51:57 +1000805unsigned long compat_sys_mmap2(unsigned long addr, size_t len,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700806 unsigned long prot, unsigned long flags,
807 unsigned long fd, unsigned long pgoff)
808{
809 /* This should remain 12 even if PAGE_SIZE changes */
810 return sys_mmap(addr, len, prot, flags, fd, pgoff << 12);
811}
812
Stephen Rothwellb09a4912005-10-18 14:51:57 +1000813long compat_sys_tgkill(u32 tgid, u32 pid, int sig)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700814{
815 /* sign extend tgid, pid */
816 return sys_tgkill((int)tgid, (int)pid, sig);
817}
818
819/*
820 * long long munging:
821 * The 32 bit ABI passes long longs in an odd even register pair.
822 */
823
Stephen Rothwellb09a4912005-10-18 14:51:57 +1000824compat_ssize_t compat_sys_pread64(unsigned int fd, char __user *ubuf, compat_size_t count,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700825 u32 reg6, u32 poshi, u32 poslo)
826{
827 return sys_pread64(fd, ubuf, count, ((loff_t)poshi << 32) | poslo);
828}
829
Stephen Rothwellb09a4912005-10-18 14:51:57 +1000830compat_ssize_t compat_sys_pwrite64(unsigned int fd, char __user *ubuf, compat_size_t count,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700831 u32 reg6, u32 poshi, u32 poslo)
832{
833 return sys_pwrite64(fd, ubuf, count, ((loff_t)poshi << 32) | poslo);
834}
835
Stephen Rothwellb09a4912005-10-18 14:51:57 +1000836compat_ssize_t compat_sys_readahead(int fd, u32 r4, u32 offhi, u32 offlo, u32 count)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700837{
838 return sys_readahead(fd, ((loff_t)offhi << 32) | offlo, count);
839}
840
Stephen Rothwellb09a4912005-10-18 14:51:57 +1000841asmlinkage int compat_sys_truncate64(const char __user * path, u32 reg4,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700842 unsigned long high, unsigned long low)
843{
844 return sys_truncate(path, (high << 32) | low);
845}
846
Stephen Rothwellb09a4912005-10-18 14:51:57 +1000847asmlinkage int compat_sys_ftruncate64(unsigned int fd, u32 reg4, unsigned long high,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700848 unsigned long low)
849{
850 return sys_ftruncate(fd, (high << 32) | low);
851}
852
853long ppc32_lookup_dcookie(u32 cookie_high, u32 cookie_low, char __user *buf,
854 size_t len)
855{
856 return sys_lookup_dcookie((u64)cookie_high << 32 | cookie_low,
857 buf, len);
858}
859
860long ppc32_fadvise64(int fd, u32 unused, u32 offset_high, u32 offset_low,
861 size_t len, int advice)
862{
863 return sys_fadvise64(fd, (u64)offset_high << 32 | offset_low, len,
864 advice);
865}
866
Stephen Rothwellb09a4912005-10-18 14:51:57 +1000867asmlinkage long compat_sys_add_key(const char __user *_type,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700868 const char __user *_description,
869 const void __user *_payload,
870 u32 plen,
871 u32 ringid)
872{
873 return sys_add_key(_type, _description, _payload, plen, ringid);
874}
875
Stephen Rothwellb09a4912005-10-18 14:51:57 +1000876asmlinkage long compat_sys_request_key(const char __user *_type,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700877 const char __user *_description,
878 const char __user *_callout_info,
879 u32 destringid)
880{
881 return sys_request_key(_type, _description, _callout_info, destringid);
882}
883