#define KVM_ARM64_DEBUG_STATE_SAVE_TRBE        (1 << 13) /* Save TRBE context if active  */
 #define KVM_ARM64_FP_FOREIGN_FPSTATE   (1 << 14)
 #define KVM_ARM64_ON_UNSUPPORTED_CPU   (1 << 15) /* Physical CPU not in supported_cpus */
+#define KVM_ARM64_HOST_SME_ENABLED     (1 << 16) /* SME enabled for EL0 */
 
 #define KVM_GUESTDBG_VALID_MASK (KVM_GUESTDBG_ENABLE | \
                                 KVM_GUESTDBG_USE_SW_BP | \
 
 
        if (read_sysreg(cpacr_el1) & CPACR_EL1_ZEN_EL0EN)
                vcpu->arch.flags |= KVM_ARM64_HOST_SVE_ENABLED;
+
+       /*
+        * We don't currently support SME guests but if we leave
+        * things in streaming mode then when the guest starts running
+        * FPSIMD or SVE code it may generate SME traps so as a
+        * special case if we are in streaming mode we force the host
+        * state to be saved now and exit streaming mode so that we
+        * don't have to handle any SME traps for valid guest
+        * operations. Do this for ZA as well for now for simplicity.
+        */
+       if (system_supports_sme()) {
+               if (read_sysreg(cpacr_el1) & CPACR_EL1_SMEN_EL0EN)
+                       vcpu->arch.flags |= KVM_ARM64_HOST_SME_ENABLED;
+
+               if (read_sysreg_s(SYS_SVCR_EL0) &
+                   (SYS_SVCR_EL0_SM_MASK | SYS_SVCR_EL0_ZA_MASK)) {
+                       vcpu->arch.flags &= ~KVM_ARM64_FP_HOST;
+                       fpsimd_save_and_flush_cpu_state();
+               }
+       }
 }
 
 /*
 
        local_irq_save(flags);
 
+       /*
+        * If we have VHE then the Hyp code will reset CPACR_EL1 to
+        * CPACR_EL1_DEFAULT and we need to reenable SME.
+        */
+       if (has_vhe() && system_supports_sme()) {
+               /* Also restore EL0 state seen on entry */
+               if (vcpu->arch.flags & KVM_ARM64_HOST_SME_ENABLED)
+                       sysreg_clear_set(CPACR_EL1, 0,
+                                        CPACR_EL1_SMEN_EL0EN |
+                                        CPACR_EL1_SMEN_EL1EN);
+               else
+                       sysreg_clear_set(CPACR_EL1,
+                                        CPACR_EL1_SMEN_EL0EN,
+                                        CPACR_EL1_SMEN_EL1EN);
+       }
+
        if (vcpu->arch.flags & KVM_ARM64_FP_ENABLED) {
                if (vcpu_has_sve(vcpu)) {
                        __vcpu_sys_reg(vcpu, ZCR_EL1) = read_sysreg_el1(SYS_ZCR);