]> www.infradead.org Git - nvme.git/commitdiff
KVM: arm64: nv: Forward SVE traps to guest hypervisor
authorOliver Upton <oliver.upton@linux.dev>
Thu, 20 Jun 2024 16:46:39 +0000 (16:46 +0000)
committerOliver Upton <oliver.upton@linux.dev>
Thu, 20 Jun 2024 19:01:20 +0000 (19:01 +0000)
Similar to FPSIMD traps, don't load SVE state if the guest hypervisor
has SVE traps enabled and forward the trap instead. Note that ZCR_EL2
will require some special handling, as it takes a sysreg trap to EL2
when HCR_EL2.NV = 1.

Reviewed-by: Marc Zyngier <maz@kernel.org>
Link: https://lore.kernel.org/r/20240620164653.1130714-3-oliver.upton@linux.dev
Signed-off-by: Oliver Upton <oliver.upton@linux.dev>
arch/arm64/include/asm/kvm_emulate.h
arch/arm64/kvm/handle_exit.c
arch/arm64/kvm/hyp/include/hyp/switch.h

index 29fdeb5b3c96cfdf33f56bfa0bf1d71d57eeb4ea..befef5d0daae37eb6f48d8d7eb5c4e226e0538a4 100644 (file)
@@ -702,5 +702,9 @@ static inline bool guest_hyp_fpsimd_traps_enabled(const struct kvm_vcpu *vcpu)
        return __guest_hyp_cptr_xen_trap_enabled(vcpu, FPEN);
 }
 
+static inline bool guest_hyp_sve_traps_enabled(const struct kvm_vcpu *vcpu)
+{
+       return __guest_hyp_cptr_xen_trap_enabled(vcpu, ZEN);
+}
 
 #endif /* __ARM64_KVM_EMULATE_H__ */
index 59fe9b10a87a61f2cdf199aea9ec43c6af01b891..e4f74699f3608c984adf40477c3f0c5ef8c6e561 100644 (file)
@@ -217,6 +217,9 @@ static int kvm_handle_unknown_ec(struct kvm_vcpu *vcpu)
  */
 static int handle_sve(struct kvm_vcpu *vcpu)
 {
+       if (guest_hyp_sve_traps_enabled(vcpu))
+               return kvm_inject_nested_sync(vcpu, kvm_vcpu_get_esr(vcpu));
+
        kvm_inject_undefined(vcpu);
        return 1;
 }
index b398f2320e9410754f4f30badcea8d6a3cf6df42..be1b22b9c324627d7d1bb51f977c1b7689b4ab8e 100644 (file)
@@ -361,6 +361,8 @@ static bool kvm_hyp_handle_fpsimd(struct kvm_vcpu *vcpu, u64 *exit_code)
        case ESR_ELx_EC_SVE:
                if (!sve_guest)
                        return false;
+               if (guest_hyp_sve_traps_enabled(vcpu))
+                       return false;
                break;
        default:
                return false;