From: Catalin Marinas <catalin.marinas@arm.com>
Date: Thu, 26 Jun 2008 17:08:49 +0000 (+0100)
Subject: Cortex-M3: Allow the building of Cortex-M3 kernel port
X-Git-Url: http://www.linux-arm.org/git?p=linux-2.6.git;a=commitdiff_plain;h=cortex-m3;hp=v2.6.26-rc8

Cortex-M3: Allow the building of Cortex-M3 kernel port

This patch modifies the required Kconfig and Makefile files to allow the
building of kernel for Cortex-M3.

Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
---

diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index b786e68..d8b24a5 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -42,10 +42,6 @@ config GENERIC_CLOCKEVENTS_BROADCAST
 	depends on GENERIC_CLOCKEVENTS
 	default y if SMP && !LOCAL_TIMERS
 
-config MMU
-	bool
-	default y
-
 config NO_IOPORT
 	bool
 	default n
@@ -176,6 +172,13 @@ source "init/Kconfig"
 
 menu "System Type"
 
+config MMU
+	bool "MMU-based Paged Memory Management Support"
+	default y
+	help
+	  Select if you want MMU-based virtualised addressing space
+	  support by paged memory management. If unsure, say 'Y'.
+
 choice
 	prompt "ARM system type"
 	default ARCH_VERSATILE
@@ -732,6 +735,23 @@ config HZ
 	default AT91_TIMER_HZ if ARCH_AT91
 	default 100
 
+config THUMB2_KERNEL
+	bool "Compile the kernel in Thumb-2 mode"
+	depends on (CPU_V7 || CPU_V7M) && EXPERIMENTAL
+	default n
+	select AEABI
+	select ARM_ASM_UNIFIED
+	help
+	  By enabling this option, the kernel will be compiled in
+	  Thumb-2 mode. A compiler/assembler that understand the unified
+	  ARM-Thumb syntax is needed.
+
+	  If unsure, say N.
+
+config ARM_ASM_UNIFIED
+	bool
+	default n
+
 config AEABI
 	bool "Use the ARM EABI to compile the kernel"
 	help
@@ -749,7 +769,7 @@ config AEABI
 
 config OABI_COMPAT
 	bool "Allow old ABI binaries to run with this kernel (EXPERIMENTAL)"
-	depends on AEABI && EXPERIMENTAL
+	depends on AEABI && !CPU_V7M && EXPERIMENTAL
 	default y
 	help
 	  This option preserves the old syscall interface along with the
diff --git a/arch/arm/Kconfig-nommu b/arch/arm/Kconfig-nommu
index 901e6df..90521b3 100644
--- a/arch/arm/Kconfig-nommu
+++ b/arch/arm/Kconfig-nommu
@@ -28,7 +28,7 @@ config FLASH_SIZE
 config PROCESSOR_ID
 	hex 'Hard wire the processor ID'
 	default 0x00007700
-	depends on !CPU_CP15
+	depends on !(CPU_CP15 || CPU_V7M)
 	help
 	  If processor has no CP15 register, this processor ID is
 	  used instead of the auto-probing which utilizes the register.
diff --git a/arch/arm/Kconfig.debug b/arch/arm/Kconfig.debug
index 192ee01..ae623be 100644
--- a/arch/arm/Kconfig.debug
+++ b/arch/arm/Kconfig.debug
@@ -8,7 +8,7 @@ source "lib/Kconfig.debug"
 # n, but then RMK will have to kill you ;).
 config FRAME_POINTER
 	bool
-	default y
+	default y if !THUMB2_KERNEL
 	help
 	  If you say N here, the resulting kernel will be slightly smaller and
 	  faster. However, when a problem occurs with the kernel, the
diff --git a/arch/arm/Makefile b/arch/arm/Makefile
index e72db27..dfd909e 100644
--- a/arch/arm/Makefile
+++ b/arch/arm/Makefile
@@ -47,6 +47,7 @@ comma = ,
 # Note that GCC does not numerically define an architecture version
 # macro, but instead defines a whole series of macros which makes
 # testing for a specific architecture or later rather impossible.
+arch-$(CONFIG_CPU_32v7M)	:=-D__LINUX_ARM_ARCH__=7 -march=armv7m -Wa,-march=armv7m
 arch-$(CONFIG_CPU_32v7)		:=-D__LINUX_ARM_ARCH__=7 $(call cc-option,-march=armv7a,-march=armv5t -Wa$(comma)-march=armv7a)
 arch-$(CONFIG_CPU_32v6)		:=-D__LINUX_ARM_ARCH__=6 $(call cc-option,-march=armv6,-march=armv5t -Wa$(comma)-march=armv6)
 # Only override the compiler option if ARMv6. The ARMv6K extensions are
@@ -84,9 +85,16 @@ else
 CFLAGS_ABI	:=$(call cc-option,-mapcs-32,-mabi=apcs-gnu) $(call cc-option,-mno-thumb-interwork,)
 endif
 
+ifeq ($(CONFIG_THUMB2_KERNEL),y)
+# We currently suppress all the gas warnings but finer-grained option
+# will be provided for the unified assembly syntax
+CFLAGS_THUMB2	:=-mthumb -Wa$(comma)-W
+AFLAGS_THUMB2	:=-mthumb -Wa$(comma)-mthumb -Wa$(comma)-W
+endif
+
 # Need -Uarm for gcc < 3.x
-KBUILD_CFLAGS	+=$(CFLAGS_ABI) $(arch-y) $(tune-y) $(call cc-option,-mshort-load-bytes,$(call cc-option,-malignment-traps,)) -msoft-float -Uarm
-KBUILD_AFLAGS	+=$(CFLAGS_ABI) $(arch-y) $(tune-y) -msoft-float
+KBUILD_CFLAGS	+=$(CFLAGS_ABI) $(CFLAGS_THUMB2) $(arch-y) $(tune-y) $(call cc-option,-mshort-load-bytes,$(call cc-option,-malignment-traps,)) -msoft-float -Uarm
+KBUILD_AFLAGS	+=$(CFLAGS_ABI) $(AFLAGS_THUMB2) $(arch-y) $(tune-y) -msoft-float
 
 CHECKFLAGS	+= -D__arm__
 
diff --git a/arch/arm/boot/compressed/head.S b/arch/arm/boot/compressed/head.S
index 3c2c8f2..2e09065 100644
--- a/arch/arm/boot/compressed/head.S
+++ b/arch/arm/boot/compressed/head.S
@@ -8,6 +8,8 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
+#include <asm/unified.h>
+
 #include <linux/linkage.h>
 
 /*
@@ -124,6 +126,7 @@ start:
 1:		mov	r7, r1			@ save architecture ID
 		mov	r8, r2			@ save atags pointer
 
+#ifndef CONFIG_CPU_V7M
 #ifndef __ARM_ARCH_2__
 		/*
 		 * Booting from Angel - need to enter SVC mode and disable
@@ -134,7 +137,8 @@ start:
 		tst	r2, #3			@ not user?
 		bne	not_angel
 		mov	r0, #0x17		@ angel_SWIreason_EnterSVC
-		swi	0x123456		@ angel_SWI_ARM
+ ARM(		swi	0x123456	)	@ angel_SWI_ARM
+ THUMB(		svc	0xab		)	@ angel_SWI_THUMB
 not_angel:
 		mrs	r2, cpsr		@ turn off interrupts to
 		orr	r2, r2, #0xc0		@ prevent angel from running
@@ -142,6 +146,7 @@ not_angel:
 #else
 		teqp	pc, #0x0c000003		@ turn off interrupts
 #endif
+#endif
 
 		/*
 		 * Note that some cache flushing and other stuff may
@@ -155,7 +160,9 @@ not_angel:
 
 		.text
 		adr	r0, LC0
-		ldmia	r0, {r1, r2, r3, r4, r5, r6, ip, sp}
+ ARM(		ldmia	r0, {r1, r2, r3, r4, r5, r6, ip, sp}	)
+ THUMB(		ldmia	r0, {r1, r2, r3, r4, r5, r6, ip}	)
+ THUMB(		ldr	sp, [r0, #28]				)
 		subs	r0, r0, r1		@ calculate the delta offset
 
 						@ if delta is zero, we are
@@ -263,16 +270,25 @@ not_relocated:	mov	r0, #0
 		adr	r2, reloc_start
 		ldr	r3, LC1
 		add	r3, r2, r3
-1:		ldmia	r2!, {r9 - r14}		@ copy relocation code
-		stmia	r1!, {r9 - r14}
-		ldmia	r2!, {r9 - r14}
-		stmia	r1!, {r9 - r14}
+ THUMB(		mov	sp, r8			) @ save the atags pointer
+1:
+ ARM(		ldmia	r2!, {r9 - r14}		) @ copy relocation code
+ ARM(		stmia	r1!, {r9 - r14}		)
+ ARM(		ldmia	r2!, {r9 - r14}		)
+ ARM(		stmia	r1!, {r9 - r14}		)
+ THUMB(		ldmia	r2!, {r8 - r12, r14}	) @ copy relocation code
+ THUMB(		stmia	r1!, {r8 - r12, r14}	)
+ THUMB(		ldmia	r2!, {r8 - r12, r14}	)
+ THUMB(		stmia	r1!, {r8 - r12, r14}	)
 		cmp	r2, r3
 		blo	1b
+ THUMB(		mov	r8, sp			) @ restore the atags pointer
 		add	sp, r1, #128		@ relocate the stack
 
 		bl	cache_clean_flush
-		add	pc, r5, r0		@ call relocation code
+ ARM(		add	pc, r5, r0		) @ call relocation code
+ THUMB(		add	r12, r5, r0		)
+ THUMB(		mov	pc, r12			) @ call relocation code
 
 /*
  * We're not in danger of overwriting ourselves.  Do this the simple way.
@@ -285,6 +301,7 @@ wont_overwrite:	mov	r0, r4
 		bl	decompress_kernel
 		b	call_kernel
 
+		.align	2
 		.type	LC0, #object
 LC0:		.word	LC0			@ r1
 		.word	__bss_start		@ r2
@@ -399,8 +416,10 @@ __setup_mmu:	sub	r3, r4, #16384		@ Page directory size
 		orr	r1, r1, #3 << 10
 		add	r2, r3, #16384
 1:		cmp	r1, r9			@ if virt > start of RAM
+		it	hs
 		orrhs	r1, r1, #0x0c		@ set cacheable, bufferable
 		cmp	r1, r10			@ if virt > end of RAM
+		it	hs
 		bichs	r1, r1, #0x0c		@ clear cacheable, bufferable
 		str	r1, [r0], #4		@ 1:1 mapping
 		add	r1, r1, #1048576
@@ -421,6 +440,7 @@ __setup_mmu:	sub	r3, r4, #16384		@ Page directory size
 		add	r1, r1, #1048576
 		str	r1, [r0]
 		mov	pc, lr
+ENDPROC(__setup_mmu)
 
 __armv4_mmu_cache_on:
 		mov	r12, lr
@@ -440,14 +460,17 @@ __armv7_mmu_cache_on:
 		mov	r12, lr
 		mrc	p15, 0, r11, c0, c1, 4	@ read ID_MMFR0
 		tst	r11, #0xf		@ VMSA
+		it	ne
 		blne	__setup_mmu
 		mov	r0, #0
 		mcr	p15, 0, r0, c7, c10, 4	@ drain write buffer
 		tst	r11, #0xf		@ VMSA
+		it	ne
 		mcrne	p15, 0, r0, c8, c7, 0	@ flush I,D TLBs
 		mrc	p15, 0, r0, c1, c0, 0	@ read control reg
 		orr	r0, r0, #0x5000		@ I-cache enable, RR cache replacement
 		orr	r0, r0, #0x003c		@ write buffer
+		itttt	ne
 		orrne	r0, r0, #1		@ MMU enabled
 		movne	r1, #-1
 		mcrne	p15, 0, r3, c2, c0, 0	@ load page table pointer
@@ -502,14 +525,18 @@ reloc_start:	add	r9, r5, r0
 		sub	r9, r9, #128		@ do not copy the stack
 		debug_reloc_start
 		mov	r1, r4
+ THUMB(		mov	sp, r8			)	@ save the atags pointer
 1:
 		.rept	4
-		ldmia	r5!, {r0, r2, r3, r10 - r14}	@ relocate kernel
-		stmia	r1!, {r0, r2, r3, r10 - r14}
+ ARM(		ldmia	r5!, {r0, r2, r3, r10 - r14}	)	@ relocate kernel
+ ARM(		stmia	r1!, {r0, r2, r3, r10 - r14}	)
+ THUMB(		ldmia	r5!, {r0, r2, r3, r8, r10 - r12, r14})	@ relocate kernel
+ THUMB(		stmia	r1!, {r0, r2, r3, r8, r10 - r12, r14})
 		.endr
 
 		cmp	r5, r9
 		blo	1b
+ THUMB(		mov	r8, sp			)	@ restore the atags pointer
 		add	sp, r1, #128		@ relocate the stack
 		debug_reloc_end
 
@@ -534,17 +561,24 @@ call_kernel:	bl	cache_clean_flush
  *  r12 = corrupted
  */
 
-call_cache_fn:	adr	r12, proc_types
+call_cache_fn:
+		adr	r12, proc_types
 #ifdef CONFIG_CPU_CP15
 		mrc	p15, 0, r6, c0, c0	@ get processor ID
+#elif defined(CONFIG_CPU_V7M)
+		ldr	r6, =0xe000ed00		@ CPUID register address
+		ldr	r6, [r6]
 #else
 		ldr	r6, =CONFIG_PROCESSOR_ID
 #endif
-1:		ldr	r1, [r12, #0]		@ get value
-		ldr	r2, [r12, #4]		@ get mask
-		eor	r1, r1, r6		@ (real ^ match)
-		tst	r1, r2			@       & mask
-		addeq	pc, r12, r3		@ call cache function
+1:		ldr	r2, [r12, #4]		@ get mask
+		ldr	r1, [r12, #0]		@ get value
+		and	r2, r6, r2		@ keep the relevant bits
+		teq	r1, r2			@ match with the value
+		itt	eq
+ ARM(		addeq	pc, r12, r3		) @ call cache function
+ THUMB(		addeq	r12, r3			)
+ THUMB(		moveq	pc, r12			) @ call cache function
 		add	r12, r12, #4*5
 		b	1b
 
@@ -562,13 +596,15 @@ call_cache_fn:	adr	r12, proc_types
  * methods.  Writeback caches _must_ have the flush method
  * defined.
  */
+		.align	2
 		.type	proc_types,#object
 proc_types:
 		.word	0x41560600		@ ARM6/610
 		.word	0xffffffe0
-		b	__arm6_mmu_cache_off	@ works, but slow
-		b	__arm6_mmu_cache_off
+		W(b)	__arm6_mmu_cache_off	@ works, but slow
+		W(b)	__arm6_mmu_cache_off
 		mov	pc, lr
+ THUMB(		nop				)
 @		b	__arm6_mmu_cache_on		@ untested
 @		b	__arm6_mmu_cache_off
 @		b	__armv3_mmu_cache_flush
@@ -576,96 +612,109 @@ proc_types:
 		.word	0x00000000		@ old ARM ID
 		.word	0x0000f000
 		mov	pc, lr
+ THUMB(		nop				)
 		mov	pc, lr
+ THUMB(		nop				)
 		mov	pc, lr
+ THUMB(		nop				)
 
 		.word	0x41007000		@ ARM7/710
 		.word	0xfff8fe00
-		b	__arm7_mmu_cache_off
-		b	__arm7_mmu_cache_off
+		W(b)	__arm7_mmu_cache_off
+		W(b)	__arm7_mmu_cache_off
 		mov	pc, lr
+ THUMB(		nop				)
 
 		.word	0x41807200		@ ARM720T (writethrough)
 		.word	0xffffff00
-		b	__armv4_mmu_cache_on
-		b	__armv4_mmu_cache_off
+		W(b)	__armv4_mmu_cache_on
+		W(b)	__armv4_mmu_cache_off
 		mov	pc, lr
+ THUMB(		nop				)
 
 		.word	0x41007400		@ ARM74x
 		.word	0xff00ff00
-		b	__armv3_mpu_cache_on
-		b	__armv3_mpu_cache_off
-		b	__armv3_mpu_cache_flush
+		W(b)	__armv3_mpu_cache_on
+		W(b)	__armv3_mpu_cache_off
+		W(b)	__armv3_mpu_cache_flush
 		
 		.word	0x41009400		@ ARM94x
 		.word	0xff00ff00
-		b	__armv4_mpu_cache_on
-		b	__armv4_mpu_cache_off
-		b	__armv4_mpu_cache_flush
+		W(b)	__armv4_mpu_cache_on
+		W(b)	__armv4_mpu_cache_off
+		W(b)	__armv4_mpu_cache_flush
 
 		.word	0x00007000		@ ARM7 IDs
 		.word	0x0000f000
 		mov	pc, lr
+ THUMB(		nop				)
 		mov	pc, lr
+ THUMB(		nop				)
 		mov	pc, lr
+ THUMB(		nop				)
 
 		@ Everything from here on will be the new ID system.
 
 		.word	0x4401a100		@ sa110 / sa1100
 		.word	0xffffffe0
-		b	__armv4_mmu_cache_on
-		b	__armv4_mmu_cache_off
-		b	__armv4_mmu_cache_flush
+		W(b)	__armv4_mmu_cache_on
+		W(b)	__armv4_mmu_cache_off
+		W(b)	__armv4_mmu_cache_flush
 
 		.word	0x6901b110		@ sa1110
 		.word	0xfffffff0
-		b	__armv4_mmu_cache_on
-		b	__armv4_mmu_cache_off
-		b	__armv4_mmu_cache_flush
+		W(b)	__armv4_mmu_cache_on
+		W(b)	__armv4_mmu_cache_off
+		W(b)	__armv4_mmu_cache_flush
 
 		.word	0x56055310		@ Feroceon
 		.word	0xfffffff0
-		b	__armv4_mmu_cache_on
-		b	__armv4_mmu_cache_off
-		b	__armv5tej_mmu_cache_flush
+		W(b)	__armv4_mmu_cache_on
+		W(b)	__armv4_mmu_cache_off
+		W(b)	__armv5tej_mmu_cache_flush
 
 		@ These match on the architecture ID
 
 		.word	0x00020000		@ ARMv4T
 		.word	0x000f0000
-		b	__armv4_mmu_cache_on
-		b	__armv4_mmu_cache_off
-		b	__armv4_mmu_cache_flush
+		W(b)	__armv4_mmu_cache_on
+		W(b)	__armv4_mmu_cache_off
+		W(b)	__armv4_mmu_cache_flush
 
 		.word	0x00050000		@ ARMv5TE
 		.word	0x000f0000
-		b	__armv4_mmu_cache_on
-		b	__armv4_mmu_cache_off
-		b	__armv4_mmu_cache_flush
+		W(b)	__armv4_mmu_cache_on
+		W(b)	__armv4_mmu_cache_off
+		W(b)	__armv4_mmu_cache_flush
 
 		.word	0x00060000		@ ARMv5TEJ
 		.word	0x000f0000
-		b	__armv4_mmu_cache_on
-		b	__armv4_mmu_cache_off
-		b	__armv5tej_mmu_cache_flush
+		W(b)	__armv4_mmu_cache_on
+		W(b)	__armv4_mmu_cache_off
+		W(b)	__armv4_mmu_cache_flush
 
 		.word	0x0007b000		@ ARMv6
 		.word	0x000ff000
-		b	__armv4_mmu_cache_on
-		b	__armv4_mmu_cache_off
-		b	__armv6_mmu_cache_flush
+		W(b)	__armv4_mmu_cache_on
+		W(b)	__armv4_mmu_cache_off
+		W(b)	__armv6_mmu_cache_flush
 
+#ifndef CONFIG_CPU_V7M
 		.word	0x000f0000		@ new CPU Id
 		.word	0x000f0000
-		b	__armv7_mmu_cache_on
-		b	__armv7_mmu_cache_off
-		b	__armv7_mmu_cache_flush
+		W(b)	__armv7_mmu_cache_on
+		W(b)	__armv7_mmu_cache_off
+		W(b)	__armv7_mmu_cache_flush
+#endif
 
 		.word	0			@ unrecognised type
 		.word	0
 		mov	pc, lr
+ THUMB(		nop				)
 		mov	pc, lr
+ THUMB(		nop				)
 		mov	pc, lr
+ THUMB(		nop				)
 
 		.size	proc_types, . - proc_types
 
@@ -761,6 +810,7 @@ __armv4_mpu_cache_flush:
 		bcs	1b			@ segments 7 to 0
 
 		teq	r2, #0
+		it	ne
 		mcrne	p15, 0, ip, c7, c5, 0	@ invalidate I cache
 		mcr	p15, 0, ip, c7, c10, 4	@ drain WB
 		mov	pc, lr
@@ -782,7 +832,8 @@ __armv7_mmu_cache_flush:
 		mcr	p15, 0, r10, c7, c14, 0	@ clean+invalidate D
 		b	iflush
 hierarchical:
-		stmfd	sp!, {r0-r5, r7, r9-r11}
+ ARM(		stmfd	sp!, {r0-r5, r7, r9-r11})
+ THUMB(		stmfd	sp!, {r0-r7, r9-r11}	)
 		mrc	p15, 1, r0, c0, c0, 1	@ read clidr
 		ands	r3, r0, #0x7000000	@ extract loc from clidr
 		mov	r3, r3, lsr #23		@ left align loc bit field
@@ -801,14 +852,19 @@ loop1:
 		add	r2, r2, #4		@ add 4 (line length offset)
 		ldr	r4, =0x3ff
 		ands	r4, r4, r1, lsr #3	@ find maximum number on the way size
-		.word	0xe16f5f14		@ clz r5, r4 - find bit position of way size increment
+ ARM(		.word	0xe16f5f14		) @ clz r5, r4
+ THUMB(		clz	r5, r4			) @ find bit position of way size increment
 		ldr	r7, =0x7fff
 		ands	r7, r7, r1, lsr #13	@ extract max number of the index size
 loop2:
 		mov	r9, r4			@ create working copy of max way size
 loop3:
-		orr	r11, r10, r9, lsl r5	@ factor way and cache number into r11
-		orr	r11, r11, r7, lsl r2	@ factor index number into r11
+ ARM(		orr	r11, r10, r9, lsl r5	) @ factor way and cache number into r11
+ ARM(		orr	r11, r11, r7, lsl r2	) @ factor index number into r11
+ THUMB(		lsl	r6, r9, r5		)
+ THUMB(		orr	r11, r10, r6		) @ factor way and cache number into r11
+ THUMB(		lsl	r6, r7, r2		)
+ THUMB(		orr	r11, r11, r6		) @ factor index number into r11
 		mcr	p15, 0, r11, c7, c14, 2	@ clean & invalidate by set/way
 		subs	r9, r9, #1		@ decrement the way
 		bge	loop3
@@ -821,7 +877,8 @@ skip:
 finished:
 		mov	r10, #0			@ swith back to cache level 0
 		mcr	p15, 2, r10, c0, c0, 0	@ select current cache level in cssr
-		ldmfd	sp!, {r0-r5, r7, r9-r11}
+ ARM(		ldmfd	sp!, {r0-r5, r7, r9-r11})
+ THUMB(		ldmfd	sp!, {r0-r7, r9-r11}	)
 iflush:
 		mcr	p15, 0, r10, c7, c5, 0	@ invalidate I+BTB
 		mcr	p15, 0, r10, c7, c10, 4	@ drain WB
@@ -845,6 +902,7 @@ __armv4_mmu_cache_flush:
 		mov	r2, #1024
 		mov	r2, r2, lsl r1		@ base dcache size *2
 		tst	r3, #1 << 14		@ test M bit
+		it	ne
 		addne	r2, r2, r2, lsr #1	@ +1/2 size if M == 1
 		mov	r3, r3, lsr #12
 		and	r3, r3, #3
@@ -853,7 +911,10 @@ __armv4_mmu_cache_flush:
 no_cache_id:
 		bic	r1, pc, #63		@ align to longest cache line
 		add	r2, r1, r2
-1:		ldr	r3, [r1], r11		@ s/w flush D cache
+1:
+ ARM(		ldr	r3, [r1], r11		) @ s/w flush D cache
+ THUMB(		ldr	r3, [r1]		) @ s/w flush D cache
+ THUMB(		add	r1, r1, r11		)
 		teq	r1, r2
 		bne	1b
 
@@ -873,6 +934,7 @@ __armv3_mpu_cache_flush:
  * memory, which again must be relocatable.
  */
 #ifdef DEBUG
+		.align	2
 		.type	phexbuf,#object
 phexbuf:	.space	12
 		.size	phexbuf, . - phexbuf
diff --git a/arch/arm/common/Kconfig b/arch/arm/common/Kconfig
index 3e07346..56483c1 100644
--- a/arch/arm/common/Kconfig
+++ b/arch/arm/common/Kconfig
@@ -4,6 +4,9 @@ config ARM_GIC
 config ARM_VIC
 	bool
 
+config ARM_NVIC
+	bool
+
 config ICST525
 	bool
 
diff --git a/arch/arm/common/Makefile b/arch/arm/common/Makefile
index 3d0b9fa..5c49e3c 100644
--- a/arch/arm/common/Makefile
+++ b/arch/arm/common/Makefile
@@ -5,6 +5,7 @@
 obj-y				+= rtctime.o
 obj-$(CONFIG_ARM_GIC)		+= gic.o
 obj-$(CONFIG_ARM_VIC)		+= vic.o
+obj-$(CONFIG_ARM_NVIC)		+= nvic.o
 obj-$(CONFIG_ICST525)		+= icst525.o
 obj-$(CONFIG_ICST307)		+= icst307.o
 obj-$(CONFIG_SA1111)		+= sa1111.o
diff --git a/arch/arm/common/nvic.c b/arch/arm/common/nvic.c
new file mode 100644
index 0000000..ea40cc8
--- /dev/null
+++ b/arch/arm/common/nvic.c
@@ -0,0 +1,99 @@
+/*
+ *  linux/arch/arm/common/nvic.c
+ *
+ *  Copyright (C) 2008 ARM Limited, All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Support for the Nested Vectored Interrupt Controller found on the
+ * ARMv7-M CPUs (Cortex-M3)
+ */
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/smp.h>
+
+#include <asm/irq.h>
+#include <asm/io.h>
+#include <asm/mach/irq.h>
+#include <asm/hardware/nvic.h>
+
+static DEFINE_SPINLOCK(irq_controller_lock);
+
+/*
+ * Routines to acknowledge, disable and enable interrupts
+ *
+ * Linux assumes that when we're done with an interrupt we need to
+ * unmask it, in the same way we need to unmask an interrupt when
+ * we first enable it.
+ *
+ * The NVIC has a separate notion of "end of interrupt" to re-enable
+ * an interrupt after handling, in order to support hardware
+ * prioritisation.
+ *
+ * We can make the NVIC behave in the way that Linux expects by making
+ * our "acknowledge" routine disable the interrupt, then mark it as
+ * complete.
+ */
+static void nvic_ack_irq(unsigned int irq)
+{
+	u32 mask = 1 << (irq % 32);
+
+	spin_lock(&irq_controller_lock);
+	writel(mask, NVIC_CLEAR_ENABLE + irq / 32 * 4);
+	spin_unlock(&irq_controller_lock);
+}
+
+static void nvic_mask_irq(unsigned int irq)
+{
+	u32 mask = 1 << (irq % 32);
+
+	spin_lock(&irq_controller_lock);
+	writel(mask, NVIC_CLEAR_ENABLE + irq / 32 * 4);
+	spin_unlock(&irq_controller_lock);
+}
+
+static void nvic_unmask_irq(unsigned int irq)
+{
+	u32 mask = 1 << (irq % 32);
+
+	spin_lock(&irq_controller_lock);
+	writel(mask, NVIC_SET_ENABLE + irq / 32 * 4);
+	spin_unlock(&irq_controller_lock);
+}
+
+static struct irq_chip nvic_chip = {
+	.name		= "NVIC",
+	.ack		= nvic_ack_irq,
+	.mask		= nvic_mask_irq,
+	.unmask		= nvic_unmask_irq,
+};
+
+void __init nvic_init(void)
+{
+	unsigned int max_irq, i;
+
+	max_irq = ((readl(NVIC_INTR_CTRL) & 0x1f) + 1) * 32;
+
+	/*
+	 * Disable all interrupts
+	 */
+	for (i = 0; i < max_irq / 32; i++)
+		writel(~0, NVIC_CLEAR_ENABLE + i * 4);
+
+	/*
+	 * Set priority on all interrupts.
+	 */
+	for (i = 0; i < max_irq; i += 4)
+		writel(0, NVIC_PRIORITY + i);
+
+	/*
+	 * Setup the Linux IRQ subsystem.
+	 */
+	for (i = 0; i < NR_IRQS; i++) {
+		set_irq_chip(i, &nvic_chip);
+		set_irq_handler(i, handle_level_irq);
+		set_irq_flags(i, IRQF_VALID | IRQF_PROBE);
+	}
+}
diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile
index ad455ff..28a9f01 100644
--- a/arch/arm/kernel/Makefile
+++ b/arch/arm/kernel/Makefile
@@ -6,10 +6,16 @@ AFLAGS_head.o := -DTEXT_OFFSET=$(TEXT_OFFSET)
 
 # Object file lists.
 
-obj-y		:= compat.o entry-armv.o entry-common.o irq.o \
+obj-y		:= compat.o entry-common.o irq.o \
 		   process.o ptrace.o setup.o signal.o \
 		   sys_arm.o stacktrace.o time.o traps.o
 
+ifeq ($(CONFIG_CPU_V7M),y)
+obj-y		+= entry-v7m.o
+else
+obj-y		+= entry-armv.o
+endif
+
 obj-$(CONFIG_ISA_DMA_API)	+= dma.o
 obj-$(CONFIG_ARCH_ACORN)	+= ecard.o 
 obj-$(CONFIG_FIQ)		+= fiq.o
diff --git a/arch/arm/kernel/armksyms.c b/arch/arm/kernel/armksyms.c
index 688b7b1..de0b889 100644
--- a/arch/arm/kernel/armksyms.c
+++ b/arch/arm/kernel/armksyms.c
@@ -45,8 +45,10 @@ extern void __aeabi_uidiv(void);
 extern void __aeabi_uidivmod(void);
 extern void __aeabi_ulcmp(void);
 
+#ifndef CONFIG_CPU_V7M
 extern void fpundefinstr(void);
 extern void fp_enter(void);
+#endif
 
 /*
  * This has a special calling convention; it doesn't
@@ -64,7 +66,9 @@ extern void fp_enter(void);
  * floating point math emulator support.
  * These symbols will never change their calling convention...
  */
+#ifndef CONFIG_CPU_V7M
 EXPORT_SYMBOL_ALIAS(kern_fp_enter,fp_enter);
+#endif
 EXPORT_SYMBOL_ALIAS(fp_printk,printk);
 EXPORT_SYMBOL_ALIAS(fp_send_sig,send_sig);
 
diff --git a/arch/arm/kernel/asm-offsets.c b/arch/arm/kernel/asm-offsets.c
index 4a88125..009c1a1 100644
--- a/arch/arm/kernel/asm-offsets.c
+++ b/arch/arm/kernel/asm-offsets.c
@@ -79,7 +79,11 @@ int main(void)
   DEFINE(S_LR,			offsetof(struct pt_regs, ARM_lr));
   DEFINE(S_PC,			offsetof(struct pt_regs, ARM_pc));
   DEFINE(S_PSR,			offsetof(struct pt_regs, ARM_cpsr));
+#ifdef CONFIG_CPU_V7M
+  DEFINE(S_EXC_LR,		offsetof(struct pt_regs, ARM_EXC_lr));
+#else
   DEFINE(S_OLD_R0,		offsetof(struct pt_regs, ARM_ORIG_r0));
+#endif
   DEFINE(S_FRAME_SIZE,		sizeof(struct pt_regs));
   BLANK();
 #ifdef CONFIG_CPU_HAS_ASID
diff --git a/arch/arm/kernel/debug.S b/arch/arm/kernel/debug.S
index 5617566..f4ad3cf 100644
--- a/arch/arm/kernel/debug.S
+++ b/arch/arm/kernel/debug.S
@@ -9,6 +9,8 @@
  *
  *  32-bit debugging code
  */
+#include <asm/unified.h>
+
 #include <linux/linkage.h>
 
 		.text
@@ -89,10 +91,12 @@
 ENTRY(printhex8)
 		mov	r1, #8
 		b	printhex
+ENDPROC(printhex8)
 
 ENTRY(printhex4)
 		mov	r1, #4
 		b	printhex
+ENDPROC(printhex4)
 
 ENTRY(printhex2)
 		mov	r1, #2
@@ -103,6 +107,7 @@ printhex:	adr	r2, hexbuf
 1:		and	r1, r0, #15
 		mov	r0, r0, lsr #4
 		cmp	r1, #10
+		ite	lt
 		addlt	r1, r1, #'0'
 		addge	r1, r1, #'a' - 10
 		strb	r1, [r3, #-1]!
@@ -110,6 +115,7 @@ printhex:	adr	r2, hexbuf
 		bne	1b
 		mov	r0, r2
 		b	printascii
+ENDPROC(printhex2)
 
 		.ltorg
 
@@ -120,18 +126,22 @@ ENTRY(printascii)
 		senduart r1, r3
 		busyuart r2, r3
 		teq	r1, #'\n'
+		itt	eq
 		moveq	r1, #'\r'
 		beq	1b
 2:		teq	r0, #0
+		itt	ne
 		ldrneb	r1, [r0], #1
 		teqne	r1, #0
 		bne	1b
 		mov	pc, lr
+ENDPROC(printascii)
 
 ENTRY(printch)
 		addruart r3
 		mov	r1, r0
 		mov	r0, #0
 		b	1b
+ENDPROC(printch)
 
 hexbuf:		.space 16
diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S
index 7dca225..c9c8f2f 100644
--- a/arch/arm/kernel/entry-armv.S
+++ b/arch/arm/kernel/entry-armv.S
@@ -14,6 +14,7 @@
  *  Note:  there is a StrongARM bug in the STMIA rn, {regs}^ instruction
  *  that causes it to save wrong values...  Be aware!
  */
+#include <asm/unified.h>
 
 #include <asm/memory.h>
 #include <asm/glue.h>
@@ -29,11 +30,12 @@
 	.macro	irq_handler
 	get_irqnr_preamble r5, lr
 1:	get_irqnr_and_base r0, r6, r5, lr
+	ittt	ne
 	movne	r1, sp
 	@
 	@ routine called with r0 = irq number, r1 = struct pt_regs *
 	@
-	adrne	lr, 1b
+	badr	lr, 1b, ne
 	bne	asm_do_IRQ
 
 #ifdef CONFIG_SMP
@@ -44,14 +46,16 @@
 	 * preserved from get_irqnr_and_base above
 	 */
 	test_for_ipi r0, r6, r5, lr
+	ittt	ne
 	movne	r0, sp
-	adrne	lr, 1b
+	badr	lr, 1b, ne
 	bne	do_IPI
 
 #ifdef CONFIG_LOCAL_TIMERS
 	test_for_ltirq r0, r6, r5, lr
+	ittt	ne
 	movne	r0, sp
-	adrne	lr, 1b
+	badr	lr, 1b, ne
 	bne	do_local_timer
 #endif
 #endif
@@ -69,24 +73,31 @@
  */
 	.macro	inv_entry, reason
 	sub	sp, sp, #S_FRAME_SIZE
-	stmib	sp, {r1 - lr}
+ ARM(	stmib	sp, {r1 - lr}		)
+ THUMB(	stmia	sp, {r0 - r12}		)
+ THUMB(	str	sp, [sp, #S_SP]		)
+ THUMB(	str	lr, [sp, #S_LR]		)
 	mov	r1, #\reason
 	.endm
 
 __pabt_invalid:
 	inv_entry BAD_PREFETCH
 	b	common_invalid
+ENDPROC(__pabt_invalid)
 
 __dabt_invalid:
 	inv_entry BAD_DATA
 	b	common_invalid
+ENDPROC(__dabt_invalid)
 
 __irq_invalid:
 	inv_entry BAD_IRQ
 	b	common_invalid
+ENDPROC(__irq_invalid)
 
 __und_invalid:
 	inv_entry BAD_UNDEFINSTR
+ENDPROC(__und_invalid)
 
 	@
 	@ XXX fall through to common_invalid
@@ -121,13 +132,16 @@ common_invalid:
 	.macro	svc_entry, stack_hole=0
 	sub	sp, sp, #(S_FRAME_SIZE + \stack_hole)
  SPFIX(	tst	sp, #4		)
+ SPFIX(	it	ne		)
  SPFIX(	bicne	sp, sp, #4	)
-	stmib	sp, {r1 - r12}
+ ARM(	stmib	sp, {r1 - r12}	)
+ THUMB(	stmia	sp, {r0 - r12}	)
 
 	ldmia	r0, {r1 - r3}
 	add	r5, sp, #S_SP		@ here for interlock avoidance
 	mov	r4, #-1			@  ""  ""      ""       ""
 	add	r0, sp, #(S_FRAME_SIZE + \stack_hole)
+ SPFIX(	it	ne		)
  SPFIX(	addne	r0, r0, #4	)
 	str	r1, [sp]		@ save the "real" r0 copied
 					@ from the exception stack
@@ -155,6 +169,7 @@ __dabt_svc:
 	@
 	mrs	r9, cpsr
 	tst	r3, #PSR_I_BIT
+	it	eq
 	biceq	r9, r9, #PSR_I_BIT
 
 	@
@@ -189,9 +204,9 @@ __dabt_svc:
 	@
 	@ restore SPSR and restart the instruction
 	@
-	ldr	r0, [sp, #S_PSR]
-	msr	spsr_cxsf, r0
-	ldmia	sp, {r0 - pc}^			@ load r0 - pc, cpsr
+ ARM(	arm_rfe r0		)
+ THUMB(	thumb_rfe r0, r1, r2	)
+ENDPROC(__dabt_svc)
 
 	.align	5
 __irq_svc:
@@ -217,12 +232,14 @@ __irq_svc:
 	blne	svc_preempt
 #endif
 	ldr	r0, [sp, #S_PSR]		@ irqs are already disabled
-	msr	spsr_cxsf, r0
+ ARM(	msr	spsr_cxsf, r0	)
 #ifdef CONFIG_TRACE_IRQFLAGS
 	tst	r0, #PSR_I_BIT
 	bleq	trace_hardirqs_on
 #endif
-	ldmia	sp, {r0 - pc}^			@ load r0 - pc, cpsr
+ ARM(	ldmia	sp, {r0 - pc}^	)		@ load r0 - pc, cpsr
+ THUMB(	thumb_rfe r0, r1, r2	)
+ENDPROC(__irq_svc)
 
 	.ltorg
 
@@ -255,7 +272,7 @@ __und_svc:
 	@  r0 - instruction
 	@
 	ldr	r0, [r2, #-4]
-	adr	r9, 1f
+	badr	r9, 1f
 	bl	call_fpe
 
 	mov	r0, sp				@ struct pt_regs *regs
@@ -269,9 +286,9 @@ __und_svc:
 	@
 	@ restore SPSR and restart the instruction
 	@
-	ldr	lr, [sp, #S_PSR]		@ Get SVC cpsr
-	msr	spsr_cxsf, lr
-	ldmia	sp, {r0 - pc}^			@ Restore SVC registers
+ ARM(	arm_rfe lr)
+ THUMB(	thumb_rfe r0, r1, r2	)
+ENDPROC(__und_svc)
 
 	.align	5
 __pabt_svc:
@@ -282,6 +299,7 @@ __pabt_svc:
 	@
 	mrs	r9, cpsr
 	tst	r3, #PSR_I_BIT
+	it	eq
 	biceq	r9, r9, #PSR_I_BIT
 
 	@
@@ -310,9 +328,9 @@ __pabt_svc:
 	@
 	@ restore SPSR and restart the instruction
 	@
-	ldr	r0, [sp, #S_PSR]
-	msr	spsr_cxsf, r0
-	ldmia	sp, {r0 - pc}^			@ load r0 - pc, cpsr
+ ARM(	arm_rfe r0		)
+ THUMB(	thumb_rfe r0, r1, r2	)
+ENDPROC(__pabt_svc)
 
 	.align	5
 .LCcralign:
@@ -336,7 +354,8 @@ __pabt_svc:
 
 	.macro	usr_entry
 	sub	sp, sp, #S_FRAME_SIZE
-	stmib	sp, {r1 - r12}
+ ARM(	stmib	sp, {r1 - r12}	)
+ THUMB(	stmia	sp, {r0 - r12}	)
 
 	ldmia	r0, {r1 - r3}
 	add	r0, sp, #S_PC		@ here for interlock avoidance
@@ -355,7 +374,8 @@ __pabt_svc:
 	@ Also, separately save sp_usr and lr_usr
 	@
 	stmia	r0, {r2 - r4}
-	stmdb	r0, {sp, lr}^
+ ARM(	stmdb	r0, {sp, lr}^			)
+ THUMB(	store_user_sp_lr r0, r1, S_SP - S_PC	)
 
 	@
 	@ Enable the alignment trap while in kernel mode
@@ -410,8 +430,9 @@ __dabt_usr:
 	@
 	enable_irq
 	mov	r2, sp
-	adr	lr, ret_from_exception
+	badr	lr, ret_from_exception
 	b	do_DataAbort
+ENDPROC(__dabt_usr)
 
 	.align	5
 __irq_usr:
@@ -441,6 +462,7 @@ __irq_usr:
 
 	mov	why, #0
 	b	ret_to_user
+ENDPROC(__irq_usr)
 
 	.ltorg
 
@@ -455,16 +477,20 @@ __und_usr:
 	@
 	@  r0 - instruction
 	@
-	adr	r9, ret_from_exception
-	adr	lr, __und_usr_unknown
+	badr	r9, ret_from_exception
+	badr	lr, __und_usr_unknown
 	tst	r3, #PSR_T_BIT			@ Thumb mode?
+	itet	eq
 	subeq	r4, r2, #4			@ ARM instr at LR - 4
 	subne	r4, r2, #2			@ Thumb instr at LR - 2
 1:	ldreqt	r0, [r4]
 	beq	call_fpe
 	@ Thumb instruction
 #if __LINUX_ARM_ARCH__ >= 7
-2:	ldrht	r5, [r4], #2
+2:
+ ARM(	ldrht	r5, [r4], #2	)
+ THUMB(	ldrht	r5, [r4]	)
+ THUMB(	add	r4, r4, #2	)
 	and	r0, r5, #0xf800			@ mask bits 111x x... .... ....
 	cmp	r0, #0xe800			@ 32bit instruction if xx != 0
 	blo	__und_usr_unknown
@@ -474,6 +500,7 @@ __und_usr:
 #else
 	b	__und_usr_unknown
 #endif
+ENDPROC(__und_usr)
 
 	@
 	@ fallthrough to call_fpe
@@ -543,6 +570,7 @@ call_fpe:
 1:
 #endif
 	tst	r0, #0x08000000			@ only CDP/CPRT/LDC/STC have bit 27
+	ite	ne
 	tstne	r0, #0x04000000			@ bit 26 set on both ARM and Thumb-2
 #if defined(CONFIG_CPU_ARM610) || defined(CONFIG_CPU_ARM710)
 	and	r8, r0, #0x0f000000		@ mask out op-code bits
@@ -551,9 +579,11 @@ call_fpe:
 	moveq	pc, lr
 	get_thread_info r10			@ get current thread
 	and	r8, r0, #0x00000f00		@ mask out CP number
+ THUMB(	lsr	r8, r8, #8		)
 	mov	r7, #1
 	add	r6, r10, #TI_USED_CP
-	strb	r7, [r6, r8, lsr #8]		@ set appropriate used_cp[]
+ ARM(	strb	r7, [r6, r8, lsr #8]	)	@ set appropriate used_cp[]
+ THUMB(	strb	r7, [r6, r8]		)	@ set appropriate used_cp[]
 #ifdef CONFIG_IWMMXT
 	@ Test if we need to give access to iWMMXt coprocessors
 	ldr	r5, [r10, #TI_FLAGS]
@@ -561,36 +591,38 @@ call_fpe:
 	movcss	r7, r5, lsr #(TIF_USING_IWMMXT + 1)
 	bcs	iwmmxt_task_enable
 #endif
-	add	pc, pc, r8, lsr #6
-	mov	r0, r0
-
-	mov	pc, lr				@ CP#0
-	b	do_fpe				@ CP#1 (FPE)
-	b	do_fpe				@ CP#2 (FPE)
-	mov	pc, lr				@ CP#3
+ ARM(	add	pc, pc, r8, lsr #6	)
+ THUMB(	lsl	r8, r8, #2		)
+ THUMB(	add	pc, r8			)
+	nop
+
+	W(mov)	pc, lr				@ CP#0
+	W(b)	do_fpe				@ CP#1 (FPE)
+	W(b)	do_fpe				@ CP#2 (FPE)
+	W(mov)	pc, lr				@ CP#3
 #ifdef CONFIG_CRUNCH
 	b	crunch_task_enable		@ CP#4 (MaverickCrunch)
 	b	crunch_task_enable		@ CP#5 (MaverickCrunch)
 	b	crunch_task_enable		@ CP#6 (MaverickCrunch)
 #else
-	mov	pc, lr				@ CP#4
-	mov	pc, lr				@ CP#5
-	mov	pc, lr				@ CP#6
+	W(mov)	pc, lr				@ CP#4
+	W(mov)	pc, lr				@ CP#5
+	W(mov)	pc, lr				@ CP#6
 #endif
-	mov	pc, lr				@ CP#7
-	mov	pc, lr				@ CP#8
-	mov	pc, lr				@ CP#9
+	W(mov)	pc, lr				@ CP#7
+	W(mov)	pc, lr				@ CP#8
+	W(mov)	pc, lr				@ CP#9
 #ifdef CONFIG_VFP
-	b	do_vfp				@ CP#10 (VFP)
-	b	do_vfp				@ CP#11 (VFP)
+	W(b)	do_vfp				@ CP#10 (VFP)
+	W(b)	do_vfp				@ CP#11 (VFP)
 #else
-	mov	pc, lr				@ CP#10 (VFP)
-	mov	pc, lr				@ CP#11 (VFP)
+	W(mov)	pc, lr				@ CP#10 (VFP)
+	W(mov)	pc, lr				@ CP#11 (VFP)
 #endif
-	mov	pc, lr				@ CP#12
-	mov	pc, lr				@ CP#13
-	mov	pc, lr				@ CP#14 (Debug)
-	mov	pc, lr				@ CP#15 (Control)
+	W(mov)	pc, lr				@ CP#12
+	W(mov)	pc, lr				@ CP#13
+	W(mov)	pc, lr				@ CP#14 (Debug)
+	W(mov)	pc, lr				@ CP#15 (Control)
 
 #ifdef CONFIG_NEON
 	.align	6
@@ -640,8 +672,9 @@ no_fp:	mov	pc, lr
 
 __und_usr_unknown:
 	mov	r0, sp
-	adr	lr, ret_from_exception
+	badr	lr, ret_from_exception
 	b	do_undefinstr
+ENDPROC(__und_usr_unknown)
 
 	.align	5
 __pabt_usr:
@@ -658,7 +691,9 @@ __pabt_usr:
 	enable_irq				@ Enable interrupts
 	mov	r1, sp				@ regs
 	bl	do_PrefetchAbort		@ call abort handler
+ENDPROC(__pabt_usr)
 	/* fall through */
+
 /*
  * This is the return code to user mode for abort handlers
  */
@@ -666,6 +701,7 @@ ENTRY(ret_from_exception)
 	get_thread_info tsk
 	mov	why, #0
 	b	ret_to_user
+ENDPROC(ret_from_exception)
 
 /*
  * Register switch for ARMv3 and ARMv4 processors
@@ -675,7 +711,10 @@ ENTRY(ret_from_exception)
 ENTRY(__switch_to)
 	add	ip, r1, #TI_CPU_SAVE
 	ldr	r3, [r2, #TI_TP_VALUE]
-	stmia	ip!, {r4 - sl, fp, sp, lr}	@ Store most regs on stack
+ ARM(	stmia	ip!, {r4 - sl, fp, sp, lr} )	@ Store most regs on stack
+ THUMB(	stmia	ip!, {r4 - sl, fp}	   )	@ Store most regs on stack
+ THUMB(	str	sp, [ip], #4		   )
+ THUMB(	str	lr, [ip], #4		   )
 #ifdef CONFIG_MMU
 	ldr	r6, [r2, #TI_CPU_DOMAIN]
 #endif
@@ -700,8 +739,13 @@ ENTRY(__switch_to)
 	ldr	r0, =thread_notify_head
 	mov	r1, #THREAD_NOTIFY_SWITCH
 	bl	atomic_notifier_call_chain
+ THUMB(	mov	ip, r4			   )
 	mov	r0, r5
-	ldmia	r4, {r4 - sl, fp, sp, pc}	@ Load all regs saved previously
+ ARM(	ldmia	r4, {r4 - sl, fp, sp, pc}  )	@ Load all regs saved previously
+ THUMB(	ldmia	ip!, {r4 - sl, fp}	   )	@ Load all regs saved previously
+ THUMB(	ldr	sp, [ip], #4		   )
+ THUMB(	ldr	pc, [ip]		   )
+ENDPROC(__switch_to)
 
 	__INIT
 
@@ -734,6 +778,7 @@ ENTRY(__switch_to)
  * if your compiled code is not going to use the new instructions for other
  * purpose.
  */
+ THUMB(	.arm	)
 
 	.macro	usr_ret, reg
 #ifdef CONFIG_ARM_THUMB
@@ -905,6 +950,7 @@ kuser_cmpxchg_fixup:
 #endif
 1:	ldrex	r3, [r2]
 	subs	r3, r3, r0
+	it	eq
 	strexeq	r3, r1, [r2]
 	teqeq	r3, #1
 	beq	1b
@@ -985,6 +1031,7 @@ __kuser_helper_version:				@ 0xffff0ffc
 	.globl	__kuser_helper_end
 __kuser_helper_end:
 
+ THUMB(	.thumb	)
 
 /*
  * Vector stubs.
@@ -1019,16 +1066,23 @@ vector_\name:
 	@ Prepare for SVC32 mode.  IRQs remain disabled.
 	@
 	mrs	r0, cpsr
-	eor	r0, r0, #(\mode ^ SVC_MODE)
+	eor	r0, r0, #(\mode ^ SVC_MODE | PSR_ISETSTATE)
 	msr	spsr_cxsf, r0
 
 	@
 	@ the branch table must immediately follow this code
 	@
 	and	lr, lr, #0x0f
+ THUMB(	adr	r0, 1f			)
+ THUMB(	ldr	lr, [r0, lr, lsl #2]	)
 	mov	r0, sp
-	ldr	lr, [pc, lr, lsl #2]
+ ARM(	ldr	lr, [pc, lr, lsl #2]	)
 	movs	pc, lr			@ branch to handler in SVC mode
+ENDPROC(vector_\name)
+
+	.align	2
+	@ handler addresses follow this label
+1:
 	.endm
 
 	.globl	__stubs_start
@@ -1166,14 +1220,16 @@ __stubs_end:
 
 	.globl	__vectors_start
 __vectors_start:
-	swi	SYS_ERROR0
-	b	vector_und + stubs_offset
-	ldr	pc, .LCvswi + stubs_offset
-	b	vector_pabt + stubs_offset
-	b	vector_dabt + stubs_offset
-	b	vector_addrexcptn + stubs_offset
-	b	vector_irq + stubs_offset
-	b	vector_fiq + stubs_offset
+ ARM(	swi	SYS_ERROR0	)
+ THUMB(	svc	#0		)
+ THUMB(	nop			)
+	W(b)	vector_und + stubs_offset
+	W(ldr)	pc, .LCvswi + stubs_offset
+	W(b)	vector_pabt + stubs_offset
+	W(b)	vector_dabt + stubs_offset
+	W(b)	vector_addrexcptn + stubs_offset
+	W(b)	vector_irq + stubs_offset
+	W(b)	vector_fiq + stubs_offset
 
 	.globl	__vectors_end
 __vectors_end:
diff --git a/arch/arm/kernel/entry-common.S b/arch/arm/kernel/entry-common.S
index 597ed00..288d5ae 100644
--- a/arch/arm/kernel/entry-common.S
+++ b/arch/arm/kernel/entry-common.S
@@ -8,6 +8,8 @@
  * published by the Free Software Foundation.
  */
 
+#include <asm/unified.h>
+
 #include <asm/unistd.h>
 #include <asm/arch/entry-macro.S>
 
@@ -30,19 +32,37 @@ ret_fast_syscall:
 	arch_ret_to_user r1, lr
 
 	@ fast_restore_user_regs
+#ifdef CONFIG_CPU_V7M
+	enable_irq
+	add	sp, #S_OFF
+	v7m_exception_slow_exit ret_r0=1
+#else
+ THUMB(	mov	r2, sp			     )
+ THUMB(	load_user_sp_lr r2, r3, S_OFF + S_SP )	@ calling sp, lr
 	ldr	r1, [sp, #S_OFF + S_PSR]	@ get calling cpsr
-	ldr	lr, [sp, #S_OFF + S_PC]!	@ get pc
+ ARM(	ldr	lr, [sp, #S_OFF + S_PC]!     )	@ get pc
+ THUMB(	ldr	lr, [sp, #S_OFF + S_PC]	     )	@ get pc
+ THUMB(	add	sp, sp, #S_OFF + S_R1	     )
 	msr	spsr_cxsf, r1			@ save in spsr_svc
-	ldmdb	sp, {r1 - lr}^			@ get calling r1 - lr
+ ARM(	ldmdb	sp, {r1 - lr}^		     )	@ get calling r1 - lr
+ THUMB(	ldmia	sp, {r1 - r12}		     )	@ get calling r1 - r12
 	mov	r0, r0
-	add	sp, sp, #S_FRAME_SIZE - S_PC
+ ARM(	add	sp, sp, #S_FRAME_SIZE - S_PC )
+ THUMB(	add	sp, sp, #S_FRAME_SIZE - S_R1 )
 	movs	pc, lr				@ return & move spsr_svc into cpsr
+#endif
 
 /*
  * Ok, we need to do extra processing, enter the slow path.
  */
 fast_work_pending:
+#ifdef CONFIG_CPU_V7M
+	@ S_R0 not at the beginning of struct pt_regs
+	add	sp, #S_OFF
+	str	r0, [sp, #S_R0]			@ returned r0
+#else
 	str	r0, [sp, #S_R0+S_OFF]!		@ returned r0
+#endif
 work_pending:
 	tst	r1, #_TIF_NEED_RESCHED
 	bne	work_resched
@@ -69,13 +89,23 @@ no_work_pending:
 	arch_ret_to_user r1, lr
 
 	@ slow_restore_user_regs
+#ifdef CONFIG_CPU_V7M
+	v7m_exception_slow_exit ret_r0=0
+#else
+ THUMB(	mov	r2, sp			     )
+ THUMB(	load_user_sp_lr r2, r3, S_SP	     )	@ calling sp, lr
 	ldr	r1, [sp, #S_PSR]		@ get calling cpsr
-	ldr	lr, [sp, #S_PC]!		@ get pc
+ ARM(	ldr	lr, [sp, #S_PC]!	     )	@ get pc
+ THUMB(	ldr	lr, [sp, #S_PC]		     )	@ get pc
 	msr	spsr_cxsf, r1			@ save in spsr_svc
-	ldmdb	sp, {r0 - lr}^			@ get calling r0 - lr
+ ARM(	ldmdb	sp, {r0 - lr}^		     )	@ get calling r0 - lr
+ THUMB(	ldmia	sp, {r0 - r12}		     )	@ get calling r0 - r12
 	mov	r0, r0
-	add	sp, sp, #S_FRAME_SIZE - S_PC
+ ARM(	add	sp, sp, #S_FRAME_SIZE - S_PC )
+ THUMB(	add	sp, sp, #S_FRAME_SIZE	     )
 	movs	pc, lr				@ return & move spsr_svc into cpsr
+#endif
+ENDPROC(ret_to_user)
 
 /*
  * This is how we return from a fork.
@@ -91,7 +121,7 @@ ENTRY(ret_from_fork)
 	mov	r0, #1				@ trace exit [IP = 1]
 	bl	syscall_trace
 	b	ret_slow_syscall
-	
+ENDPROC(ret_from_fork)
 
 	.equ NR_syscalls,0
 #define CALL(x) .equ NR_syscalls,NR_syscalls+1
@@ -120,14 +150,20 @@ ENTRY(ret_from_fork)
 
 	.align	5
 ENTRY(vector_swi)
+#ifdef CONFIG_CPU_V7M
+	v7m_exception_entry
+#else
 	sub	sp, sp, #S_FRAME_SIZE
 	stmia	sp, {r0 - r12}			@ Calling r0 - r12
-	add	r8, sp, #S_PC
-	stmdb	r8, {sp, lr}^			@ Calling sp, lr
+ ARM(	add	r8, sp, #S_PC		)
+ ARM(	stmdb	r8, {sp, lr}^		)	@ Calling sp, lr
+ THUMB(	mov	r8, sp			)
+ THUMB(	store_user_sp_lr r8, r10, S_SP	)	@ calling sp, lr
 	mrs	r8, spsr			@ called from non-FIQ mode, so ok.
 	str	lr, [sp, #S_PC]			@ Save calling PC
 	str	r8, [sp, #S_PSR]		@ Save CPSR
 	str	r0, [sp, #S_OLD_R0]		@ Save OLD_R0
+#endif
 	zero_fp
 
 	/*
@@ -142,6 +178,7 @@ ENTRY(vector_swi)
 	 */
 #ifdef CONFIG_ARM_THUMB
 	tst	r8, #PSR_T_BIT
+	ite	ne
 	movne	r10, #0				@ no thumb OABI emulation
 	ldreq	r10, [lr, #-4]			@ get SWI instruction
 #else
@@ -197,6 +234,7 @@ ENTRY(vector_swi)
 	 * get the old ABI syscall table address.
 	 */
 	bics	r10, r10, #0xff000000
+	itt	ne
 	eorne	scno, r10, #__NR_OABI_SYSCALL_BASE
 	ldrne	tbl, =sys_oabi_call_table
 #elif !defined(CONFIG_AEABI)
@@ -209,7 +247,8 @@ ENTRY(vector_swi)
 	bne	__sys_trace
 
 	cmp	scno, #NR_syscalls		@ check upper syscall limit
-	adr	lr, ret_fast_syscall		@ return address
+	badr	lr, ret_fast_syscall		@ return address
+	it	cc
 	ldrcc	pc, [tbl, scno, lsl #2]		@ call sys_* routine
 
 	add	r1, sp, #S_OFF
@@ -218,6 +257,7 @@ ENTRY(vector_swi)
 	eor	r0, scno, #__NR_SYSCALL_BASE	@ put OS number back
 	bcs	arm_syscall	
 	b	sys_ni_syscall			@ not private func
+ENDPROC(vector_swi)
 
 	/*
 	 * This is the really slow path.  We're going to be doing
@@ -229,16 +269,23 @@ __sys_trace:
 	mov	r0, #0				@ trace entry [IP = 0]
 	bl	syscall_trace
 
-	adr	lr, __sys_trace_return		@ return address
+	badr	lr, __sys_trace_return		@ return address
 	mov	scno, r0			@ syscall number (possibly new)
-	add	r1, sp, #S_R0 + S_OFF		@ pointer to regs
+	add	r1, sp, #S_OFF			@ pointer to regs
 	cmp	scno, #NR_syscalls		@ check upper syscall limit
+	itt	cc
 	ldmccia	r1, {r0 - r3}			@ have to reload r0 - r3
 	ldrcc	pc, [tbl, scno, lsl #2]		@ call sys_* routine
 	b	2b
 
 __sys_trace_return:
+#ifdef CONFIG_CPU_V7M
+	@ S_R0 not at the beginning of struct pt_regs
+	add	sp, #S_OFF
+	str	r0, [sp, #S_R0]			@ save returned r0
+#else
 	str	r0, [sp, #S_R0 + S_OFF]!	@ save returned r0
+#endif
 	mov	r2, scno
 	mov	r1, sp
 	mov	r0, #1				@ trace exit [IP = 1]
@@ -275,65 +322,81 @@ ENTRY(sys_call_table)
  */
 @ r0 = syscall number
 @ r8 = syscall table
-		.type	sys_syscall, #function
 sys_syscall:
 		bic	scno, r0, #__NR_OABI_SYSCALL_BASE
 		cmp	scno, #__NR_syscall - __NR_SYSCALL_BASE
+		it	ne
 		cmpne	scno, #NR_syscalls	@ check range
+		itttt	lo
 		stmloia	sp, {r5, r6}		@ shuffle args
 		movlo	r0, r1
 		movlo	r1, r2
 		movlo	r2, r3
+		itt	lo
 		movlo	r3, r4
 		ldrlo	pc, [tbl, scno, lsl #2]
 		b	sys_ni_syscall
+ENDPROC(sys_syscall)
 
 sys_fork_wrapper:
 		add	r0, sp, #S_OFF
 		b	sys_fork
+ENDPROC(sys_fork_wrapper)
 
 sys_vfork_wrapper:
 		add	r0, sp, #S_OFF
 		b	sys_vfork
+ENDPROC(sys_vfork_wrapper)
 
 sys_execve_wrapper:
 		add	r3, sp, #S_OFF
 		b	sys_execve
+ENDPROC(sys_execve_wrapper)
 
 sys_clone_wrapper:
 		add	ip, sp, #S_OFF
 		str	ip, [sp, #4]
 		b	sys_clone
+ENDPROC(sys_clone_wrapper)
 
 sys_sigsuspend_wrapper:
 		add	r3, sp, #S_OFF
 		b	sys_sigsuspend
+ENDPROC(sys_sigsuspend_wrapper)
 
 sys_rt_sigsuspend_wrapper:
 		add	r2, sp, #S_OFF
 		b	sys_rt_sigsuspend
+ENDPROC(sys_rt_sigsuspend_wrapper)
 
 sys_sigreturn_wrapper:
 		add	r0, sp, #S_OFF
 		b	sys_sigreturn
+ENDPROC(sys_sigreturn_wrapper)
 
 sys_rt_sigreturn_wrapper:
 		add	r0, sp, #S_OFF
 		b	sys_rt_sigreturn
+ENDPROC(sys_rt_sigreturn_wrapper)
 
 sys_sigaltstack_wrapper:
 		ldr	r2, [sp, #S_OFF + S_SP]
 		b	do_sigaltstack
+ENDPROC(sys_sigaltstack_wrapper)
 
 sys_statfs64_wrapper:
 		teq	r1, #88
+		it	eq
 		moveq	r1, #84
 		b	sys_statfs64
+ENDPROC(sys_statfs64_wrapper)
 
 sys_fstatfs64_wrapper:
 		teq	r1, #88
+		it	eq
 		moveq	r1, #84
 		b	sys_fstatfs64
+ENDPROC(sys_fstatfs64_wrapper)
 
 /*
  * Note: off_4k (r5) is always units of 4K.  If we can't do the requested
@@ -342,6 +405,7 @@ sys_fstatfs64_wrapper:
 sys_mmap2:
 #if PAGE_SHIFT > 12
 		tst	r5, #PGOFF_MASK
+		ittt	eq
 		moveq	r5, r5, lsr #PAGE_SHIFT - 12
 		streq	r5, [sp, #4]
 		beq	do_mmap2
@@ -351,11 +415,16 @@ sys_mmap2:
 		str	r5, [sp, #4]
 		b	do_mmap2
 #endif
+ENDPROC(sys_mmap2)
 
 ENTRY(pabort_ifar)
+#ifndef CONFIG_CPU_V7M
 		mrc	p15, 0, r0, cr6, cr0, 2
+#endif
+ENDPROC(pabort_ifar)
 ENTRY(pabort_noifar)
 		mov	pc, lr
+ENDPROC(pabort_noifar)
 
 #ifdef CONFIG_OABI_COMPAT
 
@@ -366,26 +435,31 @@ ENTRY(pabort_noifar)
 sys_oabi_pread64:
 		stmia	sp, {r3, r4}
 		b	sys_pread64
+ENDPROC(sys_oabi_pread64)
 
 sys_oabi_pwrite64:
 		stmia	sp, {r3, r4}
 		b	sys_pwrite64
+ENDPROC(sys_oabi_pwrite64)
 
 sys_oabi_truncate64:
 		mov	r3, r2
 		mov	r2, r1
 		b	sys_truncate64
+ENDPROC(sys_oabi_truncate64)
 
 sys_oabi_ftruncate64:
 		mov	r3, r2
 		mov	r2, r1
 		b	sys_ftruncate64
+ENDPROC(sys_oabi_ftruncate64)
 
 sys_oabi_readahead:
 		str	r3, [sp]
 		mov	r3, r2
 		mov	r2, r1
 		b	sys_readahead
+ENDPROC(sys_oabi_readahead)
 
 /*
  * Let's declare a second syscall table for old ABI binaries
diff --git a/arch/arm/kernel/entry-header.S b/arch/arm/kernel/entry-header.S
index 87ab4e1..92365bf 100644
--- a/arch/arm/kernel/entry-header.S
+++ b/arch/arm/kernel/entry-header.S
@@ -26,7 +26,7 @@
  * The SWI code relies on the fact that R0 is at the bottom of the stack
  * (due to slow/fast restore user regs).
  */
-#if S_R0 != 0
+#if S_R0 != 0 && !defined(CONFIG_CPU_V7M)
 #error "Please fix"
 #endif
 
@@ -37,7 +37,9 @@
 	.endm
 
 	.macro	get_thread_info, rd
-	mov	\rd, sp, lsr #13
+ ARM(	mov	\rd, sp, lsr #13	)
+ THUMB(	mov	\rd, sp			)
+ THUMB(	lsr	\rd, \rd, #13		)
 	mov	\rd, \rd, lsl #13
 	.endm
 
@@ -49,6 +51,136 @@
 #endif
 	.endm
 
+	@
+	@ Store/load the USER SP and LR registers by switching to the SYS
+	@ mode. Useful in Thumb-2 mode where "stm/ldm rd, {sp, lr}^" is not
+	@ available. Should only be called from SVC mode
+	@
+	.macro	store_user_sp_lr, rd, rtemp, offset = 0
+	mrs	\rtemp, cpsr
+	eor	\rtemp, \rtemp, #(SVC_MODE ^ SYSTEM_MODE)
+	msr	cpsr_c, \rtemp			@ switch to the SYS mode
+
+	str	sp, [\rd, #\offset]		@ save sp_usr
+	str	lr, [\rd, #\offset + 4]		@ save lr_usr
+
+	eor	\rtemp, \rtemp, #(SVC_MODE ^ SYSTEM_MODE)
+	msr	cpsr_c, \rtemp			@ switch back to the SVC mode
+	.endm
+
+	.macro	load_user_sp_lr, rd, rtemp, offset = 0
+	mrs	\rtemp, cpsr
+	eor	\rtemp, \rtemp, #(SVC_MODE ^ SYSTEM_MODE)
+	msr	cpsr_c, \rtemp			@ switch to the SYS mode
+
+	ldr	sp, [\rd, #\offset]		@ load sp_usr
+	ldr	lr, [\rd, #\offset + 4]		@ load lr_usr
+
+	eor	\rtemp, \rtemp, #(SVC_MODE ^ SYSTEM_MODE)
+	msr	cpsr_c, \rtemp			@ switch back to the SVC mode
+	.endm
+
+	.macro	arm_rfe, rpsr
+	ldr	\rpsr, [sp, #S_PSR]
+	msr	spsr_cxsf, \rpsr
+	ldmia	sp, {r0 - pc}^			@ load r0 - pc, cpsr
+	.endm
+
+	.macro	thumb_rfe, rsp, rpc, rpsr
+	ldr	\rsp, [sp, #S_SP]		@ top of the stack
+	ldr	\rpc, [sp, #S_PC]		@ return address
+	ldr	\rpsr, [sp, #S_PSR]		@ return cpsr
+	tst	\rsp, #4			@ orig stack 8-byte aligned?
+	stmdb	\rsp, {\rpc, \rpsr}		@ rfe context
+	ldmia	sp, {r0 - r12}
+	ldr	lr, [sp, #S_LR]
+	ite	eq
+	addeq	sp, sp, #S_FRAME_SIZE - 8	@ aligned
+	addne	sp, sp, #S_FRAME_SIZE - 4	@ not aligned
+	rfeia	sp!
+	.endm
+
+/*
+ * ARMv7M exception entry/exit macros.
+ *
+ * xPSR, ReturnAddress(), LR (R14), R12, R3, R2, R1, and R0 are
+ * automatically saved on the current stack (32 words) before
+ * switching to the exception stack (SP_main). The order of struct
+ * pt_regs members was changed to take advantage of the automatic
+ * state saving.
+ *
+ * If exception is taken while in user mode, SP_main is
+ * empty. Otherwise, SP_main is aligned to 64 bit automatically
+ * (CCR.STKALIGN set).
+ *
+ * Linux assumes that the interrupts are disabled when entering an
+ * exception handler and it may BUG if this is not the case. Interrupts
+ * are disabled during entry and reenabled in the exit macro.
+ *
+ * The v7m_exception_entry macro preserves the original r0-r5, r7 for
+ * the system call arguments.
+ *
+ * v7_exception_fast_exit is used when returning from interrupts.
+ *
+ * v7_exception_slow_exit is used when returning from SVC or PendSV.
+ * When returning to kernel mode, we don't return from exception.
+ */
+	.macro	v7m_exception_entry
+	cpsid	i
+	cmp	lr, #0xfffffffd		@ check the return stack
+	beq	1f			@ exception on process stack
+	add	r12, sp, #32		@ MSP before exception
+	stmdb	sp!, {r4-r12, lr}	@ push unsaved registers
+	b	2f
+1:
+	mrs	r12, psp		@ get the process stack
+	sub	sp, #S_FRAME_SIZE
+	stmia	sp, {r4-r12, lr}	@ push unsaved registers
+	ldmia	r12, {r0-r3, r6, r8-r10} @ load automatically saved registers
+	add	r12, sp, #S_R0
+	stmia	r12, {r0-r3, r6, r8-r10} @ fill in the rest of struct pt_regs
+2:
+	.endm
+
+	.macro	v7m_exception_fast_exit
+	ldmia	sp!, {r4-r12, lr}	@ restore previously saved state
+	cmp	lr, #0xfffffffd		@ check the return stack
+	it	eq
+	addeq	sp, #32			@ returning to PSP, just restore MSP
+	cpsie	i
+	bx	lr
+	.endm
+
+	.macro	v7m_exception_slow_exit ret_r0
+	cpsid	i
+	ldr	lr, [sp, #S_EXC_LR]	@ read exception LR
+	cmp	lr, #0xfffffffd		@ check the return stack
+	beq	1f			@ returning to PSP
+	@ Prepare the MSP stack
+	ldmia	sp, {r4-r11}		@ restore previously saved state
+	ldr	lr, [sp, #S_PC]
+	add	sp, #S_R0
+	ldmia	sp, {r0-r3, r12}	@ restore the rest of registers
+	add	sp, #S_FRAME_SIZE-S_R0	@ restore the stack pointer
+	cpsie	i
+	bx	lr
+1:
+	@ Prepare the PSP stack
+	ldr	r12, [sp, #S_SP]	@ read original PSP
+	.if	\ret_r0
+	add	r11, sp, #S_R1
+	ldmia	r11, {r1-r7}		@ read state saved on MSP (r0 preserved)
+	.else
+	add	r11, sp, #S_R0
+	ldmia	r11, {r0-r7}		@ read state saved on MSP
+	.endif
+	msr	psp, r12		@ restore PSP
+	stmia	r12, {r0-r7}		@ restore saved state to PSP
+	ldmia	sp, {r4-r11}		@ restore previously saved state
+	add	sp, #S_FRAME_SIZE	@ restore the original MSP
+	cpsie	i
+	bx	lr
+	.endm
 
 /*
  * These are the registers used in the syscall handler, and allow us to
diff --git a/arch/arm/kernel/entry-v7m.S b/arch/arm/kernel/entry-v7m.S
new file mode 100644
index 0000000..57e1cfd
--- /dev/null
+++ b/arch/arm/kernel/entry-v7m.S
@@ -0,0 +1,125 @@
+/*
+ * linux/arch/arm/kernel/entry-v7m.S
+ *
+ * Copyright (C) 2008 ARM Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Low-level vector interface routines for the ARMv7-M architecture
+ */
+#include <asm/unified.h>
+
+#include <asm/memory.h>
+#include <asm/glue.h>
+#include <asm/arch/entry-macro.S>
+#include <asm/thread_notify.h>
+
+#include "entry-header.S"
+
+#ifdef CONFIG_PREEMPT
+#error "CONFIG_PREEMPT not supported on the current ARMv7M implementation"
+#endif
+#ifdef CONFIG_TRACE_IRQFLAGS
+#error "CONFIG_TRACE_IRQFLAGS not supported on the current ARMv7M implementation"
+#endif
+
+__invalid_entry:
+	v7m_exception_entry
+	mov	r0, sp
+	bl	__show_regs
+1:	b	1b
+ENDPROC(__invalid_entry)
+
+__irq_entry:
+	v7m_exception_entry
+
+	@
+	@ Invoke the IRQ handler
+	@
+	mrs	r0, ipsr
+	and	r0, #0xff
+	sub	r0, #16			@ IRQ number
+	mov	r1, sp
+	@ routine called with r0 = irq number, r1 = struct pt_regs *
+	bl	asm_do_IRQ
+
+	@
+	@ Check for any pending work if returning to user
+	@
+	ldr	lr, [sp, #S_EXC_LR]
+	cmp	lr, #0xfffffffd		@ check the return stack
+	bne	2f			@ returning to kernel
+	get_thread_info tsk
+	ldr	r1, [tsk, #TI_FLAGS]
+	tst	r1, #_TIF_WORK_MASK
+	beq	2f			@ no work pending
+	ldr	r1, =0xe000ed04		@ ICSR
+	mov	r0, #1 << 28		@ ICSR.PENDSVSET
+	str	r0, [r1]		@ raise PendSV
+
+2:
+	v7m_exception_fast_exit
+ENDPROC(__irq_entry)
+
+__pendsv_entry:
+	v7m_exception_entry
+
+	ldr	r1, =0xe000ed04		@ ICSR
+	mov	r0, #1 << 27		@ ICSR.PENDSVCLR
+	str	r0, [r1]		@ clear PendSV
+
+	@ execute the pending work, including reschedule
+	get_thread_info tsk
+	mov	why, #0
+	b	ret_to_user
+ENDPROC(__pendsv_entry)
+
+/*
+ * Register switch for ARMv7-M processors.
+ * r0 = previous task_struct, r1 = previous thread_info, r2 = next thread_info
+ * previous and next are guaranteed not to be the same.
+ */
+ENTRY(__switch_to)
+	add	ip, r1, #TI_CPU_SAVE
+	stmia	ip!, {r4 - sl, fp}	@ Store most regs on stack
+	str	sp, [ip], #4
+	str	lr, [ip], #4
+	mov	r5, r0
+	add	r4, r2, #TI_CPU_SAVE
+	ldr	r0, =thread_notify_head
+	mov	r1, #THREAD_NOTIFY_SWITCH
+	bl	atomic_notifier_call_chain
+	mov	ip, r4
+	mov	r0, r5
+	ldmia	ip!, {r4 - sl, fp}	@ Load all regs saved previously
+	ldr	sp, [ip], #4
+	ldr	pc, [ip]
+ENDPROC(__switch_to)
+
+	.data
+	.align	8
+/*
+ * Vector table (64 words => 256 bytes natural alignment)
+ */
+ENTRY(vector_table)
+	.long	0			@ 0 - Reset stack pointer
+	.long	__invalid_entry		@ 1 - Reset
+	.long	__invalid_entry		@ 2 - NMI
+	.long	__invalid_entry		@ 3 - HardFault
+	.long	__invalid_entry		@ 4 - MemManage
+	.long	__invalid_entry		@ 5 - BusFault
+	.long	__invalid_entry		@ 6 - UsageFault
+	.long	__invalid_entry		@ 7 - Reserved
+	.long	__invalid_entry		@ 8 - Reserved
+	.long	__invalid_entry		@ 9 - Reserved
+	.long	__invalid_entry		@ 10 - Reserved
+	.long	vector_swi		@ 11 - SVCall
+	.long	__invalid_entry		@ 12 - Debug Monitor
+	.long	__invalid_entry		@ 13 - Reserved
+	.long	__pendsv_entry		@ 14 - PendSV
+	.long	__invalid_entry		@ 15 - SysTick
+	.rept	64 - 16
+	.long	__irq_entry		@ 16..64 - External Interrupts
+	.endr
diff --git a/arch/arm/kernel/head-common.S b/arch/arm/kernel/head-common.S
index 7e9c00a..c1e5de5 100644
--- a/arch/arm/kernel/head-common.S
+++ b/arch/arm/kernel/head-common.S
@@ -10,6 +10,7 @@
  * published by the Free Software Foundation.
  *
  */
+#include <asm/unified.h>
 
 #define ATAG_CORE 0x54410001
 #define ATAG_CORE_SIZE ((2*4 + 3*4) >> 2)
@@ -24,7 +25,11 @@ __switch_data:
 	.long	processor_id			@ r4
 	.long	__machine_arch_type		@ r5
 	.long	__atags_pointer			@ r6
+#ifdef CONFIG_CPU_CP15
 	.long	cr_alignment			@ r7
+#else
+	.long	0				@ r7
+#endif
 	.long	init_thread_union + THREAD_START_SP @ sp
 
 /*
@@ -36,12 +41,12 @@ __switch_data:
  *  r2  = atags pointer
  *  r9  = processor ID
  */
-	.type	__mmap_switched, %function
 __mmap_switched:
 	adr	r3, __switch_data + 4
 
 	ldmia	r3!, {r4, r5, r6, r7}
 	cmp	r4, r5				@ Copy data segment if needed
+	itttt	ne
 1:	cmpne	r5, r6
 	ldrne	fp, [r4], #4
 	strne	fp, [r5], #4
@@ -49,16 +54,20 @@ __mmap_switched:
 
 	mov	fp, #0				@ Clear BSS (and zero fp)
 1:	cmp	r6, r7
+	itt	cc
 	strcc	fp, [r6],#4
 	bcc	1b
 
-	ldmia	r3, {r4, r5, r6, r7, sp}
+ ARM(	ldmia	r3, {r4, r5, r6, r7, sp})
+ THUMB(	ldmia	r3, {r4, r5, r6, r7}	)
+ THUMB(	ldr	sp, [r3, #16]		)
 	str	r9, [r4]			@ Save processor ID
 	str	r1, [r5]			@ Save machine type
 	str	r2, [r6]			@ Save atags pointer
 	bic	r4, r0, #CR_A			@ Clear 'A' bit
 	stmia	r7, {r0, r4}			@ Save control register values
 	b	start_kernel
+ENDPROC(__mmap_switched)
 
 /*
  * Exception handling.  Something went wrong and we can't proceed.  We
@@ -69,8 +78,6 @@ __mmap_switched:
  * and hope for the best (useful if bootloader fails to pass a proper
  * machine ID for example).
  */
-
-	.type	__error_p, %function
 __error_p:
 #ifdef CONFIG_DEBUG_LL
 	adr	r0, str_p1
@@ -84,8 +91,8 @@ str_p1:	.asciz	"\nError: unrecognized/unsupported processor variant (0x"
 str_p2:	.asciz	").\n"
 	.align
 #endif
+ENDPROC(__error_p)
 
-	.type	__error_a, %function
 __error_a:
 #ifdef CONFIG_DEBUG_LL
 	mov	r4, r1				@ preserve machine ID
@@ -115,13 +122,14 @@ __error_a:
 	adr	r0, str_a3
 	bl	printascii
 	b	__error
+ENDPROC(__error_a)
+
 str_a1:	.asciz	"\nError: unrecognized/unsupported machine ID (r1 = 0x"
 str_a2:	.asciz	").\n\nAvailable machine support:\n\nID (hex)\tNAME\n"
 str_a3:	.asciz	"\nPlease check your kernel config and/or bootloader.\n"
 	.align
 #endif
 
-	.type	__error, %function
 __error:
 #ifdef CONFIG_ARCH_RPC
 /*
@@ -138,6 +146,7 @@ __error:
 #endif
 1:	mov	r0, r0
 	b	1b
+ENDPROC(__error)
 
 
 /*
@@ -153,10 +162,12 @@ __error:
  *	r5 = proc_info pointer in physical address space
  *	r9 = cpuid (preserved)
  */
-	.type	__lookup_processor_type, %function
 __lookup_processor_type:
-	adr	r3, 3f
-	ldmda	r3, {r5 - r7}
+ ARM(	adr	r3, 3f		)
+ ARM(	ldmda	r3, {r5 - r7}	)
+ THUMB(	adr	r3, 3f+4	)
+ THUMB(	ldmdb	r3, {r5 - r7}	)
+ THUMB(	sub	r3, r3, #4	)
 	sub	r3, r3, r7			@ get offset between virt&phys
 	add	r5, r5, r3			@ convert virt addresses to
 	add	r6, r6, r3			@ physical address space
@@ -169,6 +180,7 @@ __lookup_processor_type:
 	blo	1b
 	mov	r5, #0				@ unknown processor
 2:	mov	pc, lr
+ENDPROC(__lookup_processor_type)
 
 /*
  * This provides a C-API version of the above function.
@@ -179,6 +191,7 @@ ENTRY(lookup_processor_type)
 	bl	__lookup_processor_type
 	mov	r0, r5
 	ldmfd	sp!, {r4 - r7, r9, pc}
+ENDPROC(lookup_processor_type)
 
 /*
  * Look in include/asm-arm/procinfo.h and arch/arm/kernel/arch.[ch] for
@@ -201,7 +214,6 @@ ENTRY(lookup_processor_type)
  *  r3, r4, r6 corrupted
  *  r5 = mach_info pointer in physical address space
  */
-	.type	__lookup_machine_type, %function
 __lookup_machine_type:
 	adr	r3, 3b
 	ldmia	r3, {r4, r5, r6}
@@ -216,6 +228,7 @@ __lookup_machine_type:
 	blo	1b
 	mov	r5, #0				@ unknown machine
 2:	mov	pc, lr
+ENDPROC(__lookup_machine_type)
 
 /*
  * This provides a C-API version of the above function.
@@ -226,6 +239,7 @@ ENTRY(lookup_machine_type)
 	bl	__lookup_machine_type
 	mov	r0, r5
 	ldmfd	sp!, {r4 - r6, pc}
+ENDPROC(lookup_machine_type)
 
 /* Determine validity of the r2 atags pointer.  The heuristic requires
  * that the pointer be aligned, in the first 16k of physical RAM and
@@ -239,8 +253,6 @@ ENTRY(lookup_machine_type)
  *  r2 either valid atags pointer, or zero
  *  r5, r6 corrupted
  */
-
-	.type	__vet_atags, %function
 __vet_atags:
 	tst	r2, #0x3			@ aligned?
 	bne	1f
@@ -257,3 +269,4 @@ __vet_atags:
 
 1:	mov	r2, #0
 	mov	pc, lr
+ENDPROC(__vet_atags)
diff --git a/arch/arm/kernel/head-nommu.S b/arch/arm/kernel/head-nommu.S
index 5d78ffb..953a6b5 100644
--- a/arch/arm/kernel/head-nommu.S
+++ b/arch/arm/kernel/head-nommu.S
@@ -11,6 +11,8 @@
  *  Common kernel startup code (non-paged MM)
  *
  */
+#include <asm/unified.h>
+
 #include <linux/linkage.h>
 #include <linux/init.h>
 
@@ -21,6 +23,9 @@
 #include <asm/thread_info.h>
 #include <asm/system.h>
 
+#define ATAG_CORE	0x54410001
+#define ATAG_CORE_SIZE	((2*4 + 3*4) >> 2)
+
 /*
  * Kernel startup entry point.
  * ---------------------------
@@ -34,14 +39,21 @@
  *
  */
 	.section ".text.head", "ax"
-	.type	stext, %function
 ENTRY(stext)
-	msr	cpsr_c, #PSR_F_BIT | PSR_I_BIT | SVC_MODE @ ensure svc mode
-						@ and irqs disabled
-#ifndef CONFIG_CPU_CP15
-	ldr	r9, =CONFIG_PROCESSOR_ID
+#ifndef CONFIG_CPU_V7M
+ ARM(	msr	cpsr_c, #PSR_F_BIT | PSR_I_BIT | SVC_MODE ) @ ensure svc mode
+ THUMB(	mov	r9, #PSR_F_BIT | PSR_I_BIT | SVC_MODE )
+ THUMB(	msr	cpsr_c, r9 )			@ ensure svc mode
 #else
+	cpsid	i				@ disable interrupts
+#endif
+#if defined(CONFIG_CPU_CP15)
 	mrc	p15, 0, r9, c0, c0		@ get processor id
+#elif defined(CONFIG_CPU_V7M)
+	ldr	r9, =0xe000ed00			@ CPUID register address
+	ldr	r9, [r9]
+#else
+	ldr	r9, =CONFIG_PROCESSOR_ID
 #endif
 	bl	__lookup_processor_type		@ r5=procinfo r9=cpuid
 	movs	r10, r5				@ invalid processor (r5=0)?
@@ -52,16 +64,21 @@ ENTRY(stext)
 
 	ldr	r13, __switch_data		@ address to jump to after
 						@ the initialization is done
-	adr	lr, __after_proc_init		@ return (PIC) address
-	add	pc, r10, #PROCINFO_INITFUNC
+	badr	lr, __after_proc_init		@ return (PIC) address
+ ARM(	add	pc, r10, #PROCINFO_INITFUNC	)
+ THUMB(	add	r12, r10, #PROCINFO_INITFUNC	)
+ THUMB(	mov	pc, r12				)
+ENDPROC(stext)
 
 /*
  * Set the Control Register and Read the process ID.
  */
-	.type	__after_proc_init, %function
 __after_proc_init:
 #ifdef CONFIG_CPU_CP15
-	mrc	p15, 0, r0, c1, c0, 0		@ read control reg
+	/*
+	 * CP15 system control register value returned in r0 from
+	 * the CPU init function.
+	 */
 #ifdef CONFIG_ALIGNMENT_TRAP
 	orr	r0, r0, #CR_A
 #else
@@ -86,6 +103,7 @@ __after_proc_init:
 
 	mov	pc, r13				@ clear the BSS and jump
 						@ to start_kernel
+ENDPROC(__after_proc_init)
 	.ltorg
 
 #include "head-common.S"
diff --git a/arch/arm/kernel/head.S b/arch/arm/kernel/head.S
index bff4c6e..50df792 100644
--- a/arch/arm/kernel/head.S
+++ b/arch/arm/kernel/head.S
@@ -11,6 +11,8 @@
  *
  *  Kernel startup code for all 32-bit CPUs
  */
+#include <asm/unified.h>
+
 #include <linux/linkage.h>
 #include <linux/init.h>
 
@@ -75,9 +77,10 @@
  * circumstances, zImage) is for.
  */
 	.section ".text.head", "ax"
-	.type	stext, %function
 ENTRY(stext)
-	msr	cpsr_c, #PSR_F_BIT | PSR_I_BIT | SVC_MODE @ ensure svc mode
+ ARM(	msr	cpsr_c, #PSR_F_BIT | PSR_I_BIT | SVC_MODE ) @ ensure svc mode
+ THUMB(	mov	r9, #PSR_F_BIT | PSR_I_BIT | SVC_MODE )
+ THUMB(	msr	cpsr_c, r9 )			@ ensure svc mode
 						@ and irqs disabled
 	mrc	p15, 0, r9, c0, c0		@ get processor id
 	bl	__lookup_processor_type		@ r5=procinfo r9=cpuid
@@ -98,11 +101,13 @@ ENTRY(stext)
 	 */
 	ldr	r13, __switch_data		@ address to jump to after
 						@ mmu has been enabled
-	adr	lr, __enable_mmu		@ return (PIC) address
-	add	pc, r10, #PROCINFO_INITFUNC
+	badr	lr, __enable_mmu		@ return (PIC) address
+ ARM(	add	pc, r10, #PROCINFO_INITFUNC	)
+ THUMB(	add	r12, r10, #PROCINFO_INITFUNC	)
+ THUMB(	mov	pc, r12				)
+ENDPROC(stext)
 
 #if defined(CONFIG_SMP)
-	.type   secondary_startup, #function
 ENTRY(secondary_startup)
 	/*
 	 * Common entry point for secondary CPUs.
@@ -125,9 +130,12 @@ ENTRY(secondary_startup)
 	ldmia	r4, {r5, r7, r13}		@ address to jump to after
 	sub	r4, r4, r5			@ mmu has been enabled
 	ldr	r4, [r7, r4]			@ get secondary_data.pgdir
-	adr	lr, __enable_mmu		@ return address
-	add	pc, r10, #PROCINFO_INITFUNC	@ initialise processor
-						@ (return control reg)
+	badr	lr, __enable_mmu		@ return address
+ ARM(	add	pc, r10, #PROCINFO_INITFUNC	) @ initialise processor
+						  @ (return control reg)
+ THUMB(	add	r12, r10, #PROCINFO_INITFUNC	)
+ THUMB(	mov	pc, r12				)
+ENDPROC(secondary_startup)
 
 	/*
 	 * r6  = &secondary_data
@@ -136,6 +144,7 @@ ENTRY(__secondary_switched)
 	ldr	sp, [r7, #4]			@ get secondary_data.stack
 	mov	fp, #0
 	b	secondary_start_kernel
+ENDPROC(__secondary_switched)
 
 	.type	__secondary_data, %object
 __secondary_data:
@@ -151,7 +160,6 @@ __secondary_data:
  * this is just loading the page table pointer and domain access
  * registers.
  */
-	.type	__enable_mmu, %function
 __enable_mmu:
 #ifdef CONFIG_ALIGNMENT_TRAP
 	orr	r0, r0, #CR_A
@@ -174,6 +182,7 @@ __enable_mmu:
 	mcr	p15, 0, r5, c3, c0, 0		@ load domain access register
 	mcr	p15, 0, r4, c2, c0, 0		@ load page table pointer
 	b	__turn_mmu_on
+ENDPROC(__enable_mmu)
 
 /*
  * Enable the MMU.  This completely changes the structure of the visible
@@ -187,7 +196,6 @@ __enable_mmu:
  * other registers depend on the function called upon completion
  */
 	.align	5
-	.type	__turn_mmu_on, %function
 __turn_mmu_on:
 	mov	r0, r0
 	mcr	p15, 0, r0, c1, c0, 0		@ write control reg
@@ -195,7 +203,7 @@ __turn_mmu_on:
 	mov	r3, r3
 	mov	r3, r3
 	mov	pc, r13
-
+ENDPROC(__turn_mmu_on)
 
 
 /*
@@ -211,7 +219,6 @@ __turn_mmu_on:
  *  r0, r3, r6, r7 corrupted
  *  r4 = physical page table address
  */
-	.type	__create_page_tables, %function
 __create_page_tables:
 	pgtbl	r4				@ page table address
 
@@ -251,6 +258,7 @@ __create_page_tables:
 	add	r6, r4, r6, lsr #18
 1:	cmp	r0, r6
 	add	r3, r3, #1 << 20
+	it	ls
 	strls	r3, [r0], #4
 	bls	1b
 
@@ -294,6 +302,7 @@ __create_page_tables:
 	add	r0, r4, r3
 	rsb	r3, r3, #0x4000			@ PTRS_PER_PGD*sizeof(long)
 	cmp	r3, #0x0800			@ limit to 512MB
+	it	hi
 	movhi	r3, #0x0800
 	add	r6, r0, r3
 	ldr	r3, [r8, #MACHINFO_PHYSIO]
@@ -325,6 +334,7 @@ __create_page_tables:
 #endif
 #endif
 	mov	pc, lr
+ENDPROC(__create_page_tables)
 	.ltorg
 
 #include "head-common.S"
diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c
index 46bf2ed..0724f75 100644
--- a/arch/arm/kernel/process.c
+++ b/arch/arm/kernel/process.c
@@ -29,6 +29,7 @@
 #include <linux/tick.h>
 #include <linux/utsname.h>
 
+#include <asm/unified.h>
 #include <asm/leds.h>
 #include <asm/processor.h>
 #include <asm/system.h>
@@ -395,7 +396,11 @@ pid_t kernel_thread(int (*fn)(void *), void *arg, unsigned long flags)
 	regs.ARM_r2 = (unsigned long)fn;
 	regs.ARM_r3 = (unsigned long)do_exit;
 	regs.ARM_pc = (unsigned long)kernel_thread_helper;
-	regs.ARM_cpsr = SVC_MODE;
+	regs.ARM_cpsr = SVC_MODE | PSR_ISETSTATE;
+#ifdef CONFIG_CPU_V7M
+	/* Return to Handler mode */
+	regs.ARM_EXC_lr = 0xfffffff1L;
+#endif
 
 	return do_fork(flags|CLONE_VM|CLONE_UNTRACED, 0, &regs, 0, NULL, NULL);
 }
diff --git a/arch/arm/kernel/ptrace.c b/arch/arm/kernel/ptrace.c
index 4b05dc5..de49766 100644
--- a/arch/arm/kernel/ptrace.c
+++ b/arch/arm/kernel/ptrace.c
@@ -523,7 +523,13 @@ static int ptrace_read_user(struct task_struct *tsk, unsigned long off,
 		return -EIO;
 
 	tmp = 0;
-	if (off < sizeof(struct pt_regs))
+	if (off == PT_TEXT_ADDR)
+		tmp = tsk->mm->start_code;
+	else if (off == PT_DATA_ADDR)
+		tmp = tsk->mm->start_data;
+	else if (off == PT_TEXT_END_ADDR)
+		tmp = tsk->mm->end_code;
+	else if (off < sizeof(struct pt_regs))
 		tmp = get_user_reg(tsk, off >> 2);
 
 	return put_user(tmp, ret);
diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c
index b7b0720..ca65bf7 100644
--- a/arch/arm/kernel/setup.c
+++ b/arch/arm/kernel/setup.c
@@ -25,6 +25,7 @@
 #include <linux/smp.h>
 #include <linux/fs.h>
 
+#include <asm/unified.h>
 #include <asm/cpu.h>
 #include <asm/elf.h>
 #include <asm/procinfo.h>
@@ -111,6 +112,9 @@ EXPORT_SYMBOL(elf_platform);
 unsigned long phys_initrd_start __initdata = 0;
 unsigned long phys_initrd_size __initdata = 0;
 
+unsigned long memory_start;
+unsigned long memory_end;
+
 static struct meminfo meminfo __initdata = { 0, };
 static const char *cpu_name;
 static const char *machine_name;
@@ -294,6 +298,12 @@ static void __init dump_cpu_info(int cpu)
 		printk("Cache coherency enabled\n");
 }
 
+#ifdef CONFIG_CPU_V7M
+int cpu_architecture(void)
+{
+	return CPU_ARCH_ARMv7M;
+}
+#else
 int cpu_architecture(void)
 {
 	int cpu_arch;
@@ -326,6 +336,7 @@ int cpu_architecture(void)
 
 	return cpu_arch;
 }
+#endif
 
 /*
  * These functions re-use the assembly code in head.S, which
@@ -365,9 +376,15 @@ static void __init setup_processor(void)
 	cpu_cache = *list->cache;
 #endif
 
+#ifdef CONFIG_CPU_V7M
+	printk("CPU: %s [%08x] revision %d (ARMv%sM)\n",
+	       cpu_name, processor_id, (int)processor_id & 15,
+	       proc_arch[cpu_architecture()]);
+#else
 	printk("CPU: %s [%08x] revision %d (ARMv%s), cr=%08lx\n",
 	       cpu_name, processor_id, (int)processor_id & 15,
 	       proc_arch[cpu_architecture()], cr_alignment);
+#endif
 
 	sprintf(init_utsname()->machine, "%s%c", list->arch_name, ENDIANNESS);
 	sprintf(elf_platform, "%s%c", list->elf_name, ENDIANNESS);
@@ -398,6 +415,7 @@ void cpu_init(void)
 	if (system_state == SYSTEM_BOOTING)
 		dump_cpu_info(cpu);
 
+#ifndef CONFIG_CPU_V7M
 	/*
 	 * setup stacks for re-entrant exception handlers
 	 */
@@ -411,14 +429,19 @@ void cpu_init(void)
 	"msr	cpsr_c, %7"
 	    :
 	    : "r" (stk),
-	      "I" (PSR_F_BIT | PSR_I_BIT | IRQ_MODE),
+	ARM(  "I" (PSR_F_BIT | PSR_I_BIT | IRQ_MODE),	)
+	THUMB("r" (PSR_F_BIT | PSR_I_BIT | IRQ_MODE),	)
 	      "I" (offsetof(struct stack, irq[0])),
-	      "I" (PSR_F_BIT | PSR_I_BIT | ABT_MODE),
+	ARM(  "I" (PSR_F_BIT | PSR_I_BIT | ABT_MODE),	)
+	THUMB("r" (PSR_F_BIT | PSR_I_BIT | ABT_MODE),	)
 	      "I" (offsetof(struct stack, abt[0])),
-	      "I" (PSR_F_BIT | PSR_I_BIT | UND_MODE),
+	ARM(  "I" (PSR_F_BIT | PSR_I_BIT | UND_MODE),	)
+	THUMB("r" (PSR_F_BIT | PSR_I_BIT | UND_MODE),	)
 	      "I" (offsetof(struct stack, und[0])),
-	      "I" (PSR_F_BIT | PSR_I_BIT | SVC_MODE)
+	ARM(  "I" (PSR_F_BIT | PSR_I_BIT | SVC_MODE)	)
+	THUMB("r" (PSR_F_BIT | PSR_I_BIT | SVC_MODE)	)
 	    : "r14");
+#endif
 }
 
 static struct machine_desc * __init setup_machine(unsigned int nr)
@@ -469,6 +492,12 @@ static void __init arm_add_memory(unsigned long start, unsigned long size)
 	bank->start = PAGE_ALIGN(start);
 	bank->size  = size & PAGE_MASK;
 	bank->node  = PHYS_TO_NID(start);
+
+	if (meminfo.nr_banks == 1) {
+		memory_start = bank->start;
+		memory_end = memory_start + bank->size;
+	}
+	BUG_ON(memory_start == memory_end);
 }
 
 /*
diff --git a/arch/arm/kernel/signal.c b/arch/arm/kernel/signal.c
index ef2f86a..f843c28 100644
--- a/arch/arm/kernel/signal.c
+++ b/arch/arm/kernel/signal.c
@@ -534,7 +534,9 @@ setup_rt_frame(int usig, struct k_sigaction *ka, siginfo_t *info,
 
 static inline void restart_syscall(struct pt_regs *regs)
 {
+#ifndef CONFIG_CPU_V7M
 	regs->ARM_r0 = regs->ARM_ORIG_r0;
+#endif
 	regs->ARM_pc -= thumb_mode(regs) ? 2 : 4;
 }
 
diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c
index 5595fdd..9b60271 100644
--- a/arch/arm/kernel/traps.c
+++ b/arch/arm/kernel/traps.c
@@ -708,6 +708,7 @@ EXPORT_SYMBOL(abort);
 
 void __init trap_init(void)
 {
+#ifndef CONFIG_CPU_V7M
 	unsigned long vectors = CONFIG_VECTORS_BASE;
 	extern char __stubs_start[], __stubs_end[];
 	extern char __vectors_start[], __vectors_end[];
@@ -732,4 +733,5 @@ void __init trap_init(void)
 
 	flush_icache_range(vectors, vectors + PAGE_SIZE);
 	modify_domain(DOMAIN_USER, DOMAIN_CLIENT);
+#endif
 }
diff --git a/arch/arm/lib/ashldi3.S b/arch/arm/lib/ashldi3.S
index 55e57a1..dbbf4c4 100644
--- a/arch/arm/lib/ashldi3.S
+++ b/arch/arm/lib/ashldi3.S
@@ -25,6 +25,7 @@ along with this program; see the file COPYING.  If not, write to
 the Free Software Foundation, 51 Franklin Street, Fifth Floor,
 Boston, MA 02110-1301, USA.  */
 
+#include <asm/unified.h>
 
 #include <linux/linkage.h>
 
@@ -41,9 +42,14 @@ ENTRY(__aeabi_llsl)
 
 	subs	r3, r2, #32
 	rsb	ip, r2, #32
+	itett	mi
 	movmi	ah, ah, lsl r2
 	movpl	ah, al, lsl r3
-	orrmi	ah, ah, al, lsr ip
+ ARM(	orrmi	ah, ah, al, lsr ip	)
+ THUMB(	lsrmi	r3, al, ip		)
+ THUMB(	orrmi	ah, ah, r3		)
 	mov	al, al, lsl r2
 	mov	pc, lr
 
+ENDPROC(__ashldi3)
+ENDPROC(__aeabi_llsl)
diff --git a/arch/arm/lib/ashrdi3.S b/arch/arm/lib/ashrdi3.S
index 0b31398..92d56cc 100644
--- a/arch/arm/lib/ashrdi3.S
+++ b/arch/arm/lib/ashrdi3.S
@@ -25,6 +25,7 @@ along with this program; see the file COPYING.  If not, write to
 the Free Software Foundation, 51 Franklin Street, Fifth Floor,
 Boston, MA 02110-1301, USA.  */
 
+#include <asm/unified.h>
 
 #include <linux/linkage.h>
 
@@ -41,9 +42,14 @@ ENTRY(__aeabi_lasr)
 
 	subs	r3, r2, #32
 	rsb	ip, r2, #32
+	itett	mi
 	movmi	al, al, lsr r2
 	movpl	al, ah, asr r3
-	orrmi	al, al, ah, lsl ip
+ ARM(	orrmi	al, al, ah, lsl ip	)
+ THUMB(	lslmi	r3, ah, ip		)
+ THUMB(	orrmi	al, al, r3		)
 	mov	ah, ah, asr r2
 	mov	pc, lr
 
+ENDPROC(__ashrdi3)
+ENDPROC(__aeabi_lasr)
diff --git a/arch/arm/lib/backtrace.S b/arch/arm/lib/backtrace.S
index 84dc890..343b6fb 100644
--- a/arch/arm/lib/backtrace.S
+++ b/arch/arm/lib/backtrace.S
@@ -10,6 +10,8 @@
  * 27/03/03 Ian Molton Clean up CONFIG_CPU
  *
  */
+#include <asm/unified.h>
+
 #include <linux/linkage.h>
 #include <asm/assembler.h>
 		.text
@@ -28,15 +30,20 @@ ENTRY(__backtrace)
 
 ENTRY(c_backtrace)
 
-#if !defined(CONFIG_FRAME_POINTER) || !defined(CONFIG_PRINTK)
+#if defined(CONFIG_THUMB2_KERNEL) || !defined(CONFIG_FRAME_POINTER) || !defined(CONFIG_PRINTK)
 		mov	pc, lr
+ENDPROC(__backtrace)
+ENDPROC(c_backtrace)
 #else
 		stmfd	sp!, {r4 - r8, lr}	@ Save an extra register so we have a location...
 		movs	frame, r0		@ if frame pointer is zero
 		beq	no_frame		@ we have no stack frames
 
 		tst	r1, #0x10		@ 26 or 32-bit mode?
-		moveq	mask, #0xfc000003	@ mask for 26-bit
+		itte	eq
+ ARM(		moveq	mask, #0xfc000003	)
+ THUMB(		moveq	mask, #0xfc000000	)
+ THUMB(		orreq	mask, #0x03		)
 		movne	mask, #0		@ mask for 32-bit
 
 1:		stmfd	sp!, {pc}		@ calculate offset of PC stored
@@ -71,6 +78,7 @@ for_each_frame:	tst	frame, mask		@ Check for address exceptions
 1003:		ldr	r2, [sv_pc, #-4]	@ if stmfd sp!, {args} exists,
 		ldr	r3, .Ldsi+4		@ adjust saved 'pc' back one
 		teq	r3, r2, lsr #10		@ instruction
+		ite	ne
 		subne	r0, sv_pc, #4		@ allow for mov
 		subeq	r0, sv_pc, #8		@ allow for mov + stmia
 
@@ -82,6 +90,7 @@ for_each_frame:	tst	frame, mask		@ Check for address exceptions
 		ldr	r1, [sv_pc, #-4]	@ if stmfd sp!, {args} exists,
 		ldr	r3, .Ldsi+4
 		teq	r3, r1, lsr #10
+		ittt	eq
 		ldreq	r0, [frame, #-8]	@ get sp
 		subeq	r0, r0, #4		@ point at the last arg
 		bleq	.Ldumpstm		@ dump saved registers
@@ -89,6 +98,7 @@ for_each_frame:	tst	frame, mask		@ Check for address exceptions
 1004:		ldr	r1, [sv_pc, #0]		@ if stmfd sp!, {..., fp, ip, lr, pc}
 		ldr	r3, .Ldsi		@ instruction exists,
 		teq	r3, r1, lsr #10
+		itt	eq
 		subeq	r0, frame, #16
 		bleq	.Ldumpstm		@ dump saved registers
 
@@ -103,6 +113,8 @@ for_each_frame:	tst	frame, mask		@ Check for address exceptions
 		mov	r1, frame
 		bl	printk
 no_frame:	ldmfd	sp!, {r4 - r8, pc}
+ENDPROC(__backtrace)
+ENDPROC(c_backtrace)
 		
 		.section __ex_table,"a"
 		.align	3
@@ -122,10 +134,13 @@ no_frame:	ldmfd	sp!, {r4 - r8, pc}
 		mov	reg, #10
 		mov	r7, #0
 1:		mov	r3, #1
-		tst	instr, r3, lsl reg
+ ARM(		tst	instr, r3, lsl reg	)
+ THUMB(		lsl	r3, reg			)
+ THUMB(		tst	instr, r3		)
 		beq	2f
 		add	r7, r7, #1
 		teq	r7, #6
+		itte	eq
 		moveq	r7, #1
 		moveq	r1, #'\n'
 		movne	r1, #' '
@@ -136,6 +151,7 @@ no_frame:	ldmfd	sp!, {r4 - r8, pc}
 2:		subs	reg, reg, #1
 		bpl	1b
 		teq	r7, #0
+		itt	ne
 		adrne	r0, .Lcr
 		blne	printk
 		ldmfd	sp!, {instr, reg, stack, r7, pc}
diff --git a/arch/arm/lib/bitops.h b/arch/arm/lib/bitops.h
index 2e787d4..5e34c12 100644
--- a/arch/arm/lib/bitops.h
+++ b/arch/arm/lib/bitops.h
@@ -13,18 +13,22 @@
 	mov	pc, lr
 	.endm
 
-	.macro	testop, instr, store
+	.macro	testop, instr, store, cond=al
 	and	r3, r0, #7		@ Get bit offset
 	mov	r2, #1
 	add	r1, r1, r0, lsr #3	@ Get byte offset
 	mov	r3, r2, lsl r3		@ create mask
 1:	ldrexb	r2, [r1]
 	ands	r0, r2, r3		@ save old value of bit
-	\instr	r2, r2, r3			@ toggle bit
+	.ifnc	\cond,al
+	it	\cond
+	.endif
+	\instr	r2, r2, r3		@ toggle bit
 	strexb	ip, r2, [r1]
 	cmp	ip, #0
 	bne	1b
 	cmp	r0, #0
+	it	ne
 	movne	r0, #1
 2:	mov	pc, lr
 	.endm
@@ -49,7 +53,7 @@
  * Note: we can trivially conditionalise the store instruction
  * to avoid dirtying the data cache.
  */
-	.macro	testop, instr, store
+	.macro	testop, instr, store, cond=al
 	add	r1, r1, r0, lsr #3
 	and	r3, r0, #7
 	mov	r0, #1
diff --git a/arch/arm/lib/changebit.S b/arch/arm/lib/changebit.S
index 389567c..477e111 100644
--- a/arch/arm/lib/changebit.S
+++ b/arch/arm/lib/changebit.S
@@ -7,6 +7,8 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
+#include <asm/unified.h>
+
 #include <linux/linkage.h>
 #include <asm/assembler.h>
 #include "bitops.h"
@@ -19,3 +21,5 @@ ENTRY(_change_bit_be)
 		eor	r0, r0, #0x18		@ big endian byte ordering
 ENTRY(_change_bit_le)
 	bitop	eor
+ENDPROC(_change_bit_be)
+ENDPROC(_change_bit_le)
diff --git a/arch/arm/lib/clear_user.S b/arch/arm/lib/clear_user.S
index ecb28dc..e2be2b2 100644
--- a/arch/arm/lib/clear_user.S
+++ b/arch/arm/lib/clear_user.S
@@ -7,6 +7,8 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
+#include <asm/unified.h>
+
 #include <linux/linkage.h>
 #include <asm/assembler.h>
 
@@ -26,24 +28,45 @@ ENTRY(__clear_user)
 		ands	ip, r0, #3
 		beq	1f
 		cmp	ip, #2
-USER(		strbt	r2, [r0], #1)
-USER(		strlebt	r2, [r0], #1)
-USER(		strltbt	r2, [r0], #1)
+ARM(USER(	strbt	r2, [r0], #1	))
+THUMB(USER(	strbt	r2, [r0]	))
+THUMB(		add	r0, #1		)
+ARM(USER(	strlebt	r2, [r0], #1	))
+		itt	le
+THUMB(USER(	strlebt	r2, [r0]	))
+THUMB(		addle	r0, #1		)
+ARM(USER(	strltbt	r2, [r0], #1	))
+		itt	lt
+THUMB(USER(	strltbt	r2, [r0]	))
+THUMB(		addlt	r0, #1		)
 		rsb	ip, ip, #4
 		sub	r1, r1, ip		@  7  6  5  4  3  2  1
 1:		subs	r1, r1, #8		@ -1 -2 -3 -4 -5 -6 -7
-USER(		strplt	r2, [r0], #4)
-USER(		strplt	r2, [r0], #4)
+ARM(USER(	strplt	r2, [r0], #4	))
+ARM(USER(	strplt	r2, [r0], #4	))
+		itttt	pl
+THUMB(USER(	strplt	r2, [r0]	))
+THUMB(USER(	strplt	r2, [r0, #4]	))
+THUMB(		addpl	r0, #8		)
 		bpl	1b
 		adds	r1, r1, #4		@  3  2  1  0 -1 -2 -3
-USER(		strplt	r2, [r0], #4)
+ARM(USER(	strplt	r2, [r0], #4	))
+		itt	pl
+THUMB(USER(	strplt	r2, [r0]	))
+THUMB(		addpl	r0, #4		)
 2:		tst	r1, #2			@ 1x 1x 0x 0x 1x 1x 0x
-USER(		strnebt	r2, [r0], #1)
-USER(		strnebt	r2, [r0], #1)
+ARM(USER(	strnebt	r2, [r0], #1	))
+ARM(USER(	strnebt	r2, [r0], #1	))
+		ittt	ne
+THUMB(USER(	strnebt	r2, [r0]	))
+THUMB(USER(	strnebt	r2, [r0, #1]	))
+THUMB(		addne	r0, #2		)
 		tst	r1, #1			@ x1 x0 x1 x0 x1 x0 x1
-USER(		strnebt	r2, [r0], #1)
+		it	ne
+USER(		strnebt	r2, [r0]	)
 		mov	r0, #0
 		ldmfd	sp!, {r1, pc}
+ENDPROC(__clear_user)
 
 		.section .fixup,"ax"
 		.align	0
diff --git a/arch/arm/lib/clearbit.S b/arch/arm/lib/clearbit.S
index 3475165..ad17f9a 100644
--- a/arch/arm/lib/clearbit.S
+++ b/arch/arm/lib/clearbit.S
@@ -7,6 +7,8 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
+#include <asm/unified.h>
+
 #include <linux/linkage.h>
 #include <asm/assembler.h>
 #include "bitops.h"
@@ -20,3 +22,5 @@ ENTRY(_clear_bit_be)
 		eor	r0, r0, #0x18		@ big endian byte ordering
 ENTRY(_clear_bit_le)
 	bitop	bic
+ENDPROC(_clear_bit_be)
+ENDPROC(_clear_bit_le)
diff --git a/arch/arm/lib/copy_from_user.S b/arch/arm/lib/copy_from_user.S
index 6b7363c..9c6e101 100644
--- a/arch/arm/lib/copy_from_user.S
+++ b/arch/arm/lib/copy_from_user.S
@@ -9,6 +9,7 @@
  *  it under the terms of the GNU General Public License version 2 as
  *  published by the Free Software Foundation.
  */
+#include <asm/unified.h>
 
 #include <linux/linkage.h>
 #include <asm/assembler.h>
@@ -33,8 +34,18 @@
  *	Number of bytes NOT copied.
  */
 
+#ifndef CONFIG_THUMB2_KERNEL
+#define LDR1W_SHIFT	0
+#else
+#define LDR1W_SHIFT	1
+#endif
+#define STR1W_SHIFT	0
+
 	.macro ldr1w ptr reg abort
-100:	ldrt \reg, [\ptr], #4
+100:
+ ARM(	ldrt \reg, [\ptr], #4		)
+ THUMB(	ldrt \reg, [\ptr]		)
+ THUMB(	add.w \ptr, \ptr, #4		)
 	.section __ex_table, "a"
 	.long 100b, \abort
 	.previous
@@ -53,14 +64,20 @@
 	.endm
 
 	.macro ldr1b ptr reg cond=al abort
-100:	ldr\cond\()bt \reg, [\ptr], #1
+	.ifnc \cond,al
+	itt \cond
+	.endif
+100:
+ ARM(	ldr\cond\()bt \reg, [\ptr], #1	)
+ THUMB(	ldr\cond\()bt \reg, [\ptr]	)
+ THUMB(	add\cond \ptr, \ptr, #1		)
 	.section __ex_table, "a"
 	.long 100b, \abort
 	.previous
 	.endm
 
 	.macro str1w ptr reg abort
-	str \reg, [\ptr], #4
+	W(str) \reg, [\ptr], #4
 	.endm
 
 	.macro str8w ptr reg1 reg2 reg3 reg4 reg5 reg6 reg7 reg8 abort
@@ -68,6 +85,9 @@
 	.endm
 
 	.macro str1b ptr reg cond=al abort
+	.ifnc \cond,al
+	it \cond
+	.endif
 	str\cond\()b \reg, [\ptr], #1
 	.endm
 
@@ -87,6 +107,8 @@ ENTRY(__copy_from_user)
 
 #include "copy_template.S"
 
+ENDPROC(__copy_from_user)
+
 	.section .fixup,"ax"
 	.align 0
 	copy_abort_preamble
diff --git a/arch/arm/lib/copy_page.S b/arch/arm/lib/copy_page.S
index 666c99c..1f2e27c 100644
--- a/arch/arm/lib/copy_page.S
+++ b/arch/arm/lib/copy_page.S
@@ -9,6 +9,8 @@
  *
  *  ASM optimised string functions
  */
+#include <asm/unified.h>
+
 #include <linux/linkage.h>
 #include <asm/assembler.h>
 #include <asm/asm-offsets.h>
@@ -39,8 +41,11 @@ ENTRY(copy_page)
 		ldmia	r1!, {r3, r4, ip, lr}		@	4
 		subs	r2, r2, #1			@	1
 		stmia	r0!, {r3, r4, ip, lr}		@	4
+		itt	gt
 		ldmgtia	r1!, {r3, r4, ip, lr}		@	4
 		bgt	1b				@	1
+	PLD(	itt	eq			)
 	PLD(	ldmeqia r1!, {r3, r4, ip, lr}	)
 	PLD(	beq	2b			)
 		ldmfd	sp!, {r4, pc}			@	3
+ENDPROC(copy_page)
diff --git a/arch/arm/lib/copy_template.S b/arch/arm/lib/copy_template.S
index cab355c..fb4451d 100644
--- a/arch/arm/lib/copy_template.S
+++ b/arch/arm/lib/copy_template.S
@@ -65,6 +65,13 @@
  *
  *	Restore registers with the values previously saved with the
  *	'preserv' macro. Called upon code termination.
+ *
+ * LDR1W_SHIFT
+ * STR1W_SHIFT
+ *
+ *	Correction to be applied to the "ip" register when branching into
+ *	the ldr1w or str1w instructions (some of these macros may expand to
+ *	than one 32bit instruction in Thumb-2)
  */
 
 
@@ -107,9 +114,16 @@
 
 5:		ands	ip, r2, #28
 		rsb	ip, ip, #32
+#if LDR1W_SHIFT > 0
+		lsl	ip, ip, #LDR1W_SHIFT
+#endif
+		it	ne
 		addne	pc, pc, ip		@ C is always clear here
 		b	7f
-6:		nop
+6:
+		.rept	(1 << LDR1W_SHIFT)
+		W(nop)
+		.endr
 		ldr1w	r1, r3, abort=20f
 		ldr1w	r1, r4, abort=20f
 		ldr1w	r1, r5, abort=20f
@@ -118,9 +132,16 @@
 		ldr1w	r1, r8, abort=20f
 		ldr1w	r1, lr, abort=20f
 
+#if LDR1W_SHIFT < STR1W_SHIFT
+		lsl	ip, ip, #STR1W_SHIFT - LDR1W_SHIFT
+#elif LDR1W_SHIFT > STR1W_SHIFT
+		lsr	ip, ip, #LDR1W_SHIFT - STR1W_SHIFT
+#endif
 		add	pc, pc, ip
 		nop
-		nop
+		.rept	(1 << STR1W_SHIFT)
+		W(nop)
+		.endr
 		str1w	r0, r3, abort=20f
 		str1w	r0, r4, abort=20f
 		str1w	r0, r5, abort=20f
diff --git a/arch/arm/lib/copy_to_user.S b/arch/arm/lib/copy_to_user.S
index 5224d94..b4454fc 100644
--- a/arch/arm/lib/copy_to_user.S
+++ b/arch/arm/lib/copy_to_user.S
@@ -9,6 +9,7 @@
  *  it under the terms of the GNU General Public License version 2 as
  *  published by the Free Software Foundation.
  */
+#include <asm/unified.h>
 
 #include <linux/linkage.h>
 #include <asm/assembler.h>
@@ -33,8 +34,15 @@
  *	Number of bytes NOT copied.
  */
 
+#define LDR1W_SHIFT	0
+#ifndef CONFIG_THUMB2_KERNEL
+#define STR1W_SHIFT	0
+#else
+#define STR1W_SHIFT	1
+#endif
+
 	.macro ldr1w ptr reg abort
-	ldr \reg, [\ptr], #4
+	W(ldr) \reg, [\ptr], #4
 	.endm
 
 	.macro ldr4w ptr reg1 reg2 reg3 reg4 abort
@@ -46,11 +54,17 @@
 	.endm
 
 	.macro ldr1b ptr reg cond=al abort
+	.ifnc \cond,al
+	it \cond
+	.endif
 	ldr\cond\()b \reg, [\ptr], #1
 	.endm
 
 	.macro str1w ptr reg abort
-100:	strt \reg, [\ptr], #4
+100:
+ ARM(	strt \reg, [\ptr], #4		)
+ THUMB(	strt \reg, [\ptr]		)
+ THUMB(	add.w \ptr, \ptr, #4		)
 	.section __ex_table, "a"
 	.long 100b, \abort
 	.previous
@@ -68,7 +82,13 @@
 	.endm
 
 	.macro str1b ptr reg cond=al abort
-100:	str\cond\()bt \reg, [\ptr], #1
+	.ifnc \cond,al
+	itt \cond
+	.endif
+100:
+ ARM(	str\cond\()bt \reg, [\ptr], #1	)
+ THUMB(	str\cond\()bt \reg, [\ptr]	)
+ THUMB(	add\cond \ptr, \ptr, #1		)
 	.section __ex_table, "a"
 	.long 100b, \abort
 	.previous
@@ -90,6 +110,8 @@ ENTRY(__copy_to_user)
 
 #include "copy_template.S"
 
+ENDPROC(__copy_to_user)
+
 	.section .fixup,"ax"
 	.align 0
 	copy_abort_preamble
diff --git a/arch/arm/lib/csumipv6.S b/arch/arm/lib/csumipv6.S
index 9621469..47d8f17 100644
--- a/arch/arm/lib/csumipv6.S
+++ b/arch/arm/lib/csumipv6.S
@@ -7,6 +7,8 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
+#include <asm/unified.h>
+
 #include <linux/linkage.h>
 #include <asm/assembler.h>
 
@@ -29,4 +31,5 @@ ENTRY(__csum_ipv6_magic)
 		adcs	r0, r0, r2
 		adcs	r0, r0, #0
 		ldmfd	sp!, {pc}
+ENDPROC(__csum_ipv6_magic)
 
diff --git a/arch/arm/lib/csumpartial.S b/arch/arm/lib/csumpartial.S
index a78dae5..e9df2c7 100644
--- a/arch/arm/lib/csumpartial.S
+++ b/arch/arm/lib/csumpartial.S
@@ -7,6 +7,8 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
+#include <asm/unified.h>
+
 #include <linux/linkage.h>
 #include <asm/assembler.h>
 
@@ -39,6 +41,7 @@ td3	.req	lr
 
 		/* we must have at least one byte. */
 		tst	buf, #1			@ odd address?
+		itttt	ne
 		movne	sum, sum, ror #8
 		ldrneb	td0, [buf], #1
 		subne	len, len, #1
@@ -68,25 +71,30 @@ td3	.req	lr
 		bne	.Lless8_wordlp
 
 .Lless8_byte:	tst	len, #1			@ odd number of bytes
+		itt	ne
 		ldrneb	td0, [buf], #1		@ include last byte
 		adcnes	sum, sum, td0, put_byte_0	@ update checksum
 
 .Ldone:		adc	r0, sum, #0		@ collect up the last carry
 		ldr	td0, [sp], #4
 		tst	td0, #1			@ check buffer alignment
+		it	ne
 		movne	r0, r0, ror #8		@ rotate checksum by 8 bits
 		ldr	pc, [sp], #4		@ return
 
 .Lnot_aligned:	tst	buf, #1			@ odd address
+		ittt	ne
 		ldrneb	td0, [buf], #1		@ make even
 		subne	len, len, #1
 		adcnes	sum, sum, td0, put_byte_1	@ update checksum
 
 		tst	buf, #2			@ 32-bit aligned?
 #if __LINUX_ARM_ARCH__ >= 4
+		itt	ne
 		ldrneh	td0, [buf], #2		@ make 32-bit aligned
 		subne	len, len, #2
 #else
+		itttt	ne
 		ldrneb	td0, [buf], #1
 		ldrneb	ip, [buf], #1
 		subne	len, len, #2
@@ -96,6 +104,7 @@ td3	.req	lr
 		orrne	td0, ip, td0, lsl #8
 #endif
 #endif
+		it	ne
 		adcnes	sum, sum, td0		@ update checksum
 		mov	pc, lr
 
@@ -105,10 +114,12 @@ ENTRY(csum_partial)
 		blo	.Lless8			@ 8 bytes to copy.
 
 		tst	buf, #1
+		it	ne
 		movne	sum, sum, ror #8
 
 		adds	sum, sum, #0		@ C = 0
 		tst	buf, #3			@ Test destination alignment
+		it	ne
 		blne	.Lnot_aligned		@ align destination, return here
 
 1:		bics	ip, len, #31
@@ -139,3 +150,4 @@ ENTRY(csum_partial)
 		tst	len, #0x1c
 		bne	4b
 		b	.Lless4
+ENDPROC(csum_partial)
diff --git a/arch/arm/lib/csumpartialcopy.S b/arch/arm/lib/csumpartialcopy.S
index 21effe0..ab07d80 100644
--- a/arch/arm/lib/csumpartialcopy.S
+++ b/arch/arm/lib/csumpartialcopy.S
@@ -7,6 +7,8 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
+#include <asm/unified.h>
+
 #include <linux/linkage.h>
 #include <asm/assembler.h>
 
@@ -18,13 +20,15 @@
  */
 
 		.macro	save_regs
-		mov	ip, sp
-		stmfd	sp!, {r1, r4 - r8, fp, ip, lr, pc}
-		sub	fp, ip, #4
+ ARM(		mov	ip, sp					)
+ ARM(		stmfd	sp!, {r1, r4 - r8, fp, ip, lr, pc}	)
+ ARM(		sub	fp, ip, #4				)
+ THUMB(		stmfd	sp!, {r1, r4 - r8, lr}			)
 		.endm
 
 		.macro	load_regs
-		ldmfd	sp, {r1, r4 - r8, fp, sp, pc}
+ ARM(		ldmfd	sp, {r1, r4 - r8, fp, sp, pc}		)
+ THUMB(		ldmfd	sp!, {r1, r4 - r8, pc}			)
 		.endm
 
 		.macro	load1b, reg1
@@ -50,5 +54,6 @@
 		.endm
 
 #define FN_ENTRY	ENTRY(csum_partial_copy_nocheck)
+#define FN_EXIT		ENDPROC(csum_partial_copy_nocheck)
 
 #include "csumpartialcopygeneric.S"
diff --git a/arch/arm/lib/csumpartialcopygeneric.S b/arch/arm/lib/csumpartialcopygeneric.S
index c50e8f5..ed9173d 100644
--- a/arch/arm/lib/csumpartialcopygeneric.S
+++ b/arch/arm/lib/csumpartialcopygeneric.S
@@ -16,6 +16,8 @@
  *
  * Note that 'tst' and 'teq' preserve the carry flag.
  */
+#include <asm/unified.h>
+
 
 src	.req	r0
 dst	.req	r1
@@ -40,6 +42,7 @@ sum	.req	r3
 		adcs	sum, sum, ip, put_byte_1	@ update checksum
 		strb	ip, [dst], #1
 		tst	dst, #2
+		it	eq
 		moveq	pc, lr			@ dst is now 32bit aligned
 
 .Ldst_16bit:	load2b	r8, ip
@@ -94,6 +97,7 @@ FN_ENTRY
 
 		adds	sum, sum, #0		@ C = 0
 		tst	dst, #3			@ Test destination alignment
+		it	ne
 		blne	.Ldst_unaligned		@ align destination, return here
 
 		/*
@@ -147,6 +151,7 @@ FN_ENTRY
 		strb	r5, [dst], #1
 		mov	r5, r4, get_byte_2
 .Lexit:		tst	len, #1
+		ittt	ne
 		strneb	r5, [dst], #1
 		andne	r5, r5, #255
 		adcnes	sum, sum, r5, put_byte_0
@@ -160,6 +165,7 @@ FN_ENTRY
 .Ldone:		adc	r0, sum, #0
 		ldr	sum, [sp, #0]		@ dst
 		tst	sum, #1
+		it	ne
 		movne	r0, r0, ror #8
 		load_regs
 
@@ -329,3 +335,4 @@ FN_ENTRY
 		adcs	sum, sum, r4, push #24
 		mov	r5, r4, get_byte_1
 		b	.Lexit
+FN_EXIT
diff --git a/arch/arm/lib/csumpartialcopyuser.S b/arch/arm/lib/csumpartialcopyuser.S
index c3b93e2..a197e72 100644
--- a/arch/arm/lib/csumpartialcopyuser.S
+++ b/arch/arm/lib/csumpartialcopyuser.S
@@ -10,6 +10,8 @@
  * 27/03/03 Ian Molton Clean up CONFIG_CPU
  *
  */
+#include <asm/unified.h>
+
 #include <linux/linkage.h>
 #include <asm/assembler.h>
 #include <asm/errno.h>
@@ -18,17 +20,22 @@
 		.text
 
 		.macro	save_regs
-		mov	ip, sp
-		stmfd	sp!, {r1 - r2, r4 - r8, fp, ip, lr, pc}
-		sub	fp, ip, #4
+ ARM(		mov	ip, sp					)
+ ARM(		stmfd	sp!, {r1 - r2, r4 - r8, fp, ip, lr, pc}	)
+ ARM(		sub	fp, ip, #4				)
+ THUMB(		stmfd	sp!, {r1, r2, r4 - r8, lr}		)
 		.endm
 
 		.macro	load_regs
-		ldmfd	sp, {r1, r2, r4-r8, fp, sp, pc}
+ ARM(		ldmfd	sp, {r1, r2, r4-r8, fp, sp, pc}		)
+ THUMB(		ldmfd	sp!, {r1, r2, r4 - r8, pc}		)
 		.endm
 
 		.macro	load1b,	reg1
-9999:		ldrbt	\reg1, [r0], $1
+9999:
+ ARM(		ldrbt	\reg1, [r0], $1	)
+ THUMB(		ldrbt	\reg1, [r0]	)
+ THUMB(		add	\reg1, $1	)
 		.section __ex_table, "a"
 		.align	3
 		.long	9999b, 6001f
@@ -36,8 +43,14 @@
 		.endm
 
 		.macro	load2b, reg1, reg2
-9999:		ldrbt	\reg1, [r0], $1
-9998:		ldrbt	\reg2, [r0], $1
+9999:
+ ARM(		ldrbt	\reg1, [r0], $1	)
+ THUMB(		ldrbt	\reg1, [r0]	)
+ THUMB(		add	\reg1, $1	)
+9998:
+ ARM(		ldrbt	\reg2, [r0], $1	)
+ THUMB(		ldrbt	\reg2, [r0]	)
+ THUMB(		add	\reg2, $1	)
 		.section __ex_table, "a"
 		.long	9999b, 6001f
 		.long	9998b, 6001f
@@ -45,7 +58,10 @@
 		.endm
 
 		.macro	load1l, reg1
-9999:		ldrt	\reg1, [r0], $4
+9999:
+ ARM(		ldrt	\reg1, [r0], $4	)
+ THUMB(		ldrt	\reg1, [r0]	)
+ THUMB(		add	\reg1, $4	)
 		.section __ex_table, "a"
 		.align	3
 		.long	9999b, 6001f
@@ -53,8 +69,14 @@
 		.endm
 
 		.macro	load2l, reg1, reg2
-9999:		ldrt	\reg1, [r0], $4
-9998:		ldrt	\reg2, [r0], $4
+9999:
+ ARM(		ldrt	\reg1, [r0], $4	)
+ THUMB(		ldrt	\reg1, [r0]	)
+ THUMB(		add	\reg1, $4	)
+9998:
+ ARM(		ldrt	\reg2, [r0], $4	)
+ THUMB(		ldrt	\reg2, [r0]	)
+ THUMB(		add	\reg2, $4	)
 		.section __ex_table, "a"
 		.long	9999b, 6001f
 		.long	9998b, 6001f
@@ -62,10 +84,22 @@
 		.endm
 
 		.macro	load4l, reg1, reg2, reg3, reg4
-9999:		ldrt	\reg1, [r0], $4
-9998:		ldrt	\reg2, [r0], $4
-9997:		ldrt	\reg3, [r0], $4
-9996:		ldrt	\reg4, [r0], $4
+9999:
+ ARM(		ldrt	\reg1, [r0], $4	)
+ THUMB(		ldrt	\reg1, [r0]	)
+ THUMB(		add	\reg1, $4	)
+9998:
+ ARM(		ldrt	\reg2, [r0], $4	)
+ THUMB(		ldrt	\reg2, [r0]	)
+ THUMB(		add	\reg2, $4	)
+9997:
+ ARM(		ldrt	\reg3, [r0], $4	)
+ THUMB(		ldrt	\reg3, [r0]	)
+ THUMB(		add	\reg3, $4	)
+9996:
+ ARM(		ldrt	\reg4, [r0], $4	)
+ THUMB(		ldrt	\reg4, [r0]	)
+ THUMB(		add	\reg4, $4	)
 		.section __ex_table, "a"
 		.long	9999b, 6001f
 		.long	9998b, 6001f
@@ -82,6 +116,7 @@
  */
 
 #define FN_ENTRY	ENTRY(csum_partial_copy_from_user)
+#define FN_EXIT		ENDPROC(csum_partial_copy_from_user)
 
 #include "csumpartialcopygeneric.S"
 
@@ -100,6 +135,7 @@
 		add	r2, r2, r1
 		mov	r0, #0			@ zero the buffer
 6002:		teq	r2, r1
+		it 	ne
 		strneb	r0, [r1], #1
 		bne	6002b
 		load_regs
diff --git a/arch/arm/lib/delay.S b/arch/arm/lib/delay.S
index 930a702..3c2c57d 100644
--- a/arch/arm/lib/delay.S
+++ b/arch/arm/lib/delay.S
@@ -7,6 +7,8 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
+#include <asm/unified.h>
+
 #include <linux/linkage.h>
 #include <asm/assembler.h>
 #include <asm/param.h>
@@ -31,7 +33,10 @@ ENTRY(__const_udelay)				@ 0 <= r0 <= 0x7fffff06
 		mov	r2, r2, lsr #10		@ max = 0x00007fff
 		mul	r0, r2, r0		@ max = 2^32-1
 		movs	r0, r0, lsr #6
+		it	eq
 		moveq	pc, lr
+ENDPROC(__udelay)
+ENDPROC(__const_udelay)				@ 0 <= r0 <= 0x7fffff06
 
 /*
  * loops = r0 * HZ * loops_per_jiffy / 1000000
@@ -58,5 +63,7 @@ ENTRY(__delay)
 		movls	pc, lr
 		subs	r0, r0, #1
 #endif
+		it	hi
 		bhi	__delay
 		mov	pc, lr
+ENDPROC(__delay)
diff --git a/arch/arm/lib/div64.S b/arch/arm/lib/div64.S
index 58eef66..b1fa394 100644
--- a/arch/arm/lib/div64.S
+++ b/arch/arm/lib/div64.S
@@ -11,6 +11,7 @@
  *  it under the terms of the GNU General Public License version 2 as
  *  published by the Free Software Foundation.
  */
+#include <asm/unified.h>
 
 #include <linux/linkage.h>
 
@@ -84,8 +85,10 @@ ENTRY(__do_div64)
 	@ The division loop for needed upper bit positions.
  	@ Break out early if dividend reaches 0.
 2:	cmp	xh, yl
+	itt	cs
 	orrcs	yh, yh, ip
 	subcss	xh, xh, yl
+	it	ne
 	movnes	ip, ip, lsr #1
 	mov	yl, yl, lsr #1
 	bne	2b
@@ -93,7 +96,9 @@ ENTRY(__do_div64)
 	@ See if we need to handle lower 32-bit result.
 3:	cmp	xh, #0
 	mov	yl, #0
+	it	eq
 	cmpeq	xl, r4
+	itt	lo
 	movlo	xh, xl
 	movlo	pc, lr
 
@@ -104,7 +109,9 @@ ENTRY(__do_div64)
 4:	movs	xl, xl, lsl #1
 	adcs	xh, xh, xh
 	beq	6f
+	it	cc
 	cmpcc	xh, r4
+	itt	cs
 5:	orrcs	yl, yl, ip
 	subcs	xh, xh, r4
 	movs	ip, ip, lsr #1
@@ -116,6 +123,7 @@ ENTRY(__do_div64)
 	@ Otherwise, if lower part is also null then we are done.
 6:	bcs	5b
 	cmp	xl, #0
+	it	eq
 	moveq	pc, lr
 
 	@ We still have remainer bits in the low part.  Bring them up.
@@ -177,13 +185,16 @@ ENTRY(__do_div64)
 	mov	yh, xh, lsr ip
 	mov	yl, xl, lsr ip
 	rsb	ip, ip, #32
-	orr	yl, yl, xh, lsl ip
+ ARM(	orr	yl, yl, xh, lsl ip	)
+ THUMB(	lsl	xh, xh, ip		)
+ THUMB(	orr	yl, yl, xh		)
 	mov	xh, xl, lsl ip
 	mov	xh, xh, lsr ip
 	mov	pc, lr
 
 	@ eq -> division by 1: obvious enough...
-9:	moveq	yl, xl
+9:	itttt	eq
+	moveq	yl, xl
 	moveq	yh, xh
 	moveq	xh, #0
 	moveq	pc, lr
@@ -198,3 +209,4 @@ ENTRY(__do_div64)
 	mov	xh, #0
 	ldr	pc, [sp], #8
 
+ENDPROC(__do_div64)
diff --git a/arch/arm/lib/findbit.S b/arch/arm/lib/findbit.S
index a5ca024..543bf27 100644
--- a/arch/arm/lib/findbit.S
+++ b/arch/arm/lib/findbit.S
@@ -13,6 +13,8 @@
  *   also call with zero size.
  * Reworked by rmk.
  */
+#include <asm/unified.h>
+
 #include <linux/linkage.h>
 #include <asm/assembler.h>
                 .text
@@ -25,7 +27,10 @@ ENTRY(_find_first_zero_bit_le)
 		teq	r1, #0	
 		beq	3f
 		mov	r2, #0
-1:		ldrb	r3, [r0, r2, lsr #3]
+1:
+ ARM(		ldrb	r3, [r0, r2, lsr #3]	)
+ THUMB(		lsr	r3, r2, #3		)
+ THUMB(		ldrb	r3, [r0, r3]		)
 		eors	r3, r3, #0xff		@ invert bits
 		bne	.L_found		@ any now set - found zero bit
 		add	r2, r2, #8		@ next bit pointer
@@ -33,6 +38,7 @@ ENTRY(_find_first_zero_bit_le)
 		blo	1b
 3:		mov	r0, r1			@ no free bits
 		mov	pc, lr
+ENDPROC(_find_first_zero_bit_le)
 
 /*
  * Purpose  : Find next 'zero' bit
@@ -43,13 +49,16 @@ ENTRY(_find_next_zero_bit_le)
 		beq	3b
 		ands	ip, r2, #7
 		beq	1b			@ If new byte, goto old routine
-		ldrb	r3, [r0, r2, lsr #3]
+ ARM(		ldrb	r3, [r0, r2, lsr #3]	)
+ THUMB(		lsr	r3, r2, #3		)
+ THUMB(		ldrb	r3, [r0, r3]		)
 		eor	r3, r3, #0xff		@ now looking for a 1 bit
 		movs	r3, r3, lsr ip		@ shift off unused bits
 		bne	.L_found
 		orr	r2, r2, #7		@ if zero, then no bits here
 		add	r2, r2, #1		@ align bit pointer
 		b	2b			@ loop for next bit
+ENDPROC(_find_next_zero_bit_le)
 
 /*
  * Purpose  : Find a 'one' bit
@@ -59,7 +68,10 @@ ENTRY(_find_first_bit_le)
 		teq	r1, #0	
 		beq	3f
 		mov	r2, #0
-1:		ldrb	r3, [r0, r2, lsr #3]
+1:
+ ARM(		ldrb	r3, [r0, r2, lsr #3]	)
+ THUMB(		lsr	r3, r2, #3		)
+ THUMB(		ldrb	r3, [r0, r3]		)
 		movs	r3, r3
 		bne	.L_found		@ any now set - found zero bit
 		add	r2, r2, #8		@ next bit pointer
@@ -67,6 +79,7 @@ ENTRY(_find_first_bit_le)
 		blo	1b
 3:		mov	r0, r1			@ no free bits
 		mov	pc, lr
+ENDPROC(_find_first_bit_le)
 
 /*
  * Purpose  : Find next 'one' bit
@@ -77,12 +90,15 @@ ENTRY(_find_next_bit_le)
 		beq	3b
 		ands	ip, r2, #7
 		beq	1b			@ If new byte, goto old routine
-		ldrb	r3, [r0, r2, lsr #3]
+ ARM(		ldrb	r3, [r0, r2, lsr #3]	)
+ THUMB(		lsr	r3, r2, #3		)
+ THUMB(		ldrb	r3, [r0, r3]		)
 		movs	r3, r3, lsr ip		@ shift off unused bits
 		bne	.L_found
 		orr	r2, r2, #7		@ if zero, then no bits here
 		add	r2, r2, #1		@ align bit pointer
 		b	2b			@ loop for next bit
+ENDPROC(_find_next_bit_le)
 
 #ifdef __ARMEB__
 
@@ -91,7 +107,9 @@ ENTRY(_find_first_zero_bit_be)
 		beq	3f
 		mov	r2, #0
 1:		eor	r3, r2, #0x18		@ big endian byte ordering
-		ldrb	r3, [r0, r3, lsr #3]
+ ARM(		ldrb	r3, [r0, r3, lsr #3]	)
+ THUMB(		lsr	r3, #3			)
+ THUMB(		ldrb	r3, [r0, r3]		)
 		eors	r3, r3, #0xff		@ invert bits
 		bne	.L_found		@ any now set - found zero bit
 		add	r2, r2, #8		@ next bit pointer
@@ -99,6 +117,7 @@ ENTRY(_find_first_zero_bit_be)
 		blo	1b
 3:		mov	r0, r1			@ no free bits
 		mov	pc, lr
+ENDPROC(_find_first_zero_bit_be)
 
 ENTRY(_find_next_zero_bit_be)
 		teq	r1, #0
@@ -106,20 +125,25 @@ ENTRY(_find_next_zero_bit_be)
 		ands	ip, r2, #7
 		beq	1b			@ If new byte, goto old routine
 		eor	r3, r2, #0x18		@ big endian byte ordering
-		ldrb	r3, [r0, r3, lsr #3]
+ ARM(		ldrb	r3, [r0, r3, lsr #3]	)
+ THUMB(		lsr	r3, #3			)
+ THUMB(		ldrb	r3, [r0, r3]		)
 		eor	r3, r3, #0xff		@ now looking for a 1 bit
 		movs	r3, r3, lsr ip		@ shift off unused bits
 		bne	.L_found
 		orr	r2, r2, #7		@ if zero, then no bits here
 		add	r2, r2, #1		@ align bit pointer
 		b	2b			@ loop for next bit
+ENDPROC(_find_next_zero_bit_be)
 
 ENTRY(_find_first_bit_be)
 		teq	r1, #0
 		beq	3f
 		mov	r2, #0
 1:		eor	r3, r2, #0x18		@ big endian byte ordering
-		ldrb	r3, [r0, r3, lsr #3]
+ ARM(		ldrb	r3, [r0, r3, lsr #3]	)
+ THUMB(		lsr	r3, #3			)
+ THUMB(		ldrb	r3, [r0, r3]		)
 		movs	r3, r3
 		bne	.L_found		@ any now set - found zero bit
 		add	r2, r2, #8		@ next bit pointer
@@ -127,6 +151,7 @@ ENTRY(_find_first_bit_be)
 		blo	1b
 3:		mov	r0, r1			@ no free bits
 		mov	pc, lr
+ENDPROC(_find_first_bit_be)
 
 ENTRY(_find_next_bit_be)
 		teq	r1, #0
@@ -134,12 +159,15 @@ ENTRY(_find_next_bit_be)
 		ands	ip, r2, #7
 		beq	1b			@ If new byte, goto old routine
 		eor	r3, r2, #0x18		@ big endian byte ordering
-		ldrb	r3, [r0, r3, lsr #3]
+ ARM(		ldrb	r3, [r0, r3, lsr #3]	)
+ THUMB(		lsr	r3, #3			)
+ THUMB(		ldrb	r3, [r0, r3]		)
 		movs	r3, r3, lsr ip		@ shift off unused bits
 		bne	.L_found
 		orr	r2, r2, #7		@ if zero, then no bits here
 		add	r2, r2, #1		@ align bit pointer
 		b	2b			@ loop for next bit
+ENDPROC(_find_next_bit_be)
 
 #endif
 
diff --git a/arch/arm/lib/getuser.S b/arch/arm/lib/getuser.S
index 1dd8ea4..658913e 100644
--- a/arch/arm/lib/getuser.S
+++ b/arch/arm/lib/getuser.S
@@ -26,17 +26,22 @@
  * Note that ADDR_LIMIT is either 0 or 0xc0000000.
  * Note also that it is intended that __get_user_bad is not global.
  */
+#include <asm/unified.h>
+
+#include <linux/linkage.h>
 #include <asm/errno.h>
 
-	.global	__get_user_1
-__get_user_1:
+ENTRY(__get_user_1)
 1:	ldrbt	r2, [r0]
 	mov	r0, #0
 	mov	pc, lr
+ENDPROC(__get_user_1)
 
-	.global	__get_user_2
-__get_user_2:
-2:	ldrbt	r2, [r0], #1
+ENTRY(__get_user_2)
+2:
+ ARM(	ldrbt	r2, [r0], #1	)
+ THUMB(	ldrbt	r2, [r0]	)
+ THUMB(	add	r0, #1		)
 3:	ldrbt	r3, [r0]
 #ifndef __ARMEB__
 	orr	r2, r2, r3, lsl #8
@@ -45,17 +50,19 @@ __get_user_2:
 #endif
 	mov	r0, #0
 	mov	pc, lr
+ENDPROC(__get_user_2)
 
-	.global	__get_user_4
-__get_user_4:
+ENTRY(__get_user_4)
 4:	ldrt	r2, [r0]
 	mov	r0, #0
 	mov	pc, lr
+ENDPROC(__get_user_4)
 
 __get_user_bad:
 	mov	r2, #0
 	mov	r0, #-EFAULT
 	mov	pc, lr
+ENDPROC(__get_user_bad)
 
 .section __ex_table, "a"
 	.long	1b, __get_user_bad
diff --git a/arch/arm/lib/io-readsb.S b/arch/arm/lib/io-readsb.S
index fb966ad..082cdcb 100644
--- a/arch/arm/lib/io-readsb.S
+++ b/arch/arm/lib/io-readsb.S
@@ -7,17 +7,22 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
+#include <asm/unified.h>
+
 #include <linux/linkage.h>
 #include <asm/assembler.h>
 
 .Linsb_align:	rsb	ip, ip, #4
 		cmp	ip, r2
+		it	gt
 		movgt	ip, r2
 		cmp	ip, #2
 		ldrb	r3, [r0]
 		strb	r3, [r1], #1
+		itt	ge
 		ldrgeb	r3, [r0]
 		strgeb	r3, [r1], #1
+		itt	gt
 		ldrgtb	r3, [r0]
 		strgtb	r3, [r1], #1
 		subs	r2, r2, ip
@@ -25,6 +30,7 @@
 
 ENTRY(__raw_readsb)
 		teq	r2, #0		@ do we have to check for the zero len?
+		it	eq
 		moveq	pc, lr
 		ands	ip, r1, #3
 		bne	.Linsb_align
@@ -72,6 +78,7 @@ ENTRY(__raw_readsb)
 		bpl	.Linsb_16_lp
 
 		tst	r2, #15
+		it	eq
 		ldmeqfd	sp!, {r4 - r6, pc}
 
 .Linsb_no_16:	tst	r2, #8
@@ -109,14 +116,18 @@ ENTRY(__raw_readsb)
 		str	r3, [r1], #4
 
 .Linsb_no_4:	ands	r2, r2, #3
+		it	eq
 		ldmeqfd	sp!, {r4 - r6, pc}
 
 		cmp	r2, #2
 		ldrb	r3, [r0]
 		strb	r3, [r1], #1
+		itt	ge
 		ldrgeb	r3, [r0]
 		strgeb	r3, [r1], #1
+		itt	gt
 		ldrgtb	r3, [r0]
 		strgtb	r3, [r1]
 
 		ldmfd	sp!, {r4 - r6, pc}
+ENDPROC(__raw_readsb)
diff --git a/arch/arm/lib/io-readsl.S b/arch/arm/lib/io-readsl.S
index 75a9121..b963018 100644
--- a/arch/arm/lib/io-readsl.S
+++ b/arch/arm/lib/io-readsl.S
@@ -7,11 +7,14 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
+#include <asm/unified.h>
+
 #include <linux/linkage.h>
 #include <asm/assembler.h>
 
 ENTRY(__raw_readsl)
 		teq	r2, #0		@ do we have to check for the zero len?
+		it	eq
 		moveq	pc, lr
 		ands	ip, r1, #3
 		bne	3f
@@ -28,9 +31,11 @@ ENTRY(__raw_readsl)
 		bpl	1b
 		ldmfd	sp!, {r4, lr}
 2:		movs	r2, r2, lsl #31
+		ittt	cs
 		ldrcs	r3, [r0, #0]
 		ldrcs	ip, [r0, #0]
 		stmcsia	r1!, {r3, ip}
+		itt	ne
 		ldrne	r3, [r0, #0]
 		strne	r3, [r1, #0]
 		mov	pc, lr
@@ -48,6 +53,7 @@ ENTRY(__raw_readsl)
 
 4:		subs	r2, r2, #1
 		mov	ip, r3, pull #24
+		itttt	ne
 		ldrne	r3, [r0]
 		orrne	ip, ip, r3, push #8
 		strne	ip, [r1], #4
@@ -56,6 +62,7 @@ ENTRY(__raw_readsl)
 
 5:		subs	r2, r2, #1
 		mov	ip, r3, pull #16
+		itttt	ne
 		ldrne	r3, [r0]
 		orrne	ip, ip, r3, push #16
 		strne	ip, [r1], #4
@@ -64,6 +71,7 @@ ENTRY(__raw_readsl)
 
 6:		subs	r2, r2, #1
 		mov	ip, r3, pull #8
+		itttt	ne
 		ldrne	r3, [r0]
 		orrne	ip, ip, r3, push #24
 		strne	ip, [r1], #4
@@ -76,3 +84,4 @@ ENTRY(__raw_readsl)
 8:		mov	r3, ip, get_byte_0
 		strb	r3, [r1, #0]
 		mov	pc, lr
+ENDPROC(__raw_readsl)
diff --git a/arch/arm/lib/io-readsw-armv4.S b/arch/arm/lib/io-readsw-armv4.S
index 4db1c5f..693305e 100644
--- a/arch/arm/lib/io-readsw-armv4.S
+++ b/arch/arm/lib/io-readsw-armv4.S
@@ -7,6 +7,8 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
+#include <asm/unified.h>
+
 #include <linux/linkage.h>
 #include <asm/assembler.h>
 
@@ -26,6 +28,7 @@
 
 ENTRY(__raw_readsw)
 		teq	r2, #0
+		it	eq
 		moveq	pc, lr
 		tst	r1, #3
 		bne	.Linsw_align
@@ -76,7 +79,8 @@ ENTRY(__raw_readsw)
 		pack	r3, r3, ip
 		str	r3, [r1], #4
 
-.Lno_insw_2:	ldrneh	r3, [r0]
+.Lno_insw_2:	itt	ne
+		ldrneh	r3, [r0]
 		strneh	r3, [r1]
 
 		ldmfd	sp!, {r4, r5, pc}
@@ -94,6 +98,7 @@ ENTRY(__raw_readsw)
 #endif
 
 .Linsw_noalign:	stmfd	sp!, {r4, lr}
+		it	cc
 		ldrccb	ip, [r1, #-1]!
 		bcc	1f
 
@@ -121,6 +126,7 @@ ENTRY(__raw_readsw)
 
 3:		tst	r2, #1
 		strb	ip, [r1], #1
+		itttt	ne
 		ldrneh	ip, [r0]
    _BE_ONLY_(	movne	ip, ip, ror #8		)
 		strneb	ip, [r1], #1
@@ -128,3 +134,4 @@ ENTRY(__raw_readsw)
    _BE_ONLY_(	movne	ip, ip, lsr #24		)
 		strneb	ip, [r1]
 		ldmfd	sp!, {r4, pc}
+ENDPROC(__raw_readsw)
diff --git a/arch/arm/lib/io-writesb.S b/arch/arm/lib/io-writesb.S
index 7eba2b6..7d87383 100644
--- a/arch/arm/lib/io-writesb.S
+++ b/arch/arm/lib/io-writesb.S
@@ -7,6 +7,8 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
+#include <asm/unified.h>
+
 #include <linux/linkage.h>
 #include <asm/assembler.h>
 
@@ -32,12 +34,15 @@
 
 .Loutsb_align:	rsb	ip, ip, #4
 		cmp	ip, r2
+		it	gt
 		movgt	ip, r2
 		cmp	ip, #2
 		ldrb	r3, [r1], #1
 		strb	r3, [r0]
+		itt	ge
 		ldrgeb	r3, [r1], #1
 		strgeb	r3, [r0]
+		itt	gt
 		ldrgtb	r3, [r1], #1
 		strgtb	r3, [r0]
 		subs	r2, r2, ip
@@ -45,6 +50,7 @@
 
 ENTRY(__raw_writesb)
 		teq	r2, #0		@ do we have to check for the zero len?
+		it	eq
 		moveq	pc, lr
 		ands	ip, r1, #3
 		bne	.Loutsb_align
@@ -64,6 +70,7 @@ ENTRY(__raw_writesb)
 		bpl	.Loutsb_16_lp
 
 		tst	r2, #15
+		it	eq
 		ldmeqfd	sp!, {r4, r5, pc}
 
 .Loutsb_no_16:	tst	r2, #8
@@ -80,14 +87,18 @@ ENTRY(__raw_writesb)
 		outword	r3
 
 .Loutsb_no_4:	ands	r2, r2, #3
+		it	eq
 		ldmeqfd	sp!, {r4, r5, pc}
 
 		cmp	r2, #2
 		ldrb	r3, [r1], #1
 		strb	r3, [r0]
+		itt	ge
 		ldrgeb	r3, [r1], #1
 		strgeb	r3, [r0]
+		itt	gt
 		ldrgtb	r3, [r1]
 		strgtb	r3, [r0]
 
 		ldmfd	sp!, {r4, r5, pc}
+ENDPROC(__raw_writesb)
diff --git a/arch/arm/lib/io-writesl.S b/arch/arm/lib/io-writesl.S
index f8f14dd..112c855 100644
--- a/arch/arm/lib/io-writesl.S
+++ b/arch/arm/lib/io-writesl.S
@@ -7,11 +7,14 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
+#include <asm/unified.h>
+
 #include <linux/linkage.h>
 #include <asm/assembler.h>
 
 ENTRY(__raw_writesl)
 		teq	r2, #0		@ do we have to check for the zero len?
+		it	eq
 		moveq	pc, lr
 		ands	ip, r1, #3
 		bne	3f
@@ -28,10 +31,14 @@ ENTRY(__raw_writesl)
 		bpl	1b
 		ldmfd	sp!, {r4, lr}
 2:		movs	r2, r2, lsl #31
+		itt	cs
 		ldmcsia	r1!, {r3, ip}
 		strcs	r3, [r0, #0]
+		it	ne
 		ldrne	r3, [r1, #0]
+		it	cs
 		strcs	ip, [r0, #0]
+		it	ne
 		strne	r3, [r0, #0]
 		mov	pc, lr
 
@@ -64,3 +71,4 @@ ENTRY(__raw_writesl)
 		str	ip, [r0]
 		bne	6b
 		mov	pc, lr
+ENDPROC(__raw_writesl)
diff --git a/arch/arm/lib/io-writesw-armv4.S b/arch/arm/lib/io-writesw-armv4.S
index c8e85bd..58e5fd4 100644
--- a/arch/arm/lib/io-writesw-armv4.S
+++ b/arch/arm/lib/io-writesw-armv4.S
@@ -7,6 +7,8 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
+#include <asm/unified.h>
+
 #include <linux/linkage.h>
 #include <asm/assembler.h>
 
@@ -31,6 +33,7 @@
 
 ENTRY(__raw_writesw)
 		teq	r2, #0
+		it	eq
 		moveq	pc, lr
 		ands	r3, r1, #3
 		bne	.Loutsw_align
@@ -61,7 +64,8 @@ ENTRY(__raw_writesw)
 		ldr	r3, [r1], #4
 		outword	r3
 
-.Lno_outsw_2:	ldrneh	r3, [r1]
+.Lno_outsw_2:	itt	ne
+		ldrneh	r3, [r1]
 		strneh	r3, [r0]
 
 		ldmfd	sp!, {r4, r5, pc}
@@ -75,7 +79,11 @@ ENTRY(__raw_writesw)
 #endif
 
 .Loutsw_noalign:
-		ldr	r3, [r1, -r3]!
+ ARM(		ldr	r3, [r1, -r3]!	)
+ THUMB(		rsb	r3, r3, #0	)
+ THUMB(		ldr	r3, [r1, r3]	)
+ THUMB(		sub	r1, r3		)
+		it	cs
 		subcs	r2, r2, #1
 		bcs	2f
 		subs	r2, r2, #2
@@ -91,6 +99,8 @@ ENTRY(__raw_writesw)
 		bpl	1b
 
 		tst	r2, #1
-3:		movne	ip, r3, lsr #8
+3:		itt	ne
+		movne	ip, r3, lsr #8
 		strneh	ip, [r0]
 		mov	pc, lr
+ENDPROC(__raw_writesw)
diff --git a/arch/arm/lib/lib1funcs.S b/arch/arm/lib/lib1funcs.S
index 4e492f4..207f08c 100644
--- a/arch/arm/lib/lib1funcs.S
+++ b/arch/arm/lib/lib1funcs.S
@@ -31,6 +31,7 @@ You should have received a copy of the GNU General Public License
 along with this program; see the file COPYING.  If not, write to
 the Free Software Foundation, 59 Temple Place - Suite 330,
 Boston, MA 02111-1307, USA.  */
+#include <asm/unified.h>
 
 
 #include <linux/linkage.h>
@@ -56,6 +57,7 @@ Boston, MA 02111-1307, USA.  */
 	@ at the left end of each 4 bit nibbles in the division loop
 	@ to save one loop in most cases.
 	tst	\divisor, #0xe0000000
+	itte	eq
 	moveq	\divisor, \divisor, lsl #3
 	moveq	\curbit, #8
 	movne	\curbit, #1
@@ -65,6 +67,7 @@ Boston, MA 02111-1307, USA.  */
 	@ division loop.  Continue shifting until the divisor is 
 	@ larger than the dividend.
 1:	cmp	\divisor, #0x10000000
+	ittt	lo
 	cmplo	\divisor, \dividend
 	movlo	\divisor, \divisor, lsl #4
 	movlo	\curbit, \curbit, lsl #4
@@ -73,6 +76,7 @@ Boston, MA 02111-1307, USA.  */
 	@ For very big divisors, we must shift it a bit at a time, or
 	@ we will be in danger of overflowing.
 1:	cmp	\divisor, #0x80000000
+	ittt	lo
 	cmplo	\divisor, \dividend
 	movlo	\divisor, \divisor, lsl #1
 	movlo	\curbit, \curbit, lsl #1
@@ -84,19 +88,25 @@ Boston, MA 02111-1307, USA.  */
 
 	@ Division loop
 1:	cmp	\dividend, \divisor
+	itt	hs
 	subhs	\dividend, \dividend, \divisor
 	orrhs	\result,   \result,   \curbit
 	cmp	\dividend, \divisor,  lsr #1
+	itt	hs
 	subhs	\dividend, \dividend, \divisor, lsr #1
 	orrhs	\result,   \result,   \curbit,  lsr #1
 	cmp	\dividend, \divisor,  lsr #2
+	itt	hs
 	subhs	\dividend, \dividend, \divisor, lsr #2
 	orrhs	\result,   \result,   \curbit,  lsr #2
 	cmp	\dividend, \divisor,  lsr #3
+	itt	hs
 	subhs	\dividend, \dividend, \divisor, lsr #3
 	orrhs	\result,   \result,   \curbit,  lsr #3
 	cmp	\dividend, #0			@ Early termination?
+	it	ne
 	movnes	\curbit,   \curbit,  lsr #4	@ No, any more bits to do?
+	it	ne
 	movne	\divisor,  \divisor, lsr #4
 	bne	1b
 
@@ -113,19 +123,24 @@ Boston, MA 02111-1307, USA.  */
 #else
 
 	cmp	\divisor, #(1 << 16)
+	itt	hs
 	movhs	\divisor, \divisor, lsr #16
 	movhs	\order, #16
+	it	lo
 	movlo	\order, #0
 
 	cmp	\divisor, #(1 << 8)
+	itt	hs
 	movhs	\divisor, \divisor, lsr #8
 	addhs	\order, \order, #8
 
 	cmp	\divisor, #(1 << 4)
+	itt	hs
 	movhs	\divisor, \divisor, lsr #4
 	addhs	\order, \order, #4
 
 	cmp	\divisor, #(1 << 2)
+	ite	hi
 	addhi	\order, \order, #3
 	addls	\order, \order, \divisor, lsr #1
 
@@ -152,6 +167,7 @@ Boston, MA 02111-1307, USA.  */
 	@ division loop.  Continue shifting until the divisor is 
 	@ larger than the dividend.
 1:	cmp	\divisor, #0x10000000
+	ittt	lo
 	cmplo	\divisor, \dividend
 	movlo	\divisor, \divisor, lsl #4
 	addlo	\order, \order, #4
@@ -160,6 +176,7 @@ Boston, MA 02111-1307, USA.  */
 	@ For very big divisors, we must shift it a bit at a time, or
 	@ we will be in danger of overflowing.
 1:	cmp	\divisor, #0x80000000
+	ittt	lo
 	cmplo	\divisor, \dividend
 	movlo	\divisor, \divisor, lsl #1
 	addlo	\order, \order, #1
@@ -173,19 +190,25 @@ Boston, MA 02111-1307, USA.  */
 	blt	2f
 
 1:	cmp	\dividend, \divisor
+	it	hs
 	subhs	\dividend, \dividend, \divisor
 	cmp	\dividend, \divisor,  lsr #1
+	it	hs
 	subhs	\dividend, \dividend, \divisor, lsr #1
 	cmp	\dividend, \divisor,  lsr #2
+	it	hs
 	subhs	\dividend, \dividend, \divisor, lsr #2
 	cmp	\dividend, \divisor,  lsr #3
+	it	hs
 	subhs	\dividend, \dividend, \divisor, lsr #3
 	cmp	\dividend, #1
 	mov	\divisor, \divisor, lsr #4
+	it	ge
 	subges	\order, \order, #4
 	bge	1b
 
 	tst	\order, #3
+	it	ne
 	teqne	\dividend, #0
 	beq	5f
 
@@ -194,12 +217,15 @@ Boston, MA 02111-1307, USA.  */
 	blt	4f
 	beq	3f
 	cmp	\dividend, \divisor
+	it	hs
 	subhs	\dividend, \dividend, \divisor
 	mov	\divisor,  \divisor,  lsr #1
 3:	cmp	\dividend, \divisor
+	it	hs
 	subhs	\dividend, \dividend, \divisor
 	mov	\divisor,  \divisor,  lsr #1
 4:	cmp	\dividend, \divisor
+	it	hs
 	subhs	\dividend, \dividend, \divisor
 5:
 .endm
@@ -209,6 +235,7 @@ ENTRY(__udivsi3)
 ENTRY(__aeabi_uidiv)
 
 	subs	r2, r1, #1
+	it	eq
 	moveq	pc, lr
 	bcc	Ldiv0
 	cmp	r0, r1
@@ -221,7 +248,8 @@ ENTRY(__aeabi_uidiv)
 	mov	r0, r2
 	mov	pc, lr
 
-11:	moveq	r0, #1
+11:	ite	eq
+	moveq	r0, #1
 	movne	r0, #0
 	mov	pc, lr
 
@@ -230,21 +258,28 @@ ENTRY(__aeabi_uidiv)
 	mov	r0, r0, lsr r2
 	mov	pc, lr
 
+ENDPROC(__udivsi3)
+ENDPROC(__aeabi_uidiv)
 
 ENTRY(__umodsi3)
 
 	subs	r2, r1, #1			@ compare divisor with 1
 	bcc	Ldiv0
+	ite	ne
 	cmpne	r0, r1				@ compare dividend with divisor
 	moveq   r0, #0
+	it	hi
 	tsthi	r1, r2				@ see if divisor is power of 2
+	it	eq
 	andeq	r0, r0, r2
+	it	ls
 	movls	pc, lr
 
 	ARM_MOD_BODY r0, r1, r2, r3
 
 	mov	pc, lr
 
+ENDPROC(__umodsi3)
 
 ENTRY(__divsi3)
 ENTRY(__aeabi_idiv)
@@ -252,10 +287,12 @@ ENTRY(__aeabi_idiv)
 	cmp	r1, #0
 	eor	ip, r0, r1			@ save the sign of the result.
 	beq	Ldiv0
+	it	mi
 	rsbmi	r1, r1, #0			@ loops below use unsigned.
 	subs	r2, r1, #1			@ division by 1 or -1 ?
 	beq	10f
 	movs	r3, r0
+	it	mi
 	rsbmi	r3, r0, #0			@ positive dividend value
 	cmp	r3, r1
 	bls	11f
@@ -265,14 +302,18 @@ ENTRY(__aeabi_idiv)
 	ARM_DIV_BODY r3, r1, r0, r2
 
 	cmp	ip, #0
+	it	mi
 	rsbmi	r0, r0, #0
 	mov	pc, lr
 
 10:	teq	ip, r0				@ same sign ?
+	it	mi
 	rsbmi	r0, r0, #0
 	mov	pc, lr
 
-11:	movlo	r0, #0
+11:	it	lo
+	movlo	r0, #0
+	itt	eq
 	moveq	r0, ip, asr #31
 	orreq	r0, r0, #1
 	mov	pc, lr
@@ -281,30 +322,41 @@ ENTRY(__aeabi_idiv)
 
 	cmp	ip, #0
 	mov	r0, r3, lsr r2
+	it	mi
 	rsbmi	r0, r0, #0
 	mov	pc, lr
 
+ENDPROC(__divsi3)
+ENDPROC(__aeabi_idiv)
 
 ENTRY(__modsi3)
 
 	cmp	r1, #0
 	beq	Ldiv0
+	it	mi
 	rsbmi	r1, r1, #0			@ loops below use unsigned.
 	movs	ip, r0				@ preserve sign of dividend
+	it	mi
 	rsbmi	r0, r0, #0			@ if negative make positive
 	subs	r2, r1, #1			@ compare divisor with 1
+	ite	ne
 	cmpne	r0, r1				@ compare dividend with divisor
 	moveq	r0, #0
+	it	hi
 	tsthi	r1, r2				@ see if divisor is power of 2
+	it	eq
 	andeq	r0, r0, r2
 	bls	10f
 
 	ARM_MOD_BODY r0, r1, r2, r3
 
 10:	cmp	ip, #0
+	it	mi
 	rsbmi	r0, r0, #0
 	mov	pc, lr
 
+ENDPROC(__modsi3)
+
 #ifdef CONFIG_AEABI
 
 ENTRY(__aeabi_uidivmod)
@@ -316,6 +368,8 @@ ENTRY(__aeabi_uidivmod)
 	sub	r1, r1, r3
 	mov	pc, lr
 
+ENDPROC(__aeabi_uidivmod)
+
 ENTRY(__aeabi_idivmod)
 
 	stmfd	sp!, {r0, r1, ip, lr}
@@ -325,6 +379,8 @@ ENTRY(__aeabi_idivmod)
 	sub	r1, r1, r3
 	mov	pc, lr
 
+ENDPROC(__aeabi_idivmod)
+
 #endif
 
 Ldiv0:
diff --git a/arch/arm/lib/lshrdi3.S b/arch/arm/lib/lshrdi3.S
index a86dbdd..baa5209 100644
--- a/arch/arm/lib/lshrdi3.S
+++ b/arch/arm/lib/lshrdi3.S
@@ -24,6 +24,7 @@ You should have received a copy of the GNU General Public License
 along with this program; see the file COPYING.  If not, write to
 the Free Software Foundation, 51 Franklin Street, Fifth Floor,
 Boston, MA 02110-1301, USA.  */
+#include <asm/unified.h>
 
 
 #include <linux/linkage.h>
@@ -41,9 +42,14 @@ ENTRY(__aeabi_llsr)
 
 	subs	r3, r2, #32
 	rsb	ip, r2, #32
+	itett	mi
 	movmi	al, al, lsr r2
 	movpl	al, ah, lsr r3
-	orrmi	al, al, ah, lsl ip
+ ARM(	orrmi	al, al, ah, lsl ip	)
+ THUMB(	lslmi	r3, ah, ip		)
+ THUMB(	orrmi	al, al, r3		)
 	mov	ah, ah, lsr r2
 	mov	pc, lr
 
+ENDPROC(__lshrdi3)
+ENDPROC(__aeabi_llsr)
diff --git a/arch/arm/lib/memchr.S b/arch/arm/lib/memchr.S
index e7ab1ea..2ee546e 100644
--- a/arch/arm/lib/memchr.S
+++ b/arch/arm/lib/memchr.S
@@ -9,6 +9,8 @@
  *
  *  ASM optimised string functions
  */
+#include <asm/unified.h>
+
 #include <linux/linkage.h>
 #include <asm/assembler.h>
 
@@ -21,5 +23,7 @@ ENTRY(memchr)
 	teq	r3, r1
 	bne	1b
 	sub	r0, r0, #1
-2:	movne	r0, #0
+2:	it	ne
+	movne	r0, #0
 	mov	pc, lr
+ENDPROC(memchr)
diff --git a/arch/arm/lib/memcpy.S b/arch/arm/lib/memcpy.S
index 7e71d67..c8866af 100644
--- a/arch/arm/lib/memcpy.S
+++ b/arch/arm/lib/memcpy.S
@@ -9,12 +9,16 @@
  *  it under the terms of the GNU General Public License version 2 as
  *  published by the Free Software Foundation.
  */
+#include <asm/unified.h>
 
 #include <linux/linkage.h>
 #include <asm/assembler.h>
 
+#define LDR1W_SHIFT	0
+#define STR1W_SHIFT	0
+
 	.macro ldr1w ptr reg abort
-	ldr \reg, [\ptr], #4
+	W(ldr) \reg, [\ptr], #4
 	.endm
 
 	.macro ldr4w ptr reg1 reg2 reg3 reg4 abort
@@ -26,11 +30,16 @@
 	.endm
 
 	.macro ldr1b ptr reg cond=al abort
+	.ifnc \cond,al
+	it \cond
 	ldr\cond\()b \reg, [\ptr], #1
+	.else
+	ldrb \reg, [\ptr], #1
+	.endif
 	.endm
 
 	.macro str1w ptr reg abort
-	str \reg, [\ptr], #4
+	W(str) \reg, [\ptr], #4
 	.endm
 
 	.macro str8w ptr reg1 reg2 reg3 reg4 reg5 reg6 reg7 reg8 abort
@@ -38,7 +47,12 @@
 	.endm
 
 	.macro str1b ptr reg cond=al abort
+	.ifnc \cond,al
+	it \cond
 	str\cond\()b \reg, [\ptr], #1
+	.else
+	strb \reg, [\ptr], #1
+	.endif
 	.endm
 
 	.macro enter reg1 reg2
@@ -57,3 +71,4 @@ ENTRY(memcpy)
 
 #include "copy_template.S"
 
+ENDPROC(memcpy)
diff --git a/arch/arm/lib/memmove.S b/arch/arm/lib/memmove.S
index ef7fddc..8be0272 100644
--- a/arch/arm/lib/memmove.S
+++ b/arch/arm/lib/memmove.S
@@ -9,6 +9,7 @@
  *  it under the terms of the GNU General Public License version 2 as
  *  published by the Free Software Foundation.
  */
+#include <asm/unified.h>
 
 #include <linux/linkage.h>
 #include <asm/assembler.h>
@@ -37,7 +38,9 @@
 ENTRY(memmove)
 
 		subs	ip, r0, r1
+		it	hi
 		cmphi	r2, ip
+		it	ls
 		bls	memcpy
 
 		stmfd	sp!, {r0, r4, lr}
@@ -79,46 +82,55 @@ ENTRY(memmove)
 
 5:		ands	ip, r2, #28
 		rsb	ip, ip, #32
+		it	ne
 		addne	pc, pc, ip		@ C is always clear here
 		b	7f
 6:		nop
-		ldr	r3, [r1, #-4]!
-		ldr	r4, [r1, #-4]!
-		ldr	r5, [r1, #-4]!
-		ldr	r6, [r1, #-4]!
-		ldr	r7, [r1, #-4]!
-		ldr	r8, [r1, #-4]!
-		ldr	lr, [r1, #-4]!
+		W(ldr)	r3, [r1, #-4]!
+		W(ldr)	r4, [r1, #-4]!
+		W(ldr)	r5, [r1, #-4]!
+		W(ldr)	r6, [r1, #-4]!
+		W(ldr)	r7, [r1, #-4]!
+		W(ldr)	r8, [r1, #-4]!
+		W(ldr)	lr, [r1, #-4]!
 
 		add	pc, pc, ip
 		nop
 		nop
-		str	r3, [r0, #-4]!
-		str	r4, [r0, #-4]!
-		str	r5, [r0, #-4]!
-		str	r6, [r0, #-4]!
-		str	r7, [r0, #-4]!
-		str	r8, [r0, #-4]!
-		str	lr, [r0, #-4]!
+		W(str)	r3, [r0, #-4]!
+		W(str)	r4, [r0, #-4]!
+		W(str)	r5, [r0, #-4]!
+		W(str)	r6, [r0, #-4]!
+		W(str)	r7, [r0, #-4]!
+		W(str)	r8, [r0, #-4]!
+		W(str)	lr, [r0, #-4]!
 
 	CALGN(	bcs	2b			)
 
 7:		ldmfd	sp!, {r5 - r8}
 
 8:		movs	r2, r2, lsl #31
+		it	ne
 		ldrneb	r3, [r1, #-1]!
+		itt	cs
 		ldrcsb	r4, [r1, #-1]!
 		ldrcsb	ip, [r1, #-1]
+		it	ne
 		strneb	r3, [r0, #-1]!
+		itt	cs
 		strcsb	r4, [r0, #-1]!
 		strcsb	ip, [r0, #-1]
 		ldmfd	sp!, {r0, r4, pc}
 
 9:		cmp	ip, #2
+		it	gt
 		ldrgtb	r3, [r1, #-1]!
+		it	ge
 		ldrgeb	r4, [r1, #-1]!
 		ldrb	lr, [r1, #-1]!
+		it	gt
 		strgtb	r3, [r0, #-1]!
+		it	ge
 		strgeb	r4, [r0, #-1]!
 		subs	r2, r2, ip
 		strb	lr, [r0, #-1]!
@@ -204,3 +216,4 @@ ENTRY(memmove)
 
 18:		backward_copy_shift	push=24	pull=8
 
+ENDPROC(memmove)
diff --git a/arch/arm/lib/memset.S b/arch/arm/lib/memset.S
index 95b110b..925c5e2 100644
--- a/arch/arm/lib/memset.S
+++ b/arch/arm/lib/memset.S
@@ -9,6 +9,8 @@
  *
  *  ASM optimised string functions
  */
+#include <asm/unified.h>
+
 #include <linux/linkage.h>
 #include <asm/assembler.h>
 
@@ -19,7 +21,9 @@
 1:	subs	r2, r2, #4		@ 1 do we have enough
 	blt	5f			@ 1 bytes to align with?
 	cmp	r3, #2			@ 1
+	it	lt
 	strltb	r1, [r0], #1		@ 1
+	it	le
 	strleb	r1, [r0], #1		@ 1
 	strb	r1, [r0], #1		@ 1
 	add	r2, r2, r3		@ 1 (r2 = r2 - (4 - r3))
@@ -48,33 +52,42 @@ ENTRY(memset)
 	mov	lr, r1
 
 2:	subs	r2, r2, #64
+	itttt	ge
 	stmgeia	r0!, {r1, r3, ip, lr}	@ 64 bytes at a time.
 	stmgeia	r0!, {r1, r3, ip, lr}
 	stmgeia	r0!, {r1, r3, ip, lr}
 	stmgeia	r0!, {r1, r3, ip, lr}
 	bgt	2b
+	it	eq
 	ldmeqfd	sp!, {pc}		@ Now <64 bytes to go.
 /*
  * No need to correct the count; we're only testing bits from now on
  */
 	tst	r2, #32
+	itt	ne
 	stmneia	r0!, {r1, r3, ip, lr}
 	stmneia	r0!, {r1, r3, ip, lr}
 	tst	r2, #16
+	it	ne
 	stmneia	r0!, {r1, r3, ip, lr}
 	ldr	lr, [sp], #4
 
 4:	tst	r2, #8
+	it	ne
 	stmneia	r0!, {r1, r3}
 	tst	r2, #4
+	it	ne
 	strne	r1, [r0], #4
 /*
  * When we get here, we've got less than 4 bytes to zero.  We
  * may have an unaligned pointer as well.
  */
 5:	tst	r2, #2
+	itt	ne
 	strneb	r1, [r0], #1
 	strneb	r1, [r0], #1
 	tst	r2, #1
+	it	ne
 	strneb	r1, [r0], #1
 	mov	pc, lr
+ENDPROC(memset)
diff --git a/arch/arm/lib/memzero.S b/arch/arm/lib/memzero.S
index abf2508..7719ae7 100644
--- a/arch/arm/lib/memzero.S
+++ b/arch/arm/lib/memzero.S
@@ -7,6 +7,8 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
+#include <asm/unified.h>
+
 #include <linux/linkage.h>
 #include <asm/assembler.h>
 
@@ -21,7 +23,9 @@
 1:	subs	r1, r1, #4		@ 1 do we have enough
 	blt	5f			@ 1 bytes to align with?
 	cmp	r3, #2			@ 1
+	it	lt
 	strltb	r2, [r0], #1		@ 1
+	it	le
 	strleb	r2, [r0], #1		@ 1
 	strb	r2, [r0], #1		@ 1
 	add	r1, r1, r3		@ 1 (r1 = r1 - (4 - r3))
@@ -48,33 +52,42 @@ ENTRY(__memzero)
 	mov	lr, r2			@ 1
 
 3:	subs	r1, r1, #64		@ 1 write 32 bytes out per loop
+	itttt	ge
 	stmgeia	r0!, {r2, r3, ip, lr}	@ 4
 	stmgeia	r0!, {r2, r3, ip, lr}	@ 4
 	stmgeia	r0!, {r2, r3, ip, lr}	@ 4
 	stmgeia	r0!, {r2, r3, ip, lr}	@ 4
 	bgt	3b			@ 1
+	it	eq
 	ldmeqfd	sp!, {pc}		@ 1/2 quick exit
 /*
  * No need to correct the count; we're only testing bits from now on
  */
 	tst	r1, #32			@ 1
+	itt	ne
 	stmneia	r0!, {r2, r3, ip, lr}	@ 4
 	stmneia	r0!, {r2, r3, ip, lr}	@ 4
 	tst	r1, #16			@ 1 16 bytes or more?
+	it	ne
 	stmneia	r0!, {r2, r3, ip, lr}	@ 4
 	ldr	lr, [sp], #4		@ 1
 
 4:	tst	r1, #8			@ 1 8 bytes or more?
+	it	ne
 	stmneia	r0!, {r2, r3}		@ 2
 	tst	r1, #4			@ 1 4 bytes or more?
+	it	ne
 	strne	r2, [r0], #4		@ 1
 /*
  * When we get here, we've got less than 4 bytes to zero.  We
  * may have an unaligned pointer as well.
  */
 5:	tst	r1, #2			@ 1 2 bytes or more?
+	itt	ne
 	strneb	r2, [r0], #1		@ 1
 	strneb	r2, [r0], #1		@ 1
 	tst	r1, #1			@ 1 a byte left over
+	it	ne
 	strneb	r2, [r0], #1		@ 1
 	mov	pc, lr			@ 1
+ENDPROC(__memzero)
diff --git a/arch/arm/lib/muldi3.S b/arch/arm/lib/muldi3.S
index d89c606..9484b52 100644
--- a/arch/arm/lib/muldi3.S
+++ b/arch/arm/lib/muldi3.S
@@ -9,6 +9,7 @@
  *  it under the terms of the GNU General Public License version 2 as
  *  published by the Free Software Foundation.
  */
+#include <asm/unified.h>
 
 #include <linux/linkage.h>
 
@@ -43,3 +44,5 @@ ENTRY(__aeabi_lmul)
 	adc	xh, xh, ip, lsr #16
 	mov	pc, lr
 
+ENDPROC(__muldi3)
+ENDPROC(__aeabi_lmul)
diff --git a/arch/arm/lib/putuser.S b/arch/arm/lib/putuser.S
index 8620afe..9a474d9 100644
--- a/arch/arm/lib/putuser.S
+++ b/arch/arm/lib/putuser.S
@@ -26,43 +26,56 @@
  * Note that ADDR_LIMIT is either 0 or 0xc0000000
  * Note also that it is intended that __put_user_bad is not global.
  */
+#include <asm/unified.h>
+
+#include <linux/linkage.h>
 #include <asm/errno.h>
 
-	.global	__put_user_1
-__put_user_1:
+ENTRY(__put_user_1)
 1:	strbt	r2, [r0]
 	mov	r0, #0
 	mov	pc, lr
+ENDPROC(__put_user_1)
 
-	.global	__put_user_2
-__put_user_2:
+ENTRY(__put_user_2)
 	mov	ip, r2, lsr #8
 #ifndef __ARMEB__
-2:	strbt	r2, [r0], #1
+2:
+ ARM(	strbt	r2, [r0], #1	)
+ THUMB(	strbt	r2, [r0]	)
+ THUMB(	add	r0, #1		)
 3:	strbt	ip, [r0]
 #else
-2:	strbt	ip, [r0], #1
+2:
+ ARM(	strbt	ip, [r0], #1	)
+ THUMB(	strbt	ip, [r0]	)
+ THUMB(	add	r0, #1		)
 3:	strbt	r2, [r0]
 #endif
 	mov	r0, #0
 	mov	pc, lr
+ENDPROC(__put_user_2)
 
-	.global	__put_user_4
-__put_user_4:
+ENTRY(__put_user_4)
 4:	strt	r2, [r0]
 	mov	r0, #0
 	mov	pc, lr
+ENDPROC(__put_user_4)
 
-	.global	__put_user_8
-__put_user_8:
-5:	strt	r2, [r0], #4
+ENTRY(__put_user_8)
+5:
+ ARM(	strt	r2, [r0], #4	)
+ THUMB(	strt	r2, [r0]	)
+ THUMB(	add	r0, #4		)
 6:	strt	r3, [r0]
 	mov	r0, #0
 	mov	pc, lr
+ENDPROC(__put_user_8)
 
 __put_user_bad:
 	mov	r0, #-EFAULT
 	mov	pc, lr
+ENDPROC(__put_user_bad)
 
 .section __ex_table, "a"
 	.long	1b, __put_user_bad
diff --git a/arch/arm/lib/setbit.S b/arch/arm/lib/setbit.S
index 83bc23d..88e956d 100644
--- a/arch/arm/lib/setbit.S
+++ b/arch/arm/lib/setbit.S
@@ -7,6 +7,8 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
+#include <asm/unified.h>
+
 #include <linux/linkage.h>
 #include <asm/assembler.h>
 #include "bitops.h"
@@ -20,3 +22,5 @@ ENTRY(_set_bit_be)
 		eor	r0, r0, #0x18		@ big endian byte ordering
 ENTRY(_set_bit_le)
 	bitop	orr
+ENDPROC(_set_bit_be)
+ENDPROC(_set_bit_le)
diff --git a/arch/arm/lib/sha1.S b/arch/arm/lib/sha1.S
index ff6ece4..3c71fca 100644
--- a/arch/arm/lib/sha1.S
+++ b/arch/arm/lib/sha1.S
@@ -12,6 +12,7 @@
  *
  *  The reference implementation for this code is linux/lib/sha1.c
  */
+#include <asm/unified.h>
 
 #include <linux/linkage.h>
 
@@ -185,6 +186,9 @@ ENTRY(sha_transform)
 
 	ldmfd	sp!, {r4 - r8, pc}
 
+ENDPROC(sha_transform)
+
+	.align	2
 .L_sha_K:
 	.word	0x5a827999, 0x6ed9eba1, 0x8f1bbcdc, 0xca62c1d6
 
@@ -193,6 +197,7 @@ ENTRY(sha_transform)
  * void sha_init(__u32 *buf)
  */
 
+	.align	2
 .L_sha_initial_digest:
 	.word	0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476, 0xc3d2e1f0
 
@@ -204,3 +209,4 @@ ENTRY(sha_init)
 	stmia	r0, {r1, r2, r3, ip, lr}
 	ldr	pc, [sp], #4
 
+ENDPROC(sha_init)
diff --git a/arch/arm/lib/strchr.S b/arch/arm/lib/strchr.S
index 9f18d6f..29109bb 100644
--- a/arch/arm/lib/strchr.S
+++ b/arch/arm/lib/strchr.S
@@ -9,6 +9,8 @@
  *
  *  ASM optimised string functions
  */
+#include <asm/unified.h>
+
 #include <linux/linkage.h>
 #include <asm/assembler.h>
 
@@ -18,9 +20,12 @@ ENTRY(strchr)
 		and	r1, r1, #0xff
 1:		ldrb	r2, [r0], #1
 		teq	r2, r1
+		it	ne
 		teqne	r2, #0
 		bne	1b
 		teq	r2, r1
+		ite	ne
 		movne	r0, #0
 		subeq	r0, r0, #1
 		mov	pc, lr
+ENDPROC(strchr)
diff --git a/arch/arm/lib/strncpy_from_user.S b/arch/arm/lib/strncpy_from_user.S
index 36e3741..07e249a 100644
--- a/arch/arm/lib/strncpy_from_user.S
+++ b/arch/arm/lib/strncpy_from_user.S
@@ -7,6 +7,8 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
+#include <asm/unified.h>
+
 #include <linux/linkage.h>
 #include <asm/assembler.h>
 #include <asm/errno.h>
@@ -23,7 +25,10 @@
 ENTRY(__strncpy_from_user)
 	mov	ip, r1
 1:	subs	r2, r2, #1
-USER(	ldrplbt	r3, [r1], #1)
+ARM(USER(	ldrplbt	r3, [r1], #1	))
+	itt	pl
+THUMB(USER(	ldrplbt	r3, [r1]	))
+THUMB(		addpl	r1, #1		)
 	bmi	2f
 	strb	r3, [r0], #1
 	teq	r3, #0
@@ -31,6 +36,7 @@ USER(	ldrplbt	r3, [r1], #1)
 	sub	r1, r1, #1	@ take NUL character out of count
 2:	sub	r0, r1, ip
 	mov	pc, lr
+ENDPROC(__strncpy_from_user)
 
 	.section .fixup,"ax"
 	.align	0
diff --git a/arch/arm/lib/strnlen_user.S b/arch/arm/lib/strnlen_user.S
index 18d8fa4..0cd8add 100644
--- a/arch/arm/lib/strnlen_user.S
+++ b/arch/arm/lib/strnlen_user.S
@@ -7,6 +7,8 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
+#include <asm/unified.h>
+
 #include <linux/linkage.h>
 #include <asm/assembler.h>
 #include <asm/errno.h>
@@ -23,7 +25,9 @@
 ENTRY(__strnlen_user)
 	mov	r2, r0
 1:
-USER(	ldrbt	r3, [r0], #1)
+ARM(USER(	ldrbt	r3, [r0], #1	))
+THUMB(USER(	ldrbt	r3, [r0]	))
+THUMB(		add	r0, #1		)
 	teq	r3, #0
 	beq	2f
 	subs	r1, r1, #1
@@ -31,6 +35,7 @@ USER(	ldrbt	r3, [r0], #1)
 	add	r0, r0, #1
 2:	sub	r0, r0, r2
 	mov	pc, lr
+ENDPROC(__strnlen_user)
 
 	.section .fixup,"ax"
 	.align	0
diff --git a/arch/arm/lib/strrchr.S b/arch/arm/lib/strrchr.S
index 538df22..e3a7586 100644
--- a/arch/arm/lib/strrchr.S
+++ b/arch/arm/lib/strrchr.S
@@ -9,6 +9,8 @@
  *
  *  ASM optimised string functions
  */
+#include <asm/unified.h>
+
 #include <linux/linkage.h>
 #include <asm/assembler.h>
 
@@ -18,8 +20,10 @@ ENTRY(strrchr)
 		mov	r3, #0
 1:		ldrb	r2, [r0], #1
 		teq	r2, r1
+		it	eq
 		subeq	r3, r0, #1
 		teq	r2, #0
 		bne	1b
 		mov	r0, r3
 		mov	pc, lr
+ENDPROC(strrchr)
diff --git a/arch/arm/lib/testchangebit.S b/arch/arm/lib/testchangebit.S
index b25dcd2..a4fe45f 100644
--- a/arch/arm/lib/testchangebit.S
+++ b/arch/arm/lib/testchangebit.S
@@ -7,6 +7,8 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
+#include <asm/unified.h>
+
 #include <linux/linkage.h>
 #include <asm/assembler.h>
 #include "bitops.h"
@@ -16,3 +18,5 @@ ENTRY(_test_and_change_bit_be)
 		eor	r0, r0, #0x18		@ big endian byte ordering
 ENTRY(_test_and_change_bit_le)
 	testop	eor, strb
+ENDPROC(_test_and_change_bit_be)
+ENDPROC(_test_and_change_bit_le)
diff --git a/arch/arm/lib/testclearbit.S b/arch/arm/lib/testclearbit.S
index 2dcc4b1..f67f090 100644
--- a/arch/arm/lib/testclearbit.S
+++ b/arch/arm/lib/testclearbit.S
@@ -7,6 +7,8 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
+#include <asm/unified.h>
+
 #include <linux/linkage.h>
 #include <asm/assembler.h>
 #include "bitops.h"
@@ -15,4 +17,6 @@
 ENTRY(_test_and_clear_bit_be)
 		eor	r0, r0, #0x18		@ big endian byte ordering
 ENTRY(_test_and_clear_bit_le)
-	testop	bicne, strneb
+	testop	bicne, strneb, ne
+ENDPROC(_test_and_clear_bit_be)
+ENDPROC(_test_and_clear_bit_le)
diff --git a/arch/arm/lib/testsetbit.S b/arch/arm/lib/testsetbit.S
index 9011c96..d3a8512 100644
--- a/arch/arm/lib/testsetbit.S
+++ b/arch/arm/lib/testsetbit.S
@@ -7,6 +7,8 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
+#include <asm/unified.h>
+
 #include <linux/linkage.h>
 #include <asm/assembler.h>
 #include "bitops.h"
@@ -15,4 +17,6 @@
 ENTRY(_test_and_set_bit_be)
 		eor	r0, r0, #0x18		@ big endian byte ordering
 ENTRY(_test_and_set_bit_le)
-	testop	orreq, streqb
+	testop	orreq, streqb, eq
+ENDPROC(_test_and_set_bit_be)
+ENDPROC(_test_and_set_bit_le)
diff --git a/arch/arm/lib/uaccess.S b/arch/arm/lib/uaccess.S
index b48bd6d..ffdd274 100644
--- a/arch/arm/lib/uaccess.S
+++ b/arch/arm/lib/uaccess.S
@@ -277,6 +277,7 @@ USER(		strgebt	r3, [r0], #1)			@ May fault
 		ldrgtb	r3, [r1], #0
 USER(		strgtbt	r3, [r0], #1)			@ May fault
 		b	.Lc2u_finished
+ENDPROC(__copy_to_user)
 
 		.section .fixup,"ax"
 		.align	0
@@ -542,6 +543,7 @@ USER(		ldrgebt	r3, [r1], #1)			@ May fault
 USER(		ldrgtbt	r3, [r1], #1)			@ May fault
 		strgtb	r3, [r0], #1
 		b	.Lcfu_finished
+ENDPROC(__copy_from_user)
 
 		.section .fixup,"ax"
 		.align	0
diff --git a/arch/arm/lib/ucmpdi2.S b/arch/arm/lib/ucmpdi2.S
index f76de07..eb6cabe 100644
--- a/arch/arm/lib/ucmpdi2.S
+++ b/arch/arm/lib/ucmpdi2.S
@@ -9,6 +9,7 @@
  *  it under the terms of the GNU General Public License version 2 as
  *  published by the Free Software Foundation.
  */
+#include <asm/unified.h>
 
 #include <linux/linkage.h>
 
@@ -27,22 +28,34 @@
 ENTRY(__ucmpdi2)
 
 	cmp	xh, yh
+	it	eq
 	cmpeq	xl, yl
+	it	lo
 	movlo	r0, #0
+	it	eq
 	moveq	r0, #1
+	it	hi
 	movhi	r0, #2
 	mov	pc, lr
 
+ENDPROC(__ucmpdi2)
+
 #ifdef CONFIG_AEABI
 
 ENTRY(__aeabi_ulcmp)
 
 	cmp	xh, yh
+	it	eq
 	cmpeq	xl, yl
+	it	lo
 	movlo	r0, #-1
+	it	eq
 	moveq	r0, #0
+	it	hi
 	movhi	r0, #1
 	mov	pc, lr
 
+ENDPROC(__aeabi_ulcmp)
+
 #endif
 
diff --git a/arch/arm/mach-integrator/integrator_cp.c b/arch/arm/mach-integrator/integrator_cp.c
index 913f64b..86d8aad 100644
--- a/arch/arm/mach-integrator/integrator_cp.c
+++ b/arch/arm/mach-integrator/integrator_cp.c
@@ -48,14 +48,14 @@
 
 #define INTCP_PA_CLCD_BASE		0xc0000000
 
-#define INTCP_VA_CIC_BASE		0xf1000040
-#define INTCP_VA_PIC_BASE		0xf1400000
-#define INTCP_VA_SIC_BASE		0xfca00000
+#define INTCP_VA_CIC_BASE		IO_ADDRESS(INTEGRATOR_HDR_BASE) + 0x40
+#define INTCP_VA_PIC_BASE		IO_ADDRESS(INTEGRATOR_IC_BASE)
+#define INTCP_VA_SIC_BASE		IO_ADDRESS(0xca000000)
 
 #define INTCP_PA_ETH_BASE		0xc8000000
 #define INTCP_ETH_SIZE			0x10
 
-#define INTCP_VA_CTRL_BASE		0xfcb00000
+#define INTCP_VA_CTRL_BASE		IO_ADDRESS(0xcb000000)
 #define INTCP_FLASHPROG			0x04
 #define CINTEGRATOR_FLASHPROG_FLVPPEN	(1 << 0)
 #define CINTEGRATOR_FLASHPROG_FLWREN	(1 << 1)
@@ -120,12 +120,12 @@ static struct map_desc intcp_io_desc[] __initdata = {
 		.length		= SZ_4K,
 		.type		= MT_DEVICE
 	}, {
-		.virtual	= 0xfca00000,
+		.virtual	= IO_ADDRESS(0xca000000),
 		.pfn		= __phys_to_pfn(0xca000000),
 		.length		= SZ_4K,
 		.type		= MT_DEVICE
 	}, {
-		.virtual	= 0xfcb00000,
+		.virtual	= IO_ADDRESS(0xcb000000),
 		.pfn		= __phys_to_pfn(0xcb000000),
 		.length		= SZ_4K,
 		.type		= MT_DEVICE
@@ -393,8 +393,8 @@ static struct platform_device *intcp_devs[] __initdata = {
  */
 static unsigned int mmc_status(struct device *dev)
 {
-	unsigned int status = readl(0xfca00004);
-	writel(8, 0xfcb00008);
+	unsigned int status = readl(IO_ADDRESS(0xca000000) + 4);
+	writel(8, IO_ADDRESS(0xcb000000) + 8);
 
 	return status & 8;
 }
diff --git a/arch/arm/mach-realview/Kconfig b/arch/arm/mach-realview/Kconfig
index 5ccde7c..396f4a5 100644
--- a/arch/arm/mach-realview/Kconfig
+++ b/arch/arm/mach-realview/Kconfig
@@ -3,7 +3,8 @@ menu "RealView platform type"
 
 config MACH_REALVIEW_EB
 	bool "Support RealView/EB platform"
-	select ARM_GIC
+	select ARM_GIC if !CPU_V7M
+	select ARM_NVIC if CPU_V7M
 	help
 	  Include support for the ARM(R) RealView Emulation Baseboard platform.
 
diff --git a/arch/arm/mach-realview/Makefile.boot b/arch/arm/mach-realview/Makefile.boot
index c7e75ac..67116b8 100644
--- a/arch/arm/mach-realview/Makefile.boot
+++ b/arch/arm/mach-realview/Makefile.boot
@@ -1,4 +1,4 @@
-   zreladdr-y	:= 0x00008000
-params_phys-y	:= 0x00000100
-initrd_phys-y	:= 0x00800000
+   zreladdr-y	:= 0x20008000
+params_phys-y	:= 0x20000100
+initrd_phys-y	:= 0x20800000
 
diff --git a/arch/arm/mach-realview/realview_eb.c b/arch/arm/mach-realview/realview_eb.c
index 5782d83..11f0dda 100644
--- a/arch/arm/mach-realview/realview_eb.c
+++ b/arch/arm/mach-realview/realview_eb.c
@@ -30,6 +30,7 @@
 #include <asm/leds.h>
 #include <asm/mach-types.h>
 #include <asm/hardware/gic.h>
+#include <asm/hardware/nvic.h>
 #include <asm/hardware/icst307.h>
 #include <asm/hardware/cache-l2x0.h>
 
@@ -44,6 +45,11 @@
 #include "core.h"
 #include "clock.h"
 
+#if defined(CONFIG_CPU_V7M) && (PAGE_OFFSET != PHYS_OFFSET)
+#error "PAGE_OFFSET != PHYS_OFFSET"
+#endif
+
+#ifndef CONFIG_CPU_V7M
 static struct map_desc realview_eb_io_desc[] __initdata = {
 	{
 		.virtual	= IO_ADDRESS(REALVIEW_SYS_BASE),
@@ -104,6 +110,7 @@ static struct map_desc realview_eb11mp_io_desc[] __initdata = {
 		.type		= MT_DEVICE,
 	}
 };
+#endif	/* CONFIG_CPU_V7M */
 
 static void __init realview_eb_map_io(void)
 {
@@ -274,6 +281,7 @@ static int eth_device_register(void)
 
 static void __init gic_init_irq(void)
 {
+#ifndef CONFIG_CPU_V7M
 	if (core_tile_eb11mp()) {
 		unsigned int pldctrl;
 
@@ -301,6 +309,9 @@ static void __init gic_init_irq(void)
 		gic_dist_init(0, __io_address(REALVIEW_EB_GIC_DIST_BASE), 29);
 		gic_cpu_init(0, gic_cpu_base_addr);
 	}
+#else	/* !CONFIG_CPU_V7M */
+	nvic_init();
+#endif
 }
 
 /*
@@ -392,7 +403,7 @@ MACHINE_START(REALVIEW_EB, "ARM-RealView EB")
 	/* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */
 	.phys_io	= REALVIEW_EB_UART0_BASE,
 	.io_pg_offst	= (IO_ADDRESS(REALVIEW_EB_UART0_BASE) >> 18) & 0xfffc,
-	.boot_params	= 0x00000100,
+	.boot_params	= PHYS_OFFSET + 0x100,
 	.map_io		= realview_eb_map_io,
 	.init_irq	= gic_init_irq,
 	.timer		= &realview_eb_timer,
diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig
index 33ed048..151a6e0 100644
--- a/arch/arm/mm/Kconfig
+++ b/arch/arm/mm/Kconfig
@@ -427,6 +427,19 @@ config CPU_V7
 	select CPU_COPY_V6 if MMU
 	select CPU_TLB_V7 if MMU
 
+# ARMv7
+config CPU_V7M
+	bool "Support ARMv7-M processors"
+	depends on MACH_REALVIEW_EB && EXPERIMENTAL
+	select THUMB2_KERNEL
+	select ARM_THUMB
+	select CPU_32v7M
+	select CPU_32v6K
+	select CPU_ABRT_EV7M
+	select CPU_PABRT_NOIFAR
+	select CPU_CACHE_V7M
+	select CPU_CACHE_VIPT
+
 # Figure out what processor architecture version we should be using.
 # This defines the compiler instruction set which depends on the machine type.
 config CPU_32v3
@@ -456,6 +469,9 @@ config CPU_32v6
 config CPU_32v7
 	bool
 
+config CPU_32v7M
+	bool
+
 # The abort model
 config CPU_ABRT_NOMMU
 	bool
@@ -481,6 +497,9 @@ config CPU_ABRT_EV6
 config CPU_ABRT_EV7
 	bool
 
+config CPU_ABRT_EV7M
+	bool
+
 config CPU_PABRT_IFAR
 	bool
 
@@ -506,6 +525,9 @@ config CPU_CACHE_V6
 config CPU_CACHE_V7
 	bool
 
+config CPU_CACHE_V7M
+	bool
+
 config CPU_CACHE_VIVT
 	bool
 
@@ -592,7 +614,7 @@ comment "Processor Features"
 
 config ARM_THUMB
 	bool "Support Thumb user binaries"
-	depends on CPU_ARM720T || CPU_ARM740T || CPU_ARM920T || CPU_ARM922T || CPU_ARM925T || CPU_ARM926T || CPU_ARM940T || CPU_ARM946E || CPU_ARM1020 || CPU_ARM1020E || CPU_ARM1022 || CPU_ARM1026 || CPU_XSCALE || CPU_XSC3 || CPU_V6 || CPU_V7 || CPU_FEROCEON
+	depends on CPU_ARM720T || CPU_ARM740T || CPU_ARM920T || CPU_ARM922T || CPU_ARM925T || CPU_ARM926T || CPU_ARM940T || CPU_ARM946E || CPU_ARM1020 || CPU_ARM1020E || CPU_ARM1022 || CPU_ARM1026 || CPU_XSCALE || CPU_XSC3 || CPU_V6 || CPU_V7 || CPU_FEROCEON || CPU_V7M
 	default y
 	help
 	  Say Y if you want to include kernel support for running user space
diff --git a/arch/arm/mm/Makefile b/arch/arm/mm/Makefile
index 32b2d2d..b571826 100644
--- a/arch/arm/mm/Makefile
+++ b/arch/arm/mm/Makefile
@@ -2,14 +2,13 @@
 # Makefile for the linux arm-specific parts of the memory manager.
 #
 
-obj-y				:= consistent.o extable.o fault.o init.o \
-				   iomap.o
+obj-y				:= extable.o fault.o init.o iomap.o
 
 obj-$(CONFIG_MMU)		+= fault-armv.o flush.o ioremap.o mmap.o \
-				   pgd.o mmu.o
+				   consistent.o pgd.o mmu.o
 
 ifneq ($(CONFIG_MMU),y)
-obj-y				+= nommu.o
+obj-y				+= consistent-nommu.o nommu.o
 endif
 
 obj-$(CONFIG_MODULES)		+= proc-syms.o
@@ -25,6 +24,7 @@ obj-$(CONFIG_CPU_ABRT_EV5T)	+= abort-ev5t.o
 obj-$(CONFIG_CPU_ABRT_EV5TJ)	+= abort-ev5tj.o
 obj-$(CONFIG_CPU_ABRT_EV6)	+= abort-ev6.o
 obj-$(CONFIG_CPU_ABRT_EV7)	+= abort-ev7.o
+obj-$(CONFIG_CPU_ABRT_EV7M)	+= abort-ev7m.o
 
 obj-$(CONFIG_CPU_CACHE_V3)	+= cache-v3.o
 obj-$(CONFIG_CPU_CACHE_V4)	+= cache-v4.o
@@ -72,5 +72,6 @@ obj-$(CONFIG_CPU_XSC3)		+= proc-xsc3.o
 obj-$(CONFIG_CPU_FEROCEON)	+= proc-feroceon.o
 obj-$(CONFIG_CPU_V6)		+= proc-v6.o
 obj-$(CONFIG_CPU_V7)		+= proc-v7.o
+obj-$(CONFIG_CPU_V7M)		+= proc-v7m.o
 
 obj-$(CONFIG_CACHE_L2X0)	+= cache-l2x0.o
diff --git a/arch/arm/mm/abort-ev7.S b/arch/arm/mm/abort-ev7.S
index eb90bce..2e6dc04 100644
--- a/arch/arm/mm/abort-ev7.S
+++ b/arch/arm/mm/abort-ev7.S
@@ -30,3 +30,4 @@ ENTRY(v7_early_abort)
 	 * New designs should not need to patch up faults.
 	 */
 	mov	pc, lr
+ENDPROC(v7_early_abort)
diff --git a/arch/arm/mm/abort-ev7m.S b/arch/arm/mm/abort-ev7m.S
new file mode 100644
index 0000000..083e85b
--- /dev/null
+++ b/arch/arm/mm/abort-ev7m.S
@@ -0,0 +1,9 @@
+#include <linux/linkage.h>
+#include <asm/assembler.h>
+/*
+ * Function: v7m_early_abort
+ */
+	.align	5
+ENTRY(v7m_early_abort)
+	mov	pc, lr
+ENDPROC(v7m_early_abort)
diff --git a/arch/arm/mm/abort-nommu.S b/arch/arm/mm/abort-nommu.S
index a7cc7f9..625e580 100644
--- a/arch/arm/mm/abort-nommu.S
+++ b/arch/arm/mm/abort-nommu.S
@@ -17,3 +17,4 @@ ENTRY(nommu_early_abort)
 	mov	r0, #0				@ clear r0, r1 (no FSR/FAR)
 	mov	r1, #0
 	mov	pc, lr
+ENDPROC(nommu_early_abort)
diff --git a/arch/arm/mm/alignment.c b/arch/arm/mm/alignment.c
index e162cca..790ea33 100644
--- a/arch/arm/mm/alignment.c
+++ b/arch/arm/mm/alignment.c
@@ -18,6 +18,7 @@
 #include <linux/proc_fs.h>
 #include <linux/init.h>
 
+#include <asm/unified.h>
 #include <asm/uaccess.h>
 #include <asm/unaligned.h>
 
@@ -148,7 +149,9 @@ union offset_union {
 
 #define __get8_unaligned_check(ins,val,addr,err)	\
 	__asm__(					\
-	"1:	"ins"	%1, [%2], #1\n"			\
+ ARM(	"1:	"ins"	%1, [%2], #1\n"	)		\
+ THUMB(	"1:	"ins"	%1, [%2]\n"	)		\
+ THUMB(	"	add	%2, %2, #1\n"	)		\
 	"2:\n"						\
 	"	.section .fixup,\"ax\"\n"		\
 	"	.align	2\n"				\
@@ -204,7 +207,9 @@ union offset_union {
 	do {							\
 		unsigned int err = 0, v = val, a = addr;	\
 		__asm__( FIRST_BYTE_16				\
-		"1:	"ins"	%1, [%2], #1\n"			\
+	 ARM(	"1:	"ins"	%1, [%2], #1\n"	)		\
+	 THUMB(	"1:	"ins"	%1, [%2]\n"	)		\
+	 THUMB(	"	add	%2, %2, #1\n"	)		\
 		"	mov	%1, %1, "NEXT_BYTE"\n"		\
 		"2:	"ins"	%1, [%2]\n"			\
 		"3:\n"						\
@@ -234,11 +239,17 @@ union offset_union {
 	do {							\
 		unsigned int err = 0, v = val, a = addr;	\
 		__asm__( FIRST_BYTE_32				\
-		"1:	"ins"	%1, [%2], #1\n"			\
+	 ARM(	"1:	"ins"	%1, [%2], #1\n"	)		\
+	 THUMB(	"1:	"ins"	%1, [%2]\n"	)		\
+	 THUMB(	"	add	%2, %2, #1\n"	)		\
 		"	mov	%1, %1, "NEXT_BYTE"\n"		\
-		"2:	"ins"	%1, [%2], #1\n"			\
+	 ARM(	"2:	"ins"	%1, [%2], #1\n"	)		\
+	 THUMB(	"2:	"ins"	%1, [%2]\n"	)		\
+	 THUMB(	"	add	%2, %2, #1\n"	)		\
 		"	mov	%1, %1, "NEXT_BYTE"\n"		\
-		"3:	"ins"	%1, [%2], #1\n"			\
+	 ARM(	"3:	"ins"	%1, [%2], #1\n"	)		\
+	 THUMB(	"3:	"ins"	%1, [%2]\n"	)		\
+	 THUMB(	"	add	%2, %2, #1\n"	)		\
 		"	mov	%1, %1, "NEXT_BYTE"\n"		\
 		"4:	"ins"	%1, [%2]\n"			\
 		"5:\n"						\
diff --git a/arch/arm/mm/cache-v7.S b/arch/arm/mm/cache-v7.S
index 35ffc4d..8a265ac 100644
--- a/arch/arm/mm/cache-v7.S
+++ b/arch/arm/mm/cache-v7.S
@@ -10,6 +10,8 @@
  *
  *  This is the "shell" of the ARMv7 processor support.
  */
+#include <asm/unified.h>
+
 #include <linux/linkage.h>
 #include <linux/init.h>
 #include <asm/assembler.h>
@@ -21,7 +23,7 @@
  *
  *	Flush the whole D-cache.
  *
- *	Corrupted registers: r0-r5, r7, r9-r11
+ *	Corrupted registers: r0-r7, r9-r11 (r6 only in Thumb mode)
  *
  *	- mm    - mm_struct describing address space
  */
@@ -50,8 +52,12 @@ loop1:
 loop2:
 	mov	r9, r4				@ create working copy of max way size
 loop3:
-	orr	r11, r10, r9, lsl r5		@ factor way and cache number into r11
-	orr	r11, r11, r7, lsl r2		@ factor index number into r11
+ ARM(	orr	r11, r10, r9, lsl r5	)	@ factor way and cache number into r11
+ THUMB(	lsl	r6, r9, r5		)
+ THUMB(	orr	r11, r10, r6		)	@ factor way and cache number into r11
+ ARM(	orr	r11, r11, r7, lsl r2	)	@ factor index number into r11
+ THUMB(	lsl	r6, r7, r2		)
+ THUMB(	orr	r11, r11, r6		)	@ factor index number into r11
 	mcr	p15, 0, r11, c7, c14, 2		@ clean & invalidate by set/way
 	subs	r9, r9, #1			@ decrement the way
 	bge	loop3
@@ -66,6 +72,7 @@ finished:
 	mcr	p15, 2, r10, c0, c0, 0		@ select current cache level in cssr
 	isb
 	mov	pc, lr
+ENDPROC(v7_flush_dcache_all)
 
 /*
  *	v7_flush_cache_all()
@@ -79,12 +86,15 @@ finished:
  *
  */
 ENTRY(v7_flush_kern_cache_all)
-	stmfd	sp!, {r4-r5, r7, r9-r11, lr}
+ ARM(	stmfd	sp!, {r4-r5, r7, r9-r11, lr}	)
+ THUMB(	stmfd	sp!, {r4-r7, r9-r11, lr}	)
 	bl	v7_flush_dcache_all
 	mov	r0, #0
 	mcr	p15, 0, r0, c7, c5, 0		@ I+BTB cache invalidate
-	ldmfd	sp!, {r4-r5, r7, r9-r11, lr}
+ ARM(	ldmfd	sp!, {r4-r5, r7, r9-r11, lr}	)
+ THUMB(	ldmfd	sp!, {r4-r7, r9-r11, lr}	)
 	mov	pc, lr
+ENDPROC(v7_flush_kern_cache_all)
 
 /*
  *	v7_flush_cache_all()
@@ -110,6 +120,8 @@ ENTRY(v7_flush_user_cache_all)
  */
 ENTRY(v7_flush_user_cache_range)
 	mov	pc, lr
+ENDPROC(v7_flush_user_cache_all)
+ENDPROC(v7_flush_user_cache_range)
 
 /*
  *	v7_coherent_kern_range(start,end)
@@ -155,6 +167,8 @@ ENTRY(v7_coherent_user_range)
 	dsb
 	isb
 	mov	pc, lr
+ENDPROC(v7_coherent_kern_range)
+ENDPROC(v7_coherent_user_range)
 
 /*
  *	v7_flush_kern_dcache_page(kaddr)
@@ -174,6 +188,7 @@ ENTRY(v7_flush_kern_dcache_page)
 	blo	1b
 	dsb
 	mov	pc, lr
+ENDPROC(v7_flush_kern_dcache_page)
 
 /*
  *	v7_dma_inv_range(start,end)
@@ -190,10 +205,12 @@ ENTRY(v7_dma_inv_range)
 	sub	r3, r2, #1
 	tst	r0, r3
 	bic	r0, r0, r3
+	it	ne
 	mcrne	p15, 0, r0, c7, c14, 1		@ clean & invalidate D / U line
 
 	tst	r1, r3
 	bic	r1, r1, r3
+	it	ne
 	mcrne	p15, 0, r1, c7, c14, 1		@ clean & invalidate D / U line
 1:
 	mcr	p15, 0, r0, c7, c6, 1		@ invalidate D / U line
@@ -202,6 +219,7 @@ ENTRY(v7_dma_inv_range)
 	blo	1b
 	dsb
 	mov	pc, lr
+ENDPROC(v7_dma_inv_range)
 
 /*
  *	v7_dma_clean_range(start,end)
@@ -219,6 +237,7 @@ ENTRY(v7_dma_clean_range)
 	blo	1b
 	dsb
 	mov	pc, lr
+ENDPROC(v7_dma_clean_range)
 
 /*
  *	v7_dma_flush_range(start,end)
@@ -236,6 +255,7 @@ ENTRY(v7_dma_flush_range)
 	blo	1b
 	dsb
 	mov	pc, lr
+ENDPROC(v7_dma_flush_range)
 
 	__INITDATA
 
diff --git a/arch/arm/mm/consistent-nommu.c b/arch/arm/mm/consistent-nommu.c
new file mode 100644
index 0000000..985b55d
--- /dev/null
+++ b/arch/arm/mm/consistent-nommu.c
@@ -0,0 +1,208 @@
+/*
+ *  linux/arch/arm/mm/consistent.c
+ *
+ *  Copyright (C) 2000-2004 Russell King
+ *  Modified by Catalin Marinas for MMU-less support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ *  DMA uncached mapping support.
+ */
+#include <linux/slab.h>
+#include <linux/errno.h>
+#include <linux/list.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/dma-mapping.h>
+
+#include <asm/memory.h>
+#include <asm/cacheflush.h>
+#include <asm/sizes.h>
+
+static void *
+__dma_alloc(struct device *dev, size_t size, dma_addr_t *handle, gfp_t gfp)
+{
+	struct page *page, *end;
+	unsigned long order;
+	u64 mask = ISA_DMA_THRESHOLD;
+	void *ptr;
+
+	if (dev) {
+		mask = dev->coherent_dma_mask;
+
+		/*
+		 * Sanity check the DMA mask - it must be non-zero, and
+		 * must be able to be satisfied by a DMA allocation.
+		 */
+		if (mask == 0) {
+			dev_warn(dev, "coherent DMA mask is unset\n");
+			goto no_page;
+		}
+
+		if ((~mask) & ISA_DMA_THRESHOLD) {
+			dev_warn(dev, "coherent DMA mask %#llx is smaller "
+				 "than system GFP_DMA mask %#llx\n",
+				 mask, (unsigned long long)ISA_DMA_THRESHOLD);
+			goto no_page;
+		}
+	}
+
+	size = PAGE_ALIGN(size);
+	order = get_order(size);
+
+	if (mask != 0xffffffff)
+		gfp |= GFP_DMA;
+
+	page = alloc_pages(gfp, order);
+	if (!page)
+		goto no_page;
+
+	/*
+	 * Invalidate any data that might be lurking in the
+	 * kernel direct-mapped region for device DMA.
+	 */
+	ptr = page_address(page);
+	memset(ptr, 0, size);
+	dmac_flush_range(ptr, ptr + size);
+	outer_flush_range(__pa(ptr), __pa(ptr) + size);
+
+	end = page + (1 << order);
+
+	split_page(page, order);
+
+	/*
+	 * Set the "dma handle"
+	 */
+	*handle = page_to_dma(dev, page);
+
+	do {
+		/*
+		 * x86 does not mark the pages reserved...
+		 */
+		SetPageReserved(page);
+		page++;
+	} while (size -= PAGE_SIZE);
+
+	/*
+	 * Free the otherwise unused pages.
+	 */
+	while (page < end) {
+		__free_page(page);
+		page++;
+	}
+
+ 	return ptr;
+
+ no_page:
+	*handle = ~0;
+	return NULL;
+}
+
+/*
+ * Allocate DMA-coherent memory space and return both the kernel and
+ * bus address for that space.
+ */
+void *
+dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *handle, gfp_t gfp)
+{
+	return __dma_alloc(dev, size, handle, gfp);
+}
+EXPORT_SYMBOL(dma_alloc_coherent);
+
+/*
+ * Allocate a writecombining region, in the same way as
+ * dma_alloc_coherent above.
+ */
+void *
+dma_alloc_writecombine(struct device *dev, size_t size, dma_addr_t *handle, gfp_t gfp)
+{
+	return __dma_alloc(dev, size, handle, gfp);
+}
+EXPORT_SYMBOL(dma_alloc_writecombine);
+
+static int dma_mmap(struct device *dev, struct vm_area_struct *vma,
+		    void *cpu_addr, dma_addr_t dma_addr, size_t size)
+{
+	unsigned long user_size;
+	int ret = -ENXIO;
+
+	user_size = (vma->vm_end - vma->vm_start) >> PAGE_SHIFT;
+
+	vma->vm_flags |= VM_RESERVED;
+	ret = remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff,
+			      user_size << PAGE_SHIFT, vma->vm_page_prot);
+
+	return ret;
+}
+
+int dma_mmap_coherent(struct device *dev, struct vm_area_struct *vma,
+		      void *cpu_addr, dma_addr_t dma_addr, size_t size)
+{
+	vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+	return dma_mmap(dev, vma, cpu_addr, dma_addr, size);
+}
+EXPORT_SYMBOL(dma_mmap_coherent);
+
+int dma_mmap_writecombine(struct device *dev, struct vm_area_struct *vma,
+			  void *cpu_addr, dma_addr_t dma_addr, size_t size)
+{
+	vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
+	return dma_mmap(dev, vma, cpu_addr, dma_addr, size);
+}
+EXPORT_SYMBOL(dma_mmap_writecombine);
+
+/*
+ * free a page as defined by the above mapping.
+ * Must not be called with IRQs disabled.
+ */
+void dma_free_coherent(struct device *dev, size_t size, void *cpu_addr, dma_addr_t handle)
+{
+	struct page *page;
+
+	WARN_ON(irqs_disabled());
+
+	size = PAGE_ALIGN(size);
+	page = virt_to_page(cpu_addr);
+
+	do {
+		/*
+		 * x86 does not mark the pages reserved...
+		 */
+		ClearPageReserved(page);
+
+		__free_page(page);
+		page++;
+	} while (size -= PAGE_SIZE);
+}
+EXPORT_SYMBOL(dma_free_coherent);
+
+/*
+ * Make an area consistent for devices.
+ * Note: Drivers should NOT use this function directly, as it will break
+ * platforms with CONFIG_DMABOUNCE.
+ * Use the driver DMA support - see dma-mapping.h (dma_sync_*)
+ */
+void consistent_sync(const void *start, size_t size, int direction)
+{
+	const void *end = start + size;
+
+	switch (direction) {
+	case DMA_FROM_DEVICE:		/* invalidate only */
+		dmac_inv_range(start, end);
+		outer_inv_range(__pa(start), __pa(end));
+		break;
+	case DMA_TO_DEVICE:		/* writeback only */
+		dmac_clean_range(start, end);
+		outer_clean_range(__pa(start), __pa(end));
+		break;
+	case DMA_BIDIRECTIONAL:		/* writeback and invalidate */
+		dmac_flush_range(start, end);
+		outer_flush_range(__pa(start), __pa(end));
+		break;
+	default:
+		BUG();
+	}
+}
+EXPORT_SYMBOL(consistent_sync);
diff --git a/arch/arm/mm/fault.c b/arch/arm/mm/fault.c
index 28ad7ab..549cf28 100644
--- a/arch/arm/mm/fault.c
+++ b/arch/arm/mm/fault.c
@@ -21,6 +21,7 @@
 
 #include "fault.h"
 
+#ifdef CONFIG_MMU
 
 #ifdef CONFIG_KPROBES
 static inline int notify_page_fault(struct pt_regs *regs, unsigned int fsr)
@@ -95,6 +96,10 @@ void show_pte(struct mm_struct *mm, unsigned long addr)
 
 	printk("\n");
 }
+#else					/* CONFIG_MMU */
+void show_pte(struct mm_struct *mm, unsigned long addr)
+{ }
+#endif					/* CONFIG_MMU */
 
 /*
  * Oops.  The kernel tried to access some page that wasn't present.
@@ -169,6 +174,7 @@ void do_bad_area(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
 		__do_kernel_fault(mm, addr, fsr, regs);
 }
 
+#ifdef CONFIG_MMU
 #define VM_FAULT_BADMAP		0x010000
 #define VM_FAULT_BADACCESS	0x020000
 
@@ -320,6 +326,13 @@ no_context:
 	__do_kernel_fault(mm, addr, fsr, regs);
 	return 0;
 }
+#else					/* CONFIG_MMU */
+static int
+do_page_fault(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
+{
+	return 0;
+}
+#endif					/* CONFIG_MMU */
 
 /*
  * First Level Translation Fault Handler
@@ -338,6 +351,7 @@ no_context:
  * interrupt or a critical region, and should only copy the information
  * from the master page table, nothing more.
  */
+#ifdef CONFIG_MMU
 static int __kprobes
 do_translation_fault(unsigned long addr, unsigned int fsr,
 		     struct pt_regs *regs)
@@ -376,6 +390,14 @@ bad_area:
 	do_bad_area(addr, fsr, regs);
 	return 0;
 }
+#else					/* CONFIG_MMU */
+static int
+do_translation_fault(unsigned long addr, unsigned int fsr,
+		     struct pt_regs *regs)
+{
+	return 0;
+}
+#endif					/* CONFIG_MMU */
 
 /*
  * Some section permission faults need to be handled gracefully.
diff --git a/arch/arm/mm/nommu.c b/arch/arm/mm/nommu.c
index 63c62fd..793974d 100644
--- a/arch/arm/mm/nommu.c
+++ b/arch/arm/mm/nommu.c
@@ -34,6 +34,7 @@ void __init reserve_node_zero(pg_data_t *pgdat)
 			BOOTMEM_DEFAULT);
 #endif
 
+#ifndef CONFIG_CPU_V7M
 	/*
 	 * Register the exception vector page.
 	 * some architectures which the DRAM is the exception vector to trap,
@@ -41,6 +42,7 @@ void __init reserve_node_zero(pg_data_t *pgdat)
 	 */
 	reserve_bootmem_node(pgdat, CONFIG_VECTORS_BASE, PAGE_SIZE,
 			BOOTMEM_DEFAULT);
+#endif
 }
 
 /*
diff --git a/arch/arm/mm/proc-macros.S b/arch/arm/mm/proc-macros.S
index b131500..4b84d98 100644
--- a/arch/arm/mm/proc-macros.S
+++ b/arch/arm/mm/proc-macros.S
@@ -4,6 +4,7 @@
  *  VMA_VM_FLAGS
  *  VM_EXEC
  */
+#include <asm/unified.h>
 #include <asm/asm-offsets.h>
 #include <asm/thread_info.h>
 
diff --git a/arch/arm/mm/proc-v7.S b/arch/arm/mm/proc-v7.S
index b49f9a4..5c9523b 100644
--- a/arch/arm/mm/proc-v7.S
+++ b/arch/arm/mm/proc-v7.S
@@ -9,6 +9,8 @@
  *
  *  This is the "shell" of the ARMv7 processor support.
  */
+#include <asm/unified.h>
+
 #include <linux/linkage.h>
 #include <asm/assembler.h>
 #include <asm/asm-offsets.h>
@@ -25,9 +27,11 @@
 
 ENTRY(cpu_v7_proc_init)
 	mov	pc, lr
+ENDPROC(cpu_v7_proc_init)
 
 ENTRY(cpu_v7_proc_fin)
 	mov	pc, lr
+ENDPROC(cpu_v7_proc_fin)
 
 /*
  *	cpu_v7_reset(loc)
@@ -43,6 +47,7 @@ ENTRY(cpu_v7_proc_fin)
 	.align	5
 ENTRY(cpu_v7_reset)
 	mov	pc, r0
+ENDPROC(cpu_v7_reset)
 
 /*
  *	cpu_v7_do_idle()
@@ -52,8 +57,9 @@ ENTRY(cpu_v7_reset)
  *	IRQs are already disabled.
  */
 ENTRY(cpu_v7_do_idle)
-	.long	0xe320f003			@ ARM V7 WFI instruction
+	wfi
 	mov	pc, lr
+ENDPROC(cpu_v7_do_idle)
 
 ENTRY(cpu_v7_dcache_clean_area)
 #ifndef TLB_CAN_READ_FROM_L1_CACHE
@@ -65,6 +71,7 @@ ENTRY(cpu_v7_dcache_clean_area)
 	dsb
 #endif
 	mov	pc, lr
+ENDPROC(cpu_v7_dcache_clean_area)
 
 /*
  *	cpu_v7_switch_mm(pgd_phys, tsk)
@@ -89,6 +96,7 @@ ENTRY(cpu_v7_switch_mm)
 	isb
 #endif
 	mov	pc, lr
+ENDPROC(cpu_v7_switch_mm)
 
 /*
  *	cpu_v7_set_pte_ext(ptep, pte)
@@ -112,7 +120,9 @@ ENTRY(cpu_v7_switch_mm)
  */
 ENTRY(cpu_v7_set_pte_ext)
 #ifdef CONFIG_MMU
-	str	r1, [r0], #-2048		@ linux version
+ ARM(	str	r1, [r0], #-2048	)	@ linux version
+ THUMB(	str	r1, [r0]		)	@ linux version
+ THUMB(	sub	r0, r0, #2048		)
 
 	bic	r3, r1, #0x000003f0
 	bic	r3, r3, #0x00000003
@@ -120,27 +130,33 @@ ENTRY(cpu_v7_set_pte_ext)
 	orr	r3, r3, #PTE_EXT_AP0 | 2
 
 	tst	r1, #L_PTE_WRITE
+	ite	ne
 	tstne	r1, #L_PTE_DIRTY
 	orreq	r3, r3, #PTE_EXT_APX
 
 	tst	r1, #L_PTE_USER
+	ittt	ne
 	orrne	r3, r3, #PTE_EXT_AP1
 	tstne	r3, #PTE_EXT_APX
 	bicne	r3, r3, #PTE_EXT_APX | PTE_EXT_AP0
 
 	tst	r1, #L_PTE_YOUNG
+	it	eq
 	biceq	r3, r3, #PTE_EXT_APX | PTE_EXT_AP_MASK
 
 	tst	r1, #L_PTE_EXEC
+	it	eq
 	orreq	r3, r3, #PTE_EXT_XN
 
 	tst	r1, #L_PTE_PRESENT
+	it	eq
 	moveq	r3, #0
 
 	str	r3, [r0]
 	mcr	p15, 0, r0, c7, c10, 1		@ flush_pte
 #endif
 	mov	pc, lr
+ENDPROC(cpu_v7_set_pte_ext)
 
 cpu_v7_name:
 	.ascii	"ARMv7 Processor"
@@ -188,16 +204,19 @@ __v7_setup:
 	bic	r0, r0, r5			@ clear bits them
 	orr	r0, r0, r6			@ set them
 	mov	pc, lr				@ return to head.S:__ret
+ENDPROC(__v7_setup)
 
+	.align	2
 	/*
-	 *         V X F   I D LR
-	 * .... ...E PUI. .T.T 4RVI ZFRS BLDP WCAM
+	 *  T      V X F   I D LR
+	 * .E.. ...E PUI. .T.T 4RVI ZFRS BLDP WCAM
 	 * rrrr rrrx xxx0 0101 xxxx xxxx x111 xxxx < forced
 	 *         0 110       0011 1.00 .111 1101 < we want
 	 */
 	.type	v7_crval, #object
 v7_crval:
-	crval	clear=0x0120c302, mmuset=0x00c0387d, ucset=0x00c0187c
+ ARM(	crval	clear=0x0120c302, mmuset=0x00c0387d, ucset=0x00c0187c	)
+ THUMB(	crval	clear=0x0120c302, mmuset=0x40c0387d, ucset=0x40c0187c	)
 
 __v7_setup_stack:
 	.space	4 * 11				@ 11 registers
diff --git a/arch/arm/mm/proc-v7m.S b/arch/arm/mm/proc-v7m.S
new file mode 100644
index 0000000..fc283aa
--- /dev/null
+++ b/arch/arm/mm/proc-v7m.S
@@ -0,0 +1,192 @@
+/*
+ *  linux/arch/arm/mm/proc-v7m.S
+ *
+ *  Copyright (C) 2008 ARM Ltd.
+ *  Copyright (C) 2001 Deep Blue Solutions Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ *  This is the "shell" of the ARMv7-M processor support.
+ */
+#include <asm/unified.h>
+
+#include <linux/linkage.h>
+#include <asm/assembler.h>
+#include <asm/asm-offsets.h>
+#include <asm/elf.h>
+#include <asm/pgtable-hwdef.h>
+#include <asm/pgtable.h>
+
+#include "proc-macros.S"
+
+ENTRY(cpu_v7m_proc_init)
+	mov	pc, lr
+ENDPROC(cpu_v7m_proc_init)
+
+ENTRY(cpu_v7m_proc_fin)
+	mov	pc, lr
+ENDPROC(cpu_v7m_proc_fin)
+
+/*
+ *	cpu_v7m_reset(loc)
+ *
+ *	Perform a soft reset of the system.  Put the CPU into the
+ *	same state as it would be if it had been reset, and branch
+ *	to what would be the reset vector.
+ *
+ *	- loc   - location to jump to for soft reset
+ *
+ *	It is assumed that:
+ */
+	.align	5
+ENTRY(cpu_v7m_reset)
+	mov	pc, r0
+ENDPROC(cpu_v7m_reset)
+
+/*
+ *	cpu_v7m_do_idle()
+ *
+ *	Idle the processor (eg, wait for interrupt).
+ *
+ *	IRQs are already disabled.
+ */
+ENTRY(cpu_v7m_do_idle)
+	wfi
+	mov	pc, lr
+ENDPROC(cpu_v7m_do_idle)
+
+ENTRY(cpu_v7m_dcache_clean_area)
+	mov	pc, lr
+ENDPROC(cpu_v7m_dcache_clean_area)
+
+/*
+ *	cpu_v7m_switch_mm(pgd_phys, tsk)
+ *
+ *	Set the translation table base pointer to be pgd_phys
+ *
+ *	- pgd_phys - physical address of new TTB
+ *
+ *	It is assumed that:
+ *	- we are not using split page tables
+ */
+ENTRY(cpu_v7m_switch_mm)
+	mov	pc, lr
+ENDPROC(cpu_v7m_switch_mm)
+
+ENTRY(cpu_v7m_set_pte_ext)
+	mov	pc, lr
+ENDPROC(cpu_v7m_set_pte_ext)
+
+cpu_v7m_name:
+	.ascii	"ARMv7-M Processor"
+	.align
+
+	.section ".text.init", #alloc, #execinstr
+
+/*
+ *	__v7m_setup
+ *
+ *	Initialise TLB, Caches, and MMU state ready to switch the MMU
+ *	on.  Return in r0 the new CP15 C1 control register setting.
+ *
+ *	We automatically detect if we have a Harvard cache, and use the
+ *	Harvard cache control instructions insead of the unified cache
+ *	control instructions.
+ *
+ *	This should be able to cover all ARMv7-M cores.
+ *
+ *	It is assumed that:
+ *	- cache type register is implemented
+ */
+__v7m_setup:
+	@ Configure the vector table base address
+	ldr	r0, =0xe000ed08		@ vector table base address
+	ldr	r12, =vector_table
+	str	r12, [r0]
+
+	@ Lower the priority of the SVC and PendSV exceptions
+	ldr	r0, =0xe000ed1c
+	mov	r5, #0x80000000
+	str	r5, [r0]		@ set SVC priority
+	ldr	r0, =0xe000ed20
+	mov	r5, #0x00800000
+	str	r5, [r0]		@ set PendSV priority
+
+	@ SVC to run the kernel in this mode
+	badr	r0, 1f
+	ldr	r5, [r12, #11 * 4]	@ read the SVC vector entry
+	str	r0, [r12, #11 * 4]	@ write the temporary SVC vector entry
+	mov	r6, lr			@ save LR
+	mov	r7, sp			@ save SP
+	ldr	sp, =__v7m_setup_stack_top
+	cpsie	i
+	svc	#0
+1:	cpsid	i
+	str	r5, [r12, #11 * 4]	@ restore the original SVC vector entry
+	mov	lr, r6			@ restore LR
+	mov	sp, r7			@ restore SP
+
+	@ Special-purpose control register
+	mov	r0, #1
+	msr	control, r0		@ Thread mode has unpriviledged access
+
+	@ Configure the System Control Register
+	ldr	r0, =0xe000ed10		@ system control register
+	ldr	r12, [r0]
+	orr	r12, #1 << 9		@ STKALIGN
+	str	r12, [r0]
+	mov	pc, lr
+ENDPROC(__v7m_setup)
+
+	.align	2
+	.type	v7m_processor_functions, #object
+ENTRY(v7m_processor_functions)
+	.word	v7m_early_abort
+	.word	cpu_v7m_proc_init
+	.word	cpu_v7m_proc_fin
+	.word	cpu_v7m_reset
+	.word	cpu_v7m_do_idle
+	.word	cpu_v7m_dcache_clean_area
+	.word	cpu_v7m_switch_mm
+	.word	cpu_v7m_set_pte_ext
+	.word	pabort_noifar
+	.size	v7m_processor_functions, . - v7m_processor_functions
+
+	.type	cpu_arch_name, #object
+cpu_arch_name:
+	.asciz	"armv7m"
+	.size	cpu_arch_name, . - cpu_arch_name
+
+	.type	cpu_elf_name, #object
+cpu_elf_name:
+	.asciz	"v7m"
+	.size	cpu_elf_name, . - cpu_elf_name
+	.align
+
+	.section ".proc.info.init", #alloc, #execinstr
+
+	/*
+	 * Match any ARMv7-M processor core.
+	 */
+	.type	__v7m_proc_info, #object
+__v7m_proc_info:
+	.long	0x000f0000		@ Required ID value
+	.long	0x000f0000		@ Mask for ID
+	.long   0			@ proc_info_list.__cpu_mm_mmu_flags
+	.long   0			@ proc_info_list.__cpu_io_mmu_flags
+	b	__v7m_setup		@ proc_info_list.__cpu_flush
+	.long	cpu_arch_name
+	.long	cpu_elf_name
+	.long	HWCAP_SWP|HWCAP_HALF|HWCAP_THUMB|HWCAP_FAST_MULT|HWCAP_EDSP
+	.long	cpu_v7m_name
+	.long	v7m_processor_functions	@ proc_info_list.proc
+	.long	0			@ proc_info_list.tlb
+	.long	0			@ proc_info_list.user
+	.long	0			@ proc_info_list.cache
+	.size	__v7m_proc_info, . - __v7m_proc_info
+
+__v7m_setup_stack:
+	.space	4 * 8				@ 8 registers
+__v7m_setup_stack_top:
diff --git a/arch/arm/mm/tlb-v7.S b/arch/arm/mm/tlb-v7.S
index b56dda8..68e3e7a 100644
--- a/arch/arm/mm/tlb-v7.S
+++ b/arch/arm/mm/tlb-v7.S
@@ -11,6 +11,8 @@
  *  ARM architecture version 6 TLB handling functions.
  *  These assume a split I/D TLB.
  */
+#include <asm/unified.h>
+
 #include <linux/linkage.h>
 #include <asm/asm-offsets.h>
 #include <asm/page.h>
@@ -43,6 +45,7 @@ ENTRY(v7wbi_flush_user_tlb_range)
 1:
 	mcr	p15, 0, r0, c8, c6, 1		@ TLB invalidate D MVA (was 1)
 	tst	r2, #VM_EXEC			@ Executable area ?
+	it	ne
 	mcrne	p15, 0, r0, c8, c5, 1		@ TLB invalidate I MVA (was 1)
 	add	r0, r0, #PAGE_SZ
 	cmp	r0, r1
@@ -51,6 +54,7 @@ ENTRY(v7wbi_flush_user_tlb_range)
 	mcr	p15, 0, ip, c7, c5, 6		@ flush BTAC/BTB
 	dsb
 	mov	pc, lr
+ENDPROC(v7wbi_flush_user_tlb_range)
 
 /*
  *	v7wbi_flush_kern_tlb_range(start,end)
@@ -77,6 +81,7 @@ ENTRY(v7wbi_flush_kern_tlb_range)
 	dsb
 	isb
 	mov	pc, lr
+ENDPROC(v7wbi_flush_kern_tlb_range)
 
 	.section ".text.init", #alloc, #execinstr
 
diff --git a/arch/arm/vfp/entry.S b/arch/arm/vfp/entry.S
index 806ce26..b8a1498 100644
--- a/arch/arm/vfp/entry.S
+++ b/arch/arm/vfp/entry.S
@@ -15,24 +15,27 @@
  *  r10 = thread_info structure
  *  lr  = failure return
  */
+#include <asm/unified.h>
+
 #include <linux/linkage.h>
 #include <linux/init.h>
 #include <asm/asm-offsets.h>
 #include <asm/assembler.h>
 #include <asm/vfpmacros.h>
 
-	.globl	do_vfp
-do_vfp:
+ENTRY(do_vfp)
 	enable_irq
  	ldr	r4, .LCvfp
 	ldr	r11, [r10, #TI_CPU]	@ CPU number
 	add	r10, r10, #TI_VFPSTATE	@ r10 = workspace
 	ldr	pc, [r4]		@ call VFP entry point
+ENDPROC(do_vfp)
 
 ENTRY(vfp_null_entry)
 	mov	pc, lr
 ENDPROC(vfp_null_entry)
 
+	.align	2
 .LCvfp:
 	.word	vfp_vector
 
@@ -40,12 +43,13 @@ ENDPROC(vfp_null_entry)
 @ failure to the VFP initialisation code.
 
 	__INIT
-	.globl	vfp_testing_entry
-vfp_testing_entry:
+ENTRY(vfp_testing_entry)
 	ldr	r0, VFP_arch_address
 	str	r5, [r0]		@ known non-zero value
 	mov	pc, r9			@ we have handled the fault
+ENDPROC(vfp_testing_entry)
 
+	.align	2
 VFP_arch_address:
 	.word	VFP_arch
 
diff --git a/arch/arm/vfp/vfp.h b/arch/arm/vfp/vfp.h
index c85860b..f0daa8b 100644
--- a/arch/arm/vfp/vfp.h
+++ b/arch/arm/vfp/vfp.h
@@ -8,6 +8,7 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
+#include <asm/unified.h>
 
 static inline u32 vfp_shiftright32jamming(u32 val, unsigned int shift)
 {
@@ -37,6 +38,7 @@ static inline u32 vfp_hi64to32jamming(u64 val)
 
 	asm(
 	"cmp	%Q1, #1		@ vfp_hi64to32jamming\n\t"
+	"ite	cc\n\t"
 	"movcc	%0, %R1\n\t"
 	"orrcs	%0, %R1, #1"
 	: "=r" (v) : "r" (val) : "cc");
diff --git a/arch/arm/vfp/vfphw.S b/arch/arm/vfp/vfphw.S
index 353f9e5..dc0870a 100644
--- a/arch/arm/vfp/vfphw.S
+++ b/arch/arm/vfp/vfphw.S
@@ -14,6 +14,8 @@
  * r10 points at the start of the private FP workspace in the thread structure
  * sp points to a struct pt_regs (as defined in include/asm/proc/ptrace.h)
  */
+#include <asm/unified.h>
+
 #include <asm/thread_info.h>
 #include <asm/vfpmacros.h>
 #include "../kernel/entry-header.S"
@@ -68,8 +70,7 @@
 @  r11 = CPU number
 @  lr  = failure return
 
-	.globl	vfp_support_entry
-vfp_support_entry:
+ENTRY(vfp_support_entry)
 	DBGSTR3	"instr %08x pc %08x state %p", r0, r2, r10
 
 	VFPFMRX	r1, FPEXC		@ Is the VFP enabled?
@@ -102,8 +103,10 @@ vfp_support_entry:
 	VFPFSTMIA r4, r5		@ save the working registers
 	VFPFMRX	r5, FPSCR		@ current status
 	tst	r1, #FPEXC_EX		@ is there additional state to save?
+	itt	ne
 	VFPFMRX	r6, FPINST, NE		@ FPINST (only if FPEXC.EX is set)
 	tstne	r1, #FPEXC_FP2V		@ is there an FPINST2 to read?
+	it	ne
 	VFPFMRX	r8, FPINST2, NE		@ FPINST2 if needed (and present)
 	stmia	r4, {r1, r5, r6, r8}	@ save FPEXC, FPSCR, FPINST, FPINST2
 					@ and point r4 at the word at the
@@ -118,8 +121,10 @@ no_old_VFP_process:
 					@ FPEXC is in a safe state
 	ldmia	r10, {r1, r5, r6, r8}	@ load FPEXC, FPSCR, FPINST, FPINST2
 	tst	r1, #FPEXC_EX		@ is there additional state to restore?
+	itt	ne
 	VFPFMXR	FPINST, r6, NE		@ restore FPINST (only if FPEXC.EX is set)
 	tstne	r1, #FPEXC_FP2V		@ is there an FPINST2 to write?
+	it	ne
 	VFPFMXR	FPINST2, r8, NE		@ FPINST2 if needed (and present)
 	VFPFMXR	FPSCR, r5		@ restore status
 
@@ -165,11 +170,10 @@ process_exception:
 					@ code will raise an exception if
 					@ required. If not, the user code will
 					@ retry the faulted instruction
+ENDPROC(vfp_support_entry)
 
 #ifdef CONFIG_SMP
-	.globl	vfp_save_state
-	.type	vfp_save_state, %function
-vfp_save_state:
+ENTRY(vfp_save_state)
 	@ Save the current VFP state
 	@ r0 - save location
 	@ r1 - FPEXC
@@ -177,42 +181,50 @@ vfp_save_state:
 	VFPFSTMIA r0, r2		@ save the working registers
 	VFPFMRX	r2, FPSCR		@ current status
 	tst	r1, #FPEXC_EX		@ is there additional state to save?
+	itt	ne
 	VFPFMRX	r3, FPINST, NE		@ FPINST (only if FPEXC.EX is set)
 	tstne	r1, #FPEXC_FP2V		@ is there an FPINST2 to read?
+	it	ne
 	VFPFMRX	r12, FPINST2, NE	@ FPINST2 if needed (and present)
 	stmia	r0, {r1, r2, r3, r12}	@ save FPEXC, FPSCR, FPINST, FPINST2
 	mov	pc, lr
+ENDPROC(vfp_save_state)
 #endif
 
 last_VFP_context_address:
 	.word	last_VFP_context
 
-	.globl	vfp_get_float
-vfp_get_float:
-	add	pc, pc, r0, lsl #3
-	mov	r0, r0
+	.macro	tbl_branch, base, tmp, shift
+ ARM(	add	pc, pc, \base, lsl \shift	)
+ ARM(	mov	r0, r0				)
+ THUMB(	adr	\tmp, 1f			)
+ THUMB(	add	\tmp, \tmp, \base, lsl \shift	)
+ THUMB(	mov	pc, \tmp			)
+1:
+	.endm
+
+ENTRY(vfp_get_float)
+	tbl_branch r0, r3, #3
 	.irp	dr,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
 	mrc	p10, 0, r0, c\dr, c0, 0	@ fmrs	r0, s0
 	mov	pc, lr
 	mrc	p10, 0, r0, c\dr, c0, 4	@ fmrs	r0, s1
 	mov	pc, lr
 	.endr
+ENDPROC(vfp_get_float)
 
-	.globl	vfp_put_float
-vfp_put_float:
-	add	pc, pc, r1, lsl #3
-	mov	r0, r0
+ENTRY(vfp_put_float)
+	tbl_branch r1, r3, #3
 	.irp	dr,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
 	mcr	p10, 0, r0, c\dr, c0, 0	@ fmsr	r0, s0
 	mov	pc, lr
 	mcr	p10, 0, r0, c\dr, c0, 4	@ fmsr	r0, s1
 	mov	pc, lr
 	.endr
+ENDPROC(vfp_put_float)
 
-	.globl	vfp_get_double
-vfp_get_double:
-	add	pc, pc, r0, lsl #3
-	mov	r0, r0
+ENTRY(vfp_get_double)
+	tbl_branch r0, r3, #3
 	.irp	dr,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
 	fmrrd	r0, r1, d\dr
 	mov	pc, lr
@@ -229,11 +241,10 @@ vfp_get_double:
 	mov	r0, #0
 	mov	r1, #0
 	mov	pc, lr
+ENDPROC(vfp_get_double)
 
-	.globl	vfp_put_double
-vfp_put_double:
-	add	pc, pc, r2, lsl #3
-	mov	r0, r0
+ENTRY(vfp_put_double)
+	tbl_branch r2, r3, #3
 	.irp	dr,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
 	fmdrr	d\dr, r0, r1
 	mov	pc, lr
@@ -245,3 +256,4 @@ vfp_put_double:
 	mov	pc, lr
 	.endr
 #endif
+ENDPROC(vfp_put_double)
diff --git a/include/asm-arm/arch-integrator/debug-macro.S b/include/asm-arm/arch-integrator/debug-macro.S
index 85b327c..d3de33a 100644
--- a/include/asm-arm/arch-integrator/debug-macro.S
+++ b/include/asm-arm/arch-integrator/debug-macro.S
@@ -14,6 +14,7 @@
 		.macro	addruart,rx
 		mrc	p15, 0, \rx, c1, c0
 		tst	\rx, #1			@ MMU enabled?
+		itee	eq
 		moveq	\rx, #0x16000000	@ physical base address
 		movne	\rx, #0xf0000000	@ virtual base
 		addne	\rx, \rx, #0x16000000 >> 4
diff --git a/include/asm-arm/arch-integrator/entry-macro.S b/include/asm-arm/arch-integrator/entry-macro.S
index 491af1a..e9ee98a 100644
--- a/include/asm-arm/arch-integrator/entry-macro.S
+++ b/include/asm-arm/arch-integrator/entry-macro.S
@@ -26,6 +26,7 @@
 		ldr	\irqstat, [\base, #IRQ_STATUS]		@ get masked status
 		ldr	\base, =IO_ADDRESS(INTEGRATOR_HDR_BASE)
 		teq	\irqstat, #0
+		itt	eq
 		ldreq	\irqstat, [\base, #(INTEGRATOR_HDR_IC_OFFSET+IRQ_STATUS)]
 		moveq	\irqnr, #IRQ_CIC_START
 
diff --git a/include/asm-arm/arch-integrator/hardware.h b/include/asm-arm/arch-integrator/hardware.h
index 6f0947b..4511994 100644
--- a/include/asm-arm/arch-integrator/hardware.h
+++ b/include/asm-arm/arch-integrator/hardware.h
@@ -36,8 +36,12 @@
 #define PCIO_BASE		PCI_IO_VADDR
 #define PCIMEM_BASE		PCI_MEMORY_VADDR
 
+#ifdef CONFIG_MMU
 /* macro to get at IO space when running virtually */
 #define IO_ADDRESS(x) (((x) >> 4) + IO_BASE) 
+#else
+#define IO_ADDRESS(x) (x)
+#endif
 
 #define pcibios_assign_all_busses()	1
 
diff --git a/include/asm-arm/arch-realview/board-eb.h b/include/asm-arm/arch-realview/board-eb.h
index 206f7a7..43406ad 100644
--- a/include/asm-arm/arch-realview/board-eb.h
+++ b/include/asm-arm/arch-realview/board-eb.h
@@ -26,25 +26,25 @@
 /*
  * RealView EB + ARM11MPCore peripheral addresses
  */
-#define REALVIEW_EB_UART0_BASE		0x10009000	/* UART 0 */
-#define REALVIEW_EB_UART1_BASE		0x1000A000	/* UART 1 */
-#define REALVIEW_EB_UART2_BASE		0x1000B000	/* UART 2 */
-#define REALVIEW_EB_UART3_BASE		0x1000C000	/* UART 3 */
-#define REALVIEW_EB_SSP_BASE		0x1000D000	/* Synchronous Serial Port */
-#define REALVIEW_EB_WATCHDOG_BASE	0x10010000	/* watchdog interface */
-#define REALVIEW_EB_TIMER0_1_BASE	0x10011000	/* Timer 0 and 1 */
-#define REALVIEW_EB_TIMER2_3_BASE	0x10012000	/* Timer 2 and 3 */
-#define REALVIEW_EB_GPIO0_BASE		0x10013000	/* GPIO port 0 */
-#define REALVIEW_EB_RTC_BASE		0x10017000	/* Real Time Clock */
-#define REALVIEW_EB_CLCD_BASE		0x10020000	/* CLCD */
-#define REALVIEW_EB_GIC_CPU_BASE	0x10040000	/* Generic interrupt controller CPU interface */
-#define REALVIEW_EB_GIC_DIST_BASE	0x10041000	/* Generic interrupt controller distributor */
-#define REALVIEW_EB_SMC_BASE		0x10080000	/* Static memory controller */
-
-#define REALVIEW_EB_FLASH_BASE		0x40000000
+#define REALVIEW_EB_UART0_BASE		0x40009000	/* UART 0 */
+#define REALVIEW_EB_UART1_BASE		0x4000A000	/* UART 1 */
+#define REALVIEW_EB_UART2_BASE		0x4000B000	/* UART 2 */
+#define REALVIEW_EB_UART3_BASE		0x4000C000	/* UART 3 */
+#define REALVIEW_EB_SSP_BASE		0x4000D000	/* Synchronous Serial Port */
+#define REALVIEW_EB_WATCHDOG_BASE	0x40010000	/* watchdog interface */
+#define REALVIEW_EB_TIMER0_1_BASE	0x40011000	/* Timer 0 and 1 */
+#define REALVIEW_EB_TIMER2_3_BASE	0x40012000	/* Timer 2 and 3 */
+#define REALVIEW_EB_GPIO0_BASE		0x40013000	/* GPIO port 0 */
+#define REALVIEW_EB_RTC_BASE		0x40017000	/* Real Time Clock */
+#define REALVIEW_EB_CLCD_BASE		0x40020000	/* CLCD */
+#define REALVIEW_EB_GIC_CPU_BASE	0x40040000	/* Generic interrupt controller CPU interface */
+#define REALVIEW_EB_GIC_DIST_BASE	0x40041000	/* Generic interrupt controller distributor */
+#define REALVIEW_EB_SMC_BASE		0x40080000	/* Static memory controller */
+
+#define REALVIEW_EB_FLASH_BASE		0x28000000
 #define REALVIEW_EB_FLASH_SIZE		SZ_64M
-#define REALVIEW_EB_ETH_BASE		0x4E000000	/* Ethernet */
-#define REALVIEW_EB_USB_BASE		0x4F000000	/* USB */
+#define REALVIEW_EB_ETH_BASE		0x26000000	/* Ethernet */
+#define REALVIEW_EB_USB_BASE		0x27000000	/* USB */
 
 #ifdef CONFIG_REALVIEW_EB_ARM11MP_REVB
 #define REALVIEW_EB11MP_SCU_BASE	0x10100000	/* SCU registers */
@@ -64,7 +64,11 @@
 #define REALVIEW_EB11MP_SYS_PLD_CTRL1	0x74		/* Register offset for MPCore sysctl */
 #endif
 
+#ifndef CONFIG_CPU_V7M
 #define IRQ_EB_GIC_START	32
+#else
+#define IRQ_EB_GIC_START	0
+#endif
 
 /*
  * RealView EB interrupt sources
@@ -155,7 +159,11 @@
 /*
  * Only define NR_IRQS if less than NR_IRQS_EB
  */
+#ifndef CONFIG_CPU_V7M
 #define NR_IRQS_EB		(IRQ_EB_GIC_START + 96)
+#else
+#define NR_IRQS_EB		(IRQ_EB_GIC_START + 64)
+#endif
 
 #if defined(CONFIG_MACH_REALVIEW_EB) \
 	&& (!defined(NR_IRQS) || (NR_IRQS < NR_IRQS_EB))
diff --git a/include/asm-arm/arch-realview/debug-macro.S b/include/asm-arm/arch-realview/debug-macro.S
index c8c860c..34e6d7a 100644
--- a/include/asm-arm/arch-realview/debug-macro.S
+++ b/include/asm-arm/arch-realview/debug-macro.S
@@ -12,10 +12,15 @@
 */
 
 		.macro	addruart,rx
+#ifdef CONFIG_CPU_V7M
+		mov	\rx,      #0x40000000
+#else
 		mrc	p15, 0, \rx, c1, c0
 		tst	\rx, #1			@ MMU enabled?
+		ite	eq
 		moveq	\rx,      #0x10000000
 		movne	\rx,      #0xf0000000	@ virtual base
+#endif
 		orr	\rx, \rx, #0x00009000
 		.endm
 
diff --git a/include/asm-arm/arch-realview/entry-macro.S b/include/asm-arm/arch-realview/entry-macro.S
index cd26306..7a56668 100644
--- a/include/asm-arm/arch-realview/entry-macro.S
+++ b/include/asm-arm/arch-realview/entry-macro.S
@@ -49,8 +49,11 @@
 		bic     \irqnr, \irqstat, #0x1c00
 
 		cmp     \irqnr, #29
+		it	cc
 		cmpcc	\irqnr, \irqnr
+		it	ne
 		cmpne	\irqnr, \tmp
+		it	cs
 		cmpcs	\irqnr, \irqnr
 
 		.endm
@@ -65,7 +68,9 @@
 		.macro test_for_ipi, irqnr, irqstat, base, tmp
 		bic	\irqnr, \irqstat, #0x1c00
 		cmp	\irqnr, #16
+		it	cc
 		strcc	\irqstat, [\base, #GIC_CPU_EOI]
+		it	cs
 		cmpcs	\irqnr, \irqnr
 		.endm
 
@@ -75,6 +80,7 @@
 		bic	\irqnr, \irqstat, #0x1c00
 		mov 	\tmp, #0
 		cmp	\irqnr, #29
+		itt	eq
 		moveq	\tmp, #1
 		streq	\irqstat, [\base, #GIC_CPU_EOI]
 		cmp	\tmp, #0
diff --git a/include/asm-arm/arch-realview/hardware.h b/include/asm-arm/arch-realview/hardware.h
index 1ee8313..6cc249f 100644
--- a/include/asm-arm/arch-realview/hardware.h
+++ b/include/asm-arm/arch-realview/hardware.h
@@ -25,7 +25,11 @@
 #include <asm/sizes.h>
 
 /* macro to get at IO space when running virtually */
+#ifdef CONFIG_MMU
 #define IO_ADDRESS(x)		(((x) & 0x0fffffff) + 0xf0000000)
+#else
+#define IO_ADDRESS(x)		(x)
+#endif
 #define __io_address(n)		__io(IO_ADDRESS(n))
 
 #endif
diff --git a/include/asm-arm/arch-realview/memory.h b/include/asm-arm/arch-realview/memory.h
index ed370ab..c867bcb 100644
--- a/include/asm-arm/arch-realview/memory.h
+++ b/include/asm-arm/arch-realview/memory.h
@@ -20,10 +20,12 @@
 #ifndef __ASM_ARCH_MEMORY_H
 #define __ASM_ARCH_MEMORY_H
 
+#ifndef CONFIG_CPU_V7M
 /*
  * Physical DRAM offset.
  */
 #define PHYS_OFFSET		UL(0x00000000)
+#endif
 
 /*
  * Virtual view <-> DMA view memory address translations
diff --git a/include/asm-arm/arch-realview/platform.h b/include/asm-arm/arch-realview/platform.h
index 424c0aa..7400225 100644
--- a/include/asm-arm/arch-realview/platform.h
+++ b/include/asm-arm/arch-realview/platform.h
@@ -85,7 +85,7 @@
 #define REALVIEW_SYS_TEST_OSC3_OFFSET        0xCC
 #define REALVIEW_SYS_TEST_OSC4_OFFSET        0xD0
 
-#define REALVIEW_SYS_BASE                    0x10000000
+#define REALVIEW_SYS_BASE                    0x40000000
 #define REALVIEW_SYS_ID                      (REALVIEW_SYS_BASE + REALVIEW_SYS_ID_OFFSET)
 #define REALVIEW_SYS_SW                      (REALVIEW_SYS_BASE + REALVIEW_SYS_SW_OFFSET)
 #define REALVIEW_SYS_LED                     (REALVIEW_SYS_BASE + REALVIEW_SYS_LED_OFFSET)
@@ -174,18 +174,18 @@
 /*
  * RealView common peripheral addresses
  */
-#define REALVIEW_SCTL_BASE            0x10001000	/* System controller */
-#define REALVIEW_I2C_BASE             0x10002000	/* I2C control */
-#define REALVIEW_AACI_BASE            0x10004000	/* Audio */
-#define REALVIEW_MMCI0_BASE           0x10005000	/* MMC interface */
-#define REALVIEW_KMI0_BASE            0x10006000	/* KMI interface */
-#define REALVIEW_KMI1_BASE            0x10007000	/* KMI 2nd interface */
-#define REALVIEW_CHAR_LCD_BASE        0x10008000	/* Character LCD */
-#define REALVIEW_SCI_BASE             0x1000E000	/* Smart card controller */
-#define REALVIEW_GPIO1_BASE           0x10014000	/* GPIO port 1 */
-#define REALVIEW_GPIO2_BASE           0x10015000	/* GPIO port 2 */
-#define REALVIEW_DMC_BASE             0x10018000	/* DMC configuration */
-#define REALVIEW_DMAC_BASE            0x10030000	/* DMA controller */
+#define REALVIEW_SCTL_BASE            0x40001000	/* System controller */
+#define REALVIEW_I2C_BASE             0x40002000	/* I2C control */
+#define REALVIEW_AACI_BASE            0x40004000	/* Audio */
+#define REALVIEW_MMCI0_BASE           0x40005000	/* MMC interface */
+#define REALVIEW_KMI0_BASE            0x40006000	/* KMI interface */
+#define REALVIEW_KMI1_BASE            0x40007000	/* KMI 2nd interface */
+#define REALVIEW_CHAR_LCD_BASE        0x40008000	/* Character LCD */
+#define REALVIEW_SCI_BASE             0x4000E000	/* Smart card controller */
+#define REALVIEW_GPIO1_BASE           0x40014000	/* GPIO port 1 */
+#define REALVIEW_GPIO2_BASE           0x40015000	/* GPIO port 2 */
+#define REALVIEW_DMC_BASE             0x40018000	/* DMC configuration */
+#define REALVIEW_DMAC_BASE            0x40030000	/* DMA controller */
 
 /* PCI space */
 #define REALVIEW_PCI_BASE             0x41000000	/* PCI Interface */
diff --git a/include/asm-arm/assembler.h b/include/asm-arm/assembler.h
index fce8328..31ac9d4 100644
--- a/include/asm-arm/assembler.h
+++ b/include/asm-arm/assembler.h
@@ -81,7 +81,11 @@
  * assumes FIQs are enabled, and that the processor is in SVC mode.
  */
 	.macro	save_and_disable_irqs, oldcpsr
+#ifdef CONFIG_CPU_V7M
+	mrs	\oldcpsr, primask
+#else
 	mrs	\oldcpsr, cpsr
+#endif
 	disable_irq
 	.endm
 
@@ -90,7 +94,11 @@
  * guarantee that this will preserve the flags.
  */
 	.macro	restore_irqs, oldcpsr
+#ifdef CONFIG_CPU_V7M
+	msr	primask, \oldcpsr
+#else
 	msr	cpsr_c, \oldcpsr
+#endif
 	.endm
 
 #define USER(x...)				\
diff --git a/include/asm-arm/atomic.h b/include/asm-arm/atomic.h
index 3b59f94..5dc8219 100644
--- a/include/asm-arm/atomic.h
+++ b/include/asm-arm/atomic.h
@@ -90,6 +90,7 @@ static inline int atomic_cmpxchg(atomic_t *ptr, int old, int new)
 		"ldrex	%1, [%2]\n"
 		"mov	%0, #0\n"
 		"teq	%1, %3\n"
+		"it	eq\n"
 		"strexeq %0, %4, [%2]\n"
 		    : "=&r" (res), "=&r" (oldval)
 		    : "r" (&ptr->counter), "Ir" (old), "r" (new)
diff --git a/include/asm-arm/cacheflush.h b/include/asm-arm/cacheflush.h
index 759a97b..f79cdfe 100644
--- a/include/asm-arm/cacheflush.h
+++ b/include/asm-arm/cacheflush.h
@@ -118,6 +118,14 @@
 //# endif
 #endif
 
+#if defined(CONFIG_CPU_V7M)
+# ifdef _CACHE
+#  error "Multi-cache not supported on ARMv7-M"
+# else
+#  define _CACHE v7m
+# endif
+#endif
+
 #if !defined(_CACHE) && !defined(MULTI_CACHE)
 #error Unknown cache maintainence model
 #endif
@@ -238,6 +246,22 @@ extern struct cpu_cache_fns cpu_cache;
 
 #else
 
+#ifdef CONFIG_CPU_V7M
+
+static inline void v7m_flush_kern_all(void) { }
+static inline void v7m_flush_user_all(void) { }
+static inline void v7m_flush_user_range(unsigned long a, unsigned long b, unsigned int c) { }
+
+static inline void v7m_coherent_kern_range(unsigned long a, unsigned long b) { }
+static inline void v7m_coherent_user_range(unsigned long a, unsigned long b) { }
+static inline void v7m_flush_kern_dcache_page(void *a) { }
+
+static inline void v7m_dma_inv_range(const void *a, const void *b) { }
+static inline void v7m_dma_clean_range(const void *a, const void *b) { }
+static inline void v7m_dma_flush_range(const void *a, const void *b) { }
+
+#endif
+
 #define __cpuc_flush_kern_all		__glue(_CACHE,_flush_kern_cache_all)
 #define __cpuc_flush_user_all		__glue(_CACHE,_flush_user_cache_all)
 #define __cpuc_flush_user_range		__glue(_CACHE,_flush_user_cache_range)
diff --git a/include/asm-arm/checksum.h b/include/asm-arm/checksum.h
index eaa0efd..327a3a5 100644
--- a/include/asm-arm/checksum.h
+++ b/include/asm-arm/checksum.h
@@ -73,6 +73,7 @@ ip_fast_csum(const void *iph, unsigned int ihl)
 1:	adcs	%0, %0, %3					\n\
 	ldr	%3, [%1], #4					\n\
 	tst	%2, #15			@ do this carefully	\n\
+	it	ne						\n\
 	subne	%2, %2, #1		@ without destroying	\n\
 	bne	1b			@ the carry flag	\n\
 	adcs	%0, %0, %3					\n\
diff --git a/include/asm-arm/glue.h b/include/asm-arm/glue.h
index a97a182..fef0a5c 100644
--- a/include/asm-arm/glue.h
+++ b/include/asm-arm/glue.h
@@ -115,6 +115,14 @@
 # endif
 #endif
 
+#ifdef CONFIG_CPU_ABRT_EV7M
+# ifdef CPU_DABORT_HANDLER
+#  define MULTI_DABORT 1
+# else
+#  define CPU_DABORT_HANDLER v7m_early_abort
+# endif
+#endif
+
 #ifndef CPU_DABORT_HANDLER
 #error Unknown data abort handler type
 #endif
diff --git a/include/asm-arm/hardware/nvic.h b/include/asm-arm/hardware/nvic.h
new file mode 100644
index 0000000..b7f8026
--- /dev/null
+++ b/include/asm-arm/hardware/nvic.h
@@ -0,0 +1,34 @@
+/*
+ *  linux/include/asm-arm/hardware/nvic.h
+ *
+ *  Copyright (C) 2008 ARM Limited, All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#ifndef __ASM_ARM_HARDWARE_NVIC_H
+#define __ASM_ARM_HARDWARE_NVIC_H
+
+#include <linux/compiler.h>
+
+#define V7M_SCS				0xe000e000
+#define NVIC_INTR_CTRL			(V7M_SCS + 0x004)
+#define NVIC_SYSTICK_CTRL		(V7M_SCS + 0x010)
+#define NVIC_SYSTICK_RELOAD		(V7M_SCS + 0x014)
+#define NVIC_SYSTICK_CURRENT		(V7M_SCS + 0x018)
+#define NVIC_SYSTICK_CALIBRATION	(V7M_SCS + 0x01c)
+#define NVIC_SET_ENABLE			(V7M_SCS + 0x100)
+#define NVIC_CLEAR_ENABLE		(V7M_SCS + 0x180)
+#define NVIC_SET_PENDING		(V7M_SCS + 0x200)
+#define NVIC_CLEAR_PENDING		(V7M_SCS + 0x280)
+#define NVIC_ACTIVE_BIT			(V7M_SCS + 0x300)
+#define NVIC_PRIORITY			(V7M_SCS + 0x400)
+#define NVIC_INTR_CTRL_STATE		(V7M_SCS + 0xd04)
+#define NVIC_SOFTWARE_INTR		(V7M_SCS + 0xf00)
+
+#ifndef __ASSEMBLY__
+void nvic_init(void);
+#endif
+
+#endif
diff --git a/include/asm-arm/irqflags.h b/include/asm-arm/irqflags.h
index 6d09974..5dbb6de 100644
--- a/include/asm-arm/irqflags.h
+++ b/include/asm-arm/irqflags.h
@@ -10,6 +10,15 @@
  */
 #if __LINUX_ARM_ARCH__ >= 6
 
+#ifdef CONFIG_CPU_V7M
+#define raw_local_irq_save(x)					\
+	({							\
+	__asm__ __volatile__(					\
+	"mrs	%0, primask		@ local_irq_save\n"	\
+	"cpsid	i"						\
+	: "=r" (x) : : "memory", "cc");				\
+	})
+#else
 #define raw_local_irq_save(x)					\
 	({							\
 	__asm__ __volatile__(					\
@@ -17,6 +26,7 @@
 	"cpsid	i"						\
 	: "=r" (x) : : "memory", "cc");				\
 	})
+#endif
 
 #define raw_local_irq_enable()  __asm__("cpsie i	@ __sti" : : : "memory", "cc")
 #define raw_local_irq_disable() __asm__("cpsid i	@ __cli" : : : "memory", "cc")
@@ -103,6 +113,35 @@
 
 #endif
 
+#ifdef CONFIG_CPU_V7M
+
+/*
+ * Save the current interrupt enable state.
+ */
+#define raw_local_save_flags(x)					\
+	({							\
+	__asm__ __volatile__(					\
+	"mrs	%0, primask		@ local_save_flags"	\
+	: "=r" (x) : : "memory", "cc");				\
+	})
+
+/*
+ * restore saved IRQ & FIQ state
+ */
+#define raw_local_irq_restore(x)				\
+	__asm__ __volatile__(					\
+	"msr	primask, %0		@ local_irq_restore\n"	\
+	:							\
+	: "r" (x)						\
+	: "memory", "cc")
+
+#define raw_irqs_disabled_flags(flags)	\
+({					\
+	(int)((flags) & 1);		\
+})
+
+#else
+
 /*
  * Save the current interrupt enable state.
  */
@@ -128,5 +167,7 @@
 	(int)((flags) & PSR_I_BIT);	\
 })
 
+#endif	/* CONFIG_CPU_V7M */
+
 #endif
 #endif
diff --git a/include/asm-arm/locks.h b/include/asm-arm/locks.h
index 852220e..a102ec0 100644
--- a/include/asm-arm/locks.h
+++ b/include/asm-arm/locks.h
@@ -24,6 +24,7 @@
 "	teq	ip, #0\n"			\
 "	bne	1b\n"				\
 "	teq	lr, #0\n"			\
+"	itt	mi\n"				\
 "	movmi	ip, %0\n"			\
 "	blmi	" #fail				\
 	:					\
@@ -43,6 +44,7 @@
 "	teq	ip, #0\n"			\
 "	bne	1b\n"				\
 "	teq	lr, #0\n"			\
+"	itet	mi\n"				\
 "	movmi	ip, %1\n"			\
 "	movpl	ip, #0\n"			\
 "	blmi	" #fail "\n"			\
@@ -65,6 +67,7 @@
 "	teq	ip, #0\n"			\
 "	bne	1b\n"				\
 "	cmp	lr, #0\n"			\
+"	itt	le\n"				\
 "	movle	ip, %0\n"			\
 "	blle	" #wake				\
 	:					\
@@ -91,6 +94,7 @@
 "	teq	ip, #0\n"			\
 "	bne	1b\n"				\
 "	teq	lr, #0\n"			\
+"	itt	ne\n"				\
 "	movne	ip, %0\n"			\
 "	blne	" #fail				\
 	:					\
@@ -150,6 +154,7 @@
 "	subs	lr, lr, %1\n"			\
 "	str	lr, [%0]\n"			\
 "	msr	cpsr_c, ip\n"			\
+"	itt	mi\n"				\
 "	movmi	ip, %0\n"			\
 "	blmi	" #fail				\
 	:					\
@@ -170,6 +175,7 @@
 "	subs	lr, lr, %2\n"			\
 "	str	lr, [%1]\n"			\
 "	msr	cpsr_c, ip\n"			\
+"	itet	mi\n"				\
 "	movmi	ip, %1\n"			\
 "	movpl	ip, #0\n"			\
 "	blmi	" #fail "\n"			\
@@ -193,6 +199,7 @@
 "	adds	lr, lr, %1\n"			\
 "	str	lr, [%0]\n"			\
 "	msr	cpsr_c, ip\n"			\
+"	itt	le\n"				\
 "	movle	ip, %0\n"			\
 "	blle	" #wake				\
 	:					\
@@ -220,6 +227,7 @@
 "	subs	lr, lr, %1\n"			\
 "	str	lr, [%0]\n"			\
 "	msr	cpsr_c, ip\n"			\
+"	itt	ne\n"				\
 "	movne	ip, %0\n"			\
 "	blne	" #fail				\
 	:					\
@@ -239,6 +247,7 @@
 "	adds	lr, lr, %1\n"			\
 "	str	lr, [%0]\n"			\
 "	msr	cpsr_c, ip\n"			\
+"	itt	cs\n"				\
 "	movcs	ip, %0\n"			\
 "	blcs	" #wake				\
 	:					\
@@ -262,6 +271,7 @@
 "	adds	lr, lr, %1\n"			\
 "	str	lr, [%0]\n"			\
 "	msr	cpsr_c, ip\n"			\
+"	itt	eq\n"				\
 "	moveq	ip, %0\n"			\
 "	bleq	" #wake				\
 	:					\
diff --git a/include/asm-arm/mmu_context.h b/include/asm-arm/mmu_context.h
index 6913d02..5913310 100644
--- a/include/asm-arm/mmu_context.h
+++ b/include/asm-arm/mmu_context.h
@@ -60,8 +60,10 @@ static inline void check_context(struct mm_struct *mm)
 
 static inline void check_context(struct mm_struct *mm)
 {
+#ifdef CONFIG_MMU
 	if (unlikely(mm->context.kvm_seq != init_mm.context.kvm_seq))
 		__check_kvm_seq(mm);
+#endif
 }
 
 #define init_new_context(tsk,mm)	0
diff --git a/include/asm-arm/mutex.h b/include/asm-arm/mutex.h
index 020bd98..2f75e72 100644
--- a/include/asm-arm/mutex.h
+++ b/include/asm-arm/mutex.h
@@ -111,8 +111,11 @@ __mutex_fastpath_trylock(atomic_t *count, int (*fail_fn)(atomic_t *))
 
 		"1: ldrex	%0, [%3]	\n\t"
 		"subs		%1, %0, #1	\n\t"
+		"it		eq\n\t"
 		"strexeq	%2, %1, [%3]	\n\t"
+		"it		lt\n\t"
 		"movlt		%0, #0		\n\t"
+		"it		eq\n\t"
 		"cmpeq		%2, #0		\n\t"
 		"bgt		1b		"
 
diff --git a/include/asm-arm/proc-fns.h b/include/asm-arm/proc-fns.h
index 75ec760..5feb070 100644
--- a/include/asm-arm/proc-fns.h
+++ b/include/asm-arm/proc-fns.h
@@ -209,6 +209,14 @@
 #   define CPU_NAME cpu_v7
 #  endif
 # endif
+# ifdef CONFIG_CPU_V7M
+#  ifdef CPU_NAME
+#   undef  MULTI_CPU
+#   define MULTI_CPU
+#  else
+#   define CPU_NAME cpu_v7m
+#  endif
+# endif
 #endif
 
 #ifndef __ASSEMBLY__
diff --git a/include/asm-arm/processor.h b/include/asm-arm/processor.h
index bd8029e..11ca4b5 100644
--- a/include/asm-arm/processor.h
+++ b/include/asm-arm/processor.h
@@ -57,7 +57,11 @@ struct thread_struct {
 #ifdef CONFIG_MMU
 #define nommu_start_thread(regs) do { } while (0)
 #else
-#define nommu_start_thread(regs) regs->ARM_r10 = current->mm->start_data
+#define nommu_start_thread(regs) do {					\
+	regs->ARM_r10 = current->mm->start_data;			\
+	regs->ARM_sp -= 32;		/* exception return state */	\
+	regs->ARM_EXC_lr = 0xfffffffdL;	/* exception lr */		\
+} while (0)
 #endif
 
 #define start_thread(regs,pc,sp)					\
@@ -71,7 +75,7 @@ struct thread_struct {
 		regs->ARM_cpsr = USR26_MODE;				\
 	if (elf_hwcap & HWCAP_THUMB && pc & 1)				\
 		regs->ARM_cpsr |= PSR_T_BIT;				\
-	regs->ARM_pc = pc & ~1;		/* pc */			\
+	regs->ARM_pc = pc /*& ~1*/;	/* pc */			\
 	regs->ARM_sp = sp;		/* sp */			\
 	regs->ARM_r2 = stack[2];	/* r2 (envp) */			\
 	regs->ARM_r1 = stack[1];	/* r1 (argv) */			\
diff --git a/include/asm-arm/ptrace.h b/include/asm-arm/ptrace.h
index 7aaa206..c63a54c 100644
--- a/include/asm-arm/ptrace.h
+++ b/include/asm-arm/ptrace.h
@@ -35,16 +35,25 @@
 #define FIQ26_MODE	0x00000001
 #define IRQ26_MODE	0x00000002
 #define SVC26_MODE	0x00000003
+#ifndef CONFIG_CPU_V7M
 #define USR_MODE	0x00000010
+#define SVC_MODE	0x00000013
+#else
+#define USR_MODE	0x00000000
+#define SVC_MODE	0x00000000
+#endif
 #define FIQ_MODE	0x00000011
 #define IRQ_MODE	0x00000012
-#define SVC_MODE	0x00000013
 #define ABT_MODE	0x00000017
 #define UND_MODE	0x0000001b
 #define SYSTEM_MODE	0x0000001f
 #define MODE32_BIT	0x00000010
 #define MODE_MASK	0x0000001f
+#ifndef CONFIG_CPU_V7M
 #define PSR_T_BIT	0x00000020
+#else
+#define PSR_T_BIT	0x01000000
+#endif
 #define PSR_F_BIT	0x00000040
 #define PSR_I_BIT	0x00000080
 #define PSR_A_BIT	0x00000100
@@ -64,6 +73,12 @@
 #define PSR_x		0x0000ff00	/* Extension		*/
 #define PSR_c		0x000000ff	/* Control		*/
 
+/* These are `magic' values for PTRACE_PEEKUSR that return info about where
+   a process is located in memory.  */
+#define PT_TEXT_ADDR		0x10000
+#define PT_DATA_ADDR		0x10004
+#define PT_TEXT_END_ADDR	0x10008
+
 #ifndef __ASSEMBLY__
 
 /*
@@ -75,6 +90,28 @@ struct pt_regs {
 	long uregs[18];
 };
 
+#ifdef CONFIG_CPU_V7M
+/* Automatically saved registers */
+#define ARM_cpsr	uregs[17]
+#define ARM_pc		uregs[16]
+#define ARM_lr		uregs[15]
+#define ARM_ip		uregs[14]
+#define ARM_r3		uregs[13]
+#define ARM_r2		uregs[12]
+#define ARM_r1		uregs[11]
+#define ARM_r0		uregs[10]
+/* saved by the exception entry code */
+#define ARM_EXC_lr	uregs[9]
+#define ARM_sp		uregs[8]
+#define ARM_fp		uregs[7]
+#define ARM_r10		uregs[6]
+#define ARM_r9		uregs[5]
+#define ARM_r8		uregs[4]
+#define ARM_r7		uregs[3]
+#define ARM_r6		uregs[2]
+#define ARM_r5		uregs[1]
+#define ARM_r4		uregs[0]
+#else
 #define ARM_cpsr	uregs[16]
 #define ARM_pc		uregs[15]
 #define ARM_lr		uregs[14]
@@ -93,6 +130,7 @@ struct pt_regs {
 #define ARM_r1		uregs[1]
 #define ARM_r0		uregs[0]
 #define ARM_ORIG_r0	uregs[17]
+#endif
 
 #ifdef __KERNEL__
 
@@ -124,6 +162,7 @@ struct pt_regs {
  */
 static inline int valid_user_regs(struct pt_regs *regs)
 {
+#ifndef CONFIG_CPU_V7M
 	if (user_mode(regs) && (regs->ARM_cpsr & PSR_I_BIT) == 0) {
 		regs->ARM_cpsr &= ~(PSR_F_BIT | PSR_A_BIT);
 		return 1;
@@ -137,6 +176,9 @@ static inline int valid_user_regs(struct pt_regs *regs)
 		regs->ARM_cpsr |= USR_MODE;
 
 	return 0;
+#else
+	return 1;
+#endif
 }
 
 #endif	/* __KERNEL__ */
diff --git a/include/asm-arm/spinlock.h b/include/asm-arm/spinlock.h
index 2b41ebb..242b822 100644
--- a/include/asm-arm/spinlock.h
+++ b/include/asm-arm/spinlock.h
@@ -31,7 +31,10 @@ static inline void __raw_spin_lock(raw_spinlock_t *lock)
 "1:	ldrex	%0, [%1]\n"
 "	teq	%0, #0\n"
 #ifdef CONFIG_CPU_32v6K
+"	itee	ne\n"
 "	wfene\n"
+#else
+"	itt	eq\n"
 #endif
 "	strexeq	%0, %2, [%1]\n"
 "	teqeq	%0, #0\n"
@@ -50,6 +53,7 @@ static inline int __raw_spin_trylock(raw_spinlock_t *lock)
 	__asm__ __volatile__(
 "	ldrex	%0, [%1]\n"
 "	teq	%0, #0\n"
+"	it	eq\n"
 "	strexeq	%0, %2, [%1]"
 	: "=&r" (tmp)
 	: "r" (&lock->lock), "r" (1)
@@ -94,7 +98,10 @@ static inline void __raw_write_lock(raw_rwlock_t *rw)
 "1:	ldrex	%0, [%1]\n"
 "	teq	%0, #0\n"
 #ifdef CONFIG_CPU_32v6K
+"	itee	ne\n"
 "	wfene\n"
+#else
+"	itt	eq\n"
 #endif
 "	strexeq	%0, %2, [%1]\n"
 "	teq	%0, #0\n"
@@ -113,6 +120,7 @@ static inline int __raw_write_trylock(raw_rwlock_t *rw)
 	__asm__ __volatile__(
 "1:	ldrex	%0, [%1]\n"
 "	teq	%0, #0\n"
+"	it	eq\n"
 "	strexeq	%0, %2, [%1]"
 	: "=&r" (tmp)
 	: "r" (&rw->lock), "r" (0x80000000)
@@ -163,6 +171,11 @@ static inline void __raw_read_lock(raw_rwlock_t *rw)
 	__asm__ __volatile__(
 "1:	ldrex	%0, [%2]\n"
 "	adds	%0, %0, #1\n"
+#ifdef CONFIG_CPU_32v6K
+"	itet	pl\n"
+#else
+"	itt	pl\n"
+#endif
 "	strexpl	%1, %0, [%2]\n"
 #ifdef CONFIG_CPU_32v6K
 "	wfemi\n"
@@ -190,6 +203,7 @@ static inline void __raw_read_unlock(raw_rwlock_t *rw)
 "	bne	1b"
 #ifdef CONFIG_CPU_32v6K
 "\n	cmp	%0, #0\n"
+"	itt	eq\n"
 "	mcreq   p15, 0, %0, c7, c10, 4\n"
 "	seveq"
 #endif
diff --git a/include/asm-arm/system.h b/include/asm-arm/system.h
index 514af79..3056e86 100644
--- a/include/asm-arm/system.h
+++ b/include/asm-arm/system.h
@@ -15,6 +15,7 @@
 #define CPU_ARCH_ARMv5TEJ	7
 #define CPU_ARCH_ARMv6		8
 #define CPU_ARCH_ARMv7		9
+#define CPU_ARCH_ARMv7M		10
 
 /*
  * CR1 bits (CP#15 CR1)
@@ -74,6 +75,8 @@
 		    : "cc");						\
 		__val;							\
 	})
+#elif defined(CONFIG_CPU_V7M)
+#define read_cpuid(reg) (*(unsigned int *)0xe000ed00)
 #else
 extern unsigned int processor_id;
 #define read_cpuid(reg) (processor_id)
@@ -254,7 +257,9 @@ static inline void set_copro_access(unsigned int val)
  * so enable interrupts over the context switch to avoid high
  * latency.
  */
+#ifndef CONFIG_CPU_V7M
 #define __ARCH_WANT_INTERRUPTS_ON_CTXSW
+#endif
 
 /*
  * switch_to(prev, next) should switch from task `prev' to `next'
diff --git a/include/asm-arm/uaccess.h b/include/asm-arm/uaccess.h
index 4c1a3fa..8683927 100644
--- a/include/asm-arm/uaccess.h
+++ b/include/asm-arm/uaccess.h
@@ -12,6 +12,7 @@
  * User space memory access functions
  */
 #include <linux/sched.h>
+#include <asm/unified.h>
 #include <asm/errno.h>
 #include <asm/memory.h>
 #include <asm/domain.h>
@@ -68,7 +69,7 @@ static inline void set_fs(mm_segment_t fs)
 
 #define __addr_ok(addr) ({ \
 	unsigned long flag; \
-	__asm__("cmp %2, %0; movlo %0, #0" \
+	__asm__("cmp %2, %0; it lo; movlo %0, #0" \
 		: "=&r" (flag) \
 		: "0" (current_thread_info()->addr_limit), "r" (addr) \
 		: "cc"); \
@@ -78,7 +79,7 @@ static inline void set_fs(mm_segment_t fs)
 #define __range_ok(addr,size) ({ \
 	unsigned long flag, roksum; \
 	__chk_user_ptr(addr);	\
-	__asm__("adds %1, %2, %3; sbcccs %1, %1, %0; movcc %0, #0" \
+	__asm__("adds %1, %2, %3; it cc; sbcccs %1, %1, %0; it cc; movcc %0, #0" \
 		: "=&r" (flag), "=&r" (roksum) \
 		: "r" (addr), "Ir" (size), "0" (current_thread_info()->addr_limit) \
 		: "cc"); \
@@ -225,7 +226,7 @@ do {									\
 
 #define __get_user_asm_byte(x,addr,err)				\
 	__asm__ __volatile__(					\
-	"1:	ldrbt	%1,[%2],#0\n"				\
+	"1:	ldrbt	%1,[%2]\n"				\
 	"2:\n"							\
 	"	.section .fixup,\"ax\"\n"			\
 	"	.align	2\n"					\
@@ -261,7 +262,7 @@ do {									\
 
 #define __get_user_asm_word(x,addr,err)				\
 	__asm__ __volatile__(					\
-	"1:	ldrt	%1,[%2],#0\n"				\
+	"1:	ldrt	%1,[%2]\n"				\
 	"2:\n"							\
 	"	.section .fixup,\"ax\"\n"			\
 	"	.align	2\n"					\
@@ -306,7 +307,7 @@ do {									\
 
 #define __put_user_asm_byte(x,__pu_addr,err)			\
 	__asm__ __volatile__(					\
-	"1:	strbt	%1,[%2],#0\n"				\
+	"1:	strbt	%1,[%2]\n"				\
 	"2:\n"							\
 	"	.section .fixup,\"ax\"\n"			\
 	"	.align	2\n"					\
@@ -339,7 +340,7 @@ do {									\
 
 #define __put_user_asm_word(x,__pu_addr,err)			\
 	__asm__ __volatile__(					\
-	"1:	strt	%1,[%2],#0\n"				\
+	"1:	strt	%1,[%2]\n"				\
 	"2:\n"							\
 	"	.section .fixup,\"ax\"\n"			\
 	"	.align	2\n"					\
@@ -364,8 +365,10 @@ do {									\
 
 #define __put_user_asm_dword(x,__pu_addr,err)			\
 	__asm__ __volatile__(					\
-	"1:	strt	" __reg_oper1 ", [%1], #4\n"		\
-	"2:	strt	" __reg_oper0 ", [%1], #0\n"		\
+ ARM(	"1:	strt	" __reg_oper1 ", [%1], #4\n"	)	\
+ THUMB(	"1:	strt	" __reg_oper1 ", [%1]\n"	)	\
+ THUMB(	"	add	%1, %1, #4\n"			)	\
+	"2:	strt	" __reg_oper0 ", [%1]\n"		\
 	"3:\n"							\
 	"	.section .fixup,\"ax\"\n"			\
 	"	.align	2\n"					\
diff --git a/include/asm-arm/unified.h b/include/asm-arm/unified.h
new file mode 100644
index 0000000..2797529
--- /dev/null
+++ b/include/asm-arm/unified.h
@@ -0,0 +1,132 @@
+/*
+ * include/asm-arm/unified.h - Unified Assembler Syntax helper macros
+ *
+ * Copyright (C) 2007 ARM Limited
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef __ASM_UNIFIED_H
+#define __ASM_UNIFIED_H
+
+#if defined(__ASSEMBLY__) && defined(CONFIG_ARM_ASM_UNIFIED)
+	.syntax unified
+#endif
+
+#ifdef CONFIG_THUMB2_KERNEL
+
+#if __GNUC__ < 4
+#error Thumb-2 kernel requires gcc >= 4
+#endif
+
+#define PSR_ISETSTATE	PSR_T_BIT
+
+#define ARM(x...)
+#define THUMB(x...)	x
+#define W(instr)	instr.w
+
+#ifdef __ASSEMBLY__
+	/* Thumb function address */
+	.macro badr, reg, func, cond=al
+	adr\cond \reg, \func + 1
+	.endm
+#endif
+
+#else	/* !CONFIG_THUMB2_KERNEL */
+
+#define PSR_ISETSTATE	0
+
+#define ARM(x...)	x
+#define THUMB(x...)
+#define W(instr)	instr
+
+#ifdef __ASSEMBLY__
+	/* ARM branch address */
+	.macro	badr, reg, func, cond=al
+	adr\cond \reg, \func
+	.endm
+#endif
+
+#endif	/* CONFIG_THUMB2_KERNEL */
+
+#ifndef CONFIG_ARM_ASM_UNIFIED
+
+#ifdef __ASSEMBLY__
+	.macro	it, cond
+	.endm
+	.macro	itt, cond
+	.endm
+	.macro	ite, cond
+	.endm
+	.macro	ittt, cond
+	.endm
+	.macro	itte, cond
+	.endm
+	.macro	itet, cond
+	.endm
+	.macro	itee, cond
+	.endm
+	.macro	itttt, cond
+	.endm
+	.macro	ittte, cond
+	.endm
+	.macro	ittet, cond
+	.endm
+	.macro	ittee, cond
+	.endm
+	.macro	itett, cond
+	.endm
+	.macro	itete, cond
+	.endm
+	.macro	iteet, cond
+	.endm
+	.macro	iteee, cond
+	.endm
+#else	/* !__ASSEMBLY__ */
+__asm__(
+"	.macro	it, cond\n"
+"	.endm\n"
+"	.macro	itt, cond\n"
+"	.endm\n"
+"	.macro	ite, cond\n"
+"	.endm\n"
+"	.macro	ittt, cond\n"
+"	.endm\n"
+"	.macro	itte, cond\n"
+"	.endm\n"
+"	.macro	itet, cond\n"
+"	.endm\n"
+"	.macro	itee, cond\n"
+"	.endm\n"
+"	.macro	itttt, cond\n"
+"	.endm\n"
+"	.macro	ittte, cond\n"
+"	.endm\n"
+"	.macro	ittet, cond\n"
+"	.endm\n"
+"	.macro	ittee, cond\n"
+"	.endm\n"
+"	.macro	itett, cond\n"
+"	.endm\n"
+"	.macro	itete, cond\n"
+"	.endm\n"
+"	.macro	iteet, cond\n"
+"	.endm\n"
+"	.macro	iteee, cond\n"
+"	.endm\n");
+#endif	/* __ASSEMBLY__ */
+
+#endif	/* CONFIG_ARM_ASM_UNIFIED */
+
+#endif	/* !CONFIG_ARM_ASM_UNIFIED */
diff --git a/include/asm-arm/vfpmacros.h b/include/asm-arm/vfpmacros.h
index cccb389..94927c6 100644
--- a/include/asm-arm/vfpmacros.h
+++ b/include/asm-arm/vfpmacros.h
@@ -6,11 +6,11 @@
 #include "vfp.h"
 
 @ Macros to allow building with old toolkits (with no VFP support)
-	.macro	VFPFMRX, rd, sysreg, cond
+	.macro	VFPFMRX, rd, sysreg, cond = al
 	MRC\cond	p10, 7, \rd, \sysreg, cr0, 0	@ FMRX	\rd, \sysreg
 	.endm
 
-	.macro	VFPFMXR, sysreg, rd, cond
+	.macro	VFPFMXR, sysreg, rd, cond = al
 	MCR\cond	p10, 7, \rd, \sysreg, cr0, 0	@ FMXR	\sysreg, \rd
 	.endm
 
@@ -25,6 +25,7 @@
 	VFPFMRX	\tmp, MVFR0			    @ Media and VFP Feature Register 0
 	and	\tmp, \tmp, #MVFR0_A_SIMD_MASK	    @ A_SIMD field
 	cmp	\tmp, #2			    @ 32 x 64bit registers?
+	ite	eq
 	ldceql	p11, cr0, [\base],#32*4		    @ FLDMIAD \base!, {d16-d31}
 	addne	\base, \base, #32*4		    @ step over unused register space
 #endif
@@ -41,6 +42,7 @@
 	VFPFMRX	\tmp, MVFR0			    @ Media and VFP Feature Register 0
 	and	\tmp, \tmp, #MVFR0_A_SIMD_MASK	    @ A_SIMD field
 	cmp	\tmp, #2			    @ 32 x 64bit registers?
+	ite	eq
 	stceql	p11, cr0, [\base],#32*4		    @ FSTMIAD \base!, {d16-d31}
 	addne	\base, \base, #32*4		    @ step over unused register space
 #endif
