[PATCH] kvmtool: delegate exit/reboot responsibility to vcpu0

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Our exit/reboot code is a bit of a mess:

  - Both kvm__reboot and kvm_cpu_exit send SIGKVMEXIT to running vcpus
  - When vcpu0 exits, the main thread starts executing destructors
    (exitcalls) whilst other vcpus may be running
  - The pause_lock isn't always held when inspecting is_running for
    a vcpu

This patch attempts to fix these issues by restricting the exit/reboot
path to vcpu0 and the main thread. In particular, a KVM_SYSTEM_EVENT
will signal SIGKVMEXIT to vcpu0, which will join with the main thread
and then tear down the other vcpus before invoking any destructor code.

Cc: Julien Grall <julien.grall@xxxxxxx>
Cc: Balbir Singh <bsingharora@xxxxxxxxx>
Signed-off-by: Will Deacon <will.deacon@xxxxxxx>
---

Balbir -- does this work on ppc?

 builtin-run.c |  6 ++++--
 kvm-cpu.c     |  3 ++-
 kvm.c         | 28 ++++++----------------------
 3 files changed, 12 insertions(+), 25 deletions(-)

diff --git a/builtin-run.c b/builtin-run.c
index edcaf3ecde01..72b878dcff38 100644
--- a/builtin-run.c
+++ b/builtin-run.c
@@ -630,7 +630,6 @@ static struct kvm *kvm_cmd_run_init(int argc, const char **argv)
 static int kvm_cmd_run_work(struct kvm *kvm)
 {
 	int i;
-	void *ret = NULL;
 
 	for (i = 0; i < kvm->nrcpus; i++) {
 		if (pthread_create(&kvm->cpus[i]->thread, NULL, kvm_cpu_thread, kvm->cpus[i]) != 0)
@@ -638,7 +637,10 @@ static int kvm_cmd_run_work(struct kvm *kvm)
 	}
 
 	/* Only VCPU #0 is going to exit by itself when shutting down */
-	return pthread_join(kvm->cpus[0]->thread, &ret);
+	if (pthread_join(kvm->cpus[0]->thread, NULL) != 0)
+		die("unable to join with vcpu 0");
+
+	return kvm_cpu__exit(kvm);
 }
 
 static void kvm_cmd_run_exit(struct kvm *kvm, int guest_ret)
diff --git a/kvm-cpu.c b/kvm-cpu.c
index 2af459b34807..cc8385f6143e 100644
--- a/kvm-cpu.c
+++ b/kvm-cpu.c
@@ -305,6 +305,7 @@ int kvm_cpu__exit(struct kvm *kvm)
 	kvm_cpu__delete(kvm->cpus[0]);
 	kvm->cpus[0] = NULL;
 
+	kvm__pause(kvm);
 	for (i = 1; i < kvm->nrcpus; i++) {
 		if (kvm->cpus[i]->is_running) {
 			pthread_kill(kvm->cpus[i]->thread, SIGKVMEXIT);
@@ -315,6 +316,7 @@ int kvm_cpu__exit(struct kvm *kvm)
 		if (ret == NULL)
 			r = 0;
 	}
+	kvm__continue(kvm);
 
 	free(kvm->cpus);
 
@@ -324,4 +326,3 @@ int kvm_cpu__exit(struct kvm *kvm)
 
 	return r;
 }
-core_exit(kvm_cpu__exit);
diff --git a/kvm.c b/kvm.c
index 18b46068271e..7fa76f784de7 100644
--- a/kvm.c
+++ b/kvm.c
@@ -396,22 +396,15 @@ void kvm__dump_mem(struct kvm *kvm, unsigned long addr, unsigned long size, int
 
 void kvm__reboot(struct kvm *kvm)
 {
-	int i;
-
 	/* Check if the guest is running */
 	if (!kvm->cpus[0] || kvm->cpus[0]->thread == 0)
 		return;
 
-	mutex_lock(&pause_lock);
-
-	/* The kvm->cpus array contains a null pointer in the last location */
-	for (i = 0; ; i++) {
-		if (kvm->cpus[i])
-			pthread_kill(kvm->cpus[i]->thread, SIGKVMEXIT);
-		else
-			break;
-	}
+	pthread_kill(kvm->cpus[0]->thread, SIGKVMEXIT);
+}
 
+void kvm__continue(struct kvm *kvm)
+{
 	mutex_unlock(&pause_lock);
 }
 
@@ -419,12 +412,12 @@ void kvm__pause(struct kvm *kvm)
 {
 	int i, paused_vcpus = 0;
 
+	mutex_lock(&pause_lock);
+
 	/* Check if the guest is running */
 	if (!kvm->cpus[0] || kvm->cpus[0]->thread == 0)
 		return;
 
-	mutex_lock(&pause_lock);
-
 	pause_event = eventfd(0, 0);
 	if (pause_event < 0)
 		die("Failed creating pause notification event");
@@ -445,15 +438,6 @@ void kvm__pause(struct kvm *kvm)
 	close(pause_event);
 }
 
-void kvm__continue(struct kvm *kvm)
-{
-	/* Check if the guest is running */
-	if (!kvm->cpus[0] || kvm->cpus[0]->thread == 0)
-		return;
-
-	mutex_unlock(&pause_lock);
-}
-
 void kvm__notify_paused(void)
 {
 	u64 p = 1;
-- 
2.1.4

--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Index of Archives]     [KVM ARM]     [KVM ia64]     [KVM ppc]     [Virtualization Tools]     [Spice Development]     [Libvirt]     [Libvirt Users]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite Questions]     [Linux Kernel]     [Linux SCSI]     [XFree86]
  Powered by Linux