summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarc Zyngier <maz@kernel.org>2026-02-05 09:17:04 +0000
committerMarc Zyngier <maz@kernel.org>2026-02-05 09:17:04 +0000
commit1c880ea3efd77ce1a3e16aeb617fdd76d28e197a (patch)
tree9ca099eb8d14c2f865e341e8d62cc5818476da6d
parent26e013b3fc7e3a3f31c54d1064702594e8ef9a6c (diff)
parent28e505d81766dcbe25c60d57ab9fc941cd3d38bf (diff)
Merge branch kvm-arm64/gicv3-tdir-fixes into kvmarm-master/next
* kvm-arm64/gicv3-tdir-fixes: : . : Address two trapping-related issues when running legacy (i.e. GICv3) : guests on GICv5 hosts, courtesy of Sascha Bischoff. : . KVM: arm64: Correct test for ICH_HCR_EL2_TDIR cap for GICv5 hosts KVM: arm64: gic: Enable GICv3 CPUIF trapping on GICv5 hosts if required Signed-off-by: Marc Zyngier <maz@kernel.org>
-rw-r--r--arch/arm64/kernel/cpufeature.c8
-rw-r--r--arch/arm64/kvm/vgic/vgic-v3.c25
-rw-r--r--arch/arm64/kvm/vgic/vgic-v5.c2
-rw-r--r--arch/arm64/kvm/vgic/vgic.h1
4 files changed, 22 insertions, 14 deletions
diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
index c688d2225c94..35a3ffeb4efa 100644
--- a/arch/arm64/kernel/cpufeature.c
+++ b/arch/arm64/kernel/cpufeature.c
@@ -2335,16 +2335,16 @@ static bool can_trap_icv_dir_el1(const struct arm64_cpu_capabilities *entry,
BUILD_BUG_ON(ARM64_HAS_ICH_HCR_EL2_TDIR <= ARM64_HAS_GICV3_CPUIF);
BUILD_BUG_ON(ARM64_HAS_ICH_HCR_EL2_TDIR <= ARM64_HAS_GICV5_LEGACY);
- if (!this_cpu_has_cap(ARM64_HAS_GICV3_CPUIF) &&
- !is_midr_in_range_list(has_vgic_v3))
- return false;
-
if (!is_hyp_mode_available())
return false;
if (this_cpu_has_cap(ARM64_HAS_GICV5_LEGACY))
return true;
+ if (!this_cpu_has_cap(ARM64_HAS_GICV3_CPUIF) &&
+ !is_midr_in_range_list(has_vgic_v3))
+ return false;
+
if (is_kernel_in_hyp_mode())
res.a1 = read_sysreg_s(SYS_ICH_VTR_EL2);
else
diff --git a/arch/arm64/kvm/vgic/vgic-v3.c b/arch/arm64/kvm/vgic/vgic-v3.c
index 1d6dd1b545bd..4b03a726f164 100644
--- a/arch/arm64/kvm/vgic/vgic-v3.c
+++ b/arch/arm64/kvm/vgic/vgic-v3.c
@@ -880,6 +880,20 @@ void noinstr kvm_compute_ich_hcr_trap_bits(struct alt_instr *alt,
*updptr = cpu_to_le32(insn);
}
+void vgic_v3_enable_cpuif_traps(void)
+{
+ u64 traps = vgic_ich_hcr_trap_bits();
+
+ if (traps) {
+ kvm_info("GICv3 sysreg trapping enabled ([%s%s%s%s], reduced performance)\n",
+ (traps & ICH_HCR_EL2_TALL0) ? "G0" : "",
+ (traps & ICH_HCR_EL2_TALL1) ? "G1" : "",
+ (traps & ICH_HCR_EL2_TC) ? "C" : "",
+ (traps & ICH_HCR_EL2_TDIR) ? "D" : "");
+ static_branch_enable(&vgic_v3_cpuif_trap);
+ }
+}
+
/**
* vgic_v3_probe - probe for a VGICv3 compatible interrupt controller
* @info: pointer to the GIC description
@@ -891,7 +905,6 @@ int vgic_v3_probe(const struct gic_kvm_info *info)
{
u64 ich_vtr_el2 = kvm_call_hyp_ret(__vgic_v3_get_gic_config);
bool has_v2;
- u64 traps;
int ret;
has_v2 = ich_vtr_el2 >> 63;
@@ -955,15 +968,7 @@ int vgic_v3_probe(const struct gic_kvm_info *info)
kvm_vgic_global_state.ich_vtr_el2 &= ~ICH_VTR_EL2_SEIS;
}
- traps = vgic_ich_hcr_trap_bits();
- if (traps) {
- kvm_info("GICv3 sysreg trapping enabled ([%s%s%s%s], reduced performance)\n",
- (traps & ICH_HCR_EL2_TALL0) ? "G0" : "",
- (traps & ICH_HCR_EL2_TALL1) ? "G1" : "",
- (traps & ICH_HCR_EL2_TC) ? "C" : "",
- (traps & ICH_HCR_EL2_TDIR) ? "D" : "");
- static_branch_enable(&vgic_v3_cpuif_trap);
- }
+ vgic_v3_enable_cpuif_traps();
kvm_vgic_global_state.vctrl_base = NULL;
kvm_vgic_global_state.type = VGIC_V3;
diff --git a/arch/arm64/kvm/vgic/vgic-v5.c b/arch/arm64/kvm/vgic/vgic-v5.c
index 2d3811f4e117..331651087e2c 100644
--- a/arch/arm64/kvm/vgic/vgic-v5.c
+++ b/arch/arm64/kvm/vgic/vgic-v5.c
@@ -48,5 +48,7 @@ int vgic_v5_probe(const struct gic_kvm_info *info)
static_branch_enable(&kvm_vgic_global_state.gicv3_cpuif);
kvm_info("GCIE legacy system register CPU interface\n");
+ vgic_v3_enable_cpuif_traps();
+
return 0;
}
diff --git a/arch/arm64/kvm/vgic/vgic.h b/arch/arm64/kvm/vgic/vgic.h
index 5f0fc96b4dc2..c9b3bb07e483 100644
--- a/arch/arm64/kvm/vgic/vgic.h
+++ b/arch/arm64/kvm/vgic/vgic.h
@@ -324,6 +324,7 @@ void vgic_v3_configure_hcr(struct kvm_vcpu *vcpu, struct ap_list_summary *als);
void vgic_v3_set_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr);
void vgic_v3_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr);
void vgic_v3_reset(struct kvm_vcpu *vcpu);
+void vgic_v3_enable_cpuif_traps(void);
int vgic_v3_probe(const struct gic_kvm_info *info);
int vgic_v3_map_resources(struct kvm *kvm);
int vgic_v3_lpi_sync_pending_status(struct kvm *kvm, struct vgic_irq *irq);