diff --git a/arch/arm64/kvm/fpsimd.c b/arch/arm64/kvm/fpsimd.c index ec8e4494873d..895d5a2ab1ce 100644 --- a/arch/arm64/kvm/fpsimd.c +++ b/arch/arm64/kvm/fpsimd.c @@ -178,7 +178,18 @@ void kvm_arch_vcpu_put_fp(struct kvm_vcpu *vcpu) if (vcpu_has_sve(vcpu)) { __vcpu_sys_reg(vcpu, ZCR_EL1) = read_sysreg_el1(SYS_ZCR); - /* Restore the VL that was saved when bound to the CPU */ + /* + * Restore the VL that was saved when bound to the CPU, + * which is the maximum VL for the guest. Because + * the layout of the data when saving the sve state + * depends on the VL, we need to use a consistent VL. + * Note that this means that at guest exit ZCR_EL1 is + * not necessarily the same as on guest entry. + * + * Flushing the cpu state sets the TIF_FOREIGN_FPSTATE + * bit for the context, which lets the kernel restore + * the sve state, including ZCR_EL1 later. + */ if (!has_vhe()) sve_cond_update_zcr_vq(vcpu_sve_max_vq(vcpu) - 1, SYS_ZCR_EL1);