[RFC PATCH 2/6] kvm/ppc: add a notifier chain for vcpu creation/destruction.

Scott Wood
2013-02-14T05:49:16Z

This will be used by the in-kernel MPIC to update its per-vcpu data
structures, and other vcpu init actions may benefit from migrating to
this over fixed initialization.

The notifier itself is kept in the non-arch-specific struct, and
initialized from non-arch-specific code. I was hoping to make the
entire mechanism non-arch-specific, but vm and vcpu destruction is too
arch-specific for that to happen yet -- there's no hook in
non-arch-code for per-vcpu destruction. Even just adding it to all
current architectures made me hesitate, as I lack confidence in
understanding what is going on on x86 (why are kvm_arch_vcpu_free and
kvm_arch_vcpu_destroy so different?).

Signed-off-by: Scott Wood <scottwood@freescale.com>
---
arch/powerpc/kvm/powerpc.c | 19 +++++++++++++++----
include/linux/kvm_host.h | 19 +++++++++++++++++++
virt/kvm/kvm_main.c | 2 ++
3 files changed, 36 insertions(+), 4 deletions(-)

diff --git a/arch/powerpc/kvm/powerpc.c b/arch/powerpc/kvm/powerpc.c
index 934413c..61989f4 100644
--- a/arch/powerpc/kvm/powerpc.c
+++ b/arch/powerpc/kvm/powerpc.c
@@ -440,11 +440,20 @@ void kvm_arch_flush_shadow_memslot(struct kvm *kvm,
struct kvm_vcpu *kvm_arch_vcpu_create(struct kvm *kvm, unsigned int id)
{
struct kvm_vcpu *vcpu;
+ int ret;
+
vcpu = kvmppc_core_vcpu_create(kvm, id);
- if (!IS_ERR(vcpu)) {
- vcpu->arch.wqp = &vcpu->wq;
- kvmppc_create_vcpu_debugfs(vcpu, id);
- }
+ if (IS_ERR(vcpu))
+ return vcpu;
+
+ vcpu->arch.wqp = &vcpu->wq;
+ kvmppc_create_vcpu_debugfs(vcpu, id);
+
+ ret = blocking_notifier_call_chain(&kvm->vcpu_notifier, 1, vcpu);
+ ret = notifier_to_errno(ret);
+ if (ret < 0)
+ return ERR_PTR(ret);
+
return vcpu;
}

@@ -455,6 +464,8 @@ int kvm_arch_vcpu_postcreate(struct kvm_vcpu *vcpu)

void kvm_arch_vcpu_free(struct kvm_vcpu *vcpu)
{
+ blocking_notifier_call_chain(&vcpu->kvm->vcpu_notifier, 0, vcpu);
+
/* Make sure we're not using the vcpu anymore */
hrtimer_cancel(&vcpu->arch.dec_timer);
tasklet_kill(&vcpu->arch.tasklet);
diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
index dbaf012..3d28037 100644
--- a/include/linux/kvm_host.h
+++ b/include/linux/kvm_host.h
@@ -406,6 +406,25 @@ struct kvm {
long tlbs_dirty;
struct kvm_device *devices[KVM_MAX_DEVICES];
unsigned int num_devices;
+
+ /*
+ * notifier pointer is vcpu; "val" is 1 for create, 0 for destroy
+ *
+ * Creation notice is after other vcpu init is complete, but before
+ * the vcpu has been exposed to userspace.
+ *
+ * Destruction notice is before other vcpu destruction begins, but
+ * after the vcpu is no longer able to execute (either the vm is
+ * being destroyed, or vcpu init failed and was never exposed).
+ *
+ * If a listener encounters an error during a creation event that
+ * precludes a working vcpu, it should terminate the notifier chain
+ * with an error. However, destruction notifications should never
+ * be terminated and destruction listeners should be prepared
+ * to accept getting called without having seen the creation
+ * notice.
+ */
+ struct blocking_notifier_head vcpu_notifier;
};

#define kvm_err(fmt, ...) \
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
index baf8481..dd4c78d 100644
--- a/virt/kvm/kvm_main.c
+++ b/virt/kvm/kvm_main.c
@@ -508,6 +508,8 @@ static struct kvm *kvm_create_vm(unsigned long type)
if (r)
goto out_err;

+ BLOCKING_INIT_NOTIFIER_HEAD(&kvm->vcpu_notifier);
+
raw_spin_lock(&kvm_lock);
list_add(&kvm->vm_list, &vm_list);
raw_spin_unlock(&kvm_lock);
--
1.7.9.5