Index: arch/arm/kernel/entry-armv.S
===================================================================
--- dd42dbff31b2dff8b226f1b61eff4b958fca5496/arch/arm/kernel/entry-armv.S  (mode:100644)
+++ cfdcf2133f1846c6f18e21f2a74fc267b8302c3b/arch/arm/kernel/entry-armv.S  (mode:100644)
@@ -24,91 +24,48 @@
 #include "entry-header.S"
 
 /*
- * Interrupt handling.  Preserves r7, r8, r9
- */
-	.macro	irq_handler
-1:	get_irqnr_and_base r0, r6, r5, lr
-	movne	r1, sp
-	@
-	@ routine called with r0 = irq number, r1 = struct pt_regs *
-	@
-	adrne	lr, 1b
-	bne	asm_do_IRQ
-
-#ifdef CONFIG_SMP
-	/*
-	 * XXX
-	 *
-	 * this macro assumes that irqstat (r6) and base (r5) are
-	 * preserved from get_irqnr_and_base above
-	 */
-	test_for_ipi r0, r6, r5, lr
-	movne	r0, sp
-	adrne	lr, 1b
-	bne	do_IPI
-#endif
-
-	.endm
-
-/*
  * Invalid mode handlers
  */
-	.macro	inv_entry, reason
-	sub	sp, sp, #S_FRAME_SIZE
-	stmib	sp, {r1 - lr}
+	.macro	inv_entry, sym, reason
+	sub	sp, sp, #S_FRAME_SIZE		@ Allocate frame size in one go
+	stmia	sp, {r0 - lr}			@ Save XXX r0 - lr
+	ldr	r4, .LC\sym
 	mov	r1, #\reason
 	.endm
 
 __pabt_invalid:
-	inv_entry BAD_PREFETCH
-	b	common_invalid
+	inv_entry abt, BAD_PREFETCH
+	b	1f
 
 __dabt_invalid:
-	inv_entry BAD_DATA
-	b	common_invalid
+	inv_entry abt, BAD_DATA
+	b	1f
 
 __irq_invalid:
-	inv_entry BAD_IRQ
-	b	common_invalid
+	inv_entry irq, BAD_IRQ
+	b	1f
 
 __und_invalid:
-	inv_entry BAD_UNDEFINSTR
-
-	@
-	@ XXX fall through to common_invalid
-	@
-
-@
-@ common_invalid - generic code for failed exception (re-entrant version of handlers)
-@
-common_invalid:
-	zero_fp
-
-	ldmia	r0, {r4 - r6}
-	add	r0, sp, #S_PC		@ here for interlock avoidance
-	mov	r7, #-1			@  ""   ""    ""        ""
-	str	r4, [sp]		@ save preserved r0
-	stmia	r0, {r5 - r7}		@ lr_<exception>,
-					@ cpsr_<exception>, "old_r0"
+	inv_entry und, BAD_UNDEFINSTR
 
+1:	zero_fp
+	ldmia	r4, {r5 - r7}			@ Get XXX pc, cpsr, old_r0
+	add	r4, sp, #S_PC
+	stmia	r4, {r5 - r7}			@ Save XXX pc, cpsr, old_r0
 	mov	r0, sp
-	and	r2, r6, #0x1f
+	and	r2, r6, #31			@ int mode
 	b	bad_mode
 
 /*
  * SVC mode handlers
  */
-	.macro	svc_entry
+	.macro	svc_entry, sym
 	sub	sp, sp, #S_FRAME_SIZE
-	stmib	sp, {r1 - r12}
-
-	ldmia	r0, {r1 - r3}
-	add	r5, sp, #S_SP		@ here for interlock avoidance
-	mov	r4, #-1			@  ""  ""      ""       ""
-	add	r0, sp, #S_FRAME_SIZE   @  ""  ""      ""       ""
-	str	r1, [sp]		@ save the "real" r0 copied
-					@ from the exception stack
-
+	stmia	sp, {r0 - r12}			@ save r0 - r12
+	ldr	r2, .LC\sym
+	add	r0, sp, #S_FRAME_SIZE
+	ldmia	r2, {r2 - r4}			@ get pc, cpsr
+	add	r5, sp, #S_SP
 	mov	r1, lr
 
 	@
@@ -125,7 +82,7 @@
 
 	.align	5
 __dabt_svc:
-	svc_entry
+	svc_entry abt
 
 	@
 	@ get ready to re-enable interrupts if appropriate
@@ -172,24 +129,28 @@
 
 	.align	5
 __irq_svc:
-	svc_entry
-
+	svc_entry irq
 #ifdef CONFIG_PREEMPT
-	get_thread_info tsk
-	ldr	r8, [tsk, #TI_PREEMPT]		@ get preempt count
-	add	r7, r8, #1			@ increment it
-	str	r7, [tsk, #TI_PREEMPT]
+	get_thread_info r8
+	ldr	r9, [r8, #TI_PREEMPT]		@ get preempt count
+	add	r7, r9, #1			@ increment it
+	str	r7, [r8, #TI_PREEMPT]
 #endif
-
-	irq_handler
+1:	get_irqnr_and_base r0, r6, r5, lr
+	movne	r1, sp
+	@
+	@ routine called with r0 = irq number, r1 = struct pt_regs *
+	@
+	adrne	lr, 1b
+	bne	asm_do_IRQ
 #ifdef CONFIG_PREEMPT
-	ldr	r0, [tsk, #TI_FLAGS]		@ get flags
+	ldr	r0, [r8, #TI_FLAGS]		@ get flags
 	tst	r0, #_TIF_NEED_RESCHED
 	blne	svc_preempt
 preempt_return:
-	ldr	r0, [tsk, #TI_PREEMPT]		@ read preempt value
-	str	r8, [tsk, #TI_PREEMPT]		@ restore preempt count
+	ldr	r0, [r8, #TI_PREEMPT]		@ read preempt value
 	teq	r0, r7
+	str	r9, [r8, #TI_PREEMPT]		@ restore preempt count
 	strne	r0, [r0, -r0]			@ bug()
 #endif
 	ldr	r0, [sp, #S_PSR]		@ irqs are already disabled
@@ -200,7 +161,7 @@
 
 #ifdef CONFIG_PREEMPT
 svc_preempt:
-	teq	r8, #0				@ was preempt count = 0
+	teq	r9, #0				@ was preempt count = 0
 	ldreq	r6, .LCirq_stat
 	movne	pc, lr				@ no
 	ldr	r0, [r6, #4]			@ local_irq_count
@@ -208,9 +169,9 @@
 	adds	r0, r0, r1
 	movne	pc, lr
 	mov	r7, #0				@ preempt_schedule_irq
-	str	r7, [tsk, #TI_PREEMPT]		@ expects preempt_count == 0
+	str	r7, [r8, #TI_PREEMPT]		@ expects preempt_count == 0
 1:	bl	preempt_schedule_irq		@ irq en/disable is done inside
-	ldr	r0, [tsk, #TI_FLAGS]		@ get new tasks TI_FLAGS
+	ldr	r0, [r8, #TI_FLAGS]		@ get new tasks TI_FLAGS
 	tst	r0, #_TIF_NEED_RESCHED
 	beq	preempt_return			@ go again
 	b	1b
@@ -218,7 +179,7 @@
 
 	.align	5
 __und_svc:
-	svc_entry
+	svc_entry und
 
 	@
 	@ call emulation code, which returns using r9 if it has emulated
@@ -248,7 +209,7 @@
 
 	.align	5
 __pabt_svc:
-	svc_entry
+	svc_entry abt
 
 	@
 	@ re-enable interrupts if appropriate
@@ -281,8 +242,12 @@
 	ldmia	sp, {r0 - pc}^			@ load r0 - pc, cpsr
 
 	.align	5
-.LCcralign:
-	.word	cr_alignment
+.LCirq:
+	.word	__temp_irq
+.LCund:
+	.word	__temp_und
+.LCabt:
+	.word	__temp_abt
 #ifdef MULTI_ABORT
 .LCprocfns:
 	.word	processor
@@ -297,16 +262,12 @@
 /*
  * User mode handlers
  */
-	.macro	usr_entry
-	sub	sp, sp, #S_FRAME_SIZE
-	stmib	sp, {r1 - r12}
-
-	ldmia	r0, {r1 - r3}
-	add	r0, sp, #S_PC		@ here for interlock avoidance
-	mov	r4, #-1			@  ""  ""     ""        ""
-
-	str	r1, [sp]		@ save the "real" r0 copied
-					@ from the exception stack
+	.macro	usr_entry, sym
+	sub	sp, sp, #S_FRAME_SIZE		@ Allocate frame size in one go
+	stmia	sp, {r0 - r12}			@ save r0 - r12
+	ldr	r7, .LC\sym
+	add	r5, sp, #S_PC
+	ldmia	r7, {r2 - r4}			@ Get USR pc, cpsr
 
 #if __LINUX_ARM_ARCH__ < 6
 	@ make sure our user space atomic helper is aborted
@@ -323,13 +284,13 @@
 	@
 	@ Also, separately save sp_usr and lr_usr
 	@
-	stmia	r0, {r2 - r4}
-	stmdb	r0, {sp, lr}^
+	stmia	r5, {r2 - r4}
+	stmdb	r5, {sp, lr}^
 
 	@
 	@ Enable the alignment trap while in kernel mode
 	@
-	alignment_trap r0
+	alignment_trap r7, r0, __temp_\sym
 
 	@
 	@ Clear FP to mark the first stack frame
@@ -339,7 +300,7 @@
 
 	.align	5
 __dabt_usr:
-	usr_entry
+	usr_entry abt
 
 	@
 	@ Call the processor-specific abort handler:
@@ -368,23 +329,30 @@
 
 	.align	5
 __irq_usr:
-	usr_entry
+	usr_entry irq
 
-	get_thread_info tsk
 #ifdef CONFIG_PREEMPT
-	ldr	r8, [tsk, #TI_PREEMPT]		@ get preempt count
-	add	r7, r8, #1			@ increment it
-	str	r7, [tsk, #TI_PREEMPT]
+	get_thread_info r8
+	ldr	r9, [r8, #TI_PREEMPT]		@ get preempt count
+	add	r7, r9, #1			@ increment it
+	str	r7, [r8, #TI_PREEMPT]
 #endif
-
-	irq_handler
+1:	get_irqnr_and_base r0, r6, r5, lr
+	movne	r1, sp
+	adrne	lr, 1b
+	@
+	@ routine called with r0 = irq number, r1 = struct pt_regs *
+	@
+	bne	asm_do_IRQ
 #ifdef CONFIG_PREEMPT
-	ldr	r0, [tsk, #TI_PREEMPT]
-	str	r8, [tsk, #TI_PREEMPT]
+	ldr	r0, [r8, #TI_PREEMPT]
 	teq	r0, r7
+	str	r9, [r8, #TI_PREEMPT]
 	strne	r0, [r0, -r0]
+	mov	tsk, r8
+#else
+	get_thread_info tsk
 #endif
-
 	mov	why, #0
 	b	ret_to_user
 
@@ -392,7 +360,7 @@
 
 	.align	5
 __und_usr:
-	usr_entry
+	usr_entry und
 
 	tst	r3, #PSR_T_BIT			@ Thumb mode?
 	bne	fpundefinstr			@ ignore FP
@@ -508,7 +476,7 @@
 
 	.align	5
 __pabt_usr:
-	usr_entry
+	usr_entry abt
 
 	enable_irq				@ Enable interrupts
 	mov	r0, r2				@ address (pc)
@@ -767,41 +735,29 @@
  *
  * Common stub entry macro:
  *   Enter in IRQ mode, spsr = SVC/USR CPSR, lr = SVC/USR PC
- *
- * SP points to a minimal amount of processor-private memory, the address
- * of which is copied into r0 for the mode specific abort handler.
  */
-	.macro	vector_stub, name, correction=0
+	.macro	vector_stub, name, sym, correction=0
 	.align	5
 
 vector_\name:
+	ldr	r13, .LCs\sym
 	.if \correction
 	sub	lr, lr, #\correction
 	.endif
-
-	@
-	@ Save r0, lr_<exception> (parent PC) and spsr_<exception>
-	@ (parent CPSR)
-	@
-	stmia	sp, {r0, lr}		@ save r0, lr
+	str	lr, [r13]			@ save lr_IRQ
 	mrs	lr, spsr
-	str	lr, [sp, #8]		@ save spsr
-
+	str	lr, [r13, #4]			@ save spsr_IRQ
 	@
-	@ Prepare for SVC32 mode.  IRQs remain disabled.
+	@ now branch to the relevant MODE handling routine
 	@
-	mrs	r0, cpsr
-	bic	r0, r0, #MODE_MASK
-	orr	r0, r0, #SVC_MODE
-	msr	spsr_cxsf, r0
+	mrs	r13, cpsr
+	bic	r13, r13, #MODE_MASK
+	orr	r13, r13, #SVC_MODE
+	msr	spsr_cxsf, r13			@ switch to SVC_32 mode
 
-	@
-	@ the branch table must immediately follow this code
-	@
-	mov	r0, sp
-	and	lr, lr, #0x0f
+	and	lr, lr, #15
 	ldr	lr, [pc, lr, lsl #2]
-	movs	pc, lr			@ branch to handler in SVC mode
+	movs	pc, lr				@ Changes mode and branches
 	.endm
 
 	.globl	__stubs_start
@@ -809,7 +765,7 @@
 /*
  * Interrupt dispatcher
  */
-	vector_stub	irq, 4
+	vector_stub	irq, irq, 4
 
 	.long	__irq_usr			@  0  (USR_26 / USR_32)
 	.long	__irq_invalid			@  1  (FIQ_26 / FIQ_32)
@@ -832,7 +788,7 @@
  * Data abort dispatcher
  * Enter in ABT mode, spsr = USR CPSR, lr = USR PC
  */
-	vector_stub	dabt, 8
+	vector_stub	dabt, abt, 8
 
 	.long	__dabt_usr			@  0  (USR_26 / USR_32)
 	.long	__dabt_invalid			@  1  (FIQ_26 / FIQ_32)
@@ -855,7 +811,7 @@
  * Prefetch abort dispatcher
  * Enter in ABT mode, spsr = USR CPSR, lr = USR PC
  */
-	vector_stub	pabt, 4
+	vector_stub	pabt, abt, 4
 
 	.long	__pabt_usr			@  0 (USR_26 / USR_32)
 	.long	__pabt_invalid			@  1 (FIQ_26 / FIQ_32)
@@ -878,7 +834,7 @@
  * Undef instr entry dispatcher
  * Enter in UND mode, spsr = SVC/USR CPSR, lr = SVC/USR PC
  */
-	vector_stub	und
+	vector_stub	und, und
 
 	.long	__und_usr			@  0 (USR_26 / USR_32)
 	.long	__und_invalid			@  1 (FIQ_26 / FIQ_32)
@@ -932,6 +888,13 @@
 .LCvswi:
 	.word	vector_swi
 
+.LCsirq:
+	.word	__temp_irq
+.LCsund:
+	.word	__temp_und
+.LCsabt:
+	.word	__temp_abt
+
 	.globl	__stubs_end
 __stubs_end:
 
@@ -953,6 +916,23 @@
 
 	.data
 
+/*
+ * Do not reorder these, and do not insert extra data between...
+ */
+
+__temp_irq:
+	.word	0				@ saved lr_irq
+	.word	0				@ saved spsr_irq
+	.word	-1				@ old_r0
+__temp_und:
+	.word	0				@ Saved lr_und
+	.word	0				@ Saved spsr_und
+	.word	-1				@ old_r0
+__temp_abt:
+	.word	0				@ Saved lr_abt
+	.word	0				@ Saved spsr_abt
+	.word	-1				@ old_r0
+
 	.globl	cr_alignment
 	.globl	cr_no_alignment
 cr_alignment:
Index: arch/arm/kernel/entry-header.S
===================================================================
--- dd42dbff31b2dff8b226f1b61eff4b958fca5496/arch/arm/kernel/entry-header.S  (mode:100644)
+++ cfdcf2133f1846c6f18e21f2a74fc267b8302c3b/arch/arm/kernel/entry-header.S  (mode:100644)
@@ -59,10 +59,11 @@
 	mov	\rd, \rd, lsl #13
 	.endm
 
-	.macro	alignment_trap, rtemp
+	.macro	alignment_trap, rbase, rtemp, sym
 #ifdef CONFIG_ALIGNMENT_TRAP
-	ldr	\rtemp, .LCcralign
-	ldr	\rtemp, [\rtemp]
+#define OFF_CR_ALIGNMENT(x)	cr_alignment - x
+
+	ldr	\rtemp, [\rbase, #OFF_CR_ALIGNMENT(\sym)]
 	mcr	p15, 0, \rtemp, c1, c0
 #endif
 	.endm
Index: arch/arm/kernel/setup.c
===================================================================
--- dd42dbff31b2dff8b226f1b61eff4b958fca5496/arch/arm/kernel/setup.c  (mode:100644)
+++ cfdcf2133f1846c6f18e21f2a74fc267b8302c3b/arch/arm/kernel/setup.c  (mode:100644)
@@ -92,14 +92,6 @@
 struct cpu_cache_fns cpu_cache;
 #endif
 
-struct stack {
-	u32 irq[3];
-	u32 abt[3];
-	u32 und[3];
-} ____cacheline_aligned;
-
-static struct stack stacks[NR_CPUS];
-
 char elf_platform[ELF_PLATFORM_SIZE];
 EXPORT_SYMBOL(elf_platform);
 
@@ -315,6 +307,8 @@
 	       cpu_name, processor_id, (int)processor_id & 15,
 	       proc_arch[cpu_architecture()]);
 
+	dump_cpu_info(smp_processor_id());
+
 	sprintf(system_utsname.machine, "%s%c", list->arch_name, ENDIANNESS);
 	sprintf(elf_platform, "%s%c", list->elf_name, ENDIANNESS);
 	elf_hwcap = list->elf_hwcap;
@@ -322,46 +316,6 @@
 	cpu_proc_init();
 }
 
-/*
- * cpu_init - initialise one CPU.
- *
- * cpu_init dumps the cache information, initialises SMP specific
- * information, and sets up the per-CPU stacks.
- */
-void __init cpu_init(void)
-{
-	unsigned int cpu = smp_processor_id();
-	struct stack *stk = &stacks[cpu];
-
-	if (cpu >= NR_CPUS) {
-		printk(KERN_CRIT "CPU%u: bad primary CPU number\n", cpu);
-		BUG();
-	}
-
-	dump_cpu_info(cpu);
-
-	/*
-	 * setup stacks for re-entrant exception handlers
-	 */
-	__asm__ (
-	"msr	cpsr_c, %1\n\t"
-	"add	sp, %0, %2\n\t"
-	"msr	cpsr_c, %3\n\t"
-	"add	sp, %0, %4\n\t"
-	"msr	cpsr_c, %5\n\t"
-	"add	sp, %0, %6\n\t"
-	"msr	cpsr_c, %7"
-	    :
-	    : "r" (stk),
-	      "I" (PSR_F_BIT | PSR_I_BIT | IRQ_MODE),
-	      "I" (offsetof(struct stack, irq[0])),
-	      "I" (PSR_F_BIT | PSR_I_BIT | ABT_MODE),
-	      "I" (offsetof(struct stack, abt[0])),
-	      "I" (PSR_F_BIT | PSR_I_BIT | UND_MODE),
-	      "I" (offsetof(struct stack, und[0])),
-	      "I" (PSR_F_BIT | PSR_I_BIT | SVC_MODE));
-}
-
 static struct machine_desc * __init setup_machine(unsigned int nr)
 {
 	struct machine_desc *list;
@@ -761,8 +715,6 @@
 	paging_init(&meminfo, mdesc);
 	request_standard_resources(&meminfo, mdesc);
 
-	cpu_init();
-
 	/*
 	 * Set up various architecture-specific pointers
 	 */

