diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
index f5befbd..0470a2d 100644
--- a/xen/arch/arm/domain_build.c
+++ b/xen/arch/arm/domain_build.c
@@ -408,6 +408,20 @@ static int map_device(struct domain *d, const struct dt_device_node *dev)
         }
 
         DPRINT("irq %u = %u type = 0x%x\n", i, irq.irq, irq.type);
+
+        /*
+         * Only map SGI interrupt in the guest as XEN won't handle
+         * it correctly.
+         * TODO: Fix it
+         */
+        if ( !irq_is_sgi(irq.irq) )
+        {
+            printk(XENLOG_WARNING "WARNING: Don't map irq %u for %s has "
+                   "XEN doesn't handle properly non-SGI interrupt\n",
+                   i, dt_node_full_name(dev));
+            continue;
+        }
+
         /* Don't check return because the IRQ can be use by multiple device */
         gic_route_irq_to_guest(d, &irq, dt_node_name(dev));
     }
diff --git a/xen/arch/arm/gic.c b/xen/arch/arm/gic.c
index b16ba8c..e7d082a 100644
--- a/xen/arch/arm/gic.c
+++ b/xen/arch/arm/gic.c
@@ -179,6 +179,17 @@ static hw_irq_controller gic_guest_irq_type = {
     .set_affinity = gic_irq_set_affinity,
 };
 
+void gic_irq_enable(struct irq_desc *desc)
+{
+    spin_lock_irq(&desc->lock);
+    spin_lock(&gic.lock);
+
+    desc->handler->enable(desc);
+
+    spin_unlock(&gic.lock);
+    spin_unlock_irq(&desc->lock);
+}
+
 /* needs to be called with gic.lock held */
 static void gic_set_irq_properties(unsigned int irq, bool_t level,
         unsigned int cpu_mask, unsigned int priority)
@@ -543,8 +554,6 @@ static int __setup_irq(struct irq_desc *desc, unsigned int irq,
     desc->status &= ~IRQ_DISABLED;
     dsb();
 
-    desc->handler->startup(desc);
-
     return 0;
 }
 
@@ -560,6 +569,8 @@ int __init setup_dt_irq(const struct dt_irq *irq, struct irqaction *new)
 
     rc = __setup_irq(desc, irq->irq, new);
 
+    desc->handler->startup(desc);
+
     spin_unlock_irqrestore(&desc->lock, flags);
 
     return rc;
@@ -711,6 +722,7 @@ void gic_inject(void)
         gic_inject_irq_start();
 }
 
+/* TODO: Handle properly non SGI-interrupt */
 int gic_route_irq_to_guest(struct domain *d, const struct dt_irq *irq,
                            const char * devname)
 {
@@ -719,11 +731,18 @@ int gic_route_irq_to_guest(struct domain *d, const struct dt_irq *irq,
     unsigned long flags;
     int retval;
     bool_t level;
+    struct pending_irq *p;
+    /* XXX: handler other VCPU than 0 */
+    struct vcpu *v = d->vcpu[0];
 
     action = xmalloc(struct irqaction);
     if (!action)
         return -ENOMEM;
 
+    /* XXX: Here we assume a 1:1 interrupt mapping between the host and dom0 */
+    BUG_ON(irq->irq >= (d->arch.vgic.nr_lines + NR_LOCAL_IRQS));
+    p = irq_to_pending(v, irq->irq);
+
     action->dev_id = d;
     action->name = devname;
     action->free_on_release = 1;
@@ -744,6 +763,8 @@ int gic_route_irq_to_guest(struct domain *d, const struct dt_irq *irq,
         goto out;
     }
 
+    p->desc = desc;
+
 out:
     spin_unlock(&gic.lock);
     spin_unlock_irqrestore(&desc->lock, flags);
diff --git a/xen/arch/arm/vgic.c b/xen/arch/arm/vgic.c
index cea9233..4f3d816 100644
--- a/xen/arch/arm/vgic.c
+++ b/xen/arch/arm/vgic.c
@@ -372,6 +372,9 @@ static void vgic_enable_irqs(struct vcpu *v, uint32_t r, int n)
         if ( !list_empty(&p->inflight) && !gic_irq_injected(irq) )
             gic_set_guest_irq(v, irq, GICH_LR_PENDING, p->priority);
 
+        if ( p->desc != NULL )
+            gic_irq_enable(p->desc);
+
         i++;
     }
 }
@@ -685,10 +688,6 @@ void vgic_vcpu_inject_irq(struct vcpu *v, unsigned int irq, int virtual)
 
     n->irq = irq;
     n->priority = priority;
-    if (!virtual)
-        n->desc = irq_to_desc(irq);
-    else
-        n->desc = NULL;
 
     /* the irq is enabled */
     if ( rank->ienable & (1 << (irq % 32)) )
diff --git a/xen/include/asm-arm/gic.h b/xen/include/asm-arm/gic.h
index f9e9ef1..f7f3c1e 100644
--- a/xen/include/asm-arm/gic.h
+++ b/xen/include/asm-arm/gic.h
@@ -134,6 +134,7 @@
 
 #ifndef __ASSEMBLY__
 #include <xen/device_tree.h>
+#include <xen/irq.h>
 
 extern int domain_vgic_init(struct domain *d);
 extern void domain_vgic_free(struct domain *d);
@@ -154,6 +155,9 @@ extern void gic_inject(void);
 extern void gic_clear_pending_irqs(struct vcpu *v);
 extern int gic_events_need_delivery(void);
 
+/* Helper to enable an IRQ and take all the needed locks */
+extern void gic_irq_enable(struct irq_desc *desc);
+
 extern void __cpuinit init_maintenance_interrupt(void);
 extern void gic_set_guest_irq(struct vcpu *v, unsigned int irq,
         unsigned int state, unsigned int priority);
diff --git a/xen/include/asm-arm/irq.h b/xen/include/asm-arm/irq.h
index 80ff68d..346dc1d 100644
--- a/xen/include/asm-arm/irq.h
+++ b/xen/include/asm-arm/irq.h
@@ -46,6 +46,12 @@ int __init request_dt_irq(const struct dt_irq *irq,
                           void *dev_id);
 int __init setup_dt_irq(const struct dt_irq *irq, struct irqaction *new);
 
+#define FIRST_SGI_IRQ   32
+static inline bool_t irq_is_sgi(unsigned int irq)
+{
+    return (irq >= FIRST_SGI_IRQ);
+}
+
 #endif /* _ASM_HW_IRQ_H */
 /*
  * Local variables:
