The emulation code is activated by setting params->vcpu_base to zero
Signed-off-by: Pavel Fedin <[email protected]>
---
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 [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html