diff options
Diffstat (limited to 'arch/arm/mm/mmap.c')
| -rw-r--r-- | arch/arm/mm/mmap.c | 134 | 
1 files changed, 24 insertions, 110 deletions
diff --git a/arch/arm/mm/mmap.c b/arch/arm/mm/mmap.c index ce8cb1970d7a..10062ceadd1c 100644 --- a/arch/arm/mm/mmap.c +++ b/arch/arm/mm/mmap.c @@ -11,18 +11,6 @@  #include <linux/random.h>  #include <asm/cachetype.h> -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; -} -  #define COLOUR_ALIGN(addr,pgoff)		\  	((((addr)+SHMLBA-1)&~(SHMLBA-1)) +	\  	 (((pgoff)<<PAGE_SHIFT) & (SHMLBA-1))) @@ -69,9 +57,9 @@ arch_get_unmapped_area(struct file *filp, unsigned long addr,  {  	struct mm_struct *mm = current->mm;  	struct vm_area_struct *vma; -	unsigned long start_addr;  	int do_align = 0;  	int aliasing = cache_is_vipt_aliasing(); +	struct vm_unmapped_area_info info;  	/*  	 * We only need to do colour alignment if either the I or D @@ -104,46 +92,14 @@ arch_get_unmapped_area(struct file *filp, unsigned long addr,  		    (!vma || addr + len <= vma->vm_start))  			return addr;  	} -	if (len > mm->cached_hole_size) { -	        start_addr = addr = mm->free_area_cache; -	} else { -	        start_addr = addr = mm->mmap_base; -	        mm->cached_hole_size = 0; -	} -full_search: -	if (do_align) -		addr = COLOUR_ALIGN(addr, pgoff); -	else -		addr = PAGE_ALIGN(addr); - -	for (vma = find_vma(mm, addr); ; vma = vma->vm_next) { -		/* At this point:  (!vma || addr < vma->vm_end). */ -		if (TASK_SIZE - len < addr) { -			/* -			 * Start a new search - just in case we missed -			 * some holes. -			 */ -			if (start_addr != TASK_UNMAPPED_BASE) { -				start_addr = addr = TASK_UNMAPPED_BASE; -				mm->cached_hole_size = 0; -				goto full_search; -			} -			return -ENOMEM; -		} -		if (!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_align) -			addr = COLOUR_ALIGN(addr, pgoff); -	} +	info.flags = 0; +	info.length = len; +	info.low_limit = mm->mmap_base; +	info.high_limit = TASK_SIZE; +	info.align_mask = do_align ? (PAGE_MASK & (SHMLBA - 1)) : 0; +	info.align_offset = pgoff << PAGE_SHIFT; +	return vm_unmapped_area(&info);  }  unsigned long @@ -156,6 +112,7 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0,  	unsigned long addr = addr0;  	int do_align = 0;  	int aliasing = cache_is_vipt_aliasing(); +	struct vm_unmapped_area_info info;  	/*  	 * We only need to do colour alignment if either the I or D @@ -187,70 +144,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; -	} - -	/* either no address requested or can't fit in requested address hole */ -	addr = mm->free_area_cache; -	if (do_align) { -		unsigned long base = COLOUR_ALIGN_DOWN(addr - len, pgoff); -		addr = base + len; -	} - -	/* make sure it can fit in the remaining address space */ -	if (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 (mm->mmap_base < len) -		goto bottomup; - -	addr = mm->mmap_base - len; -	if (do_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 (!vma || addr+len <= vma->vm_start) -			/* remember the address as a hint for next time */ -			return (mm->free_area_cache = addr); +	info.flags = VM_UNMAPPED_AREA_TOPDOWN; +	info.length = len; +	info.low_limit = PAGE_SIZE; +	info.high_limit = mm->mmap_base; +	info.align_mask = do_align ? (PAGE_MASK & (SHMLBA - 1)) : 0; +	info.align_offset = pgoff << PAGE_SHIFT; +	addr = vm_unmapped_area(&info); -		/* 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_align) -			addr = COLOUR_ALIGN_DOWN(addr, pgoff); -	} while (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 = mm->mmap_base; +		info.high_limit = TASK_SIZE; +		addr = vm_unmapped_area(&info); +	}  	return addr;  } @@ -279,7 +193,7 @@ void arch_pick_mmap_layout(struct mm_struct *mm)   * You really shouldn't be using read() or write() on /dev/mem.  This   * might go away in the future.   */ -int valid_phys_addr_range(unsigned long addr, size_t size) +int valid_phys_addr_range(phys_addr_t addr, size_t size)  {  	if (addr < PHYS_OFFSET)  		return 0;  |