root/arch/sparc/kernel/sys_sparc.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. sys_getpagesize
  2. sparc_pipe
  3. quick_sys_write
  4. sys_ipc
  5. get_sparc_unmapped_area
  6. sys_mmap

   1 /* $Id: sys_sparc.c,v 1.11 1996/04/25 06:09:10 davem Exp $
   2  * linux/arch/sparc/kernel/sys_sparc.c
   3  *
   4  * This file contains various random system calls that
   5  * have a non-standard calling sequence on the Linux/sparc
   6  * platform.
   7  */
   8 
   9 #include <linux/errno.h>
  10 #include <linux/sched.h>
  11 #include <linux/mm.h>
  12 #include <linux/sem.h>
  13 #include <linux/msg.h>
  14 #include <linux/shm.h>
  15 #include <linux/stat.h>
  16 #include <linux/mman.h>
  17 
  18 #include <asm/segment.h>
  19 
  20 /* XXX Make this per-binary type, this way we can detect the type of
  21  * XXX a binary.  Every Sparc executable calls this very early on.
  22  */
  23 asmlinkage unsigned long sys_getpagesize(void)
     /* [previous][next][first][last][top][bottom][index][help] */
  24 {
  25         return PAGE_SIZE; /* Possibly older binaries want 8192 on sun4's? */
  26 }
  27 
  28 /*
  29  * sys_pipe() is the normal C calling standard for creating
  30  * a pipe. It's not the way unix traditionally does this, though.
  31  */
  32 asmlinkage int sparc_pipe(struct pt_regs *regs)
     /* [previous][next][first][last][top][bottom][index][help] */
  33 {
  34         int fd[2];
  35         int error;
  36 
  37         error = do_pipe(fd);
  38         if (error) {
  39                 return error;
  40         } else {
  41                 regs->u_regs[UREG_I1] = fd[1];
  42                 return fd[0];
  43         }
  44 }
  45 
  46 /* Note most sanity checking already done in sclow.S code. */
  47 asmlinkage int quick_sys_write(unsigned int fd, char *buf, unsigned int count)
     /* [previous][next][first][last][top][bottom][index][help] */
  48 {
  49         struct file *file = current->files->fd[fd];
  50         struct inode *inode = file->f_inode;
  51         int error;
  52 
  53         error = verify_area(VERIFY_READ, buf, count);
  54         if(error)
  55                 return error;
  56         /*
  57          * If data has been written to the file, remove the setuid and
  58          * the setgid bits. We do it anyway otherwise there is an
  59          * extremely exploitable race - does your OS get it right |->
  60          *
  61          * Set ATTR_FORCE so it will always be changed.
  62          */
  63         if (!suser() && (inode->i_mode & (S_ISUID | S_ISGID))) {
  64                 struct iattr newattrs;
  65                 newattrs.ia_mode = inode->i_mode & ~(S_ISUID | S_ISGID);
  66                 newattrs.ia_valid = ATTR_CTIME | ATTR_MODE | ATTR_FORCE;
  67                 notify_change(inode, &newattrs);
  68         }
  69 
  70         down(&inode->i_sem);
  71         error = file->f_op->write(inode,file,buf,count);
  72         up(&inode->i_sem);
  73         return error;
  74 }
  75 
  76 /* XXX do we need this crap? XXX */
  77 
  78 /*
  79  * sys_ipc() is the de-multiplexer for the SysV IPC calls..
  80  *
  81  * This is really horribly ugly.
  82  */
  83 asmlinkage int sys_ipc (uint call, int first, int second, int third, void *ptr, long fifth)
     /* [previous][next][first][last][top][bottom][index][help] */
  84 {
  85         int version;
  86 
  87         version = call >> 16; /* hack for backward compatibility */
  88         call &= 0xffff;
  89 
  90         if (call <= SEMCTL)
  91                 switch (call) {
  92                 case SEMOP:
  93                         return sys_semop (first, (struct sembuf *)ptr, second);
  94                 case SEMGET:
  95                         return sys_semget (first, second, third);
  96                 case SEMCTL: {
  97                         union semun fourth;
  98                         int err;
  99                         if (!ptr)
 100                                 return -EINVAL;
 101                         if ((err = verify_area (VERIFY_READ, ptr, sizeof(long))))
 102                                 return err;
 103                         fourth.__pad = (void *) get_fs_long(ptr);
 104                         return sys_semctl (first, second, third, fourth);
 105                         }
 106                 default:
 107                         return -EINVAL;
 108                 }
 109         if (call <= MSGCTL) 
 110                 switch (call) {
 111                 case MSGSND:
 112                         return sys_msgsnd (first, (struct msgbuf *) ptr, 
 113                                            second, third);
 114                 case MSGRCV:
 115                         switch (version) {
 116                         case 0: {
 117                                 struct ipc_kludge tmp;
 118                                 int err;
 119                                 if (!ptr)
 120                                         return -EINVAL;
 121                                 if ((err = verify_area (VERIFY_READ, ptr, sizeof(tmp))))
 122                                         return err;
 123                                 memcpy_fromfs (&tmp,(struct ipc_kludge *) ptr,
 124                                                sizeof (tmp));
 125                                 return sys_msgrcv (first, tmp.msgp, second, tmp.msgtyp, third);
 126                                 }
 127                         case 1: default:
 128                                 return sys_msgrcv (first, (struct msgbuf *) ptr, second, fifth, third);
 129                         }
 130                 case MSGGET:
 131                         return sys_msgget ((key_t) first, second);
 132                 case MSGCTL:
 133                         return sys_msgctl (first, second, (struct msqid_ds *) ptr);
 134                 default:
 135                         return -EINVAL;
 136                 }
 137         if (call <= SHMCTL) 
 138                 switch (call) {
 139                 case SHMAT:
 140                         switch (version) {
 141                         case 0: default: {
 142                                 ulong raddr;
 143                                 int err;
 144                                 if ((err = verify_area(VERIFY_WRITE, (ulong*) third, sizeof(ulong))))
 145                                         return err;
 146                                 err = sys_shmat (first, (char *) ptr, second, &raddr);
 147                                 if (err)
 148                                         return err;
 149                                 put_fs_long (raddr, (ulong *) third);
 150                                 return 0;
 151                                 }
 152                         case 1: /* iBCS2 emulator entry point */
 153                                 if (get_fs() != get_ds())
 154                                         return -EINVAL;
 155                                 return sys_shmat (first, (char *) ptr, second, (ulong *) third);
 156                         }
 157                 case SHMDT: 
 158                         return sys_shmdt ((char *)ptr);
 159                 case SHMGET:
 160                         return sys_shmget (first, second, third);
 161                 case SHMCTL:
 162                         return sys_shmctl (first, second, (struct shmid_ds *) ptr);
 163                 default:
 164                         return -EINVAL;
 165                 }
 166         return -EINVAL;
 167 }
 168 
 169 unsigned long get_sparc_unmapped_area(unsigned long len)
     /* [previous][next][first][last][top][bottom][index][help] */
 170 {
 171         unsigned long addr = 0xE8000000UL;
 172         struct vm_area_struct * vmm;
 173 
 174         if (len > TASK_SIZE)
 175                 return 0;
 176         for (vmm = find_vma(current, addr); ; vmm = vmm->vm_next) {
 177                 /* At this point:  (!vmm || addr < vmm->vm_end). */
 178                 if (TASK_SIZE - len < addr)
 179                         return 0;
 180                 if (!vmm || addr + len <= vmm->vm_start)
 181                         return addr;
 182                 addr = vmm->vm_end;
 183         }
 184 }
 185 
 186 /* Linux version of mmap */
 187 asmlinkage unsigned long sys_mmap(unsigned long addr, unsigned long len,
     /* [previous][next][first][last][top][bottom][index][help] */
 188         unsigned long prot, unsigned long flags, unsigned long fd,
 189         unsigned long off)
 190 {
 191         struct file * file = NULL;
 192         long retval;
 193 
 194         if (!(flags & MAP_ANONYMOUS)) {
 195                 if (fd >= NR_OPEN || !(file = current->files->fd[fd])){
 196                         return -EBADF;
 197             }
 198         }
 199         if(!(flags & MAP_FIXED) && !addr) {
 200                 addr = get_sparc_unmapped_area(len);
 201                 if(!addr){
 202                         return -ENOMEM;
 203                 }
 204         }
 205         retval = do_mmap(file, addr, len, prot, flags, off);
 206         return retval;
 207 }

/* [previous][next][first][last][top][bottom][index][help] */