syscalls.c 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  1. /*
  2. * arch/v850/kernel/syscalls.c -- Various system-call definitions not
  3. * defined in machine-independent code
  4. *
  5. * Copyright (C) 2001,02 NEC Corporation
  6. * Copyright (C) 2001,02 Miles Bader <miles@gnu.org>
  7. *
  8. * This file is subject to the terms and conditions of the GNU General
  9. * Public License. See the file COPYING in the main directory of this
  10. * archive for more details.
  11. *
  12. * This file was derived the ppc version, arch/ppc/kernel/syscalls.c
  13. * ... which was derived from "arch/i386/kernel/sys_i386.c" by Gary Thomas;
  14. * modified by Cort Dougan (cort@cs.nmt.edu)
  15. * and Paul Mackerras (paulus@cs.anu.edu.au).
  16. */
  17. #include <linux/errno.h>
  18. #include <linux/mm.h>
  19. #include <linux/smp.h>
  20. #include <linux/syscalls.h>
  21. #include <linux/sem.h>
  22. #include <linux/msg.h>
  23. #include <linux/shm.h>
  24. #include <linux/stat.h>
  25. #include <linux/mman.h>
  26. #include <linux/sys.h>
  27. #include <linux/ipc.h>
  28. #include <linux/utsname.h>
  29. #include <linux/file.h>
  30. #include <asm/uaccess.h>
  31. #include <asm/unistd.h>
  32. /*
  33. * sys_ipc() is the de-multiplexer for the SysV IPC calls..
  34. *
  35. * This is really horribly ugly.
  36. */
  37. int
  38. sys_ipc (uint call, int first, int second, int third, void *ptr, long fifth)
  39. {
  40. int version, ret;
  41. version = call >> 16; /* hack for backward compatibility */
  42. call &= 0xffff;
  43. ret = -EINVAL;
  44. switch (call) {
  45. case SEMOP:
  46. ret = sys_semop (first, (struct sembuf *)ptr, second);
  47. break;
  48. case SEMGET:
  49. ret = sys_semget (first, second, third);
  50. break;
  51. case SEMCTL:
  52. {
  53. union semun fourth;
  54. if (!ptr)
  55. break;
  56. if ((ret = access_ok(VERIFY_READ, ptr, sizeof(long)) ? 0 : -EFAULT)
  57. || (ret = get_user(fourth.__pad, (void **)ptr)))
  58. break;
  59. ret = sys_semctl (first, second, third, fourth);
  60. break;
  61. }
  62. case MSGSND:
  63. ret = sys_msgsnd (first, (struct msgbuf *) ptr, second, third);
  64. break;
  65. case MSGRCV:
  66. switch (version) {
  67. case 0: {
  68. struct ipc_kludge tmp;
  69. if (!ptr)
  70. break;
  71. if ((ret = access_ok(VERIFY_READ, ptr, sizeof(tmp)) ? 0 : -EFAULT)
  72. || (ret = copy_from_user(&tmp,
  73. (struct ipc_kludge *) ptr,
  74. sizeof (tmp))))
  75. break;
  76. ret = sys_msgrcv (first, tmp.msgp, second, tmp.msgtyp,
  77. third);
  78. break;
  79. }
  80. default:
  81. ret = sys_msgrcv (first, (struct msgbuf *) ptr,
  82. second, fifth, third);
  83. break;
  84. }
  85. break;
  86. case MSGGET:
  87. ret = sys_msgget ((key_t) first, second);
  88. break;
  89. case MSGCTL:
  90. ret = sys_msgctl (first, second, (struct msqid_ds *) ptr);
  91. break;
  92. case SHMAT:
  93. switch (version) {
  94. default: {
  95. ulong raddr;
  96. if ((ret = access_ok(VERIFY_WRITE, (ulong*) third,
  97. sizeof(ulong)) ? 0 : -EFAULT))
  98. break;
  99. ret = do_shmat (first, (char *) ptr, second, &raddr);
  100. if (ret)
  101. break;
  102. ret = put_user (raddr, (ulong *) third);
  103. break;
  104. }
  105. case 1: /* iBCS2 emulator entry point */
  106. if (!segment_eq(get_fs(), get_ds()))
  107. break;
  108. ret = do_shmat (first, (char *) ptr, second,
  109. (ulong *) third);
  110. break;
  111. }
  112. break;
  113. case SHMDT:
  114. ret = sys_shmdt ((char *)ptr);
  115. break;
  116. case SHMGET:
  117. ret = sys_shmget (first, second, third);
  118. break;
  119. case SHMCTL:
  120. ret = sys_shmctl (first, second, (struct shmid_ds *) ptr);
  121. break;
  122. }
  123. return ret;
  124. }
  125. static inline unsigned long
  126. do_mmap2 (unsigned long addr, size_t len,
  127. unsigned long prot, unsigned long flags,
  128. unsigned long fd, unsigned long pgoff)
  129. {
  130. struct file * file = NULL;
  131. int ret = -EBADF;
  132. flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
  133. if (! (flags & MAP_ANONYMOUS)) {
  134. if (!(file = fget (fd)))
  135. goto out;
  136. }
  137. down_write (&current->mm->mmap_sem);
  138. ret = do_mmap_pgoff (file, addr, len, prot, flags, pgoff);
  139. up_write (&current->mm->mmap_sem);
  140. if (file)
  141. fput (file);
  142. out:
  143. return ret;
  144. }
  145. unsigned long sys_mmap2 (unsigned long addr, size_t len,
  146. unsigned long prot, unsigned long flags,
  147. unsigned long fd, unsigned long pgoff)
  148. {
  149. return do_mmap2 (addr, len, prot, flags, fd, pgoff);
  150. }
  151. unsigned long sys_mmap (unsigned long addr, size_t len,
  152. unsigned long prot, unsigned long flags,
  153. unsigned long fd, off_t offset)
  154. {
  155. int err = -EINVAL;
  156. if (offset & ~PAGE_MASK)
  157. goto out;
  158. err = do_mmap2 (addr, len, prot, flags, fd, offset >> PAGE_SHIFT);
  159. out:
  160. return err;
  161. }
  162. /*
  163. * Do a system call from kernel instead of calling sys_execve so we
  164. * end up with proper pt_regs.
  165. */
  166. int kernel_execve(const char *filename, char *const argv[], char *const envp[])
  167. {
  168. register char *__a __asm__ ("r6") = filename;
  169. register void *__b __asm__ ("r7") = argv;
  170. register void *__c __asm__ ("r8") = envp;
  171. register unsigned long __syscall __asm__ ("r12") = __NR_execve;
  172. register unsigned long __ret __asm__ ("r10");
  173. __asm__ __volatile__ ("trap 0"
  174. : "=r" (__ret), "=r" (__syscall)
  175. : "1" (__syscall), "r" (__a), "r" (__b), "r" (__c)
  176. : "r1", "r5", "r11", "r13", "r14",
  177. "r15", "r16", "r17", "r18", "r19");
  178. return __ret;
  179. }