sys_sh.c 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297
  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/smp_lock.h>
  15. #include <linux/sem.h>
  16. #include <linux/msg.h>
  17. #include <linux/shm.h>
  18. #include <linux/stat.h>
  19. #include <linux/syscalls.h>
  20. #include <linux/mman.h>
  21. #include <linux/file.h>
  22. #include <linux/utsname.h>
  23. #include <asm/cacheflush.h>
  24. #include <asm/uaccess.h>
  25. #include <asm/ipc.h>
  26. /*
  27. * sys_pipe() is the normal C calling standard for creating
  28. * a pipe. It's not the way Unix traditionally does this, though.
  29. */
  30. asmlinkage int sys_pipe(unsigned long r4, unsigned long r5,
  31. unsigned long r6, unsigned long r7,
  32. struct pt_regs regs)
  33. {
  34. int fd[2];
  35. int error;
  36. error = do_pipe(fd);
  37. if (!error) {
  38. regs.regs[1] = fd[1];
  39. return fd[0];
  40. }
  41. return error;
  42. }
  43. #if defined(HAVE_ARCH_UNMAPPED_AREA)
  44. /*
  45. * To avoid cache alias, we map the shard page with same color.
  46. */
  47. #define COLOUR_ALIGN(addr) (((addr)+SHMLBA-1)&~(SHMLBA-1))
  48. unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr,
  49. unsigned long len, unsigned long pgoff, unsigned long flags)
  50. {
  51. struct mm_struct *mm = current->mm;
  52. struct vm_area_struct *vma;
  53. unsigned long start_addr;
  54. if (flags & MAP_FIXED) {
  55. /* We do not accept a shared mapping if it would violate
  56. * cache aliasing constraints.
  57. */
  58. if ((flags & MAP_SHARED) && (addr & (SHMLBA - 1)))
  59. return -EINVAL;
  60. return addr;
  61. }
  62. if (len > TASK_SIZE)
  63. return -ENOMEM;
  64. if (addr) {
  65. if (flags & MAP_PRIVATE)
  66. addr = PAGE_ALIGN(addr);
  67. else
  68. addr = COLOUR_ALIGN(addr);
  69. vma = find_vma(mm, addr);
  70. if (TASK_SIZE - len >= addr &&
  71. (!vma || addr + len <= vma->vm_start))
  72. return addr;
  73. }
  74. if (len <= mm->cached_hole_size) {
  75. mm->cached_hole_size = 0;
  76. mm->free_area_cache = TASK_UNMAPPED_BASE;
  77. }
  78. if (flags & MAP_PRIVATE)
  79. addr = PAGE_ALIGN(mm->free_area_cache);
  80. else
  81. addr = COLOUR_ALIGN(mm->free_area_cache);
  82. start_addr = addr;
  83. full_search:
  84. for (vma = find_vma(mm, addr); ; vma = vma->vm_next) {
  85. /* At this point: (!vma || addr < vma->vm_end). */
  86. if (TASK_SIZE - len < addr) {
  87. /*
  88. * Start a new search - just in case we missed
  89. * some holes.
  90. */
  91. if (start_addr != TASK_UNMAPPED_BASE) {
  92. start_addr = addr = TASK_UNMAPPED_BASE;
  93. mm->cached_hole_size = 0;
  94. goto full_search;
  95. }
  96. return -ENOMEM;
  97. }
  98. if (!vma || addr + len <= vma->vm_start) {
  99. /*
  100. * Remember the place where we stopped the search:
  101. */
  102. mm->free_area_cache = addr + len;
  103. return addr;
  104. }
  105. if (addr + mm->cached_hole_size < vma->vm_start)
  106. mm->cached_hole_size = vma->vm_start - addr;
  107. addr = vma->vm_end;
  108. if (!(flags & MAP_PRIVATE))
  109. addr = COLOUR_ALIGN(addr);
  110. }
  111. }
  112. #endif
  113. static inline long
  114. do_mmap2(unsigned long addr, unsigned long len, unsigned long prot,
  115. unsigned long flags, int fd, unsigned long pgoff)
  116. {
  117. int error = -EBADF;
  118. struct file *file = NULL;
  119. flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
  120. if (!(flags & MAP_ANONYMOUS)) {
  121. file = fget(fd);
  122. if (!file)
  123. goto out;
  124. }
  125. down_write(&current->mm->mmap_sem);
  126. error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
  127. up_write(&current->mm->mmap_sem);
  128. if (file)
  129. fput(file);
  130. out:
  131. return error;
  132. }
  133. asmlinkage int old_mmap(unsigned long addr, unsigned long len,
  134. unsigned long prot, unsigned long flags,
  135. int fd, unsigned long off)
  136. {
  137. if (off & ~PAGE_MASK)
  138. return -EINVAL;
  139. return do_mmap2(addr, len, prot, flags, fd, off>>PAGE_SHIFT);
  140. }
  141. asmlinkage long sys_mmap2(unsigned long addr, unsigned long len,
  142. unsigned long prot, unsigned long flags,
  143. unsigned long fd, unsigned long pgoff)
  144. {
  145. return do_mmap2(addr, len, prot, flags, fd, pgoff);
  146. }
  147. /*
  148. * sys_ipc() is the de-multiplexer for the SysV IPC calls..
  149. *
  150. * This is really horribly ugly.
  151. */
  152. asmlinkage int sys_ipc(uint call, int first, int second,
  153. int third, void __user *ptr, long fifth)
  154. {
  155. int version, ret;
  156. version = call >> 16; /* hack for backward compatibility */
  157. call &= 0xffff;
  158. if (call <= SEMCTL)
  159. switch (call) {
  160. case SEMOP:
  161. return sys_semtimedop(first, (struct sembuf __user *)ptr,
  162. second, NULL);
  163. case SEMTIMEDOP:
  164. return sys_semtimedop(first, (struct sembuf __user *)ptr,
  165. second,
  166. (const struct timespec __user *)fifth);
  167. case SEMGET:
  168. return sys_semget (first, second, third);
  169. case SEMCTL: {
  170. union semun fourth;
  171. if (!ptr)
  172. return -EINVAL;
  173. if (get_user(fourth.__pad, (void * __user *) ptr))
  174. return -EFAULT;
  175. return sys_semctl (first, second, third, fourth);
  176. }
  177. default:
  178. return -EINVAL;
  179. }
  180. if (call <= MSGCTL)
  181. switch (call) {
  182. case MSGSND:
  183. return sys_msgsnd (first, (struct msgbuf __user *) ptr,
  184. second, third);
  185. case MSGRCV:
  186. switch (version) {
  187. case 0: {
  188. struct ipc_kludge tmp;
  189. if (!ptr)
  190. return -EINVAL;
  191. if (copy_from_user(&tmp,
  192. (struct ipc_kludge __user *) ptr,
  193. sizeof (tmp)))
  194. return -EFAULT;
  195. return sys_msgrcv (first, tmp.msgp, second,
  196. tmp.msgtyp, third);
  197. }
  198. default:
  199. return sys_msgrcv (first,
  200. (struct msgbuf __user *) ptr,
  201. second, fifth, third);
  202. }
  203. case MSGGET:
  204. return sys_msgget ((key_t) first, second);
  205. case MSGCTL:
  206. return sys_msgctl (first, second,
  207. (struct msqid_ds __user *) ptr);
  208. default:
  209. return -EINVAL;
  210. }
  211. if (call <= SHMCTL)
  212. switch (call) {
  213. case SHMAT:
  214. switch (version) {
  215. default: {
  216. ulong raddr;
  217. ret = do_shmat (first, (char __user *) ptr,
  218. second, &raddr);
  219. if (ret)
  220. return ret;
  221. return put_user (raddr, (ulong __user *) third);
  222. }
  223. case 1: /* iBCS2 emulator entry point */
  224. if (!segment_eq(get_fs(), get_ds()))
  225. return -EINVAL;
  226. return do_shmat (first, (char __user *) ptr,
  227. second, (ulong *) third);
  228. }
  229. case SHMDT:
  230. return sys_shmdt ((char __user *)ptr);
  231. case SHMGET:
  232. return sys_shmget (first, second, third);
  233. case SHMCTL:
  234. return sys_shmctl (first, second,
  235. (struct shmid_ds __user *) ptr);
  236. default:
  237. return -EINVAL;
  238. }
  239. return -EINVAL;
  240. }
  241. asmlinkage int sys_uname(struct old_utsname * name)
  242. {
  243. int err;
  244. if (!name)
  245. return -EFAULT;
  246. down_read(&uts_sem);
  247. err=copy_to_user(name, &system_utsname, sizeof (*name));
  248. up_read(&uts_sem);
  249. return err?-EFAULT:0;
  250. }
  251. asmlinkage ssize_t sys_pread_wrapper(unsigned int fd, char * buf,
  252. size_t count, long dummy, loff_t pos)
  253. {
  254. return sys_pread64(fd, buf, count, pos);
  255. }
  256. asmlinkage ssize_t sys_pwrite_wrapper(unsigned int fd, const char * buf,
  257. size_t count, long dummy, loff_t pos)
  258. {
  259. return sys_pwrite64(fd, buf, count, pos);
  260. }
  261. asmlinkage int sys_fadvise64_64_wrapper(int fd, u32 offset0, u32 offset1,
  262. u32 len0, u32 len1, int advice)
  263. {
  264. #ifdef __LITTLE_ENDIAN__
  265. return sys_fadvise64_64(fd, (u64)offset1 << 32 | offset0,
  266. (u64)len1 << 32 | len0, advice);
  267. #else
  268. return sys_fadvise64_64(fd, (u64)offset0 << 32 | offset1,
  269. (u64)len0 << 32 | len1, advice);
  270. #endif
  271. }