[hypervisor] Add Join to Guest to wait on all VCPUs.
Corresponding change to Garnet to follow.
Change-Id: I728ba3b56758c1ad7697aafb10671af3cab4a4fd
diff --git a/system/ulib/hypervisor/guest.cpp b/system/ulib/hypervisor/guest.cpp
index 93c179a..7d24fc0 100644
--- a/system/ulib/hypervisor/guest.cpp
+++ b/system/ulib/hypervisor/guest.cpp
@@ -192,3 +192,21 @@
return ZX_OK;
}
+
+zx_status_t Guest::Join() {
+ // We assume that the VCPU-0 thread will be started first, and that no additional VCPUs will
+ // be brought up after it terminates.
+ zx_status_t status = vcpus_[0]->Join();
+
+ // Once the initial VCPU has terminated, wait for any additional VCPUs.
+ for (size_t id = 1; id != kMaxVcpus; ++id) {
+ if (vcpus_[id] != nullptr) {
+ zx_status_t vcpu_status = vcpus_[id]->Join();
+ if (vcpu_status != ZX_OK) {
+ status = vcpu_status;
+ }
+ }
+ }
+
+ return status;
+}
diff --git a/system/ulib/hypervisor/include/hypervisor/guest.h b/system/ulib/hypervisor/include/hypervisor/guest.h
index 0e19d49..ecae767 100644
--- a/system/ulib/hypervisor/include/hypervisor/guest.h
+++ b/system/ulib/hypervisor/include/hypervisor/guest.h
@@ -41,11 +41,16 @@
zx_status_t CreateMapping(TrapType type, uint64_t addr, size_t size, uint64_t offset,
IoHandler* handler);
- // Setup a handler function to run when an additional VCPU is brought up.
+ // Setup a handler function to run when an additional VCPU is brought up. The factory should
+ // call Start on the new VCPU to begin executing the guest on a new thread.
void RegisterVcpuFactory(VcpuFactory factory);
+ // Initializes a VCPU by calling the VCPU factory. The first VCPU must have id 0.
zx_status_t StartVcpu(uintptr_t entry, uint64_t id);
+ // Waits for all VCPUs associated with the guest to finish executing.
+ zx_status_t Join();
+
private:
// TODO(alexlegg): Consolidate this constant with other definitions in Garnet.
static constexpr size_t kMaxVcpus = 16u;