diff options
Diffstat (limited to 'arch/xtensa/kernel/syscall.c')
| -rw-r--r-- | arch/xtensa/kernel/syscall.c | 50 | 
1 files changed, 44 insertions, 6 deletions
diff --git a/arch/xtensa/kernel/syscall.c b/arch/xtensa/kernel/syscall.c index 816e6d0d686..5d3f7a119ed 100644 --- a/arch/xtensa/kernel/syscall.c +++ b/arch/xtensa/kernel/syscall.c @@ -32,26 +32,64 @@ typedef void (*syscall_t)(void);  syscall_t sys_call_table[__NR_syscall_count] /* FIXME __cacheline_aligned */= {  	[0 ... __NR_syscall_count - 1] = (syscall_t)&sys_ni_syscall, -#undef __SYSCALL  #define __SYSCALL(nr,symbol,nargs) [ nr ] = (syscall_t)symbol, -#undef _XTENSA_UNISTD_H -#undef  __KERNEL_SYSCALLS__ -#include <asm/unistd.h> +#include <uapi/asm/unistd.h>  }; +#define COLOUR_ALIGN(addr, pgoff) \ +	((((addr) + SHMLBA - 1) & ~(SHMLBA - 1)) + \ +	 (((pgoff) << PAGE_SHIFT) & (SHMLBA - 1))) +  asmlinkage long xtensa_shmat(int shmid, char __user *shmaddr, int shmflg)  {  	unsigned long ret;  	long err; -	err = do_shmat(shmid, shmaddr, shmflg, &ret); +	err = do_shmat(shmid, shmaddr, shmflg, &ret, SHMLBA);  	if (err)  		return err;  	return (long)ret;  } -asmlinkage long xtensa_fadvise64_64(int fd, int advice, unsigned long long offset, unsigned long long len) +asmlinkage long xtensa_fadvise64_64(int fd, int advice, +		unsigned long long offset, unsigned long long len)  {  	return sys_fadvise64_64(fd, offset, len, advice);  } +unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, +		unsigned long len, unsigned long pgoff, unsigned long flags) +{ +	struct vm_area_struct *vmm; + +	if (flags & MAP_FIXED) { +		/* We do not accept a shared mapping if it would violate +		 * cache aliasing constraints. +		 */ +		if ((flags & MAP_SHARED) && +				((addr - (pgoff << PAGE_SHIFT)) & (SHMLBA - 1))) +			return -EINVAL; +		return addr; +	} + +	if (len > TASK_SIZE) +		return -ENOMEM; +	if (!addr) +		addr = TASK_UNMAPPED_BASE; + +	if (flags & MAP_SHARED) +		addr = COLOUR_ALIGN(addr, pgoff); +	else +		addr = PAGE_ALIGN(addr); + +	for (vmm = find_vma(current->mm, addr); ; vmm = vmm->vm_next) { +		/* At this point:  (!vmm || addr < vmm->vm_end). */ +		if (TASK_SIZE - len < addr) +			return -ENOMEM; +		if (!vmm || addr + len <= vmm->vm_start) +			return addr; +		addr = vmm->vm_end; +		if (flags & MAP_SHARED) +			addr = COLOUR_ALIGN(addr, pgoff); +	} +}  | 
