From 2829c605886e4e984533dfd6617822f585334f29 Mon Sep 17 00:00:00 2001 From: Quentin Perret Date: Wed, 7 Dec 2022 14:41:56 +0000 Subject: [PATCH] ANDROID: KVM: arm64: Notify pKVM modules of PSCI events Introduce a notifier allowing a pKVM module to be notified for major PSCI events: {CPU,SYSTEM}_SUSPEND, as well as on the resume path. Bug: 244543039 Bug: 245034629 Change-Id: Ia82923445214925fc77e321457c8eab31f9d42e8 Signed-off-by: Quentin Perret --- arch/arm64/include/asm/kvm_pkvm_module.h | 7 +++++++ arch/arm64/kvm/hyp/include/nvhe/modules.h | 3 +++ arch/arm64/kvm/hyp/nvhe/modules.c | 1 + arch/arm64/kvm/hyp/nvhe/psci-relay.c | 18 ++++++++++++++++++ 4 files changed, 29 insertions(+) diff --git a/arch/arm64/include/asm/kvm_pkvm_module.h b/arch/arm64/include/asm/kvm_pkvm_module.h index 8b88727038b0..ee0da3a99cbf 100644 --- a/arch/arm64/include/asm/kvm_pkvm_module.h +++ b/arch/arm64/include/asm/kvm_pkvm_module.h @@ -8,6 +8,12 @@ typedef void (*dyn_hcall_t)(struct kvm_cpu_context *); +enum pkvm_psci_notification { + PKVM_PSCI_CPU_SUSPEND, + PKVM_PSCI_SYSTEM_SUSPEND, + PKVM_PSCI_CPU_ENTRY, +}; + struct pkvm_module_ops { int (*create_private_mapping)(phys_addr_t phys, size_t size, enum kvm_pgtable_prot prot, @@ -22,6 +28,7 @@ struct pkvm_module_ops { int (*protect_host_page)(u64 pfn, enum kvm_pgtable_prot prot); int (*register_host_smc_handler)(bool (*cb)(struct kvm_cpu_context *)); int (*register_illegal_abt_notifier)(void (*cb)(struct kvm_cpu_context *)); + int (*register_psci_notifier)(void (*cb)(enum pkvm_psci_notification, struct kvm_cpu_context *)); }; struct pkvm_module_section { diff --git a/arch/arm64/kvm/hyp/include/nvhe/modules.h b/arch/arm64/kvm/hyp/include/nvhe/modules.h index 48eae5f57321..bde933e0861f 100644 --- a/arch/arm64/kvm/hyp/include/nvhe/modules.h +++ b/arch/arm64/kvm/hyp/include/nvhe/modules.h @@ -6,6 +6,9 @@ int __pkvm_register_host_smc_handler(bool (*cb)(struct kvm_cpu_context *)); int __pkvm_register_illegal_abt_notifier(void (*cb)(struct kvm_cpu_context *)); +enum pkvm_psci_notification; +int __pkvm_register_psci_notifier(void (*cb)(enum pkvm_psci_notification, struct kvm_cpu_context *)); + #ifdef CONFIG_MODULES int __pkvm_init_module(void *module_init); int __pkvm_register_hcall(unsigned long hfn_hyp_va); diff --git a/arch/arm64/kvm/hyp/nvhe/modules.c b/arch/arm64/kvm/hyp/nvhe/modules.c index 47ee9b83a28c..99fa311daade 100644 --- a/arch/arm64/kvm/hyp/nvhe/modules.c +++ b/arch/arm64/kvm/hyp/nvhe/modules.c @@ -65,6 +65,7 @@ const struct pkvm_module_ops module_ops = { .protect_host_page = hyp_protect_host_page, .register_host_smc_handler = __pkvm_register_host_smc_handler, .register_illegal_abt_notifier = __pkvm_register_illegal_abt_notifier, + .register_psci_notifier = __pkvm_register_psci_notifier, }; int __pkvm_init_module(void *module_init) diff --git a/arch/arm64/kvm/hyp/nvhe/psci-relay.c b/arch/arm64/kvm/hyp/nvhe/psci-relay.c index 0fa155323e19..c5b439fd0066 100644 --- a/arch/arm64/kvm/hyp/nvhe/psci-relay.c +++ b/arch/arm64/kvm/hyp/nvhe/psci-relay.c @@ -24,6 +24,18 @@ void __noreturn __host_enter(struct kvm_cpu_context *host_ctxt); /* Config options set by the host. */ struct kvm_host_psci_config __ro_after_init kvm_host_psci_config; +static void (*pkvm_psci_notifier)(enum pkvm_psci_notification, struct kvm_cpu_context *); +static void pkvm_psci_notify(enum pkvm_psci_notification notif, struct kvm_cpu_context *host_ctxt) +{ + if (READ_ONCE(pkvm_psci_notifier)) + pkvm_psci_notifier(notif, host_ctxt); +} + +int __pkvm_register_psci_notifier(void (*cb)(enum pkvm_psci_notification, struct kvm_cpu_context *)) +{ + return cmpxchg(&pkvm_psci_notifier, NULL, cb) ? -EBUSY : 0; +} + #define INVALID_CPU_ID UINT_MAX struct psci_boot_args { @@ -169,6 +181,8 @@ static int psci_cpu_suspend(u64 func_id, struct kvm_cpu_context *host_ctxt) boot_args->pc = pc; boot_args->r0 = r0; + pkvm_psci_notify(PKVM_PSCI_CPU_SUSPEND, host_ctxt); + /* * Will either return if shallow sleep state, or wake up into the entry * point if it is a deep sleep state. @@ -196,6 +210,8 @@ static int psci_system_suspend(u64 func_id, struct kvm_cpu_context *host_ctxt) boot_args->pc = pc; boot_args->r0 = r0; + pkvm_psci_notify(PKVM_PSCI_SYSTEM_SUSPEND, host_ctxt); + /* Will only return on error. */ return psci_call(func_id, __hyp_pa(&kvm_hyp_cpu_resume), @@ -220,6 +236,8 @@ asmlinkage void __noreturn kvm_host_psci_cpu_entry(bool is_cpu_on) if (is_cpu_on) release_boot_args(boot_args); + pkvm_psci_notify(PKVM_PSCI_CPU_ENTRY, host_ctxt); + __host_enter(host_ctxt); }