[PATCH v3 4/5] KVM: arm64: vgic: Do not access the GICv5 CPU interface from EL1

Fuad Tabba fuad.tabba at linux.dev
Mon Oct 12 09:15:23 PDT 2026


can_access_vgic_from_kernel() requires VHE only for the GICv3 system
register interface, so on a native GICv5 system without
FEAT_GCIE_LEGACY it returns true under nVHE. The kernel then saves and
restores the CPU interface from EL1, where ICH_VMCR_EL2 and the
ICH_PPI_* registers are UNDEFINED, and running a vCPU oopses the host.
The nVHE world switch already does that work at EL2.

Anything that requires EL2 system registers or instructions is out of
reach of a kernel running at EL1, which leaves GICv2, the one
memory-mapped CPU interface. Allow GICv2 from EL1 and require VHE for
everything else.

Fixes: 9b8e3d4ca0e73 ("KVM: arm64: gic-v5: Implement GICv5 load/put and save/restore")
Suggested-by: Marc Zyngier <maz at kernel.org>
Reviewed-by: Sascha Bischoff <sascha.bischoff at arm.com>
Signed-off-by: Fuad Tabba <fuad.tabba at linux.dev>
---
 arch/arm64/kvm/vgic/vgic.c | 7 +++----
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/arch/arm64/kvm/vgic/vgic.c b/arch/arm64/kvm/vgic/vgic.c
index b25303d9919fd..fe5b14a8b1214 100644
--- a/arch/arm64/kvm/vgic/vgic.c
+++ b/arch/arm64/kvm/vgic/vgic.c
@@ -1045,11 +1045,10 @@ static void vgic_flush_lr_state(struct kvm_vcpu *vcpu)
 static inline bool can_access_vgic_from_kernel(void)
 {
 	/*
-	 * GICv2 can always be accessed from the kernel because it is
-	 * memory-mapped, and VHE systems can access GICv3 EL2 system
-	 * registers.
+	 * GICv2 is memory-mapped. Every other CPU interface uses EL2 system
+	 * registers, which only VHE can access from the kernel.
 	 */
-	return !static_branch_unlikely(&kvm_vgic_global_state.gicv3_cpuif) || has_vhe();
+	return has_vhe() || kvm_vgic_global_state.type == VGIC_V2;
 }
 
 static inline void vgic_save_state(struct kvm_vcpu *vcpu)
-- 
2.39.5




More information about the linux-arm-kernel mailing list