Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 09cec754 authored by Gleb Natapov's avatar Gleb Natapov Committed by Avi Kivity
Browse files

KVM: Timer event should not unconditionally unhalt vcpu.



Currently timer events are processed before entering guest mode. Move it
to main vcpu event loop since timer events should be processed even while
vcpu is halted.  Timer may cause interrupt/nmi to be injected and only then
vcpu will be unhalted.

Signed-off-by: default avatarGleb Natapov <gleb@redhat.com>
Signed-off-by: default avatarAvi Kivity <avi@redhat.com>
parent 089d034e
Loading
Loading
Loading
Loading
+3 −3
Original line number Diff line number Diff line
@@ -488,10 +488,10 @@ int kvm_emulate_halt(struct kvm_vcpu *vcpu)
		hrtimer_cancel(p_ht);
		vcpu->arch.ht_active = 0;

		if (test_and_clear_bit(KVM_REQ_UNHALT, &vcpu->requests))
		if (test_and_clear_bit(KVM_REQ_UNHALT, &vcpu->requests) ||
				kvm_cpu_has_pending_timer(vcpu))
			if (vcpu->arch.mp_state == KVM_MP_STATE_HALTED)
				vcpu->arch.mp_state =
					KVM_MP_STATE_RUNNABLE;
				vcpu->arch.mp_state = KVM_MP_STATE_RUNNABLE;

		if (vcpu->arch.mp_state != KVM_MP_STATE_RUNNABLE)
			return -EINTR;
+34 −23
Original line number Diff line number Diff line
@@ -3133,9 +3133,6 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
		}
	}

	clear_bit(KVM_REQ_PENDING_TIMER, &vcpu->requests);
	kvm_inject_pending_timer_irqs(vcpu);

	preempt_disable();

	kvm_x86_ops->prepare_guest_switch(vcpu);
@@ -3235,6 +3232,7 @@ out:
	return r;
}


static int __vcpu_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
{
	int r;
@@ -3261,14 +3259,28 @@ static int __vcpu_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
			kvm_vcpu_block(vcpu);
			down_read(&vcpu->kvm->slots_lock);
			if (test_and_clear_bit(KVM_REQ_UNHALT, &vcpu->requests))
				if (vcpu->arch.mp_state == KVM_MP_STATE_HALTED)
			{
				switch(vcpu->arch.mp_state) {
				case KVM_MP_STATE_HALTED:
					vcpu->arch.mp_state =
						KVM_MP_STATE_RUNNABLE;
			if (vcpu->arch.mp_state != KVM_MP_STATE_RUNNABLE)
				case KVM_MP_STATE_RUNNABLE:
					break;
				case KVM_MP_STATE_SIPI_RECEIVED:
				default:
					r = -EINTR;
					break;
				}
			}
		}

		if (r <= 0)
			break;

		clear_bit(KVM_REQ_PENDING_TIMER, &vcpu->requests);
		if (kvm_cpu_has_pending_timer(vcpu))
			kvm_inject_pending_timer_irqs(vcpu);

		if (r > 0) {
		if (dm_request_for_irq_injection(vcpu, kvm_run)) {
			r = -EINTR;
			kvm_run->exit_reason = KVM_EXIT_INTR;
@@ -3285,7 +3297,6 @@ static int __vcpu_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
			down_read(&vcpu->kvm->slots_lock);
		}
	}
	}

	up_read(&vcpu->kvm->slots_lock);
	post_kvm_run_save(vcpu, kvm_run);
+3 −2
Original line number Diff line number Diff line
@@ -1611,11 +1611,12 @@ void kvm_vcpu_block(struct kvm_vcpu *vcpu)
		prepare_to_wait(&vcpu->wq, &wait, TASK_INTERRUPTIBLE);

		if (kvm_cpu_has_interrupt(vcpu) ||
		    kvm_cpu_has_pending_timer(vcpu) ||
				kvm_arch_vcpu_runnable(vcpu)) {
			set_bit(KVM_REQ_UNHALT, &vcpu->requests);
			break;
		}
		if (kvm_cpu_has_pending_timer(vcpu))
			break;
		if (signal_pending(current))
			break;