syscalls.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:7k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

  1. /*
  2.  * BK Id: SCCS/s.syscalls.c 1.11 10/16/01 15:58:42 trini
  3.  */
  4. /*
  5.  * linux/arch/ppc/kernel/sys_ppc.c
  6.  *
  7.  *  PowerPC version 
  8.  *    Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
  9.  *
  10.  * Derived from "arch/i386/kernel/sys_i386.c"
  11.  * Adapted from the i386 version by Gary Thomas
  12.  * Modified by Cort Dougan (cort@cs.nmt.edu)
  13.  * and Paul Mackerras (paulus@cs.anu.edu.au).
  14.  *
  15.  * This file contains various random system calls that
  16.  * have a non-standard calling sequence on the Linux/PPC
  17.  * platform.
  18.  *
  19.  *  This program is free software; you can redistribute it and/or
  20.  *  modify it under the terms of the GNU General Public License
  21.  *  as published by the Free Software Foundation; either version
  22.  *  2 of the License, or (at your option) any later version.
  23.  *
  24.  */
  25. #include <linux/config.h>
  26. #include <linux/errno.h>
  27. #include <linux/sched.h>
  28. #include <linux/mm.h>
  29. #include <linux/smp.h>
  30. #include <linux/smp_lock.h>
  31. #include <linux/sem.h>
  32. #include <linux/msg.h>
  33. #include <linux/shm.h>
  34. #include <linux/stat.h>
  35. #include <linux/mman.h>
  36. #include <linux/sys.h>
  37. #include <linux/ipc.h>
  38. #include <linux/utsname.h>
  39. #include <linux/file.h>
  40. #include <asm/uaccess.h>
  41. #include <asm/ipc.h>
  42. #include <asm/semaphore.h>
  43. void
  44. check_bugs(void)
  45. {
  46. }
  47. int sys_ioperm(unsigned long from, unsigned long num, int on)
  48. {
  49. printk(KERN_ERR "sys_ioperm()n");
  50. return -EIO;
  51. }
  52. int sys_iopl(int a1, int a2, int a3, int a4)
  53. {
  54. printk(KERN_ERR "sys_iopl(%x, %x, %x, %x)!n", a1, a2, a3, a4);
  55. return (-ENOSYS);
  56. }
  57. int sys_vm86(int a1, int a2, int a3, int a4)
  58. {
  59. printk(KERN_ERR "sys_vm86(%x, %x, %x, %x)!n", a1, a2, a3, a4);
  60. return (-ENOSYS);
  61. }
  62. int sys_modify_ldt(int a1, int a2, int a3, int a4)
  63. {
  64. printk(KERN_ERR "sys_modify_ldt(%x, %x, %x, %x)!n", a1, a2, a3, a4);
  65. return (-ENOSYS);
  66. }
  67. /*
  68.  * sys_ipc() is the de-multiplexer for the SysV IPC calls..
  69.  *
  70.  * This is really horribly ugly.
  71.  */
  72. int
  73. sys_ipc (uint call, int first, int second, int third, void *ptr, long fifth)
  74. {
  75. int version, ret;
  76. version = call >> 16; /* hack for backward compatibility */
  77. call &= 0xffff;
  78. ret = -EINVAL;
  79. switch (call) {
  80. case SEMOP:
  81. ret = sys_semop (first, (struct sembuf *)ptr, second);
  82. break;
  83. case SEMGET:
  84. ret = sys_semget (first, second, third);
  85. break;
  86. case SEMCTL: {
  87. union semun fourth;
  88. if (!ptr)
  89. break;
  90. if ((ret = verify_area (VERIFY_READ, ptr, sizeof(long)))
  91.     || (ret = get_user(fourth.__pad, (void **)ptr)))
  92. break;
  93. ret = sys_semctl (first, second, third, fourth);
  94. break;
  95. }
  96. case MSGSND:
  97. ret = sys_msgsnd (first, (struct msgbuf *) ptr, second, third);
  98. break;
  99. case MSGRCV:
  100. switch (version) {
  101. case 0: {
  102. struct ipc_kludge tmp;
  103. if (!ptr)
  104. break;
  105. if ((ret = verify_area (VERIFY_READ, ptr, sizeof(tmp)))
  106.     || (ret = copy_from_user(&tmp,
  107. (struct ipc_kludge *) ptr,
  108. sizeof (tmp))))
  109. break;
  110. ret = sys_msgrcv (first, tmp.msgp, second, tmp.msgtyp,
  111.   third);
  112. break;
  113. }
  114. default:
  115. ret = sys_msgrcv (first, (struct msgbuf *) ptr,
  116.   second, fifth, third);
  117. break;
  118. }
  119. break;
  120. case MSGGET:
  121. ret = sys_msgget ((key_t) first, second);
  122. break;
  123. case MSGCTL:
  124. ret = sys_msgctl (first, second, (struct msqid_ds *) ptr);
  125. break;
  126. case SHMAT:
  127. switch (version) {
  128. default: {
  129. ulong raddr;
  130. if ((ret = verify_area(VERIFY_WRITE, (ulong*) third,
  131.        sizeof(ulong))))
  132. break;
  133. ret = sys_shmat (first, (char *) ptr, second, &raddr);
  134. if (ret)
  135. break;
  136. ret = put_user (raddr, (ulong *) third);
  137. break;
  138. }
  139. case 1: /* iBCS2 emulator entry point */
  140. if (!segment_eq(get_fs(), get_ds()))
  141. break;
  142. ret = sys_shmat (first, (char *) ptr, second,
  143.  (ulong *) third);
  144. break;
  145. }
  146. break;
  147. case SHMDT: 
  148. ret = sys_shmdt ((char *)ptr);
  149. break;
  150. case SHMGET:
  151. ret = sys_shmget (first, second, third);
  152. break;
  153. case SHMCTL:
  154. ret = sys_shmctl (first, second, (struct shmid_ds *) ptr);
  155. break;
  156. }
  157. return ret;
  158. }
  159. /*
  160.  * sys_pipe() is the normal C calling standard for creating
  161.  * a pipe. It's not the way unix traditionally does this, though.
  162.  */
  163. int sys_pipe(int *fildes)
  164. {
  165. int fd[2];
  166. int error;
  167. error = do_pipe(fd);
  168. if (!error) {
  169. if (copy_to_user(fildes, fd, 2*sizeof(int)))
  170. error = -EFAULT;
  171. }
  172. return error;
  173. }
  174. static inline unsigned long
  175. do_mmap2(unsigned long addr, size_t len,
  176.  unsigned long prot, unsigned long flags,
  177.  unsigned long fd, unsigned long pgoff)
  178. {
  179. struct file * file = NULL;
  180. int ret = -EBADF;
  181. flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
  182. if (!(flags & MAP_ANONYMOUS)) {
  183. if (!(file = fget(fd)))
  184. goto out;
  185. }
  186. down_write(&current->mm->mmap_sem);
  187. ret = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
  188. up_write(&current->mm->mmap_sem);
  189. if (file)
  190. fput(file);
  191. out:
  192. return ret;
  193. }
  194. unsigned long sys_mmap2(unsigned long addr, size_t len,
  195. unsigned long prot, unsigned long flags,
  196. unsigned long fd, unsigned long pgoff)
  197. {
  198. return do_mmap2(addr, len, prot, flags, fd, pgoff);
  199. }
  200. unsigned long sys_mmap(unsigned long addr, size_t len,
  201.        unsigned long prot, unsigned long flags,
  202.        unsigned long fd, off_t offset)
  203. {
  204. int err = -EINVAL;
  205. if (offset & ~PAGE_MASK)
  206. goto out;
  207. err = do_mmap2(addr, len, prot, flags, fd, offset >> PAGE_SHIFT);
  208. out:
  209. return err;
  210. }
  211. extern int sys_select(int, fd_set *, fd_set *, fd_set *, struct timeval *);
  212. /*
  213.  * Due to some executables calling the wrong select we sometimes
  214.  * get wrong args.  This determines how the args are being passed
  215.  * (a single ptr to them all args passed) then calls
  216.  * sys_select() with the appropriate args. -- Cort
  217.  */
  218. int
  219. ppc_select(int n, fd_set *inp, fd_set *outp, fd_set *exp, struct timeval *tvp)
  220. {
  221. if ( (unsigned long)n >= 4096 )
  222. {
  223. unsigned long *buffer = (unsigned long *)n;
  224. if (verify_area(VERIFY_READ, buffer, 5*sizeof(unsigned long))
  225.     || __get_user(n, buffer)
  226.     || __get_user(inp, ((fd_set **)(buffer+1)))
  227.     || __get_user(outp, ((fd_set **)(buffer+2)))
  228.     || __get_user(exp, ((fd_set **)(buffer+3)))
  229.     || __get_user(tvp, ((struct timeval **)(buffer+4))))
  230. return -EFAULT;
  231. }
  232. return sys_select(n, inp, outp, exp, tvp);
  233. }
  234. int sys_pause(void)
  235. {
  236. current->state = TASK_INTERRUPTIBLE;
  237. schedule();
  238. return -ERESTARTNOHAND;
  239. }
  240. int sys_uname(struct old_utsname * name)
  241. {
  242. int err = -EFAULT;
  243. down_read(&uts_sem);
  244. if (name && !copy_to_user(name, &system_utsname, sizeof (*name)))
  245. err = 0;
  246. up_read(&uts_sem);
  247. return err;
  248. }
  249. int sys_olduname(struct oldold_utsname * name)
  250. {
  251. int error;
  252. if (!name)
  253. return -EFAULT;
  254. if (!access_ok(VERIFY_WRITE,name,sizeof(struct oldold_utsname)))
  255. return -EFAULT;
  256.   
  257. down_read(&uts_sem);
  258. error = __copy_to_user(&name->sysname,&system_utsname.sysname,__OLD_UTS_LEN);
  259. error -= __put_user(0,name->sysname+__OLD_UTS_LEN);
  260. error -= __copy_to_user(&name->nodename,&system_utsname.nodename,__OLD_UTS_LEN);
  261. error -= __put_user(0,name->nodename+__OLD_UTS_LEN);
  262. error -= __copy_to_user(&name->release,&system_utsname.release,__OLD_UTS_LEN);
  263. error -= __put_user(0,name->release+__OLD_UTS_LEN);
  264. error -= __copy_to_user(&name->version,&system_utsname.version,__OLD_UTS_LEN);
  265. error -= __put_user(0,name->version+__OLD_UTS_LEN);
  266. error -= __copy_to_user(&name->machine,&system_utsname.machine,__OLD_UTS_LEN);
  267. error = __put_user(0,name->machine+__OLD_UTS_LEN);
  268. up_read(&uts_sem);
  269. error = error ? -EFAULT : 0;
  270. return error;
  271. }
  272. #ifndef CONFIG_PCI
  273. /*
  274.  * Those are normally defined in arch/ppc/kernel/pci.c. But when CONFIG_PCI is
  275.  * not defined, this file is not linked at all, so here are the "empty" versions
  276.  */
  277. int sys_pciconfig_read(void) { return -ENOSYS; }
  278. int sys_pciconfig_write(void) { return -ENOSYS; }
  279. long sys_pciconfig_iobase(void) { return -ENOSYS; }
  280. #endif