static const struct irq_domain_ops *vpe_domain_ops;
 static const struct irq_domain_ops *sgi_domain_ops;
 
+static bool has_v4_1(void)
+{
+       return !!sgi_domain_ops;
+}
+
 int its_alloc_vcpu_irqs(struct its_vm *vm)
 {
        int vpe_base_irq, i;
        return irq_set_vcpu_affinity(vpe->irq, info);
 }
 
-int its_schedule_vpe(struct its_vpe *vpe, bool on)
+int its_make_vpe_non_resident(struct its_vpe *vpe, bool db)
 {
-       struct its_cmd_info info;
+       struct irq_desc *desc = irq_to_desc(vpe->irq);
+       struct its_cmd_info info = { };
        int ret;
 
        WARN_ON(preemptible());
 
-       info.cmd_type = on ? SCHEDULE_VPE : DESCHEDULE_VPE;
+       info.cmd_type = DESCHEDULE_VPE;
+       if (has_v4_1()) {
+               /* GICv4.1 can directly deal with doorbells */
+               info.req_db = db;
+       } else {
+               /* Undo the nested disable_irq() calls... */
+               while (db && irqd_irq_disabled(&desc->irq_data))
+                       enable_irq(vpe->irq);
+       }
+
+       ret = its_send_vpe_cmd(vpe, &info);
+       if (!ret)
+               vpe->resident = false;
+
+       return ret;
+}
+
+int its_make_vpe_resident(struct its_vpe *vpe, bool g0en, bool g1en)
+{
+       struct its_cmd_info info = { };
+       int ret;
+
+       WARN_ON(preemptible());
+
+       info.cmd_type = SCHEDULE_VPE;
+       if (has_v4_1()) {
+               info.g0en = g0en;
+               info.g1en = g1en;
+       } else {
+               /* Disabled the doorbell, as we're about to enter the guest */
+               disable_irq_nosync(vpe->irq);
+       }
 
        ret = its_send_vpe_cmd(vpe, &info);
        if (!ret)
-               vpe->resident = on;
+               vpe->resident = true;
 
        return ret;
 }
 
 
 int its_alloc_vcpu_irqs(struct its_vm *vm);
 void its_free_vcpu_irqs(struct its_vm *vm);
-int its_schedule_vpe(struct its_vpe *vpe, bool on);
+int its_make_vpe_resident(struct its_vpe *vpe, bool g0en, bool g1en);
+int its_make_vpe_non_resident(struct its_vpe *vpe, bool db);
 int its_invall_vpe(struct its_vpe *vpe);
 int its_map_vlpi(int irq, struct its_vlpi_map *map);
 int its_get_vlpi(int irq, struct its_vlpi_map *map);
 
  * it. And if we've migrated our vcpu from one CPU to another, we must
  * tell the ITS (so that the messages reach the right redistributor).
  * This is done in two steps: first issue a irq_set_affinity() on the
- * irq corresponding to the vcpu, then call its_schedule_vpe(). You
- * must be in a non-preemptible context. On exit, another call to
- * its_schedule_vpe() tells the redistributor that we're done with the
- * vcpu.
+ * irq corresponding to the vcpu, then call its_make_vpe_resident().
+ * You must be in a non-preemptible context. On exit, a call to
+ * its_make_vpe_non_resident() tells the redistributor that we're done
+ * with the vcpu.
  *
  * Finally, the doorbell handling: Each vcpu is allocated an interrupt
  * which will fire each time a VLPI is made pending whilst the vcpu is
        struct kvm_vcpu *vcpu = info;
 
        /* We got the message, no need to fire again */
-       if (!irqd_irq_disabled(&irq_to_desc(irq)->irq_data))
+       if (!kvm_vgic_global_state.has_gicv4_1 &&
+           !irqd_irq_disabled(&irq_to_desc(irq)->irq_data))
                disable_irq_nosync(irq);
 
        vcpu->arch.vgic_cpu.vgic_v3.its_vpe.pending_last = true;
 int vgic_v4_put(struct kvm_vcpu *vcpu, bool need_db)
 {
        struct its_vpe *vpe = &vcpu->arch.vgic_cpu.vgic_v3.its_vpe;
-       struct irq_desc *desc = irq_to_desc(vpe->irq);
 
        if (!vgic_supports_direct_msis(vcpu->kvm) || !vpe->resident)
                return 0;
 
-       /*
-        * If blocking, a doorbell is required. Undo the nested
-        * disable_irq() calls...
-        */
-       while (need_db && irqd_irq_disabled(&desc->irq_data))
-               enable_irq(vpe->irq);
-
-       return its_schedule_vpe(vpe, false);
+       return its_make_vpe_non_resident(vpe, need_db);
 }
 
 int vgic_v4_load(struct kvm_vcpu *vcpu)
        if (err)
                return err;
 
-       /* Disabled the doorbell, as we're about to enter the guest */
-       disable_irq_nosync(vpe->irq);
-
-       err = its_schedule_vpe(vpe, true);
+       err = its_make_vpe_resident(vpe, false, vcpu->kvm->arch.vgic.enabled);
        if (err)
                return err;
 
        /*
         * Now that the VPE is resident, let's get rid of a potential
-        * doorbell interrupt that would still be pending.
+        * doorbell interrupt that would still be pending. This is a
+        * GICv4.0 only "feature"...
         */
-       return irq_set_irqchip_state(vpe->irq, IRQCHIP_STATE_PENDING, false);
+       if (!kvm_vgic_global_state.has_gicv4_1)
+               err = irq_set_irqchip_state(vpe->irq, IRQCHIP_STATE_PENDING, false);
+
+       return err;
 }
 
 static struct vgic_its *vgic_get_its(struct kvm *kvm,