| From 42c157f5d0b580ad67929961e0b0d328d07b15cc Mon Sep 17 00:00:00 2001 |
| From: Sergey Senozhatsky <senozhatsky@chromium.org> |
| Date: Thu, 10 Jun 2021 10:58:52 +0900 |
| Subject: [PATCH] BACKPORT: FROMLIST: kvm: add PM-notifier |
| |
| Add KVM PM-notifier so that architectures can have arch-specific |
| VM suspend/resume routines. Such architectures need to select |
| CONFIG_HAVE_KVM_PM_NOTIFIER and implement kvm_arch_pm_notifier(). |
| |
| Signed-off-by: Sergey Senozhatsky <senozhatsky@chromium.org> |
| Acked-by: Marc Zyngier <maz@kernel.org> |
| (am from https://lore.kernel.org/patchwork/patch/1441655/) |
| (also found at https://lore.kernel.org/r/20210606021045.14159-1-senozhatsky@chromium.org) |
| |
| BUG=b:187377603 |
| TEST=did rounds of suspend-resume on hatch-arc-r and checked that |
| PVCLOCK_GUEST_STOPPED is set |
| |
| Change-Id: Ia2d44977b59c1cb08638cb996c1a4696221b3aed |
| Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/third_party/kernel/+/2951944 |
| Tested-by: Sergey Senozhatsky <senozhatsky@chromium.org> |
| Reviewed-by: Suleiman Souhlal <suleiman@chromium.org> |
| Commit-Queue: Sergey Senozhatsky <senozhatsky@chromium.org> |
| --- |
| include/linux/kvm_host.h | 9 +++++++++ |
| virt/kvm/Kconfig | 3 +++ |
| virt/kvm/kvm_main.c | 35 +++++++++++++++++++++++++++++++++++ |
| 3 files changed, 47 insertions(+) |
| |
| diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h |
| index 8583ed3ff344..2aefabb1f5da 100644 |
| --- a/include/linux/kvm_host.h |
| +++ b/include/linux/kvm_host.h |
| @@ -28,6 +28,7 @@ |
| #include <linux/rcuwait.h> |
| #include <linux/refcount.h> |
| #include <linux/nospec.h> |
| +#include <linux/notifier.h> |
| #include <asm/signal.h> |
| |
| #include <linux/kvm.h> |
| @@ -585,6 +586,10 @@ struct kvm { |
| pid_t userspace_pid; |
| unsigned int max_halt_poll_ns; |
| u32 dirty_ring_size; |
| + |
| +#ifdef CONFIG_HAVE_KVM_PM_NOTIFIER |
| + struct notifier_block pm_notifier; |
| +#endif |
| }; |
| |
| #define kvm_err(fmt, ...) \ |
| @@ -998,6 +1003,10 @@ int kvm_arch_vcpu_create(struct kvm_vcpu *vcpu); |
| void kvm_arch_vcpu_postcreate(struct kvm_vcpu *vcpu); |
| void kvm_arch_vcpu_destroy(struct kvm_vcpu *vcpu); |
| |
| +#ifdef CONFIG_HAVE_KVM_PM_NOTIFIER |
| +int kvm_arch_pm_notifier(struct kvm *kvm, unsigned long state); |
| +#endif |
| + |
| #ifdef __KVM_HAVE_ARCH_VCPU_DEBUGFS |
| void kvm_arch_create_vcpu_debugfs(struct kvm_vcpu *vcpu, struct dentry *debugfs_dentry); |
| #endif |
| diff --git a/virt/kvm/Kconfig b/virt/kvm/Kconfig |
| index 1c37ccd5d402..62b39149b8c8 100644 |
| --- a/virt/kvm/Kconfig |
| +++ b/virt/kvm/Kconfig |
| @@ -63,3 +63,6 @@ config HAVE_KVM_NO_POLL |
| |
| config KVM_XFER_TO_GUEST_WORK |
| bool |
| + |
| +config HAVE_KVM_PM_NOTIFIER |
| + bool |
| diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c |
| index 6a6bc7af0e28..f362ac0a1b2b 100644 |
| --- a/virt/kvm/kvm_main.c |
| +++ b/virt/kvm/kvm_main.c |
| @@ -51,6 +51,7 @@ |
| #include <linux/io.h> |
| #include <linux/lockdep.h> |
| #include <linux/kthread.h> |
| +#include <linux/suspend.h> |
| |
| #include <asm/processor.h> |
| #include <asm/ioctl.h> |
| @@ -780,6 +781,38 @@ static int kvm_init_mmu_notifier(struct kvm *kvm) |
| |
| #endif /* CONFIG_MMU_NOTIFIER && KVM_ARCH_WANT_MMU_NOTIFIER */ |
| |
| +#ifdef CONFIG_HAVE_KVM_PM_NOTIFIER |
| +static int kvm_pm_notifier_call(struct notifier_block *bl, |
| + unsigned long state, |
| + void *unused) |
| +{ |
| + struct kvm *kvm = container_of(bl, struct kvm, pm_notifier); |
| + |
| + return kvm_arch_pm_notifier(kvm, state); |
| +} |
| + |
| +static void kvm_init_pm_notifier(struct kvm *kvm) |
| +{ |
| + kvm->pm_notifier.notifier_call = kvm_pm_notifier_call; |
| + /* Suspend KVM before we suspend ftrace, RCU, etc. */ |
| + kvm->pm_notifier.priority = INT_MAX; |
| + register_pm_notifier(&kvm->pm_notifier); |
| +} |
| + |
| +static void kvm_destroy_pm_notifier(struct kvm *kvm) |
| +{ |
| + unregister_pm_notifier(&kvm->pm_notifier); |
| +} |
| +#else /* !CONFIG_HAVE_KVM_PM_NOTIFIER */ |
| +static void kvm_init_pm_notifier(struct kvm *kvm) |
| +{ |
| +} |
| + |
| +static void kvm_destroy_pm_notifier(struct kvm *kvm) |
| +{ |
| +} |
| +#endif /* CONFIG_HAVE_KVM_PM_NOTIFIER */ |
| + |
| static struct kvm_memslots *kvm_alloc_memslots(void) |
| { |
| int i; |
| @@ -963,6 +996,7 @@ static struct kvm *kvm_create_vm(unsigned long type) |
| mutex_unlock(&kvm_lock); |
| |
| preempt_notifier_inc(); |
| + kvm_init_pm_notifier(kvm); |
| |
| return kvm; |
| |
| @@ -1010,6 +1044,7 @@ static void kvm_destroy_vm(struct kvm *kvm) |
| int i; |
| struct mm_struct *mm = kvm->mm; |
| |
| + kvm_destroy_pm_notifier(kvm); |
| kvm_uevent_notify_change(KVM_EVENT_DESTROY_VM, kvm); |
| kvm_destroy_vm_debugfs(kvm); |
| kvm_arch_sync_events(kvm); |
| -- |
| 2.17.1 |
| |