linux-old/arch/ppc64/kernel/sys_ppc32.c
<<
>>
Prefs
   1/*
   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
  17#include <asm/ptrace.h>
  18#include <linux/config.h>
  19#include <linux/kernel.h>
  20#include <linux/sched.h>
  21#include <linux/fs.h> 
  22#include <linux/mm.h> 
  23#include <linux/file.h> 
  24#include <linux/signal.h>
  25#include <linux/utime.h>
  26#include <linux/resource.h>
  27#include <linux/times.h>
  28#include <linux/utsname.h>
  29#include <linux/timex.h>
  30#include <linux/smp.h>
  31#include <linux/smp_lock.h>
  32#include <linux/sem.h>
  33#include <linux/msg.h>
  34#include <linux/shm.h>
  35#include <linux/slab.h>
  36#include <linux/uio.h>
  37#include <linux/nfs_fs.h>
  38#include <linux/smb_fs.h>
  39#include <linux/smb_mount.h>
  40#include <linux/ncp_fs.h>
  41#include <linux/quota.h>
  42#include <linux/quotacompat.h>
  43#include <linux/module.h>
  44#include <linux/sunrpc/svc.h>
  45#include <linux/nfsd/nfsd.h>
  46#include <linux/nfsd/cache.h>
  47#include <linux/nfsd/xdr.h>
  48#include <linux/nfsd/syscall.h>
  49#include <linux/poll.h>
  50#include <linux/personality.h>
  51#include <linux/stat.h>
  52#include <linux/filter.h>
  53#include <linux/highmem.h>
  54#include <linux/highuid.h>
  55#include <linux/mman.h>
  56#include <linux/sysctl.h>
  57
  58#include <asm/types.h>
  59#include <asm/ipc.h>
  60#include <asm/uaccess.h>
  61
  62#include <asm/semaphore.h>
  63
  64#include <net/scm.h>
  65#include <linux/elf.h>
  66#include <asm/ppcdebug.h>
  67#include <asm/time.h>
  68#include <asm/ppc32.h>
  69
  70extern unsigned long wall_jiffies;
  71#define USEC_PER_SEC (1000000)
  72
  73
  74extern asmlinkage long sys_utime(char * filename, struct utimbuf * times);
  75
  76struct utimbuf32 {
  77        __kernel_time_t32 actime, modtime;
  78};
  79
  80asmlinkage long sys32_utime(char * filename, struct utimbuf32 *times)
  81{
  82        struct utimbuf t;
  83        mm_segment_t old_fs;
  84        int ret;
  85        char *filenam;
  86        
  87        PPCDBG(PPCDBG_SYS32NI, "sys32_utime - running - filename=%s, times=%p - pid=%ld, comm=%s \n", filename, times, current->pid, current->comm);
  88
  89        if (!times)
  90                return sys_utime(filename, NULL);
  91        if (get_user(t.actime, &times->actime) || __get_user(t.modtime, &times->modtime))
  92                return -EFAULT;
  93        filenam = getname(filename);
  94
  95        ret = PTR_ERR(filenam);
  96        if (!IS_ERR(filenam)) {
  97                old_fs = get_fs();
  98                set_fs (KERNEL_DS); 
  99                ret = sys_utime(filenam, &t);
 100                set_fs (old_fs);
 101                putname (filenam);
 102        }
 103
 104        return ret;
 105}
 106
 107asmlinkage int sys32_ustat(__kernel_dev_t32 dev, struct ustat32 * ubuf)
 108{
 109
 110        struct super_block *s;
 111        struct ustat32 tmp;
 112        struct statfs sbuf;
 113        int err = -EINVAL;
 114
 115        s = get_super(to_kdev_t(dev));
 116        if (s == NULL)
 117                goto out;
 118        err = vfs_statfs(s, &sbuf);
 119        drop_super(s);
 120        if (err)
 121                goto out;
 122
 123        memset(&tmp,0,sizeof(struct ustat));
 124        tmp.f_tfree = sbuf.f_bfree;
 125        tmp.f_tinode = sbuf.f_ffree;
 126
 127        err = copy_to_user(ubuf, &tmp, sizeof(struct ustat32)) ? -EFAULT : 0;
 128
 129out:
 130        return err;
 131
 132}
 133
 134struct iovec32 { u32 iov_base; __kernel_size_t32 iov_len; };
 135
 136typedef ssize_t (*IO_fn_t)(struct file *, char *, size_t, loff_t *);
 137typedef __kernel_ssize_t32 ssize_t32;
 138
 139static long do_readv_writev32(int type, struct file *file,
 140                              const struct iovec32 *vector, u32 count)
 141{
 142        unsigned long tot_len;
 143        struct iovec iovstack[UIO_FASTIOV];
 144        struct iovec *iov=iovstack, *ivp;
 145        struct inode *inode;
 146        long retval, i;
 147        IO_fn_t fn;
 148
 149        /* First get the "struct iovec" from user memory and
 150         * verify all the pointers
 151         */
 152        if (!count)
 153                return 0;
 154        if (count > UIO_MAXIOV)
 155                return -EINVAL;
 156        if(verify_area(VERIFY_READ, vector, sizeof(struct iovec32)*count))
 157                return -EFAULT;
 158        if (count > UIO_FASTIOV) {
 159                iov = kmalloc(count*sizeof(struct iovec), GFP_KERNEL);
 160                if (!iov)
 161                        return -ENOMEM;
 162        }
 163
 164        tot_len = 0;
 165        i = count;
 166        ivp = iov;
 167        while(i > 0) {
 168                u32 len;
 169                u32 buf;
 170
 171                __get_user(len, &vector->iov_len);
 172                __get_user(buf, &vector->iov_base);
 173                tot_len += len;
 174                ivp->iov_base = (void *)A(buf);
 175                ivp->iov_len = (__kernel_size_t) len;
 176                vector++;
 177                ivp++;
 178                if ((len < 0) || (tot_len != (ssize_t32)tot_len)) {
 179                        if (iov != iovstack)
 180                                kfree(iov);
 181                        return -EINVAL;
 182                }
 183                i--;
 184        }
 185
 186        inode = file->f_dentry->d_inode;
 187        /* VERIFY_WRITE actually means a read, as we write to user space */
 188        retval = locks_verify_area((type == VERIFY_WRITE
 189                                    ? FLOCK_VERIFY_READ : FLOCK_VERIFY_WRITE),
 190                                   inode, file, file->f_pos, tot_len);
 191        if (retval) {
 192                if (iov != iovstack)
 193                        kfree(iov);
 194                return retval;
 195        }
 196
 197        /* Then do the actual IO.  Note that sockets need to be handled
 198         * specially as they have atomicity guarantees and can handle
 199         * iovec's natively
 200         */
 201        if (inode->i_sock) {
 202                int err;
 203                err = sock_readv_writev(type, inode, file, iov, count, tot_len);
 204                if (iov != iovstack)
 205                        kfree(iov);
 206                return err;
 207        }
 208
 209        if (!file->f_op) {
 210                if (iov != iovstack)
 211                        kfree(iov);
 212                return -EINVAL;
 213        }
 214        /* VERIFY_WRITE actually means a read, as we write to user space */
 215        fn = file->f_op->read;
 216        if (type == VERIFY_READ)
 217                fn = (IO_fn_t) file->f_op->write;               
 218        ivp = iov;
 219        while (count > 0) {
 220                void * base;
 221                int len, nr;
 222
 223                base = ivp->iov_base;
 224                len = ivp->iov_len;
 225                ivp++;
 226                count--;
 227                nr = fn(file, base, len, &file->f_pos);
 228                if (nr < 0) {
 229                        if (retval)
 230                                break;
 231                        retval = nr;
 232                        break;
 233                }
 234                retval += nr;
 235                if (nr != len)
 236                        break;
 237        }
 238        if (iov != iovstack)
 239                kfree(iov);
 240        return retval;
 241}
 242
 243asmlinkage long sys32_readv(u32 fd, struct iovec32 *vector, u32 count)
 244{
 245        struct file *file;
 246        long ret = -EBADF;
 247        
 248        PPCDBG(PPCDBG_SYS32, "sys32_readv - entered - pid=%ld current=%lx comm=%s \n", current->pid, current, current->comm);
 249
 250        file = fget(fd);
 251        if(!file)
 252                goto bad_file;
 253
 254        if (file->f_op && (file->f_mode & FMODE_READ) &&
 255     (file->f_op->readv || file->f_op->read))
 256                ret = do_readv_writev32(VERIFY_WRITE, file, vector, count);
 257        fput(file);
 258
 259bad_file:
 260        PPCDBG(PPCDBG_SYS32, "sys32_readv - exited - pid=%ld current=%lx comm=%s \n", current->pid, current, current->comm);
 261        return ret;
 262}
 263
 264asmlinkage long sys32_writev(u32 fd, struct iovec32 *vector, u32 count)
 265{
 266        struct file *file;
 267        int ret = -EBADF;
 268        
 269        PPCDBG(PPCDBG_SYS32, "sys32_writev - entered - pid=%ld current=%lx comm=%s \n", current->pid, current, current->comm);
 270
 271        file = fget(fd);
 272        if(!file)
 273                goto bad_file;
 274        if (file->f_op && (file->f_mode & FMODE_WRITE) &&
 275           (file->f_op->writev || file->f_op->write))
 276                ret = do_readv_writev32(VERIFY_READ, file, vector, count);
 277        fput(file);
 278
 279bad_file:
 280        PPCDBG(PPCDBG_SYS32, "sys32_writev - exited - pid=%ld current=%lx comm=%s \n", current->pid, current, current->comm);
 281        return ret;
 282}
 283
 284
 285
 286static inline int get_flock(struct flock *kfl, struct flock32 *ufl)
 287{
 288        int err;
 289        
 290        err = get_user(kfl->l_type, &ufl->l_type);
 291        err |= __get_user(kfl->l_whence, &ufl->l_whence);
 292        err |= __get_user(kfl->l_start, &ufl->l_start);
 293        err |= __get_user(kfl->l_len, &ufl->l_len);
 294        err |= __get_user(kfl->l_pid, &ufl->l_pid);
 295        return err;
 296}
 297
 298static inline int put_flock(struct flock *kfl, struct flock32 *ufl)
 299{
 300        int err;
 301        
 302        err = __put_user(kfl->l_type, &ufl->l_type);
 303        err |= __put_user(kfl->l_whence, &ufl->l_whence);
 304        err |= __put_user(kfl->l_start, &ufl->l_start);
 305        err |= __put_user(kfl->l_len, &ufl->l_len);
 306        err |= __put_user(kfl->l_pid, &ufl->l_pid);
 307        return err;
 308}
 309
 310extern asmlinkage long sys_fcntl(unsigned int fd, unsigned int cmd, unsigned long arg);
 311asmlinkage long sys32_fcntl(unsigned int fd, unsigned int cmd, unsigned long arg)
 312{
 313        switch (cmd) {
 314        case F_GETLK:
 315        case F_SETLK:
 316        case F_SETLKW:
 317        {
 318                struct flock f;
 319                mm_segment_t old_fs;
 320                long ret;
 321
 322                if(get_flock(&f, (struct flock32 *)arg))
 323                        return -EFAULT;
 324                old_fs = get_fs(); set_fs (KERNEL_DS);
 325                ret = sys_fcntl(fd, cmd, (unsigned long)&f);
 326                set_fs (old_fs);
 327                if(put_flock(&f, (struct flock32 *)arg))
 328                        return -EFAULT;
 329                return ret;
 330        }
 331        default:
 332                return sys_fcntl(fd, cmd, (unsigned long)arg);
 333        }
 334}
 335
 336struct ncp_mount_data32 {
 337        int version;
 338        unsigned int ncp_fd;
 339        __kernel_uid_t32 mounted_uid;
 340        __kernel_pid_t32 wdog_pid;
 341        unsigned char mounted_vol[NCP_VOLNAME_LEN + 1];
 342        unsigned int time_out;
 343        unsigned int retry_count;
 344        unsigned int flags;
 345        __kernel_uid_t32 uid;
 346        __kernel_gid_t32 gid;
 347        __kernel_mode_t32 file_mode;
 348        __kernel_mode_t32 dir_mode;
 349};
 350
 351static void *do_ncp_super_data_conv(void *raw_data)
 352{
 353        struct ncp_mount_data *n = (struct ncp_mount_data *)raw_data;
 354        struct ncp_mount_data32 *n32 = (struct ncp_mount_data32 *)raw_data;
 355
 356        n->dir_mode = n32->dir_mode;
 357        n->file_mode = n32->file_mode;
 358        n->gid = n32->gid;
 359        n->uid = n32->uid;
 360        memmove (n->mounted_vol, n32->mounted_vol, (sizeof (n32->mounted_vol) + 3 * sizeof (unsigned int)));
 361        n->wdog_pid = n32->wdog_pid;
 362        n->mounted_uid = n32->mounted_uid;
 363        return raw_data;
 364}
 365
 366struct smb_mount_data32 {
 367        int version;
 368        __kernel_uid_t32 mounted_uid;
 369        __kernel_uid_t32 uid;
 370        __kernel_gid_t32 gid;
 371        __kernel_mode_t32 file_mode;
 372        __kernel_mode_t32 dir_mode;
 373};
 374
 375static void *do_smb_super_data_conv(void *raw_data)
 376{
 377        struct smb_mount_data *s = (struct smb_mount_data *)raw_data;
 378        struct smb_mount_data32 *s32 = (struct smb_mount_data32 *)raw_data;
 379
 380        s->version = s32->version;
 381        s->mounted_uid = s32->mounted_uid;
 382        s->uid = s32->uid;
 383        s->gid = s32->gid;
 384        s->file_mode = s32->file_mode;
 385        s->dir_mode = s32->dir_mode;
 386        return raw_data;
 387}
 388
 389static int copy_mount_stuff_to_kernel(const void *user, unsigned long *kernel)
 390{
 391        int i;
 392        unsigned long page;
 393        struct vm_area_struct *vma;
 394
 395        *kernel = 0;
 396        if(!user)
 397                return 0;
 398        vma = find_vma(current->mm, (unsigned long)user);
 399        if(!vma || (unsigned long)user < vma->vm_start)
 400                return -EFAULT;
 401        if(!(vma->vm_flags & VM_READ))
 402                return -EFAULT;
 403        i = vma->vm_end - (unsigned long) user;
 404        if(PAGE_SIZE <= (unsigned long) i)
 405                i = PAGE_SIZE - 1;
 406        if(!(page = __get_free_page(GFP_KERNEL)))
 407                return -ENOMEM;
 408        if(copy_from_user((void *) page, user, i)) {
 409                free_page(page);
 410                return -EFAULT;
 411        }
 412        *kernel = page;
 413        return 0;
 414}
 415
 416#define SMBFS_NAME      "smbfs"
 417#define NCPFS_NAME      "ncpfs"
 418
 419asmlinkage long sys32_mount(char *dev_name, char *dir_name, char *type, unsigned long new_flags, u32 data)
 420{
 421        unsigned long type_page = 0;
 422        unsigned long data_page = 0;
 423        unsigned long dev_page = 0;
 424        unsigned long dir_page = 0;
 425        int err, is_smb, is_ncp;
 426        
 427        PPCDBG(PPCDBG_SYS32, "sys32_mount - entered - pid=%ld current=%lx comm=%s \n", current->pid, current, current->comm);
 428
 429        is_smb = is_ncp = 0;
 430
 431        err = copy_mount_stuff_to_kernel((const void *)type, &type_page);
 432        if (err)
 433                goto out;
 434
 435        if (!type_page) {
 436                err = -EINVAL;
 437                goto out;
 438        }
 439
 440        is_smb = !strcmp((char *)type_page, SMBFS_NAME);
 441        is_ncp = !strcmp((char *)type_page, NCPFS_NAME);
 442
 443        err = copy_mount_stuff_to_kernel((const void *)AA(data), &data_page);
 444        if (err)
 445                goto type_out;
 446
 447        err = copy_mount_stuff_to_kernel(dev_name, &dev_page);
 448        if (err)
 449                goto data_out;
 450
 451        err = copy_mount_stuff_to_kernel(dir_name, &dir_page);
 452        if (err)
 453                goto dev_out;
 454
 455        if (!is_smb && !is_ncp) {
 456                lock_kernel();
 457                err = do_mount((char*)dev_page, (char*)dir_page,
 458                                (char*)type_page, new_flags, (char*)data_page);
 459                unlock_kernel();
 460        } else {
 461                if (is_ncp)
 462                        do_ncp_super_data_conv((void *)data_page);
 463                else
 464                        do_smb_super_data_conv((void *)data_page);
 465
 466                lock_kernel();
 467                err = do_mount((char*)dev_page, (char*)dir_page,
 468                                (char*)type_page, new_flags, (char*)data_page);
 469                unlock_kernel();
 470        }
 471        free_page(dir_page);
 472
 473dev_out:
 474        free_page(dev_page);
 475
 476data_out:
 477        free_page(data_page);
 478
 479type_out:
 480        free_page(type_page);
 481
 482out:
 483        
 484        PPCDBG(PPCDBG_SYS32, "sys32_mount - exited - pid=%ld current=%lx comm=%s \n", current->pid, current, current->comm);
 485
 486        return err;
 487}
 488
 489struct user_dqblk32 {
 490    __u32 dqb_bhardlimit;
 491    __u32 dqb_bsoftlimit;
 492    __u32 dqb_curblocks;
 493    __u32 dqb_ihardlimit;
 494    __u32 dqb_isoftlimit;
 495    __u32 dqb_curinodes;
 496    __kernel_time_t32 dqb_btime;
 497    __kernel_time_t32 dqb_itime;
 498};
 499                                
 500
 501extern asmlinkage long sys_quotactl(unsigned int cmd, const char *special, qid_t id, caddr_t addr);
 502
 503/* Note: it is necessary to treat cmd and id as unsigned ints, 
 504 * with the corresponding cast to a signed int to insure that the 
 505 * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
 506 * and the register representation of a signed int (msr in 64-bit mode) is performed.
 507 */
 508asmlinkage long sys32_quotactl(u32 cmd_parm, const char *special, u32 id_parm, caddr_t addr)
 509{
 510        unsigned int cmd = cmd_parm;
 511        qid_t id  = (qid_t)id_parm;
 512        unsigned int cmds = cmd >> SUBCMDSHIFT;
 513        int err;
 514        struct v1c_mem_dqblk d;
 515        mm_segment_t old_fs;
 516        char *spec;
 517        
 518        PPCDBG(PPCDBG_SYS32, "sys32_quotactl - entered - pid=%ld current=%lx comm=%s \n",
 519                    current->pid, current, current->comm);
 520
 521        switch (cmds) {
 522        case Q_V1_GETQUOTA:
 523                break;
 524        case Q_V1_SETQUOTA:
 525        case Q_V1_SETUSE:
 526        case Q_V1_SETQLIM:
 527                if (copy_from_user(&d, addr, sizeof(struct user_dqblk32)))
 528                        return -EFAULT;
 529                d.dqb_itime = ((struct user_dqblk32 *)&d)->dqb_itime;
 530                d.dqb_btime = ((struct user_dqblk32 *)&d)->dqb_btime;
 531                break;
 532        default:
 533                return sys_quotactl(cmd, special, id, addr);
 534        }
 535        spec = getname(special);
 536        err = PTR_ERR(spec);
 537        if (IS_ERR(spec))
 538                return err;
 539        old_fs = get_fs();
 540        set_fs (KERNEL_DS);
 541        err = sys_quotactl(cmd, (const char *)spec, id, (caddr_t)&d);
 542        set_fs (old_fs);
 543        putname (spec);
 544        if (cmds == Q_V1_GETQUOTA) {
 545                __kernel_time_t b = d.dqb_btime, i = d.dqb_itime;
 546                ((struct user_dqblk32 *)&d)->dqb_itime = i;
 547                ((struct user_dqblk32 *)&d)->dqb_btime = b;
 548                if (copy_to_user(addr, &d, sizeof(struct user_dqblk32)))
 549                        return -EFAULT;
 550        }
 551        
 552        PPCDBG(PPCDBG_SYS32, "sys32_quotactl - exited - pid=%ld current=%lx comm=%s \n",
 553                    current->pid, current, current->comm);
 554
 555        return err;
 556}
 557
 558
 559
 560/* readdir & getdents */
 561#define NAME_OFFSET(de) ((int) ((de)->d_name - (char *) (de)))
 562#define ROUND_UP(x) (((x)+sizeof(u32)-1) & ~(sizeof(u32)-1))
 563
 564struct old_linux_dirent32 {
 565        u32             d_ino;
 566        u32             d_offset;
 567        unsigned short  d_namlen;
 568        char            d_name[1];
 569};
 570
 571struct readdir_callback32 {
 572        struct old_linux_dirent32 * dirent;
 573        int count;
 574};
 575
 576static int fillonedir(void * __buf, const char * name, int namlen,
 577                                  off_t offset, ino_t ino, unsigned int d_type)
 578{
 579        struct readdir_callback32 * buf = (struct readdir_callback32 *) __buf;
 580        struct old_linux_dirent32 * dirent;
 581
 582        if (buf->count)
 583                return -EINVAL;
 584        buf->count++;
 585        dirent = buf->dirent;
 586        put_user(ino, &dirent->d_ino);
 587        put_user(offset, &dirent->d_offset);
 588        put_user(namlen, &dirent->d_namlen);
 589        copy_to_user(dirent->d_name, name, namlen);
 590        put_user(0, dirent->d_name + namlen);
 591        return 0;
 592}
 593
 594asmlinkage int old32_readdir(unsigned int fd, struct old_linux_dirent32 *dirent, unsigned int count)
 595{
 596        int error = -EBADF;
 597        struct file * file;
 598        struct readdir_callback32 buf;
 599
 600        file = fget(fd);
 601        if (!file)
 602                goto out;
 603
 604        buf.count = 0;
 605        buf.dirent = dirent;
 606
 607        error = vfs_readdir(file, (filldir_t)fillonedir, &buf);
 608        if (error < 0)
 609                goto out_putf;
 610        error = buf.count;
 611
 612out_putf:
 613        fput(file);
 614out:
 615        return error;
 616}
 617
 618#if 0
 619struct linux_dirent32 {
 620        u32             d_ino;
 621        u32             d_off;
 622        unsigned short  d_reclen;
 623        char            d_name[1];
 624};
 625#else
 626struct linux_dirent32 {
 627        u32             d_ino;
 628        u32             d_off;
 629        unsigned short  d_reclen;
 630  /* unsigned char      d_type; */
 631        char            d_name[256];
 632};
 633#endif
 634
 635struct getdents_callback32 {
 636        struct linux_dirent32 * current_dir;
 637        struct linux_dirent32 * previous;
 638        int count;
 639        int error;
 640};
 641
 642static int
 643filldir(void * __buf, const char * name, int namlen, off_t offset, ino_t ino,
 644                               unsigned int d_type)
 645{
 646        struct linux_dirent32 * dirent;
 647        struct getdents_callback32 * buf = (struct getdents_callback32 *) __buf;
 648        int reclen = ROUND_UP(NAME_OFFSET(dirent) + namlen + 1);
 649
 650        buf->error = -EINVAL;   /* only used if we fail.. */
 651        if (reclen > buf->count)
 652                return -EINVAL;
 653        dirent = buf->previous;
 654        if (dirent)
 655                put_user(offset, &dirent->d_off);
 656        dirent = buf->current_dir;
 657        buf->previous = dirent;
 658        put_user(ino, &dirent->d_ino);
 659        put_user(reclen, &dirent->d_reclen);
 660        copy_to_user(dirent->d_name, name, namlen);
 661        put_user(0, dirent->d_name + namlen);
 662        ((char *) dirent) += reclen;
 663        buf->current_dir = dirent;
 664        buf->count -= reclen;
 665        return 0;
 666}
 667
 668asmlinkage long sys32_getdents(unsigned int fd, struct linux_dirent32 *dirent, unsigned int count)
 669{
 670        struct file * file;
 671        struct linux_dirent32 * lastdirent;
 672        struct getdents_callback32 buf;
 673        int error = -EBADF;
 674
 675        PPCDBG(PPCDBG_SYS32NI, "sys32_getdents - running - fd=%x, pid=%ld, comm=%s \n", fd, current->pid, current->comm);
 676
 677        file = fget(fd);
 678        if (!file)
 679                goto out;
 680
 681        buf.current_dir = dirent;
 682        buf.previous = NULL;
 683        buf.count = count;
 684        buf.error = 0;
 685
 686        error = vfs_readdir(file, (filldir_t)filldir, &buf);
 687        if (error < 0)
 688                goto out_putf;
 689        lastdirent = buf.previous;
 690        error = buf.error;
 691        if(lastdirent) {
 692                put_user(file->f_pos, &lastdirent->d_off);
 693                error = count - buf.count;
 694        }
 695 out_putf:
 696        fput(file);
 697
 698 out:
 699        return error;
 700}
 701/* end of readdir & getdents */
 702
 703
 704
 705/* 32-bit timeval and related flotsam.  */
 706
 707struct timeval32
 708{
 709        int tv_sec, tv_usec;
 710};
 711
 712struct itimerval32
 713{
 714        struct timeval32 it_interval;
 715        struct timeval32 it_value;
 716};
 717
 718
 719
 720
 721/*
 722 * Ooo, nasty.  We need here to frob 32-bit unsigned longs to
 723 * 64-bit unsigned longs.
 724 */
 725static inline int
 726get_fd_set32(unsigned long n, unsigned long *fdset, u32 *ufdset)
 727{
 728        if (ufdset) {
 729                unsigned long odd;
 730
 731                if (verify_area(VERIFY_WRITE, ufdset, n*sizeof(u32)))
 732                        return -EFAULT;
 733
 734                odd = n & 1UL;
 735                n &= ~1UL;
 736                while (n) {
 737                        unsigned long h, l;
 738                        __get_user(l, ufdset);
 739                        __get_user(h, ufdset+1);
 740                        ufdset += 2;
 741                        *fdset++ = h << 32 | l;
 742                        n -= 2;
 743                }
 744                if (odd)
 745                        __get_user(*fdset, ufdset);
 746        } else {
 747                /* Tricky, must clear full unsigned long in the
 748                 * kernel fdset at the end, this makes sure that
 749                 * actually happens.
 750                 */
 751                memset(fdset, 0, ((n + 1) & ~1)*sizeof(u32));
 752        }
 753        return 0;
 754}
 755
 756static inline void
 757set_fd_set32(unsigned long n, u32 *ufdset, unsigned long *fdset)
 758{
 759        unsigned long odd;
 760
 761        if (!ufdset)
 762                return;
 763
 764        odd = n & 1UL;
 765        n &= ~1UL;
 766        while (n) {
 767                unsigned long h, l;
 768                l = *fdset++;
 769                h = l >> 32;
 770                __put_user(l, ufdset);
 771                __put_user(h, ufdset+1);
 772                ufdset += 2;
 773                n -= 2;
 774        }
 775        if (odd)
 776                __put_user(*fdset, ufdset);
 777}
 778
 779
 780
 781#define MAX_SELECT_SECONDS ((unsigned long) (MAX_SCHEDULE_TIMEOUT / HZ)-1)
 782
 783asmlinkage long sys32_select(int n, u32 *inp, u32 *outp, u32 *exp, u32 tvp_x)
 784{
 785        fd_set_bits fds;
 786        struct timeval32 *tvp = (struct timeval32 *)AA(tvp_x);
 787        char *bits;
 788        unsigned long nn;
 789        long timeout;
 790        int ret, size;
 791        
 792  PPCDBG(PPCDBG_SYS32X, "sys32_select - entered - n=%x, inp=%p, outp=%p - pid=%ld comm=%s \n", n, inp, outp, current->pid, current->comm);
 793
 794        timeout = MAX_SCHEDULE_TIMEOUT;
 795        if (tvp) {
 796                time_t sec, usec;
 797                if ((ret = verify_area(VERIFY_READ, tvp, sizeof(*tvp)))
 798                    || (ret = __get_user(sec, &tvp->tv_sec))
 799                    || (ret = __get_user(usec, &tvp->tv_usec)))
 800                        goto out_nofds;
 801
 802                ret = -EINVAL;
 803                if(sec < 0 || usec < 0)
 804                        goto out_nofds;
 805
 806                if ((unsigned long) sec < MAX_SELECT_SECONDS) {
 807                        timeout = (usec + 1000000/HZ - 1) / (1000000/HZ);
 808                        timeout += sec * (unsigned long) HZ;
 809                }
 810        }
 811
 812        ret = -EINVAL;
 813        if (n < 0)
 814                goto out_nofds;
 815        if (n > current->files->max_fdset)
 816                n = current->files->max_fdset;
 817
 818        /*
 819         * We need 6 bitmaps (in/out/ex for both incoming and outgoing),
 820         * since we used fdset we need to allocate memory in units of
 821         * long-words. 
 822         */
 823        ret = -ENOMEM;
 824        size = FDS_BYTES(n);
 825        bits = kmalloc(6 * size, GFP_KERNEL);
 826        if (!bits)
 827                goto out_nofds;
 828        fds.in      = (unsigned long *)  bits;
 829        fds.out     = (unsigned long *) (bits +   size);
 830        fds.ex      = (unsigned long *) (bits + 2*size);
 831        fds.res_in  = (unsigned long *) (bits + 3*size);
 832        fds.res_out = (unsigned long *) (bits + 4*size);
 833        fds.res_ex  = (unsigned long *) (bits + 5*size);
 834
 835        nn = (n + 8*sizeof(u32) - 1) / (8*sizeof(u32));
 836        if ((ret = get_fd_set32(nn, fds.in, inp)) ||
 837            (ret = get_fd_set32(nn, fds.out, outp)) ||
 838            (ret = get_fd_set32(nn, fds.ex, exp)))
 839                goto out;
 840        zero_fd_set(n, fds.res_in);
 841        zero_fd_set(n, fds.res_out);
 842        zero_fd_set(n, fds.res_ex);
 843
 844        ret = do_select(n, &fds, &timeout);
 845
 846        if (tvp && !(current->personality & STICKY_TIMEOUTS)) {
 847                time_t sec = 0, usec = 0;
 848                if (timeout) {
 849                        sec = timeout / HZ;
 850                        usec = timeout % HZ;
 851                        usec *= (1000000/HZ);
 852                }
 853                put_user(sec, &tvp->tv_sec);
 854                put_user(usec, &tvp->tv_usec);
 855        }
 856
 857        if (ret < 0)
 858                goto out;
 859        if (!ret) {
 860                ret = -ERESTARTNOHAND;
 861                if (signal_pending(current))
 862                        goto out;
 863                ret = 0;
 864        }
 865
 866        set_fd_set32(nn, inp, fds.res_in);
 867        set_fd_set32(nn, outp, fds.res_out);
 868        set_fd_set32(nn, exp, fds.res_ex);
 869  
 870out:
 871        kfree(bits);
 872
 873out_nofds:
 874        PPCDBG(PPCDBG_SYS32X, "sys32_select - exited - pid=%ld, comm=%s \n", current->pid, current->comm);
 875        return ret;
 876}
 877
 878/* Note: it is necessary to treat n as an unsigned int, 
 879 * with the corresponding cast to a signed int to insure that the 
 880 * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
 881 * and the register representation of a signed int (msr in 64-bit mode) is performed.
 882 */
 883asmlinkage int ppc32_select(u32 n, u32* inp, u32* outp, u32* exp, u32 tvp_x)
 884{
 885        return sys32_select((int)n, inp, outp, exp, tvp_x);
 886}
 887
 888static int cp_new_stat32(struct inode *inode, struct stat32 *statbuf)
 889{
 890        unsigned long ino, blksize, blocks;
 891        kdev_t dev, rdev;
 892        umode_t mode;
 893        nlink_t nlink;
 894        uid_t uid;
 895        gid_t gid;
 896        off_t size;
 897        time_t atime, mtime, ctime;
 898        int err;
 899
 900        /* Stream the loads of inode data into the load buffer,
 901         * then we push it all into the store buffer below.  This
 902         * should give optimal cache performance.
 903         */
 904        ino = inode->i_ino;
 905        dev = inode->i_dev;
 906        mode = inode->i_mode;
 907        nlink = inode->i_nlink;
 908        uid = inode->i_uid;
 909        gid = inode->i_gid;
 910        rdev = inode->i_rdev;
 911        size = inode->i_size;
 912        atime = inode->i_atime;
 913        mtime = inode->i_mtime;
 914        ctime = inode->i_ctime;
 915        blksize = inode->i_blksize;
 916        blocks = inode->i_blocks;
 917
 918        err  = put_user(kdev_t_to_nr(dev), &statbuf->st_dev);
 919        err |= put_user(ino, &statbuf->st_ino);
 920        err |= put_user(mode, &statbuf->st_mode);
 921        err |= put_user(nlink, &statbuf->st_nlink);
 922        err |= put_user(uid, &statbuf->st_uid);
 923        err |= put_user(gid, &statbuf->st_gid);
 924        err |= put_user(kdev_t_to_nr(rdev), &statbuf->st_rdev);
 925        err |= put_user(size, &statbuf->st_size);
 926        err |= put_user(atime, &statbuf->st_atime);
 927        err |= put_user(0, &statbuf->__unused1);
 928        err |= put_user(mtime, &statbuf->st_mtime);
 929        err |= put_user(0, &statbuf->__unused2);
 930        err |= put_user(ctime, &statbuf->st_ctime);
 931        err |= put_user(0, &statbuf->__unused3);
 932        if (blksize) {
 933                err |= put_user(blksize, &statbuf->st_blksize);
 934                err |= put_user(blocks, &statbuf->st_blocks);
 935        } else {
 936                unsigned int tmp_blocks;
 937
 938#define D_B   7
 939#define I_B   (BLOCK_SIZE / sizeof(unsigned short))
 940                tmp_blocks = (size + BLOCK_SIZE - 1) / BLOCK_SIZE;
 941                if (tmp_blocks > D_B) {
 942                        unsigned int indirect;
 943
 944                        indirect = (tmp_blocks - D_B + I_B - 1) / I_B;
 945                        tmp_blocks += indirect;
 946                        if (indirect > 1) {
 947                                indirect = (indirect - 1 + I_B - 1) / I_B;
 948                                tmp_blocks += indirect;
 949                                if (indirect > 1)
 950                                        tmp_blocks++;
 951                        }
 952                }
 953                err |= put_user(BLOCK_SIZE, &statbuf->st_blksize);
 954                err |= put_user((BLOCK_SIZE / 512) * tmp_blocks, &statbuf->st_blocks);
 955#undef D_B
 956#undef I_B
 957        }
 958        err |= put_user(0, &statbuf->__unused4[0]);
 959        err |= put_user(0, &statbuf->__unused4[1]);
 960
 961        return err;
 962}
 963
 964static __inline__ int
 965do_revalidate(struct dentry *dentry)
 966{
 967        struct inode * inode = dentry->d_inode;
 968        if (inode->i_op && inode->i_op->revalidate)
 969                return inode->i_op->revalidate(dentry);
 970        return 0;
 971}
 972
 973asmlinkage long sys32_newstat(char* filename, struct stat32* statbuf)
 974{
 975        struct nameidata nd;
 976        int error;
 977        
 978        PPCDBG(PPCDBG_SYS32X, "sys32_newstat - running - filename=%s, statbuf=%p, pid=%ld, comm=%s\n", filename, statbuf, current->pid, current->comm);
 979
 980        error = user_path_walk(filename, &nd);
 981        if (!error) {
 982                error = do_revalidate(nd.dentry);
 983                if (!error)
 984                        error = cp_new_stat32(nd.dentry->d_inode, statbuf);
 985                path_release(&nd);
 986        }
 987        return error;
 988}
 989
 990asmlinkage long sys32_newlstat(char * filename, struct stat32 *statbuf)
 991{
 992        struct nameidata nd;
 993        int error;
 994        
 995        PPCDBG(PPCDBG_SYS32X, "sys32_newlstat - running - fn=%s, pid=%ld, comm=%s\n", filename, current->pid, current->comm);
 996
 997        error = user_path_walk_link(filename, &nd);
 998        if (!error) {
 999                error = do_revalidate(nd.dentry);
1000                if (!error)
1001                        error = cp_new_stat32(nd.dentry->d_inode, statbuf);
1002
1003                path_release(&nd);
1004        }
1005        return error;
1006}
1007
1008asmlinkage long sys32_newfstat(unsigned int fd, struct stat32 *statbuf)
1009{
1010        struct file *f;
1011        int err = -EBADF;
1012        
1013        PPCDBG(PPCDBG_SYS32X, "sys32_newfstat - running - fd=%x, pid=%ld, comm=%s\n", fd, current->pid, current->comm);
1014
1015        f = fget(fd);
1016        if (f) {
1017                struct dentry * dentry = f->f_dentry;
1018
1019                err = do_revalidate(dentry);
1020                if (!err)
1021                        err = cp_new_stat32(dentry->d_inode, statbuf);
1022                fput(f);
1023        }
1024        return err;
1025}
1026
1027static inline int put_statfs (struct statfs32 *ubuf, struct statfs *kbuf)
1028{
1029        struct statfs32 tmp;
1030        memset(&tmp, 0, sizeof(tmp));
1031
1032        tmp.f_type = kbuf->f_type;
1033        tmp.f_bsize = kbuf->f_bsize;
1034        tmp.f_blocks = kbuf->f_blocks;
1035        tmp.f_bfree = kbuf->f_bfree;
1036        tmp.f_bavail = kbuf->f_bavail;
1037        tmp.f_files = kbuf->f_files;
1038        tmp.f_ffree = kbuf->f_ffree;
1039        tmp.f_namelen = kbuf->f_namelen;
1040        tmp.f_fsid.val[0] = kbuf->f_fsid.val[0];
1041        tmp.f_fsid.val[1] = kbuf->f_fsid.val[1];
1042
1043        return copy_to_user(ubuf, &tmp, sizeof(tmp)) ? -EFAULT : 0;
1044}
1045
1046extern asmlinkage int sys_statfs(const char * path, struct statfs * buf);
1047
1048asmlinkage long sys32_statfs(const char * path, struct statfs32 *buf)
1049{
1050        int ret;
1051        struct statfs s;
1052        mm_segment_t old_fs = get_fs();
1053        char *pth;
1054        
1055        PPCDBG(PPCDBG_SYS32X, "sys32_statfs - entered - pid=%ld current=%lx comm=%s\n", current->pid, current, current->comm);
1056        
1057        pth = getname (path);
1058        ret = PTR_ERR(pth);
1059        if (!IS_ERR(pth)) {
1060                set_fs (KERNEL_DS);
1061                ret = sys_statfs((const char *)pth, &s);
1062                set_fs (old_fs);
1063                putname (pth);
1064                if (put_statfs(buf, &s))
1065                        return -EFAULT;
1066        }
1067        
1068        PPCDBG(PPCDBG_SYS32X, "sys32_statfs - exited - pid=%ld current=%lx comm=%s \n", current->pid, current, current->comm);
1069
1070        return ret;
1071}
1072
1073extern asmlinkage long sys_fstatfs(unsigned int fd, struct statfs * buf);
1074
1075asmlinkage long sys32_fstatfs(unsigned int fd, struct statfs32 *buf)
1076{
1077        int ret;
1078        struct statfs s;
1079        mm_segment_t old_fs = get_fs();
1080        
1081        PPCDBG(PPCDBG_SYS32X, "sys32_fstatfs - entered - pid=%ld current=%lx comm=%s\n", current->pid, current, current->comm);
1082        
1083        set_fs (KERNEL_DS);
1084        ret = sys_fstatfs(fd, &s);
1085        set_fs (old_fs);
1086        if (put_statfs(buf, &s))
1087                return -EFAULT;
1088        
1089        PPCDBG(PPCDBG_SYS32X, "sys32_fstatfs - exited - pid=%ld current=%lx comm=%s\n", current->pid, current, current->comm);
1090
1091        return ret;
1092}
1093
1094
1095
1096extern asmlinkage long sys_sysfs(int option, unsigned long arg1, unsigned long arg2);
1097
1098/* Note: it is necessary to treat option as an unsigned int,
1099 * with the corresponding cast to a signed int to insure that the 
1100 * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
1101 * and the register representation of a signed int (msr in 64-bit mode) is performed.
1102 */
1103asmlinkage long sys32_sysfs(u32 option, u32 arg1, u32 arg2)
1104{
1105        PPCDBG(PPCDBG_SYS32, "sys32_sysfs - running - pid=%ld, comm=%s\n", current->pid, current->comm);
1106        return sys_sysfs((int)option, arg1, arg2);
1107}
1108
1109
1110
1111
1112extern unsigned long do_mremap(unsigned long addr,
1113        unsigned long old_len, unsigned long new_len,
1114        unsigned long flags, unsigned long new_addr);
1115                
1116asmlinkage unsigned long sys32_mremap(unsigned long addr, unsigned long old_len, unsigned long new_len,
1117                                        unsigned long flags, u32 __new_addr)
1118{
1119        unsigned long ret = -EINVAL;
1120        unsigned long new_addr = AA(__new_addr);
1121        
1122        PPCDBG(PPCDBG_SYS32, "sys32_mremap - entered - pid=%ld current=%lx comm=%s\n",
1123                    current->pid, current, current->comm);
1124
1125
1126        if (old_len > 0xf0000000UL || new_len > 0xf0000000UL)
1127                goto out;
1128        if (addr > 0xf0000000UL - old_len)
1129                goto out;
1130        down_write(&current->mm->mmap_sem);
1131        if (flags & MREMAP_FIXED) {
1132                if (new_addr > 0xf0000000UL - new_len)
1133                        goto out_sem;
1134        } else if (addr > 0xf0000000UL - new_len) {
1135                ret = -ENOMEM;
1136                if (!(flags & MREMAP_MAYMOVE))
1137                        goto out_sem;
1138                new_addr = get_unmapped_area (NULL, addr, new_len, 0, 0);
1139                if (!new_addr)
1140                        goto out_sem;
1141                flags |= MREMAP_FIXED;
1142        }
1143        ret = do_mremap(addr, old_len, new_len, flags, new_addr);
1144out_sem:
1145        up_write(&current->mm->mmap_sem);
1146out:
1147        
1148        PPCDBG(PPCDBG_SYS32, "sys32_mremap - exited - pid=%ld current=%lx comm=%s\n",
1149                    current->pid, current, current->comm);
1150
1151        return ret;       
1152}
1153
1154
1155
1156/* Handle adjtimex compatability. */
1157struct timex32 {
1158        u32 modes;
1159        s32 offset, freq, maxerror, esterror;
1160        s32 status, constant, precision, tolerance;
1161        struct timeval32 time;
1162        s32 tick;
1163        s32 ppsfreq, jitter, shift, stabil;
1164        s32 jitcnt, calcnt, errcnt, stbcnt;
1165        s32  :32; s32  :32; s32  :32; s32  :32;
1166        s32  :32; s32  :32; s32  :32; s32  :32;
1167        s32  :32; s32  :32; s32  :32; s32  :32;
1168};
1169
1170extern int do_adjtimex(struct timex *);
1171extern void ppc_adjtimex(void);
1172
1173asmlinkage long sys32_adjtimex(struct timex32 *utp)
1174{
1175        struct timex txc;
1176        int ret;
1177        
1178        PPCDBG(PPCDBG_SYS32, "sys32_adjtimex - running - pid=%ld current=%lx comm=%s \n", current->pid, current, current->comm);
1179
1180        memset(&txc, 0, sizeof(struct timex));
1181
1182        if(get_user(txc.modes, &utp->modes) ||
1183           __get_user(txc.offset, &utp->offset) ||
1184           __get_user(txc.freq, &utp->freq) ||
1185           __get_user(txc.maxerror, &utp->maxerror) ||
1186           __get_user(txc.esterror, &utp->esterror) ||
1187           __get_user(txc.status, &utp->status) ||
1188           __get_user(txc.constant, &utp->constant) ||
1189           __get_user(txc.precision, &utp->precision) ||
1190           __get_user(txc.tolerance, &utp->tolerance) ||
1191           __get_user(txc.time.tv_sec, &utp->time.tv_sec) ||
1192           __get_user(txc.time.tv_usec, &utp->time.tv_usec) ||
1193           __get_user(txc.tick, &utp->tick) ||
1194           __get_user(txc.ppsfreq, &utp->ppsfreq) ||
1195           __get_user(txc.jitter, &utp->jitter) ||
1196           __get_user(txc.shift, &utp->shift) ||
1197           __get_user(txc.stabil, &utp->stabil) ||
1198           __get_user(txc.jitcnt, &utp->jitcnt) ||
1199           __get_user(txc.calcnt, &utp->calcnt) ||
1200           __get_user(txc.errcnt, &utp->errcnt) ||
1201           __get_user(txc.stbcnt, &utp->stbcnt))
1202                return -EFAULT;
1203
1204        ret = do_adjtimex(&txc);
1205
1206        /* adjust the conversion of TB to time of day to track adjtimex */
1207        ppc_adjtimex();
1208
1209        if(put_user(txc.modes, &utp->modes) ||
1210           __put_user(txc.offset, &utp->offset) ||
1211           __put_user(txc.freq, &utp->freq) ||
1212           __put_user(txc.maxerror, &utp->maxerror) ||
1213           __put_user(txc.esterror, &utp->esterror) ||
1214           __put_user(txc.status, &utp->status) ||
1215           __put_user(txc.constant, &utp->constant) ||
1216           __put_user(txc.precision, &utp->precision) ||
1217           __put_user(txc.tolerance, &utp->tolerance) ||
1218           __put_user(txc.time.tv_sec, &utp->time.tv_sec) ||
1219           __put_user(txc.time.tv_usec, &utp->time.tv_usec) ||
1220           __put_user(txc.tick, &utp->tick) ||
1221           __put_user(txc.ppsfreq, &utp->ppsfreq) ||
1222           __put_user(txc.jitter, &utp->jitter) ||
1223           __put_user(txc.shift, &utp->shift) ||
1224           __put_user(txc.stabil, &utp->stabil) ||
1225           __put_user(txc.jitcnt, &utp->jitcnt) ||
1226           __put_user(txc.calcnt, &utp->calcnt) ||
1227           __put_user(txc.errcnt, &utp->errcnt) ||
1228           __put_user(txc.stbcnt, &utp->stbcnt))
1229                ret = -EFAULT;
1230
1231        return ret;
1232}
1233
1234
1235
1236#ifdef CONFIG_MODULES
1237
1238extern asmlinkage unsigned long sys_create_module(const char *name_user, size_t size);
1239
1240asmlinkage unsigned long sys32_create_module(const char *name_user, __kernel_size_t32 size)
1241{
1242        
1243        PPCDBG(PPCDBG_SYS32M, "sys32_create_module - running - pid=%ld current=%lx comm=%s\n", current->pid, current, current->comm);
1244
1245        return sys_create_module(name_user, (size_t)size);
1246}
1247
1248
1249
1250extern asmlinkage long sys_init_module(const char *name_user, struct module *mod_user);
1251
1252asmlinkage long sys32_init_module(const char *name_user, struct module *mod_user)
1253{
1254        
1255        PPCDBG(PPCDBG_SYS32, "sys32_init_module - running - pid=%ld current=%lx comm=%s\n", current->pid, current, current->comm);
1256
1257        return sys_init_module(name_user, mod_user);
1258}
1259
1260
1261
1262extern asmlinkage long sys_delete_module(const char *name_user);
1263
1264asmlinkage long sys32_delete_module(const char *name_user)
1265{
1266        
1267        PPCDBG(PPCDBG_SYS32, "sys32_delete_module - running - pid=%ld current=%lx comm=%s\n", current->pid, current, current->comm);
1268
1269        return sys_delete_module(name_user);
1270}
1271
1272
1273
1274struct module_info32 {
1275        u32 addr;
1276        u32 size;
1277        u32 flags;
1278        s32 usecount;
1279};
1280
1281/* Query various bits about modules.  */
1282
1283static inline long
1284get_mod_name(const char *user_name, char **buf)
1285{
1286        unsigned long page;
1287        long retval;
1288
1289        if ((unsigned long)user_name >= TASK_SIZE
1290            && !segment_eq(get_fs (), KERNEL_DS))
1291                return -EFAULT;
1292
1293        page = __get_free_page(GFP_KERNEL);
1294        if (!page)
1295                return -ENOMEM;
1296
1297        retval = strncpy_from_user((char *)page, user_name, PAGE_SIZE);
1298        if (retval > 0) {
1299                if (retval < PAGE_SIZE) {
1300                        *buf = (char *)page;
1301                        return retval;
1302                }
1303                retval = -ENAMETOOLONG;
1304        } else if (!retval)
1305                retval = -EINVAL;
1306
1307        free_page(page);
1308        return retval;
1309}
1310
1311static inline void
1312put_mod_name(char *buf)
1313{
1314        free_page((unsigned long)buf);
1315}
1316
1317static __inline__ struct module *find_module(const char *name)
1318{
1319        struct module *mod;
1320
1321        for (mod = module_list; mod ; mod = mod->next) {
1322                if (mod->flags & MOD_DELETED)
1323                        continue;
1324                if (!strcmp(mod->name, name))
1325                        break;
1326        }
1327
1328        return mod;
1329}
1330
1331static int
1332qm_modules(char *buf, size_t bufsize, __kernel_size_t32 *ret)
1333{
1334        struct module *mod;
1335        size_t nmod, space, len;
1336
1337        nmod = space = 0;
1338
1339        for (mod = module_list; mod->next != NULL; mod = mod->next, ++nmod) {
1340                len = strlen(mod->name)+1;
1341                if (len > bufsize)
1342                        goto calc_space_needed;
1343                if (copy_to_user(buf, mod->name, len))
1344                        return -EFAULT;
1345                buf += len;
1346                bufsize -= len;
1347                space += len;
1348        }
1349
1350        if (put_user(nmod, ret))
1351                return -EFAULT;
1352        else
1353                return 0;
1354
1355calc_space_needed:
1356        space += len;
1357        while ((mod = mod->next)->next != NULL)
1358                space += strlen(mod->name)+1;
1359
1360        if (put_user(space, ret))
1361                return -EFAULT;
1362        else
1363                return -ENOSPC;
1364}
1365
1366static int
1367qm_deps(struct module *mod, char *buf, size_t bufsize, __kernel_size_t32 *ret)
1368{
1369        size_t i, space, len;
1370
1371        if (mod->next == NULL)
1372                return -EINVAL;
1373        if (!MOD_CAN_QUERY(mod))
1374                return put_user(0, ret);
1375
1376        space = 0;
1377        for (i = 0; i < mod->ndeps; ++i) {
1378                const char *dep_name = mod->deps[i].dep->name;
1379
1380                len = strlen(dep_name)+1;
1381                if (len > bufsize)
1382                        goto calc_space_needed;
1383                if (copy_to_user(buf, dep_name, len))
1384                        return -EFAULT;
1385                buf += len;
1386                bufsize -= len;
1387                space += len;
1388        }
1389
1390        return put_user(i, ret);
1391
1392calc_space_needed:
1393        space += len;
1394        while (++i < mod->ndeps)
1395                space += strlen(mod->deps[i].dep->name)+1;
1396
1397        if (put_user(space, ret))
1398                return -EFAULT;
1399        else
1400                return -ENOSPC;
1401}
1402
1403static int
1404qm_refs(struct module *mod, char *buf, size_t bufsize, __kernel_size_t32 *ret)
1405{
1406        size_t nrefs, space, len;
1407        struct module_ref *ref;
1408
1409        if (mod->next == NULL)
1410                return -EINVAL;
1411        if (!MOD_CAN_QUERY(mod))
1412                if (put_user(0, ret))
1413                        return -EFAULT;
1414                else
1415                        return 0;
1416
1417        space = 0;
1418        for (nrefs = 0, ref = mod->refs; ref ; ++nrefs, ref = ref->next_ref) {
1419                const char *ref_name = ref->ref->name;
1420
1421                len = strlen(ref_name)+1;
1422                if (len > bufsize)
1423                        goto calc_space_needed;
1424                if (copy_to_user(buf, ref_name, len))
1425                        return -EFAULT;
1426                buf += len;
1427                bufsize -= len;
1428                space += len;
1429        }
1430
1431        if (put_user(nrefs, ret))
1432                return -EFAULT;
1433        else
1434                return 0;
1435
1436calc_space_needed:
1437        space += len;
1438        while ((ref = ref->next_ref) != NULL)
1439                space += strlen(ref->ref->name)+1;
1440
1441        if (put_user(space, ret))
1442                return -EFAULT;
1443        else
1444                return -ENOSPC;
1445}
1446
1447static inline int
1448qm_symbols(struct module *mod, char *buf, size_t bufsize, __kernel_size_t32 *ret)
1449{
1450        size_t i, space, len;
1451        struct module_symbol *s;
1452        char *strings;
1453        unsigned *vals;
1454
1455        if (!MOD_CAN_QUERY(mod))
1456                if (put_user(0, ret))
1457                        return -EFAULT;
1458                else
1459                        return 0;
1460
1461        space = mod->nsyms * 2*sizeof(u32);
1462
1463        i = len = 0;
1464        s = mod->syms;
1465
1466        if (space > bufsize)
1467                goto calc_space_needed;
1468
1469        if (!access_ok(VERIFY_WRITE, buf, space))
1470                return -EFAULT;
1471
1472        bufsize -= space;
1473        vals = (unsigned *)buf;
1474        strings = buf+space;
1475
1476        for (; i < mod->nsyms ; ++i, ++s, vals += 2) {
1477                len = strlen(s->name)+1;
1478                if (len > bufsize)
1479                        goto calc_space_needed;
1480
1481                if (copy_to_user(strings, s->name, len)
1482                    || __put_user(s->value, vals+0)
1483                    || __put_user(space, vals+1))
1484                        return -EFAULT;
1485
1486                strings += len;
1487                bufsize -= len;
1488                space += len;
1489        }
1490
1491        if (put_user(i, ret))
1492                return -EFAULT;
1493        else
1494                return 0;
1495
1496calc_space_needed:
1497        for (; i < mod->nsyms; ++i, ++s)
1498                space += strlen(s->name)+1;
1499
1500        if (put_user(space, ret))
1501                return -EFAULT;
1502        else
1503                return -ENOSPC;
1504}
1505
1506static inline int
1507qm_info(struct module *mod, char *buf, size_t bufsize, __kernel_size_t32 *ret)
1508{
1509        int error = 0;
1510
1511        if (mod->next == NULL)
1512                return -EINVAL;
1513
1514        if (sizeof(struct module_info32) <= bufsize) {
1515                struct module_info32 info;
1516                info.addr = (unsigned long)mod;
1517                info.size = mod->size;
1518                info.flags = mod->flags;
1519                info.usecount =
1520                        ((mod_member_present(mod, can_unload)
1521                          && mod->can_unload)
1522                         ? -1 : atomic_read(&mod->uc.usecount));
1523
1524                if (copy_to_user(buf, &info, sizeof(struct module_info32)))
1525                        return -EFAULT;
1526        } else
1527                error = -ENOSPC;
1528
1529        if (put_user(sizeof(struct module_info32), ret))
1530                return -EFAULT;
1531
1532        return error;
1533}
1534
1535/* Note: it is necessary to treat which as an unsigned int, 
1536 * with the corresponding cast to a signed int to insure that the 
1537 * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
1538 * and the register representation of a signed int (msr in 64-bit mode) is performed.
1539 */
1540asmlinkage long sys32_query_module(char *name_user, u32 which, char *buf, __kernel_size_t32 bufsize, u32 ret)
1541{
1542        struct module *mod;
1543        int err;
1544        
1545        PPCDBG(PPCDBG_SYS32M, "sys32_query_module - entered - pid=%ld current=%lx comm=%s\n",
1546                    current->pid, current, current->comm);
1547
1548        lock_kernel();
1549        if (name_user == 0) {
1550                /* This finds "kernel_module" which is not exported. */
1551                for(mod = module_list; mod->next != NULL; mod = mod->next)
1552                        ;
1553        } else {
1554                long namelen;
1555                char *name;
1556
1557                if ((namelen = get_mod_name(name_user, &name)) < 0) {
1558                        err = namelen;
1559                        goto out;
1560                }
1561                err = -ENOENT;
1562                if (namelen == 0) {
1563                        /* This finds "kernel_module" which is not exported. */
1564                        for(mod = module_list; mod->next != NULL; mod = mod->next)
1565                                ;
1566                } else if ((mod = find_module(name)) == NULL) {
1567                        put_mod_name(name);
1568                        goto out;
1569                }
1570                put_mod_name(name);
1571        }
1572
1573        switch ((int)which)
1574        {
1575        case 0:
1576                err = 0;
1577                break;
1578        case QM_MODULES:
1579                err = qm_modules(buf, bufsize, (__kernel_size_t32 *)AA(ret));
1580                break;
1581        case QM_DEPS:
1582                err = qm_deps(mod, buf, bufsize, (__kernel_size_t32 *)AA(ret));
1583                break;
1584        case QM_REFS:
1585                err = qm_refs(mod, buf, bufsize, (__kernel_size_t32 *)AA(ret));
1586                break;
1587        case QM_SYMBOLS:
1588                err = qm_symbols(mod, buf, bufsize, (__kernel_size_t32 *)AA(ret));
1589                break;
1590        case QM_INFO:
1591                err = qm_info(mod, buf, bufsize, (__kernel_size_t32 *)AA(ret));
1592                break;
1593        default:
1594                err = -EINVAL;
1595                break;
1596        }
1597out:
1598        unlock_kernel();
1599        
1600        PPCDBG(PPCDBG_SYS32, "sys32_query_module - exited - pid=%ld current=%lx comm=%s\n", current->pid, current, current->comm);
1601
1602        return err;
1603}
1604
1605
1606
1607struct kernel_sym32 {
1608        u32 value;
1609        char name[60];
1610};
1611                 
1612extern asmlinkage long sys_get_kernel_syms(struct kernel_sym *table);
1613
1614asmlinkage long sys32_get_kernel_syms(struct kernel_sym32 *table)
1615{
1616        int len, i;
1617        struct kernel_sym *tbl;
1618        mm_segment_t old_fs;
1619        
1620        PPCDBG(PPCDBG_SYS32, "sys32_get_kernel_syms - entered - pid=%ld current=%lx comm=%s \n", current->pid, current, current->comm);
1621
1622        
1623        len = sys_get_kernel_syms(NULL);
1624        if (!table) return len;
1625        tbl = kmalloc (len * sizeof (struct kernel_sym), GFP_KERNEL);
1626        if (!tbl) return -ENOMEM;
1627        old_fs = get_fs();
1628        set_fs (KERNEL_DS);
1629        sys_get_kernel_syms(tbl);
1630        set_fs (old_fs);
1631        for (i = 0; i < len; i++, table += sizeof (struct kernel_sym32)) {
1632                if (put_user (tbl[i].value, &table->value) ||
1633                    copy_to_user (table->name, tbl[i].name, 60))
1634                        break;
1635        }
1636        kfree (tbl);
1637        
1638        PPCDBG(PPCDBG_SYS32, "sys32_get_kernel_syms - exited - pid=%ld current=%lx comm=%s \n", current->pid, current, current->comm);
1639
1640        return i;
1641}
1642
1643#else /* CONFIG_MODULES */
1644
1645asmlinkage unsigned long sys32_create_module(const char *name_user, size_t size)
1646{
1647        
1648        PPCDBG(PPCDBG_SYS32, "sys32_create_module - running - pid=%ld, comm=%s\n", current->pid, current->comm);
1649
1650        return -ENOSYS;
1651}
1652
1653asmlinkage long sys32_init_module(const char *name_user, struct module *mod_user)
1654{
1655        PPCDBG(PPCDBG_SYS32, "sys32_init_module - running - pid=%ld, comm=%s\n", current->pid, current->comm);
1656
1657        return -ENOSYS;
1658}
1659
1660asmlinkage long sys32_delete_module(const char *name_user)
1661{
1662        PPCDBG(PPCDBG_SYS32, "sys32_delete_module - running - pid=%ld, comm=%s\n", current->pid, current->comm);
1663
1664        return -ENOSYS;
1665}
1666
1667/* Note: it is necessary to treat which as an unsigned int, 
1668 * with the corresponding cast to a signed int to insure that the 
1669 * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
1670 * and the register representation of a signed int (msr in 64-bit mode) is performed.
1671 */
1672asmlinkage long sys32_query_module(const char *name_user, u32 which, char *buf, size_t bufsize, size_t *ret)
1673{
1674        PPCDBG(PPCDBG_SYS32, "sys32_query_module - entered - pid=%ld current=%lx comm=%s\n", current->pid, current, current->comm);
1675
1676        /* Let the program know about the new interface.  Not that it'll do them much good. */
1677        if ((int)which == 0)
1678                return 0;
1679
1680        PPCDBG(PPCDBG_SYS32, "sys32_query_module - exited - pid=%ld current=%lx comm=%s\n", current->pid, current, current->comm);
1681        return -ENOSYS;
1682}
1683
1684asmlinkage long sys32_get_kernel_syms(struct kernel_sym *table)
1685{
1686        PPCDBG(PPCDBG_SYS32, "sys32_get_kernel_syms - running - pid=%ld, comm=%s\n", current->pid, current->comm);
1687
1688        return -ENOSYS;
1689}
1690
1691#endif  /* CONFIG_MODULES */
1692
1693
1694
1695/* Stuff for NFS server syscalls... */
1696struct nfsctl_svc32 {
1697        u16                     svc32_port;
1698        s32                     svc32_nthreads;
1699};
1700
1701struct nfsctl_client32 {
1702        s8                      cl32_ident[NFSCLNT_IDMAX+1];
1703        s32                     cl32_naddr;
1704        struct in_addr          cl32_addrlist[NFSCLNT_ADDRMAX];
1705        s32                     cl32_fhkeytype;
1706        s32                     cl32_fhkeylen;
1707        u8                      cl32_fhkey[NFSCLNT_KEYMAX];
1708};
1709
1710struct nfsctl_export32 {
1711        s8                      ex32_client[NFSCLNT_IDMAX+1];
1712        s8                      ex32_path[NFS_MAXPATHLEN+1];
1713        __kernel_dev_t32        ex32_dev;
1714        __kernel_ino_t32        ex32_ino;
1715        s32                     ex32_flags;
1716        __kernel_uid_t32        ex32_anon_uid;
1717        __kernel_gid_t32        ex32_anon_gid;
1718};
1719
1720struct nfsctl_uidmap32 {
1721        u32                     ug32_ident;   /* char * */
1722        __kernel_uid_t32        ug32_uidbase;
1723        s32                     ug32_uidlen;
1724        u32                     ug32_udimap;  /* uid_t * */
1725        __kernel_uid_t32        ug32_gidbase;
1726        s32                     ug32_gidlen;
1727        u32                     ug32_gdimap;  /* gid_t * */
1728};
1729
1730struct nfsctl_fhparm32 {
1731        struct sockaddr         gf32_addr;
1732        __kernel_dev_t32        gf32_dev;
1733        __kernel_ino_t32        gf32_ino;
1734        s32                     gf32_version;
1735};
1736
1737struct nfsctl_fdparm32 {
1738        struct sockaddr         gd32_addr;
1739        s8                      gd32_path[NFS_MAXPATHLEN+1];
1740        s32                     gd32_version;
1741};
1742
1743struct nfsctl_fsparm32 {
1744        struct sockaddr         gd32_addr;
1745        s8                      gd32_path[NFS_MAXPATHLEN+1];
1746        s32                     gd32_maxlen;
1747};
1748
1749struct nfsctl_arg32 {
1750        s32                     ca32_version;   /* safeguard */
1751        union {
1752                struct nfsctl_svc32     u32_svc;
1753                struct nfsctl_client32  u32_client;
1754                struct nfsctl_export32  u32_export;
1755                struct nfsctl_uidmap32  u32_umap;
1756                struct nfsctl_fhparm32  u32_getfh;
1757                struct nfsctl_fdparm32  u32_getfd;
1758                struct nfsctl_fsparm32  u32_getfs;
1759        } u;
1760#define ca32_svc        u.u32_svc
1761#define ca32_client     u.u32_client
1762#define ca32_export     u.u32_export
1763#define ca32_umap       u.u32_umap
1764#define ca32_getfh      u.u32_getfh
1765#define ca32_getfd      u.u32_getfd
1766#define ca32_getfs      u.u32_getfs
1767#define ca32_authd      u.u32_authd
1768};
1769
1770union nfsctl_res32 {
1771        __u8                    cr32_getfh[NFS_FHSIZE];
1772        struct knfsd_fh         cr32_getfs;
1773};
1774
1775static int nfs_svc32_trans(struct nfsctl_arg *karg, struct nfsctl_arg32 *arg32)
1776{
1777        int err;
1778        
1779        err = __get_user(karg->ca_version, &arg32->ca32_version);
1780        err |= __get_user(karg->ca_svc.svc_port, &arg32->ca32_svc.svc32_port);
1781        err |= __get_user(karg->ca_svc.svc_nthreads, &arg32->ca32_svc.svc32_nthreads);
1782        return err;
1783}
1784
1785static int nfs_clnt32_trans(struct nfsctl_arg *karg, struct nfsctl_arg32 *arg32)
1786{
1787        int err;
1788        
1789        err = __get_user(karg->ca_version, &arg32->ca32_version);
1790        err |= copy_from_user(&karg->ca_client.cl_ident[0],
1791                          &arg32->ca32_client.cl32_ident[0],
1792                          NFSCLNT_IDMAX);
1793        err |= __get_user(karg->ca_client.cl_naddr, &arg32->ca32_client.cl32_naddr);
1794        err |= copy_from_user(&karg->ca_client.cl_addrlist[0],
1795                          &arg32->ca32_client.cl32_addrlist[0],
1796                          (sizeof(struct in_addr) * NFSCLNT_ADDRMAX));
1797        err |= __get_user(karg->ca_client.cl_fhkeytype,
1798                      &arg32->ca32_client.cl32_fhkeytype);
1799        err |= __get_user(karg->ca_client.cl_fhkeylen,
1800                      &arg32->ca32_client.cl32_fhkeylen);
1801        err |= copy_from_user(&karg->ca_client.cl_fhkey[0],
1802                          &arg32->ca32_client.cl32_fhkey[0],
1803                          NFSCLNT_KEYMAX);
1804
1805        if(err) return -EFAULT;
1806        return 0;
1807}
1808
1809static int nfs_exp32_trans(struct nfsctl_arg *karg, struct nfsctl_arg32 *arg32)
1810{
1811        int err;
1812        
1813        err = __get_user(karg->ca_version, &arg32->ca32_version);
1814        err |= copy_from_user(&karg->ca_export.ex_client[0],
1815                          &arg32->ca32_export.ex32_client[0],
1816                          NFSCLNT_IDMAX);
1817        err |= copy_from_user(&karg->ca_export.ex_path[0],
1818                          &arg32->ca32_export.ex32_path[0],
1819                          NFS_MAXPATHLEN);
1820        err |= __get_user(karg->ca_export.ex_dev,
1821                      &arg32->ca32_export.ex32_dev);
1822        err |= __get_user(karg->ca_export.ex_ino,
1823                      &arg32->ca32_export.ex32_ino);
1824        err |= __get_user(karg->ca_export.ex_flags,
1825                      &arg32->ca32_export.ex32_flags);
1826        err |= __get_user(karg->ca_export.ex_anon_uid,
1827                      &arg32->ca32_export.ex32_anon_uid);
1828        err |= __get_user(karg->ca_export.ex_anon_gid,
1829                      &arg32->ca32_export.ex32_anon_gid);
1830        karg->ca_export.ex_anon_uid = karg->ca_export.ex_anon_uid;
1831        karg->ca_export.ex_anon_gid = karg->ca_export.ex_anon_gid;
1832
1833        if(err) return -EFAULT;
1834        return 0;
1835}
1836
1837static int nfs_uud32_trans(struct nfsctl_arg *karg, struct nfsctl_arg32 *arg32)
1838{
1839        u32 uaddr;
1840        int i;
1841        int err;
1842
1843        memset(karg, 0, sizeof(*karg));
1844        if(__get_user(karg->ca_version, &arg32->ca32_version))
1845                return -EFAULT;
1846        karg->ca_umap.ug_ident = (char *)get_free_page(GFP_USER);
1847        if(!karg->ca_umap.ug_ident)
1848                return -ENOMEM;
1849        err = __get_user(uaddr, &arg32->ca32_umap.ug32_ident);
1850        if(strncpy_from_user(karg->ca_umap.ug_ident,
1851                             (char *)A(uaddr), PAGE_SIZE) <= 0)
1852                return -EFAULT;
1853        err |= __get_user(karg->ca_umap.ug_uidbase,
1854                      &arg32->ca32_umap.ug32_uidbase);
1855        err |= __get_user(karg->ca_umap.ug_uidlen,
1856                      &arg32->ca32_umap.ug32_uidlen);
1857        err |= __get_user(uaddr, &arg32->ca32_umap.ug32_udimap);
1858        if (err)
1859                return -EFAULT;
1860        karg->ca_umap.ug_udimap = kmalloc((sizeof(uid_t) * karg->ca_umap.ug_uidlen),
1861                                          GFP_USER);
1862        if(!karg->ca_umap.ug_udimap)
1863                return -ENOMEM;
1864        for(i = 0; i < karg->ca_umap.ug_uidlen; i++)
1865                err |= __get_user(karg->ca_umap.ug_udimap[i],
1866                              &(((__kernel_uid_t32 *)A(uaddr))[i]));
1867        err |= __get_user(karg->ca_umap.ug_gidbase,
1868                      &arg32->ca32_umap.ug32_gidbase);
1869        err |= __get_user(karg->ca_umap.ug_uidlen,
1870                      &arg32->ca32_umap.ug32_gidlen);
1871        err |= __get_user(uaddr, &arg32->ca32_umap.ug32_gdimap);
1872        if (err)
1873                return -EFAULT;
1874        karg->ca_umap.ug_gdimap = kmalloc((sizeof(gid_t) * karg->ca_umap.ug_uidlen),
1875                                          GFP_USER);
1876        if(!karg->ca_umap.ug_gdimap)
1877                return -ENOMEM;
1878        for(i = 0; i < karg->ca_umap.ug_gidlen; i++)
1879                err |= __get_user(karg->ca_umap.ug_gdimap[i],
1880                              &(((__kernel_gid_t32 *)A(uaddr))[i]));
1881
1882        return err;
1883}
1884
1885static int nfs_getfh32_trans(struct nfsctl_arg *karg, struct nfsctl_arg32 *arg32)
1886{
1887        int err;
1888        
1889        err = __get_user(karg->ca_version, &arg32->ca32_version);
1890        err |= copy_from_user(&karg->ca_getfh.gf_addr,
1891                          &arg32->ca32_getfh.gf32_addr,
1892                          (sizeof(struct sockaddr)));
1893        err |= __get_user(karg->ca_getfh.gf_dev,
1894                      &arg32->ca32_getfh.gf32_dev);
1895        err |= __get_user(karg->ca_getfh.gf_ino,
1896                      &arg32->ca32_getfh.gf32_ino);
1897        err |= __get_user(karg->ca_getfh.gf_version,
1898                      &arg32->ca32_getfh.gf32_version);
1899
1900        if(err) return -EFAULT;
1901        return 0;
1902}
1903
1904static int nfs_getfd32_trans(struct nfsctl_arg *karg, struct nfsctl_arg32 *arg32)
1905{
1906        int err;
1907        
1908        err = __get_user(karg->ca_version, &arg32->ca32_version);
1909        err |= copy_from_user(&karg->ca_getfd.gd_addr,
1910                          &arg32->ca32_getfd.gd32_addr,
1911                          (sizeof(struct sockaddr)));
1912        err |= copy_from_user(&karg->ca_getfd.gd_path,
1913                          &arg32->ca32_getfd.gd32_path,
1914                          (NFS_MAXPATHLEN+1));
1915        err |= __get_user(karg->ca_getfd.gd_version,
1916                      &arg32->ca32_getfd.gd32_version);
1917
1918        if(err) return -EFAULT;
1919        return 0;
1920}
1921
1922static int nfs_getfs32_trans(struct nfsctl_arg *karg, struct nfsctl_arg32 *arg32)
1923{
1924        int err;
1925        
1926        err = __get_user(karg->ca_version, &arg32->ca32_version);
1927        err |= copy_from_user(&karg->ca_getfs.gd_addr,
1928                          &arg32->ca32_getfs.gd32_addr,
1929                          (sizeof(struct sockaddr)));
1930        err |= copy_from_user(&karg->ca_getfs.gd_path,
1931                          &arg32->ca32_getfs.gd32_path,
1932                          (NFS_MAXPATHLEN+1));
1933        err |= __get_user(karg->ca_getfs.gd_maxlen,
1934                      &arg32->ca32_getfs.gd32_maxlen);
1935
1936        if(err) return -EFAULT;
1937        return 0;
1938}
1939
1940/* This really doesn't need translations, we are only passing
1941 * back a union which contains opaque nfs file handle data.
1942 */
1943static int nfs_getfh32_res_trans(union nfsctl_res *kres, union nfsctl_res32 *res32)
1944{
1945        int err;
1946
1947        err = copy_to_user(res32, kres, sizeof(*res32));
1948
1949        if(err) return -EFAULT;
1950        return 0;
1951}
1952
1953/* Note: it is necessary to treat cmd_parm as an unsigned int, 
1954 * with the corresponding cast to a signed int to insure that the 
1955 * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
1956 * and the register representation of a signed int (msr in 64-bit mode) is performed.
1957 */
1958int asmlinkage sys32_nfsservctl(u32 cmd_parm, struct nfsctl_arg32 *arg32, union nfsctl_res32 *res32)
1959{
1960  int cmd = (int)cmd_parm;
1961        struct nfsctl_arg *karg = NULL;
1962        union nfsctl_res *kres = NULL;
1963        mm_segment_t oldfs;
1964        int err;
1965
1966        karg = kmalloc(sizeof(*karg), GFP_USER);
1967        if(!karg)
1968                return -ENOMEM;
1969        if(res32) {
1970                kres = kmalloc(sizeof(*kres), GFP_USER);
1971                if(!kres) {
1972                        kfree(karg);
1973                        return -ENOMEM;
1974                }
1975        }
1976        switch(cmd) {
1977        case NFSCTL_SVC:
1978                err = nfs_svc32_trans(karg, arg32);
1979                break;
1980        case NFSCTL_ADDCLIENT:
1981                err = nfs_clnt32_trans(karg, arg32);
1982                break;
1983        case NFSCTL_DELCLIENT:
1984                err = nfs_clnt32_trans(karg, arg32);
1985                break;
1986        case NFSCTL_EXPORT:
1987        case NFSCTL_UNEXPORT:
1988                err = nfs_exp32_trans(karg, arg32);
1989                break;
1990        /* This one is unimplemented, be we're ready for it. */
1991        case NFSCTL_UGIDUPDATE:
1992                err = nfs_uud32_trans(karg, arg32);
1993                break;
1994        case NFSCTL_GETFH:
1995                err = nfs_getfh32_trans(karg, arg32);
1996                break;
1997        case NFSCTL_GETFD:
1998                err = nfs_getfd32_trans(karg, arg32);
1999                break;
2000        case NFSCTL_GETFS:
2001                err = nfs_getfs32_trans(karg, arg32);
2002                break;
2003        default:
2004                err = -EINVAL;
2005                break;
2006        }
2007        if(err)
2008                goto done;
2009        oldfs = get_fs();
2010        set_fs(KERNEL_DS);
2011        err = sys_nfsservctl(cmd, karg, kres);
2012        set_fs(oldfs);
2013
2014        if (err)
2015                goto done;
2016
2017        if((cmd == NFSCTL_GETFH) ||
2018           (cmd == NFSCTL_GETFD) ||
2019           (cmd == NFSCTL_GETFS))
2020                err = nfs_getfh32_res_trans(kres, res32);
2021
2022done:
2023        if(karg) {
2024                if(cmd == NFSCTL_UGIDUPDATE) {
2025                        if(karg->ca_umap.ug_ident)
2026                                kfree(karg->ca_umap.ug_ident);
2027                        if(karg->ca_umap.ug_udimap)
2028                                kfree(karg->ca_umap.ug_udimap);
2029                        if(karg->ca_umap.ug_gdimap)
2030                                kfree(karg->ca_umap.ug_gdimap);
2031                }
2032                kfree(karg);
2033        }
2034        if(kres)
2035                kfree(kres);
2036        return err;
2037}
2038
2039
2040
2041struct timespec32 {
2042        s32    tv_sec;
2043        s32    tv_nsec;
2044};
2045
2046extern asmlinkage long sys_nanosleep(struct timespec *rqtp, struct timespec *rmtp);
2047
2048asmlinkage long sys32_nanosleep(struct timespec32 *rqtp, struct timespec32 *rmtp)
2049{
2050        struct timespec t;
2051        int ret;
2052        mm_segment_t old_fs = get_fs ();
2053        
2054        PPCDBG(PPCDBG_SYS32NI, "sys32_nanosleep - running - pid=%ld, comm=%s \n", current->pid, current->comm);
2055        
2056        if (get_user (t.tv_sec, &rqtp->tv_sec) ||
2057            __get_user (t.tv_nsec, &rqtp->tv_nsec))
2058                return -EFAULT;
2059        set_fs (KERNEL_DS);
2060        ret = sys_nanosleep(&t, rmtp ? &t : NULL);
2061        set_fs (old_fs);
2062        if (rmtp && ret == -EINTR) {
2063                if (__put_user (t.tv_sec, &rmtp->tv_sec) ||
2064                    __put_user (t.tv_nsec, &rmtp->tv_nsec))
2065                        return -EFAULT;
2066        }
2067        
2068        return ret;
2069}
2070
2071
2072
2073
2074/* These are here just in case some old sparc32 binary calls it. */
2075asmlinkage long sys32_pause(void)
2076{
2077        
2078        PPCDBG(PPCDBG_SYS32, "sys32_pause - running - pid=%ld, comm=%s \n", current->pid, current->comm);
2079
2080        current->state = TASK_INTERRUPTIBLE;
2081        schedule();
2082        
2083        return -ERESTARTNOHAND;
2084}
2085
2086
2087
2088static inline long get_it32(struct itimerval *o, struct itimerval32 *i)
2089{
2090        return (!access_ok(VERIFY_READ, i, sizeof(*i)) ||
2091                (__get_user(o->it_interval.tv_sec, &i->it_interval.tv_sec) |
2092                 __get_user(o->it_interval.tv_usec, &i->it_interval.tv_usec) |
2093                 __get_user(o->it_value.tv_sec, &i->it_value.tv_sec) |
2094                 __get_user(o->it_value.tv_usec, &i->it_value.tv_usec)));
2095}
2096
2097static inline long put_it32(struct itimerval32 *o, struct itimerval *i)
2098{
2099        return (!access_ok(VERIFY_WRITE, o, sizeof(*o)) ||
2100                (__put_user(i->it_interval.tv_sec, &o->it_interval.tv_sec) |
2101                 __put_user(i->it_interval.tv_usec, &o->it_interval.tv_usec) |
2102                 __put_user(i->it_value.tv_sec, &o->it_value.tv_sec) |
2103                 __put_user(i->it_value.tv_usec, &o->it_value.tv_usec)));
2104}
2105
2106static inline long get_tv32(struct timeval *o, struct timeval32 *i)
2107{
2108        return (!access_ok(VERIFY_READ, i, sizeof(*i)) ||
2109                (__get_user(o->tv_sec, &i->tv_sec) |
2110                 __get_user(o->tv_usec, &i->tv_usec)));
2111}
2112
2113static inline long put_tv32(struct timeval32 *o, struct timeval *i)
2114{
2115        return (!access_ok(VERIFY_WRITE, o, sizeof(*o)) ||
2116                (__put_user(i->tv_sec, &o->tv_sec) |
2117                 __put_user(i->tv_usec, &o->tv_usec)));
2118}
2119
2120
2121
2122
2123extern int do_getitimer(int which, struct itimerval *value);
2124
2125/* Note: it is necessary to treat which as an unsigned int, 
2126 * with the corresponding cast to a signed int to insure that the 
2127 * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
2128 * and the register representation of a signed int (msr in 64-bit mode) is performed.
2129 */
2130asmlinkage long sys32_getitimer(u32 which, struct itimerval32 *it)
2131{
2132        struct itimerval kit;
2133        int error;
2134        
2135        PPCDBG(PPCDBG_SYS32, "sys32_getitimer - entered - pid=%ld current=%lx comm=%s \n", current->pid, current, current->comm);
2136
2137        error = do_getitimer((int)which, &kit);
2138        if (!error && put_it32(it, &kit))
2139                error = -EFAULT;
2140
2141        
2142        PPCDBG(PPCDBG_SYS32, "sys32_getitimer - exited - pid=%ld current=%lx comm=%s\n", current->pid, current, current->comm);
2143        return error;
2144}
2145
2146
2147
2148extern int do_setitimer(int which, struct itimerval *, struct itimerval *);
2149
2150/* Note: it is necessary to treat which as an unsigned int, 
2151 * with the corresponding cast to a signed int to insure that the 
2152 * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
2153 * and the register representation of a signed int (msr in 64-bit mode) is performed.
2154 */
2155asmlinkage long sys32_setitimer(u32 which, struct itimerval32 *in, struct itimerval32 *out)
2156{
2157        struct itimerval kin, kout;
2158        int error;
2159        
2160        PPCDBG(PPCDBG_SYS32, "sys32_setitimer - entered - pid=%ld current=%lx comm=%s\n", current->pid, current, current->comm);
2161
2162        if (in) {
2163                if (get_it32(&kin, in))
2164                        return -EFAULT;
2165        } else
2166                memset(&kin, 0, sizeof(kin));
2167
2168        error = do_setitimer((int)which, &kin, out ? &kout : NULL);
2169        if (error || !out)
2170                return error;
2171        if (put_it32(out, &kout))
2172                return -EFAULT;
2173
2174        
2175        PPCDBG(PPCDBG_SYS32, "sys32_setitimer - exited - pid=%ld current=%lx comm=%s\n", current->pid, current, current->comm);
2176        return 0;
2177}
2178
2179#define RLIM_INFINITY32 0xffffffff
2180#define RESOURCE32(x) ((x > RLIM_INFINITY32) ? RLIM_INFINITY32 : x)
2181
2182struct rlimit32 {
2183        u32     rlim_cur;
2184        u32     rlim_max;
2185};
2186
2187extern asmlinkage long sys_getrlimit(unsigned int resource, struct rlimit *rlim);
2188asmlinkage long sys32_getrlimit(unsigned int resource, struct rlimit32 *rlim)
2189{
2190        struct rlimit r;
2191        int ret;
2192        mm_segment_t old_fs = get_fs();
2193        
2194        set_fs (KERNEL_DS);
2195        ret = sys_getrlimit(resource, &r);
2196        set_fs(old_fs);
2197        if (!ret) {
2198                ret = put_user(RESOURCE32(r.rlim_cur), &rlim->rlim_cur);
2199                ret |= __put_user(RESOURCE32(r.rlim_max), &rlim->rlim_max);
2200        }
2201        
2202        return ret;
2203}
2204
2205/* Back compatibility for getrlimit. Needed for some apps. */
2206asmlinkage long sys32_old_getrlimit(unsigned int resource, struct rlimit32* rlim)
2207{
2208        struct rlimit   x;    // 64-bit version of the resource limits.
2209        struct rlimit32 x32;  // 32-bit version of the resource limits.
2210        long rc = 0;
2211        
2212        if (resource >= RLIM_NLIMITS) {
2213                PPCDBG(PPCDBG_SYS32, "sys32_old_getrlimit - specified resource is too large (%x) - pid=%ld, comm=%s\n", resource, current->pid, current->comm);
2214                return -EINVAL;
2215        }
2216
2217        memcpy(&x, current->rlim+resource, sizeof(struct rlimit));
2218
2219        if(x.rlim_cur > RLIM_INFINITY32)
2220                x32.rlim_cur = RLIM_INFINITY32;
2221        else
2222                x32.rlim_cur = x.rlim_cur;
2223
2224        if(x.rlim_max > RLIM_INFINITY32)
2225                x32.rlim_max = RLIM_INFINITY32;
2226        else
2227                x32.rlim_max = x.rlim_max;
2228
2229        rc = (copy_to_user(rlim, &x32, sizeof(x32))) ? (-EFAULT) : 0;
2230        if (rc == 0) {
2231                PPCDBG(PPCDBG_SYS32, "sys32_old_getrlimit - current=%x, maximum=%x - pid=%ld, comm=%s\n", x32.rlim_cur, x32.rlim_max, current->pid, current->comm);
2232        } else {
2233                PPCDBG(PPCDBG_SYS32, "sys32_old_getrlimit - unable to copy into user's storage - pid=%ld, comm=%s\n", current->pid, current->comm);
2234        }
2235        return rc;
2236}
2237
2238extern asmlinkage long sys_setrlimit(unsigned int resource, struct rlimit *rlim);
2239asmlinkage long sys32_setrlimit(unsigned int resource, struct rlimit32 *rlim)
2240{
2241        struct rlimit r;
2242        long ret;
2243        mm_segment_t old_fs = get_fs ();
2244        
2245        PPCDBG(PPCDBG_SYS32, "sys32_setrlimit - entered - resource=%x, rlim=%p - pid=%ld, comm=%s\n", resource, rlim, current->pid, current->comm);
2246
2247        if (resource >= RLIM_NLIMITS) return -EINVAL;   
2248        if (get_user (r.rlim_cur, &rlim->rlim_cur) ||
2249            __get_user (r.rlim_max, &rlim->rlim_max))
2250                return -EFAULT;
2251        if (r.rlim_cur >= RLIM_INFINITY32)
2252                r.rlim_cur = RLIM_INFINITY;
2253        if (r.rlim_max >= RLIM_INFINITY32)
2254                r.rlim_max = RLIM_INFINITY;
2255        set_fs (KERNEL_DS);
2256        ret = sys_setrlimit(resource, &r);
2257        set_fs (old_fs);
2258        
2259        PPCDBG(PPCDBG_SYS32, "sys32_setrlimit - exited w/ ret=%x - pid=%ld, comm=%s\n", ret, current->pid, current->comm);
2260        return ret;
2261}
2262
2263
2264struct rusage32 {
2265        struct timeval32 ru_utime;
2266        struct timeval32 ru_stime;
2267        s32    ru_maxrss;
2268        s32    ru_ixrss;
2269        s32    ru_idrss;
2270        s32    ru_isrss;
2271        s32    ru_minflt;
2272        s32    ru_majflt;
2273        s32    ru_nswap;
2274        s32    ru_inblock;
2275        s32    ru_oublock;
2276        s32    ru_msgsnd; 
2277        s32    ru_msgrcv; 
2278        s32    ru_nsignals;
2279        s32    ru_nvcsw;
2280        s32    ru_nivcsw;
2281};
2282
2283static int put_rusage (struct rusage32 *ru, struct rusage *r)
2284{
2285        int err;
2286        
2287        err = put_user (r->ru_utime.tv_sec, &ru->ru_utime.tv_sec);
2288        err |= __put_user (r->ru_utime.tv_usec, &ru->ru_utime.tv_usec);
2289        err |= __put_user (r->ru_stime.tv_sec, &ru->ru_stime.tv_sec);
2290        err |= __put_user (r->ru_stime.tv_usec, &ru->ru_stime.tv_usec);
2291        err |= __put_user (r->ru_maxrss, &ru->ru_maxrss);
2292        err |= __put_user (r->ru_ixrss, &ru->ru_ixrss);
2293        err |= __put_user (r->ru_idrss, &ru->ru_idrss);
2294        err |= __put_user (r->ru_isrss, &ru->ru_isrss);
2295        err |= __put_user (r->ru_minflt, &ru->ru_minflt);
2296        err |= __put_user (r->ru_majflt, &ru->ru_majflt);
2297        err |= __put_user (r->ru_nswap, &ru->ru_nswap);
2298        err |= __put_user (r->ru_inblock, &ru->ru_inblock);
2299        err |= __put_user (r->ru_oublock, &ru->ru_oublock);
2300        err |= __put_user (r->ru_msgsnd, &ru->ru_msgsnd);
2301        err |= __put_user (r->ru_msgrcv, &ru->ru_msgrcv);
2302        err |= __put_user (r->ru_nsignals, &ru->ru_nsignals);
2303        err |= __put_user (r->ru_nvcsw, &ru->ru_nvcsw);
2304        err |= __put_user (r->ru_nivcsw, &ru->ru_nivcsw);
2305        return err;
2306}
2307
2308
2309extern asmlinkage long sys_getrusage(int who, struct rusage *ru);
2310
2311/* Note: it is necessary to treat who as an unsigned int, 
2312 * with the corresponding cast to a signed int to insure that the 
2313 * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
2314 * and the register representation of a signed int (msr in 64-bit mode) is performed.
2315 */
2316asmlinkage long sys32_getrusage(u32 who, struct rusage32 *ru)
2317{
2318        struct rusage r;
2319        int ret;
2320        mm_segment_t old_fs = get_fs();
2321        
2322        PPCDBG(PPCDBG_SYS32X, "sys32_getrusage - running - pid=%ld, comm=%s\n", current->pid, current->comm);
2323                
2324        set_fs (KERNEL_DS);
2325        ret = sys_getrusage((int)who, &r);
2326        set_fs (old_fs);
2327        if (put_rusage (ru, &r)) 
2328                return -EFAULT;
2329
2330        return ret;
2331}
2332
2333
2334
2335
2336struct sysinfo32 {
2337        s32 uptime;
2338        u32 loads[3];
2339        u32 totalram;
2340        u32 freeram;
2341        u32 sharedram;
2342        u32 bufferram;
2343        u32 totalswap;
2344        u32 freeswap;
2345        unsigned short procs;
2346        unsigned short pad;
2347        u32 totalhigh;
2348        u32 freehigh;
2349        u32 mem_unit;
2350        char _f[20-2*sizeof(u32)-sizeof(int)];
2351};
2352
2353extern asmlinkage long sys_sysinfo(struct sysinfo *info);
2354
2355asmlinkage long sys32_sysinfo(struct sysinfo32 *info)
2356{
2357        struct sysinfo s;
2358        int ret, err;
2359        int bitcount = 0;
2360        mm_segment_t old_fs = get_fs ();
2361        
2362        PPCDBG(PPCDBG_SYS32, "sys32_sysinfo - entered - pid=%ld current=%lx comm=%s \n", current->pid, current, current->comm);
2363        
2364        set_fs (KERNEL_DS);
2365        ret = sys_sysinfo(&s);
2366        set_fs (old_fs);
2367        /* Check to see if any memory value is too large for 32-bit and scale
2368         *  down if needed
2369         */
2370        if ((s.totalram >> 32) || (s.totalswap >> 32)) {
2371                while (s.mem_unit < PAGE_SIZE) {
2372                        s.mem_unit <<= 1;
2373                        bitcount++;
2374                }
2375                s.totalram >>= bitcount;
2376                s.freeram >>= bitcount;
2377                s.sharedram >>= bitcount;
2378                s.bufferram >>= bitcount;
2379                s.totalswap >>= bitcount;
2380                s.freeswap >>= bitcount;
2381                s.totalhigh >>= bitcount;
2382                s.freehigh >>= bitcount;
2383        }
2384        
2385        err = put_user (s.uptime, &info->uptime);
2386        err |= __put_user (s.loads[0], &info->loads[0]);
2387        err |= __put_user (s.loads[1], &info->loads[1]);
2388        err |= __put_user (s.loads[2], &info->loads[2]);
2389        err |= __put_user (s.totalram, &info->totalram);
2390        err |= __put_user (s.freeram, &info->freeram);
2391        err |= __put_user (s.sharedram, &info->sharedram);
2392        err |= __put_user (s.bufferram, &info->bufferram);
2393        err |= __put_user (s.totalswap, &info->totalswap);
2394        err |= __put_user (s.freeswap, &info->freeswap);
2395        err |= __put_user (s.procs, &info->procs);
2396        err |= __put_user (s.totalhigh, &info->totalhigh);
2397        err |= __put_user (s.freehigh, &info->freehigh);
2398        err |= __put_user (s.mem_unit, &info->mem_unit);
2399        
2400        if (err)
2401                return -EFAULT;
2402        
2403        PPCDBG(PPCDBG_SYS32, "sys32_sysinfo - exited - pid=%ld current=%lx comm=%s \n", current->pid, current, current->comm);
2404
2405        return ret;
2406}
2407
2408
2409
2410
2411/* Translations due to time_t size differences.  Which affects all
2412   sorts of things, like timeval and itimerval.  */
2413extern struct timezone sys_tz;
2414extern int do_sys_settimeofday(struct timeval *tv, struct timezone *tz);
2415
2416asmlinkage long sys32_gettimeofday(struct timeval32 *tv, struct timezone *tz)
2417{
2418        
2419        PPCDBG(PPCDBG_SYS32X, "sys32_gettimeofday - running - pid=%ld, comm=%s\n", current->pid, current->comm);
2420
2421        if (tv) {
2422                struct timeval ktv;
2423                do_gettimeofday(&ktv);
2424                if (put_tv32(tv, &ktv))
2425                        return -EFAULT;
2426        }
2427        if (tz) {
2428                if (copy_to_user(tz, &sys_tz, sizeof(sys_tz)))
2429                        return -EFAULT;
2430        }
2431        
2432        return 0;
2433}
2434
2435
2436
2437asmlinkage long sys32_settimeofday(struct timeval32 *tv, struct timezone *tz)
2438{
2439        struct timeval ktv;
2440        struct timezone ktz;
2441        
2442        PPCDBG(PPCDBG_SYS32, "sys32_settimeofday - running - pid=%ld current=%lx comm=%s \n", current->pid, current, current->comm);
2443
2444        if (tv) {
2445                if (get_tv32(&ktv, tv))
2446                        return -EFAULT;
2447        }
2448        if (tz) {
2449                if (copy_from_user(&ktz, tz, sizeof(ktz)))
2450                        return -EFAULT;
2451        }
2452
2453        return do_sys_settimeofday(tv ? &ktv : NULL, tz ? &ktz : NULL);
2454}
2455
2456
2457
2458
2459struct tms32 {
2460        __kernel_clock_t32 tms_utime;
2461        __kernel_clock_t32 tms_stime;
2462        __kernel_clock_t32 tms_cutime;
2463        __kernel_clock_t32 tms_cstime;
2464};
2465                                
2466extern asmlinkage long sys_times(struct tms * tbuf);
2467
2468asmlinkage long sys32_times(struct tms32 *tbuf)
2469{
2470        struct tms t;
2471        long ret;
2472        mm_segment_t old_fs = get_fs ();
2473        int err;
2474        
2475        PPCDBG(PPCDBG_SYS32, "sys32_times - entered - pid=%ld current=%lx comm=%s \n", current->pid, current, current->comm);
2476        
2477        set_fs (KERNEL_DS);
2478        ret = sys_times(tbuf ? &t : NULL);
2479        set_fs (old_fs);
2480        if (tbuf) {
2481                err = put_user (t.tms_utime, &tbuf->tms_utime);
2482                err |= __put_user (t.tms_stime, &tbuf->tms_stime);
2483                err |= __put_user (t.tms_cutime, &tbuf->tms_cutime);
2484                err |= __put_user (t.tms_cstime, &tbuf->tms_cstime);
2485                if (err)
2486                        ret = -EFAULT;
2487        }
2488        
2489        PPCDBG(PPCDBG_SYS32, "sys32_times - exited - pid=%ld current=%lx comm=%s \n", current->pid, current, current->comm);
2490
2491        return ret;
2492}
2493
2494struct msgbuf32 { s32 mtype; char mtext[1]; };
2495
2496struct semid_ds32 {
2497        struct ipc_perm32 sem_perm;
2498        unsigned int _pad0;
2499        __kernel_time_t32 sem_otime;
2500        unsigned int _pad1;
2501        __kernel_time_t32 sem_ctime;
2502        u32 sem_base;
2503        u32 sem_pending;
2504        u32 sem_pending_last;
2505        u32 undo;
2506        unsigned short sem_nsems;
2507};
2508
2509struct semid64_ds32 {
2510        struct ipc64_perm32 sem_perm;
2511        unsigned int __unused1;
2512        __kernel_time_t32 sem_otime;
2513        unsigned int __unused2;
2514        __kernel_time_t32 sem_ctime;
2515        u32 sem_nsems;
2516        u32 __unused3;
2517        u32 __unused4;
2518};
2519
2520struct msqid_ds32
2521{
2522        struct ipc_perm32 msg_perm;
2523        u32 msg_first;
2524        u32 msg_last;
2525        __kernel_time_t32 msg_stime;
2526        __kernel_time_t32 msg_rtime;
2527        __kernel_time_t32 msg_ctime;
2528        u32 msg_lcbytes;
2529        u32 msg_lqbytes;
2530        unsigned short msg_cbytes;
2531        unsigned short msg_qnum;
2532        unsigned short msg_qbytes;
2533        __kernel_ipc_pid_t32 msg_lspid;
2534        __kernel_ipc_pid_t32 msg_lrpid;
2535};
2536
2537struct msqid64_ds32 {
2538        struct ipc64_perm32 msg_perm;
2539        unsigned int __unused1;
2540        __kernel_time_t32 msg_stime;
2541        unsigned int __unused2;
2542        __kernel_time_t32 msg_rtime;
2543        unsigned int __unused3;
2544        __kernel_time_t32 msg_ctime;
2545        unsigned int msg_cbytes;
2546        unsigned int msg_qnum;
2547        unsigned int msg_qbytes;
2548        __kernel_pid_t32 msg_lspid;
2549        __kernel_pid_t32 msg_lrpid;
2550        unsigned int __unused4;
2551        unsigned int __unused5;
2552};
2553
2554struct shmid_ds32 {
2555        struct ipc_perm32 shm_perm;
2556        int shm_segsz;
2557        __kernel_time_t32 shm_atime;
2558        __kernel_time_t32 shm_dtime;
2559        __kernel_time_t32 shm_ctime;
2560        __kernel_ipc_pid_t32 shm_cpid;
2561        __kernel_ipc_pid_t32 shm_lpid;
2562        unsigned short shm_nattch;
2563        unsigned short __unused;
2564        unsigned int __unused2;
2565        unsigned int __unused3;
2566};
2567
2568struct shmid64_ds32 {
2569        struct ipc64_perm32 shm_perm;
2570        unsigned int __unused1;
2571        __kernel_time_t32 shm_atime;
2572        unsigned int __unused2;
2573        __kernel_time_t32 shm_dtime;
2574        unsigned int __unused3;
2575        __kernel_time_t32 shm_ctime;
2576        unsigned int __unused4;
2577        __kernel_size_t32 shm_segsz;
2578        __kernel_pid_t32 shm_cpid;
2579        __kernel_pid_t32 shm_lpid;
2580        unsigned int shm_nattch;
2581        unsigned int __unused5;
2582        unsigned int __unused6;
2583};
2584
2585/*
2586 * sys32_ipc() is the de-multiplexer for the SysV IPC calls in 32bit
2587 * emulation..
2588 *
2589 * This is really horribly ugly.
2590 */
2591static long do_sys32_semctl(int first, int second, int third, void *uptr)
2592{
2593        union semun fourth;
2594        u32 pad;
2595        int err, err2;
2596        mm_segment_t old_fs;
2597
2598        if (!uptr)
2599                return -EINVAL;
2600        err = -EFAULT;
2601        if (get_user(pad, (u32 *)uptr))
2602                return err;
2603        if ((third & (~IPC_64)) == SETVAL)
2604                fourth.val = (int)pad;
2605        else
2606                fourth.__pad = (void *)A(pad);
2607        switch (third & (~IPC_64)) {
2608
2609        case IPC_INFO:
2610        case IPC_RMID:
2611        case SEM_INFO:
2612        case GETVAL:
2613        case GETPID:
2614        case GETNCNT:
2615        case GETZCNT:
2616        case GETALL:
2617        case SETALL:
2618        case SETVAL:
2619                err = sys_semctl(first, second, third, fourth);
2620                break;
2621
2622        case IPC_STAT:
2623        case SEM_STAT:
2624                if (third & IPC_64) {
2625                        struct semid64_ds s64;
2626                        struct semid64_ds32 *usp;
2627
2628                        usp = (struct semid64_ds32 *)A(pad);
2629                        fourth.__pad = &s64;
2630                        old_fs = get_fs();
2631                        set_fs(KERNEL_DS);
2632                        err = sys_semctl(first, second, third, fourth);
2633                        set_fs(old_fs);
2634                        err2 = copy_to_user(&usp->sem_perm, &s64.sem_perm,
2635                                            sizeof(struct ipc64_perm32));
2636                        err2 |= __put_user(s64.sem_otime, &usp->sem_otime);
2637                        err2 |= __put_user(s64.sem_ctime, &usp->sem_ctime);
2638                        err2 |= __put_user(s64.sem_nsems, &usp->sem_nsems);
2639                        if (err2)
2640                                err = -EFAULT;
2641                } else {
2642                        struct semid_ds s;
2643                        struct semid_ds32 *usp;
2644
2645                        usp = (struct semid_ds32 *)A(pad);
2646                        fourth.__pad = &s;
2647                        old_fs = get_fs();
2648                        set_fs(KERNEL_DS);
2649                        err = sys_semctl(first, second, third, fourth);
2650                        set_fs(old_fs);
2651                        err2 = copy_to_user(&usp->sem_perm, &s.sem_perm,
2652                                            sizeof(struct ipc_perm32));
2653                        err2 |= __put_user(s.sem_otime, &usp->sem_otime);
2654                        err2 |= __put_user(s.sem_ctime, &usp->sem_ctime);
2655                        err2 |= __put_user(s.sem_nsems, &usp->sem_nsems);
2656                        if (err2)
2657                                err = -EFAULT;
2658                }
2659                break;
2660 
2661        case IPC_SET:
2662                if (third & IPC_64) {
2663                        struct semid64_ds s64;
2664                        struct semid64_ds32 *usp;
2665
2666                        usp = (struct semid64_ds32 *)A(pad);
2667
2668                        err = get_user(s64.sem_perm.uid, &usp->sem_perm.uid);
2669                        err |= __get_user(s64.sem_perm.gid,
2670                                          &usp->sem_perm.gid);
2671                        err |= __get_user(s64.sem_perm.mode,
2672                                          &usp->sem_perm.mode);
2673                        if (err)
2674                                goto out;
2675                        fourth.__pad = &s64;
2676
2677                        old_fs = get_fs();
2678                        set_fs(KERNEL_DS);
2679                        err = sys_semctl(first, second, third, fourth);
2680                        set_fs(old_fs);
2681
2682                } else {
2683                        struct semid_ds s;
2684                        struct semid_ds32 *usp;
2685
2686                        usp = (struct semid_ds32 *)A(pad);
2687
2688                        err = get_user(s.sem_perm.uid, &usp->sem_perm.uid);
2689                        err |= __get_user(s.sem_perm.gid,
2690                                          &usp->sem_perm.gid);
2691                        err |= __get_user(s.sem_perm.mode,
2692                                          &usp->sem_perm.mode);
2693                        if (err)
2694                                goto out;
2695                        fourth.__pad = &s;
2696
2697                        old_fs = get_fs();
2698                        set_fs(KERNEL_DS);
2699                        err = sys_semctl(first, second, third, fourth);
2700                        set_fs(old_fs);
2701                }
2702                break;
2703        default:
2704                err = -EINVAL;
2705        }
2706out:
2707        return err;
2708}
2709
2710#define MAXBUF (64*1024)
2711
2712static int 
2713do_sys32_msgsnd(int first, int second, int third, void *uptr)
2714{
2715        struct msgbuf *p;
2716        struct msgbuf32 *up = (struct msgbuf32 *)uptr;
2717        mm_segment_t old_fs;
2718        int err;
2719
2720        if (second < 0 || (second >= MAXBUF-sizeof(struct msgbuf)))
2721                return -EINVAL;
2722
2723        p = kmalloc(second + sizeof(struct msgbuf), GFP_USER);
2724        if (!p)
2725                return -ENOMEM;
2726        err = get_user(p->mtype, &up->mtype);
2727        err |= copy_from_user(p->mtext, &up->mtext, second);
2728        if (err) {
2729                err = -EFAULT;
2730                goto out;
2731        }
2732        old_fs = get_fs();
2733        set_fs(KERNEL_DS);
2734        err = sys_msgsnd(first, p, second, third);
2735        set_fs(old_fs);
2736out:
2737        kfree(p);
2738        return err;
2739}
2740
2741static int
2742do_sys32_msgrcv(int first, int second, int msgtyp, int third,
2743                int version, void *uptr)
2744{
2745        struct msgbuf32 *up;
2746        struct msgbuf *p;
2747        mm_segment_t old_fs;
2748        int err;
2749
2750        if (second < 0 || (second >= MAXBUF-sizeof(struct msgbuf)))
2751                return -EINVAL;
2752
2753        if (!version) {
2754                struct ipc_kludge_32 *uipck = (struct ipc_kludge_32 *)uptr;
2755                struct ipc_kludge_32 ipck;
2756
2757                err = -EINVAL;
2758                if (!uptr)
2759                        goto out;
2760                err = -EFAULT;
2761                if (copy_from_user(&ipck, uipck, sizeof(struct ipc_kludge_32)))
2762                        goto out;
2763                uptr = (void *)A(ipck.msgp);
2764                msgtyp = ipck.msgtyp;
2765        }
2766        err = -ENOMEM;
2767        p = kmalloc(second + sizeof (struct msgbuf), GFP_USER);
2768        if (!p)
2769                goto out;
2770        old_fs = get_fs();
2771        set_fs(KERNEL_DS);
2772        err = sys_msgrcv(first, p, second, msgtyp, third);
2773        set_fs(old_fs);
2774        if (err < 0)
2775                goto free_then_out;
2776        up = (struct msgbuf32 *)uptr;
2777        if (put_user(p->mtype, &up->mtype) ||
2778            copy_to_user(&up->mtext, p->mtext, err))
2779                err = -EFAULT;
2780free_then_out:
2781        kfree(p);
2782out:
2783        return err;
2784}
2785
2786static int
2787do_sys32_msgctl(int first, int second, void *uptr)
2788{
2789        int err = -EINVAL, err2;
2790        mm_segment_t old_fs;
2791
2792        switch (second & (~IPC_64)) {
2793
2794        case IPC_INFO:
2795        case IPC_RMID:
2796        case MSG_INFO:
2797                err = sys_msgctl(first, second, (struct msqid_ds *)uptr);
2798                break;
2799
2800        case IPC_SET:
2801                if (second & IPC_64) {
2802                        struct msqid64_ds m64;
2803                        struct msqid64_ds32 *up = (struct msqid64_ds32 *)uptr;
2804
2805                        err2 = copy_from_user(&m64.msg_perm, &up->msg_perm,
2806                                              sizeof(struct ipc64_perm32));
2807                        err2 |= __get_user(m64.msg_qbytes, &up->msg_qbytes);
2808                        if (err2) {
2809                                err = -EFAULT;
2810                                break;
2811                        }
2812                        old_fs = get_fs();
2813                        set_fs(KERNEL_DS);
2814                        err = sys_msgctl(first, second,
2815                                         (struct msqid_ds *)&m64);
2816                        set_fs(old_fs);
2817                } else {
2818                        struct msqid_ds m;
2819                        struct msqid_ds32 *up = (struct msqid_ds32 *)uptr;
2820
2821                        err2 = copy_from_user(&m.msg_perm, &up->msg_perm,
2822                                              sizeof(struct ipc_perm32));
2823                        err2 |= __get_user(m.msg_qbytes, &up->msg_qbytes);
2824                        if (err2) {
2825                                err = -EFAULT;
2826                                break;
2827                        }
2828                        old_fs = get_fs();
2829                        set_fs(KERNEL_DS);
2830                        err = sys_msgctl(first, second, &m);
2831                        set_fs(old_fs);
2832                }
2833                break;
2834
2835        case IPC_STAT:
2836        case MSG_STAT:
2837                if (second & IPC_64) {
2838                        struct msqid64_ds m64;
2839                        struct msqid64_ds32 *up = (struct msqid64_ds32 *)uptr;
2840
2841                        old_fs = get_fs();
2842                        set_fs(KERNEL_DS);
2843                        err = sys_msgctl(first, second,
2844                                         (struct msqid_ds *)&m64);
2845                        set_fs(old_fs);
2846
2847                        err2 = copy_to_user(&up->msg_perm, &m64.msg_perm,
2848                                            sizeof(struct ipc64_perm32));
2849                        err2 |= __put_user(m64.msg_stime, &up->msg_stime);
2850                        err2 |= __put_user(m64.msg_rtime, &up->msg_rtime);
2851                        err2 |= __put_user(m64.msg_ctime, &up->msg_ctime);
2852                        err2 |= __put_user(m64.msg_cbytes, &up->msg_cbytes);
2853                        err2 |= __put_user(m64.msg_qnum, &up->msg_qnum);
2854                        err2 |= __put_user(m64.msg_qbytes, &up->msg_qbytes);
2855                        err2 |= __put_user(m64.msg_lspid, &up->msg_lspid);
2856                        err2 |= __put_user(m64.msg_lrpid, &up->msg_lrpid);
2857                        if (err2)
2858                                err = -EFAULT;
2859                } else {
2860                        struct msqid64_ds m;
2861                        struct msqid_ds32 *up = (struct msqid_ds32 *)uptr;
2862
2863                        old_fs = get_fs();
2864                        set_fs(KERNEL_DS);
2865                        err = sys_msgctl(first, second, (struct msqid_ds *)&m);
2866                        set_fs(old_fs);
2867
2868                        err2 = copy_to_user(&up->msg_perm, &m.msg_perm,
2869                                            sizeof(struct ipc_perm32));
2870                        err2 |= __put_user(m.msg_stime, &up->msg_stime);
2871                        err2 |= __put_user(m.msg_rtime, &up->msg_rtime);
2872                        err2 |= __put_user(m.msg_ctime, &up->msg_ctime);
2873                        err2 |= __put_user(m.msg_cbytes, &up->msg_cbytes);
2874                        err2 |= __put_user(m.msg_qnum, &up->msg_qnum);
2875                        err2 |= __put_user(m.msg_qbytes, &up->msg_qbytes);
2876                        err2 |= __put_user(m.msg_lspid, &up->msg_lspid);
2877                        err2 |= __put_user(m.msg_lrpid, &up->msg_lrpid);
2878                        if (err2)
2879                                err = -EFAULT;
2880                }
2881                break;
2882        }
2883        return err;
2884}
2885
2886static int
2887do_sys32_shmat(int first, int second, int third, int version, void *uptr)
2888{
2889        unsigned long raddr;
2890        u32 *uaddr = (u32 *)A((u32)third);
2891        int err = -EINVAL;
2892
2893        if (version == 1)
2894                return err;
2895        err = sys_shmat(first, uptr, second, &raddr);
2896        if (err)
2897                return err;
2898        err = put_user(raddr, uaddr);
2899        return err;
2900}
2901
2902static int
2903do_sys32_shmctl(int first, int second, void *uptr)
2904{
2905        int err = -EINVAL, err2;
2906        mm_segment_t old_fs;
2907
2908        switch (second & (~IPC_64)) {
2909
2910        case IPC_INFO:
2911        case IPC_RMID:
2912        case SHM_LOCK:
2913        case SHM_UNLOCK:
2914                err = sys_shmctl(first, second, (struct shmid_ds *)uptr);
2915                break;
2916        case IPC_SET:
2917                if (second & IPC_64) {
2918                        struct shmid64_ds32 *up = (struct shmid64_ds32 *)uptr;
2919                        struct shmid64_ds s64;
2920
2921                        err = get_user(s64.shm_perm.uid, &up->shm_perm.uid);
2922                        err |= __get_user(s64.shm_perm.gid, &up->shm_perm.gid);
2923                        err |= __get_user(s64.shm_perm.mode,
2924                                          &up->shm_perm.mode);
2925                        if (err)
2926                                break;
2927                        old_fs = get_fs();
2928                        set_fs(KERNEL_DS);
2929                        err = sys_shmctl(first, second,
2930                                         (struct shmid_ds *)&s64);
2931                        set_fs(old_fs);
2932                } else {
2933                        struct shmid_ds32 *up = (struct shmid_ds32 *)uptr;
2934                        struct shmid_ds s;
2935
2936                        err = get_user(s.shm_perm.uid, &up->shm_perm.uid);
2937                        err |= __get_user(s.shm_perm.gid, &up->shm_perm.gid);
2938                        err |= __get_user(s.shm_perm.mode, &up->shm_perm.mode);
2939                        if (err)
2940                                break;
2941                        old_fs = get_fs();
2942                        set_fs(KERNEL_DS);
2943                        err = sys_shmctl(first, second, &s);
2944                        set_fs(old_fs);
2945                }
2946                break;
2947
2948        case IPC_STAT:
2949        case SHM_STAT:
2950                if (second & IPC_64) {
2951                        struct shmid64_ds32 *up = (struct shmid64_ds32 *)uptr;
2952                        struct shmid64_ds s64;
2953
2954                        old_fs = get_fs();
2955                        set_fs(KERNEL_DS);
2956                        err = sys_shmctl(first, second,
2957                                         (struct shmid_ds *)&s64);
2958                        set_fs(old_fs);
2959                        if (err < 0)
2960                                break;
2961
2962                        err2 = copy_to_user(&up->shm_perm, &s64.shm_perm,
2963                                            sizeof(struct ipc64_perm32));
2964                        err2 |= __put_user(s64.shm_atime, &up->shm_atime);
2965                        err2 |= __put_user(s64.shm_dtime, &up->shm_dtime);
2966                        err2 |= __put_user(s64.shm_ctime, &up->shm_ctime);
2967                        err2 |= __put_user(s64.shm_segsz, &up->shm_segsz);
2968                        err2 |= __put_user(s64.shm_nattch, &up->shm_nattch);
2969                        err2 |= __put_user(s64.shm_cpid, &up->shm_cpid);
2970                        err2 |= __put_user(s64.shm_lpid, &up->shm_lpid);
2971                        if (err2)
2972                                err = -EFAULT;
2973                } else {
2974                        struct shmid_ds32 *up = (struct shmid_ds32 *)uptr;
2975                        struct shmid_ds s;
2976
2977                        old_fs = get_fs();
2978                        set_fs(KERNEL_DS);
2979                        err = sys_shmctl(first, second, &s);
2980                        set_fs(old_fs);
2981                        if (err < 0)
2982                                break;
2983
2984                        err2 = copy_to_user(&up->shm_perm, &s.shm_perm,
2985                                            sizeof(struct ipc_perm32));
2986                        err2 |= __put_user (s.shm_atime, &up->shm_atime);
2987                        err2 |= __put_user (s.shm_dtime, &up->shm_dtime);
2988                        err2 |= __put_user (s.shm_ctime, &up->shm_ctime);
2989                        err2 |= __put_user (s.shm_segsz, &up->shm_segsz);
2990                        err2 |= __put_user (s.shm_nattch, &up->shm_nattch);
2991                        err2 |= __put_user (s.shm_cpid, &up->shm_cpid);
2992                        err2 |= __put_user (s.shm_lpid, &up->shm_lpid);
2993                        if (err2)
2994                                err = -EFAULT;
2995                }
2996                break;
2997
2998        case SHM_INFO: {
2999                struct shm_info si;
3000                struct shm_info32 {
3001                        int used_ids;
3002                        u32 shm_tot, shm_rss, shm_swp;
3003                        u32 swap_attempts, swap_successes;
3004                } *uip = (struct shm_info32 *)uptr;
3005
3006                old_fs = get_fs();
3007                set_fs(KERNEL_DS);
3008                err = sys_shmctl(first, second, (struct shmid_ds *)&si);
3009                set_fs(old_fs);
3010                if (err < 0)
3011                        break;
3012                err2 = put_user(si.used_ids, &uip->used_ids);
3013                err2 |= __put_user(si.shm_tot, &uip->shm_tot);
3014                err2 |= __put_user(si.shm_rss, &uip->shm_rss);
3015                err2 |= __put_user(si.shm_swp, &uip->shm_swp);
3016                err2 |= __put_user(si.swap_attempts, &uip->swap_attempts);
3017                err2 |= __put_user(si.swap_successes, &uip->swap_successes);
3018                if (err2)
3019                        err = -EFAULT;
3020                break;
3021        }
3022        }
3023        return err;
3024}
3025
3026/*
3027 * Note: it is necessary to treat first_parm, second_parm, and
3028 * third_parm as unsigned ints, with the corresponding cast to a
3029 * signed int to insure that the proper conversion (sign extension)
3030 * between the register representation of a signed int (msr in 32-bit
3031 * mode) and the register representation of a signed int (msr in
3032 * 64-bit mode) is performed.
3033 */
3034asmlinkage long sys32_ipc(u32 call, u32 first_parm, u32 second_parm, u32 third_parm, u32 ptr, u32 fifth)
3035{
3036        int first  = (int)first_parm;
3037        int second = (int)second_parm;
3038        int third  = (int)third_parm;
3039        int version, err;
3040        
3041        PPCDBG(PPCDBG_SYS32, "sys32_ipc - entered - call=%x, parm1=%x, parm2=%x, parm3=%x, parm4=%x, parm5=%x \n", 
3042         call, first_parm, second_parm, third_parm, ptr, fifth);
3043
3044        version = call >> 16; /* hack for backward compatibility */
3045        call &= 0xffff;
3046
3047        switch (call) {
3048
3049        case SEMOP:
3050                /* struct sembuf is the same on 32 and 64bit :)) */
3051                err = sys_semop(first, (struct sembuf *)AA(ptr),
3052                                second);
3053                break;
3054        case SEMGET:
3055                err = sys_semget(first, second, third);
3056                break;
3057        case SEMCTL:
3058                err = do_sys32_semctl(first, second, third,
3059                                      (void *)AA(ptr));
3060                break;
3061
3062        case MSGSND:
3063                err = do_sys32_msgsnd(first, second, third,
3064                                      (void *)AA(ptr));
3065                break;
3066        case MSGRCV:
3067                err = do_sys32_msgrcv(first, second, fifth, third,
3068                                      version, (void *)AA(ptr));
3069                break;
3070        case MSGGET:
3071                err = sys_msgget((key_t)first, second);
3072                break;
3073        case MSGCTL:
3074                err = do_sys32_msgctl(first, second, (void *)AA(ptr));
3075                break;
3076
3077        case SHMAT:
3078                err = do_sys32_shmat(first, second, third,
3079                                     version, (void *)AA(ptr));
3080                break;
3081        case SHMDT: 
3082                err = sys_shmdt((char *)AA(ptr));
3083                break;
3084        case SHMGET:
3085                err = sys_shmget(first, second, third);
3086                break;
3087        case SHMCTL:
3088                err = do_sys32_shmctl(first, second, (void *)AA(ptr));
3089                break;
3090        default:
3091                err = -ENOSYS;
3092                break;
3093        }
3094
3095        
3096        PPCDBG(PPCDBG_SYS32, "sys32_ipc - exited w/ %d/0x%x \n", err, err);
3097        return err;
3098}
3099
3100/* stat syscall methods. */
3101extern asmlinkage int sys_stat(char* filename, struct __old_kernel_stat* statbuf);
3102
3103static int cp_old_stat32(struct inode* inode, struct __old_kernel_stat32* statbuf)
3104{
3105        static int warncount = 5;
3106        struct __old_kernel_stat32 tmp;
3107
3108        if (warncount) {
3109                warncount--;
3110                printk("VFS: Warning: %s using old stat() call. Recompile your binary.\n",
3111                        current->comm);
3112        }
3113
3114        tmp.st_dev = kdev_t_to_nr(inode->i_dev);
3115        tmp.st_ino = inode->i_ino;
3116        tmp.st_mode = inode->i_mode;
3117        tmp.st_nlink = inode->i_nlink;
3118        SET_OLDSTAT_UID(tmp, inode->i_uid);
3119        SET_OLDSTAT_GID(tmp, inode->i_gid);
3120        tmp.st_rdev = kdev_t_to_nr(inode->i_rdev);
3121        tmp.st_size = inode->i_size;
3122        tmp.st_atime = inode->i_atime;
3123        tmp.st_mtime = inode->i_mtime;
3124        tmp.st_ctime = inode->i_ctime;
3125        return copy_to_user(statbuf,&tmp,sizeof(tmp)) ? -EFAULT : 0;
3126}
3127
3128asmlinkage long sys32_stat(char* filename, struct __old_kernel_stat32* statbuf)
3129{
3130        struct nameidata nd;
3131        int error;
3132        
3133        PPCDBG(PPCDBG_SYS32X, "sys32_stat - entered - pid=%ld current=%lx comm=%s \n", current->pid, current, current->comm);
3134
3135        error = user_path_walk(filename, &nd);
3136        if (!error) {
3137                error = do_revalidate(nd.dentry);
3138                if (!error)
3139                        error = cp_old_stat32(nd.dentry->d_inode, statbuf);
3140                path_release(&nd);
3141        }
3142        
3143        PPCDBG(PPCDBG_SYS32X, "sys32_stat - exited - pid=%ld current=%lx comm=%s \n", current->pid, current, current->comm);
3144
3145        return error;
3146}
3147
3148asmlinkage long sys32_fstat(unsigned int fd, struct __old_kernel_stat32* statbuf)
3149{
3150        struct file *f;
3151        int err = -EBADF;
3152        
3153        PPCDBG(PPCDBG_SYS32X, "sys32_fstat - entered - pid=%ld current=%lx comm=%s \n", current->pid, current, current->comm);
3154
3155        f = fget(fd);
3156        if (f) {
3157                struct dentry * dentry = f->f_dentry;
3158
3159                err = do_revalidate(dentry);
3160                if (!err)
3161                        err = cp_old_stat32(dentry->d_inode, statbuf);
3162                fput(f);
3163        }
3164        
3165        PPCDBG(PPCDBG_SYS32X, "sys32_fstat - exited - pid=%ld current=%lx comm=%s \n", current->pid, current, current->comm);
3166
3167        return err;
3168}
3169
3170asmlinkage long sys32_lstat(char* filename, struct __old_kernel_stat32* statbuf)
3171{
3172        struct nameidata nd;
3173        int error;
3174        
3175        PPCDBG(PPCDBG_SYS32X, "sys32_lstat - entered - pid=%ld current=%lx comm=%s \n", current->pid, current, current->comm);
3176
3177        error = user_path_walk_link(filename, &nd);
3178        if (!error) {
3179                error = do_revalidate(nd.dentry);
3180                if (!error)
3181                        error = cp_old_stat32(nd.dentry->d_inode, statbuf);
3182
3183                path_release(&nd);
3184        }
3185        
3186        PPCDBG(PPCDBG_SYS32X, "sys32_lstat - exited - pid=%ld current=%lx comm=%s \n", current->pid, current, current->comm);
3187
3188        return error;
3189}
3190
3191extern asmlinkage ssize_t sys_sendfile(int out_fd, int in_fd, off_t* offset, size_t count);
3192
3193/* Note: it is necessary to treat out_fd and in_fd as unsigned ints, 
3194 * with the corresponding cast to a signed int to insure that the 
3195 * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
3196 * and the register representation of a signed int (msr in 64-bit mode) is performed.
3197 */
3198asmlinkage long sys32_sendfile(u32 out_fd, u32 in_fd, __kernel_off_t32* offset, u32 count)
3199{
3200        mm_segment_t old_fs = get_fs();
3201        int ret;
3202        off_t of;
3203        
3204        if (offset && get_user(of, offset))
3205                return -EFAULT;
3206                
3207        set_fs(KERNEL_DS);
3208        ret = sys_sendfile((int)out_fd, (int)in_fd, offset ? &of : NULL, count);
3209        set_fs(old_fs);
3210        
3211        if (offset && put_user(of, offset))
3212                return -EFAULT;
3213                
3214        return ret;
3215}
3216
3217extern asmlinkage int sys_setsockopt(int fd, int level, int optname, char *optval, int optlen);
3218
3219asmlinkage long sys32_setsockopt(int fd, int level, int optname, char* optval, int optlen)
3220{
3221        
3222        PPCDBG(PPCDBG_SYS32,"sys32_setsockopt - running - pid=%ld, comm=%s\n", current->pid, current->comm);
3223
3224        if (optname == SO_ATTACH_FILTER) {
3225                struct sock_fprog32 {
3226                        __u16 len;
3227                        __u32 filter;
3228                } *fprog32 = (struct sock_fprog32 *)optval;
3229                struct sock_fprog kfprog;
3230                struct sock_filter *kfilter;
3231                unsigned int fsize;
3232                mm_segment_t old_fs;
3233                __u32 uptr;
3234                int ret;
3235
3236                if (get_user(kfprog.len, &fprog32->len) ||
3237                    __get_user(uptr, &fprog32->filter))
3238                        return -EFAULT;
3239                kfprog.filter = (struct sock_filter *)A(uptr);
3240                fsize = kfprog.len * sizeof(struct sock_filter);
3241                kfilter = (struct sock_filter *)kmalloc(fsize, GFP_KERNEL);
3242                if (kfilter == NULL)
3243                        return -ENOMEM;
3244                if (copy_from_user(kfilter, kfprog.filter, fsize)) {
3245                        kfree(kfilter);
3246                        return -EFAULT;
3247                }
3248                kfprog.filter = kfilter;
3249                old_fs = get_fs();
3250                set_fs(KERNEL_DS);
3251                ret = sys_setsockopt(fd, level, optname,
3252                                     (char *)&kfprog, sizeof(kfprog));
3253                set_fs(old_fs);
3254                kfree(kfilter);
3255                return ret;
3256        }
3257        return sys_setsockopt(fd, level, optname, optval, optlen);
3258}
3259
3260
3261
3262
3263#define MAX_SOCK_ADDR   128             /* 108 for Unix domain -  16 for IP, 16 for IPX, 24 for IPv6, about 80 for AX.25 */
3264#define __CMSG32_NXTHDR(ctl, len, cmsg, cmsglen) __cmsg32_nxthdr((ctl),(len),(cmsg),(cmsglen))
3265#define CMSG32_NXTHDR(mhdr, cmsg, cmsglen) cmsg32_nxthdr((mhdr), (cmsg), (cmsglen))
3266
3267#define CMSG32_ALIGN(len) ( ((len)+sizeof(int)-1) & ~(sizeof(int)-1) )
3268
3269#define CMSG32_DATA(cmsg)       ((void *)((char *)(cmsg) + CMSG32_ALIGN(sizeof(struct cmsghdr32))))
3270#define CMSG32_SPACE(len) (CMSG32_ALIGN(sizeof(struct cmsghdr32)) + CMSG32_ALIGN(len))
3271#define CMSG32_LEN(len) (CMSG32_ALIGN(sizeof(struct cmsghdr32)) + (len))
3272#define __CMSG32_FIRSTHDR(ctl,len) ((len) >= sizeof(struct cmsghdr32) ? \
3273                                    (struct cmsghdr32 *)(ctl) : \
3274                                    (struct cmsghdr32 *)NULL)
3275#define CMSG32_FIRSTHDR(msg)    __CMSG32_FIRSTHDR((msg)->msg_control, (msg)->msg_controllen)
3276
3277struct msghdr32
3278{
3279        u32               msg_name;
3280        int               msg_namelen;
3281        u32               msg_iov;
3282        __kernel_size_t32 msg_iovlen;
3283        u32               msg_control;
3284        __kernel_size_t32 msg_controllen;
3285        unsigned          msg_flags;
3286};
3287
3288struct cmsghdr32
3289{
3290        __kernel_size_t32 cmsg_len;
3291        int               cmsg_level;
3292        int               cmsg_type;
3293};
3294
3295__inline__ struct cmsghdr32 *__cmsg32_nxthdr(void *__ctl, __kernel_size_t __size,
3296                                             struct cmsghdr32 *__cmsg, int __cmsg_len)
3297{
3298        struct cmsghdr32 * __ptr;
3299
3300        __ptr = (struct cmsghdr32 *)(((unsigned char *) __cmsg) +
3301                                     CMSG32_ALIGN(__cmsg_len));
3302        if ((unsigned long)((char*)(__ptr+1) - (char *) __ctl) > __size)
3303                return NULL;
3304
3305        return __ptr;
3306}
3307
3308__inline__ struct cmsghdr32 *cmsg32_nxthdr (struct msghdr *__msg,
3309                                            struct cmsghdr32 *__cmsg,
3310                                            int __cmsg_len)
3311{
3312        return __cmsg32_nxthdr(__msg->msg_control, __msg->msg_controllen,
3313                               __cmsg, __cmsg_len);
3314}
3315
3316extern __inline__ struct socket *socki_lookup(struct inode *inode)
3317{
3318        return &inode->u.socket_i;
3319}
3320
3321extern __inline__ struct socket *sockfd_lookup(int fd, int *err)
3322{
3323        struct file *file;
3324        struct inode *inode;
3325
3326        if (!(file = fget(fd)))
3327        {
3328                *err = -EBADF;
3329                return NULL;
3330        }
3331
3332        inode = file->f_dentry->d_inode;
3333        if (!inode || !inode->i_sock || !socki_lookup(inode))
3334        {
3335                *err = -ENOTSOCK;
3336                fput(file);
3337                return NULL;
3338        }
3339
3340        return socki_lookup(inode);
3341}
3342
3343extern __inline__ void sockfd_put(struct socket *sock)
3344{
3345        fput(sock->file);
3346}
3347
3348static inline int msghdr_from_user32_to_kern(struct msghdr *kmsg, struct msghdr32 *umsg)
3349{
3350        u32 tmp1, tmp2, tmp3;
3351        int err;
3352
3353        err = get_user(tmp1, &umsg->msg_name);
3354        err |= __get_user(tmp2, &umsg->msg_iov);
3355        err |= __get_user(tmp3, &umsg->msg_control);
3356        if (err)
3357                return -EFAULT;
3358
3359        kmsg->msg_name = (void *)A(tmp1);
3360        kmsg->msg_iov = (struct iovec *)A(tmp2);
3361        kmsg->msg_control = (void *)A(tmp3);
3362
3363        err = get_user(kmsg->msg_namelen, &umsg->msg_namelen);
3364        err |= get_user(kmsg->msg_iovlen, &umsg->msg_iovlen);
3365        err |= get_user(kmsg->msg_controllen, &umsg->msg_controllen);
3366        err |= get_user(kmsg->msg_flags, &umsg->msg_flags);
3367        
3368        return err;
3369}
3370
3371static inline int iov_from_user32_to_kern(struct iovec *kiov,
3372                                          struct iovec32 *uiov32,
3373                                          int niov)
3374{
3375        int tot_len = 0;
3376
3377        while(niov > 0) {
3378                u32 len, buf;
3379
3380                if(get_user(len, &uiov32->iov_len) ||
3381                   get_user(buf, &uiov32->iov_base)) {
3382                        tot_len = -EFAULT;
3383                        break;
3384                }
3385                tot_len += len;
3386                kiov->iov_base = (void *)A(buf);
3387                kiov->iov_len = (__kernel_size_t) len;
3388                uiov32++;
3389                kiov++;
3390                niov--;
3391        }
3392        return tot_len;
3393}
3394
3395/* I've named the args so it is easy to tell whose space the pointers are in. */
3396static int verify_iovec32(struct msghdr *kern_msg, struct iovec *kern_iov,
3397                          char *kern_address, int mode)
3398{
3399        int tot_len;
3400
3401        if(kern_msg->msg_namelen) {
3402                if(mode==VERIFY_READ) {
3403                        int err = move_addr_to_kernel(kern_msg->msg_name,
3404                                                      kern_msg->msg_namelen,
3405                                                      kern_address);
3406                        if(err < 0)
3407                                return err;
3408                }
3409                kern_msg->msg_name = kern_address;
3410        } else
3411                kern_msg->msg_name = NULL;
3412
3413        if(kern_msg->msg_iovlen > UIO_FASTIOV) {
3414                kern_iov = kmalloc(kern_msg->msg_iovlen * sizeof(struct iovec),
3415                                   GFP_KERNEL);
3416                if(!kern_iov)
3417                        return -ENOMEM;
3418        }
3419
3420        tot_len = iov_from_user32_to_kern(kern_iov,
3421                                          (struct iovec32 *)kern_msg->msg_iov,
3422                                          kern_msg->msg_iovlen);
3423        if(tot_len >= 0)
3424                kern_msg->msg_iov = kern_iov;
3425        else if(kern_msg->msg_iovlen > UIO_FASTIOV)
3426                kfree(kern_iov);
3427
3428        return tot_len;
3429}
3430
3431/* There is a lot of hair here because the alignment rules (and
3432 * thus placement) of cmsg headers and length are different for
3433 * 32-bit apps.  -DaveM
3434 */
3435static int cmsghdr_from_user32_to_kern(struct msghdr *kmsg,
3436                                       unsigned char *stackbuf, int stackbuf_size)
3437{
3438        struct cmsghdr32 *ucmsg;
3439        struct cmsghdr *kcmsg, *kcmsg_base;
3440        __kernel_size_t32 ucmlen;
3441        __kernel_size_t kcmlen, tmp;
3442
3443        kcmlen = 0;
3444        kcmsg_base = kcmsg = (struct cmsghdr *)stackbuf;
3445        ucmsg = CMSG32_FIRSTHDR(kmsg);
3446        while(ucmsg != NULL) {
3447                if(get_user(ucmlen, &ucmsg->cmsg_len))
3448                        return -EFAULT;
3449
3450                /* Catch bogons. */
3451                if(CMSG32_ALIGN(ucmlen) <
3452                   CMSG32_ALIGN(sizeof(struct cmsghdr32)))
3453                        return -EINVAL;
3454                if((unsigned long)(((char *)ucmsg - (char *)kmsg->msg_control)
3455                                   + ucmlen) > kmsg->msg_controllen)
3456                        return -EINVAL;
3457
3458                tmp = ((ucmlen - CMSG32_ALIGN(sizeof(*ucmsg))) +
3459                       CMSG_ALIGN(sizeof(struct cmsghdr)));
3460                kcmlen += tmp;
3461                ucmsg = CMSG32_NXTHDR(kmsg, ucmsg, ucmlen);
3462        }
3463        if (kcmlen == 0)
3464                return -EINVAL;
3465
3466        /* The kcmlen holds the 64-bit version of the control length.
3467         * It may not be modified as we do not stick it into the kmsg
3468         * until we have successfully copied over all of the data
3469         * from the user.
3470         */
3471        if (kcmlen > stackbuf_size)
3472                kcmsg_base = kcmsg = kmalloc(kcmlen, GFP_KERNEL);
3473        if (kcmsg == NULL)
3474                return -ENOBUFS;
3475
3476        /* Now copy them over neatly. */
3477        memset(kcmsg, 0, kcmlen);
3478        ucmsg = CMSG32_FIRSTHDR(kmsg);
3479        while (ucmsg != NULL) {
3480                __get_user(ucmlen, &ucmsg->cmsg_len);
3481                tmp = ((ucmlen - CMSG32_ALIGN(sizeof(*ucmsg))) +
3482                       CMSG_ALIGN(sizeof(struct cmsghdr)));
3483                kcmsg->cmsg_len = tmp;
3484                __get_user(kcmsg->cmsg_level, &ucmsg->cmsg_level);
3485                __get_user(kcmsg->cmsg_type, &ucmsg->cmsg_type);
3486
3487                /* Copy over the data. */
3488                if(copy_from_user(CMSG_DATA(kcmsg),
3489                                  CMSG32_DATA(ucmsg),
3490                                  (ucmlen - CMSG32_ALIGN(sizeof(*ucmsg)))))
3491                        goto out_free_efault;
3492
3493                /* Advance. */
3494                kcmsg = (struct cmsghdr *)((char *)kcmsg + CMSG_ALIGN(tmp));
3495                ucmsg = CMSG32_NXTHDR(kmsg, ucmsg, ucmlen);
3496        }
3497
3498        /* Ok, looks like we made it.  Hook it up and return success. */
3499        kmsg->msg_control = kcmsg_base;
3500        kmsg->msg_controllen = kcmlen;
3501        return 0;
3502
3503out_free_efault:
3504        if(kcmsg_base != (struct cmsghdr *)stackbuf)
3505                kfree(kcmsg_base);
3506        return -EFAULT;
3507}
3508
3509asmlinkage long sys32_sendmsg(int fd, struct msghdr32* user_msg, unsigned int user_flags)
3510{
3511        struct socket *sock;
3512        char address[MAX_SOCK_ADDR];
3513        struct iovec iov[UIO_FASTIOV];
3514        unsigned char ctl[sizeof(struct cmsghdr) + 20];
3515        unsigned char *ctl_buf = ctl;
3516        struct msghdr kern_msg;
3517        int err, total_len;
3518        
3519        PPCDBG(PPCDBG_SYS32, "sys32_sendmsg - entered - fd=%x, user_msg@=%p, user_flags=%x \n", fd, user_msg, user_flags);
3520
3521        if(msghdr_from_user32_to_kern(&kern_msg, user_msg))
3522                return -EFAULT;
3523        if(kern_msg.msg_iovlen > UIO_MAXIOV)
3524                return -EMSGSIZE;
3525        err = verify_iovec32(&kern_msg, iov, address, VERIFY_READ);
3526        if (err < 0)
3527                goto out;
3528        total_len = err;
3529
3530        if(kern_msg.msg_controllen) {
3531                err = cmsghdr_from_user32_to_kern(&kern_msg, ctl, sizeof(ctl));
3532                if(err)
3533                        goto out_freeiov;
3534                ctl_buf = kern_msg.msg_control;
3535        }
3536        kern_msg.msg_flags = user_flags;
3537
3538        sock = sockfd_lookup(fd, &err);
3539        if (sock != NULL) {
3540                if (sock->file->f_flags & O_NONBLOCK)
3541                        kern_msg.msg_flags |= MSG_DONTWAIT;
3542                err = sock_sendmsg(sock, &kern_msg, total_len);
3543                sockfd_put(sock);
3544        }
3545
3546        /* N.B. Use kfree here, as kern_msg.msg_controllen might change? */
3547        if(ctl_buf != ctl)
3548                kfree(ctl_buf);
3549out_freeiov:
3550        if(kern_msg.msg_iov != iov)
3551                kfree(kern_msg.msg_iov);
3552out:
3553        
3554        PPCDBG(PPCDBG_SYS32, "sys32_sendmsg - exited w/ %lx \n", err);
3555        return err;
3556}
3557
3558static void put_cmsg32(struct msghdr *kmsg, int level, int type,
3559                       int len, void *data)
3560{
3561        struct cmsghdr32 *cm = (struct cmsghdr32 *) kmsg->msg_control;
3562        struct cmsghdr32 cmhdr;
3563        int cmlen = CMSG32_LEN(len);
3564
3565        if (cm == NULL || kmsg->msg_controllen < sizeof(*cm)) {
3566                kmsg->msg_flags |= MSG_CTRUNC;
3567                return;
3568        }
3569
3570        if (kmsg->msg_controllen < cmlen) {
3571                kmsg->msg_flags |= MSG_CTRUNC;
3572                cmlen = kmsg->msg_controllen;
3573        }
3574        cmhdr.cmsg_level = level;
3575        cmhdr.cmsg_type = type;
3576        cmhdr.cmsg_len = cmlen;
3577
3578        if (copy_to_user(cm, &cmhdr, sizeof cmhdr))
3579                return;
3580        if (copy_to_user(CMSG32_DATA(cm), data, cmlen - sizeof(struct cmsghdr32)))
3581                return;
3582        cmlen = CMSG32_SPACE(len);
3583        kmsg->msg_control += cmlen;
3584        kmsg->msg_controllen -= cmlen;
3585}
3586
3587
3588static void scm_detach_fds32(struct msghdr *kmsg, struct scm_cookie *scm)
3589{
3590        struct cmsghdr32 *cm = (struct cmsghdr32 *) kmsg->msg_control;
3591        int fdmax = (kmsg->msg_controllen - sizeof(struct cmsghdr32)) / sizeof(int);
3592        int fdnum = scm->fp->count;
3593        struct file **fp = scm->fp->fp;
3594        int *cmfptr;
3595        int err = 0, i;
3596
3597        if (fdnum < fdmax)
3598                fdmax = fdnum;
3599
3600        for (i = 0, cmfptr = (int *) CMSG32_DATA(cm); i < fdmax; i++, cmfptr++) {
3601                int new_fd;
3602                err = get_unused_fd();
3603                if (err < 0)
3604                        break;
3605                new_fd = err;
3606                err = put_user(new_fd, cmfptr);
3607                if (err) {
3608                        put_unused_fd(new_fd);
3609                        break;
3610                }
3611                /* Bump the usage count and install the file. */
3612                get_file(fp[i]);
3613                fd_install(new_fd, fp[i]);
3614        }
3615
3616        if (i > 0) {
3617                int cmlen = CMSG32_LEN(i * sizeof(int));
3618                if (!err)
3619                        err = put_user(SOL_SOCKET, &cm->cmsg_level);
3620                if (!err)
3621                        err = put_user(SCM_RIGHTS, &cm->cmsg_type);
3622                if (!err)
3623                        err = put_user(cmlen, &cm->cmsg_len);
3624                if (!err) {
3625                        cmlen = CMSG32_SPACE(i * sizeof(int));
3626                        kmsg->msg_control += cmlen;
3627                        kmsg->msg_controllen -= cmlen;
3628                }
3629        }
3630        if (i < fdnum)
3631                kmsg->msg_flags |= MSG_CTRUNC;
3632
3633        /*
3634         * All of the files that fit in the message have had their
3635         * usage counts incremented, so we just free the list.
3636         */
3637        __scm_destroy(scm);
3638}
3639
3640/* In these cases we (currently) can just copy to data over verbatim
3641 * because all CMSGs created by the kernel have well defined types which
3642 * have the same layout in both the 32-bit and 64-bit API.  One must add
3643 * some special cased conversions here if we start sending control messages
3644 * with incompatible types.
3645 *
3646 * SCM_RIGHTS and SCM_CREDENTIALS are done by hand in recvmsg32 right after
3647 * we do our work.  The remaining cases are:
3648 *
3649 * SOL_IP       IP_PKTINFO      struct in_pktinfo       32-bit clean
3650 *              IP_TTL          int                     32-bit clean
3651 *              IP_TOS          __u8                    32-bit clean
3652 *              IP_RECVOPTS     variable length         32-bit clean
3653 *              IP_RETOPTS      variable length         32-bit clean
3654 *              (these last two are clean because the types are defined
3655 *               by the IPv4 protocol)
3656 *              IP_RECVERR      struct sock_extended_err +
3657 *                              struct sockaddr_in      32-bit clean
3658 * SOL_IPV6     IPV6_RECVERR    struct sock_extended_err +
3659 *                              struct sockaddr_in6     32-bit clean
3660 *              IPV6_PKTINFO    struct in6_pktinfo      32-bit clean
3661 *              IPV6_HOPLIMIT   int                     32-bit clean
3662 *              IPV6_FLOWINFO   u32                     32-bit clean
3663 *              IPV6_HOPOPTS    ipv6 hop exthdr         32-bit clean
3664 *              IPV6_DSTOPTS    ipv6 dst exthdr(s)      32-bit clean
3665 *              IPV6_RTHDR      ipv6 routing exthdr     32-bit clean
3666 *              IPV6_AUTHHDR    ipv6 auth exthdr        32-bit clean
3667 */
3668static void cmsg32_recvmsg_fixup(struct msghdr *kmsg, unsigned long orig_cmsg_uptr)
3669{
3670        unsigned char *workbuf, *wp;
3671        unsigned long bufsz, space_avail;
3672        struct cmsghdr *ucmsg;
3673
3674        bufsz = ((unsigned long)kmsg->msg_control) - orig_cmsg_uptr;
3675        space_avail = kmsg->msg_controllen + bufsz;
3676        wp = workbuf = kmalloc(bufsz, GFP_KERNEL);
3677        if(workbuf == NULL)
3678                goto fail;
3679
3680        /* To make this more sane we assume the kernel sends back properly
3681         * formatted control messages.  Because of how the kernel will truncate
3682         * the cmsg_len for MSG_TRUNC cases, we need not check that case either.
3683         */
3684        ucmsg = (struct cmsghdr *) orig_cmsg_uptr;
3685        while(((unsigned long)ucmsg) <=
3686              (((unsigned long)kmsg->msg_control) - sizeof(struct cmsghdr))) {
3687                struct cmsghdr32 *kcmsg32 = (struct cmsghdr32 *) wp;
3688                int clen64, clen32;
3689
3690                /* UCMSG is the 64-bit format CMSG entry in user-space.
3691                 * KCMSG32 is within the kernel space temporary buffer
3692                 * we use to convert into a 32-bit style CMSG.
3693                 */
3694                __get_user(kcmsg32->cmsg_len, &ucmsg->cmsg_len);
3695                __get_user(kcmsg32->cmsg_level, &ucmsg->cmsg_level);
3696                __get_user(kcmsg32->cmsg_type, &ucmsg->cmsg_type);
3697
3698                clen64 = kcmsg32->cmsg_len;
3699                copy_from_user(CMSG32_DATA(kcmsg32), CMSG_DATA(ucmsg),
3700                               clen64 - CMSG_ALIGN(sizeof(*ucmsg)));
3701                clen32 = ((clen64 - CMSG_ALIGN(sizeof(*ucmsg))) +
3702                          CMSG32_ALIGN(sizeof(struct cmsghdr32)));
3703                kcmsg32->cmsg_len = clen32;
3704
3705                switch (kcmsg32->cmsg_type) {
3706                        /*
3707                         * The timestamp type's data needs to be converted
3708                         * from 64-bit time values to 32-bit time values
3709                         */
3710                case SO_TIMESTAMP: {
3711                        __kernel_time_t32* ptr_time32 = CMSG32_DATA(kcmsg32);
3712                        __kernel_time_t*   ptr_time   = CMSG_DATA(ucmsg);
3713                        *ptr_time32     = *ptr_time;
3714                        *(ptr_time32+1) = *(ptr_time+1);
3715                        kcmsg32->cmsg_len -= 2*(sizeof(__kernel_time_t) -
3716                                                sizeof(__kernel_time_t32));
3717                }
3718                default:;
3719                }
3720
3721                ucmsg = (struct cmsghdr *) (((char *)ucmsg) + CMSG_ALIGN(clen64));
3722                wp = (((char *)kcmsg32) + CMSG32_ALIGN(kcmsg32->cmsg_len));
3723        }
3724
3725        /* Copy back fixed up data, and adjust pointers. */
3726        bufsz = (wp - workbuf);
3727        copy_to_user((void *)orig_cmsg_uptr, workbuf, bufsz);
3728
3729        kmsg->msg_control = (struct cmsghdr *)
3730                (((char *)orig_cmsg_uptr) + bufsz);
3731        kmsg->msg_controllen = space_avail - bufsz;
3732
3733        kfree(workbuf);
3734        return;
3735
3736fail:
3737        /* If we leave the 64-bit format CMSG chunks in there,
3738         * the application could get confused and crash.  So to
3739         * ensure greater recovery, we report no CMSGs.
3740         */
3741        kmsg->msg_controllen += bufsz;
3742        kmsg->msg_control = (void *) orig_cmsg_uptr;
3743}
3744
3745asmlinkage long sys32_recvmsg(int fd, struct msghdr32* user_msg, unsigned int user_flags)
3746{
3747        struct iovec iovstack[UIO_FASTIOV];
3748        struct msghdr kern_msg;
3749        char addr[MAX_SOCK_ADDR];
3750        struct socket *sock;
3751        struct iovec *iov = iovstack;
3752        struct sockaddr *uaddr;
3753        int *uaddr_len;
3754        unsigned long cmsg_ptr;
3755        int err, total_len, len = 0;
3756        
3757        PPCDBG(PPCDBG_SYS32, "sys32_recvmsg - entered - fd=%x, user_msg@=%p, user_flags=%x \n", fd, user_msg, user_flags);
3758
3759        if(msghdr_from_user32_to_kern(&kern_msg, user_msg))
3760                return -EFAULT;
3761        if(kern_msg.msg_iovlen > UIO_MAXIOV)
3762                return -EMSGSIZE;
3763
3764        uaddr = kern_msg.msg_name;
3765        uaddr_len = &user_msg->msg_namelen;
3766        err = verify_iovec32(&kern_msg, iov, addr, VERIFY_WRITE);
3767        if (err < 0)
3768                goto out;
3769        total_len = err;
3770
3771        cmsg_ptr = (unsigned long) kern_msg.msg_control;
3772        kern_msg.msg_flags = 0;
3773
3774        sock = sockfd_lookup(fd, &err);
3775        if (sock != NULL) {
3776                struct scm_cookie scm;
3777
3778                if (sock->file->f_flags & O_NONBLOCK)
3779                        user_flags |= MSG_DONTWAIT;
3780                memset(&scm, 0, sizeof(scm));
3781                err = sock->ops->recvmsg(sock, &kern_msg, total_len,
3782                                         user_flags, &scm);
3783                if(err >= 0) {
3784                        len = err;
3785                        if(!kern_msg.msg_control) {
3786                                if(sock->passcred || scm.fp)
3787                                        kern_msg.msg_flags |= MSG_CTRUNC;
3788                                if(scm.fp)
3789                                        __scm_destroy(&scm);
3790                        } else {
3791                                /* If recvmsg processing itself placed some
3792                                 * control messages into user space, it's is
3793                                 * using 64-bit CMSG processing, so we need
3794                                 * to fix it up before we tack on more stuff.
3795                                 */
3796                                if((unsigned long) kern_msg.msg_control != cmsg_ptr)
3797                                        cmsg32_recvmsg_fixup(&kern_msg, cmsg_ptr);
3798
3799                                /* Wheee... */
3800                                if(sock->passcred)
3801                                        put_cmsg32(&kern_msg,
3802                                                   SOL_SOCKET, SCM_CREDENTIALS,
3803                                                   sizeof(scm.creds), &scm.creds);
3804                                if(scm.fp != NULL)
3805                                        scm_detach_fds32(&kern_msg, &scm);
3806                        }
3807                }
3808                sockfd_put(sock);
3809        }
3810
3811  if (uaddr != NULL && err >= 0 && kern_msg.msg_namelen)
3812                err = move_addr_to_user(addr, kern_msg.msg_namelen, uaddr, uaddr_len);
3813        if(cmsg_ptr != 0 && err >= 0) {
3814                unsigned long ucmsg_ptr = ((unsigned long)kern_msg.msg_control);
3815                __kernel_size_t32 uclen = (__kernel_size_t32) (ucmsg_ptr - cmsg_ptr);
3816                err |= __put_user(uclen, &user_msg->msg_controllen);
3817        }
3818        if(err >= 0)
3819                err = __put_user(kern_msg.msg_flags, &user_msg->msg_flags);
3820        if(kern_msg.msg_iov != iov)
3821                kfree(kern_msg.msg_iov);
3822out:
3823        if(err < 0)
3824                return err;
3825        
3826        PPCDBG(PPCDBG_SYS32, "sys32_recvmsg - exited w/ %lx \n", len);
3827        return len;
3828}
3829
3830/*
3831 * count32() counts the number of arguments/envelopes
3832 */
3833static int count32(u32 * argv, int max)
3834{
3835        int i = 0;
3836
3837        if (argv != NULL) {
3838                for (;;) {
3839                        u32 p; int error;
3840
3841                        error = get_user(p,argv);
3842                        if (error)
3843                                return error;
3844                        if (!p)
3845                                break;
3846                        argv++;
3847                        if (++i > max)
3848                                return -E2BIG;
3849                }
3850        }
3851        return i;
3852}
3853
3854/*
3855 * 'copy_string32()' copies argument/envelope strings from user
3856 * memory to free pages in kernel mem. These are in a format ready
3857 * to be put directly into the top of new user memory.
3858 */
3859static int copy_strings32(int argc, u32 * argv, struct linux_binprm *bprm)
3860{
3861        while (argc-- > 0) {
3862                u32 str;
3863                int len;
3864                unsigned long pos;
3865
3866                if (get_user(str, argv + argc) ||
3867                    !str ||
3868                    !(len = strnlen_user((char *)A(str), bprm->p)))
3869                        return -EFAULT;
3870
3871                if (bprm->p < len)
3872                        return -E2BIG;
3873
3874                bprm->p -= len;
3875
3876                pos = bprm->p;
3877                while (len) {
3878                        char *kaddr;
3879                        struct page *page;
3880                        int offset, bytes_to_copy, new, err;
3881
3882                        offset = pos % PAGE_SIZE;
3883                        page = bprm->page[pos / PAGE_SIZE];
3884                        new = 0;
3885                        if (!page) {
3886                                page = alloc_page(GFP_USER);
3887                                bprm->page[pos / PAGE_SIZE] = page;
3888                                if (!page)
3889                                        return -ENOMEM;
3890                                new = 1;
3891                        }
3892                        kaddr = (char *)kmap(page);
3893
3894                        if (new && offset)
3895                                memset(kaddr, 0, offset);
3896                        bytes_to_copy = PAGE_SIZE - offset;
3897                        if (bytes_to_copy > len) {
3898                                bytes_to_copy = len;
3899                                if (new)
3900                                        memset(kaddr+offset+len, 0,
3901                                               PAGE_SIZE-offset-len);
3902                        }
3903
3904                        err = copy_from_user(kaddr + offset, (char *)A(str),
3905                                             bytes_to_copy);
3906                        flush_page_to_ram(page);
3907                        kunmap((unsigned long)kaddr);
3908
3909                        if (err)
3910                                return -EFAULT;
3911
3912                        pos += bytes_to_copy;
3913                        str += bytes_to_copy;
3914                        len -= bytes_to_copy;
3915                }
3916        }
3917        return 0;
3918}
3919
3920/*
3921 * sys32_execve() executes a new program.
3922 */
3923static int do_execve32(char * filename, u32 * argv, u32 * envp, struct pt_regs * regs)
3924{
3925        struct linux_binprm bprm;
3926        struct file * file;
3927        int retval;
3928        int i;
3929
3930        bprm.p = PAGE_SIZE*MAX_ARG_PAGES-sizeof(void *);
3931        memset(bprm.page, 0, MAX_ARG_PAGES * sizeof(bprm.page[0]));
3932
3933        file = open_exec(filename);
3934
3935        retval = PTR_ERR(file);
3936        if (IS_ERR(file))
3937                return retval;
3938
3939        bprm.file = file;
3940        bprm.filename = filename;
3941        bprm.sh_bang = 0;
3942        bprm.loader = 0;
3943        bprm.exec = 0;
3944        if ((bprm.argc = count32(argv, bprm.p / sizeof(u32))) < 0) {
3945                allow_write_access(file);
3946                fput(file);
3947                return bprm.argc;
3948        }
3949        if ((bprm.envc = count32(envp, bprm.p / sizeof(u32))) < 0) {
3950                allow_write_access(file);
3951                fput(file);
3952                return bprm.argc;
3953        }
3954  
3955        retval = prepare_binprm(&bprm);
3956        if (retval < 0)
3957                goto out;
3958        
3959        retval = copy_strings_kernel(1, &bprm.filename, &bprm);
3960        if (retval < 0)
3961                goto out;
3962
3963        bprm.exec = bprm.p;
3964        retval = copy_strings32(bprm.envc, envp, &bprm);
3965        if (retval < 0)
3966                goto out;
3967
3968        retval = copy_strings32(bprm.argc, argv, &bprm);
3969        if (retval < 0)
3970                goto out;
3971
3972        retval = search_binary_handler(&bprm, regs);
3973        if (retval >= 0)
3974                /* execve success */
3975                return retval;
3976
3977out:
3978        /* Something went wrong, return the inode and free the argument pages*/
3979        allow_write_access(bprm.file);
3980        if (bprm.file)
3981                fput(bprm.file);
3982
3983        for (i=0 ; i<MAX_ARG_PAGES ; i++)
3984                if (bprm.page[i])
3985                        __free_page(bprm.page[i]);
3986
3987        return retval;
3988}
3989
3990asmlinkage long sys32_execve(unsigned long a0, unsigned long a1, unsigned long a2,
3991                                               unsigned long a3, unsigned long a4, unsigned long a5,
3992                                               struct pt_regs *regs)
3993{
3994        int error;
3995        char * filename;
3996        
3997        filename = getname((char *) a0);
3998        error = PTR_ERR(filename);
3999        if (IS_ERR(filename))
4000                goto out;
4001        if (regs->msr & MSR_FP)
4002                giveup_fpu(current);
4003
4004        error = do_execve32(filename, (u32*) a1, (u32*) a2, regs);
4005
4006        if (error == 0)
4007                current->ptrace &= ~PT_DTRACE;
4008        putname(filename);
4009
4010out:
4011        return error;
4012}
4013
4014/* Set up a thread for executing a new program. */
4015void start_thread32(struct pt_regs* regs, unsigned long nip, unsigned long sp)
4016{
4017        set_fs(USER_DS);
4018        memset(regs->gpr, 0, sizeof(regs->gpr));
4019        memset(&regs->ctr, 0, 4 * sizeof(regs->ctr));
4020        regs->nip = nip;
4021        regs->gpr[1] = sp;
4022        regs->msr = MSR_USER32;
4023#ifndef CONFIG_SMP
4024        if (last_task_used_math == current)
4025                last_task_used_math = 0;
4026#endif
4027        current->thread.fpscr = 0;
4028}
4029
4030extern asmlinkage int sys_prctl(int option, unsigned long arg2, unsigned long arg3,
4031                                unsigned long arg4, unsigned long arg5);
4032
4033/* Note: it is necessary to treat option as an unsigned int, 
4034 * with the corresponding cast to a signed int to insure that the 
4035 * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
4036 * and the register representation of a signed int (msr in 64-bit mode) is performed.
4037 */
4038asmlinkage long sys32_prctl(u32 option, u32 arg2, u32 arg3, u32 arg4, u32 arg5)
4039{
4040        PPCDBG(PPCDBG_SYS32, "sys32_prctl - running - pid=%ld current=%lx comm=%s\n", current->pid, current, current->comm);
4041
4042        return sys_prctl((int)option,
4043                         (unsigned long) arg2,
4044                         (unsigned long) arg3,
4045                         (unsigned long) arg4,
4046                         (unsigned long) arg5);
4047}
4048
4049extern asmlinkage int sys_sched_rr_get_interval(pid_t pid, struct timespec *interval);
4050
4051/* Note: it is necessary to treat pid as an unsigned int, 
4052 * with the corresponding cast to a signed int to insure that the 
4053 * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
4054 * and the register representation of a signed int (msr in 64-bit mode) is performed.
4055 */
4056asmlinkage int sys32_sched_rr_get_interval(u32 pid, struct timespec32 *interval)
4057{
4058        struct timespec t;
4059        int ret;
4060        mm_segment_t old_fs = get_fs ();
4061        
4062        PPCDBG(PPCDBG_SYS32, "sys32_sched_rr_get_interval - entered - pid=%ld current=%lx comm=%s \n", current->pid, current, current->comm);
4063        
4064        set_fs (KERNEL_DS);
4065        ret = sys_sched_rr_get_interval((int)pid, &t);
4066        set_fs (old_fs);
4067        if (put_user (t.tv_sec, &interval->tv_sec) ||
4068            __put_user (t.tv_nsec, &interval->tv_nsec))
4069                return -EFAULT;
4070        
4071        PPCDBG(PPCDBG_SYS32, "sys32_sched_rr_get_interval - exited - pid=%ld current=%lx comm=%s \n", current->pid, current, current->comm);
4072        return ret;
4073}
4074
4075extern asmlinkage int sys_pciconfig_read(unsigned long bus, unsigned long dfn, unsigned long off,
4076                                         unsigned long len, unsigned char *buf);
4077
4078asmlinkage int sys32_pciconfig_read(u32 bus, u32 dfn, u32 off, u32 len, u32 ubuf)
4079{
4080        
4081        PPCDBG(PPCDBG_SYS32, "sys32_pciconfig_read - running - pid=%ld current=%lx comm=%s\n", current->pid, current, current->comm);
4082
4083        return sys_pciconfig_read((unsigned long) bus,
4084                                  (unsigned long) dfn,
4085                                  (unsigned long) off,
4086                                  (unsigned long) len,
4087                                  (unsigned char *)AA(ubuf));
4088}
4089
4090
4091
4092
4093extern asmlinkage int sys_pciconfig_write(unsigned long bus, unsigned long dfn, unsigned long off,
4094                                                                        unsigned long len, unsigned char *buf);
4095
4096asmlinkage int sys32_pciconfig_write(u32 bus, u32 dfn, u32 off, u32 len, u32 ubuf)
4097{
4098        
4099        PPCDBG(PPCDBG_SYS32, "sys32_pciconfig_write - running - pid=%ld current=%lx comm=%s \n", current->pid, current, current->comm);
4100
4101        return sys_pciconfig_write((unsigned long) bus,
4102                                   (unsigned long) dfn,
4103                                   (unsigned long) off,
4104                                   (unsigned long) len,
4105                                   (unsigned char *)AA(ubuf));
4106}
4107
4108extern asmlinkage int sys_newuname(struct new_utsname * name);
4109
4110asmlinkage int ppc64_newuname(struct new_utsname * name)
4111{
4112        int errno = sys_newuname(name);
4113
4114        if (current->personality == PER_LINUX32 && !errno) {
4115                if(copy_to_user(name->machine, "ppc\0\0", 8)) {
4116                        errno = -EFAULT;
4117                }
4118        }
4119        return errno;
4120}
4121
4122extern asmlinkage long sys_personality(unsigned long);
4123
4124asmlinkage int sys32_personality(unsigned long personality)
4125{
4126        int ret;
4127        if (current->personality == PER_LINUX32 && personality == PER_LINUX)
4128                personality = PER_LINUX32;
4129        ret = sys_personality(personality);
4130        if (ret == PER_LINUX32)
4131                ret = PER_LINUX;
4132        return ret;
4133}
4134
4135
4136
4137extern asmlinkage long sys_access(const char * filename, int mode);
4138
4139/* Note: it is necessary to treat mode as an unsigned int,
4140 * with the corresponding cast to a signed int to insure that the 
4141 * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
4142 * and the register representation of a signed int (msr in 64-bit mode) is performed.
4143 */
4144asmlinkage long sys32_access(const char * filename, u32 mode)
4145{
4146        return sys_access(filename, (int)mode);
4147}
4148
4149
4150extern asmlinkage int sys_clone(int p1, int p2, int p3, int p4, int p5, int p6, struct pt_regs *regs);
4151
4152/* Note: it is necessary to treat p1, p2, p3, p4, p5, p7, and regs as unsigned ints,
4153 * with the corresponding cast to a signed int to insure that the 
4154 * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
4155 * and the register representation of a signed int (msr in 64-bit mode) is performed.
4156 */
4157asmlinkage int sys32_clone(u32 p1, u32 p2, u32 p3, u32 p4, u32 p5, u32 p6, struct pt_regs *regs)
4158{
4159        return sys_clone((int)p1, (int)p2, (int)p3, (int)p4, (int)p5, (int)p6, regs);
4160}
4161
4162
4163extern asmlinkage long sys_creat(const char * pathname, int mode);
4164
4165/* Note: it is necessary to treat mode as an unsigned int,
4166 * with the corresponding cast to a signed int to insure that the 
4167 * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
4168 * and the register representation of a signed int (msr in 64-bit mode) is performed.
4169 */
4170asmlinkage long sys32_creat(const char * pathname, u32 mode)
4171{
4172        return sys_creat(pathname, (int)mode);
4173}
4174
4175
4176extern asmlinkage long sys_exit(int error_code);
4177
4178/* Note: it is necessary to treat error_code as an unsigned int,
4179 * with the corresponding cast to a signed int to insure that the 
4180 * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
4181 * and the register representation of a signed int (msr in 64-bit mode) is performed.
4182 */
4183asmlinkage long sys32_exit(u32 error_code)
4184{
4185        return sys_exit((int)error_code);
4186}
4187
4188
4189extern asmlinkage long sys_wait4(pid_t pid, unsigned int * stat_addr, int options, struct rusage * ru);
4190
4191/* Note: it is necessary to treat pid and options as unsigned ints,
4192 * with the corresponding cast to a signed int to insure that the 
4193 * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
4194 * and the register representation of a signed int (msr in 64-bit mode) is performed.
4195 */
4196asmlinkage long sys32_wait4(u32 pid, unsigned int * stat_addr, u32 options, struct rusage * ru)
4197{
4198        PPCDBG(PPCDBG_SYS32, "sys32_wait4 - running - pid=%ld current=%lx comm=%s \n", current->pid, current, current->comm);
4199
4200        if (!ru)
4201                return sys_wait4((int)pid, stat_addr, options, NULL);
4202        else {
4203                struct rusage r;
4204                int ret;
4205                unsigned int status;
4206                mm_segment_t old_fs = get_fs();
4207                
4208                set_fs (KERNEL_DS);
4209                ret = sys_wait4((int)pid, stat_addr ? &status : NULL, options, &r);
4210                set_fs (old_fs);
4211                if (put_rusage ((struct rusage32 *)ru, &r)) return -EFAULT;
4212                if (stat_addr && put_user (status, stat_addr))
4213                        return -EFAULT;
4214                return ret;
4215        }
4216        
4217}
4218
4219
4220extern asmlinkage long sys_waitpid(pid_t pid, unsigned int * stat_addr, int options);
4221
4222/* Note: it is necessary to treat pid and options as unsigned ints,
4223 * with the corresponding cast to a signed int to insure that the 
4224 * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
4225 * and the register representation of a signed int (msr in 64-bit mode) is performed.
4226 */
4227asmlinkage long sys32_waitpid(u32 pid, unsigned int * stat_addr, u32 options)
4228{
4229        return sys_waitpid((int)pid, stat_addr, (int)options);
4230}
4231
4232
4233extern asmlinkage int sys_fork(int p1, int p2, int p3, int p4, int p5, int p6, struct pt_regs *regs);
4234
4235/* Note: it is necessary to treat p1, p2, p3, p4, p5, and p6 as unsigned ints,
4236 * with the corresponding cast to a signed int to insure that the 
4237 * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
4238 * and the register representation of a signed int (msr in 64-bit mode) is performed.
4239 */
4240asmlinkage int sys32_fork(u32 p1, u32 p2, u32 p3, u32 p4, u32 p5, u32 p6, struct pt_regs *regs)
4241{
4242        return sys_fork((int)p1, (int)p2, (int)p3, (int)p4, (int)p5, (int)p6, regs);
4243}
4244
4245
4246extern asmlinkage long sys_getgroups(int gidsetsize, gid_t *grouplist);
4247
4248/* Note: it is necessary to treat gidsetsize as an unsigned int,
4249 * with the corresponding cast to a signed int to insure that the 
4250 * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
4251 * and the register representation of a signed int (msr in 64-bit mode) is performed.
4252 */
4253asmlinkage long sys32_getgroups(u32 gidsetsize, gid_t *grouplist)
4254{
4255        return sys_getgroups((int)gidsetsize, grouplist);
4256}
4257
4258
4259extern asmlinkage long sys_getpgid(pid_t pid);
4260
4261/* Note: it is necessary to treat pid as an unsigned int,
4262 * with the corresponding cast to a signed int to insure that the 
4263 * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
4264 * and the register representation of a signed int (msr in 64-bit mode) is performed.
4265 */
4266asmlinkage long sys32_getpgid(u32 pid)
4267{
4268        return sys_getpgid((int)pid);
4269}
4270
4271
4272extern asmlinkage long sys_getpriority(int which, int who);
4273
4274/* Note: it is necessary to treat which and who as unsigned ints,
4275 * with the corresponding cast to a signed int to insure that the 
4276 * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
4277 * and the register representation of a signed int (msr in 64-bit mode) is performed.
4278 */
4279asmlinkage long sys32_getpriority(u32 which, u32 who)
4280{
4281        return sys_getpriority((int)which, (int)who);
4282}
4283
4284
4285extern asmlinkage long sys_getsid(pid_t pid);
4286
4287/* Note: it is necessary to treat pid as an unsigned int,
4288 * with the corresponding cast to a signed int to insure that the 
4289 * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
4290 * and the register representation of a signed int (msr in 64-bit mode) is performed.
4291 */
4292asmlinkage long sys32_getsid(u32 pid)
4293{
4294        return sys_getsid((int)pid);
4295}
4296
4297
4298extern asmlinkage long sys_kill(int pid, int sig);
4299
4300/* Note: it is necessary to treat pid and sig as unsigned ints,
4301 * with the corresponding cast to a signed int to insure that the 
4302 * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
4303 * and the register representation of a signed int (msr in 64-bit mode) is performed.
4304 */
4305asmlinkage long sys32_kill(u32 pid, u32 sig)
4306{
4307        return sys_kill((int)pid, (int)sig);
4308}
4309
4310
4311extern asmlinkage long sys_mkdir(const char * pathname, int mode);
4312
4313/* Note: it is necessary to treat mode as an unsigned int,
4314 * with the corresponding cast to a signed int to insure that the 
4315 * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
4316 * and the register representation of a signed int (msr in 64-bit mode) is performed.
4317 */
4318asmlinkage long sys32_mkdir(const char * pathname, u32 mode)
4319{
4320        return sys_mkdir(pathname, (int)mode);
4321}
4322
4323
4324extern asmlinkage long sys_mlockall(int flags);
4325
4326/* Note: it is necessary to treat flags as an unsigned int,
4327 * with the corresponding cast to a signed int to insure that the 
4328 * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
4329 * and the register representation of a signed int (msr in 64-bit mode) is performed.
4330 */
4331asmlinkage long sys32_mlockall(u32 flags)
4332{
4333        return sys_mlockall((int)flags);
4334}
4335
4336
4337extern asmlinkage long sys_msync(unsigned long start, size_t len, int flags);
4338
4339/* Note: it is necessary to treat flags as an unsigned int,
4340 * with the corresponding cast to a signed int to insure that the 
4341 * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
4342 * and the register representation of a signed int (msr in 64-bit mode) is performed.
4343 */
4344asmlinkage long sys32_msync(unsigned long start, size_t len, u32 flags)
4345{
4346        return sys_msync(start, len, (int)flags);
4347}
4348
4349
4350extern asmlinkage long sys_nice(int increment);
4351
4352/* Note: it is necessary to treat increment as an unsigned int,
4353 * with the corresponding cast to a signed int to insure that the 
4354 * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
4355 * and the register representation of a signed int (msr in 64-bit mode) is performed.
4356 */
4357asmlinkage long sys32_nice(u32 increment)
4358{
4359        return sys_nice((int)increment);
4360}
4361
4362/*
4363 * This is just a version for 32-bit applications which does
4364 * not force O_LARGEFILE on.
4365 */
4366long sys32_open(const char * filename, int flags, int mode)
4367{
4368        char * tmp;
4369        int fd, error;
4370
4371        tmp = getname(filename);
4372        fd = PTR_ERR(tmp);
4373        if (!IS_ERR(tmp)) {
4374                fd = get_unused_fd();
4375                if (fd >= 0) {
4376                        struct file * f = filp_open(tmp, flags, mode);
4377                        error = PTR_ERR(f);
4378                        if (IS_ERR(f))
4379                                goto out_error;
4380                        fd_install(fd, f);
4381                }
4382out:
4383                putname(tmp);
4384        }
4385        return fd;
4386
4387out_error:
4388        put_unused_fd(fd);
4389        fd = error;
4390        goto out;
4391}
4392
4393extern asmlinkage long sys_readlink(const char * path, char * buf, int bufsiz);
4394
4395/* Note: it is necessary to treat bufsiz as an unsigned int,
4396 * with the corresponding cast to a signed int to insure that the 
4397 * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
4398 * and the register representation of a signed int (msr in 64-bit mode) is performed.
4399 */
4400asmlinkage long sys32_readlink(const char * path, char * buf, u32 bufsiz)
4401{
4402        return sys_readlink(path, buf, (int)bufsiz);
4403}
4404
4405
4406extern asmlinkage long sys_reboot(int magic1, int magic2, unsigned int cmd, void * arg);
4407
4408/* Note: it is necessary to treat magic1 and magic2 as unsigned ints,
4409 * with the corresponding cast to a signed int to insure that the 
4410 * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
4411 * and the register representation of a signed int (msr in 64-bit mode) is performed.
4412 */
4413asmlinkage long sys32_reboot(u32 magic1, u32 magic2, unsigned int cmd, void * arg)
4414{
4415        return sys_reboot((int)magic1, (int)magic2, cmd, arg);
4416}
4417
4418
4419extern asmlinkage long sys_sched_get_priority_max(int policy);
4420
4421/* Note: it is necessary to treat option as an unsigned int,
4422 * with the corresponding cast to a signed int to insure that the 
4423 * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
4424 * and the register representation of a signed int (msr in 64-bit mode) is performed.
4425 */
4426asmlinkage long sys32_sched_get_priority_max(u32 policy)
4427{
4428        return sys_sched_get_priority_max((int)policy);
4429}
4430
4431
4432extern asmlinkage long sys_sched_get_priority_min(int policy);
4433
4434/* Note: it is necessary to treat policy as an unsigned int,
4435 * with the corresponding cast to a signed int to insure that the 
4436 * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
4437 * and the register representation of a signed int (msr in 64-bit mode) is performed.
4438 */
4439asmlinkage long sys32_sched_get_priority_min(u32 policy)
4440{
4441        return sys_sched_get_priority_min((int)policy);
4442}
4443
4444
4445extern asmlinkage long sys_sched_getparam(pid_t pid, struct sched_param *param);
4446
4447/* Note: it is necessary to treat pid as an unsigned int,
4448 * with the corresponding cast to a signed int to insure that the 
4449 * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
4450 * and the register representation of a signed int (msr in 64-bit mode) is performed.
4451 */
4452asmlinkage long sys32_sched_getparam(u32 pid, struct sched_param *param)
4453{
4454        return sys_sched_getparam((int)pid, param);
4455}
4456
4457
4458extern asmlinkage long sys_sched_getscheduler(pid_t pid);
4459
4460/* Note: it is necessary to treat pid as an unsigned int,
4461 * with the corresponding cast to a signed int to insure that the 
4462 * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
4463 * and the register representation of a signed int (msr in 64-bit mode) is performed.
4464 */
4465asmlinkage long sys32_sched_getscheduler(u32 pid)
4466{
4467        return sys_sched_getscheduler((int)pid);
4468}
4469
4470
4471extern asmlinkage long sys_sched_setparam(pid_t pid, struct sched_param *param);
4472
4473/* Note: it is necessary to treat pid as an unsigned int,
4474 * with the corresponding cast to a signed int to insure that the 
4475 * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
4476 * and the register representation of a signed int (msr in 64-bit mode) is performed.
4477 */
4478asmlinkage long sys32_sched_setparam(u32 pid, struct sched_param *param)
4479{
4480        return sys_sched_setparam((int)pid, param);
4481}
4482
4483
4484extern asmlinkage long sys_sched_setscheduler(pid_t pid, int policy, struct sched_param *param);
4485
4486/* Note: it is necessary to treat pid and policy as unsigned ints,
4487 * with the corresponding cast to a signed int to insure that the 
4488 * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
4489 * and the register representation of a signed int (msr in 64-bit mode) is performed.
4490 */
4491asmlinkage long sys32_sched_setscheduler(u32 pid, u32 policy, struct sched_param *param)
4492{
4493        return sys_sched_setscheduler((int)pid, (int)policy, param);
4494}
4495
4496
4497extern asmlinkage long sys_setdomainname(char *name, int len);
4498
4499/* Note: it is necessary to treat len as an unsigned int,
4500 * with the corresponding cast to a signed int to insure that the 
4501 * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
4502 * and the register representation of a signed int (msr in 64-bit mode) is performed.
4503 */
4504asmlinkage long sys32_setdomainname(char *name, u32 len)
4505{
4506        return sys_setdomainname(name, (int)len);
4507}
4508
4509
4510extern asmlinkage long sys_setgroups(int gidsetsize, gid_t *grouplist);
4511
4512/* Note: it is necessary to treat gidsetsize as an unsigned int,
4513 * with the corresponding cast to a signed int to insure that the 
4514 * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
4515 * and the register representation of a signed int (msr in 64-bit mode) is performed.
4516 */
4517asmlinkage long sys32_setgroups(u32 gidsetsize, gid_t *grouplist)
4518{
4519        return sys_setgroups((int)gidsetsize, grouplist);
4520}
4521
4522
4523extern asmlinkage long sys_sethostname(char *name, int len);
4524
4525/* Note: it is necessary to treat len as an unsigned int,
4526 * with the corresponding cast to a signed int to insure that the 
4527 * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
4528 * and the register representation of a signed int (msr in 64-bit mode) is performed.
4529 */
4530asmlinkage long sys32_sethostname(char *name, u32 len)
4531{
4532        return sys_sethostname(name, (int)len);
4533}
4534
4535
4536extern asmlinkage long sys_setpgid(pid_t pid, pid_t pgid);
4537
4538/* Note: it is necessary to treat pid and pgid as unsigned ints,
4539 * with the corresponding cast to a signed int to insure that the 
4540 * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
4541 * and the register representation of a signed int (msr in 64-bit mode) is performed.
4542 */
4543asmlinkage long sys32_setpgid(u32 pid, u32 pgid)
4544{
4545        return sys_setpgid((int)pid, (int)pgid);
4546}
4547
4548
4549extern asmlinkage long sys_setpriority(int which, int who, int niceval);
4550
4551/* Note: it is necessary to treat which, who, and niceval as unsigned ints,
4552 * with the corresponding cast to a signed int to insure that the 
4553 * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
4554 * and the register representation of a signed int (msr in 64-bit mode) is performed.
4555 */
4556asmlinkage long sys32_setpriority(u32 which, u32 who, u32 niceval)
4557{
4558        return sys_setpriority((int)which, (int)who, (int)niceval);
4559}
4560
4561
4562extern asmlinkage long sys_ssetmask(int newmask);
4563
4564/* Note: it is necessary to treat newmask as an unsigned int,
4565 * with the corresponding cast to a signed int to insure that the 
4566 * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
4567 * and the register representation of a signed int (msr in 64-bit mode) is performed.
4568 */
4569asmlinkage long sys32_ssetmask(u32 newmask)
4570{
4571        return sys_ssetmask((int) newmask);
4572}
4573
4574
4575extern asmlinkage long sys_swapon(const char * specialfile, int swap_flags);
4576
4577/* Note: it is necessary to treat swap_flags as an unsigned int,
4578 * with the corresponding cast to a signed int to insure that the 
4579 * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
4580 * and the register representation of a signed int (msr in 64-bit mode) is performed.
4581 */
4582asmlinkage long sys32_swapon(const char * specialfile, u32 swap_flags)
4583{
4584        return sys_swapon(specialfile, (int)swap_flags);
4585}
4586
4587
4588extern asmlinkage long sys_syslog(int type, char * buf, int len);
4589
4590/* Note: it is necessary to treat type and len as an unsigned int,
4591 * with the corresponding cast to a signed int to insure that the 
4592 * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
4593 * and the register representation of a signed int (msr in 64-bit mode) is performed.
4594 */
4595asmlinkage long sys32_syslog(u32 type, char * buf, u32 len)
4596{
4597        return sys_syslog((int)type, buf, (int)len);
4598}
4599
4600
4601extern asmlinkage long sys_umask(int mask);
4602
4603/* Note: it is necessary to treat mask as an unsigned int,
4604 * with the corresponding cast to a signed int to insure that the 
4605 * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
4606 * and the register representation of a signed int (msr in 64-bit mode) is performed.
4607 */
4608asmlinkage long sys32_umask(u32 mask)
4609{
4610        return sys_umask((int)mask);
4611}
4612
4613
4614extern asmlinkage long sys_umount(char * name, int flags);
4615
4616/* Note: it is necessary to treat flags as an unsigned int,
4617 * with the corresponding cast to a signed int to insure that the 
4618 * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
4619 * and the register representation of a signed int (msr in 64-bit mode) is performed.
4620 */
4621asmlinkage long sys32_umount(char * name, u32 flags)
4622{
4623        return sys_umount(name, (int)flags);
4624}
4625
4626
4627extern asmlinkage int sys_vfork(int p1, int p2, int p3, int p4, int p5, int p6, struct pt_regs *regs);
4628
4629/* Note: it is necessary to treat p1, p2, p3, p4, p5, and p6 as unsigned ints,
4630 * with the corresponding cast to a signed int to insure that the 
4631 * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
4632 * and the register representation of a signed int (msr in 64-bit mode) is performed.
4633 */
4634asmlinkage int sys32_vfork(u32 p1, u32 p2, u32 p3, u32 p4, u32 p5, u32 p6, struct pt_regs *regs)
4635{
4636        return sys_vfork((int)p1, (int)p2, (int)p3, (int)p4, (int)p5, (int)p6, regs);
4637}
4638
4639extern asmlinkage ssize_t sys_pread(unsigned int fd, char * buf,
4640                                    size_t count, loff_t pos);
4641
4642extern asmlinkage ssize_t sys_pwrite(unsigned int fd, const char * buf,
4643                                     size_t count, loff_t pos);
4644
4645asmlinkage ssize_t32 sys32_pread(unsigned int fd, char *ubuf,
4646                                 __kernel_size_t32 count, u32 reg6, u32 poshi, u32 poslo)
4647{
4648        return sys_pread(fd, ubuf, count, ((loff_t)AA(poshi) << 32) | AA(poslo));
4649}
4650
4651asmlinkage ssize_t32 sys32_pwrite(unsigned int fd, char *ubuf,
4652                                  __kernel_size_t32 count, u32 reg6 ,u32 poshi, u32 poslo)
4653{
4654        return sys_pwrite(fd, ubuf, count, ((loff_t)AA(poshi) << 32) | AA(poslo));
4655}
4656
4657extern ssize_t sys_readahead(int fd, loff_t offset, size_t count);
4658
4659ssize_t32 sys32_readahead(int fd, u32 r4, u32 offhi, u32 offlo, u32 count)
4660{
4661        return sys_readahead(fd, ((loff_t)offhi << 32) | offlo, AA(count));
4662}
4663
4664extern asmlinkage long sys_truncate(const char * path, unsigned long length);
4665extern asmlinkage long sys_ftruncate(unsigned int fd, unsigned long length);
4666
4667asmlinkage int sys32_truncate64(const char * path, u32 reg4, unsigned long high, unsigned long low)
4668{
4669        if ((int)high < 0)
4670                return -EINVAL;
4671        else
4672                return sys_truncate(path, (high << 32) | low);
4673}
4674
4675asmlinkage int sys32_ftruncate64(unsigned int fd, u32 reg4, unsigned long high, unsigned long low)
4676{
4677        if ((int)high < 0)
4678                return -EINVAL;
4679        else
4680                return sys_ftruncate(fd, (high << 32) | low);
4681}
4682
4683
4684
4685asmlinkage long sys32_fcntl64(unsigned int fd, unsigned int cmd, unsigned long arg)
4686{
4687        if (cmd >= F_GETLK64 && cmd <= F_SETLKW64)
4688                return sys_fcntl(fd, cmd + F_GETLK - F_GETLK64, arg);
4689        return sys32_fcntl(fd, cmd, arg);
4690}
4691
4692
4693
4694
4695struct __sysctl_args32 {
4696        u32 name;
4697        int nlen;
4698        u32 oldval;
4699        u32 oldlenp;
4700        u32 newval;
4701        u32 newlen;
4702        u32 __unused[4];
4703};
4704
4705extern asmlinkage long sys32_sysctl(struct __sysctl_args32 *args)
4706{
4707        struct __sysctl_args32 tmp;
4708        int error;
4709        size_t oldlen, *oldlenp = NULL;
4710        unsigned long addr = (((long)&args->__unused[0]) + 7) & ~7;
4711
4712        if (copy_from_user(&tmp, args, sizeof(tmp)))
4713                return -EFAULT;
4714
4715        if (tmp.oldval && tmp.oldlenp) {
4716                /* Duh, this is ugly and might not work if sysctl_args
4717                   is in read-only memory, but do_sysctl does indirectly
4718                   a lot of uaccess in both directions and we'd have to
4719                   basically copy the whole sysctl.c here, and
4720                   glibc's __sysctl uses rw memory for the structure
4721                   anyway.  */
4722                if (get_user(oldlen, (u32 *)A(tmp.oldlenp)) ||
4723                    put_user(oldlen, (size_t *)addr))
4724                        return -EFAULT;
4725                oldlenp = (size_t *)addr;
4726        }
4727
4728        lock_kernel();
4729        error = do_sysctl((int *)A(tmp.name), tmp.nlen, (void *)A(tmp.oldval),
4730                          oldlenp, (void *)A(tmp.newval), tmp.newlen);
4731        unlock_kernel();
4732        if (oldlenp) {
4733                if (!error) {
4734                        if (get_user(oldlen, (size_t *)addr) ||
4735                            put_user(oldlen, (u32 *)A(tmp.oldlenp)))
4736                                error = -EFAULT;
4737                }
4738                copy_to_user(args->__unused, tmp.__unused, sizeof(tmp.__unused));
4739        }
4740        return error;
4741}
4742
4743asmlinkage long sys32_time(__kernel_time_t32* tloc)
4744{
4745        __kernel_time_t32 secs;
4746
4747        struct timeval tv;
4748
4749        do_gettimeofday( &tv );
4750        secs = tv.tv_sec;
4751
4752        if (tloc) {
4753                if (put_user(secs,tloc))
4754                        secs = -EFAULT;
4755        }
4756
4757        return secs;
4758}
4759
4760extern unsigned long sys_mmap(unsigned long addr, size_t len,
4761                              unsigned long prot, unsigned long flags,
4762                              unsigned long fd, off_t offset);
4763
4764unsigned long sys32_mmap2(unsigned long addr, size_t len,
4765                          unsigned long prot, unsigned long flags,
4766                          unsigned long fd, unsigned long pgoff)
4767{
4768        /* This should remain 12 even if PAGE_SIZE changes */
4769        return sys_mmap(addr, len, prot, flags, fd, pgoff << 12);
4770}
4771
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.