@@ -587,6 +587,7 @@ static __always_inline u64 kvm_get_reset_cptr_el2(struct kvm_vcpu *vcpu)
} else if (has_hvhe()) {
val = (CPACR_EL1_FPEN_EL0EN | CPACR_EL1_FPEN_EL1EN);
+ /* Leave traps enabled, we will restore EL2 lazily */
if (!vcpu_has_sve(vcpu) ||
(vcpu->arch.fp_state != FP_STATE_GUEST_OWNED))
val |= CPACR_EL1_ZEN_EL1EN | CPACR_EL1_ZEN_EL0EN;
@@ -595,6 +596,7 @@ static __always_inline u64 kvm_get_reset_cptr_el2(struct kvm_vcpu *vcpu)
} else {
val = CPTR_NVHE_EL2_RES1;
+ /* Leave traps enabled, we will restore EL2 lazily */
if (vcpu_has_sve(vcpu) &&
(vcpu->arch.fp_state == FP_STATE_GUEST_OWNED))
val |= CPTR_EL2_TZ;
@@ -420,6 +420,7 @@ void handle_trap(struct kvm_cpu_context *host_ctxt)
handle_host_smc(host_ctxt);
break;
case ESR_ELx_EC_SVE:
+ /* Handle lazy restore of the host VL */
if (has_hvhe())
sysreg_clear_set(cpacr_el1, 0, (CPACR_EL1_ZEN_EL1EN |
CPACR_EL1_ZEN_EL0EN));
When we exit from a SVE guest we leave the SVE configuration in EL2 as it was for the guest, only switching back to the host configuration on next use by the host. This is perhaps a little surprising when encountered in the code by itself, add comments explaining what is going on both in the trap handler and when we configure the traps. Signed-off-by: Mark Brown <broonie@kernel.org> --- Changes in v2: - Rebase onto v6.9-rc1. - Link to v1: https://lore.kernel.org/r/20231221-kvm-arm64-nvhe-sve-trap-v1-1-332ecc56f694@kernel.org --- arch/arm64/include/asm/kvm_emulate.h | 2 ++ arch/arm64/kvm/hyp/nvhe/hyp-main.c | 1 + 2 files changed, 3 insertions(+) --- base-commit: 4cece764965020c22cff7665b18a012006359095 change-id: 20231218-kvm-arm64-nvhe-sve-trap-f65a3dd46a6a Best regards,