diff options
author | neel <neel@FreeBSD.org> | 2014-04-28 22:06:40 +0000 |
---|---|---|
committer | neel <neel@FreeBSD.org> | 2014-04-28 22:06:40 +0000 |
commit | b616a9a2e4a5c8e20ca308fb6e309583803cb19c (patch) | |
tree | 2a5755c72feac26b7524cca10dc7e5475e332ee8 /usr.sbin | |
parent | 8820383a981da45b9f3593b94de0c67e3856d71c (diff) | |
download | FreeBSD-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')
-rw-r--r-- | usr.sbin/bhyve/bhyverun.c | 28 | ||||
-rw-r--r-- | usr.sbin/bhyvectl/bhyvectl.c | 13 |
2 files changed, 31 insertions, 10 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: diff --git a/usr.sbin/bhyvectl/bhyvectl.c b/usr.sbin/bhyvectl/bhyvectl.c index 2e732b5..ceee33a 100644 --- a/usr.sbin/bhyvectl/bhyvectl.c +++ b/usr.sbin/bhyvectl/bhyvectl.c @@ -191,13 +191,16 @@ usage(void) " [--get-highmem]\n" " [--get-gpa-pmap]\n" " [--assert-lapic-lvt=<pin>]\n" - " [--inject-nmi]\n", + " [--inject-nmi]\n" + " [--force-reset]\n" + " [--force-poweroff]\n", progname); exit(1); } static int get_stats, getcap, setcap, capval, get_gpa_pmap; static int inject_nmi, assert_lapic_lvt; +static int force_reset, force_poweroff; static const char *capname; static int create, destroy, get_lowmem, get_highmem; static uint64_t memsize; @@ -565,6 +568,8 @@ main(int argc, char *argv[]) { "create", NO_ARG, &create, 1 }, { "destroy", NO_ARG, &destroy, 1 }, { "inject-nmi", NO_ARG, &inject_nmi, 1 }, + { "force-reset", NO_ARG, &force_reset, 1 }, + { "force-poweroff", NO_ARG, &force_poweroff, 1 }, { NULL, 0, NULL, 0 } }; @@ -1535,6 +1540,12 @@ main(int argc, char *argv[]) printf("vm_run error %d\n", error); } + if (!error && force_reset) + error = vm_suspend(ctx, VM_SUSPEND_RESET); + + if (!error && force_poweroff) + error = vm_suspend(ctx, VM_SUSPEND_POWEROFF); + if (error) printf("errno = %d\n", errno); |