@@ -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);
@@ -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, ...) \
@@ -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);
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(-)