arm: enable interrupts while handling traps
authorIan Campbell <ian.campbell@citrix.com>
Tue, 26 Jun 2012 15:23:47 +0000 (16:23 +0100)
committerIan Campbell <ian.campbell@citrix.com>
Tue, 26 Jun 2012 15:23:47 +0000 (16:23 +0100)
For most traps we can do this as soon as we have saved the necessary state.
For IRQs and FIQs we must wait until we have acked the interrupt with the GIC.

Signed-off-by: Ian Campbell <ian.campbell@citrix.com>
Acked-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
Committed-by: Ian Campbell <ian.campbell@citrix.com>
xen/arch/arm/entry.S
xen/arch/arm/gic.c
xen/arch/arm/traps.c

index 7a22e2d9e988bd0c0a24c79c65afb8f66c995329..5bc39063f95f99c4a22835dcbb194029db437449 100644 (file)
@@ -44,6 +44,17 @@ save_guest_regs:
 
 #define DEFINE_TRAP_ENTRY(trap)                                                                                \
        ALIGN;                                                                                          \
+trap_##trap:                                                                                           \
+       SAVE_ALL;                                                                                       \
+       cpsie i;        /* local_irq_enable */                                                          \
+       adr lr, return_from_trap;                                                                       \
+       mov r0, sp;                                                                                     \
+       mov r11, sp;                                                                                    \
+       bic sp, #7; /* Align the stack pointer (noop on guest trap) */                                  \
+       b do_trap_##trap
+
+#define DEFINE_TRAP_ENTRY_NOIRQ(trap)                                                                  \
+       ALIGN;                                                                                          \
 trap_##trap:                                                                                           \
        SAVE_ALL;                                                                                       \
        adr lr, return_from_trap;                                                                       \
@@ -69,8 +80,8 @@ DEFINE_TRAP_ENTRY(supervisor_call)
 DEFINE_TRAP_ENTRY(prefetch_abort)
 DEFINE_TRAP_ENTRY(data_abort)
 DEFINE_TRAP_ENTRY(hypervisor)
-DEFINE_TRAP_ENTRY(irq)
-DEFINE_TRAP_ENTRY(fiq)
+DEFINE_TRAP_ENTRY_NOIRQ(irq)
+DEFINE_TRAP_ENTRY_NOIRQ(fiq)
 
 return_from_trap:
        mov sp, r11
@@ -83,7 +94,7 @@ ENTRY(return_to_new_vcpu)
 ENTRY(return_to_guest)
        mov r11, sp
        bic sp, #7 /* Align the stack pointer */
-       bl leave_hypervisor_tail
+       bl leave_hypervisor_tail /* Disables interrupts on return */
        mov sp, r11
        RESTORE_ONE_BANKED(SP_usr)
        /* LR_usr is the same physical register as lr and is restored below */
index cc9d37b3d359888fd40b0c68916cc5aa8fd666a4..1a2b95f2489b4c6b21648d26642695dbbb857fa2 100644 (file)
@@ -509,6 +509,8 @@ void gic_interrupt(struct cpu_user_regs *regs, int is_fiq)
     uint32_t intack = GICC[GICC_IAR];
     unsigned int irq = intack & GICC_IA_IRQ;
 
+    local_irq_enable();
+
     if ( irq == 1023 )
         /* Spurious interrupt */
         return;
index abc26a32ec57d3f51b7a3d7628fd5dc849a1569b..5ed754f9eda55071a5f89c0dad66e95b5e19d872 100644 (file)
@@ -412,7 +412,6 @@ static void do_debug_trap(struct cpu_user_regs *regs, unsigned int code)
 static void do_trap_hypercall(struct cpu_user_regs *regs, unsigned long iss)
 {
     arm_hypercall_t *call = NULL;
-    local_irq_enable();
 
     if ( iss != XEN_HYPERCALL_TAG )
     {