diff options
author | neel <neel@FreeBSD.org> | 2014-03-26 23:34:27 +0000 |
---|---|---|
committer | neel <neel@FreeBSD.org> | 2014-03-26 23:34:27 +0000 |
commit | 3e49998fdfce1f7d28cbd813dab17114caeb6392 (patch) | |
tree | 26d2d3b3da3f94b1b7988cb043cec70d34999f99 /usr.sbin/bhyve | |
parent | 0b79334339fb4e8a621ab2cb4ed45bb729778613 (diff) | |
download | FreeBSD-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.c | 35 |
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); } |