The emulation code is activated by setting params->vcpu_base to zero Signed-off-by: Pavel Fedin <p.fedin@xxxxxxxxxxx> --- include/kvm/arm_vgic.h | 1 + virt/kvm/arm/vgic-v2-emul.c | 60 ++++++++++++++++++++++++++++++++++++++++----- 2 files changed, 55 insertions(+), 6 deletions(-) diff --git a/include/kvm/arm_vgic.h b/include/kvm/arm_vgic.h index 31cda96..fa533e7 100644 --- a/include/kvm/arm_vgic.h +++ b/include/kvm/arm_vgic.h @@ -254,6 +254,7 @@ struct vgic_dist { struct vgic_vm_ops vm_ops; struct vgic_io_device dist_iodev; + struct vgic_io_device cpu_iodev; struct vgic_io_device *redist_iodevs; }; diff --git a/virt/kvm/arm/vgic-v2-emul.c b/virt/kvm/arm/vgic-v2-emul.c index 1390797..c2e1274 100644 --- a/virt/kvm/arm/vgic-v2-emul.c +++ b/virt/kvm/arm/vgic-v2-emul.c @@ -404,6 +404,8 @@ static const struct vgic_io_range vgic_dist_ranges[] = { {} }; +static const struct vgic_io_range vgic_cpu_ranges[]; + static void vgic_dispatch_sgi(struct kvm_vcpu *vcpu, u32 reg) { struct kvm *kvm = vcpu->kvm; @@ -520,12 +522,20 @@ static int vgic_v2_map_resources(struct kvm *kvm, goto out_unregister; } - ret = kvm_phys_addr_ioremap(kvm, dist->vgic_cpu_base, - params->vcpu_base, KVM_VGIC_V2_CPU_SIZE, - true); - if (ret) { - kvm_err("Unable to remap VGIC CPU to VCPU\n"); - goto out_unregister; + if (params->vcpu_base) { + ret = kvm_phys_addr_ioremap(kvm, dist->vgic_cpu_base, + params->vcpu_base, + KVM_VGIC_V2_CPU_SIZE, true); + if (ret) { + kvm_err("Unable to remap VGIC CPU to VCPU\n"); + goto out_unregister; + } + } else { + vgic_register_kvm_io_dev(kvm, dist->vgic_cpu_base, + KVM_VGIC_V2_CPU_SIZE, + vgic_cpu_ranges, -1, + &dist->cpu_iodev); + dist->sw_cpuif = true; } dist->ready = true; @@ -611,6 +621,34 @@ static bool handle_cpu_mmio_misc(struct kvm_vcpu *vcpu, return updated; } +static bool handle_mmio_intack(struct kvm_vcpu *vcpu, + struct kvm_exit_mmio *mmio, phys_addr_t offset) +{ + int pending; + + if (mmio->is_write) + return false; + + pending = vgic_get_pending_irq(vcpu); + mmio_data_write(mmio, ~0, pending); + + return true; +} + +static bool handle_mmio_eoi(struct kvm_vcpu *vcpu, + struct kvm_exit_mmio *mmio, phys_addr_t offset) +{ + u32 reg; + + if (!mmio->is_write) + return false; + + reg = mmio_data_read(mmio, ~0); + vgic_clear_pending_irq(vcpu, reg); + + return false; +} + static bool handle_mmio_abpr(struct kvm_vcpu *vcpu, struct kvm_exit_mmio *mmio, phys_addr_t offset) { @@ -645,6 +683,16 @@ static const struct vgic_io_range vgic_cpu_ranges[] = { .handle_mmio = handle_cpu_mmio_misc, }, { + .base = GIC_CPU_INTACK, + .len = 4, + .handle_mmio = handle_mmio_intack, + }, + { + .base = GIC_CPU_EOI, + .len = 4, + .handle_mmio = handle_mmio_eoi, + }, + { .base = GIC_CPU_ALIAS_BINPOINT, .len = 4, .handle_mmio = handle_mmio_abpr, -- 2.1.4 -- To unsubscribe from this list: send the line "unsubscribe kvm" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html