aboutsummaryrefslogtreecommitdiff
path: root/sys/amd64/vmm/vmm.c
diff options
context:
space:
mode:
authorNeel Natu <neel@FreeBSD.org>2014-04-28 22:06:40 +0000
committerNeel Natu <neel@FreeBSD.org>2014-04-28 22:06:40 +0000
commitf0fdcfe247c3927f40b1612388f9a35973d56728 (patch)
tree2a5755c72feac26b7524cca10dc7e5475e332ee8 /sys/amd64/vmm/vmm.c
parent70b7e330c6da51d24f6719e06bec3c5cee4f8f25 (diff)
downloadsrc-f0fdcfe247c3927f40b1612388f9a35973d56728.tar.gz
src-f0fdcfe247c3927f40b1612388f9a35973d56728.zip
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@
Notes
Notes: svn path=/head/; revision=265062
Diffstat (limited to 'sys/amd64/vmm/vmm.c')
-rw-r--r--sys/amd64/vmm/vmm.c41
1 files changed, 35 insertions, 6 deletions
diff --git a/sys/amd64/vmm/vmm.c b/sys/amd64/vmm/vmm.c
index 27136f301286..51a132bda981 100644
--- a/sys/amd64/vmm/vmm.c
+++ b/sys/amd64/vmm/vmm.c
@@ -1211,16 +1211,45 @@ vm_handle_suspend(struct vm *vm, int vcpuid, bool *retu)
}
int
-vm_suspend(struct vm *vm)
+vm_suspend(struct vm *vm, enum vm_suspend_how how)
{
+ int i;
- if (atomic_cmpset_int(&vm->suspend, 0, 1)) {
- VM_CTR0(vm, "virtual machine suspended");
- return (0);
- } else {
- VM_CTR0(vm, "virtual machine already suspended");
+ if (how <= VM_SUSPEND_NONE || how >= VM_SUSPEND_LAST)
+ return (EINVAL);
+
+ if (atomic_cmpset_int(&vm->suspend, 0, how) == 0) {
+ VM_CTR2(vm, "virtual machine already suspended %d/%d",
+ vm->suspend, how);
return (EALREADY);
}
+
+ VM_CTR1(vm, "virtual machine successfully suspended %d", how);
+
+ /*
+ * Notify all active vcpus that they are now suspended.
+ */
+ for (i = 0; i < VM_MAXCPU; i++) {
+ if (CPU_ISSET(i, &vm->active_cpus))
+ vcpu_notify_event(vm, i, false);
+ }
+
+ return (0);
+}
+
+void
+vm_exit_suspended(struct vm *vm, int vcpuid, uint64_t rip)
+{
+ struct vm_exit *vmexit;
+
+ KASSERT(vm->suspend > VM_SUSPEND_NONE && vm->suspend < VM_SUSPEND_LAST,
+ ("vm_exit_suspended: invalid suspend type %d", vm->suspend));
+
+ vmexit = vm_exitinfo(vm, vcpuid);
+ vmexit->rip = rip;
+ vmexit->inst_length = 0;
+ vmexit->exitcode = VM_EXITCODE_SUSPENDED;
+ vmexit->u.suspended.how = vm->suspend;
}
int