diff options
author | Oliver Upton <oliver.upton@linux.dev> | 2024-06-20 16:46:44 +0000 |
---|---|---|
committer | Oliver Upton <oliver.upton@linux.dev> | 2024-06-20 19:02:40 +0000 |
commit | 2e3cf82063a00ea0629e03e223c7c6ba58718f12 (patch) | |
tree | 4cd1fca3bf1eec10415b8682378ccae1a660ce02 | |
parent | 9092aca9fe9aa986b573355affdd190710a906c0 (diff) | |
download | linux-stable-2e3cf82063a00ea0629e03e223c7c6ba58718f12.tar.gz linux-stable-2e3cf82063a00ea0629e03e223c7c6ba58718f12.tar.bz2 linux-stable-2e3cf82063a00ea0629e03e223c7c6ba58718f12.zip |
KVM: arm64: nv: Ensure correct VL is loaded before saving SVE state
It is possible that the guest hypervisor has selected a smaller VL than
the maximum for its nested guest. As such, ZCR_EL2 may be configured for
a different VL when exiting a nested guest.
Set ZCR_EL2 (via the EL1 alias) to the maximum VL for the VM before
saving SVE state as the SVE save area is dimensioned by the max VL.
Reviewed-by: Marc Zyngier <maz@kernel.org>
Link: https://lore.kernel.org/r/20240620164653.1130714-8-oliver.upton@linux.dev
Signed-off-by: Oliver Upton <oliver.upton@linux.dev>
-rw-r--r-- | arch/arm64/kvm/fpsimd.c | 11 |
1 files changed, 7 insertions, 4 deletions
diff --git a/arch/arm64/kvm/fpsimd.c b/arch/arm64/kvm/fpsimd.c index 0815ff0347f5..c53e5b14038d 100644 --- a/arch/arm64/kvm/fpsimd.c +++ b/arch/arm64/kvm/fpsimd.c @@ -195,11 +195,14 @@ void kvm_arch_vcpu_put_fp(struct kvm_vcpu *vcpu) * Note that this means that at guest exit ZCR_EL1 is * not necessarily the same as on guest entry. * - * Restoring the VL isn't needed in VHE mode since - * ZCR_EL2 (accessed via ZCR_EL1) would fulfill the same - * role when doing the save from EL2. + * ZCR_EL2 holds the guest hypervisor's VL when running + * a nested guest, which could be smaller than the + * max for the vCPU. Similar to above, we first need to + * switch to a VL consistent with the layout of the + * vCPU's SVE state. KVM support for NV implies VHE, so + * using the ZCR_EL1 alias is safe. */ - if (!has_vhe()) + if (!has_vhe() || (vcpu_has_nv(vcpu) && !is_hyp_ctxt(vcpu))) sve_cond_update_zcr_vq(vcpu_sve_max_vq(vcpu) - 1, SYS_ZCR_EL1); } |