aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndrey Smetanin <asmetanin@virtuozzo.com>2015-12-28 10:27:21 -0500
committerPaolo Bonzini <pbonzini@redhat.com>2016-01-08 13:04:41 -0500
commit0cdeabb1186fc3a6c7854f05cec7c99e32935ebc (patch)
tree9669ccea141691fe28419654a1aa745e18c361a2
parentf808495da56f28e94c6448125158f1175009fcfc (diff)
kvm/x86: Reorg stimer_expiration() to better control timer restart
Split stimer_expiration() into two parts - timer expiration message sending and timer restart/cleanup based on timer state(config). This also fixes a bug where a one-shot timer message whose delivery failed once would get lost for good. 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>
-rw-r--r--arch/x86/kvm/hyperv.c26
1 files changed, 14 insertions, 12 deletions
diff --git a/arch/x86/kvm/hyperv.c b/arch/x86/kvm/hyperv.c
index 0dd7d1731c22..5f85c12b223c 100644
--- a/arch/x86/kvm/hyperv.c
+++ b/arch/x86/kvm/hyperv.c
@@ -554,30 +554,27 @@ static int synic_deliver_msg(struct kvm_vcpu_hv_synic *synic, u32 sint,
554 return r; 554 return r;
555} 555}
556 556
557static void stimer_send_msg(struct kvm_vcpu_hv_stimer *stimer) 557static int stimer_send_msg(struct kvm_vcpu_hv_stimer *stimer)
558{ 558{
559 struct kvm_vcpu *vcpu = stimer_to_vcpu(stimer); 559 struct kvm_vcpu *vcpu = stimer_to_vcpu(stimer);
560 struct hv_message *msg = &stimer->msg; 560 struct hv_message *msg = &stimer->msg;
561 struct hv_timer_message_payload *payload = 561 struct hv_timer_message_payload *payload =
562 (struct hv_timer_message_payload *)&msg->u.payload; 562 (struct hv_timer_message_payload *)&msg->u.payload;
563 int r;
564 563
565 stimer->msg_pending = true;
566 payload->expiration_time = stimer->exp_time; 564 payload->expiration_time = stimer->exp_time;
567 payload->delivery_time = get_time_ref_counter(vcpu->kvm); 565 payload->delivery_time = get_time_ref_counter(vcpu->kvm);
568 r = synic_deliver_msg(vcpu_to_synic(vcpu), 566 return synic_deliver_msg(vcpu_to_synic(vcpu),
569 HV_STIMER_SINT(stimer->config), msg); 567 HV_STIMER_SINT(stimer->config), msg);
570 if (!r)
571 stimer->msg_pending = false;
572} 568}
573 569
574static void stimer_expiration(struct kvm_vcpu_hv_stimer *stimer) 570static void stimer_expiration(struct kvm_vcpu_hv_stimer *stimer)
575{ 571{
576 stimer_send_msg(stimer); 572 stimer->msg_pending = true;
577 if (!(stimer->config & HV_STIMER_PERIODIC)) 573 if (!stimer_send_msg(stimer)) {
578 stimer->config &= ~HV_STIMER_ENABLE; 574 stimer->msg_pending = false;
579 else 575 if (!(stimer->config & HV_STIMER_PERIODIC))
580 stimer_start(stimer); 576 stimer->config &= ~HV_STIMER_ENABLE;
577 }
581} 578}
582 579
583void kvm_hv_process_stimers(struct kvm_vcpu *vcpu) 580void kvm_hv_process_stimers(struct kvm_vcpu *vcpu)
@@ -594,6 +591,11 @@ void kvm_hv_process_stimers(struct kvm_vcpu *vcpu)
594 time_now = get_time_ref_counter(vcpu->kvm); 591 time_now = get_time_ref_counter(vcpu->kvm);
595 if (time_now >= stimer->exp_time) 592 if (time_now >= stimer->exp_time)
596 stimer_expiration(stimer); 593 stimer_expiration(stimer);
594
595 if (stimer->config & HV_STIMER_ENABLE)
596 stimer_start(stimer);
597 else
598 stimer_cleanup(stimer);
597 } 599 }
598 } 600 }
599} 601}