diff options
author | Neel Natu <neel@FreeBSD.org> | 2014-04-28 22:06:40 +0000 |
---|---|---|
committer | Neel Natu <neel@FreeBSD.org> | 2014-04-28 22:06:40 +0000 |
commit | f0fdcfe247c3927f40b1612388f9a35973d56728 (patch) | |
tree | 2a5755c72feac26b7524cca10dc7e5475e332ee8 /sys/amd64/vmm/vmm.c | |
parent | 70b7e330c6da51d24f6719e06bec3c5cee4f8f25 (diff) | |
download | src-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.c | 41 |
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 |