Beispiel #1
0
/*
 * 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 vm_exit *vmexit;
	struct vcpu *vcpu;
	int t, timo, spindown;

	vcpu = &vm->vcpu[vcpuid];
	spindown = 0;

	vcpu_lock(vcpu);

	/*
	 * Do a final check for pending NMI or interrupts before
	 * really putting this thread to sleep.
	 *
	 * These interrupts could have happened any time after we
	 * returned from VMRUN() and before we grabbed the vcpu lock.
	 */
	if (!vm_nmi_pending(vm, vcpuid) &&
	    (intr_disabled || !vlapic_pending_intr(vcpu->vlapic, NULL))) {
		t = ticks;
		vcpu_require_state_locked(vcpu, VCPU_SLEEPING);
		if (vlapic_enabled(vcpu->vlapic)) {
			/*
			 * XXX msleep_spin() is not interruptible so use the
			 * 'timo' to put an upper bound on the sleep time.
			 */
			timo = hz;
			msleep_spin(vcpu, &vcpu->mtx, "vmidle", timo);
		} else {
			/*
			 * Spindown the vcpu if the apic is disabled and it
			 * had entered the halted state.
			 */
			spindown = 1;
		}
		vcpu_require_state_locked(vcpu, VCPU_FROZEN);
		vmm_stat_incr(vm, vcpuid, VCPU_IDLE_TICKS, ticks - t);
	}
	vcpu_unlock(vcpu);

	/*
	 * Since 'vm_deactivate_cpu()' grabs a sleep mutex we must call it
	 * outside the confines of the vcpu spinlock.
	 */
	if (spindown) {
		*retu = true;
		vmexit = vm_exitinfo(vm, vcpuid);
		vmexit->exitcode = VM_EXITCODE_SPINDOWN_CPU;
		vm_deactivate_cpu(vm, vcpuid);
		VCPU_CTR0(vm, vcpuid, "spinning down cpu");
	}

	return (0);
}
Beispiel #2
0
void
vm_exit_reqidle(struct vm *vm, int vcpuid, uint64_t rip)
{
	struct vm_exit *vmexit;

	vmexit = vm_exitinfo(vm, vcpuid);
	vmexit->rip = rip;
	vmexit->inst_length = 0;
	vmexit->exitcode = VM_EXITCODE_REQIDLE;
	vmm_stat_incr(vm, vcpuid, VMEXIT_REQIDLE, 1);
}
Beispiel #3
0
void
vm_exit_rendezvous(struct vm *vm, int vcpuid, uint64_t rip)
{
	struct vm_exit *vmexit;

	KASSERT(vm->rendezvous_func != NULL, ("rendezvous not in progress"));

	vmexit = vm_exitinfo(vm, vcpuid);
	vmexit->rip = rip;
	vmexit->inst_length = 0;
	vmexit->exitcode = VM_EXITCODE_RENDEZVOUS;
	vmm_stat_incr(vm, vcpuid, VMEXIT_RENDEZVOUS, 1);
}
Beispiel #4
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 = (enum vm_suspend_how) vm->suspend;
}
Beispiel #5
0
static void
vm_inject_fault(struct vm *vm, int vcpuid, struct vm_exception *exception)
{
	struct vm_exit *vmexit;
	int error;

	error = vm_inject_exception(vm, vcpuid, exception);
	KASSERT(error == 0, ("vm_inject_exception error %d", error));

	/*
	 * A fault-like exception allows the instruction to be restarted
	 * after the exception handler returns.
	 *
	 * By setting the inst_length to 0 we ensure that the instruction
	 * pointer remains at the faulting instruction.
	 */
	vmexit = vm_exitinfo(vm, vcpuid);
	vmexit->inst_length = 0;
}