Date: Fri, 2 May 2014 00:33:56 +0000 (UTC) From: Neel Natu <neel@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r265203 - in head: sys/amd64/include sys/amd64/vmm usr.sbin/bhyve Message-ID: <201405020033.s420Xu91035658@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
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 */ }
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201405020033.s420Xu91035658>