sys_microblaze.c 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227
  1. /*
  2. * Copyright (C) 2007-2009 Michal Simek <monstr@monstr.eu>
  3. * Copyright (C) 2007-2009 PetaLogix
  4. * Copyright (C) 2007 John Williams <john.williams@petalogix.com>
  5. *
  6. * Copyright (C) 2006 Atmark Techno, Inc.
  7. * Yasushi SHOJI <yashi@atmark-techno.com>
  8. * Tetsuya OHKAWA <tetsuya@atmark-techno.com>
  9. *
  10. * This file is subject to the terms and conditions of the GNU General Public
  11. * License. See the file "COPYING" in the main directory of this archive
  12. * for more details.
  13. */
  14. #include <linux/errno.h>
  15. #include <linux/mm.h>
  16. #include <linux/smp.h>
  17. #include <linux/smp_lock.h>
  18. #include <linux/syscalls.h>
  19. #include <linux/sem.h>
  20. #include <linux/msg.h>
  21. #include <linux/shm.h>
  22. #include <linux/stat.h>
  23. #include <linux/mman.h>
  24. #include <linux/sys.h>
  25. #include <linux/ipc.h>
  26. #include <linux/utsname.h>
  27. #include <linux/file.h>
  28. #include <linux/module.h>
  29. #include <linux/err.h>
  30. #include <linux/fs.h>
  31. #include <linux/ipc.h>
  32. #include <linux/semaphore.h>
  33. #include <linux/syscalls.h>
  34. #include <linux/uaccess.h>
  35. #include <linux/unistd.h>
  36. #include <asm/syscalls.h>
  37. /*
  38. * sys_ipc() is the de-multiplexer for the SysV IPC calls..
  39. *
  40. * This is really horribly ugly. This will be remove with new toolchain.
  41. */
  42. asmlinkage int
  43. sys_ipc(uint call, int first, int second, int third, void *ptr, long fifth)
  44. {
  45. int version, ret;
  46. version = call >> 16; /* hack for backward compatibility */
  47. call &= 0xffff;
  48. ret = -EINVAL;
  49. switch (call) {
  50. case SEMOP:
  51. ret = sys_semop(first, (struct sembuf *)ptr, second);
  52. break;
  53. case SEMGET:
  54. ret = sys_semget(first, second, third);
  55. break;
  56. case SEMCTL:
  57. {
  58. union semun fourth;
  59. if (!ptr)
  60. break;
  61. ret = (access_ok(VERIFY_READ, ptr, sizeof(long)) ? 0 : -EFAULT)
  62. || (get_user(fourth.__pad, (void **)ptr)) ;
  63. if (ret)
  64. break;
  65. ret = sys_semctl(first, second, third, fourth);
  66. break;
  67. }
  68. case MSGSND:
  69. ret = sys_msgsnd(first, (struct msgbuf *) ptr, second, third);
  70. break;
  71. case MSGRCV:
  72. switch (version) {
  73. case 0: {
  74. struct ipc_kludge tmp;
  75. if (!ptr)
  76. break;
  77. ret = (access_ok(VERIFY_READ, ptr, sizeof(tmp))
  78. ? 0 : -EFAULT) || copy_from_user(&tmp,
  79. (struct ipc_kludge *) ptr, sizeof(tmp));
  80. if (ret)
  81. break;
  82. ret = sys_msgrcv(first, tmp.msgp, second, tmp.msgtyp,
  83. third);
  84. break;
  85. }
  86. default:
  87. ret = sys_msgrcv(first, (struct msgbuf *) ptr,
  88. second, fifth, third);
  89. break;
  90. }
  91. break;
  92. case MSGGET:
  93. ret = sys_msgget((key_t) first, second);
  94. break;
  95. case MSGCTL:
  96. ret = sys_msgctl(first, second, (struct msqid_ds *) ptr);
  97. break;
  98. case SHMAT:
  99. switch (version) {
  100. default: {
  101. ulong raddr;
  102. ret = access_ok(VERIFY_WRITE, (ulong *) third,
  103. sizeof(ulong)) ? 0 : -EFAULT;
  104. if (ret)
  105. break;
  106. ret = do_shmat(first, (char *) ptr, second, &raddr);
  107. if (ret)
  108. break;
  109. ret = put_user(raddr, (ulong *) third);
  110. break;
  111. }
  112. case 1: /* iBCS2 emulator entry point */
  113. if (!segment_eq(get_fs(), get_ds()))
  114. break;
  115. ret = do_shmat(first, (char *) ptr, second,
  116. (ulong *) third);
  117. break;
  118. }
  119. break;
  120. case SHMDT:
  121. ret = sys_shmdt((char *)ptr);
  122. break;
  123. case SHMGET:
  124. ret = sys_shmget(first, second, third);
  125. break;
  126. case SHMCTL:
  127. ret = sys_shmctl(first, second, (struct shmid_ds *) ptr);
  128. break;
  129. }
  130. return -EINVAL;
  131. }
  132. asmlinkage int sys_vfork(struct pt_regs *regs)
  133. {
  134. return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->r1,
  135. regs, 0, NULL, NULL);
  136. }
  137. asmlinkage int sys_clone(int flags, unsigned long stack, struct pt_regs *regs)
  138. {
  139. if (!stack)
  140. stack = regs->r1;
  141. return do_fork(flags, stack, regs, 0, NULL, NULL);
  142. }
  143. asmlinkage int sys_execve(char __user *filenamei, char __user *__user *argv,
  144. char __user *__user *envp, struct pt_regs *regs)
  145. {
  146. int error;
  147. char *filename;
  148. filename = getname(filenamei);
  149. error = PTR_ERR(filename);
  150. if (IS_ERR(filename))
  151. goto out;
  152. error = do_execve(filename, argv, envp, regs);
  153. putname(filename);
  154. out:
  155. return error;
  156. }
  157. asmlinkage unsigned long
  158. sys_mmap2(unsigned long addr, size_t len,
  159. unsigned long prot, unsigned long flags,
  160. unsigned long fd, unsigned long pgoff)
  161. {
  162. struct file *file = NULL;
  163. int ret = -EBADF;
  164. flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
  165. if (!(flags & MAP_ANONYMOUS)) {
  166. file = fget(fd);
  167. if (!file) {
  168. printk(KERN_INFO "no fd in mmap\r\n");
  169. goto out;
  170. }
  171. }
  172. down_write(&current->mm->mmap_sem);
  173. ret = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
  174. up_write(&current->mm->mmap_sem);
  175. if (file)
  176. fput(file);
  177. out:
  178. return ret;
  179. }
  180. asmlinkage unsigned long sys_mmap(unsigned long addr, size_t len,
  181. unsigned long prot, unsigned long flags,
  182. unsigned long fd, off_t offset)
  183. {
  184. int err = -EINVAL;
  185. if (offset & ~PAGE_MASK) {
  186. printk(KERN_INFO "no pagemask in mmap\r\n");
  187. goto out;
  188. }
  189. err = sys_mmap2(addr, len, prot, flags, fd, offset >> PAGE_SHIFT);
  190. out:
  191. return err;
  192. }
  193. /*
  194. * Do a system call from kernel instead of calling sys_execve so we
  195. * end up with proper pt_regs.
  196. */
  197. int kernel_execve(const char *filename, char *const argv[], char *const envp[])
  198. {
  199. register const char *__a __asm__("r5") = filename;
  200. register const void *__b __asm__("r6") = argv;
  201. register const void *__c __asm__("r7") = envp;
  202. register unsigned long __syscall __asm__("r12") = __NR_execve;
  203. register unsigned long __ret __asm__("r3");
  204. __asm__ __volatile__ ("brki r14, 0x8"
  205. : "=r" (__ret), "=r" (__syscall)
  206. : "1" (__syscall), "r" (__a), "r" (__b), "r" (__c)
  207. : "r4", "r8", "r9",
  208. "r10", "r11", "r14", "cc", "memory");
  209. return __ret;
  210. }