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

嵌入式Linux

开发平台:

Unix_Linux

  1. /*
  2.  * This file contains various system calls that have different calling
  3.  * conventions on different platforms.
  4.  *
  5.  * Copyright (C) 1999-2000 Hewlett-Packard Co
  6.  * Copyright (C) 1999-2000 David Mosberger-Tang <davidm@hpl.hp.com>
  7.  */
  8. #include <linux/config.h>
  9. #include <linux/errno.h>
  10. #include <linux/fs.h>
  11. #include <linux/mm.h>
  12. #include <linux/mman.h>
  13. #include <linux/sched.h>
  14. #include <linux/file.h> /* doh, must come after sched.h... */
  15. #include <linux/smp.h>
  16. #include <linux/smp_lock.h>
  17. #include <linux/highuid.h>
  18. #include <asm/shmparam.h>
  19. #include <asm/uaccess.h>
  20. unsigned long
  21. arch_get_unmapped_area (struct file *filp, unsigned long addr, unsigned long len,
  22. unsigned long pgoff, unsigned long flags)
  23. {
  24. long map_shared = (flags & MAP_SHARED);
  25. unsigned long align_mask = PAGE_SIZE - 1;
  26. struct vm_area_struct * vmm;
  27. if (len > RGN_MAP_LIMIT)
  28. return -ENOMEM;
  29. if (!addr)
  30. addr = TASK_UNMAPPED_BASE;
  31. if (map_shared && (TASK_SIZE > 0xfffffffful))
  32. /*
  33.  * For 64-bit tasks, align shared segments to 1MB to avoid potential
  34.  * performance penalty due to virtual aliasing (see ASDM).  For 32-bit
  35.  * tasks, we prefer to avoid exhausting the address space too quickly by
  36.  * limiting alignment to a single page.
  37.  */
  38. align_mask = SHMLBA - 1;
  39. addr = (addr + align_mask) & ~align_mask;
  40. for (vmm = find_vma(current->mm, addr); ; vmm = vmm->vm_next) {
  41. /* At this point:  (!vmm || addr < vmm->vm_end). */
  42. if (TASK_SIZE - len < addr)
  43. return -ENOMEM;
  44. if (rgn_offset(addr) + len > RGN_MAP_LIMIT) /* no risk of overflow here... */
  45. return -ENOMEM;
  46. if (!vmm || addr + len <= vmm->vm_start)
  47. return addr;
  48. addr = (vmm->vm_end + align_mask) & ~align_mask;
  49. }
  50. }
  51. asmlinkage long
  52. ia64_getpriority (int which, int who, long arg2, long arg3, long arg4, long arg5, long arg6,
  53.   long arg7, long stack)
  54. {
  55. struct pt_regs *regs = (struct pt_regs *) &stack;
  56. extern long sys_getpriority (int, int);
  57. long prio;
  58. prio = sys_getpriority(which, who);
  59. if (prio >= 0) {
  60. regs->r8 = 0; /* ensure negative priority is not mistaken as error code */
  61. prio = 20 - prio;
  62. }
  63. return prio;
  64. }
  65. /* XXX obsolete, but leave it here until the old libc is gone... */
  66. asmlinkage unsigned long
  67. sys_getpagesize (void)
  68. {
  69. return PAGE_SIZE;
  70. }
  71. asmlinkage unsigned long
  72. ia64_shmat (int shmid, void *shmaddr, int shmflg, long arg3, long arg4, long arg5, long arg6,
  73.     long arg7, long stack)
  74. {
  75. extern int sys_shmat (int shmid, char *shmaddr, int shmflg, ulong *raddr);
  76. struct pt_regs *regs = (struct pt_regs *) &stack;
  77. unsigned long raddr;
  78. int retval;
  79. retval = sys_shmat(shmid, shmaddr, shmflg, &raddr);
  80. if (retval < 0)
  81. return retval;
  82. regs->r8 = 0; /* ensure negative addresses are not mistaken as an error code */
  83. return raddr;
  84. }
  85. asmlinkage unsigned long
  86. ia64_brk (unsigned long brk, long arg1, long arg2, long arg3,
  87.   long arg4, long arg5, long arg6, long arg7, long stack)
  88. {
  89. extern int vm_enough_memory (long pages);
  90. struct pt_regs *regs = (struct pt_regs *) &stack;
  91. unsigned long rlim, retval, newbrk, oldbrk;
  92. struct mm_struct *mm = current->mm;
  93. /*
  94.  * Most of this replicates the code in sys_brk() except for an additional safety
  95.  * check and the clearing of r8.  However, we can't call sys_brk() because we need
  96.  * to acquire the mmap_sem before we can do the test...
  97.  */
  98. down_write(&mm->mmap_sem);
  99. if (brk < mm->end_code)
  100. goto out;
  101. newbrk = PAGE_ALIGN(brk);
  102. oldbrk = PAGE_ALIGN(mm->brk);
  103. if (oldbrk == newbrk)
  104. goto set_brk;
  105. /* Always allow shrinking brk. */
  106. if (brk <= mm->brk) {
  107. if (!do_munmap(mm, newbrk, oldbrk-newbrk))
  108. goto set_brk;
  109. goto out;
  110. }
  111. /* Check against unimplemented/unmapped addresses: */
  112. if ((newbrk - oldbrk) > RGN_MAP_LIMIT || rgn_offset(newbrk) > RGN_MAP_LIMIT)
  113. goto out;
  114. /* Check against rlimit.. */
  115. rlim = current->rlim[RLIMIT_DATA].rlim_cur;
  116. if (rlim < RLIM_INFINITY && brk - mm->start_data > rlim)
  117. goto out;
  118. /* Check against existing mmap mappings. */
  119. if (find_vma_intersection(mm, oldbrk, newbrk+PAGE_SIZE))
  120. goto out;
  121. /* Check if we have enough memory.. */
  122. if (!vm_enough_memory((newbrk-oldbrk) >> PAGE_SHIFT))
  123. goto out;
  124. /* Ok, looks good - let it rip. */
  125. if (do_brk(oldbrk, newbrk-oldbrk) != oldbrk)
  126. goto out;
  127. set_brk:
  128. mm->brk = brk;
  129. out:
  130. retval = mm->brk;
  131. up_write(&mm->mmap_sem);
  132. regs->r8 = 0; /* ensure large retval isn't mistaken as error code */
  133. return retval;
  134. }
  135. /*
  136.  * On IA-64, we return the two file descriptors in ret0 and ret1 (r8
  137.  * and r9) as this is faster than doing a copy_to_user().
  138.  */
  139. asmlinkage long
  140. sys_pipe (long arg0, long arg1, long arg2, long arg3,
  141.   long arg4, long arg5, long arg6, long arg7, long stack)
  142. {
  143. struct pt_regs *regs = (struct pt_regs *) &stack;
  144. int fd[2];
  145. int retval;
  146. retval = do_pipe(fd);
  147. if (retval)
  148. goto out;
  149. retval = fd[0];
  150. regs->r9 = fd[1];
  151.   out:
  152. return retval;
  153. }
  154. static inline unsigned long
  155. do_mmap2 (unsigned long addr, unsigned long len, int prot, int flags, int fd, unsigned long pgoff)
  156. {
  157. unsigned long roff;
  158. struct file *file = 0;
  159. flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
  160. if (!(flags & MAP_ANONYMOUS)) {
  161. file = fget(fd);
  162. if (!file)
  163. return -EBADF;
  164. if (!file->f_op || !file->f_op->mmap) {
  165. addr = -ENODEV;
  166. goto out;
  167. }
  168. }
  169. /*
  170.  * A zero mmap always succeeds in Linux, independent of whether or not the
  171.  * remaining arguments are valid.
  172.  */
  173. len = PAGE_ALIGN(len);
  174. if (len == 0)
  175. goto out;
  176. /* don't permit mappings into unmapped space or the virtual page table of a region: */
  177. roff = rgn_offset(addr);
  178. if ((len | roff | (roff + len)) >= RGN_MAP_LIMIT) {
  179. addr = -EINVAL;
  180. goto out;
  181. }
  182. /* don't permit mappings that would cross a region boundary: */
  183. if (rgn_index(addr) != rgn_index(addr + len)) {
  184. addr = -EINVAL;
  185. goto out;
  186. }
  187. down_write(&current->mm->mmap_sem);
  188. addr = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
  189. up_write(&current->mm->mmap_sem);
  190. out: if (file)
  191. fput(file);
  192. return addr;
  193. }
  194. /*
  195.  * mmap2() is like mmap() except that the offset is expressed in units
  196.  * of PAGE_SIZE (instead of bytes).  This allows to mmap2() (pieces
  197.  * of) files that are larger than the address space of the CPU.
  198.  */
  199. asmlinkage unsigned long
  200. sys_mmap2 (unsigned long addr, unsigned long len, int prot, int flags, int fd, long pgoff,
  201.    long arg6, long arg7, long stack)
  202. {
  203. struct pt_regs *regs = (struct pt_regs *) &stack;
  204. addr = do_mmap2(addr, len, prot, flags, fd, pgoff);
  205. if (!IS_ERR((void *) addr))
  206. regs->r8 = 0; /* ensure large addresses are not mistaken as failures... */
  207. return addr;
  208. }
  209. asmlinkage unsigned long
  210. sys_mmap (unsigned long addr, unsigned long len, int prot, int flags,
  211.   int fd, long off, long arg6, long arg7, long stack)
  212. {
  213. struct pt_regs *regs = (struct pt_regs *) &stack;
  214. if ((off & ~PAGE_MASK) != 0)
  215. return -EINVAL;
  216. addr = do_mmap2(addr, len, prot, flags, fd, off >> PAGE_SHIFT);
  217. if (!IS_ERR((void *) addr))
  218. regs->r8 = 0; /* ensure large addresses are not mistaken as failures... */
  219. return addr;
  220. }
  221. asmlinkage long
  222. sys_vm86 (long arg0, long arg1, long arg2, long arg3)
  223. {
  224. printk(KERN_ERR "sys_vm86(%lx, %lx, %lx, %lx)!n", arg0, arg1, arg2, arg3);
  225. return -ENOSYS;
  226. }
  227. asmlinkage unsigned long
  228. ia64_create_module (const char *name_user, size_t size, long arg2, long arg3,
  229.     long arg4, long arg5, long arg6, long arg7, long stack)
  230. {
  231. extern unsigned long sys_create_module (const char *, size_t);
  232. struct pt_regs *regs = (struct pt_regs *) &stack;
  233. unsigned long   addr;
  234. addr = sys_create_module (name_user, size);
  235. if (!IS_ERR((void *) addr))
  236. regs->r8 = 0; /* ensure large addresses are not mistaken as failures... */
  237. return addr;
  238. }
  239. #if 1
  240. /*
  241.  * This is here for a while to keep compatibillity with the old stat()
  242.  * call - it will be removed later once everybody migrates to the new
  243.  * kernel stat structure that matches the glibc one - Jes
  244.  */
  245. static __inline__ int
  246. do_revalidate (struct dentry *dentry)
  247. {
  248. struct inode * inode = dentry->d_inode;
  249. if (inode->i_op && inode->i_op->revalidate)
  250. return inode->i_op->revalidate(dentry);
  251. return 0;
  252. }
  253. static int
  254. cp_ia64_old_stat (struct inode *inode, struct ia64_oldstat *statbuf)
  255. {
  256. struct ia64_oldstat tmp;
  257. unsigned int blocks, indirect;
  258. memset(&tmp, 0, sizeof(tmp));
  259. tmp.st_dev = kdev_t_to_nr(inode->i_dev);
  260. tmp.st_ino = inode->i_ino;
  261. tmp.st_mode = inode->i_mode;
  262. tmp.st_nlink = inode->i_nlink;
  263. SET_STAT_UID(tmp, inode->i_uid);
  264. SET_STAT_GID(tmp, inode->i_gid);
  265. tmp.st_rdev = kdev_t_to_nr(inode->i_rdev);
  266. tmp.st_size = inode->i_size;
  267. tmp.st_atime = inode->i_atime;
  268. tmp.st_mtime = inode->i_mtime;
  269. tmp.st_ctime = inode->i_ctime;
  270. /*
  271.  * st_blocks and st_blksize are approximated with a simple algorithm if
  272.  * they aren't supported directly by the filesystem. The minix and msdos
  273.  * filesystems don't keep track of blocks, so they would either have to
  274.  * be counted explicitly (by delving into the file itself), or by using
  275.  * this simple algorithm to get a reasonable (although not 100% accurate)
  276.  * value.
  277.  */
  278. /*
  279.  * Use minix fs values for the number of direct and indirect blocks.  The
  280.  * count is now exact for the minix fs except that it counts zero blocks.
  281.  * Everything is in units of BLOCK_SIZE until the assignment to
  282.  * tmp.st_blksize.
  283.  */
  284. #define D_B   7
  285. #define I_B   (BLOCK_SIZE / sizeof(unsigned short))
  286. if (!inode->i_blksize) {
  287. blocks = (tmp.st_size + BLOCK_SIZE - 1) / BLOCK_SIZE;
  288. if (blocks > D_B) {
  289. indirect = (blocks - D_B + I_B - 1) / I_B;
  290. blocks += indirect;
  291. if (indirect > 1) {
  292. indirect = (indirect - 1 + I_B - 1) / I_B;
  293. blocks += indirect;
  294. if (indirect > 1)
  295. blocks++;
  296. }
  297. }
  298. tmp.st_blocks = (BLOCK_SIZE / 512) * blocks;
  299. tmp.st_blksize = BLOCK_SIZE;
  300. } else {
  301. tmp.st_blocks = inode->i_blocks;
  302. tmp.st_blksize = inode->i_blksize;
  303. }
  304. return copy_to_user(statbuf,&tmp,sizeof(tmp)) ? -EFAULT : 0;
  305. }
  306. asmlinkage long
  307. ia64_oldstat (char *filename, struct ia64_oldstat *statbuf)
  308. {
  309. struct nameidata nd;
  310. int error;
  311. error = user_path_walk(filename, &nd);
  312. if (!error) {
  313. error = do_revalidate(nd.dentry);
  314. if (!error)
  315. error = cp_ia64_old_stat(nd.dentry->d_inode, statbuf);
  316. path_release(&nd);
  317. }
  318. return error;
  319. }
  320. asmlinkage long
  321. ia64_oldlstat (char *filename, struct ia64_oldstat *statbuf) {
  322. struct nameidata nd;
  323. int error;
  324. error = user_path_walk_link(filename, &nd);
  325. if (!error) {
  326. error = do_revalidate(nd.dentry);
  327. if (!error)
  328. error = cp_ia64_old_stat(nd.dentry->d_inode, statbuf);
  329. path_release(&nd);
  330. }
  331. return error;
  332. }
  333. asmlinkage long
  334. ia64_oldfstat (unsigned int fd, struct ia64_oldstat *statbuf)
  335. {
  336. struct file * f;
  337. int err = -EBADF;
  338. f = fget(fd);
  339. if (f) {
  340. struct dentry * dentry = f->f_dentry;
  341. err = do_revalidate(dentry);
  342. if (!err)
  343. err = cp_ia64_old_stat(dentry->d_inode, statbuf);
  344. fput(f);
  345. }
  346. return err;
  347. }
  348. #endif
  349. #ifndef CONFIG_PCI
  350. asmlinkage long
  351. sys_pciconfig_read (unsigned long bus, unsigned long dfn, unsigned long off, unsigned long len,
  352.     void *buf)
  353. {
  354. return -ENOSYS;
  355. }
  356. asmlinkage long
  357. sys_pciconfig_write (unsigned long bus, unsigned long dfn, unsigned long off, unsigned long len,
  358.      void *buf)
  359. {
  360. return -ENOSYS;
  361. }
  362. #endif /* CONFIG_PCI */