sys_sh.c 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234
  1. /*
  2. * linux/arch/sh/kernel/sys_sh.c
  3. *
  4. * This file contains various random system calls that
  5. * have a non-standard calling sequence on the Linux/SuperH
  6. * platform.
  7. *
  8. * Taken from i386 version.
  9. */
  10. #include <linux/errno.h>
  11. #include <linux/sched.h>
  12. #include <linux/mm.h>
  13. #include <linux/smp.h>
  14. #include <linux/sem.h>
  15. #include <linux/msg.h>
  16. #include <linux/shm.h>
  17. #include <linux/stat.h>
  18. #include <linux/syscalls.h>
  19. #include <linux/mman.h>
  20. #include <linux/file.h>
  21. #include <linux/utsname.h>
  22. #include <linux/module.h>
  23. #include <linux/fs.h>
  24. #include <linux/ipc.h>
  25. #include <asm/syscalls.h>
  26. #include <asm/uaccess.h>
  27. #include <asm/unistd.h>
  28. #include <asm/cacheflush.h>
  29. #include <asm/cachectl.h>
  30. static inline long
  31. do_mmap2(unsigned long addr, unsigned long len, unsigned long prot,
  32. unsigned long flags, int fd, unsigned long pgoff)
  33. {
  34. int error = -EBADF;
  35. struct file *file = NULL;
  36. flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
  37. if (!(flags & MAP_ANONYMOUS)) {
  38. file = fget(fd);
  39. if (!file)
  40. goto out;
  41. }
  42. down_write(&current->mm->mmap_sem);
  43. error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
  44. up_write(&current->mm->mmap_sem);
  45. if (file)
  46. fput(file);
  47. out:
  48. return error;
  49. }
  50. asmlinkage int old_mmap(unsigned long addr, unsigned long len,
  51. unsigned long prot, unsigned long flags,
  52. int fd, unsigned long off)
  53. {
  54. if (off & ~PAGE_MASK)
  55. return -EINVAL;
  56. return do_mmap2(addr, len, prot, flags, fd, off>>PAGE_SHIFT);
  57. }
  58. asmlinkage long sys_mmap2(unsigned long addr, unsigned long len,
  59. unsigned long prot, unsigned long flags,
  60. unsigned long fd, unsigned long pgoff)
  61. {
  62. /*
  63. * The shift for mmap2 is constant, regardless of PAGE_SIZE
  64. * setting.
  65. */
  66. if (pgoff & ((1 << (PAGE_SHIFT - 12)) - 1))
  67. return -EINVAL;
  68. pgoff >>= PAGE_SHIFT - 12;
  69. return do_mmap2(addr, len, prot, flags, fd, pgoff);
  70. }
  71. /*
  72. * sys_ipc() is the de-multiplexer for the SysV IPC calls..
  73. *
  74. * This is really horribly ugly.
  75. */
  76. asmlinkage int sys_ipc(uint call, int first, int second,
  77. int third, void __user *ptr, long fifth)
  78. {
  79. int version, ret;
  80. version = call >> 16; /* hack for backward compatibility */
  81. call &= 0xffff;
  82. if (call <= SEMTIMEDOP)
  83. switch (call) {
  84. case SEMOP:
  85. return sys_semtimedop(first,
  86. (struct sembuf __user *)ptr,
  87. second, NULL);
  88. case SEMTIMEDOP:
  89. return sys_semtimedop(first,
  90. (struct sembuf __user *)ptr, second,
  91. (const struct timespec __user *)fifth);
  92. case SEMGET:
  93. return sys_semget (first, second, third);
  94. case SEMCTL: {
  95. union semun fourth;
  96. if (!ptr)
  97. return -EINVAL;
  98. if (get_user(fourth.__pad, (void __user * __user *) ptr))
  99. return -EFAULT;
  100. return sys_semctl (first, second, third, fourth);
  101. }
  102. default:
  103. return -EINVAL;
  104. }
  105. if (call <= MSGCTL)
  106. switch (call) {
  107. case MSGSND:
  108. return sys_msgsnd (first, (struct msgbuf __user *) ptr,
  109. second, third);
  110. case MSGRCV:
  111. switch (version) {
  112. case 0:
  113. {
  114. struct ipc_kludge tmp;
  115. if (!ptr)
  116. return -EINVAL;
  117. if (copy_from_user(&tmp,
  118. (struct ipc_kludge __user *) ptr,
  119. sizeof (tmp)))
  120. return -EFAULT;
  121. return sys_msgrcv (first, tmp.msgp, second,
  122. tmp.msgtyp, third);
  123. }
  124. default:
  125. return sys_msgrcv (first,
  126. (struct msgbuf __user *) ptr,
  127. second, fifth, third);
  128. }
  129. case MSGGET:
  130. return sys_msgget ((key_t) first, second);
  131. case MSGCTL:
  132. return sys_msgctl (first, second,
  133. (struct msqid_ds __user *) ptr);
  134. default:
  135. return -EINVAL;
  136. }
  137. if (call <= SHMCTL)
  138. switch (call) {
  139. case SHMAT:
  140. switch (version) {
  141. default: {
  142. ulong raddr;
  143. ret = do_shmat (first, (char __user *) ptr,
  144. second, &raddr);
  145. if (ret)
  146. return ret;
  147. return put_user (raddr, (ulong __user *) third);
  148. }
  149. case 1: /* iBCS2 emulator entry point */
  150. if (!segment_eq(get_fs(), get_ds()))
  151. return -EINVAL;
  152. return do_shmat (first, (char __user *) ptr,
  153. second, (ulong *) third);
  154. }
  155. case SHMDT:
  156. return sys_shmdt ((char __user *)ptr);
  157. case SHMGET:
  158. return sys_shmget (first, second, third);
  159. case SHMCTL:
  160. return sys_shmctl (first, second,
  161. (struct shmid_ds __user *) ptr);
  162. default:
  163. return -EINVAL;
  164. }
  165. return -EINVAL;
  166. }
  167. /* sys_cacheflush -- flush (part of) the processor cache. */
  168. asmlinkage int sys_cacheflush(unsigned long addr, unsigned long len, int op)
  169. {
  170. struct vm_area_struct *vma;
  171. if ((op <= 0) || (op > (CACHEFLUSH_D_PURGE|CACHEFLUSH_I)))
  172. return -EINVAL;
  173. /*
  174. * Verify that the specified address region actually belongs
  175. * to this process.
  176. */
  177. if (addr + len < addr)
  178. return -EFAULT;
  179. down_read(&current->mm->mmap_sem);
  180. vma = find_vma (current->mm, addr);
  181. if (vma == NULL || addr < vma->vm_start || addr + len > vma->vm_end) {
  182. up_read(&current->mm->mmap_sem);
  183. return -EFAULT;
  184. }
  185. switch (op & CACHEFLUSH_D_PURGE) {
  186. case CACHEFLUSH_D_INVAL:
  187. __flush_invalidate_region((void *)addr, len);
  188. break;
  189. case CACHEFLUSH_D_WB:
  190. __flush_wback_region((void *)addr, len);
  191. break;
  192. case CACHEFLUSH_D_PURGE:
  193. __flush_purge_region((void *)addr, len);
  194. break;
  195. }
  196. if (op & CACHEFLUSH_I)
  197. flush_cache_all();
  198. up_read(&current->mm->mmap_sem);
  199. return 0;
  200. }
  201. asmlinkage int sys_uname(struct old_utsname __user *name)
  202. {
  203. int err;
  204. if (!name)
  205. return -EFAULT;
  206. down_read(&uts_sem);
  207. err = copy_to_user(name, utsname(), sizeof(*name));
  208. up_read(&uts_sem);
  209. return err?-EFAULT:0;
  210. }