summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--arch/arm64/kvm/vgic/vgic-v3.c6
-rw-r--r--arch/arm64/kvm/vgic/vgic.c13
2 files changed, 13 insertions, 6 deletions
diff --git a/arch/arm64/kvm/vgic/vgic-v3.c b/arch/arm64/kvm/vgic/vgic-v3.c
index 55847fbad4d0..968aa9d89be6 100644
--- a/arch/arm64/kvm/vgic/vgic-v3.c
+++ b/arch/arm64/kvm/vgic/vgic-v3.c
@@ -53,10 +53,14 @@ void vgic_v3_configure_hcr(struct kvm_vcpu *vcpu,
* need to deal with SPIs that can be deactivated on another
* CPU.
*
+ * On systems that do not implement TDIR, force the bit in the
+ * shadow state anyway to avoid IPI-ing on these poor sods.
+ *
* Note that we set the trap irrespective of EOIMode, as that
* can change behind our back without any warning...
*/
- if (irqs_active_outside_lrs(als) ||
+ if (!cpus_have_final_cap(ARM64_HAS_ICH_HCR_EL2_TDIR) ||
+ irqs_active_outside_lrs(als) ||
atomic_read(&vcpu->kvm->arch.vgic.active_spis))
cpuif->vgic_hcr |= ICH_HCR_EL2_TDIR;
}
diff --git a/arch/arm64/kvm/vgic/vgic.c b/arch/arm64/kvm/vgic/vgic.c
index 83969c18ef03..693ec005c996 100644
--- a/arch/arm64/kvm/vgic/vgic.c
+++ b/arch/arm64/kvm/vgic/vgic.c
@@ -370,12 +370,15 @@ static bool vgic_validate_injection(struct vgic_irq *irq, bool level, void *owne
static bool vgic_model_needs_bcst_kick(struct kvm *kvm)
{
/*
- * A GICv3 (or GICv3-like) system exposing a GICv3 to the
- * guest needs a broadcast kick to set TDIR globally, even if
- * the bit doesn't really exist (we still need to check for
- * the shadow bit in the DIR emulation fast-path).
+ * A GICv3 (or GICv3-like) system exposing a GICv3 to the guest
+ * needs a broadcast kick to set TDIR globally.
+ *
+ * For systems that do not have TDIR (ARM's own v8.0 CPUs), the
+ * shadow TDIR bit is always set, and so is the register's TC bit,
+ * so no need to kick the CPUs.
*/
- return (kvm->arch.vgic.vgic_model == KVM_DEV_TYPE_ARM_VGIC_V3);
+ return (cpus_have_final_cap(ARM64_HAS_ICH_HCR_EL2_TDIR) &&
+ kvm->arch.vgic.vgic_model == KVM_DEV_TYPE_ARM_VGIC_V3);
}
/*