arm/arm64: KVM: add virtual GICv3 distributor emulation
With everything separated and prepared, we implement a model of a
GICv3 distributor and redistributors by using the existing framework
to provide handler functions for each register group.
Currently we limit the emulation to a model enforcing a single
security state, with SRE==1 (forcing system register access) and
ARE==1 (allowing more than 8 VCPUs).
We share some of the functions provided for GICv2 emulation, but take
the different ways of addressing (v)CPUs into account.
Save and restore is currently not implemented.
Similar to the split-off of the GICv2 specific code, the new emulation
code goes into a new file (vgic-v3-emul.c).
Signed-off-by: Andre Przywara <andre.przywara@arm.com>
Signed-off-by: Christoffer Dall <christoffer.dall@linaro.org>
diff --git a/virt/kvm/arm/vgic.c b/virt/kvm/arm/vgic.c
index b6e17c8..6d23e57 100644
--- a/virt/kvm/arm/vgic.c
+++ b/virt/kvm/arm/vgic.c
@@ -1249,7 +1249,7 @@
struct kvm_vcpu *vcpu;
int edge_triggered, level_triggered;
int enabled;
- bool ret = true;
+ bool ret = true, can_inject = true;
spin_lock(&dist->lock);
@@ -1264,6 +1264,11 @@
if (irq_num >= VGIC_NR_PRIVATE_IRQS) {
cpuid = dist->irq_spi_cpu[irq_num - VGIC_NR_PRIVATE_IRQS];
+ if (cpuid == VCPU_NOT_ALLOCATED) {
+ /* Pretend we use CPU0, and prevent injection */
+ cpuid = 0;
+ can_inject = false;
+ }
vcpu = kvm_get_vcpu(kvm, cpuid);
}
@@ -1286,7 +1291,7 @@
enabled = vgic_irq_is_enabled(vcpu, irq_num);
- if (!enabled) {
+ if (!enabled || !can_inject) {
ret = false;
goto out;
}
@@ -1439,6 +1444,7 @@
}
kfree(dist->irq_sgi_sources);
kfree(dist->irq_spi_cpu);
+ kfree(dist->irq_spi_mpidr);
kfree(dist->irq_spi_target);
kfree(dist->irq_pending_on_cpu);
dist->irq_sgi_sources = NULL;
@@ -1594,6 +1600,7 @@
kvm->arch.vgic.vctrl_base = vgic->vctrl_base;
kvm->arch.vgic.vgic_dist_base = VGIC_ADDR_UNDEF;
kvm->arch.vgic.vgic_cpu_base = VGIC_ADDR_UNDEF;
+ kvm->arch.vgic.vgic_redist_base = VGIC_ADDR_UNDEF;
out_unlock:
for (; vcpu_lock_idx >= 0; vcpu_lock_idx--) {