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 <qperret@google.com>
This commit is contained in:
Quentin Perret
2022-12-07 14:41:56 +00:00
parent f3472b47c8
commit 2829c60588
4 changed files with 29 additions and 0 deletions

View File

@@ -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 {

View File

@@ -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);

View File

@@ -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)

View File

@@ -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);
}