FreeBSD/sys/amd64/vmm/vmm.c
/*
 * Emulate a guest 'hlt' by sleeping until the vcpu is ready to run.
 */
Emulate a guest 'hlt' by sleeping until the vcpu is ready to run.
Emulate a guest ' hlt ' by sleeping until the vcpu is ready to run .
static int
vm_handle_hlt(struct vm *vm, int vcpuid, bool intr_disabled, bool *retu)
{
	struct vcpu *vcpu;
	const char *wmesg;
	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) {
		if (vm->rendezvous_func != NULL || vm->suspend || vcpu->reqidle)
			break;
		if (vm_nmi_pending(vm, vcpuid))
			break;
		if (!intr_disabled) {
			if (vm_extint_pending(vm, vcpuid) ||
			    vlapic_pending_intr(vcpu->vlapic, NULL)) {
				break;
			}
		}
		if (vcpu_should_yield(vm, vcpuid))
			break;
		if (intr_disabled) {
			wmesg = "vmhalt";
			VCPU_CTR0(vm, vcpuid, "Halted");
			if (!vcpu_halted && halt_detection_enabled) {
				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(vm, vcpuid, VCPU_SLEEPING);
		msleep_spin(vcpu, &vcpu->mtx, wmesg, hz);
		vcpu_require_state_locked(vm, vcpuid, 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);
}
static int vm_handle_hlt ( struct vm * vm , int vcpuid , bool intr_disabled , bool * retu ) { struct vcpu * vcpu ; const char * wmesg ; int t , vcpu_halted , vm_halted ; KASSERT ( ! CPU_ISSET ( vcpuid , & vm -> halted_cpus ) , ( " " ) ) ; vcpu = & vm -> vcpu [ vcpuid ] ; vcpu_halted = 0 ; vm_halted = 0 ; vcpu_lock ( vcpu ) ; while ( 1 ) { if ( vm -> rendezvous_func != NULL || vm -> suspend || vcpu -> reqidle ) break ; if ( vm_nmi_pending ( vm , vcpuid ) ) break ; if ( ! intr_disabled ) { if ( vm_extint_pending ( vm , vcpuid ) || vlapic_pending_intr ( vcpu -> vlapic , NULL ) ) { break ; } } if ( vcpu_should_yield ( vm , vcpuid ) ) break ; if ( intr_disabled ) { wmesg = " " ; VCPU_CTR0 ( vm , vcpuid , " " ) ; if ( ! vcpu_halted && halt_detection_enabled ) { 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 = " " ; } t = ticks ; vcpu_require_state_locked ( vm , vcpuid , VCPU_SLEEPING ) ; msleep_spin ( vcpu , & vcpu -> mtx , wmesg , hz ) ; vcpu_require_state_locked ( vm , vcpuid , 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 ) ; }
Emulate a guest 'hlt' by sleeping until the vcpu is ready to run.
Emulate a guest ' hlt ' by sleeping until the vcpu is ready to run .
/*
		 * Do a final check for pending NMI or interrupts before
		 * really putting this thread to sleep. Also check for
		 * software events that would cause this vcpu to wakeup.
		 *
		 * These interrupts/events could have happened after the
		 * vcpu returned from VMRUN() and before it acquired the
		 * vcpu lock above.
		 */ /* Don't go to sleep if the vcpu thread needs to yield */ /*
		 * 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.
		 */ /*
		 * XXX msleep_spin() cannot be interrupted by signals so
		 * wake up periodically to check pending signals.
		 */