static const struct vgic_ops *vgic_ops;
 static const struct vgic_params *vgic;
 
+static void add_sgi_source(struct kvm_vcpu *vcpu, int irq, int source)
+{
+       vcpu->kvm->arch.vgic.vm_ops.add_sgi_source(vcpu, irq, source);
+}
+
+static bool queue_sgi(struct kvm_vcpu *vcpu, int irq)
+{
+       return vcpu->kvm->arch.vgic.vm_ops.queue_sgi(vcpu, irq);
+}
+
+int kvm_vgic_map_resources(struct kvm *kvm)
+{
+       return kvm->arch.vgic.vm_ops.map_resources(kvm, vgic);
+}
+
 /*
  * struct vgic_bitmap contains a bitmap made of unsigned longs, but
  * extracts u32s out of them.
        return false;
 }
 
+static void vgic_v2_add_sgi_source(struct kvm_vcpu *vcpu, int irq, int source)
+{
+       struct vgic_dist *dist = &vcpu->kvm->arch.vgic;
+
+       *vgic_get_sgi_sources(dist, vcpu->vcpu_id, irq) |= 1 << source;
+}
+
 /**
  * vgic_unqueue_irqs - move pending IRQs from LRs to the distributor
  * @vgic_cpu: Pointer to the vgic_cpu struct holding the LRs
  */
 static void vgic_unqueue_irqs(struct kvm_vcpu *vcpu)
 {
-       struct vgic_dist *dist = &vcpu->kvm->arch.vgic;
        struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu;
-       int vcpu_id = vcpu->vcpu_id;
        int i;
 
        for_each_set_bit(i, vgic_cpu->lr_used, vgic_cpu->nr_lr) {
                 */
                vgic_dist_irq_set_pending(vcpu, lr.irq);
                if (lr.irq < VGIC_NR_SGIS)
-                       *vgic_get_sgi_sources(dist, vcpu_id, lr.irq) |= 1 << lr.source;
+                       add_sgi_source(vcpu, lr.irq, lr.source);
                lr.state &= ~LR_STATE_PENDING;
                vgic_set_lr(vcpu, i, lr);
 
  *
  * returns true if the MMIO access has been performed in kernel space,
  * and false if it needs to be emulated in user space.
+ * Calls the actual handling routine for the selected VGIC model.
  */
 bool vgic_handle_mmio(struct kvm_vcpu *vcpu, struct kvm_run *run,
                      struct kvm_exit_mmio *mmio)
        if (!irqchip_in_kernel(vcpu->kvm))
                return false;
 
-       return vgic_v2_handle_mmio(vcpu, run, mmio);
+       /*
+        * This will currently call either vgic_v2_handle_mmio() or
+        * vgic_v3_handle_mmio(), which in turn will call
+        * vgic_handle_mmio_range() defined above.
+        */
+       return vcpu->kvm->arch.vgic.vm_ops.handle_mmio(vcpu, run, mmio);
 }
 
 static u8 *vgic_get_sgi_sources(struct vgic_dist *dist, int vcpu_id, int sgi)
        return true;
 }
 
-static bool vgic_queue_sgi(struct kvm_vcpu *vcpu, int irq)
+static bool vgic_v2_queue_sgi(struct kvm_vcpu *vcpu, int irq)
 {
        struct vgic_dist *dist = &vcpu->kvm->arch.vgic;
        unsigned long sources;
 
        /* SGIs */
        for_each_set_bit(i, vgic_cpu->pending_percpu, VGIC_NR_SGIS) {
-               if (!vgic_queue_sgi(vcpu, i))
+               if (!queue_sgi(vcpu, i))
                        overflow = 1;
        }
 
        dist->nr_cpus = 0;
 }
 
+static int vgic_v2_init_model(struct kvm *kvm)
+{
+       int i;
+
+       for (i = VGIC_NR_PRIVATE_IRQS; i < kvm->arch.vgic.nr_irqs; i += 4)
+               vgic_set_target_reg(kvm, 0, i);
+
+       return 0;
+}
+
 /*
  * Allocate and initialize the various data structures. Must be called
  * with kvm->lock held!
        if (ret)
                goto out;
 
-       for (i = VGIC_NR_PRIVATE_IRQS; i < dist->nr_irqs; i += 4)
-               vgic_set_target_reg(kvm, 0, i);
+       ret = kvm->arch.vgic.vm_ops.init_model(kvm);
+       if (ret)
+               goto out;
 
        kvm_for_each_vcpu(vcpu_id, vcpu, kvm) {
                ret = vgic_vcpu_init_maps(vcpu, nr_irqs);
  * can't do this at creation time, because user space must first set the
  * virtual CPU interface address in the guest physical address space.
  */
-int kvm_vgic_map_resources(struct kvm *kvm)
+static int vgic_v2_map_resources(struct kvm *kvm,
+                                const struct vgic_params *params)
 {
        int ret = 0;
 
        }
 
        ret = kvm_phys_addr_ioremap(kvm, kvm->arch.vgic.vgic_cpu_base,
-                                   vgic->vcpu_base, KVM_VGIC_V2_CPU_SIZE,
+                                   params->vcpu_base, KVM_VGIC_V2_CPU_SIZE,
                                    true);
        if (ret) {
                kvm_err("Unable to remap VGIC CPU to VCPU\n");
        return ret;
 }
 
+static void vgic_v2_init_emulation(struct kvm *kvm)
+{
+       struct vgic_dist *dist = &kvm->arch.vgic;
+
+       dist->vm_ops.handle_mmio = vgic_v2_handle_mmio;
+       dist->vm_ops.queue_sgi = vgic_v2_queue_sgi;
+       dist->vm_ops.add_sgi_source = vgic_v2_add_sgi_source;
+       dist->vm_ops.init_model = vgic_v2_init_model;
+       dist->vm_ops.map_resources = vgic_v2_map_resources;
+}
+
+static int init_vgic_model(struct kvm *kvm, int type)
+{
+       switch (type) {
+       case KVM_DEV_TYPE_ARM_VGIC_V2:
+               vgic_v2_init_emulation(kvm);
+               break;
+       default:
+               return -ENODEV;
+       }
+
+       return 0;
+}
+
 int kvm_vgic_create(struct kvm *kvm, u32 type)
 {
        int i, vcpu_lock_idx = -1, ret;
        }
        ret = 0;
 
+       ret = init_vgic_model(kvm, type);
+       if (ret)
+               goto out_unlock;
+
        spin_lock_init(&kvm->arch.vgic.lock);
        kvm->arch.vgic.in_kernel = true;
        kvm->arch.vgic.vgic_model = type;