summaryrefslogtreecommitdiffstats
path: root/arch/arm64/kvm/hyp/nvhe/psci-relay.c
diff options
context:
space:
mode:
authorDavid Brazdil <dbrazdil@google.com>2020-12-02 18:41:19 +0000
committerMarc Zyngier <maz@kernel.org>2020-12-04 10:08:35 +0000
commitd945f8d9ec4ab5b062ce9696761ca3a21de1e64d (patch)
treecc83fad9329fb7e136b6b04d6592c9fed48f6147 /arch/arm64/kvm/hyp/nvhe/psci-relay.c
parentabf16336dd22d018cd2577f0789b01ed705484d7 (diff)
downloadlinux-d945f8d9ec4ab5b062ce9696761ca3a21de1e64d.tar.bz2
KVM: arm64: Intercept host's SYSTEM_SUSPEND PSCI SMCs
Add a handler of SYSTEM_SUSPEND host PSCI SMCs. The semantics are equivalent to CPU_SUSPEND, typically called on the last online CPU. Reuse the same entry point and boot args struct as CPU_SUSPEND. Signed-off-by: David Brazdil <dbrazdil@google.com> Signed-off-by: Marc Zyngier <maz@kernel.org> Link: https://lore.kernel.org/r/20201202184122.26046-24-dbrazdil@google.com
Diffstat (limited to 'arch/arm64/kvm/hyp/nvhe/psci-relay.c')
-rw-r--r--arch/arm64/kvm/hyp/nvhe/psci-relay.c26
1 files changed, 26 insertions, 0 deletions
diff --git a/arch/arm64/kvm/hyp/nvhe/psci-relay.c b/arch/arm64/kvm/hyp/nvhe/psci-relay.c
index 688cf7f40d42..08dc9de69314 100644
--- a/arch/arm64/kvm/hyp/nvhe/psci-relay.c
+++ b/arch/arm64/kvm/hyp/nvhe/psci-relay.c
@@ -201,6 +201,30 @@ static int psci_cpu_suspend(u64 func_id, struct kvm_cpu_context *host_ctxt)
__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;
@@ -265,6 +289,8 @@ static unsigned long psci_1_0_handler(u64 func_id, struct kvm_cpu_context *host_
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);
}