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

login
register
mail settings
Submitter Scott Wood
Date Feb. 14, 2013, 5:49 a.m.
Message ID <1360820960-12537-3-git-send-email-scottwood@freescale.com>
Download mbox | patch
Permalink /patch/220363/
State New
Headers show

Comments

Scott Wood - Feb. 14, 2013, 5:49 a.m.
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(-)

Patch

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