2 * This file contains various system calls that have different calling
3 * conventions on different platforms.
5 * Copyright (C) 1999-2000 Hewlett-Packard Co
6 * Copyright (C) 1999-2000 David Mosberger-Tang <davidm@hpl.hp.com>
8 #include <linux/config.h>
9 #include <linux/errno.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>
19 #include <asm/uaccess.h>
22 ia64_getpriority (int which
, int who
, long arg2
, long arg3
, long arg4
, long arg5
, long arg6
,
23 long arg7
, long stack
)
25 struct pt_regs
*regs
= (struct pt_regs
*) &stack
;
26 extern long sys_getpriority (int, int);
29 prio
= sys_getpriority(which
, who
);
31 regs
->r8
= 0; /* ensure negative priority is not mistaken as error code */
37 asmlinkage
unsigned long
38 sys_getpagesize (void)
43 asmlinkage
unsigned long
44 ia64_shmat (int shmid
, void *shmaddr
, int shmflg
, long arg3
, long arg4
, long arg5
, long arg6
,
45 long arg7
, long stack
)
47 extern int sys_shmat (int shmid
, char *shmaddr
, int shmflg
, ulong
*raddr
);
48 struct pt_regs
*regs
= (struct pt_regs
*) &stack
;
52 retval
= sys_shmat(shmid
, shmaddr
, shmflg
, &raddr
);
56 regs
->r8
= 0; /* ensure negative addresses are not mistaken as an error code */
60 asmlinkage
unsigned long
61 ia64_brk (long brk
, long arg1
, long arg2
, long arg3
,
62 long arg4
, long arg5
, long arg6
, long arg7
, long stack
)
64 extern unsigned long sys_brk (unsigned long brk
);
65 struct pt_regs
*regs
= (struct pt_regs
*) &stack
;
68 retval
= sys_brk(brk
);
70 regs
->r8
= 0; /* ensure large retval isn't mistaken as error code */
75 * On IA-64, we return the two file descriptors in ret0 and ret1 (r8
76 * and r9) as this is faster than doing a copy_to_user().
79 sys_pipe (long arg0
, long arg1
, long arg2
, long arg3
,
80 long arg4
, long arg5
, long arg6
, long arg7
, long stack
)
82 struct pt_regs
*regs
= (struct pt_regs
*) &stack
;
95 static inline unsigned long
96 do_mmap2 (unsigned long addr
, unsigned long len
, int prot
, int flags
, int fd
, unsigned long pgoff
)
98 long start_low
, end_low
, starting_region
, ending_region
;
99 unsigned long loff
, hoff
;
100 struct file
*file
= 0;
101 /* the virtual address space that is mappable in each region: */
102 # define OCTANT_SIZE ((PTRS_PER_PGD<<PGDIR_SHIFT)/8)
105 * A zero mmap always succeeds in Linux, independent of
106 * whether or not the remaining arguments are valid.
108 if (PAGE_ALIGN(len
) == 0)
111 /* Don't permit mappings into or across the address hole in a region: */
112 loff
= REGION_OFFSET(addr
);
113 hoff
= loff
- (REGION_SIZE
- OCTANT_SIZE
/2);
114 if ((len
| loff
| (loff
+ len
)) >= OCTANT_SIZE
/2
115 && (len
| hoff
| (hoff
+ len
)) >= OCTANT_SIZE
/2)
118 /* Don't permit mappings that would cross a region boundary: */
120 starting_region
= REGION_NUMBER(addr
);
121 ending_region
= REGION_NUMBER(addr
+ len
);
122 if (starting_region
!= ending_region
)
125 flags
&= ~(MAP_EXECUTABLE
| MAP_DENYWRITE
);
126 if (!(flags
& MAP_ANONYMOUS
)) {
132 down(¤t
->mm
->mmap_sem
);
133 addr
= do_mmap_pgoff(file
, addr
, len
, prot
, flags
, pgoff
);
134 up(¤t
->mm
->mmap_sem
);
142 * mmap2() is like mmap() except that the offset is expressed in units
143 * of PAGE_SIZE (instead of bytes). This allows to mmap2() (pieces
144 * of) files that are larger than the address space of the CPU.
146 asmlinkage
unsigned long
147 sys_mmap2 (unsigned long addr
, unsigned long len
, int prot
, int flags
, int fd
, long pgoff
,
148 long arg6
, long arg7
, long stack
)
150 struct pt_regs
*regs
= (struct pt_regs
*) &stack
;
152 addr
= do_mmap2(addr
, len
, prot
, flags
, fd
, pgoff
);
154 regs
->r8
= 0; /* ensure large addresses are not mistaken as failures... */
158 asmlinkage
unsigned long
159 sys_mmap (unsigned long addr
, unsigned long len
, int prot
, int flags
,
160 int fd
, long off
, long arg6
, long arg7
, long stack
)
162 struct pt_regs
*regs
= (struct pt_regs
*) &stack
;
164 if ((off
& ~PAGE_MASK
) != 0)
167 addr
= do_mmap2(addr
, len
, prot
, flags
, fd
, off
>> PAGE_SHIFT
);
169 regs
->r8
= 0; /* ensure large addresses are not mistaken as failures... */
174 sys_ioperm (unsigned long from
, unsigned long num
, int on
)
176 printk(KERN_ERR
"sys_ioperm(from=%lx, num=%lx, on=%d)\n", from
, num
, on
);
181 sys_iopl (int level
, long arg1
, long arg2
, long arg3
)
184 printk(KERN_ERR
"sys_iopl(level=%d)!\n", level
);
190 sys_vm86 (long arg0
, long arg1
, long arg2
, long arg3
)
193 printk(KERN_ERR
"sys_vm86(%lx, %lx, %lx, %lx)!\n", arg0
, arg1
, arg2
, arg3
);
199 sys_modify_ldt (long arg0
, long arg1
, long arg2
, long arg3
)
202 printk(KERN_ERR
"sys_modify_ldt(%lx, %lx, %lx, %lx)!\n", arg0
, arg1
, arg2
, arg3
);
207 asmlinkage
unsigned long
208 ia64_create_module (const char *name_user
, size_t size
, long arg2
, long arg3
,
209 long arg4
, long arg5
, long arg6
, long arg7
, long stack
)
211 extern unsigned long sys_create_module (const char *, size_t);
212 struct pt_regs
*regs
= (struct pt_regs
*) &stack
;
215 addr
= sys_create_module (name_user
, size
);
217 regs
->r8
= 0; /* ensure large addresses are not mistaken as failures... */
223 * This is here for a while to keep compatibillity with the old stat()
224 * call - it will be removed later once everybody migrates to the new
225 * kernel stat structure that matches the glibc one - Jes
227 static __inline__
int
228 do_revalidate (struct dentry
*dentry
)
230 struct inode
* inode
= dentry
->d_inode
;
231 if (inode
->i_op
&& inode
->i_op
->revalidate
)
232 return inode
->i_op
->revalidate(dentry
);
237 cp_ia64_old_stat (struct inode
*inode
, struct ia64_oldstat
*statbuf
)
239 struct ia64_oldstat tmp
;
240 unsigned int blocks
, indirect
;
242 memset(&tmp
, 0, sizeof(tmp
));
243 tmp
.st_dev
= kdev_t_to_nr(inode
->i_dev
);
244 tmp
.st_ino
= inode
->i_ino
;
245 tmp
.st_mode
= inode
->i_mode
;
246 tmp
.st_nlink
= inode
->i_nlink
;
247 SET_STAT_UID(tmp
, inode
->i_uid
);
248 SET_STAT_GID(tmp
, inode
->i_gid
);
249 tmp
.st_rdev
= kdev_t_to_nr(inode
->i_rdev
);
250 tmp
.st_size
= inode
->i_size
;
251 tmp
.st_atime
= inode
->i_atime
;
252 tmp
.st_mtime
= inode
->i_mtime
;
253 tmp
.st_ctime
= inode
->i_ctime
;
255 * st_blocks and st_blksize are approximated with a simple algorithm if
256 * they aren't supported directly by the filesystem. The minix and msdos
257 * filesystems don't keep track of blocks, so they would either have to
258 * be counted explicitly (by delving into the file itself), or by using
259 * this simple algorithm to get a reasonable (although not 100% accurate)
264 * Use minix fs values for the number of direct and indirect blocks. The
265 * count is now exact for the minix fs except that it counts zero blocks.
266 * Everything is in units of BLOCK_SIZE until the assignment to
270 #define I_B (BLOCK_SIZE / sizeof(unsigned short))
272 if (!inode
->i_blksize
) {
273 blocks
= (tmp
.st_size
+ BLOCK_SIZE
- 1) / BLOCK_SIZE
;
275 indirect
= (blocks
- D_B
+ I_B
- 1) / I_B
;
278 indirect
= (indirect
- 1 + I_B
- 1) / I_B
;
284 tmp
.st_blocks
= (BLOCK_SIZE
/ 512) * blocks
;
285 tmp
.st_blksize
= BLOCK_SIZE
;
287 tmp
.st_blocks
= inode
->i_blocks
;
288 tmp
.st_blksize
= inode
->i_blksize
;
290 return copy_to_user(statbuf
,&tmp
,sizeof(tmp
)) ? -EFAULT
: 0;
294 ia64_oldstat (char *filename
, struct ia64_oldstat
*statbuf
)
300 error
= user_path_walk(filename
, &nd
);
302 error
= do_revalidate(nd
.dentry
);
304 error
= cp_ia64_old_stat(nd
.dentry
->d_inode
, statbuf
);
313 ia64_oldlstat (char *filename
, struct ia64_oldstat
*statbuf
) {
318 error
= user_path_walk_link(filename
, &nd
);
320 error
= do_revalidate(nd
.dentry
);
322 error
= cp_ia64_old_stat(nd
.dentry
->d_inode
, statbuf
);
330 ia64_oldfstat (unsigned int fd
, struct ia64_oldstat
*statbuf
)
338 struct dentry
* dentry
= f
->f_dentry
;
340 err
= do_revalidate(dentry
);
342 err
= cp_ia64_old_stat(dentry
->d_inode
, statbuf
);
354 sys_pciconfig_read (unsigned long bus
, unsigned long dfn
, unsigned long off
, unsigned long len
,
361 sys_pciconfig_write (unsigned long bus
, unsigned long dfn
, unsigned long off
, unsigned long len
,
367 #endif /* CONFIG_PCI */