__hyp_pa(init_params));
 }
 
+static int psci_system_suspend(u64 func_id, struct kvm_cpu_context *host_ctxt)
+{
+       DECLARE_REG(unsigned long, pc, host_ctxt, 1);
+       DECLARE_REG(unsigned long, r0, host_ctxt, 2);
+
+       struct psci_boot_args *boot_args;
+       struct kvm_nvhe_init_params *init_params;
+
+       boot_args = this_cpu_ptr(hyp_symbol_addr(suspend_args));
+       init_params = this_cpu_ptr(hyp_symbol_addr(kvm_init_params));
+
+       /*
+        * No need to acquire a lock before writing to boot_args because a core
+        * can only suspend itself. Racy CPU_ON calls use a separate struct.
+        */
+       boot_args->pc = pc;
+       boot_args->r0 = r0;
+
+       /* Will only return on error. */
+       return psci_call(func_id,
+                        __hyp_pa(hyp_symbol_addr(kvm_hyp_cpu_resume)),
+                        __hyp_pa(init_params), 0);
+}
+
 asmlinkage void __noreturn kvm_host_psci_cpu_entry(bool is_cpu_on)
 {
        struct psci_boot_args *boot_args;
        case PSCI_1_0_FN_SET_SUSPEND_MODE:
        case PSCI_1_1_FN64_SYSTEM_RESET2:
                return psci_forward(host_ctxt);
+       case PSCI_1_0_FN64_SYSTEM_SUSPEND:
+               return psci_system_suspend(func_id, host_ctxt);
        default:
                return psci_0_2_handler(func_id, host_ctxt);
        }