diff options
author | Marc Zyngier <maz@kernel.org> | 2021-03-11 21:29:55 +0300 |
---|---|---|
committer | Marc Zyngier <maz@kernel.org> | 2021-03-18 17:23:12 +0300 |
commit | 8c8010d69c1322734a272eb95dbbf42b5190e565 (patch) | |
tree | b67366c7598da31074f57b7de4e569fff294dde7 /arch/arm64/kvm/fpsimd.c | |
parent | beed09067b428a7e84a53b05c1de1f93c8460e91 (diff) | |
download | linux-8c8010d69c1322734a272eb95dbbf42b5190e565.tar.xz |
KVM: arm64: Save/restore SVE state for nVHE
Implement the SVE save/restore for nVHE, following a similar
logic to that of the VHE implementation:
- the SVE state is switched on trap from EL1 to EL2
- no further changes to ZCR_EL2 occur as long as the guest isn't
preempted or exit to userspace
- ZCR_EL2 is reset to its default value on the first SVE access from
the host EL1, and ZCR_EL1 restored to the default guest value in
vcpu_put()
Acked-by: Will Deacon <will@kernel.org>
Signed-off-by: Marc Zyngier <maz@kernel.org>
Diffstat (limited to 'arch/arm64/kvm/fpsimd.c')
-rw-r--r-- | arch/arm64/kvm/fpsimd.c | 10 |
1 files changed, 8 insertions, 2 deletions
diff --git a/arch/arm64/kvm/fpsimd.c b/arch/arm64/kvm/fpsimd.c index 14ea05c5134a..5621020b28de 100644 --- a/arch/arm64/kvm/fpsimd.c +++ b/arch/arm64/kvm/fpsimd.c @@ -121,11 +121,17 @@ void kvm_arch_vcpu_put_fp(struct kvm_vcpu *vcpu) local_irq_save(flags); if (vcpu->arch.flags & KVM_ARM64_FP_ENABLED) { - if (guest_has_sve) + if (guest_has_sve) { __vcpu_sys_reg(vcpu, ZCR_EL1) = read_sysreg_el1(SYS_ZCR); + /* Restore the VL that was saved when bound to the CPU */ + if (!has_vhe()) + sve_cond_update_zcr_vq(vcpu_sve_max_vq(vcpu) - 1, + SYS_ZCR_EL1); + } + fpsimd_save_and_flush_cpu_state(); - } else if (host_has_sve) { + } else if (has_vhe() && host_has_sve) { /* * The FPSIMD/SVE state in the CPU has not been touched, and we * have SVE (and VHE): CPACR_EL1 (alias CPTR_EL2) has been |