svn commit: r265203 - in head: sys/amd64/include sys/amd64/vmm usr.sbin/bhyve
Neel Natu
neel at FreeBSD.org
Fri May 2 00:46:48 UTC 2014
Author: neel
Date: Fri May 2 00:33:56 2014
New Revision: 265203
URL: http://svnweb.freebsd.org/changeset/base/265203
Log:
Add logic in the HLT exit handler to detect if the guest has put all vcpus
to sleep permanently by executing a HLT with interrupts disabled.
When this condition is detected the guest with be suspended with a reason of
VM_SUSPEND_HALT and the bhyve(8) process will exit.
Tested by executing "halt" inside a RHEL7-beta guest.
Discussed with: grehan@
Reviewed by: jhb@, tychon@
Modified:
head/sys/amd64/include/vmm.h
head/sys/amd64/vmm/vmm.c
head/usr.sbin/bhyve/bhyverun.c
Modified: head/sys/amd64/include/vmm.h
==============================================================================
--- head/sys/amd64/include/vmm.h Thu May 1 23:34:14 2014 (r265202)
+++ head/sys/amd64/include/vmm.h Fri May 2 00:33:56 2014 (r265203)
@@ -33,6 +33,7 @@ enum vm_suspend_how {
VM_SUSPEND_NONE,
VM_SUSPEND_RESET,
VM_SUSPEND_POWEROFF,
+ VM_SUSPEND_HALT,
VM_SUSPEND_LAST
};
Modified: head/sys/amd64/vmm/vmm.c
==============================================================================
--- head/sys/amd64/vmm/vmm.c Thu May 1 23:34:14 2014 (r265202)
+++ head/sys/amd64/vmm/vmm.c Fri May 2 00:33:56 2014 (r265203)
@@ -142,6 +142,8 @@ struct vm {
int suspend;
volatile cpuset_t suspended_cpus;
+
+ volatile cpuset_t halted_cpus;
};
static int vmm_initialized;
@@ -1006,9 +1008,13 @@ vm_handle_hlt(struct vm *vm, int vcpuid,
{
struct vcpu *vcpu;
const char *wmesg;
- int t;
+ int t, vcpu_halted, vm_halted;
+
+ KASSERT(!CPU_ISSET(vcpuid, &vm->halted_cpus), ("vcpu already halted"));
vcpu = &vm->vcpu[vcpuid];
+ vcpu_halted = 0;
+ vm_halted = 0;
vcpu_lock(vcpu);
while (1) {
@@ -1032,10 +1038,26 @@ vm_handle_hlt(struct vm *vm, int vcpuid,
}
}
- if (vlapic_enabled(vcpu->vlapic))
- wmesg = "vmidle";
- else
+ /*
+ * Some Linux guests implement "halt" by having all vcpus
+ * execute HLT with interrupts disabled. 'halted_cpus' keeps
+ * track of the vcpus that have entered this state. When all
+ * vcpus enter the halted state the virtual machine is halted.
+ */
+ if (intr_disabled) {
wmesg = "vmhalt";
+ VCPU_CTR0(vm, vcpuid, "Halted");
+ if (!vcpu_halted) {
+ vcpu_halted = 1;
+ CPU_SET_ATOMIC(vcpuid, &vm->halted_cpus);
+ }
+ if (CPU_CMP(&vm->halted_cpus, &vm->active_cpus) == 0) {
+ vm_halted = 1;
+ break;
+ }
+ } else {
+ wmesg = "vmidle";
+ }
t = ticks;
vcpu_require_state_locked(vcpu, VCPU_SLEEPING);
@@ -1043,8 +1065,15 @@ vm_handle_hlt(struct vm *vm, int vcpuid,
vcpu_require_state_locked(vcpu, VCPU_FROZEN);
vmm_stat_incr(vm, vcpuid, VCPU_IDLE_TICKS, ticks - t);
}
+
+ if (vcpu_halted)
+ CPU_CLR_ATOMIC(vcpuid, &vm->halted_cpus);
+
vcpu_unlock(vcpu);
+ if (vm_halted)
+ vm_suspend(vm, VM_SUSPEND_HALT);
+
return (0);
}
Modified: head/usr.sbin/bhyve/bhyverun.c
==============================================================================
--- head/usr.sbin/bhyve/bhyverun.c Thu May 1 23:34:14 2014 (r265202)
+++ head/usr.sbin/bhyve/bhyverun.c Fri May 2 00:33:56 2014 (r265203)
@@ -453,7 +453,6 @@ vmexit_suspend(struct vmctx *ctx, struct
enum vm_suspend_how how;
how = vmexit->u.suspended.how;
- assert(how == VM_SUSPEND_RESET || how == VM_SUSPEND_POWEROFF);
fbsdrun_deletecpu(ctx, *pvcpu);
@@ -470,10 +469,17 @@ vmexit_suspend(struct vmctx *ctx, struct
}
pthread_mutex_unlock(&resetcpu_mtx);
- if (how == VM_SUSPEND_RESET)
+ switch (how) {
+ case VM_SUSPEND_RESET:
exit(0);
- if (how == VM_SUSPEND_POWEROFF)
+ case VM_SUSPEND_POWEROFF:
exit(1);
+ case VM_SUSPEND_HALT:
+ exit(2);
+ default:
+ fprintf(stderr, "vmexit_suspend: invalid reason %d\n", how);
+ exit(100);
+ }
return (0); /* NOTREACHED */
}
More information about the svn-src-head
mailing list