summaryrefslogtreecommitdiffstats
path: root/usr.sbin/bhyve
diff options
context:
space:
mode:
authorneel <neel@FreeBSD.org>2014-04-28 22:06:40 +0000
committerneel <neel@FreeBSD.org>2014-04-28 22:06:40 +0000
commitb616a9a2e4a5c8e20ca308fb6e309583803cb19c (patch)
tree2a5755c72feac26b7524cca10dc7e5475e332ee8 /usr.sbin/bhyve
parent8820383a981da45b9f3593b94de0c67e3856d71c (diff)
downloadFreeBSD-src-b616a9a2e4a5c8e20ca308fb6e309583803cb19c.zip
FreeBSD-src-b616a9a2e4a5c8e20ca308fb6e309583803cb19c.tar.gz
Allow a virtual machine to be forcibly reset or powered off. This is done
by adding an argument to the VM_SUSPEND ioctl that specifies how the virtual machine should be suspended, viz. VM_SUSPEND_RESET or VM_SUSPEND_POWEROFF. The disposition of VM_SUSPEND is also made available to the exit handler via the 'u.suspended' member of 'struct vm_exit'. This capability is exposed via the '--force-reset' and '--force-poweroff' arguments to /usr/sbin/bhyvectl. Discussed with: grehan@
Diffstat (limited to 'usr.sbin/bhyve')
-rw-r--r--usr.sbin/bhyve/bhyverun.c28
1 files changed, 19 insertions, 9 deletions
diff --git a/usr.sbin/bhyve/bhyverun.c b/usr.sbin/bhyve/bhyverun.c
index e8010e6..25abc2e 100644
--- a/usr.sbin/bhyve/bhyverun.c
+++ b/usr.sbin/bhyve/bhyverun.c
@@ -461,17 +461,18 @@ vmexit_inst_emul(struct vmctx *ctx, struct vm_exit *vmexit, int *pvcpu)
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);
+ enum vm_suspend_how how;
+
+ how = vmexit->u.suspended.how;
+ assert(how == VM_SUSPEND_RESET || how == VM_SUSPEND_POWEROFF);
fbsdrun_deletecpu(ctx, *pvcpu);
- if (*pvcpu != resetcpu) {
+ if (*pvcpu != BSP) {
pthread_mutex_lock(&resetcpu_mtx);
pthread_cond_signal(&resetcpu_cond);
pthread_mutex_unlock(&resetcpu_mtx);
@@ -483,7 +484,12 @@ vmexit_suspend(struct vmctx *ctx, struct vm_exit *vmexit, int *pvcpu)
pthread_cond_wait(&resetcpu_cond, &resetcpu_mtx);
}
pthread_mutex_unlock(&resetcpu_mtx);
- exit(0);
+
+ if (how == VM_SUSPEND_RESET)
+ exit(0);
+ if (how == VM_SUSPEND_POWEROFF)
+ exit(1);
+ return (0); /* NOTREACHED */
}
static vmexit_handler_t handler[VM_EXITCODE_MAX] = {
@@ -505,6 +511,7 @@ vm_loop(struct vmctx *ctx, int vcpu, uint64_t rip)
cpuset_t mask;
int error, rc, prevcpu;
enum vm_exitcode exitcode;
+ enum vm_suspend_how how;
if (pincpu >= 0) {
CPU_ZERO(&mask);
@@ -538,10 +545,13 @@ vm_loop(struct vmctx *ctx, int vcpu, uint64_t rip)
rip = vmexit[vcpu].rip;
break;
case VMEXIT_RESET:
- if (vm_suspend(ctx) == 0) {
- assert(resetcpu == -1);
- resetcpu = vcpu;
- }
+ case VMEXIT_POWEROFF:
+ if (rc == VMEXIT_RESET)
+ how = VM_SUSPEND_RESET;
+ else
+ how = VM_SUSPEND_POWEROFF;
+ error = vm_suspend(ctx, how);
+ assert(error == 0 || errno == EALREADY);
rip = vmexit[vcpu].rip + vmexit[vcpu].inst_length;
break;
default:
OpenPOWER on IntegriCloud