summaryrefslogtreecommitdiffstats
path: root/usr.sbin/bhyve
diff options
context:
space:
mode:
authorneel <neel@FreeBSD.org>2014-03-26 23:34:27 +0000
committerneel <neel@FreeBSD.org>2014-03-26 23:34:27 +0000
commit3e49998fdfce1f7d28cbd813dab17114caeb6392 (patch)
tree26d2d3b3da3f94b1b7988cb043cec70d34999f99 /usr.sbin/bhyve
parent0b79334339fb4e8a621ab2cb4ed45bb729778613 (diff)
downloadFreeBSD-src-3e49998fdfce1f7d28cbd813dab17114caeb6392.zip
FreeBSD-src-3e49998fdfce1f7d28cbd813dab17114caeb6392.tar.gz
Add an ioctl to suspend a virtual machine (VM_SUSPEND). The ioctl can be called
from any context i.e., it is not required to be called from a vcpu thread. The ioctl simply sets a state variable 'vm->suspend' to '1' and returns. The vcpus inspect 'vm->suspend' in the run loop and if it is set to '1' the vcpu breaks out of the loop with a reason of 'VM_EXITCODE_SUSPENDED'. The suspend handler waits until all 'vm->active_cpus' have transitioned to 'vm->suspended_cpus' before returning to userspace. Discussed with: grehan
Diffstat (limited to 'usr.sbin/bhyve')
-rw-r--r--usr.sbin/bhyve/bhyverun.c35
1 files changed, 34 insertions, 1 deletions
diff --git a/usr.sbin/bhyve/bhyverun.c b/usr.sbin/bhyve/bhyverun.c
index 99194f2..6aac50e 100644
--- a/usr.sbin/bhyve/bhyverun.c
+++ b/usr.sbin/bhyve/bhyverun.c
@@ -463,6 +463,33 @@ vmexit_inst_emul(struct vmctx *ctx, struct vm_exit *vmexit, int *pvcpu)
return (VMEXIT_CONTINUE);
}
+static pthread_mutex_t resetcpu_mtx = PTHREAD_MUTEX_INITIALIZER;
+static pthread_cond_t resetcpu_cond = PTHREAD_COND_INITIALIZER;
+static int resetcpu = -1;
+
+static int
+vmexit_suspend(struct vmctx *ctx, struct vm_exit *vmexit, int *pvcpu)
+{
+
+ assert(resetcpu != -1);
+
+ fbsdrun_deletecpu(ctx, *pvcpu);
+
+ if (*pvcpu != resetcpu) {
+ pthread_mutex_lock(&resetcpu_mtx);
+ pthread_cond_signal(&resetcpu_cond);
+ pthread_mutex_unlock(&resetcpu_mtx);
+ pthread_exit(NULL);
+ }
+
+ pthread_mutex_lock(&resetcpu_mtx);
+ while (!CPU_EMPTY(&cpumask)) {
+ pthread_cond_wait(&resetcpu_cond, &resetcpu_mtx);
+ }
+ pthread_mutex_unlock(&resetcpu_mtx);
+ exit(0);
+}
+
static vmexit_handler_t handler[VM_EXITCODE_MAX] = {
[VM_EXITCODE_INOUT] = vmexit_inout,
[VM_EXITCODE_VMX] = vmexit_vmx,
@@ -473,6 +500,7 @@ static vmexit_handler_t handler[VM_EXITCODE_MAX] = {
[VM_EXITCODE_INST_EMUL] = vmexit_inst_emul,
[VM_EXITCODE_SPINUP_AP] = vmexit_spinup_ap,
[VM_EXITCODE_SPINDOWN_CPU] = vmexit_spindown_cpu,
+ [VM_EXITCODE_SUSPENDED] = vmexit_suspend
};
static void
@@ -514,7 +542,12 @@ vm_loop(struct vmctx *ctx, int vcpu, uint64_t rip)
rip = vmexit[vcpu].rip;
break;
case VMEXIT_RESET:
- exit(0);
+ if (vm_suspend(ctx) == 0) {
+ assert(resetcpu == -1);
+ resetcpu = vcpu;
+ }
+ rip = vmexit[vcpu].rip + vmexit[vcpu].inst_length;
+ break;
default:
exit(1);
}
OpenPOWER on IntegriCloud