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

Linux/Unix编程

开发平台:

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, 2002 Hewlett-Packard Co
  6.  * 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. /*
  177.  * Don't permit mappings into unmapped space, the virtual page table of a region,
  178.  * or across a region boundary.  Note: RGN_MAP_LIMIT is equal to 2^n-PAGE_SIZE
  179.  * (for some integer n <= 61) and len > 0.
  180.  */
  181. roff = rgn_offset(addr);
  182. if ((len > RGN_MAP_LIMIT) || (roff > (RGN_MAP_LIMIT - len))) {
  183. addr = -EINVAL;
  184. goto out;
  185. }
  186. down_write(&current->mm->mmap_sem);
  187. addr = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
  188. up_write(&current->mm->mmap_sem);
  189. out: if (file)
  190. fput(file);
  191. return addr;
  192. }
  193. /*
  194.  * mmap2() is like mmap() except that the offset is expressed in units
  195.  * of PAGE_SIZE (instead of bytes).  This allows to mmap2() (pieces
  196.  * of) files that are larger than the address space of the CPU.
  197.  */
  198. asmlinkage unsigned long
  199. sys_mmap2 (unsigned long addr, unsigned long len, int prot, int flags, int fd, long pgoff,
  200.    long arg6, long arg7, long stack)
  201. {
  202. struct pt_regs *regs = (struct pt_regs *) &stack;
  203. addr = do_mmap2(addr, len, prot, flags, fd, pgoff);
  204. if (!IS_ERR((void *) addr))
  205. regs->r8 = 0; /* ensure large addresses are not mistaken as failures... */
  206. return addr;
  207. }
  208. asmlinkage unsigned long
  209. sys_mmap (unsigned long addr, unsigned long len, int prot, int flags,
  210.   int fd, long off, long arg6, long arg7, long stack)
  211. {
  212. struct pt_regs *regs = (struct pt_regs *) &stack;
  213. if ((off & ~PAGE_MASK) != 0)
  214. return -EINVAL;
  215. addr = do_mmap2(addr, len, prot, flags, fd, off >> PAGE_SHIFT);
  216. if (!IS_ERR((void *) addr))
  217. regs->r8 = 0; /* ensure large addresses are not mistaken as failures... */
  218. return addr;
  219. }
  220. asmlinkage long
  221. sys_vm86 (long arg0, long arg1, long arg2, long arg3)
  222. {
  223. printk(KERN_ERR "sys_vm86(%lx, %lx, %lx, %lx)!n", arg0, arg1, arg2, arg3);
  224. return -ENOSYS;
  225. }
  226. asmlinkage unsigned long
  227. ia64_create_module (const char *name_user, size_t size, long arg2, long arg3,
  228.     long arg4, long arg5, long arg6, long arg7, long stack)
  229. {
  230. extern unsigned long sys_create_module (const char *, size_t);
  231. struct pt_regs *regs = (struct pt_regs *) &stack;
  232. unsigned long   addr;
  233. addr = sys_create_module (name_user, size);
  234. if (!IS_ERR((void *) addr))
  235. regs->r8 = 0; /* ensure large addresses are not mistaken as failures... */
  236. return addr;
  237. }
  238. #if 1
  239. /*
  240.  * This is here for a while to keep compatibillity with the old stat()
  241.  * call - it will be removed later once everybody migrates to the new
  242.  * kernel stat structure that matches the glibc one - Jes
  243.  */
  244. static __inline__ int
  245. do_revalidate (struct dentry *dentry)
  246. {
  247. struct inode * inode = dentry->d_inode;
  248. if (inode->i_op && inode->i_op->revalidate)
  249. return inode->i_op->revalidate(dentry);
  250. return 0;
  251. }
  252. static int
  253. cp_ia64_old_stat (struct inode *inode, struct ia64_oldstat *statbuf)
  254. {
  255. struct ia64_oldstat tmp;
  256. unsigned int blocks, indirect;
  257. memset(&tmp, 0, sizeof(tmp));
  258. tmp.st_dev = kdev_t_to_nr(inode->i_dev);
  259. tmp.st_ino = inode->i_ino;
  260. tmp.st_mode = inode->i_mode;
  261. tmp.st_nlink = inode->i_nlink;
  262. SET_STAT_UID(tmp, inode->i_uid);
  263. SET_STAT_GID(tmp, inode->i_gid);
  264. tmp.st_rdev = kdev_t_to_nr(inode->i_rdev);
  265. tmp.st_size = inode->i_size;
  266. tmp.st_atime = inode->i_atime;
  267. tmp.st_mtime = inode->i_mtime;
  268. tmp.st_ctime = inode->i_ctime;
  269. /*
  270.  * st_blocks and st_blksize are approximated with a simple algorithm if
  271.  * they aren't supported directly by the filesystem. The minix and msdos
  272.  * filesystems don't keep track of blocks, so they would either have to
  273.  * be counted explicitly (by delving into the file itself), or by using
  274.  * this simple algorithm to get a reasonable (although not 100% accurate)
  275.  * value.
  276.  */
  277. /*
  278.  * Use minix fs values for the number of direct and indirect blocks.  The
  279.  * count is now exact for the minix fs except that it counts zero blocks.
  280.  * Everything is in units of BLOCK_SIZE until the assignment to
  281.  * tmp.st_blksize.
  282.  */
  283. #define D_B   7
  284. #define I_B   (BLOCK_SIZE / sizeof(unsigned short))
  285. if (!inode->i_blksize) {
  286. blocks = (tmp.st_size + BLOCK_SIZE - 1) / BLOCK_SIZE;
  287. if (blocks > D_B) {
  288. indirect = (blocks - D_B + I_B - 1) / I_B;
  289. blocks += indirect;
  290. if (indirect > 1) {
  291. indirect = (indirect - 1 + I_B - 1) / I_B;
  292. blocks += indirect;
  293. if (indirect > 1)
  294. blocks++;
  295. }
  296. }
  297. tmp.st_blocks = (BLOCK_SIZE / 512) * blocks;
  298. tmp.st_blksize = BLOCK_SIZE;
  299. } else {
  300. tmp.st_blocks = inode->i_blocks;
  301. tmp.st_blksize = inode->i_blksize;
  302. }
  303. return copy_to_user(statbuf,&tmp,sizeof(tmp)) ? -EFAULT : 0;
  304. }
  305. asmlinkage long
  306. ia64_oldstat (char *filename, struct ia64_oldstat *statbuf)
  307. {
  308. struct nameidata nd;
  309. int error;
  310. error = user_path_walk(filename, &nd);
  311. if (!error) {
  312. error = do_revalidate(nd.dentry);
  313. if (!error)
  314. error = cp_ia64_old_stat(nd.dentry->d_inode, statbuf);
  315. path_release(&nd);
  316. }
  317. return error;
  318. }
  319. asmlinkage long
  320. ia64_oldlstat (char *filename, struct ia64_oldstat *statbuf) {
  321. struct nameidata nd;
  322. int error;
  323. error = user_path_walk_link(filename, &nd);
  324. if (!error) {
  325. error = do_revalidate(nd.dentry);
  326. if (!error)
  327. error = cp_ia64_old_stat(nd.dentry->d_inode, statbuf);
  328. path_release(&nd);
  329. }
  330. return error;
  331. }
  332. asmlinkage long
  333. ia64_oldfstat (unsigned int fd, struct ia64_oldstat *statbuf)
  334. {
  335. struct file * f;
  336. int err = -EBADF;
  337. f = fget(fd);
  338. if (f) {
  339. struct dentry * dentry = f->f_dentry;
  340. err = do_revalidate(dentry);
  341. if (!err)
  342. err = cp_ia64_old_stat(dentry->d_inode, statbuf);
  343. fput(f);
  344. }
  345. return err;
  346. }
  347. #endif
  348. #ifndef CONFIG_PCI
  349. asmlinkage long
  350. sys_pciconfig_read (unsigned long bus, unsigned long dfn, unsigned long off, unsigned long len,
  351.     void *buf)
  352. {
  353. return -ENOSYS;
  354. }
  355. asmlinkage long
  356. sys_pciconfig_write (unsigned long bus, unsigned long dfn, unsigned long off, unsigned long len,
  357.      void *buf)
  358. {
  359. return -ENOSYS;
  360. }
  361. #endif /* CONFIG_PCI */