syscall.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:7k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

  1. /*
  2.  * This file is subject to the terms and conditions of the GNU General Public
  3.  * License.  See the file "COPYING" in the main directory of this archive
  4.  * for more details.
  5.  *
  6.  * Copyright (C) 1995 - 2000, 2001 by Ralf Baechle
  7.  * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
  8.  * Copyright (C) 2001 MIPS Technologies, Inc.
  9.  */
  10. #include <linux/errno.h>
  11. #include <linux/linkage.h>
  12. #include <linux/mm.h>
  13. #include <linux/smp.h>
  14. #include <linux/smp_lock.h>
  15. #include <linux/mman.h>
  16. #include <linux/sched.h>
  17. #include <linux/string.h>
  18. #include <linux/file.h>
  19. #include <linux/utsname.h>
  20. #include <linux/unistd.h>
  21. #include <linux/sem.h>
  22. #include <linux/msg.h>
  23. #include <linux/shm.h>
  24. #include <linux/slab.h>
  25. #include <asm/ipc.h>
  26. #include <asm/cachectl.h>
  27. #include <asm/offset.h>
  28. #include <asm/pgalloc.h>
  29. #include <asm/ptrace.h>
  30. #include <asm/signal.h>
  31. #include <asm/stackframe.h>
  32. #include <asm/sysmips.h>
  33. #include <asm/uaccess.h>
  34. extern asmlinkage void syscall_trace(void);
  35. asmlinkage int sys_pipe(abi64_no_regargs, struct pt_regs regs)
  36. {
  37. int fd[2];
  38. int error, res;
  39. error = do_pipe(fd);
  40. if (error) {
  41. res = error;
  42. goto out;
  43. }
  44. regs.regs[3] = fd[1];
  45. res = fd[0];
  46. out:
  47. return res;
  48. }
  49. #define COLOUR_ALIGN(addr,pgoff)
  50. ((((addr)+SHMLBA-1)&~(SHMLBA-1)) +
  51.  (((pgoff)<<PAGE_SHIFT) & (SHMLBA-1)))
  52. unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr,
  53. unsigned long len, unsigned long pgoff, unsigned long flags)
  54. {
  55. struct vm_area_struct * vmm;
  56. int do_color_align;
  57. if (flags & MAP_FIXED) {
  58. /*
  59.  * We do not accept a shared mapping if it would violate
  60.  * cache aliasing constraints.
  61.  */
  62. if ((flags & MAP_SHARED) && (addr & (SHMLBA - 1)))
  63. return -EINVAL;
  64. return addr;
  65. }
  66. if (len > TASK_SIZE)
  67. return -ENOMEM;
  68. do_color_align = 0;
  69. if (filp || (flags & MAP_SHARED))
  70. do_color_align = 1;
  71. if (addr) {
  72. if (do_color_align)
  73. addr = COLOUR_ALIGN(addr, pgoff);
  74. else
  75. addr = PAGE_ALIGN(addr);
  76. vmm = find_vma(current->mm, addr);
  77. if (TASK_SIZE - len >= addr &&
  78.     (!vmm || addr + len <= vmm->vm_start))
  79. return addr;
  80. }
  81. addr = TASK_UNMAPPED_BASE;
  82. if (do_color_align)
  83. addr = COLOUR_ALIGN(addr, pgoff);
  84. else
  85. addr = PAGE_ALIGN(addr);
  86. for (vmm = find_vma(current->mm, addr); ; vmm = vmm->vm_next) {
  87. /* At this point:  (!vmm || addr < vmm->vm_end). */
  88. if (TASK_SIZE - len < addr)
  89. return -ENOMEM;
  90. if (!vmm || addr + len <= vmm->vm_start)
  91. return addr;
  92. addr = vmm->vm_end;
  93. if (do_color_align)
  94. addr = COLOUR_ALIGN(addr, pgoff);
  95. }
  96. }
  97. asmlinkage unsigned long
  98. sys_mmap(unsigned long addr, size_t len, unsigned long prot,
  99.          unsigned long flags, unsigned long fd, off_t offset)
  100. {
  101. struct file * file = NULL;
  102. unsigned long error;
  103. error = -EINVAL;
  104. if (offset & ~PAGE_MASK)
  105. goto out;
  106. if (!(flags & MAP_ANONYMOUS)) {
  107. error = -EBADF;
  108. file = fget(fd);
  109. if (!file)
  110. goto out;
  111. }
  112.         flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
  113. down_write(&current->mm->mmap_sem);
  114.         error = do_mmap(file, addr, len, prot, flags, offset);
  115. up_write(&current->mm->mmap_sem);
  116.         if (file)
  117.                 fput(file);
  118. out:
  119. return error;
  120. }
  121. asmlinkage int sys_fork(abi64_no_regargs, struct pt_regs regs)
  122. {
  123. int res;
  124. save_static(&regs);
  125. res = do_fork(SIGCHLD, regs.regs[29], &regs, 0);
  126. return res;
  127. }
  128. asmlinkage int sys_clone(abi64_no_regargs, struct pt_regs regs)
  129. {
  130. unsigned long clone_flags;
  131. unsigned long newsp;
  132. int res;
  133. save_static(&regs);
  134. clone_flags = regs.regs[4];
  135. newsp = regs.regs[5];
  136. if (!newsp)
  137. newsp = regs.regs[29];
  138. res = do_fork(clone_flags, newsp, &regs, 0);
  139. return res;
  140. }
  141. /*
  142.  * sys_execve() executes a new program.
  143.  */
  144. asmlinkage int sys_execve(abi64_no_regargs, struct pt_regs regs)
  145. {
  146. int error;
  147. char * filename;
  148. filename = getname((char *) (long)regs.regs[4]);
  149. error = PTR_ERR(filename);
  150. if (IS_ERR(filename))
  151. goto out;
  152. error = do_execve(filename, (char **) (long)regs.regs[5],
  153.                   (char **) (long)regs.regs[6], &regs);
  154. putname(filename);
  155. out:
  156. return error;
  157. }
  158. /*
  159.  * Do the indirect syscall syscall.
  160.  *
  161.  * XXX This is borken.
  162.  */
  163. asmlinkage int sys_syscall(abi64_no_regargs, struct pt_regs regs)
  164. {
  165. return -ENOSYS;
  166. }
  167. asmlinkage int
  168. sys_sysmips(int cmd, long arg1, int arg2, int arg3)
  169. {
  170. int *p;
  171. char *name;
  172. int tmp, len, errno;
  173. switch(cmd) {
  174. case SETNAME: {
  175. char nodename[__NEW_UTS_LEN + 1];
  176. if (!capable(CAP_SYS_ADMIN))
  177. return -EPERM;
  178. name = (char *) arg1;
  179. len = strncpy_from_user(nodename, name, sizeof(nodename));
  180. if (len < 0)
  181. return -EFAULT;
  182. down_write(&uts_sem);
  183. strncpy(system_utsname.nodename, name, len);
  184. system_utsname.nodename[len] = '';
  185. up_write(&uts_sem);
  186. return 0;
  187. }
  188. case MIPS_ATOMIC_SET:
  189. printk(KERN_CRIT "How did I get here?n");
  190. return -EINVAL;
  191. case MIPS_FIXADE:
  192. tmp = current->thread.mflags & ~3;
  193. current->thread.mflags = tmp | (arg1 & 3);
  194. return 0;
  195. case FLUSH_CACHE:
  196. _flush_cache_l2();
  197. return 0;
  198. case MIPS_RDNVRAM:
  199. return -EIO;
  200. }
  201. return -EINVAL;
  202. }
  203. /*
  204.  * sys_ipc() is the de-multiplexer for the SysV IPC calls..
  205.  *
  206.  * This is really horribly ugly.
  207.  */
  208. asmlinkage int sys_ipc (uint call, int first, int second,
  209. unsigned long third, void *ptr, long fifth)
  210. {
  211. int version, ret;
  212. version = call >> 16; /* hack for backward compatibility */
  213. call &= 0xffff;
  214. switch (call) {
  215. case SEMOP:
  216. return sys_semop (first, (struct sembuf *)ptr, second);
  217. case SEMGET:
  218. return sys_semget (first, second, third);
  219. case SEMCTL: {
  220. union semun fourth;
  221. if (!ptr)
  222. return -EINVAL;
  223. if (get_user(fourth.__pad, (void **) ptr))
  224. return -EFAULT;
  225. return sys_semctl (first, second, third, fourth);
  226. }
  227. case MSGSND:
  228. return sys_msgsnd (first, (struct msgbuf *) ptr,
  229.    second, third);
  230. case MSGRCV:
  231. switch (version) {
  232. case 0: {
  233. struct ipc_kludge tmp;
  234. if (!ptr)
  235. return -EINVAL;
  236. if (copy_from_user(&tmp,
  237.    (struct ipc_kludge *) ptr,
  238.    sizeof (tmp)))
  239. return -EFAULT;
  240. return sys_msgrcv (first, tmp.msgp, second,
  241.    tmp.msgtyp, third);
  242. }
  243. default:
  244. return sys_msgrcv (first,
  245.    (struct msgbuf *) ptr,
  246.    second, fifth, third);
  247. }
  248. case MSGGET:
  249. return sys_msgget ((key_t) first, second);
  250. case MSGCTL:
  251. return sys_msgctl (first, second, (struct msqid_ds *) ptr);
  252. case SHMAT:
  253. switch (version) {
  254. default: {
  255. ulong raddr;
  256. ret = sys_shmat (first, (char *) ptr, second, &raddr);
  257. if (ret)
  258. return ret;
  259. return put_user (raddr, (ulong *) third);
  260. }
  261. case 1: /* iBCS2 emulator entry point */
  262. if (!segment_eq(get_fs(), get_ds()))
  263. return -EINVAL;
  264. return sys_shmat (first, (char *) ptr, second, (ulong *) third);
  265. }
  266. case SHMDT:
  267. return sys_shmdt ((char *)ptr);
  268. case SHMGET:
  269. return sys_shmget (first, second, third);
  270. case SHMCTL:
  271. return sys_shmctl (first, second,
  272.    (struct shmid_ds *) ptr);
  273. default:
  274. return -EINVAL;
  275. }
  276. }
  277. /*
  278.  * No implemented yet ...
  279.  */
  280. asmlinkage int sys_cachectl(char *addr, int nbytes, int op)
  281. {
  282. return -ENOSYS;
  283. }
  284. /*
  285.  * If we ever come here the user sp is bad.  Zap the process right away.
  286.  * Due to the bad stack signaling wouldn't work.
  287.  */
  288. asmlinkage void bad_stack(void)
  289. {
  290. do_exit(SIGSEGV);
  291. }
  292. asmlinkage int sys_pause(void)
  293. {
  294. current->state = TASK_INTERRUPTIBLE;
  295. schedule();
  296. return -ERESTARTNOHAND;
  297. }