From cd38c10e191eb2c37b9904a6ffc3b6bf4d9c0c48 Mon Sep 17 00:00:00 2001 From: Fuad Tabba Date: Mon, 12 Oct 2026 17:15:23 +0100 Subject: [PATCH] KVM: arm64: vgic: Do not access the GICv5 CPU interface from EL1 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 Reviewed-by: Sascha Bischoff Signed-off-by: Fuad Tabba Link: https://patch.msgid.link/20261012161524.4016464-5-fuad.tabba@linux.dev Signed-off-by: Marc Zyngier --- 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 b25303d9919f..fe5b14a8b121 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)