* Interrupt handling.  Preserves r7, r8, r9
  */
        .macro  irq_handler
+       get_irqnr_preamble r5, lr
 1:     get_irqnr_and_base r0, r6, r5, lr
        movne   r1, sp
        @
 
  */
 
 #include <asm/unistd.h>
+#include <asm/arch/entry-macro.S>
 
 #include "entry-header.S"
 
        tst     r1, #_TIF_WORK_MASK
        bne     fast_work_pending
 
+       /* perform architecture specific actions before user return */
+       arch_ret_to_user r1, lr
+
        @ fast_restore_user_regs
        ldr     r1, [sp, #S_OFF + S_PSR]        @ get calling cpsr
        ldr     lr, [sp, #S_OFF + S_PC]!        @ get pc
        tst     r1, #_TIF_WORK_MASK
        bne     work_pending
 no_work_pending:
+       /* perform architecture specific actions before user return */
+       arch_ret_to_user r1, lr
+
        @ slow_restore_user_regs
        ldr     r1, [sp, #S_PSR]                @ get calling cpsr
        ldr     lr, [sp, #S_PC]!                @ get pc
 
                .macro  disable_fiq
                .endm
 
+               .macro  get_irqnr_preamble, base, tmp
+               .endm
+
+               .macro  arch_ret_to_user, tmp1, tmp2
+               .endm
+
                .macro  get_irqnr_and_base, irqnr, irqstat, base, tmp
                mov     r4, #0xf8000000
                add     r4, r4, #0x00000500
 
        .macro  disable_fiq
        .endm
 
+       .macro  get_irqnr_preamble, base, tmp
+       .endm
+
+       .macro  arch_ret_to_user, tmp1, tmp2
+       .endm
+
        .macro  get_irqnr_and_base, irqnr, irqstat, base, tmp
        ldr     \base, =(AT91_VA_BASE_SYS)              @ base virtual address of SYS peripherals
        ldr     \irqnr, [\base, #AT91_AIC_IVR]          @ read IRQ vector register: de-asserts nIRQ to processor (and clears interrupt)
 
 #include <asm/hardware.h>
 #include <asm/hardware/entry-macro-iomd.S>
+       .macro  get_irqnr_preamble, base, tmp
+       .endm
+
+       .macro  arch_ret_to_user, tmp1, tmp2
+       .endm
 
 
                .macro  disable_fiq
                .endm
 
+               .macro  get_irqnr_preamble, base, tmp
+               .endm
+
+               .macro  arch_ret_to_user, tmp1, tmp2
+               .endm
+
 #if (INTSR2 - INTSR1) != (INTMR2 - INTMR1)
 #error INTSR stride != INTMR stride
 #endif
 
        .macro  disable_fiq
        .endm
 
+       .macro  get_irqnr_preamble, base, tmp
+       .endm
+
+       .macro  arch_ret_to_user, tmp1, tmp2
+       .endm
+
        .macro  get_irqnr_and_base, irqnr, stat, base, tmp
        mov     \base, #IRQ_STAT
        ldrb    \stat, [\base]                  @ get interrupts
 
                .macro  disable_fiq
                .endm
 
+               .macro  get_irqnr_preamble, base, tmp
+               .endm
+
+               .macro  arch_ret_to_user, tmp1, tmp2
+               .endm
+
                .equ    dc21285_high, ARMCSR_BASE & 0xff000000
                .equ    dc21285_low, ARMCSR_BASE & 0x00ffffff
 
 
                .macro  disable_fiq
                .endm
 
+               .macro  get_irqnr_preamble, base, tmp
+               .endm
+
+               .macro  arch_ret_to_user, tmp1, tmp2
+               .endm
+
                .macro  get_irqnr_and_base, irqnr, irqstat, base, tmp
                ldr     \base, =(EP93XX_AHB_VIRT_BASE)
                orr     \base, \base, #0x000b0000
 
                .macro  disable_fiq
                .endm
 
+               .macro  get_irqnr_preamble, base, tmp
+               .endm
+
+               .macro  arch_ret_to_user, tmp1, tmp2
+               .endm
+
                .macro  get_irqnr_and_base, irqnr, irqstat, base, tmp
 #if defined (CONFIG_CPU_H7201) || defined (CONFIG_CPU_H7202)
                @ we could use the id register on H7202, but this is not
 
 
                .macro  disable_fiq
                .endm
+
+               .macro  get_irqnr_preamble, base, tmp
+               .endm
+
+               .macro  arch_ret_to_user, tmp1, tmp2
+               .endm
+
 #define AITC_NIVECSR   0x40
                .macro  get_irqnr_and_base, irqnr, irqstat, base, tmp
                ldr     \irqstat, =IO_ADDRESS(IMX_AITC_BASE)
 
                .macro  disable_fiq
                .endm
 
+               .macro  get_irqnr_preamble, base, tmp
+               .endm
+
+               .macro  arch_ret_to_user, tmp1, tmp2
+               .endm
+
                .macro  get_irqnr_and_base, irqnr, irqstat, base, tmp
 /* FIXME: should not be using soo many LDRs here */
                ldr     \base, =IO_ADDRESS(INTEGRATOR_IC_BASE)
 
        .macro  disable_fiq
        .endm
 
+       .macro get_irqnr_preamble, base, tmp
+       mrc     p15, 0, \tmp, c15, c1, 0
+       orr     \tmp, \tmp, #(1 << 6)
+       mcr     p15, 0, \tmp, c15, c1, 0        @ Enable cp6 access
+       .endm
+
        /*
         * Note: a 1-cycle window exists where iintvec will return the value
         * of iintbase, so we explicitly check for "bad zeros"
         */
        .macro  get_irqnr_and_base, irqnr, irqstat, base, tmp
-       mrc     p15, 0, \tmp, c15, c1, 0
-       orr     \tmp, \tmp, #(1 << 6)
-       mcr     p15, 0, \tmp, c15, c1, 0        @ Enable cp6 access
-
        mrc     p6, 0, \irqnr, c3, c2, 0        @ Read IINTVEC
        cmp     \irqnr, #0
        mrceq   p6, 0, \irqnr, c3, c2, 0        @ Re-read on potentially bad zero
        adds    \irqstat, \irqnr, #1            @ Check for 0xffffffff
        movne   \irqnr, \irqnr, lsr #2          @ Convert to irqnr
+       .endm
 
-       biceq   \tmp, \tmp, #(1 << 6)
-       mcreq   p15, 0, \tmp, c15, c1, 0        @ Disable cp6 access if no more interrupts
+       .macro arch_ret_to_user, tmp1, tmp2
+       mrc     p15, 0, \tmp1, c15, c1, 0
+       ands    \tmp2, \tmp1, #(1 << 6)
+       bicne   \tmp1, \tmp1, #(1 << 6)
+       mcrne   p15, 0, \tmp1, c15, c1, 0       @ Disable cp6 access
        .endm
 
  */
 #include <asm/arch/iop32x.h>
 
-               .macro  disable_fiq
-               .endm
+       .macro  disable_fiq
+       .endm
 
-               .macro  get_irqnr_and_base, irqnr, irqstat, base, tmp
-               ldr     \base, =IOP3XX_REG_ADDR(0x07D8)
-               ldr     \irqstat, [\base]               @ Read IINTSRC
-               cmp     \irqstat, #0
-               clzne   \irqnr, \irqstat
-               rsbne   \irqnr, \irqnr, #31
-               .endm
+       .macro get_irqnr_preamble, base, tmp
+       mrc     p15, 0, \tmp, c15, c1, 0
+       orr     \tmp, \tmp, #(1 << 6)
+       mcr     p15, 0, \tmp, c15, c1, 0        @ Enable cp6 access
+       mrc     p15, 0, \tmp, c15, c1, 0
+       mov     \tmp, \tmp
+       sub     pc, pc, #4                      @ cp_wait
+       .endm
+
+       .macro  get_irqnr_and_base, irqnr, irqstat, base, tmp
+       mrc     p6, 0, \irqstat, c8, c0, 0      @ Read IINTSRC
+       cmp     \irqstat, #0
+       clzne   \irqnr, \irqstat
+       rsbne   \irqnr, \irqnr, #31
+       .endm
+
+       .macro arch_ret_to_user, tmp1, tmp2
+       mrc     p15, 0, \tmp1, c15, c1, 0
+       ands    \tmp2, \tmp1, #(1 << 6)
+       bicne   \tmp1, \tmp1, #(1 << 6)
+       mcrne   p15, 0, \tmp1, c15, c1, 0       @ Disable cp6 access
+       .endm
 
  */
 #include <asm/arch/iop33x.h>
 
-               .macro  disable_fiq
-               .endm
+       .macro  disable_fiq
+       .endm
 
-               .macro  get_irqnr_and_base, irqnr, irqstat, base, tmp
-               ldr     \base, =IOP3XX_REG_ADDR(0x07C8)
-               ldr     \irqstat, [\base]               @ Read IINTVEC
-               cmp     \irqstat, #0
-               ldreq   \irqstat, [\base]               @ erratum 63 workaround
-               adds    \irqnr, \irqstat, #1
-               movne   \irqnr, \irqstat, lsr #2
-               .endm
+       .macro get_irqnr_preamble, base, tmp
+       mrc     p15, 0, \tmp, c15, c1, 0
+       orr     \tmp, \tmp, #(1 << 6)
+       mcr     p15, 0, \tmp, c15, c1, 0        @ Enable cp6 access
+       mrc     p15, 0, \tmp, c15, c1, 0
+       mov     \tmp, \tmp
+       sub     pc, pc, #4                      @ cp_wait
+       .endm
+
+       .macro  get_irqnr_and_base, irqnr, irqstat, base, tmp
+       mrc     p6, 0, \irqstat, c14, c0, 0     @ Read IINTVEC
+       cmp     \irqstat, #0
+       mrceq   p6, 0, \irqstat, c14, c0, 0     @ erratum 63 workaround
+       adds    \irqnr, \irqstat, #1
+       movne   \irqnr, \irqstat, lsr #2
+       .endm
+
+       .macro arch_ret_to_user, tmp1, tmp2
+       mrc     p15, 0, \tmp1, c15, c1, 0
+       ands    \tmp2, \tmp1, #(1 << 6)
+       bicne   \tmp1, \tmp1, #(1 << 6)
+       mcrne   p15, 0, \tmp1, c15, c1, 0       @ Disable cp6 access
+       .endm
 
                .macro  disable_fiq
                .endm
 
+               .macro  get_irqnr_preamble, base, tmp
+               .endm
+
+               .macro  arch_ret_to_user, tmp1, tmp2
+               .endm
+
                .macro  get_irqnr_and_base, irqnr, irqstat, base, tmp
 
                mov     \irqnr, #0x0              @clear out irqnr as default
 
                .macro  disable_fiq
                .endm
 
+               .macro  get_irqnr_preamble, base, tmp
+               .endm
+
+               .macro  arch_ret_to_user, tmp1, tmp2
+               .endm
+
                .macro  get_irqnr_and_base, irqnr, irqstat, base, tmp
                ldr     \irqnr, =(IXP23XX_INTC_VIRT + IXP23XX_INTR_IRQ_ENC_ST_OFFSET)
                ldr     \irqnr, [\irqnr]        @ get interrupt number
 
                .macro  disable_fiq
                .endm
 
+               .macro  get_irqnr_preamble, base, tmp
+               .endm
+
+               .macro  arch_ret_to_user, tmp1, tmp2
+               .endm
+
                .macro  get_irqnr_and_base, irqnr, irqstat, base, tmp
                ldr     \irqstat, =(IXP4XX_INTC_BASE_VIRT+IXP4XX_ICIP_OFFSET)
                ldr     \irqstat, [\irqstat]            @ get interrupts
 
                .macro  disable_fiq
                .endm
 
+               .macro  get_irqnr_preamble, base, tmp
+               .endm
+
+               .macro  arch_ret_to_user, tmp1, tmp2
+               .endm
+
                .macro  get_irqnr_and_base, irqnr, irqstat, base, tmp
                mov     \irqstat, #irq_base_addr                @ Virt addr IRQ regs
                add     \irqstat, \irqstat, #0x00001000         @ Status reg
 
                .macro  disable_fiq
                .endm
 
+               .macro  get_irqnr_preamble, base, tmp
+               .endm
+
+               .macro  arch_ret_to_user, tmp1, tmp2
+               .endm
+
                .macro  get_irqnr_and_base, irqnr, irqstat, base, tmp
 
 branch_irq_lh7a400: b 1000f
 
                .macro  disable_fiq
                .endm
 
+               .macro  get_irqnr_preamble, base, tmp
+               .endm
+
+               .macro  arch_ret_to_user, tmp1, tmp2
+               .endm
+
                .macro  get_irqnr_and_base, irqnr, irqstat, base, tmp
                mov     \base, #io_p2v(0x00100000)
                add     \base, \base, #0x000ff000
 
                .macro  disable_fiq
                .endm
 
+               .macro  get_irqnr_preamble, base, tmp
+               .endm
+
+               .macro  arch_ret_to_user, tmp1, tmp2
+               .endm
+
                .macro  get_irqnr_and_base, irqnr, irqstat, base, tmp
                ldr     \base, =IO_ADDRESS(OMAP_IH1_BASE)
                ldr     \irqnr, [\base, #IRQ_ITR_REG_OFFSET]
 
                .macro  disable_fiq
                .endm
 
+               .macro  get_irqnr_preamble, base, tmp
+               .endm
+
+               .macro  arch_ret_to_user, tmp1, tmp2
+               .endm
+
                .macro  get_irqnr_and_base, irqnr, irqstat, base, tmp
 /* decode the MIC interrupt numbers */
                ldr     \base, =IO_ADDRESS(PNX4008_INTCTRLMIC_BASE)
 
                .macro  disable_fiq
                .endm
 
+               .macro  get_irqnr_preamble, base, tmp
+               .endm
+
+               .macro  arch_ret_to_user, tmp1, tmp2
+               .endm
+
                .macro  get_irqnr_and_base, irqnr, irqstat, base, tmp
 #ifdef CONFIG_PXA27x
                mrc     p6, 0, \irqstat, c0, c0, 0              @ ICIP
 
                .macro  disable_fiq
                .endm
 
+               .macro  get_irqnr_preamble, base, tmp
+               .endm
+
+               .macro  arch_ret_to_user, tmp1, tmp2
+               .endm
+
                /*
                 * The interrupt numbering scheme is defined in the
                 * interrupt controller spec.  To wit:
 
 #include <asm/hardware.h>
 #include <asm/hardware/entry-macro-iomd.S>
+       .macro  get_irqnr_preamble, base, tmp
+       .endm
+
+       .macro  arch_ret_to_user, tmp1, tmp2
+       .endm
 
 
 #include <asm/hardware.h>
 #include <asm/irq.h>
 
+       .macro  get_irqnr_preamble, base, tmp
+       .endm
+
+       .macro  arch_ret_to_user, tmp1, tmp2
+       .endm
+
        .macro  get_irqnr_and_base, irqnr, irqstat, base, tmp
 
                mov     \base, #S3C24XX_VA_IRQ
 
                .macro  disable_fiq
                .endm
 
+               .macro  get_irqnr_preamble, base, tmp
+               .endm
+
+               .macro  arch_ret_to_user, tmp1, tmp2
+               .endm
+
                .macro  get_irqnr_and_base, irqnr, irqstat, base, tmp
                mov     r4, #0xfa000000                 @ ICIP = 0xfa050000
                add     r4, r4, #0x00050000
 
                .macro  disable_fiq
                .endm
 
+               .macro  get_irqnr_preamble, base, tmp
+               .endm
+
+               .macro  arch_ret_to_user, tmp1, tmp2
+               .endm
+
                .macro  get_irqnr_and_base, irqnr, irqstat, base, tmp
                mov     r4, #0xe0000000
 
 
                .macro  disable_fiq
                .endm
 
+               .macro  get_irqnr_preamble, base, tmp
+               .endm
+
+               .macro  arch_ret_to_user, tmp1, tmp2
+               .endm
+
                .macro  get_irqnr_and_base, irqnr, irqstat, base, tmp
                ldr     \base, =IO_ADDRESS(VERSATILE_VIC_BASE)
                ldr     \irqstat, [\base, #VIC_IRQ_STATUS]      @ get masked status