PageRenderTime 33ms CodeModel.GetById 1ms app.highlight 26ms RepoModel.GetById 1ms app.codeStats 0ms

/arch/x86_64/kernel/sys_x86_64.c

https://bitbucket.org/evzijst/gittest
C | 173 lines | 133 code | 18 blank | 22 comment | 25 complexity | 8acdd8115a49202c808681a7f22af8dc MD5 | raw file
  1/*
  2 * linux/arch/x86_64/kernel/sys_x86_64.c
  3 */
  4
  5#include <linux/errno.h>
  6#include <linux/sched.h>
  7#include <linux/syscalls.h>
  8#include <linux/mm.h>
  9#include <linux/smp.h>
 10#include <linux/smp_lock.h>
 11#include <linux/sem.h>
 12#include <linux/msg.h>
 13#include <linux/shm.h>
 14#include <linux/stat.h>
 15#include <linux/mman.h>
 16#include <linux/file.h>
 17#include <linux/utsname.h>
 18#include <linux/personality.h>
 19
 20#include <asm/uaccess.h>
 21#include <asm/ia32.h>
 22
 23/*
 24 * sys_pipe() is the normal C calling standard for creating
 25 * a pipe. It's not the way Unix traditionally does this, though.
 26 */
 27asmlinkage long sys_pipe(int __user *fildes)
 28{
 29	int fd[2];
 30	int error;
 31
 32	error = do_pipe(fd);
 33	if (!error) {
 34		if (copy_to_user(fildes, fd, 2*sizeof(int)))
 35			error = -EFAULT;
 36	}
 37	return error;
 38}
 39
 40asmlinkage long sys_mmap(unsigned long addr, unsigned long len, unsigned long prot, unsigned long flags,
 41	unsigned long fd, unsigned long off)
 42{
 43	long error;
 44	struct file * file;
 45
 46	error = -EINVAL;
 47	if (off & ~PAGE_MASK)
 48		goto out;
 49
 50	error = -EBADF;
 51	file = NULL;
 52	flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
 53	if (!(flags & MAP_ANONYMOUS)) {
 54		file = fget(fd);
 55		if (!file)
 56			goto out;
 57	}
 58	down_write(&current->mm->mmap_sem);
 59	error = do_mmap_pgoff(file, addr, len, prot, flags, off >> PAGE_SHIFT);
 60	up_write(&current->mm->mmap_sem);
 61
 62	if (file)
 63		fput(file);
 64out:
 65	return error;
 66}
 67
 68static void find_start_end(unsigned long flags, unsigned long *begin,
 69			   unsigned long *end)
 70{
 71#ifdef CONFIG_IA32_EMULATION
 72	if (test_thread_flag(TIF_IA32)) { 
 73		*begin = TASK_UNMAPPED_32;
 74		*end = IA32_PAGE_OFFSET; 
 75	} else 
 76#endif
 77	if (flags & MAP_32BIT) { 
 78		/* This is usually used needed to map code in small
 79		   model, so it needs to be in the first 31bit. Limit
 80		   it to that.  This means we need to move the
 81		   unmapped base down for this case. This can give
 82		   conflicts with the heap, but we assume that glibc
 83		   malloc knows how to fall back to mmap. Give it 1GB
 84		   of playground for now. -AK */ 
 85		*begin = 0x40000000; 
 86		*end = 0x80000000;		
 87	} else { 
 88		*begin = TASK_UNMAPPED_64; 
 89		*end = TASK_SIZE; 
 90		}
 91} 
 92
 93unsigned long
 94arch_get_unmapped_area(struct file *filp, unsigned long addr,
 95		unsigned long len, unsigned long pgoff, unsigned long flags)
 96{
 97	struct mm_struct *mm = current->mm;
 98	struct vm_area_struct *vma;
 99	unsigned long start_addr;
100	unsigned long begin, end;
101	
102	find_start_end(flags, &begin, &end); 
103
104	if (len > end)
105		return -ENOMEM;
106
107	if (addr) {
108		addr = PAGE_ALIGN(addr);
109		vma = find_vma(mm, addr);
110		if (end - len >= addr &&
111		    (!vma || addr + len <= vma->vm_start))
112			return addr;
113	}
114	addr = mm->free_area_cache;
115	if (addr < begin) 
116		addr = begin; 
117	start_addr = addr;
118
119full_search:
120	for (vma = find_vma(mm, addr); ; vma = vma->vm_next) {
121		/* At this point:  (!vma || addr < vma->vm_end). */
122		if (end - len < addr) {
123			/*
124			 * Start a new search - just in case we missed
125			 * some holes.
126			 */
127			if (start_addr != begin) {
128				start_addr = addr = begin;
129				goto full_search;
130			}
131			return -ENOMEM;
132		}
133		if (!vma || addr + len <= vma->vm_start) {
134			/*
135			 * Remember the place where we stopped the search:
136			 */
137			mm->free_area_cache = addr + len;
138			return addr;
139		}
140		addr = vma->vm_end;
141	}
142}
143
144asmlinkage long sys_uname(struct new_utsname __user * name)
145{
146	int err;
147	down_read(&uts_sem);
148	err = copy_to_user(name, &system_utsname, sizeof (*name));
149	up_read(&uts_sem);
150	if (personality(current->personality) == PER_LINUX32) 
151		err |= copy_to_user(&name->machine, "i686", 5); 		
152	return err ? -EFAULT : 0;
153}
154
155asmlinkage long wrap_sys_shmat(int shmid, char __user *shmaddr, int shmflg)
156{
157	unsigned long raddr;
158	return do_shmat(shmid,shmaddr,shmflg,&raddr) ?: (long)raddr;
159}
160
161asmlinkage long sys_time64(long __user * tloc)
162{
163	struct timeval now; 
164	int i; 
165
166	do_gettimeofday(&now);
167	i = now.tv_sec;
168	if (tloc) {
169		if (put_user(i,tloc))
170			i = -EFAULT;
171	}
172	return i;
173}