kvm/x86: Update SynIC timers on guest entry only
Consolidate updating the Hyper-V SynIC timers in a single place: on guest entry in processing KVM_REQ_HV_STIMER request. This simplifies the overall logic, and makes sure the most current state of msrs and guest clock is used for arming the timers (to achieve that, KVM_REQ_HV_STIMER has to be processed after KVM_REQ_CLOCK_UPDATE). Signed-off-by: Andrey Smetanin <asmetanin@virtuozzo.com> Reviewed-by: Roman Kagan <rkagan@virtuozzo.com> CC: Gleb Natapov <gleb@kernel.org> CC: Paolo Bonzini <pbonzini@redhat.com> CC: Roman Kagan <rkagan@virtuozzo.com> CC: Denis V. Lunev <den@openvz.org> CC: qemu-devel@nongnu.org Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
		
							parent
							
								
									7be58a6488
								
							
						
					
					
						commit
						f3b138c5d8
					
				| @ -389,7 +389,7 @@ static u64 get_time_ref_counter(struct kvm *kvm) | ||||
| 	return div_u64(get_kernel_ns() + kvm->arch.kvmclock_offset, 100); | ||||
| } | ||||
| 
 | ||||
| static void stimer_mark_expired(struct kvm_vcpu_hv_stimer *stimer, | ||||
| static void stimer_mark_pending(struct kvm_vcpu_hv_stimer *stimer, | ||||
| 				bool vcpu_kick) | ||||
| { | ||||
| 	struct kvm_vcpu *vcpu = stimer_to_vcpu(stimer); | ||||
| @ -417,7 +417,7 @@ static enum hrtimer_restart stimer_timer_callback(struct hrtimer *timer) | ||||
| 	struct kvm_vcpu_hv_stimer *stimer; | ||||
| 
 | ||||
| 	stimer = container_of(timer, struct kvm_vcpu_hv_stimer, timer); | ||||
| 	stimer_mark_expired(stimer, true); | ||||
| 	stimer_mark_pending(stimer, true); | ||||
| 
 | ||||
| 	return HRTIMER_NORESTART; | ||||
| } | ||||
| @ -462,7 +462,7 @@ static int stimer_start(struct kvm_vcpu_hv_stimer *stimer) | ||||
| 		 * "If a one shot is enabled and the specified count is in | ||||
| 		 * the past, it will expire immediately." | ||||
| 		 */ | ||||
| 		stimer_mark_expired(stimer, false); | ||||
| 		stimer_mark_pending(stimer, false); | ||||
| 		return 0; | ||||
| 	} | ||||
| 
 | ||||
| @ -475,30 +475,24 @@ static int stimer_start(struct kvm_vcpu_hv_stimer *stimer) | ||||
| static int stimer_set_config(struct kvm_vcpu_hv_stimer *stimer, u64 config, | ||||
| 			     bool host) | ||||
| { | ||||
| 	stimer_cleanup(stimer); | ||||
| 	if ((stimer->config & HV_STIMER_ENABLE) && HV_STIMER_SINT(config) == 0) | ||||
| 		config &= ~HV_STIMER_ENABLE; | ||||
| 	stimer->config = config; | ||||
| 	stimer_cleanup(stimer); | ||||
| 	if (stimer->config & HV_STIMER_ENABLE) | ||||
| 		if (stimer_start(stimer)) | ||||
| 			return 1; | ||||
| 	stimer_mark_pending(stimer, false); | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static int stimer_set_count(struct kvm_vcpu_hv_stimer *stimer, u64 count, | ||||
| 			    bool host) | ||||
| { | ||||
| 	stimer->count = count; | ||||
| 
 | ||||
| 	stimer_cleanup(stimer); | ||||
| 	stimer->count = count; | ||||
| 	if (stimer->count == 0) | ||||
| 		stimer->config &= ~HV_STIMER_ENABLE; | ||||
| 	else if (stimer->config & HV_STIMER_AUTOENABLE) { | ||||
| 	else if (stimer->config & HV_STIMER_AUTOENABLE) | ||||
| 		stimer->config |= HV_STIMER_ENABLE; | ||||
| 		if (stimer_start(stimer)) | ||||
| 			return 1; | ||||
| 	} | ||||
| 
 | ||||
| 	stimer_mark_pending(stimer, false); | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| @ -582,18 +576,24 @@ void kvm_hv_process_stimers(struct kvm_vcpu *vcpu) | ||||
| { | ||||
| 	struct kvm_vcpu_hv *hv_vcpu = vcpu_to_hv_vcpu(vcpu); | ||||
| 	struct kvm_vcpu_hv_stimer *stimer; | ||||
| 	u64 time_now; | ||||
| 	u64 time_now, exp_time; | ||||
| 	int i; | ||||
| 
 | ||||
| 	for (i = 0; i < ARRAY_SIZE(hv_vcpu->stimer); i++) | ||||
| 		if (test_and_clear_bit(i, hv_vcpu->stimer_pending_bitmap)) { | ||||
| 			stimer = &hv_vcpu->stimer[i]; | ||||
| 			if (stimer->config & HV_STIMER_ENABLE) { | ||||
| 				time_now = get_time_ref_counter(vcpu->kvm); | ||||
| 				if (time_now >= stimer->exp_time) | ||||
| 					stimer_expiration(stimer); | ||||
| 				exp_time = stimer->exp_time; | ||||
| 
 | ||||
| 				if (stimer->config & HV_STIMER_ENABLE) | ||||
| 				if (exp_time) { | ||||
| 					time_now = | ||||
| 						get_time_ref_counter(vcpu->kvm); | ||||
| 					if (time_now >= exp_time) | ||||
| 						stimer_expiration(stimer); | ||||
| 				} | ||||
| 
 | ||||
| 				if ((stimer->config & HV_STIMER_ENABLE) && | ||||
| 				    stimer->count) | ||||
| 					stimer_start(stimer); | ||||
| 				else | ||||
| 					stimer_cleanup(stimer); | ||||
|  | ||||
| @ -6508,6 +6508,12 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu) | ||||
| 			r = 0; | ||||
| 			goto out; | ||||
| 		} | ||||
| 
 | ||||
| 		/*
 | ||||
| 		 * KVM_REQ_HV_STIMER has to be processed after | ||||
| 		 * KVM_REQ_CLOCK_UPDATE, because Hyper-V SynIC timers | ||||
| 		 * depend on the guest clock being up-to-date | ||||
| 		 */ | ||||
| 		if (kvm_check_request(KVM_REQ_HV_STIMER, vcpu)) | ||||
| 			kvm_hv_process_stimers(vcpu); | ||||
| 	} | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user