diff options
Diffstat (limited to 'arch/avr32/mm')
| -rw-r--r-- | arch/avr32/mm/cache.c | 3 | ||||
| -rw-r--r-- | arch/avr32/mm/dma-coherent.c | 1 | ||||
| -rw-r--r-- | arch/avr32/mm/fault.c | 38 | ||||
| -rw-r--r-- | arch/avr32/mm/init.c | 74 | 
4 files changed, 41 insertions, 75 deletions
diff --git a/arch/avr32/mm/cache.c b/arch/avr32/mm/cache.c index 24a74d1ca7d..85d635cd7b2 100644 --- a/arch/avr32/mm/cache.c +++ b/arch/avr32/mm/cache.c @@ -111,9 +111,10 @@ void flush_icache_range(unsigned long start, unsigned long end)  	__flush_icache_range(start & ~(linesz - 1),  			     (end + linesz - 1) & ~(linesz - 1));  } +EXPORT_SYMBOL(flush_icache_range);  /* - * This one is called from do_no_page(), do_swap_page() and install_page(). + * This one is called from __do_fault() and do_swap_page().   */  void flush_icache_page(struct vm_area_struct *vma, struct page *page)  { diff --git a/arch/avr32/mm/dma-coherent.c b/arch/avr32/mm/dma-coherent.c index 3c0042247ea..50cdb5b10f0 100644 --- a/arch/avr32/mm/dma-coherent.c +++ b/arch/avr32/mm/dma-coherent.c @@ -8,6 +8,7 @@  #include <linux/dma-mapping.h>  #include <linux/gfp.h> +#include <linux/export.h>  #include <asm/addrspace.h>  #include <asm/cacheflush.h> diff --git a/arch/avr32/mm/fault.c b/arch/avr32/mm/fault.c index f7040a1e399..0eca9332719 100644 --- a/arch/avr32/mm/fault.c +++ b/arch/avr32/mm/fault.c @@ -61,10 +61,10 @@ asmlinkage void do_page_fault(unsigned long ecr, struct pt_regs *regs)  	const struct exception_table_entry *fixup;  	unsigned long address;  	unsigned long page; -	int writeaccess;  	long signr;  	int code;  	int fault; +	unsigned int flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE;  	if (notify_page_fault(regs, ecr))  		return; @@ -86,6 +86,9 @@ asmlinkage void do_page_fault(unsigned long ecr, struct pt_regs *regs)  	local_irq_enable(); +	if (user_mode(regs)) +		flags |= FAULT_FLAG_USER; +retry:  	down_read(&mm->mmap_sem);  	vma = find_vma(mm, address); @@ -104,7 +107,6 @@ asmlinkage void do_page_fault(unsigned long ecr, struct pt_regs *regs)  	 */  good_area:  	code = SEGV_ACCERR; -	writeaccess = 0;  	switch (ecr) {  	case ECR_PROTECTION_X: @@ -121,7 +123,7 @@ good_area:  	case ECR_TLB_MISS_W:  		if (!(vma->vm_flags & VM_WRITE))  			goto bad_area; -		writeaccess = 1; +		flags |= FAULT_FLAG_WRITE;  		break;  	default:  		panic("Unhandled case %lu in do_page_fault!", ecr); @@ -132,7 +134,11 @@ good_area:  	 * sure we exit gracefully rather than endlessly redo the  	 * fault.  	 */ -	fault = handle_mm_fault(mm, vma, address, writeaccess ? FAULT_FLAG_WRITE : 0); +	fault = handle_mm_fault(mm, vma, address, flags); + +	if ((fault & VM_FAULT_RETRY) && fatal_signal_pending(current)) +		return; +  	if (unlikely(fault & VM_FAULT_ERROR)) {  		if (fault & VM_FAULT_OOM)  			goto out_of_memory; @@ -140,10 +146,24 @@ good_area:  			goto do_sigbus;  		BUG();  	} -	if (fault & VM_FAULT_MAJOR) -		tsk->maj_flt++; -	else -		tsk->min_flt++; + +	if (flags & FAULT_FLAG_ALLOW_RETRY) { +		if (fault & VM_FAULT_MAJOR) +			tsk->maj_flt++; +		else +			tsk->min_flt++; +		if (fault & VM_FAULT_RETRY) { +			flags &= ~FAULT_FLAG_ALLOW_RETRY; +			flags |= FAULT_FLAG_TRIED; + +			/* +			 * No need to up_read(&mm->mmap_sem) as we would have +			 * already released it in __lock_page_or_retry() in +			 * mm/filemap.c. +			 */ +			goto retry; +		} +	}  	up_read(&mm->mmap_sem);  	return; @@ -210,9 +230,9 @@ no_context:  	 */  out_of_memory:  	up_read(&mm->mmap_sem); -	pagefault_out_of_memory();  	if (!user_mode(regs))  		goto no_context; +	pagefault_out_of_memory();  	return;  do_sigbus: diff --git a/arch/avr32/mm/init.c b/arch/avr32/mm/init.c index a7314d44b17..def5391d927 100644 --- a/arch/avr32/mm/init.c +++ b/arch/avr32/mm/init.c @@ -25,8 +25,6 @@  #include <asm/setup.h>  #include <asm/sections.h> -DEFINE_PER_CPU(struct mmu_gather, mmu_gathers); -  pgd_t swapper_pg_dir[PTRS_PER_PGD] __page_aligned_data;  struct page *empty_zero_page; @@ -102,80 +100,26 @@ void __init paging_init(void)  void __init mem_init(void)  { -	int codesize, reservedpages, datasize, initsize; -	int nid, i; +	pg_data_t *pgdat; -	reservedpages = 0;  	high_memory = NULL; +	for_each_online_pgdat(pgdat) +		high_memory = max_t(void *, high_memory, +				    __va(pgdat_end_pfn(pgdat) << PAGE_SHIFT)); -	/* this will put all low memory onto the freelists */ -	for_each_online_node(nid) { -		pg_data_t *pgdat = NODE_DATA(nid); -		unsigned long node_pages = 0; -		void *node_high_memory; - -		num_physpages += pgdat->node_present_pages; - -		if (pgdat->node_spanned_pages != 0) -			node_pages = free_all_bootmem_node(pgdat); - -		totalram_pages += node_pages; - -		for (i = 0; i < node_pages; i++) -			if (PageReserved(pgdat->node_mem_map + i)) -				reservedpages++; - -		node_high_memory = (void *)((pgdat->node_start_pfn -					     + pgdat->node_spanned_pages) -					    << PAGE_SHIFT); -		if (node_high_memory > high_memory) -			high_memory = node_high_memory; -	} - -	max_mapnr = MAP_NR(high_memory); - -	codesize = (unsigned long)_etext - (unsigned long)_text; -	datasize = (unsigned long)_edata - (unsigned long)_data; -	initsize = (unsigned long)__init_end - (unsigned long)__init_begin; - -	printk ("Memory: %luk/%luk available (%dk kernel code, " -		"%dk reserved, %dk data, %dk init)\n", -		nr_free_pages() << (PAGE_SHIFT - 10), -		totalram_pages << (PAGE_SHIFT - 10), -		codesize >> 10, -		reservedpages << (PAGE_SHIFT - 10), -		datasize >> 10, -		initsize >> 10); -} - -static inline void free_area(unsigned long addr, unsigned long end, char *s) -{ -	unsigned int size = (end - addr) >> 10; - -	for (; addr < end; addr += PAGE_SIZE) { -		struct page *page = virt_to_page(addr); -		ClearPageReserved(page); -		init_page_count(page); -		free_page(addr); -		totalram_pages++; -	} - -	if (size && s) -		printk(KERN_INFO "Freeing %s memory: %dK (%lx - %lx)\n", -		       s, size, end - (size << 10), end); +	set_max_mapnr(MAP_NR(high_memory)); +	free_all_bootmem(); +	mem_init_print_info(NULL);  }  void free_initmem(void)  { -	free_area((unsigned long)__init_begin, (unsigned long)__init_end, -		  "init"); +	free_initmem_default(-1);  }  #ifdef CONFIG_BLK_DEV_INITRD -  void free_initrd_mem(unsigned long start, unsigned long end)  { -	free_area(start, end, "initrd"); +	free_reserved_area((void *)start, (void *)end, -1, "initrd");  } -  #endif  | 
