diff options
Diffstat (limited to 'arch/sparc/kernel/sys_sparc_64.c')
| -rw-r--r-- | arch/sparc/kernel/sys_sparc_64.c | 155 | 
1 files changed, 38 insertions, 117 deletions
diff --git a/arch/sparc/kernel/sys_sparc_64.c b/arch/sparc/kernel/sys_sparc_64.c index 11c6c9603e7..97309c0ec53 100644 --- a/arch/sparc/kernel/sys_sparc_64.c +++ b/arch/sparc/kernel/sys_sparc_64.c @@ -75,7 +75,7 @@ static inline int invalid_64bit_range(unsigned long addr, unsigned long len)   *    the spitfire/niagara VA-hole.   */ -static inline unsigned long COLOUR_ALIGN(unsigned long addr, +static inline unsigned long COLOR_ALIGN(unsigned long addr,  					 unsigned long pgoff)  {  	unsigned long base = (addr+SHMLBA-1)&~(SHMLBA-1); @@ -84,24 +84,13 @@ static inline unsigned long COLOUR_ALIGN(unsigned long addr,  	return base + off;  } -static inline unsigned long COLOUR_ALIGN_DOWN(unsigned long addr, -					      unsigned long pgoff) -{ -	unsigned long base = addr & ~(SHMLBA-1); -	unsigned long off = (pgoff<<PAGE_SHIFT) & (SHMLBA-1); - -	if (base + off <= addr) -		return base + off; -	return base - off; -} -  unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, unsigned long len, unsigned long pgoff, unsigned long flags)  {  	struct mm_struct *mm = current->mm;  	struct vm_area_struct * vma;  	unsigned long task_size = TASK_SIZE; -	unsigned long start_addr;  	int do_color_align; +	struct vm_unmapped_area_info info;  	if (flags & MAP_FIXED) {  		/* We do not accept a shared mapping if it would violate @@ -124,7 +113,7 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, unsi  	if (addr) {  		if (do_color_align) -			addr = COLOUR_ALIGN(addr, pgoff); +			addr = COLOR_ALIGN(addr, pgoff);  		else  			addr = PAGE_ALIGN(addr); @@ -134,50 +123,22 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, unsi  			return addr;  	} -	if (len > mm->cached_hole_size) { -	        start_addr = addr = mm->free_area_cache; -	} else { -	        start_addr = addr = TASK_UNMAPPED_BASE; -	        mm->cached_hole_size = 0; -	} - -	task_size -= len; - -full_search: -	if (do_color_align) -		addr = COLOUR_ALIGN(addr, pgoff); -	else -		addr = PAGE_ALIGN(addr); +	info.flags = 0; +	info.length = len; +	info.low_limit = TASK_UNMAPPED_BASE; +	info.high_limit = min(task_size, VA_EXCLUDE_START); +	info.align_mask = do_color_align ? (PAGE_MASK & (SHMLBA - 1)) : 0; +	info.align_offset = pgoff << PAGE_SHIFT; +	addr = vm_unmapped_area(&info); -	for (vma = find_vma(mm, addr); ; vma = vma->vm_next) { -		/* At this point:  (!vma || addr < vma->vm_end). */ -		if (addr < VA_EXCLUDE_START && -		    (addr + len) >= VA_EXCLUDE_START) { -			addr = VA_EXCLUDE_END; -			vma = find_vma(mm, VA_EXCLUDE_END); -		} -		if (unlikely(task_size < addr)) { -			if (start_addr != TASK_UNMAPPED_BASE) { -				start_addr = addr = TASK_UNMAPPED_BASE; -				mm->cached_hole_size = 0; -				goto full_search; -			} -			return -ENOMEM; -		} -		if (likely(!vma || addr + len <= vma->vm_start)) { -			/* -			 * Remember the place where we stopped the search: -			 */ -			mm->free_area_cache = addr + len; -			return addr; -		} -		if (addr + mm->cached_hole_size < vma->vm_start) -		        mm->cached_hole_size = vma->vm_start - addr; - -		addr = vma->vm_end; -		if (do_color_align) -			addr = COLOUR_ALIGN(addr, pgoff); +	if ((addr & ~PAGE_MASK) && task_size > VA_EXCLUDE_END) { +		VM_BUG_ON(addr != -ENOMEM); +		info.low_limit = VA_EXCLUDE_END; +		info.high_limit = task_size; +		addr = vm_unmapped_area(&info);  	} + +	return addr;  }  unsigned long @@ -190,6 +151,7 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0,  	unsigned long task_size = STACK_TOP32;  	unsigned long addr = addr0;  	int do_color_align; +	struct vm_unmapped_area_info info;  	/* This should only ever run for 32-bit processes.  */  	BUG_ON(!test_thread_flag(TIF_32BIT)); @@ -214,7 +176,7 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0,  	/* requesting a specific address */  	if (addr) {  		if (do_color_align) -			addr = COLOUR_ALIGN(addr, pgoff); +			addr = COLOR_ALIGN(addr, pgoff);  		else  			addr = PAGE_ALIGN(addr); @@ -224,73 +186,27 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0,  			return addr;  	} -	/* check if free_area_cache is useful for us */ -	if (len <= mm->cached_hole_size) { - 	        mm->cached_hole_size = 0; - 		mm->free_area_cache = mm->mmap_base; - 	} +	info.flags = VM_UNMAPPED_AREA_TOPDOWN; +	info.length = len; +	info.low_limit = PAGE_SIZE; +	info.high_limit = mm->mmap_base; +	info.align_mask = do_color_align ? (PAGE_MASK & (SHMLBA - 1)) : 0; +	info.align_offset = pgoff << PAGE_SHIFT; +	addr = vm_unmapped_area(&info); -	/* either no address requested or can't fit in requested address hole */ -	addr = mm->free_area_cache; -	if (do_color_align) { -		unsigned long base = COLOUR_ALIGN_DOWN(addr-len, pgoff); - -		addr = base + len; -	} - -	/* make sure it can fit in the remaining address space */ -	if (likely(addr > len)) { -		vma = find_vma(mm, addr-len); -		if (!vma || addr <= vma->vm_start) { -			/* remember the address as a hint for next time */ -			return (mm->free_area_cache = addr-len); -		} -	} - -	if (unlikely(mm->mmap_base < len)) -		goto bottomup; - -	addr = mm->mmap_base-len; -	if (do_color_align) -		addr = COLOUR_ALIGN_DOWN(addr, pgoff); - -	do { -		/* -		 * Lookup failure means no vma is above this address, -		 * else if new region fits below vma->vm_start, -		 * return with success: -		 */ -		vma = find_vma(mm, addr); -		if (likely(!vma || addr+len <= vma->vm_start)) { -			/* remember the address as a hint for next time */ -			return (mm->free_area_cache = addr); -		} - - 		/* remember the largest hole we saw so far */ - 		if (addr + mm->cached_hole_size < vma->vm_start) - 		        mm->cached_hole_size = vma->vm_start - addr; - -		/* try just below the current vma->vm_start */ -		addr = vma->vm_start-len; -		if (do_color_align) -			addr = COLOUR_ALIGN_DOWN(addr, pgoff); -	} while (likely(len < vma->vm_start)); - -bottomup:  	/*  	 * A failed mmap() very likely causes application failure,  	 * so fall back to the bottom-up function here. This scenario  	 * can happen with large stack limits and large mmap()  	 * allocations.  	 */ -	mm->cached_hole_size = ~0UL; -  	mm->free_area_cache = TASK_UNMAPPED_BASE; -	addr = arch_get_unmapped_area(filp, addr0, len, pgoff, flags); -	/* -	 * Restore the topdown base: -	 */ -	mm->free_area_cache = mm->mmap_base; -	mm->cached_hole_size = ~0UL; +	if (addr & ~PAGE_MASK) { +		VM_BUG_ON(addr != -ENOMEM); +		info.flags = 0; +		info.low_limit = TASK_UNMAPPED_BASE; +		info.high_limit = STACK_TOP32; +		addr = vm_unmapped_area(&info); +	}  	return addr;  } @@ -751,3 +667,8 @@ int kernel_execve(const char *filename,  		      : "cc");  	return __res;  } + +asmlinkage long sys_kern_features(void) +{ +	return KERN_FEATURE_MIXED_MODE_STACK; +}  |