KVM: arm64: Ensure that SME controls are disabled in protected mode

KVM (and pKVM) do not support SME guests. Therefore KVM ensures
that the host's SME state is flushed and that SME controls for
enabling access to ZA storage and for streaming are disabled.

pKVM needs to protect against a buggy/malicious host. Ensure that
it wouldn't run a guest when protected mode is enabled should any
of the SME controls be enabled.

Signed-off-by: Fuad Tabba <tabba@google.com>
diff --git a/arch/arm64/kvm/fpsimd.c b/arch/arm64/kvm/fpsimd.c
index 50635d2..6576f08 100644
--- a/arch/arm64/kvm/fpsimd.c
+++ b/arch/arm64/kvm/fpsimd.c
@@ -83,6 +83,13 @@
 			fpsimd_save_and_flush_cpu_state();
 		}
 	}
+
+	/*
+	 * If normal guests gain this support, maintain this behavior
+	 * for pKVM guests, which don't support SME.
+	 */
+	BUG_ON(is_protected_kvm_enabled() && system_supports_sme() &&
+	       read_sysreg_s(SYS_SVCR));
 }
 
 /*
diff --git a/arch/arm64/kvm/hyp/nvhe/hyp-main.c b/arch/arm64/kvm/hyp/nvhe/hyp-main.c
index 9c0fb86..9cfe911 100644
--- a/arch/arm64/kvm/hyp/nvhe/hyp-main.c
+++ b/arch/arm64/kvm/hyp/nvhe/hyp-main.c
@@ -814,6 +814,16 @@
 		goto out;
 	}
 
+	/*
+	 * KVM (and pKVM) doesn't support SME guests, and ensures that SME
+	 * features aren't enabled in pstate when loading a vcpu. Therefore,
+	 * if SME features enabled it's either a bug or a malicious host.
+	 */
+	if (unlikely(system_supports_sme() && read_sysreg_s(SYS_SVCR))) {
+		ret = -EINVAL;
+		goto out;
+	}
+
 	if (unlikely(hyp_vcpu)) {
 		flush_hyp_vcpu(hyp_vcpu);