diff options
Diffstat (limited to 'arch/mn10300/mm')
| -rw-r--r-- | arch/mn10300/mm/Kconfig.cache | 46 | ||||
| -rw-r--r-- | arch/mn10300/mm/Makefile | 9 | ||||
| -rw-r--r-- | arch/mn10300/mm/cache-dbg-flush-by-reg.S | 160 | ||||
| -rw-r--r-- | arch/mn10300/mm/cache-dbg-flush-by-tag.S | 114 | ||||
| -rw-r--r-- | arch/mn10300/mm/cache-dbg-inv-by-reg.S | 69 | ||||
| -rw-r--r-- | arch/mn10300/mm/cache-dbg-inv-by-tag.S | 120 | ||||
| -rw-r--r-- | arch/mn10300/mm/cache-dbg-inv.S | 47 | ||||
| -rw-r--r-- | arch/mn10300/mm/cache-flush-by-tag.S | 13 | ||||
| -rw-r--r-- | arch/mn10300/mm/cache-inv-by-reg.S | 22 | ||||
| -rw-r--r-- | arch/mn10300/mm/cache-inv-by-tag.S | 86 | ||||
| -rw-r--r-- | arch/mn10300/mm/cache-inv-icache.c | 4 | ||||
| -rw-r--r-- | arch/mn10300/mm/cache-smp.c | 8 | ||||
| -rw-r--r-- | arch/mn10300/mm/cache.inc | 133 | ||||
| -rw-r--r-- | arch/mn10300/mm/dma-alloc.c | 1 | ||||
| -rw-r--r-- | arch/mn10300/mm/fault.c | 52 | ||||
| -rw-r--r-- | arch/mn10300/mm/init.c | 55 | ||||
| -rw-r--r-- | arch/mn10300/mm/misalignment.c | 3 | ||||
| -rw-r--r-- | arch/mn10300/mm/pgtable.c | 12 | ||||
| -rw-r--r-- | arch/mn10300/mm/tlb-smp.c | 37 | 
19 files changed, 794 insertions, 197 deletions
diff --git a/arch/mn10300/mm/Kconfig.cache b/arch/mn10300/mm/Kconfig.cache index c4fd923a55a..bfbe52691f2 100644 --- a/arch/mn10300/mm/Kconfig.cache +++ b/arch/mn10300/mm/Kconfig.cache @@ -99,3 +99,49 @@ config MN10300_CACHE_INV_ICACHE  	help  	  Set if we need the icache to be invalidated, even if the dcache is in  	  write-through mode and doesn't need flushing. + +# +# The kernel debugger gets its own separate cache flushing functions +# +config MN10300_DEBUGGER_CACHE_FLUSH_BY_TAG +	def_bool y if KERNEL_DEBUGGER && \ +			MN10300_CACHE_WBACK && \ +			!MN10300_CACHE_SNOOP && \ +			MN10300_CACHE_MANAGE_BY_TAG +	help +	  Set if the debugger needs to flush the dcache and invalidate the +	  icache using the cache tag registers to make breakpoints work. + +config MN10300_DEBUGGER_CACHE_FLUSH_BY_REG +	def_bool y if KERNEL_DEBUGGER && \ +			MN10300_CACHE_WBACK && \ +			!MN10300_CACHE_SNOOP && \ +			MN10300_CACHE_MANAGE_BY_REG +	help +	  Set if the debugger needs to flush the dcache and invalidate the +	  icache using automatic purge registers to make breakpoints work. + +config MN10300_DEBUGGER_CACHE_INV_BY_TAG +	def_bool y if KERNEL_DEBUGGER && \ +			MN10300_CACHE_WTHRU && \ +			!MN10300_CACHE_SNOOP && \ +			MN10300_CACHE_MANAGE_BY_TAG +	help +	  Set if the debugger needs to invalidate the icache using the cache +	  tag registers to make breakpoints work. + +config MN10300_DEBUGGER_CACHE_INV_BY_REG +	def_bool y if KERNEL_DEBUGGER && \ +			MN10300_CACHE_WTHRU && \ +			!MN10300_CACHE_SNOOP && \ +			MN10300_CACHE_MANAGE_BY_REG +	help +	  Set if the debugger needs to invalidate the icache using automatic +	  purge registers to make breakpoints work. + +config MN10300_DEBUGGER_CACHE_NO_FLUSH +	def_bool y if KERNEL_DEBUGGER && \ +			(MN10300_CACHE_DISABLED || MN10300_CACHE_SNOOP) +	help +	  Set if the debugger does not need to flush the dcache and/or +	  invalidate the icache to make breakpoints work. diff --git a/arch/mn10300/mm/Makefile b/arch/mn10300/mm/Makefile index 203fee23f7d..11f38466ac2 100644 --- a/arch/mn10300/mm/Makefile +++ b/arch/mn10300/mm/Makefile @@ -13,6 +13,15 @@ cacheflush-$(CONFIG_MN10300_CACHE_INV_BY_REG) += cache-inv-by-reg.o  cacheflush-$(CONFIG_MN10300_CACHE_FLUSH_BY_TAG) += cache-flush-by-tag.o  cacheflush-$(CONFIG_MN10300_CACHE_FLUSH_BY_REG) += cache-flush-by-reg.o +cacheflush-$(CONFIG_MN10300_DEBUGGER_CACHE_FLUSH_BY_TAG) += \ +	cache-dbg-flush-by-tag.o cache-dbg-inv-by-tag.o +cacheflush-$(CONFIG_MN10300_DEBUGGER_CACHE_FLUSH_BY_REG) += \ +	cache-dbg-flush-by-reg.o +cacheflush-$(CONFIG_MN10300_DEBUGGER_CACHE_INV_BY_TAG) += \ +	cache-dbg-inv-by-tag.o cache-dbg-inv.o +cacheflush-$(CONFIG_MN10300_DEBUGGER_CACHE_INV_BY_REG) += \ +	cache-dbg-inv-by-reg.o cache-dbg-inv.o +  cacheflush-$(CONFIG_MN10300_CACHE_DISABLED) := cache-disabled.o  obj-y := \ diff --git a/arch/mn10300/mm/cache-dbg-flush-by-reg.S b/arch/mn10300/mm/cache-dbg-flush-by-reg.S new file mode 100644 index 00000000000..a775ea5d7ce --- /dev/null +++ b/arch/mn10300/mm/cache-dbg-flush-by-reg.S @@ -0,0 +1,160 @@ +/* MN10300 CPU cache invalidation routines, using automatic purge registers + * + * Copyright (C) 2011 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public Licence + * as published by the Free Software Foundation; either version + * 2 of the Licence, or (at your option) any later version. + */ +#include <linux/sys.h> +#include <linux/linkage.h> +#include <asm/smp.h> +#include <asm/page.h> +#include <asm/cache.h> +#include <asm/irqflags.h> +#include <asm/cacheflush.h> +#include "cache.inc" + +	.am33_2 + +############################################################################### +# +# void debugger_local_cache_flushinv(void) +# Flush the entire data cache back to RAM and invalidate the icache +# +############################################################################### +	ALIGN +	.globl	debugger_local_cache_flushinv +        .type	debugger_local_cache_flushinv,@function +debugger_local_cache_flushinv: +	# +	# firstly flush the dcache +	# +	movhu	(CHCTR),d0 +	btst	CHCTR_DCEN|CHCTR_ICEN,d0 +	beq	debugger_local_cache_flushinv_end + +	mov	DCPGCR,a0 + +	mov	epsw,d1 +	and	~EPSW_IE,epsw +	or	EPSW_NMID,epsw +	nop + +	btst	CHCTR_DCEN,d0 +	beq	debugger_local_cache_flushinv_no_dcache + +	# wait for busy bit of area purge +	setlb +	mov	(a0),d0 +	btst	DCPGCR_DCPGBSY,d0 +	lne + +	# set mask +	clr	d0 +	mov	d0,(DCPGMR) + +	# area purge +	# +	# DCPGCR = DCPGCR_DCP +	# +	mov	DCPGCR_DCP,d0 +	mov	d0,(a0) + +	# wait for busy bit of area purge +	setlb +	mov	(a0),d0 +	btst	DCPGCR_DCPGBSY,d0 +	lne + +debugger_local_cache_flushinv_no_dcache: +	# +	# secondly, invalidate the icache if it is enabled +	# +	mov	CHCTR,a0 +	movhu	(a0),d0 +	btst	CHCTR_ICEN,d0 +	beq	debugger_local_cache_flushinv_done + +	invalidate_icache 0 + +debugger_local_cache_flushinv_done: +	mov	d1,epsw + +debugger_local_cache_flushinv_end: +	ret	[],0 +	.size	debugger_local_cache_flushinv,.-debugger_local_cache_flushinv + +############################################################################### +# +# void debugger_local_cache_flushinv_one(u8 *addr) +# +# Invalidate one particular cacheline if it's in the icache +# +############################################################################### +	ALIGN +	.globl	debugger_local_cache_flushinv_one +	.type	debugger_local_cache_flushinv_one,@function +debugger_local_cache_flushinv_one: +	movhu	(CHCTR),d1 +	btst	CHCTR_DCEN|CHCTR_ICEN,d1 +	beq	debugger_local_cache_flushinv_one_end +	btst	CHCTR_DCEN,d1 +	beq	debugger_local_cache_flushinv_one_no_dcache + +	# round cacheline addr down +	and	L1_CACHE_TAG_MASK,d0 +	mov	d0,a1 +	mov	d0,d1 + +	# determine the dcache purge control reg address +	mov	DCACHE_PURGE(0,0),a0 +	and	L1_CACHE_TAG_ENTRY,d0 +	add	d0,a0 + +	# retain valid entries in the cache +	or	L1_CACHE_TAG_VALID,d1 + +	# conditionally purge this line in all ways +	mov	d1,(L1_CACHE_WAYDISP*0,a0) + +debugger_local_cache_flushinv_one_no_dcache: +	# +	# now try to flush the icache +	# +	mov	CHCTR,a0 +	movhu	(a0),d0 +	btst	CHCTR_ICEN,d0 +	beq	debugger_local_cache_flushinv_one_end + +	LOCAL_CLI_SAVE(d1) + +	mov	ICIVCR,a0 + +	# wait for the invalidator to quiesce +	setlb +	mov	(a0),d0 +	btst	ICIVCR_ICIVBSY,d0 +	lne + +	# set the mask +	mov	L1_CACHE_TAG_MASK,d0 +	mov	d0,(ICIVMR) + +	# invalidate the cache line at the given address +	or	ICIVCR_ICI,a1 +	mov	a1,(a0) + +	# wait for the invalidator to quiesce again +	setlb +	mov	(a0),d0 +	btst	ICIVCR_ICIVBSY,d0 +	lne + +	LOCAL_IRQ_RESTORE(d1) + +debugger_local_cache_flushinv_one_end: +	ret	[],0 +	.size	debugger_local_cache_flushinv_one,.-debugger_local_cache_flushinv_one diff --git a/arch/mn10300/mm/cache-dbg-flush-by-tag.S b/arch/mn10300/mm/cache-dbg-flush-by-tag.S new file mode 100644 index 00000000000..bf56930e6e7 --- /dev/null +++ b/arch/mn10300/mm/cache-dbg-flush-by-tag.S @@ -0,0 +1,114 @@ +/* MN10300 CPU cache invalidation routines, using direct tag flushing + * + * Copyright (C) 2011 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public Licence + * as published by the Free Software Foundation; either version + * 2 of the Licence, or (at your option) any later version. + */ +#include <linux/sys.h> +#include <linux/linkage.h> +#include <asm/smp.h> +#include <asm/page.h> +#include <asm/cache.h> +#include <asm/irqflags.h> +#include <asm/cacheflush.h> +#include "cache.inc" + +	.am33_2 + +############################################################################### +# +# void debugger_local_cache_flushinv(void) +# +# Flush the entire data cache back to RAM and invalidate the icache +# +############################################################################### +	ALIGN +	.globl	debugger_local_cache_flushinv +        .type	debugger_local_cache_flushinv,@function +debugger_local_cache_flushinv: +	# +	# firstly flush the dcache +	# +	movhu	(CHCTR),d0 +	btst	CHCTR_DCEN|CHCTR_ICEN,d0 +	beq	debugger_local_cache_flushinv_end + +	btst	CHCTR_DCEN,d0 +	beq	debugger_local_cache_flushinv_no_dcache + +	# read the addresses tagged in the cache's tag RAM and attempt to flush +	# those addresses specifically +	# - we rely on the hardware to filter out invalid tag entry addresses +	mov	DCACHE_TAG(0,0),a0		# dcache tag RAM access address +	mov	DCACHE_PURGE(0,0),a1		# dcache purge request address +	mov	L1_CACHE_NWAYS*L1_CACHE_NENTRIES,e0  # total number of entries + +mn10300_local_dcache_flush_loop: +	mov	(a0),d0 +	and	L1_CACHE_TAG_MASK,d0 +	or	L1_CACHE_TAG_VALID,d0		# retain valid entries in the +						# cache +	mov	d0,(a1)				# conditional purge + +	add	L1_CACHE_BYTES,a0 +	add	L1_CACHE_BYTES,a1 +	add	-1,e0 +	bne	mn10300_local_dcache_flush_loop + +debugger_local_cache_flushinv_no_dcache: +	# +	# secondly, invalidate the icache if it is enabled +	# +	mov	CHCTR,a0 +	movhu	(a0),d0 +	btst	CHCTR_ICEN,d0 +	beq	debugger_local_cache_flushinv_end + +	invalidate_icache 1 + +debugger_local_cache_flushinv_end: +	ret	[],0 +	.size	debugger_local_cache_flushinv,.-debugger_local_cache_flushinv + +############################################################################### +# +# void debugger_local_cache_flushinv_one(u8 *addr) +# +# Invalidate one particular cacheline if it's in the icache +# +############################################################################### +	ALIGN +	.globl	debugger_local_cache_flushinv_one +	.type	debugger_local_cache_flushinv_one,@function +debugger_local_cache_flushinv_one: +	movhu	(CHCTR),d1 +	btst	CHCTR_DCEN|CHCTR_ICEN,d1 +	beq	debugger_local_cache_flushinv_one_end +	btst	CHCTR_DCEN,d1 +	beq	debugger_local_cache_flushinv_one_icache + +	# round cacheline addr down +	and	L1_CACHE_TAG_MASK,d0 +	mov	d0,a1 + +	# determine the dcache purge control reg address +	mov	DCACHE_PURGE(0,0),a0 +	and	L1_CACHE_TAG_ENTRY,d0 +	add	d0,a0 + +	# retain valid entries in the cache +	or	L1_CACHE_TAG_VALID,a1 + +	# conditionally purge this line in all ways +	mov	a1,(L1_CACHE_WAYDISP*0,a0) + +	# now go and do the icache +	bra	debugger_local_cache_flushinv_one_icache + +debugger_local_cache_flushinv_one_end: +	ret	[],0 +	.size	debugger_local_cache_flushinv_one,.-debugger_local_cache_flushinv_one diff --git a/arch/mn10300/mm/cache-dbg-inv-by-reg.S b/arch/mn10300/mm/cache-dbg-inv-by-reg.S new file mode 100644 index 00000000000..c4e6252941b --- /dev/null +++ b/arch/mn10300/mm/cache-dbg-inv-by-reg.S @@ -0,0 +1,69 @@ +/* MN10300 CPU cache invalidation routines, using automatic purge registers + * + * Copyright (C) 2011 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public Licence + * as published by the Free Software Foundation; either version + * 2 of the Licence, or (at your option) any later version. + */ +#include <linux/sys.h> +#include <linux/linkage.h> +#include <asm/cache.h> +#include <asm/irqflags.h> +#include <asm/cacheflush.h> +#include "cache.inc" + +	.am33_2 + +	.globl	debugger_local_cache_flushinv_one + +############################################################################### +# +# void debugger_local_cache_flushinv_one(u8 *addr) +# +# Invalidate one particular cacheline if it's in the icache +# +############################################################################### +	ALIGN +	.globl	debugger_local_cache_flushinv_one +	.type	debugger_local_cache_flushinv_one,@function +debugger_local_cache_flushinv_one: +	mov	d0,a1 + +	mov	CHCTR,a0 +	movhu	(a0),d0 +	btst	CHCTR_ICEN,d0 +	beq	mn10300_local_icache_inv_range_reg_end + +	LOCAL_CLI_SAVE(d1) + +	mov	ICIVCR,a0 + +	# wait for the invalidator to quiesce +	setlb +	mov	(a0),d0 +	btst	ICIVCR_ICIVBSY,d0 +	lne + +	# set the mask +	mov	~L1_CACHE_TAG_MASK,d0 +	mov	d0,(ICIVMR) + +	# invalidate the cache line at the given address +	and	~L1_CACHE_TAG_MASK,a1 +	or	ICIVCR_ICI,a1 +	mov	a1,(a0) + +	# wait for the invalidator to quiesce again +	setlb +	mov	(a0),d0 +	btst	ICIVCR_ICIVBSY,d0 +	lne + +	LOCAL_IRQ_RESTORE(d1) + +mn10300_local_icache_inv_range_reg_end: +	ret	[],0 +	.size	debugger_local_cache_flushinv_one,.-debugger_local_cache_flushinv_one diff --git a/arch/mn10300/mm/cache-dbg-inv-by-tag.S b/arch/mn10300/mm/cache-dbg-inv-by-tag.S new file mode 100644 index 00000000000..d8ec821e5f8 --- /dev/null +++ b/arch/mn10300/mm/cache-dbg-inv-by-tag.S @@ -0,0 +1,120 @@ +/* MN10300 CPU cache invalidation routines, using direct tag flushing + * + * Copyright (C) 2011 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public Licence + * as published by the Free Software Foundation; either version + * 2 of the Licence, or (at your option) any later version. + */ +#include <linux/sys.h> +#include <linux/linkage.h> +#include <asm/smp.h> +#include <asm/page.h> +#include <asm/cache.h> +#include <asm/irqflags.h> +#include <asm/cacheflush.h> +#include "cache.inc" + +	.am33_2 + +	.globl	debugger_local_cache_flushinv_one_icache + +############################################################################### +# +# void debugger_local_cache_flushinv_one(u8 *addr) +# +# Invalidate one particular cacheline if it's in the icache +# +############################################################################### +	ALIGN +	.globl	debugger_local_cache_flushinv_one_icache +	.type	debugger_local_cache_flushinv_one_icache,@function +debugger_local_cache_flushinv_one_icache: +	movm	[d3,a2],(sp) + +	mov	CHCTR,a2 +	movhu	(a2),d0 +	btst	CHCTR_ICEN,d0 +	beq	debugger_local_cache_flushinv_one_icache_end + +	mov	d0,a1 +	and	L1_CACHE_TAG_MASK,a1 + +	# read the tags from the tag RAM, and if they indicate a matching valid +	# cache line then we invalidate that line +	mov	ICACHE_TAG(0,0),a0 +	mov	a1,d0 +	and	L1_CACHE_TAG_ENTRY,d0 +	add	d0,a0				# starting icache tag RAM +						# access address + +	and	~(L1_CACHE_DISPARITY-1),a1	# determine comparator base +	or	L1_CACHE_TAG_VALID,a1 +	mov	L1_CACHE_TAG_ADDRESS|L1_CACHE_TAG_VALID,d1 + +	LOCAL_CLI_SAVE(d3) + +	# disable the icache +	movhu	(a2),d0 +	and	~CHCTR_ICEN,d0 +	movhu	d0,(a2) + +	# and wait for it to calm down +	setlb +	movhu	(a2),d0 +	btst	CHCTR_ICBUSY,d0 +	lne + +	# check all the way tags for this cache entry +	mov	(a0),d0				# read the tag in the way 0 slot +	xor	a1,d0 +	and	d1,d0 +	beq	debugger_local_icache_kill	# jump if matched + +	add	L1_CACHE_WAYDISP,a0 +	mov	(a0),d0				# read the tag in the way 1 slot +	xor	a1,d0 +	and	d1,d0 +	beq	debugger_local_icache_kill	# jump if matched + +	add	L1_CACHE_WAYDISP,a0 +	mov	(a0),d0				# read the tag in the way 2 slot +	xor	a1,d0 +	and	d1,d0 +	beq	debugger_local_icache_kill	# jump if matched + +	add	L1_CACHE_WAYDISP,a0 +	mov	(a0),d0				# read the tag in the way 3 slot +	xor	a1,d0 +	and	d1,d0 +	bne	debugger_local_icache_finish	# jump if not matched + +debugger_local_icache_kill: +	mov	d0,(a0)				# kill the tag (D0 is 0 at this point) + +debugger_local_icache_finish: +	# wait for the cache to finish what it's doing +	setlb +	movhu	(a2),d0 +	btst	CHCTR_ICBUSY,d0 +	lne + +	# and reenable it +	or	CHCTR_ICEN,d0 +	movhu	d0,(a2) +	movhu	(a2),d0 + +	# re-enable interrupts +	LOCAL_IRQ_RESTORE(d3) + +debugger_local_cache_flushinv_one_icache_end: +	ret	[d3,a2],8 +	.size	debugger_local_cache_flushinv_one_icache,.-debugger_local_cache_flushinv_one_icache + +#ifdef CONFIG_MN10300_DEBUGGER_CACHE_INV_BY_TAG +	.globl	debugger_local_cache_flushinv_one +	.type	debugger_local_cache_flushinv_one,@function +debugger_local_cache_flushinv_one = debugger_local_cache_flushinv_one_icache +#endif diff --git a/arch/mn10300/mm/cache-dbg-inv.S b/arch/mn10300/mm/cache-dbg-inv.S new file mode 100644 index 00000000000..eba2d6dca06 --- /dev/null +++ b/arch/mn10300/mm/cache-dbg-inv.S @@ -0,0 +1,47 @@ +/* MN10300 CPU cache invalidation routines + * + * Copyright (C) 2011 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public Licence + * as published by the Free Software Foundation; either version + * 2 of the Licence, or (at your option) any later version. + */ +#include <linux/sys.h> +#include <linux/linkage.h> +#include <asm/smp.h> +#include <asm/page.h> +#include <asm/cache.h> +#include <asm/irqflags.h> +#include <asm/cacheflush.h> +#include "cache.inc" + +	.am33_2 + +	.globl	debugger_local_cache_flushinv + +############################################################################### +# +# void debugger_local_cache_flushinv(void) +# +# Invalidate the entire icache +# +############################################################################### +	ALIGN +	.globl	debugger_local_cache_flushinv +        .type	debugger_local_cache_flushinv,@function +debugger_local_cache_flushinv: +	# +	# we only need to invalidate the icache in this cache mode +	# +	mov	CHCTR,a0 +	movhu	(a0),d0 +	btst	CHCTR_ICEN,d0 +	beq	debugger_local_cache_flushinv_end + +	invalidate_icache 1 + +debugger_local_cache_flushinv_end: +	ret	[],0 +	.size	debugger_local_cache_flushinv,.-debugger_local_cache_flushinv diff --git a/arch/mn10300/mm/cache-flush-by-tag.S b/arch/mn10300/mm/cache-flush-by-tag.S index 5cd6a27dd63..1ddc0684924 100644 --- a/arch/mn10300/mm/cache-flush-by-tag.S +++ b/arch/mn10300/mm/cache-flush-by-tag.S @@ -62,7 +62,7 @@ mn10300_local_dcache_flush:  mn10300_local_dcache_flush_loop:  	mov	(a0),d0 -	and	L1_CACHE_TAG_ADDRESS|L1_CACHE_TAG_ENTRY,d0 +	and	L1_CACHE_TAG_MASK,d0  	or	L1_CACHE_TAG_VALID,d0		# retain valid entries in the  						# cache  	mov	d0,(a1)				# conditional purge @@ -112,11 +112,11 @@ mn10300_local_dcache_flush_range:  1:  	# round start addr down -	and	L1_CACHE_TAG_ADDRESS|L1_CACHE_TAG_ENTRY,d0 +	and	L1_CACHE_TAG_MASK,d0  	mov	d0,a1  	add	L1_CACHE_BYTES,d1			# round end addr up -	and	L1_CACHE_TAG_ADDRESS|L1_CACHE_TAG_ENTRY,d1 +	and	L1_CACHE_TAG_MASK,d1  	# write a request to flush all instances of an address from the cache  	mov	DCACHE_PURGE(0,0),a0 @@ -215,12 +215,11 @@ mn10300_local_dcache_flush_inv_range:  	bra	mn10300_local_dcache_flush_inv  1: -	and	L1_CACHE_TAG_ADDRESS|L1_CACHE_TAG_ENTRY,d0	# round start -								# addr down +	and	L1_CACHE_TAG_MASK,d0		# round start addr down  	mov	d0,a1 -	add	L1_CACHE_BYTES,d1			# round end addr up -	and	L1_CACHE_TAG_ADDRESS|L1_CACHE_TAG_ENTRY,d1 +	add	L1_CACHE_BYTES,d1		# round end addr up +	and	L1_CACHE_TAG_MASK,d1  	# write a request to flush and invalidate all instances of an address  	# from the cache diff --git a/arch/mn10300/mm/cache-inv-by-reg.S b/arch/mn10300/mm/cache-inv-by-reg.S index c8950861ed7..a60825b91e7 100644 --- a/arch/mn10300/mm/cache-inv-by-reg.S +++ b/arch/mn10300/mm/cache-inv-by-reg.S @@ -15,6 +15,7 @@  #include <asm/cache.h>  #include <asm/irqflags.h>  #include <asm/cacheflush.h> +#include "cache.inc"  #define mn10300_local_dcache_inv_range_intr_interval \  	+((1 << MN10300_DCACHE_INV_RANGE_INTR_LOG2_INTERVAL) - 1) @@ -62,10 +63,7 @@ mn10300_local_icache_inv:  	btst	CHCTR_ICEN,d0  	beq	mn10300_local_icache_inv_end -	# invalidate -	or	CHCTR_ICINV,d0 -	movhu	d0,(a0) -	movhu	(a0),d0 +	invalidate_icache 1  mn10300_local_icache_inv_end:  	ret	[],0 @@ -87,11 +85,8 @@ mn10300_local_dcache_inv:  	btst	CHCTR_DCEN,d0  	beq	mn10300_local_dcache_inv_end -	# invalidate -	or	CHCTR_DCINV,d0 -	movhu	d0,(a0) -	movhu	(a0),d0 - +	invalidate_dcache 1 +	  mn10300_local_dcache_inv_end:  	ret	[],0  	.size	mn10300_local_dcache_inv,.-mn10300_local_dcache_inv @@ -121,9 +116,9 @@ mn10300_local_dcache_inv_range:  	# and if they're not cacheline-aligned, we must flush any bits outside  	# the range that share cachelines with stuff inside the range  #ifdef CONFIG_MN10300_CACHE_WBACK -	btst	~(L1_CACHE_BYTES-1),d0 +	btst	~L1_CACHE_TAG_MASK,d0  	bne	1f -	btst	~(L1_CACHE_BYTES-1),d1 +	btst	~L1_CACHE_TAG_MASK,d1  	beq	2f  1:  	bra	mn10300_local_dcache_flush_inv_range @@ -141,12 +136,11 @@ mn10300_local_dcache_inv_range:  	# writeback mode, in which case we would be in flush and invalidate by  	# now  #ifndef CONFIG_MN10300_CACHE_WBACK -	and	L1_CACHE_TAG_ADDRESS|L1_CACHE_TAG_ENTRY,d0	# round start -								# addr down +	and	L1_CACHE_TAG_MASK,d0	# round start addr down  	mov	L1_CACHE_BYTES-1,d2  	add	d2,d1 -	and	L1_CACHE_TAG_ADDRESS|L1_CACHE_TAG_ENTRY,d1	# round end addr up +	and	L1_CACHE_TAG_MASK,d1	# round end addr up  #endif /* !CONFIG_MN10300_CACHE_WBACK */  	sub	d0,d1,d2		# calculate the total size diff --git a/arch/mn10300/mm/cache-inv-by-tag.S b/arch/mn10300/mm/cache-inv-by-tag.S index e9713b40c0f..ccedce9c144 100644 --- a/arch/mn10300/mm/cache-inv-by-tag.S +++ b/arch/mn10300/mm/cache-inv-by-tag.S @@ -15,6 +15,7 @@  #include <asm/cache.h>  #include <asm/irqflags.h>  #include <asm/cacheflush.h> +#include "cache.inc"  #define mn10300_local_dcache_inv_range_intr_interval \  	+((1 << MN10300_DCACHE_INV_RANGE_INTR_LOG2_INTERVAL) - 1) @@ -70,43 +71,7 @@ mn10300_local_icache_inv:  	btst	CHCTR_ICEN,d0  	beq	mn10300_local_icache_inv_end -#if defined(CONFIG_AM33_2) || defined(CONFIG_AM33_3) -	LOCAL_CLI_SAVE(d1) - -	# disable the icache -	and	~CHCTR_ICEN,d0 -	movhu	d0,(a0) - -	# and wait for it to calm down -	setlb -	movhu	(a0),d0 -	btst	CHCTR_ICBUSY,d0 -	lne - -	# invalidate -	or	CHCTR_ICINV,d0 -	movhu	d0,(a0) - -	# wait for the cache to finish -	mov	CHCTR,a0 -	setlb -	movhu	(a0),d0 -	btst	CHCTR_ICBUSY,d0 -	lne - -	# and reenable it -	and	~CHCTR_ICINV,d0 -	or	CHCTR_ICEN,d0 -	movhu	d0,(a0) -	movhu	(a0),d0 - -	LOCAL_IRQ_RESTORE(d1) -#else /* CONFIG_AM33_2 || CONFIG_AM33_3 */ -	# invalidate -	or	CHCTR_ICINV,d0 -	movhu	d0,(a0) -	movhu	(a0),d0 -#endif /* CONFIG_AM33_2 || CONFIG_AM33_3 */ +	invalidate_icache 1  mn10300_local_icache_inv_end:  	ret	[],0 @@ -128,43 +93,7 @@ mn10300_local_dcache_inv:  	btst	CHCTR_DCEN,d0  	beq	mn10300_local_dcache_inv_end -#if defined(CONFIG_AM33_2) || defined(CONFIG_AM33_3) -	LOCAL_CLI_SAVE(d1) - -	# disable the dcache -	and	~CHCTR_DCEN,d0 -	movhu	d0,(a0) - -	# and wait for it to calm down -	setlb -	movhu	(a0),d0 -	btst	CHCTR_DCBUSY,d0 -	lne - -	# invalidate -	or	CHCTR_DCINV,d0 -	movhu	d0,(a0) - -	# wait for the cache to finish -	mov	CHCTR,a0 -	setlb -	movhu	(a0),d0 -	btst	CHCTR_DCBUSY,d0 -	lne - -	# and reenable it -	and	~CHCTR_DCINV,d0 -	or	CHCTR_DCEN,d0 -	movhu	d0,(a0) -	movhu	(a0),d0 - -	LOCAL_IRQ_RESTORE(d1) -#else /* CONFIG_AM33_2 || CONFIG_AM33_3 */ -	# invalidate -	or	CHCTR_DCINV,d0 -	movhu	d0,(a0) -	movhu	(a0),d0 -#endif /* CONFIG_AM33_2 || CONFIG_AM33_3 */ +	invalidate_dcache 1  mn10300_local_dcache_inv_end:  	ret	[],0 @@ -195,9 +124,9 @@ mn10300_local_dcache_inv_range:  	# and if they're not cacheline-aligned, we must flush any bits outside  	# the range that share cachelines with stuff inside the range  #ifdef CONFIG_MN10300_CACHE_WBACK -	btst	~(L1_CACHE_BYTES-1),d0 +	btst	~L1_CACHE_TAG_MASK,d0  	bne	1f -	btst	~(L1_CACHE_BYTES-1),d1 +	btst	~L1_CACHE_TAG_MASK,d1  	beq	2f  1:  	bra	mn10300_local_dcache_flush_inv_range @@ -212,11 +141,10 @@ mn10300_local_dcache_inv_range:  	beq	mn10300_local_dcache_inv_range_end  #ifndef CONFIG_MN10300_CACHE_WBACK -	and	L1_CACHE_TAG_ADDRESS|L1_CACHE_TAG_ENTRY,d0	# round start -								# addr down +	and	L1_CACHE_TAG_MASK,d0		# round start addr down  	add	L1_CACHE_BYTES,d1		# round end addr up -	and	L1_CACHE_TAG_ADDRESS|L1_CACHE_TAG_ENTRY,d1 +	and	L1_CACHE_TAG_MASK,d1  #endif /* !CONFIG_MN10300_CACHE_WBACK */  	mov	d0,a1 diff --git a/arch/mn10300/mm/cache-inv-icache.c b/arch/mn10300/mm/cache-inv-icache.c index a8933a60b2d..a6b63dde603 100644 --- a/arch/mn10300/mm/cache-inv-icache.c +++ b/arch/mn10300/mm/cache-inv-icache.c @@ -69,7 +69,7 @@ static void flush_icache_page_range(unsigned long start, unsigned long end)  	/* invalidate the icache coverage on that region */  	mn10300_local_icache_inv_range2(addr + off, size); -	smp_cache_call(SMP_ICACHE_INV_FLUSH_RANGE, start, end); +	smp_cache_call(SMP_ICACHE_INV_RANGE, start, end);  }  /** @@ -101,7 +101,7 @@ void flush_icache_range(unsigned long start, unsigned long end)  		 * directly */  		start_page = (start >= 0x80000000UL) ? start : 0x80000000UL;  		mn10300_icache_inv_range(start_page, end); -		smp_cache_call(SMP_ICACHE_INV_FLUSH_RANGE, start, end); +		smp_cache_call(SMP_ICACHE_INV_RANGE, start, end);  		if (start_page == start)  			goto done;  		end = start_page; diff --git a/arch/mn10300/mm/cache-smp.c b/arch/mn10300/mm/cache-smp.c index 4a6e9a4b5b2..2d23b9eeee6 100644 --- a/arch/mn10300/mm/cache-smp.c +++ b/arch/mn10300/mm/cache-smp.c @@ -74,7 +74,7 @@ void smp_cache_interrupt(void)  		break;  	} -	cpu_clear(smp_processor_id(), smp_cache_ipi_map); +	cpumask_clear_cpu(smp_processor_id(), &smp_cache_ipi_map);  }  /** @@ -94,12 +94,12 @@ void smp_cache_call(unsigned long opr_mask,  	smp_cache_mask = opr_mask;  	smp_cache_start = start;  	smp_cache_end = end; -	smp_cache_ipi_map = cpu_online_map; -	cpu_clear(smp_processor_id(), smp_cache_ipi_map); +	cpumask_copy(&smp_cache_ipi_map, cpu_online_mask); +	cpumask_clear_cpu(smp_processor_id(), &smp_cache_ipi_map);  	send_IPI_allbutself(FLUSH_CACHE_IPI); -	while (!cpus_empty(smp_cache_ipi_map)) +	while (!cpumask_empty(&smp_cache_ipi_map))  		/* nothing. lockup detection does not belong here */  		mb();  } diff --git a/arch/mn10300/mm/cache.inc b/arch/mn10300/mm/cache.inc new file mode 100644 index 00000000000..394a119b9c7 --- /dev/null +++ b/arch/mn10300/mm/cache.inc @@ -0,0 +1,133 @@ +/* MN10300 CPU core caching macros -*- asm -*- + * + * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public Licence + * as published by the Free Software Foundation; either version + * 2 of the Licence, or (at your option) any later version. + */ + + +############################################################################### +# +# Invalidate the instruction cache. +#	A0: Should hold CHCTR +#	D0: Should have been read from CHCTR +#	D1: Will be clobbered +# +# On some cores it is necessary to disable the icache whilst we do this. +# +############################################################################### +	.macro invalidate_icache,disable_irq + +#if defined(CONFIG_AM33_2) || defined(CONFIG_AM33_3) +	.if \disable_irq +	# don't want an interrupt routine seeing a disabled cache +	mov	epsw,d1 +	and	~EPSW_IE,epsw +	or	EPSW_NMID,epsw +	nop +	nop +	.endif + +	# disable the icache +	and	~CHCTR_ICEN,d0 +	movhu	d0,(a0) + +	# and wait for it to calm down +	setlb +	movhu	(a0),d0 +	btst	CHCTR_ICBUSY,d0 +	lne + +	# invalidate +	or	CHCTR_ICINV,d0 +	movhu	d0,(a0) + +	# wait for the cache to finish +	setlb +	movhu	(a0),d0 +	btst	CHCTR_ICBUSY,d0 +	lne + +	# and reenable it +	or	CHCTR_ICEN,d0 +	movhu	d0,(a0) +	movhu	(a0),d0 + +	.if \disable_irq +	LOCAL_IRQ_RESTORE(d1) +	.endif + +#else /* CONFIG_AM33_2 || CONFIG_AM33_3 */ + +	# invalidate +	or	CHCTR_ICINV,d0 +	movhu	d0,(a0) +	movhu	(a0),d0 + +#endif /* CONFIG_AM33_2 || CONFIG_AM33_3 */ +	.endm + +############################################################################### +# +# Invalidate the data cache. +#	A0: Should hold CHCTR +#	D0: Should have been read from CHCTR +#	D1: Will be clobbered +# +# On some cores it is necessary to disable the dcache whilst we do this. +# +############################################################################### +	.macro invalidate_dcache,disable_irq + +#if defined(CONFIG_AM33_2) || defined(CONFIG_AM33_3) +	.if \disable_irq +	# don't want an interrupt routine seeing a disabled cache +	mov	epsw,d1 +	and	~EPSW_IE,epsw +	or	EPSW_NMID,epsw +	nop +	nop +	.endif +	 +	# disable the dcache +	and	~CHCTR_DCEN,d0 +	movhu	d0,(a0) + +	# and wait for it to calm down +	setlb +	movhu	(a0),d0 +	btst	CHCTR_DCBUSY,d0 +	lne + +	# invalidate +	or	CHCTR_DCINV,d0 +	movhu	d0,(a0) + +	# wait for the cache to finish +	setlb +	movhu	(a0),d0 +	btst	CHCTR_DCBUSY,d0 +	lne + +	# and reenable it +	or	CHCTR_DCEN,d0 +	movhu	d0,(a0) +	movhu	(a0),d0 + +	.if \disable_irq +	LOCAL_IRQ_RESTORE(d1) +	.endif + +#else /* CONFIG_AM33_2 || CONFIG_AM33_3 */ + +	# invalidate +	or	CHCTR_DCINV,d0 +	movhu	d0,(a0) +	movhu	(a0),d0 + +#endif /* CONFIG_AM33_2 || CONFIG_AM33_3 */ +	.endm diff --git a/arch/mn10300/mm/dma-alloc.c b/arch/mn10300/mm/dma-alloc.c index 159acb02cfd..e244ebe637e 100644 --- a/arch/mn10300/mm/dma-alloc.c +++ b/arch/mn10300/mm/dma-alloc.c @@ -15,6 +15,7 @@  #include <linux/string.h>  #include <linux/pci.h>  #include <linux/gfp.h> +#include <linux/export.h>  #include <asm/io.h>  static unsigned long pci_sram_allocated = 0xbc000000; diff --git a/arch/mn10300/mm/fault.c b/arch/mn10300/mm/fault.c index 59c3da49d9d..3516cbdf1ee 100644 --- a/arch/mn10300/mm/fault.c +++ b/arch/mn10300/mm/fault.c @@ -24,12 +24,12 @@  #include <linux/init.h>  #include <linux/vt_kern.h>		/* For unblank_screen() */ -#include <asm/system.h>  #include <asm/uaccess.h>  #include <asm/pgalloc.h>  #include <asm/hardirq.h> -#include <asm/gdb-stub.h>  #include <asm/cpu-regs.h> +#include <asm/debugger.h> +#include <asm/gdb-stub.h>  /*   * Unlock any spinlocks which will prevent us from getting the @@ -123,7 +123,8 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long fault_code,  	struct mm_struct *mm;  	unsigned long page;  	siginfo_t info; -	int write, fault; +	int fault; +	unsigned int flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE;  #ifdef CONFIG_GDBSTUB  	/* handle GDB stub causing a fault */ @@ -170,6 +171,9 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long fault_code,  	if (in_atomic() || !mm)  		goto no_context; +	if ((fault_code & MMUFCR_xFC_ACCESS) == MMUFCR_xFC_ACCESS_USR) +		flags |= FAULT_FLAG_USER; +retry:  	down_read(&mm->mmap_sem);  	vma = find_vma(mm, address); @@ -220,7 +224,6 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long fault_code,   */  good_area:  	info.si_code = SEGV_ACCERR; -	write = 0;  	switch (fault_code & (MMUFCR_xFC_PGINVAL|MMUFCR_xFC_TYPE)) {  	default:	/* 3: write, present */  	case MMUFCR_xFC_TYPE_WRITE: @@ -232,7 +235,7 @@ good_area:  	case MMUFCR_xFC_PGINVAL | MMUFCR_xFC_TYPE_WRITE:  		if (!(vma->vm_flags & VM_WRITE))  			goto bad_area; -		write++; +		flags |= FAULT_FLAG_WRITE;  		break;  		/* read from protected page */ @@ -251,7 +254,11 @@ good_area:  	 * make sure we exit gracefully rather than endlessly redo  	 * the fault.  	 */ -	fault = handle_mm_fault(mm, vma, address, write ? 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; @@ -259,10 +266,22 @@ good_area:  			goto do_sigbus;  		BUG();  	} -	if (fault & VM_FAULT_MAJOR) -		current->maj_flt++; -	else -		current->min_flt++; +	if (flags & FAULT_FLAG_ALLOW_RETRY) { +		if (fault & VM_FAULT_MAJOR) +			current->maj_flt++; +		else +			current->min_flt++; +		if (fault & VM_FAULT_RETRY) { +			flags &= ~FAULT_FLAG_ALLOW_RETRY; + +			 /* 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; @@ -306,10 +325,8 @@ no_context:  	printk(" printing pc:\n");  	printk(KERN_ALERT "%08lx\n", regs->pc); -#ifdef CONFIG_GDBSTUB -	gdbstub_intercept( -		regs, fault_code & 0x00010000 ? EXCEP_IAERROR : EXCEP_DAERROR); -#endif +	debugger_intercept(fault_code & 0x00010000 ? EXCEP_IAERROR : EXCEP_DAERROR, +			   SIGSEGV, SEGV_ACCERR, regs);  	page = PTBR;  	page = ((unsigned long *) __va(page))[address >> 22]; @@ -330,9 +347,10 @@ no_context:   */  out_of_memory:  	up_read(&mm->mmap_sem); -	printk(KERN_ALERT "VM: killing process %s\n", tsk->comm); -	if ((fault_code & MMUFCR_xFC_ACCESS) == MMUFCR_xFC_ACCESS_USR) -		do_exit(SIGKILL); +	if ((fault_code & MMUFCR_xFC_ACCESS) == MMUFCR_xFC_ACCESS_USR) { +		pagefault_out_of_memory(); +		return; +	}  	goto no_context;  do_sigbus: diff --git a/arch/mn10300/mm/init.c b/arch/mn10300/mm/init.c index 48907cc3bdb..97a1ec0beee 100644 --- a/arch/mn10300/mm/init.c +++ b/arch/mn10300/mm/init.c @@ -29,7 +29,6 @@  #include <linux/gfp.h>  #include <asm/processor.h> -#include <asm/system.h>  #include <asm/uaccess.h>  #include <asm/pgtable.h>  #include <asm/pgalloc.h> @@ -37,8 +36,6 @@  #include <asm/tlb.h>  #include <asm/sections.h> -DEFINE_PER_CPU(struct mmu_gather, mmu_gathers); -  unsigned long highstart_pfn, highend_pfn;  #ifdef CONFIG_MN10300_HAS_ATOMIC_OPS_UNIT @@ -102,60 +99,21 @@ void __init paging_init(void)   */  void __init mem_init(void)  { -	int codesize, reservedpages, datasize, initsize; -	int tmp; -  	BUG_ON(!mem_map);  #define START_PFN	(contig_page_data.bdata->node_min_pfn)  #define MAX_LOW_PFN	(contig_page_data.bdata->node_low_pfn) -	max_mapnr = num_physpages = MAX_LOW_PFN - START_PFN; +	max_mapnr = MAX_LOW_PFN - START_PFN;  	high_memory = (void *) __va(MAX_LOW_PFN * PAGE_SIZE);  	/* clear the zero-page */  	memset(empty_zero_page, 0, PAGE_SIZE);  	/* this will put all low memory onto the freelists */ -	totalram_pages += free_all_bootmem(); - -	reservedpages = 0; -	for (tmp = 0; tmp < num_physpages; tmp++) -		if (PageReserved(&mem_map[tmp])) -			reservedpages++; - -	codesize =  (unsigned long) &_etext - (unsigned long) &_stext; -	datasize =  (unsigned long) &_edata - (unsigned long) &_etext; -	initsize =  (unsigned long) &__init_end - (unsigned long) &__init_begin; - -	printk(KERN_INFO -	       "Memory: %luk/%luk available" -	       " (%dk kernel code, %dk reserved, %dk data, %dk init," -	       " %ldk highmem)\n", -	       nr_free_pages() << (PAGE_SHIFT - 10), -	       max_mapnr << (PAGE_SHIFT - 10), -	       codesize >> 10, -	       reservedpages << (PAGE_SHIFT - 10), -	       datasize >> 10, -	       initsize >> 10, -	       totalhigh_pages << (PAGE_SHIFT - 10)); -} +	free_all_bootmem(); -/* - * - */ -void free_init_pages(char *what, unsigned long begin, unsigned long end) -{ -	unsigned long addr; - -	for (addr = begin; addr < end; addr += PAGE_SIZE) { -		ClearPageReserved(virt_to_page(addr)); -		init_page_count(virt_to_page(addr)); -		memset((void *) addr, 0xcc, PAGE_SIZE); -		free_page(addr); -		totalram_pages++; -	} -	printk(KERN_INFO "Freeing %s: %ldk freed\n", what, (end - begin) >> 10); +	mem_init_print_info(NULL);  }  /* @@ -163,9 +121,7 @@ void free_init_pages(char *what, unsigned long begin, unsigned long end)   */  void free_initmem(void)  { -	free_init_pages("unused kernel memory", -			(unsigned long) &__init_begin, -			(unsigned long) &__init_end); +	free_initmem_default(POISON_FREE_INITMEM);  }  /* @@ -174,6 +130,7 @@ void free_initmem(void)  #ifdef CONFIG_BLK_DEV_INITRD  void free_initrd_mem(unsigned long start, unsigned long end)  { -	free_init_pages("initrd memory", start, end); +	free_reserved_area((void *)start, (void *)end, POISON_FREE_INITMEM, +			   "initrd");  }  #endif diff --git a/arch/mn10300/mm/misalignment.c b/arch/mn10300/mm/misalignment.c index eef989c1d0c..b9920b1edd5 100644 --- a/arch/mn10300/mm/misalignment.c +++ b/arch/mn10300/mm/misalignment.c @@ -23,10 +23,9 @@  #include <linux/interrupt.h>  #include <linux/pci.h>  #include <asm/processor.h> -#include <asm/system.h>  #include <asm/uaccess.h>  #include <asm/io.h> -#include <asm/atomic.h> +#include <linux/atomic.h>  #include <asm/smp.h>  #include <asm/pgalloc.h>  #include <asm/cpu-regs.h> diff --git a/arch/mn10300/mm/pgtable.c b/arch/mn10300/mm/pgtable.c index 450f7ba3f8f..e77a7c72808 100644 --- a/arch/mn10300/mm/pgtable.c +++ b/arch/mn10300/mm/pgtable.c @@ -21,7 +21,6 @@  #include <linux/spinlock.h>  #include <linux/quicklist.h> -#include <asm/system.h>  #include <asm/pgtable.h>  #include <asm/pgalloc.h>  #include <asm/tlb.h> @@ -79,8 +78,13 @@ struct page *pte_alloc_one(struct mm_struct *mm, unsigned long address)  #else  	pte = alloc_pages(GFP_KERNEL|__GFP_REPEAT, 0);  #endif -	if (pte) -		clear_highpage(pte); +	if (!pte) +		return NULL; +	clear_highpage(pte); +	if (!pgtable_page_ctor(pte)) { +		__free_page(pte); +		return NULL; +	}  	return pte;  } @@ -96,7 +100,7 @@ struct page *pte_alloc_one(struct mm_struct *mm, unsigned long address)   * checks at dup_mmap(), exec(), and other mmlist addition points   * could be used. The locking scheme was chosen on the basis of   * manfred's recommendations and having no core impact whatsoever. - * -- wli + * -- nyc   */  DEFINE_SPINLOCK(pgd_lock);  struct page *pgd_list; diff --git a/arch/mn10300/mm/tlb-smp.c b/arch/mn10300/mm/tlb-smp.c index 0b6a5ad1960..e5d0ef722bf 100644 --- a/arch/mn10300/mm/tlb-smp.c +++ b/arch/mn10300/mm/tlb-smp.c @@ -24,7 +24,6 @@  #include <linux/profile.h>  #include <linux/smp.h>  #include <asm/tlbflush.h> -#include <asm/system.h>  #include <asm/bitops.h>  #include <asm/processor.h>  #include <asm/bug.h> @@ -64,7 +63,7 @@ void smp_flush_tlb(void *unused)  	cpu_id = get_cpu(); -	if (!cpu_isset(cpu_id, flush_cpumask)) +	if (!cpumask_test_cpu(cpu_id, &flush_cpumask))  		/* This was a BUG() but until someone can quote me the line  		 * from the intel manual that guarantees an IPI to multiple  		 * CPUs is retried _only_ on the erroring CPUs its staying as a @@ -79,9 +78,9 @@ void smp_flush_tlb(void *unused)  	else  		local_flush_tlb_page(flush_mm, flush_va); -	smp_mb__before_clear_bit(); -	cpu_clear(cpu_id, flush_cpumask); -	smp_mb__after_clear_bit(); +	smp_mb__before_atomic(); +	cpumask_clear_cpu(cpu_id, &flush_cpumask); +	smp_mb__after_atomic();  out:  	put_cpu();  } @@ -103,11 +102,11 @@ static void flush_tlb_others(cpumask_t cpumask, struct mm_struct *mm,  	 * - we do not send IPIs to as-yet unbooted CPUs.  	 */  	BUG_ON(!mm); -	BUG_ON(cpus_empty(cpumask)); -	BUG_ON(cpu_isset(smp_processor_id(), cpumask)); +	BUG_ON(cpumask_empty(&cpumask)); +	BUG_ON(cpumask_test_cpu(smp_processor_id(), &cpumask)); -	cpus_and(tmp, cpumask, cpu_online_map); -	BUG_ON(!cpus_equal(cpumask, tmp)); +	cpumask_and(&tmp, &cpumask, cpu_online_mask); +	BUG_ON(!cpumask_equal(&cpumask, &tmp));  	/* I'm not happy about this global shared spinlock in the MM hot path,  	 * but we'll see how contended it is. @@ -128,7 +127,7 @@ static void flush_tlb_others(cpumask_t cpumask, struct mm_struct *mm,  	/* FIXME: if NR_CPUS>=3, change send_IPI_mask */  	smp_call_function(smp_flush_tlb, NULL, 1); -	while (!cpus_empty(flush_cpumask)) +	while (!cpumask_empty(&flush_cpumask))  		/* Lockup detection does not belong here */  		smp_mb(); @@ -146,11 +145,11 @@ void flush_tlb_mm(struct mm_struct *mm)  	cpumask_t cpu_mask;  	preempt_disable(); -	cpu_mask = mm->cpu_vm_mask; -	cpu_clear(smp_processor_id(), cpu_mask); +	cpumask_copy(&cpu_mask, mm_cpumask(mm)); +	cpumask_clear_cpu(smp_processor_id(), &cpu_mask);  	local_flush_tlb(); -	if (!cpus_empty(cpu_mask)) +	if (!cpumask_empty(&cpu_mask))  		flush_tlb_others(cpu_mask, mm, FLUSH_ALL);  	preempt_enable(); @@ -165,11 +164,11 @@ void flush_tlb_current_task(void)  	cpumask_t cpu_mask;  	preempt_disable(); -	cpu_mask = mm->cpu_vm_mask; -	cpu_clear(smp_processor_id(), cpu_mask); +	cpumask_copy(&cpu_mask, mm_cpumask(mm)); +	cpumask_clear_cpu(smp_processor_id(), &cpu_mask);  	local_flush_tlb(); -	if (!cpus_empty(cpu_mask)) +	if (!cpumask_empty(&cpu_mask))  		flush_tlb_others(cpu_mask, mm, FLUSH_ALL);  	preempt_enable(); @@ -186,11 +185,11 @@ void flush_tlb_page(struct vm_area_struct *vma, unsigned long va)  	cpumask_t cpu_mask;  	preempt_disable(); -	cpu_mask = mm->cpu_vm_mask; -	cpu_clear(smp_processor_id(), cpu_mask); +	cpumask_copy(&cpu_mask, mm_cpumask(mm)); +	cpumask_clear_cpu(smp_processor_id(), &cpu_mask);  	local_flush_tlb_page(mm, va); -	if (!cpus_empty(cpu_mask)) +	if (!cpumask_empty(&cpu_mask))  		flush_tlb_others(cpu_mask, mm, va);  	preempt_enable();  | 
