]> xenbits.xensource.com Git - people/pauldu/linux.git/commitdiff
KVM: arm64: Trap host SVE accesses when the FPSIMD state is dirty
authorMarc Zyngier <maz@kernel.org>
Wed, 17 Mar 2021 16:50:39 +0000 (16:50 +0000)
committerMarc Zyngier <maz@kernel.org>
Thu, 18 Mar 2021 14:22:31 +0000 (14:22 +0000)
ZCR_EL2 controls the upper bound for ZCR_EL1, and is set to
a potentially lower limit when the guest uses SVE. In order
to restore the SVE state on the EL1 host, we must first
reset ZCR_EL2 to its original value.

To make it as lazy as possible on the EL1 host side, set
the SVE trapping in place when exiting from the guest.
On the first EL1 access to SVE, ZCR_EL2 will be restored
to its full glory.

Suggested-by: Andrew Scull <ascull@google.com>
Acked-by: Will Deacon <will@kernel.org>
Signed-off-by: Marc Zyngier <maz@kernel.org>
arch/arm64/kvm/hyp/nvhe/hyp-main.c
arch/arm64/kvm/hyp/nvhe/switch.c

index f012f8665ecc1c6a0510bf25705b738f5660a077..8d04d69edd15e48b2254088c9dc651c8f3935538 100644 (file)
@@ -177,6 +177,10 @@ void handle_trap(struct kvm_cpu_context *host_ctxt)
        case ESR_ELx_EC_SMC64:
                handle_host_smc(host_ctxt);
                break;
+       case ESR_ELx_EC_SVE:
+               sve_cond_update_zcr_vq(ZCR_ELx_LEN_MASK, SYS_ZCR_EL2);
+               sysreg_clear_set(cptr_el2, CPTR_EL2_TZ, 0);
+               break;
        default:
                hyp_panic();
        }
index f3d0e9eca56cd2a62de3f31a77926ee8c478390a..60adc7ff4caa72f170ffc8c9217d39acc59b10db 100644 (file)
@@ -68,7 +68,7 @@ static void __activate_traps(struct kvm_vcpu *vcpu)
 static void __deactivate_traps(struct kvm_vcpu *vcpu)
 {
        extern char __kvm_hyp_host_vector[];
-       u64 mdcr_el2;
+       u64 mdcr_el2, cptr;
 
        ___deactivate_traps(vcpu);
 
@@ -101,7 +101,12 @@ static void __deactivate_traps(struct kvm_vcpu *vcpu)
                write_sysreg(HCR_HOST_NVHE_PROTECTED_FLAGS, hcr_el2);
        else
                write_sysreg(HCR_HOST_NVHE_FLAGS, hcr_el2);
-       write_sysreg(CPTR_EL2_DEFAULT, cptr_el2);
+
+       cptr = CPTR_EL2_DEFAULT;
+       if (vcpu_has_sve(vcpu) && (vcpu->arch.flags & KVM_ARM64_FP_ENABLED))
+               cptr |= CPTR_EL2_TZ;
+
+       write_sysreg(cptr, cptr_el2);
        write_sysreg(__kvm_hyp_host_vector, vbar_el2);
 }